diff --git a/helpers/general.go b/helpers/general.go index bfac5beae90..cf3c0ac5424 100644 --- a/helpers/general.go +++ b/helpers/general.go @@ -20,9 +20,12 @@ import ( "fmt" "io" "net" + "path/filepath" "strings" ) +const FilePathSeparator = string(filepath.Separator) + func FindAvailablePort() (*net.TCPAddr, error) { l, err := net.Listen("tcp", ":0") if err == nil { diff --git a/helpers/path.go b/helpers/path.go index e5f07450d95..b65533d8a80 100644 --- a/helpers/path.go +++ b/helpers/path.go @@ -16,15 +16,14 @@ package helpers import ( "errors" "fmt" + "github.com/spf13/afero" + "github.com/spf13/viper" "io" "os" "path/filepath" "regexp" "strings" "unicode" - - "github.com/spf13/afero" - "github.com/spf13/viper" ) var sanitizeRegexp = regexp.MustCompile("[^a-zA-Z0-9./_-]") @@ -173,13 +172,18 @@ func FileAndExt(in string) (name string, ext string) { ext = filepath.Ext(in) base := filepath.Base(in) // path.Base strips any trailing slash! + return FileAndExtSep(in, ext, base, FilePathSeparator), ext +} + +func FileAndExtSep(in, ext, base, pathSeparator string) (name string) { + // No file name cases. These are defined as: - // 1. any "in" path that ends in a os.PathSeparator i.e. "/" on linux - // 2. any "base" consisting of just an os.PathSeparator + // 1. any "in" path that ends in a pathSeparator + // 2. any "base" consisting of just an pathSeparator // 3. any "base" consisting of just an empty string // 4. any "base" consisting of just the current directory i.e. "." // 5. any "base" consisting of just the parent directory i.e. ".." - if (strings.LastIndex(in, string(os.PathSeparator)) == len(in)-1) || base == "" || base == "." || base == ".." || base == string(os.PathListSeparator) { + if (strings.LastIndex(in, pathSeparator) == len(in)-1) || base == "" || base == "." || base == ".." || base == pathSeparator { name = "" // there is NO filename } else if ext != "" { // there was an Extension // return the filename minus the extension (and the ".") @@ -190,6 +194,7 @@ func FileAndExt(in string) (name string, ext string) { name = base } return + } func GetRelativePath(path, base string) (final string, err error) { @@ -203,14 +208,13 @@ func GetRelativePath(path, base string) (final string, err error) { if err != nil { return "", err } - name = filepath.ToSlash(name) return name, nil } // Given a source path, determine the section // A section is the part between the root slash and the second slash or before the first slash func GuessSection(in string) string { - parts := strings.Split(in, "/") + parts := strings.Split(in, FilePathSeparator) // This will include an empty entry before and after paths with leading and trailing slashes // eg... /sect/one/ -> ["", "sect", "one", ""] @@ -256,7 +260,7 @@ func PrettifyPath(in string) string { if filepath.Ext(in) == "" { // /section/name/ -> /section/name/index.html if len(in) < 2 { - return "/" + return FilePathSeparator } return filepath.Join(filepath.Clean(in), "index.html") } else { diff --git a/helpers/path_test.go b/helpers/path_test.go index a7cca35bb1e..603723c27c5 100644 --- a/helpers/path_test.go +++ b/helpers/path_test.go @@ -4,7 +4,7 @@ import ( "fmt" "io/ioutil" "os" - "path" + "path/filepath" "strconv" "strings" "testing" @@ -119,7 +119,7 @@ func TestReplaceExtension(t *testing.T) { } for i, d := range data { - output := ReplaceExtension(d.input, d.newext) + output := ReplaceExtension(filepath.FromSlash(d.input), d.newext) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } @@ -139,8 +139,8 @@ func TestDirExists(t *testing.T) { {"../", true}, {"./..", true}, {"./../", true}, - {"/tmp", true}, - {"/tmp/", true}, + {os.TempDir(), true}, + {os.TempDir() + FilePathSeparator, true}, {"/", true}, {"/some-really-random-directory-name", false}, {"/some/really/random/directory/name", false}, @@ -149,7 +149,7 @@ func TestDirExists(t *testing.T) { } for i, d := range data { - exists, _ := DirExists(d.input, new(afero.OsFs)) + exists, _ := DirExists(filepath.FromSlash(d.input), new(afero.OsFs)) if d.expected != exists { t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, exists) } @@ -366,8 +366,8 @@ func TestAbsPathify(t *testing.T) { input, expected string } data := []test{ - {os.TempDir(), path.Clean(os.TempDir())}, // TempDir has trailing slash - {"/banana/../dir/", "/dir"}, + {os.TempDir(), filepath.Clean(os.TempDir())}, // TempDir has trailing slash + {filepath.FromSlash("/banana/../dir/"), filepath.FromSlash("/dir")}, } for i, d := range data { @@ -400,7 +400,7 @@ func TestFilename(t *testing.T) { } for i, d := range data { - output := Filename(d.input) + output := Filename(filepath.FromSlash(d.input)) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } @@ -429,7 +429,7 @@ func TestFileAndExt(t *testing.T) { } for i, d := range data { - file, ext := FileAndExt(d.input) + file, ext := FileAndExt(filepath.FromSlash(d.input)) if d.expectedFile != file { t.Errorf("Test %d failed. Expected filename %q got %q.", i, d.expectedFile, file) } @@ -467,7 +467,7 @@ func TestGuessSection(t *testing.T) { } for i, d := range data { - expected := GuessSection(d.input) + expected := GuessSection(filepath.FromSlash(d.input)) if d.expected != expected { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, expected) } diff --git a/helpers/url.go b/helpers/url.go index dd8d7508b68..a2dc0ac69f9 100644 --- a/helpers/url.go +++ b/helpers/url.go @@ -15,11 +15,10 @@ package helpers import ( "fmt" + "github.com/PuerkitoBio/purell" "net/url" - "path/filepath" + "path" "strings" - - "github.com/PuerkitoBio/purell" ) func SanitizeUrl(in string) string { @@ -68,7 +67,7 @@ func MakePermalink(host, plink string) *url.URL { panic(fmt.Errorf("Can't make permalink from absolute link %q", plink)) } - base.Path = filepath.Join(base.Path, p.Path) + base.Path = path.Join(base.Path, p.Path) // path.Join will strip off the last /, so put it back if it was there. if strings.HasSuffix(p.Path, "/") && !strings.HasSuffix(base.Path, "/") { @@ -84,7 +83,7 @@ func UrlPrep(ugly bool, in string) string { return x } else { x := PrettifyUrl(SanitizeUrl(in)) - if filepath.Ext(x) == ".xml" { + if path.Ext(x) == ".xml" { return x } url, err := purell.NormalizeURLString(x, purell.FlagAddTrailingSlash) @@ -98,10 +97,10 @@ func UrlPrep(ugly bool, in string) string { // Don't Return /index.html portion. func PrettifyUrl(in string) string { - x := PrettifyPath(in) + x := PrettifyUrlPath(in) - if filepath.Base(x) == "index.html" { - return filepath.Dir(x) + if path.Base(x) == "index.html" { + return path.Dir(x) } if in == "" { @@ -111,21 +110,43 @@ func PrettifyUrl(in string) string { return x } +// /section/name.html -> /section/name/index.html +// /section/name/ -> /section/name/index.html +// /section/name/index.html -> /section/name/index.html +func PrettifyUrlPath(in string) string { + if path.Ext(in) == "" { + // /section/name/ -> /section/name/index.html + if len(in) < 2 { + return "/" + } + return path.Join(path.Clean(in), "index.html") + } else { + name, ext := ResourceAndExt(in) + if name == "index" { + // /section/name/index.html -> /section/name/index.html + return path.Clean(in) + } else { + // /section/name.html -> /section/name/index.html + return path.Join(path.Dir(in), name, "index"+ext) + } + } +} + // /section/name/index.html -> /section/name.html // /section/name/ -> /section/name.html // /section/name.html -> /section/name.html func Uglify(in string) string { - if filepath.Ext(in) == "" { + if path.Ext(in) == "" { if len(in) < 2 { return "/" } // /section/name/ -> /section/name.html - return filepath.Clean(in) + ".html" + return path.Clean(in) + ".html" } else { - name, ext := FileAndExt(in) + name, ext := ResourceAndExt(in) if name == "index" { // /section/name/index.html -> /section/name.html - d := filepath.Dir(in) + d := path.Dir(in) if len(d) > 1 { return d + ext } else { @@ -133,7 +154,15 @@ func Uglify(in string) string { } } else { // /section/name.html -> /section/name.html - return filepath.Clean(in) + return path.Clean(in) } } } + +// Same as FileAndExt, but for Urls +func ResourceAndExt(in string) (name string, ext string) { + ext = path.Ext(in) + base := path.Base(in) + + return FileAndExtSep(in, ext, base, "/"), ext +} diff --git a/helpers/url_test.go b/helpers/url_test.go index 4014ee3437e..1d5c770ead8 100644 --- a/helpers/url_test.go +++ b/helpers/url_test.go @@ -69,14 +69,14 @@ func TestUrlPrep(t *testing.T) { } func TestPretty(t *testing.T) { - assert.Equal(t, PrettifyPath("/section/name.html"), "/section/name/index.html") - assert.Equal(t, PrettifyPath("/section/sub/name.html"), "/section/sub/name/index.html") - assert.Equal(t, PrettifyPath("/section/name/"), "/section/name/index.html") - assert.Equal(t, PrettifyPath("/section/name/index.html"), "/section/name/index.html") - assert.Equal(t, PrettifyPath("/index.html"), "/index.html") - assert.Equal(t, PrettifyPath("/name.xml"), "/name/index.xml") - assert.Equal(t, PrettifyPath("/"), "/") - assert.Equal(t, PrettifyPath(""), "/") + assert.Equal(t, PrettifyUrlPath("/section/name.html"), "/section/name/index.html") + assert.Equal(t, PrettifyUrlPath("/section/sub/name.html"), "/section/sub/name/index.html") + assert.Equal(t, PrettifyUrlPath("/section/name/"), "/section/name/index.html") + assert.Equal(t, PrettifyUrlPath("/section/name/index.html"), "/section/name/index.html") + assert.Equal(t, PrettifyUrlPath("/index.html"), "/index.html") + assert.Equal(t, PrettifyUrlPath("/name.xml"), "/name/index.xml") + assert.Equal(t, PrettifyUrlPath("/"), "/") + assert.Equal(t, PrettifyUrlPath(""), "/") assert.Equal(t, PrettifyUrl("/section/name.html"), "/section/name") assert.Equal(t, PrettifyUrl("/section/sub/name.html"), "/section/sub/name") assert.Equal(t, PrettifyUrl("/section/name/"), "/section/name") diff --git a/hugolib/page.go b/hugolib/page.go index add8fdbaaeb..67a6842c1ad 100644 --- a/hugolib/page.go +++ b/hugolib/page.go @@ -17,13 +17,6 @@ import ( "bytes" "errors" "fmt" - "html/template" - "io" - "net/url" - "path/filepath" - "strings" - "time" - "github.com/spf13/cast" "github.com/spf13/hugo/helpers" "github.com/spf13/hugo/hugofs" @@ -32,6 +25,13 @@ import ( "github.com/spf13/hugo/tpl" jww "github.com/spf13/jwalterweatherman" "github.com/spf13/viper" + "html/template" + "io" + "net/url" + "path" + "path/filepath" + "strings" + "time" ) type Page struct { @@ -197,7 +197,7 @@ func layouts(types string, layout string) (layouts []string) { // Add type/layout.html for i := range t { search := t[:len(t)-i] - layouts = append(layouts, fmt.Sprintf("%s/%s.html", strings.ToLower(filepath.Join(search...)), layout)) + layouts = append(layouts, fmt.Sprintf("%s/%s.html", strings.ToLower(path.Join(search...)), layout)) } // Add _default/layout.html @@ -250,7 +250,7 @@ func (p *Page) analyzePage() { func (p *Page) permalink() (*url.URL, error) { baseUrl := string(p.Site.BaseUrl) - dir := strings.TrimSpace(p.Source.Dir()) + dir := strings.TrimSpace(filepath.ToSlash(p.Source.Dir())) pSlug := strings.TrimSpace(p.Slug) pUrl := strings.TrimSpace(p.Url) var permalink string @@ -269,10 +269,10 @@ func (p *Page) permalink() (*url.URL, error) { // fmt.Printf("have a section override for %q in section %s → %s\n", p.Title, p.Section, permalink) } else { if len(pSlug) > 0 { - permalink = helpers.UrlPrep(viper.GetBool("UglyUrls"), filepath.Join(dir, p.Slug+"."+p.Extension())) + permalink = helpers.UrlPrep(viper.GetBool("UglyUrls"), path.Join(dir, p.Slug+"."+p.Extension())) } else { _, t := filepath.Split(p.Source.LogicalName()) - permalink = helpers.UrlPrep(viper.GetBool("UglyUrls"), filepath.Join(dir, helpers.ReplaceExtension(strings.TrimSpace(t), p.Extension()))) + permalink = helpers.UrlPrep(viper.GetBool("UglyUrls"), path.Join(dir, helpers.ReplaceExtension(strings.TrimSpace(t), p.Extension()))) } } @@ -674,6 +674,7 @@ func (p *Page) TargetPath() (outfile string) { if strings.HasSuffix(outfile, "/") { outfile = outfile + "index.html" } + outfile = filepath.FromSlash(outfile) return } @@ -685,6 +686,7 @@ func (p *Page) TargetPath() (outfile string) { if strings.HasSuffix(outfile, "/") { outfile += "index.html" } + outfile = filepath.FromSlash(outfile) return } } diff --git a/hugolib/pageGroup_test.go b/hugolib/pageGroup_test.go index ff85fba8e02..c8d89fb0308 100644 --- a/hugolib/pageGroup_test.go +++ b/hugolib/pageGroup_test.go @@ -2,6 +2,7 @@ package hugolib import ( "errors" + "path/filepath" "reflect" "testing" @@ -26,7 +27,7 @@ var pageGroupTestSources = []pageGroupTestObject{ func preparePageGroupTestPages(t *testing.T) Pages { var pages Pages for _, s := range pageGroupTestSources { - p, err := NewPage(s.path) + p, err := NewPage(filepath.FromSlash(s.path)) if err != nil { t.Fatalf("failed to prepare test page %s", s.path) } diff --git a/hugolib/page_permalink_test.go b/hugolib/page_permalink_test.go index f420b19c629..97b3d24c6ed 100644 --- a/hugolib/page_permalink_test.go +++ b/hugolib/page_permalink_test.go @@ -2,6 +2,7 @@ package hugolib import ( "html/template" + "path/filepath" "testing" "github.com/spf13/hugo/source" @@ -48,7 +49,7 @@ func TestPermalink(t *testing.T) { BaseUrl: test.base, }, }, - Source: Source{File: *source.NewFile(test.file)}, + Source: Source{File: *source.NewFile(filepath.FromSlash(test.file))}, } if test.slug != "" { diff --git a/hugolib/page_test.go b/hugolib/page_test.go index 178c72d0ee9..f6ff83aaa28 100644 --- a/hugolib/page_test.go +++ b/hugolib/page_test.go @@ -510,10 +510,10 @@ func TestDegenerateInvalidFrontMatterLeadingWhitespace(t *testing.T) { } func TestSectionEvaluation(t *testing.T) { - page, _ := NewPage("blue/file1.md") + page, _ := NewPage(filepath.FromSlash("blue/file1.md")) page.ReadFrom(strings.NewReader(SIMPLE_PAGE)) if page.Section() != "blue" { - t.Errorf("Section should be %s, got: %s", "blue", page.Section) + t.Errorf("Section should be %s, got: %s", "blue", page.Section()) } } diff --git a/hugolib/path_seperators_windows_test.go b/hugolib/path_seperators_windows_test.go index 5cdd7c5f685..7f549b54e3a 100644 --- a/hugolib/path_seperators_windows_test.go +++ b/hugolib/path_seperators_windows_test.go @@ -1,6 +1,7 @@ package hugolib import ( + "github.com/spf13/hugo/tpl" "testing" ) @@ -10,8 +11,8 @@ const ( ) func TestTemplatePathSeperator(t *testing.T) { - tmpl := new(GoHtmlTemplate) - if name := tmpl.generateTemplateNameFrom(win_base, win_path); name != "sub1/index.html" { + tmpl := new(tpl.GoHtmlTemplate) + if name := tmpl.GenerateTemplateNameFrom(win_base, win_path); name != "sub1/index.html" { t.Fatalf("Template name incorrect. Expected: %s, Got: %s", "sub1/index.html", name) } } diff --git a/hugolib/site_show_plan_test.go b/hugolib/site_show_plan_test.go index 7d18a7e5bc3..f05304f23f4 100644 --- a/hugolib/site_show_plan_test.go +++ b/hugolib/site_show_plan_test.go @@ -2,26 +2,27 @@ package hugolib import ( "bytes" - "strings" - "testing" - + "github.com/spf13/hugo/helpers" "github.com/spf13/hugo/source" "github.com/spf13/hugo/target" + "path/filepath" + "strings" + "testing" ) const ALIAS_DOC_1 = "---\ntitle: alias doc\naliases:\n - \"alias1/\"\n - \"alias-2/\"\n---\naliases\n" var fakeSource = []source.ByteSource{ { - Name: "foo/bar/file.md", + Name: filepath.FromSlash("foo/bar/file.md"), Content: []byte(SIMPLE_PAGE), }, { - Name: "alias/test/file1.md", + Name: filepath.FromSlash("alias/test/file1.md"), Content: []byte(ALIAS_DOC_1), }, { - Name: "section/somecontent.html", + Name: filepath.FromSlash("section/somecontent.html"), Content: []byte(RENDER_NO_FRONT_MATTER), }, } @@ -36,25 +37,24 @@ func stringInSlice(a string, list []string) bool { } func checkShowPlanExpected(t *testing.T, s *Site, expected string) { + out := new(bytes.Buffer) if err := s.ShowPlan(out); err != nil { t.Fatalf("ShowPlan unexpectedly returned an error: %s", err) } got := out.String() + expected = filepath.FromSlash(expected) + // hackety hack: alias is an Url + expected = strings.Replace(expected, (helpers.FilePathSeparator + " =>"), "/ =>", -1) + expected = strings.Replace(expected, "n"+(helpers.FilePathSeparator+"a"), "n/a", -1) gotList := strings.Split(got, "\n") expectedList := strings.Split(expected, "\n") - for _, x := range gotList { - if !stringInSlice(x, expectedList) { - t.Errorf("%v %v %v %v", "\nShowPlan expected:\n", expected, "\ngot:\n", got) - } - } + diff := DiffStringSlices(gotList, expectedList) - for _, x := range expectedList { - if !stringInSlice(x, gotList) { - t.Errorf("%v %v %v %v", "\nShowPlan expected:\n", expected, "\ngot:\n", got) - } + if len(diff) > 0 { + t.Errorf("Got diff in show plan: %s", diff) } } @@ -126,3 +126,26 @@ func TestFileTargetPublishDir(t *testing.T) { "section/somecontent.html (renderer: n/a)\n canonical => ../public/section/somecontent/index.html\n\n" checkShowPlanExpected(t, s, expected) } + +// DiffStringSlices returns the difference between two string slices. +// See: +// http://stackoverflow.com/questions/19374219/how-to-find-the-difference-between-two-slices-of-strings-in-golang +func DiffStringSlices(slice1 []string, slice2 []string) []string { + diffStr := []string{} + m := map[string]int{} + + for _, s1Val := range slice1 { + m[s1Val] = 1 + } + for _, s2Val := range slice2 { + m[s2Val] = m[s2Val] + 1 + } + + for mKey, mVal := range m { + if mVal == 1 { + diffStr = append(diffStr, mKey) + } + } + + return diffStr +} diff --git a/hugolib/site_test.go b/hugolib/site_test.go index 94f7373432a..ea21205b1a5 100644 --- a/hugolib/site_test.go +++ b/hugolib/site_test.go @@ -5,6 +5,7 @@ import ( "fmt" "html/template" "io" + "path/filepath" "strings" "testing" @@ -191,7 +192,7 @@ func TestRenderThingOrDefault(t *testing.T) { t.Errorf("Unable to write html: %s", err) } - file, err := hugofs.DestinationFS.Open("out/index.html") + file, err := hugofs.DestinationFS.Open(filepath.FromSlash("out/index.html")) if err != nil { t.Errorf("Unable to open html: %s", err) } @@ -221,9 +222,9 @@ func TestTargetPath(t *testing.T) { } for _, test := range tests { - p := pageMust(NewPageFrom(strings.NewReader(test.content), helpers.AbsPathify(test.doc))) + p := pageMust(NewPageFrom(strings.NewReader(test.content), helpers.AbsPathify(filepath.FromSlash(test.doc)))) - expected := test.expectedOutFile + expected := filepath.FromSlash(test.expectedOutFile) if p.TargetPath() != expected { t.Errorf("%s => OutFile expected: '%s', got: '%s'", test.doc, expected, p.TargetPath()) @@ -238,10 +239,10 @@ func TestTargetPath(t *testing.T) { func TestDraftAndFutureRender(t *testing.T) { hugofs.DestinationFS = new(afero.MemMapFs) sources := []source.ByteSource{ - {"sect/doc1.md", []byte("---\ntitle: doc1\ndraft: true\npublishdate: \"2414-05-29\"\n---\n# doc1\n*some content*")}, - {"sect/doc2.md", []byte("---\ntitle: doc2\ndraft: true\npublishdate: \"2012-05-29\"\n---\n# doc2\n*some content*")}, - {"sect/doc3.md", []byte("---\ntitle: doc3\ndraft: false\npublishdate: \"2414-05-29\"\n---\n# doc3\n*some content*")}, - {"sect/doc4.md", []byte("---\ntitle: doc4\ndraft: false\npublishdate: \"2012-05-29\"\n---\n# doc4\n*some content*")}, + {filepath.FromSlash("sect/doc1.md"), []byte("---\ntitle: doc1\ndraft: true\npublishdate: \"2414-05-29\"\n---\n# doc1\n*some content*")}, + {filepath.FromSlash("sect/doc2.md"), []byte("---\ntitle: doc2\ndraft: true\npublishdate: \"2012-05-29\"\n---\n# doc2\n*some content*")}, + {filepath.FromSlash("sect/doc3.md"), []byte("---\ntitle: doc3\ndraft: false\npublishdate: \"2414-05-29\"\n---\n# doc3\n*some content*")}, + {filepath.FromSlash("sect/doc4.md"), []byte("---\ntitle: doc4\ndraft: false\npublishdate: \"2012-05-29\"\n---\n# doc4\n*some content*")}, } siteSetup := func() *Site { @@ -296,14 +297,14 @@ func TestDraftAndFutureRender(t *testing.T) { func TestSkipRender(t *testing.T) { hugofs.DestinationFS = new(afero.MemMapFs) sources := []source.ByteSource{ - {"sect/doc1.html", []byte("---\nmarkup: markdown\n---\n# title\nsome *content*")}, - {"sect/doc2.html", []byte("more content")}, - {"sect/doc3.md", []byte("# doc3\n*some* content")}, - {"sect/doc4.md", []byte("---\ntitle: doc4\n---\n# doc4\n*some content*")}, - {"sect/doc5.html", []byte("{{ template \"head\" }}body5")}, - {"sect/doc6.html", []byte("{{ template \"head_abs\" }}body5")}, - {"doc7.html", []byte("doc7 content")}, - {"sect/doc8.html", []byte("---\nmarkup: md\n---\n# title\nsome *content*")}, + {filepath.FromSlash("sect/doc1.html"), []byte("---\nmarkup: markdown\n---\n# title\nsome *content*")}, + {filepath.FromSlash("sect/doc2.html"), []byte("more content")}, + {filepath.FromSlash("sect/doc3.md"), []byte("# doc3\n*some* content")}, + {filepath.FromSlash("sect/doc4.md"), []byte("---\ntitle: doc4\n---\n# doc4\n*some content*")}, + {filepath.FromSlash("sect/doc5.html"), []byte("{{ template \"head\" }}body5")}, + {filepath.FromSlash("sect/doc6.html"), []byte("{{ template \"head_abs\" }}body5")}, + {filepath.FromSlash("doc7.html"), []byte("doc7 content")}, + {filepath.FromSlash("sect/doc8.html"), []byte("---\nmarkup: md\n---\n# title\nsome *content*")}, } viper.Set("verbose", true) @@ -337,14 +338,14 @@ func TestSkipRender(t *testing.T) { doc string expected string }{ - {"sect/doc1.html", "\n\n

title

\n\n

some content

\n"}, - {"sect/doc2.html", "more content"}, - {"sect/doc3.html", "\n\n

doc3

\n\n

some content

\n"}, - {"sect/doc4.html", "\n\n

doc4

\n\n

some content

\n"}, - {"sect/doc5.html", "body5"}, - {"sect/doc6.html", "body5"}, - {"doc7.html", "doc7 content"}, - {"sect/doc8.html", "\n\n

title

\n\n

some content

\n"}, + {filepath.FromSlash("sect/doc1.html"), "\n\n

title

\n\n

some content

\n"}, + {filepath.FromSlash("sect/doc2.html"), "more content"}, + {filepath.FromSlash("sect/doc3.html"), "\n\n

doc3

\n\n

some content

\n"}, + {filepath.FromSlash("sect/doc4.html"), "\n\n

doc4

\n\n

some content

\n"}, + {filepath.FromSlash("sect/doc5.html"), "body5"}, + {filepath.FromSlash("sect/doc6.html"), "body5"}, + {filepath.FromSlash("doc7.html"), "doc7 content"}, + {filepath.FromSlash("sect/doc8.html"), "\n\n

title

\n\n

some content

\n"}, } for _, test := range tests { @@ -363,8 +364,8 @@ func TestSkipRender(t *testing.T) { func TestAbsUrlify(t *testing.T) { hugofs.DestinationFS = new(afero.MemMapFs) sources := []source.ByteSource{ - {"sect/doc1.html", []byte("link")}, - {"content/blue/doc2.html", []byte("---\nf: t\n---\nmore content")}, + {filepath.FromSlash("sect/doc1.html"), []byte("link")}, + {filepath.FromSlash("content/blue/doc2.html"), []byte("---\nf: t\n---\nmore content")}, } for _, canonify := range []bool{true, false} { viper.Set("CanonifyUrls", canonify) @@ -399,7 +400,7 @@ func TestAbsUrlify(t *testing.T) { for _, test := range tests { - file, err := hugofs.DestinationFS.Open(test.file) + file, err := hugofs.DestinationFS.Open(filepath.FromSlash(test.file)) if err != nil { t.Fatalf("Unable to locate rendered content: %s", test.file) } @@ -454,10 +455,10 @@ my_date = 2010-05-27T07:32:00Z Front Matter with Ordered Pages 4. This is longer content`) var WEIGHTED_SOURCES = []source.ByteSource{ - {"sect/doc1.md", WEIGHTED_PAGE_1}, - {"sect/doc2.md", WEIGHTED_PAGE_2}, - {"sect/doc3.md", WEIGHTED_PAGE_3}, - {"sect/doc4.md", WEIGHTED_PAGE_4}, + {filepath.FromSlash("sect/doc1.md"), WEIGHTED_PAGE_1}, + {filepath.FromSlash("sect/doc2.md"), WEIGHTED_PAGE_2}, + {filepath.FromSlash("sect/doc3.md"), WEIGHTED_PAGE_3}, + {filepath.FromSlash("sect/doc4.md"), WEIGHTED_PAGE_4}, } func TestOrderedPages(t *testing.T) { @@ -519,10 +520,10 @@ func TestOrderedPages(t *testing.T) { } var GROUPED_SOURCES = []source.ByteSource{ - {"sect1/doc1.md", WEIGHTED_PAGE_1}, - {"sect1/doc2.md", WEIGHTED_PAGE_2}, - {"sect2/doc3.md", WEIGHTED_PAGE_3}, - {"sect3/doc4.md", WEIGHTED_PAGE_4}, + {filepath.FromSlash("sect1/doc1.md"), WEIGHTED_PAGE_1}, + {filepath.FromSlash("sect1/doc2.md"), WEIGHTED_PAGE_2}, + {filepath.FromSlash("sect2/doc3.md"), WEIGHTED_PAGE_3}, + {filepath.FromSlash("sect3/doc4.md"), WEIGHTED_PAGE_4}, } func TestGroupedPages(t *testing.T) { @@ -712,9 +713,9 @@ Front Matter with weighted tags and categories`) func TestWeightedTaxonomies(t *testing.T) { hugofs.DestinationFS = new(afero.MemMapFs) sources := []source.ByteSource{ - {"sect/doc1.md", PAGE_WITH_WEIGHTED_TAXONOMIES_1}, - {"sect/doc2.md", PAGE_WITH_WEIGHTED_TAXONOMIES_2}, - {"sect/doc3.md", PAGE_WITH_WEIGHTED_TAXONOMIES_3}, + {filepath.FromSlash("sect/doc1.md"), PAGE_WITH_WEIGHTED_TAXONOMIES_1}, + {filepath.FromSlash("sect/doc2.md"), PAGE_WITH_WEIGHTED_TAXONOMIES_2}, + {filepath.FromSlash("sect/doc3.md"), PAGE_WITH_WEIGHTED_TAXONOMIES_3}, } taxonomies := make(map[string]string) diff --git a/hugolib/site_url_test.go b/hugolib/site_url_test.go index c0825e56b16..331cbc49f3a 100644 --- a/hugolib/site_url_test.go +++ b/hugolib/site_url_test.go @@ -2,6 +2,7 @@ package hugolib import ( "html/template" + "path/filepath" "testing" "github.com/spf13/afero" @@ -47,8 +48,8 @@ func (t *InMemoryAliasTarget) Publish(label string, permalink template.HTML) (er } var urlFakeSource = []source.ByteSource{ - {"content/blue/doc1.md", []byte(SLUG_DOC_1)}, - {"content/blue/doc2.md", []byte(SLUG_DOC_2)}, + {filepath.FromSlash("content/blue/doc1.md"), []byte(SLUG_DOC_1)}, + {filepath.FromSlash("content/blue/doc2.md"), []byte(SLUG_DOC_2)}, } func TestPageCount(t *testing.T) { @@ -93,7 +94,7 @@ func TestPageCount(t *testing.T) { "sd3/index.html", "sd4.html", } { - if _, err := hugofs.DestinationFS.Open(s); err != nil { + if _, err := hugofs.DestinationFS.Open(filepath.FromSlash(s)); err != nil { t.Errorf("No alias rendered: %s", s) } } diff --git a/source/file.go b/source/file.go index 4c6196a9fb4..a4a5b27c3df 100644 --- a/source/file.go +++ b/source/file.go @@ -14,12 +14,10 @@ package source import ( + "github.com/spf13/hugo/helpers" "io" - "path" "path/filepath" "strings" - - "github.com/spf13/hugo/helpers" ) type File struct { @@ -65,7 +63,7 @@ func (f *File) LogicalName() string { if f.logicalName != "" { return f.logicalName } else { - _, f.logicalName = path.Split(f.relpath) + _, f.logicalName = filepath.Split(f.relpath) return f.logicalName } } @@ -78,7 +76,7 @@ func (f *File) Dir() string { if f.dir != "" { return f.dir } else { - f.dir, _ = path.Split(f.relpath) + f.dir, _ = filepath.Split(f.relpath) return f.dir } } diff --git a/source/filesystem_windows_test.go b/source/filesystem_windows_test.go index e9cbdd4a101..ee618537481 100644 --- a/source/filesystem_windows_test.go +++ b/source/filesystem_windows_test.go @@ -8,8 +8,8 @@ package source var platformBase = "C:\\foo\\" var platformPaths = []TestPath{ {"foobar", "foobar", "aaa", "", ""}, - {"b\\1file", "1file", "aaa", "b", "b/"}, - {"c\\d\\2file", "2file", "aaa", "c", "c/d/"}, - {"C:\\foo\\e\\f\\3file", "3file", "aaa", "e", "e/f/"}, // note volume case is equal to platformBase - {"section\\foo.rss", "foo.rss", "aaa", "section", "section/"}, + {"b\\1file", "1file", "aaa", "b", "b\\"}, + {"c\\d\\2file", "2file", "aaa", "c", "c\\d\\"}, + {"C:\\foo\\e\\f\\3file", "3file", "aaa", "e", "e\\f\\"}, // note volume case is equal to platformBase + {"section\\foo.rss", "foo.rss", "aaa", "section", "section\\"}, } diff --git a/target/alias_test.go b/target/alias_test.go index d19349f230f..ec686af5402 100644 --- a/target/alias_test.go +++ b/target/alias_test.go @@ -1,6 +1,7 @@ package target import ( + "path/filepath" "testing" ) @@ -13,14 +14,14 @@ func TestHTMLRedirectAlias(t *testing.T) { expected string }{ {"", ""}, - {"s", "s/index.html"}, - {"/", "/index.html"}, - {"alias 1", "alias-1/index.html"}, - {"alias 2/", "alias-2/index.html"}, + {"s", filepath.FromSlash("s/index.html")}, + {"/", filepath.FromSlash("/index.html")}, + {"alias 1", filepath.FromSlash("alias-1/index.html")}, + {"alias 2/", filepath.FromSlash("alias-2/index.html")}, {"alias 3.html", "alias-3.html"}, {"alias4.html", "alias4.html"}, - {"/alias 5.html", "/alias-5.html"}, - {"/трям.html", "/трям.html"}, + {"/alias 5.html", filepath.FromSlash("/alias-5.html")}, + {"/трям.html", filepath.FromSlash("/трям.html")}, } for _, test := range tests { diff --git a/target/page.go b/target/page.go index 924037402ff..b02e139258c 100644 --- a/target/page.go +++ b/target/page.go @@ -32,7 +32,7 @@ func (pp *PagePub) Publish(path string, r io.Reader) (err error) { } func (pp *PagePub) Translate(src string) (dest string, err error) { - if src == "/" { + if src == helpers.FilePathSeparator { if pp.PublishDir != "" { return filepath.Join(pp.PublishDir, "index.html"), nil } diff --git a/target/page_test.go b/target/page_test.go index 69ad1cfa21c..ab3b0f1ca6d 100644 --- a/target/page_test.go +++ b/target/page_test.go @@ -1,6 +1,7 @@ package target import ( + "path/filepath" "testing" ) @@ -24,13 +25,14 @@ func TestPageTranslator(t *testing.T) { for _, test := range tests { f := new(PagePub) - dest, err := f.Translate(test.content) + dest, err := f.Translate(filepath.FromSlash(test.content)) + expected := filepath.FromSlash(test.expected) if err != nil { t.Fatalf("Translate returned and unexpected err: %s", err) } - if dest != test.expected { - t.Errorf("Tranlate expected return: %s, got: %s", test.expected, dest) + if dest != expected { + t.Errorf("Translate expected return: %s, got: %s", expected, dest) } } } @@ -53,7 +55,7 @@ func TestPageTranslatorBase(t *testing.T) { t.Fatalf("Translated returned and err: %s", err) } - if dest != test.expected { + if dest != filepath.FromSlash(test.expected) { t.Errorf("Translate expected: %s, got: %s", test.expected, dest) } } @@ -73,7 +75,7 @@ func TestTranslateUglyUrls(t *testing.T) { for _, test := range tests { f := &PagePub{UglyUrls: true} - dest, err := f.Translate(test.content) + dest, err := f.Translate(filepath.FromSlash(test.content)) if err != nil { t.Fatalf("Translate returned an unexpected err: %s", err) } @@ -87,7 +89,7 @@ func TestTranslateUglyUrls(t *testing.T) { func TestTranslateDefaultExtension(t *testing.T) { f := &PagePub{DefaultExtension: ".foobar"} dest, _ := f.Translate("baz") - if dest != "baz/index.foobar" { + if dest != filepath.FromSlash("baz/index.foobar") { t.Errorf("Translate expected return: %s, got %s", "baz/index.foobar", dest) } } diff --git a/tpl/template.go b/tpl/template.go index f61376552c5..5010af9ae56 100644 --- a/tpl/template.go +++ b/tpl/template.go @@ -603,6 +603,7 @@ func ExecuteTemplate(context interface{}, layouts ...string) *bytes.Buffer { buffer := new(bytes.Buffer) worked := false for _, layout := range layouts { + name := layout if localTemplates.Lookup(name) == nil { @@ -701,7 +702,7 @@ func (t *GoHtmlTemplate) AddTemplateFile(name, path string) error { } -func (t *GoHtmlTemplate) generateTemplateNameFrom(base, path string) string { +func (t *GoHtmlTemplate) GenerateTemplateNameFrom(base, path string) string { return filepath.ToSlash(path[len(base)+1:]) } @@ -720,7 +721,7 @@ func (t *GoHtmlTemplate) loadTemplates(absPath string, prefix string) { return nil } - tplName := t.generateTemplateNameFrom(absPath, path) + tplName := t.GenerateTemplateNameFrom(absPath, path) if prefix != "" { tplName = strings.Trim(prefix, "/") + "/" + tplName