From a58dfb0dba4554a4f3d3820356c836ccf71d263e Mon Sep 17 00:00:00 2001 From: Yota Toyama Date: Mon, 20 Nov 2017 00:24:13 +0900 Subject: [PATCH] Support relative paths --- examples/relative_path.feature | 36 ++++++++++++++++++++++++++++++++++ file_checker.go | 4 ++-- file_checker_test.go | 4 ++-- url_checker.go | 26 ++++++++++++++++++++---- 4 files changed, 62 insertions(+), 8 deletions(-) create mode 100644 examples/relative_path.feature diff --git a/examples/relative_path.feature b/examples/relative_path.feature new file mode 100644 index 0000000..60b33ff --- /dev/null +++ b/examples/relative_path.feature @@ -0,0 +1,36 @@ +Feature: Relative paths + Scenario: Check a markdown file + Given a file named "foo.md" with: + """ + [bar](bar.md) + """ + And a file named "bar.md" with "" + When I successfully run `liche -v foo.md` + Then the stderr should contain "OK" + + Scenario: Check a directory + Given a file named "foo.md" with: + """ + [bar](bar) + """ + And a directory named "bar" + When I successfully run `liche -v foo.md` + Then the stderr should contain "OK" + + Scenario: Check an image + Given a file named "foo.md" with: + """ + ![foo](foo.png) + """ + And a file named "foo.png" with "" + When I successfully run `liche -v foo.md` + Then the stderr should contain "OK" + + Scenario: Check a non-existent markdown file + Given a file named "foo.md" with: + """ + [bar](bar.md) + """ + When I run `liche foo.md` + Then the exit status should be 1 + And the stderr should contain "ERROR" diff --git a/file_checker.go b/file_checker.go index f1aebaf..93792cb 100644 --- a/file_checker.go +++ b/file_checker.go @@ -31,7 +31,7 @@ func (c fileChecker) Check(f string) ([]urlResult, error) { rc := make(chan urlResult, len(us)) rs := make([]urlResult, 0, len(us)) - go c.urlChecker.CheckMany(us, rc) + go c.urlChecker.CheckMany(us, f, rc) for r := range rc { rs = append(rs, r) @@ -120,7 +120,7 @@ func extractURLs(n *html.Node) []string { func isURL(s string) bool { u, err := url.Parse(s) - return err == nil && (u.Scheme == "http" || u.Scheme == "https") + return err == nil && (u.Scheme == "" || u.Scheme == "http" || u.Scheme == "https") } func isHTMLFile(f string) bool { diff --git a/file_checker_test.go b/file_checker_test.go index 98396b0..7adc17b 100644 --- a/file_checker_test.go +++ b/file_checker_test.go @@ -49,11 +49,11 @@ func TestURLParse(t *testing.T) { } func TestIsURL(t *testing.T) { - for _, s := range []string{"http://google.com", "https://google.com"} { + for _, s := range []string{"http://google.com", "https://google.com", "file-path"} { assert.True(t, isURL(s)) } - for _, s := range []string{"", "file-path"} { + for _, s := range []string{"ftp://foo.com", "file://file-path"} { assert.False(t, isURL(s)) } } diff --git a/url_checker.go b/url_checker.go index 2d8224e..8d897c6 100644 --- a/url_checker.go +++ b/url_checker.go @@ -1,6 +1,9 @@ package main import ( + "net/url" + "os" + "path" "sync" "time" @@ -16,7 +19,17 @@ func newURLChecker(t time.Duration, s semaphore) urlChecker { return urlChecker{t, s} } -func (c urlChecker) Check(u string) error { +func (c urlChecker) Check(u string, f string) error { + uu, err := url.Parse(u) + + if err != nil { + return err + } + + if uu.Scheme == "" { + return checkRelativePath(u, f) + } + c.semaphore.Request() defer c.semaphore.Release() @@ -25,18 +38,18 @@ func (c urlChecker) Check(u string) error { return err } - _, _, err := fasthttp.GetTimeout(nil, u, c.timeout) + _, _, err = fasthttp.GetTimeout(nil, u, c.timeout) return err } -func (c urlChecker) CheckMany(us []string, rc chan<- urlResult) { +func (c urlChecker) CheckMany(us []string, f string, rc chan<- urlResult) { wg := sync.WaitGroup{} for _, s := range us { wg.Add(1) go func(s string) { - rc <- urlResult{s, c.Check(s)} + rc <- urlResult{s, c.Check(s, f)} wg.Done() }(s) } @@ -44,3 +57,8 @@ func (c urlChecker) CheckMany(us []string, rc chan<- urlResult) { wg.Wait() close(rc) } + +func checkRelativePath(p string, f string) error { + _, err := os.Stat(path.Join(path.Dir(f), p)) + return err +}