diff options
Diffstat (limited to 'helpers')
-rw-r--r-- | helpers/content.go | 37 | ||||
-rw-r--r-- | helpers/content_test.go | 71 | ||||
-rw-r--r-- | helpers/general.go | 14 | ||||
-rw-r--r-- | helpers/general_test.go | 79 | ||||
-rw-r--r-- | helpers/path.go | 17 | ||||
-rw-r--r-- | helpers/path_test.go | 85 | ||||
-rw-r--r-- | helpers/pathspec.go | 11 | ||||
-rw-r--r-- | helpers/pathspec_test.go | 62 | ||||
-rw-r--r-- | helpers/testhelpers_test.go | 58 | ||||
-rw-r--r-- | helpers/url.go | 33 | ||||
-rw-r--r-- | helpers/url_test.go | 142 |
11 files changed, 220 insertions, 389 deletions
diff --git a/helpers/content.go b/helpers/content.go index d04e34a07..510d496b9 100644 --- a/helpers/content.go +++ b/helpers/content.go @@ -50,30 +50,18 @@ type ContentSpec struct { anchorNameSanitizer converter.AnchorNameSanitizer getRenderer func(t hooks.RendererType, id any) any - // SummaryLength is the length of the summary that Hugo extracts from a content. - summaryLength int - - BuildFuture bool - BuildExpired bool - BuildDrafts bool - - Cfg config.Provider + Cfg config.AllProvider } // NewContentSpec returns a ContentSpec initialized // with the appropriate fields from the given config.Provider. -func NewContentSpec(cfg config.Provider, logger loggers.Logger, contentFs afero.Fs, ex *hexec.Exec) (*ContentSpec, error) { +func NewContentSpec(cfg config.AllProvider, logger loggers.Logger, contentFs afero.Fs, ex *hexec.Exec) (*ContentSpec, error) { spec := &ContentSpec{ - summaryLength: cfg.GetInt("summaryLength"), - BuildFuture: cfg.GetBool("buildFuture"), - BuildExpired: cfg.GetBool("buildExpired"), - BuildDrafts: cfg.GetBool("buildDrafts"), - Cfg: cfg, } converterProvider, err := markup.NewConverterProvider(converter.ProviderConfig{ - Cfg: cfg, + Conf: cfg, ContentFs: contentFs, Logger: logger, Exec: ex, @@ -157,6 +145,9 @@ func (c *ContentSpec) SanitizeAnchorName(s string) string { } func (c *ContentSpec) ResolveMarkup(in string) string { + if c == nil { + panic("nil ContentSpec") + } in = strings.ToLower(in) switch in { case "md", "markdown", "mdown": @@ -194,17 +185,17 @@ func (c *ContentSpec) TruncateWordsByRune(in []string) (string, bool) { count := 0 for index, word := range words { - if count >= c.summaryLength { + if count >= c.Cfg.SummaryLength() { return strings.Join(words[:index], " "), true } runeCount := utf8.RuneCountInString(word) if len(word) == runeCount { count++ - } else if count+runeCount < c.summaryLength { + } else if count+runeCount < c.Cfg.SummaryLength() { count += runeCount } else { for ri := range word { - if count >= c.summaryLength { + if count >= c.Cfg.SummaryLength() { truncatedWords := append(words[:index], word[:ri]) return strings.Join(truncatedWords, " "), true } @@ -229,7 +220,7 @@ func (c *ContentSpec) TruncateWordsToWholeSentence(s string) (string, bool) { wordCount++ lastWordIndex = i - if wordCount >= c.summaryLength { + if wordCount >= c.Cfg.SummaryLength() { break } @@ -283,19 +274,19 @@ func isEndOfSentence(r rune) bool { func (c *ContentSpec) truncateWordsToWholeSentenceOld(content string) (string, bool) { words := strings.Fields(content) - if c.summaryLength >= len(words) { + if c.Cfg.SummaryLength() >= len(words) { return strings.Join(words, " "), false } - for counter, word := range words[c.summaryLength:] { + for counter, word := range words[c.Cfg.SummaryLength():] { if strings.HasSuffix(word, ".") || strings.HasSuffix(word, "?") || strings.HasSuffix(word, ".\"") || strings.HasSuffix(word, "!") { - upper := c.summaryLength + counter + 1 + upper := c.Cfg.SummaryLength() + counter + 1 return strings.Join(words[:upper], " "), (upper < len(words)) } } - return strings.Join(words[:c.summaryLength], " "), true + return strings.Join(words[:c.Cfg.SummaryLength()], " "), true } diff --git a/helpers/content_test.go b/helpers/content_test.go index 54b7ef3f9..2909c0266 100644 --- a/helpers/content_test.go +++ b/helpers/content_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Hugo Authors. All rights reserved. +// Copyright 2023 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package helpers +package helpers_test import ( "bytes" @@ -19,12 +19,9 @@ import ( "strings" "testing" - "github.com/spf13/afero" - - "github.com/gohugoio/hugo/common/loggers" - "github.com/gohugoio/hugo/config" - qt "github.com/frankban/quicktest" + "github.com/gohugoio/hugo/config" + "github.com/gohugoio/hugo/helpers" ) const tstHTMLContent = "<!DOCTYPE html><html><head><script src=\"http://two/foobar.js\"></script></head><body><nav><ul><li hugo-nav=\"section_0\"></li><li hugo-nav=\"section_1\"></li></ul></nav><article>content <a href=\"http://two/foobar\">foobar</a>. Follow up</article><p>This is some text.<br>And some more.</p></body></html>" @@ -43,7 +40,7 @@ func TestTrimShortHTML(t *testing.T) { {[]byte("<p>Hello</p>\n<ul>\n<li>list1</li>\n<li>list2</li>\n</ul>"), []byte("<p>Hello</p>\n<ul>\n<li>list1</li>\n<li>list2</li>\n</ul>")}, } - c := newTestContentSpec() + c := newTestContentSpec(nil) for i, test := range tests { output := c.TrimShortHTML(test.input) if !bytes.Equal(test.output, output) { @@ -52,55 +49,23 @@ func TestTrimShortHTML(t *testing.T) { } } -func TestStripEmptyNav(t *testing.T) { - c := qt.New(t) - cleaned := stripEmptyNav([]byte("do<nav>\n</nav>\n\nbedobedo")) - c.Assert(cleaned, qt.DeepEquals, []byte("dobedobedo")) -} - func TestBytesToHTML(t *testing.T) { c := qt.New(t) - c.Assert(BytesToHTML([]byte("dobedobedo")), qt.Equals, template.HTML("dobedobedo")) -} - -func TestNewContentSpec(t *testing.T) { - cfg := config.NewWithTestDefaults() - c := qt.New(t) - - cfg.Set("summaryLength", 32) - cfg.Set("buildFuture", true) - cfg.Set("buildExpired", true) - cfg.Set("buildDrafts", true) - - spec, err := NewContentSpec(cfg, loggers.NewErrorLogger(), afero.NewMemMapFs(), nil) - - c.Assert(err, qt.IsNil) - c.Assert(spec.summaryLength, qt.Equals, 32) - c.Assert(spec.BuildFuture, qt.Equals, true) - c.Assert(spec.BuildExpired, qt.Equals, true) - c.Assert(spec.BuildDrafts, qt.Equals, true) + c.Assert(helpers.BytesToHTML([]byte("dobedobedo")), qt.Equals, template.HTML("dobedobedo")) } var benchmarkTruncateString = strings.Repeat("This is a sentence about nothing.", 20) func BenchmarkTestTruncateWordsToWholeSentence(b *testing.B) { - c := newTestContentSpec() + c := newTestContentSpec(nil) b.ResetTimer() for i := 0; i < b.N; i++ { c.TruncateWordsToWholeSentence(benchmarkTruncateString) } } -func BenchmarkTestTruncateWordsToWholeSentenceOld(b *testing.B) { - c := newTestContentSpec() - b.ResetTimer() - for i := 0; i < b.N; i++ { - c.truncateWordsToWholeSentenceOld(benchmarkTruncateString) - } -} - func TestTruncateWordsToWholeSentence(t *testing.T) { - c := newTestContentSpec() + type test struct { input, expected string max int @@ -118,7 +83,9 @@ func TestTruncateWordsToWholeSentence(t *testing.T) { {"This... is a more difficult test?", "This... is a more difficult test?", 1, false}, } for i, d := range data { - c.summaryLength = d.max + cfg := config.New() + cfg.Set("summaryLength", d.max) + c := newTestContentSpec(cfg) output, truncated := c.TruncateWordsToWholeSentence(d.input) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) @@ -131,7 +98,7 @@ func TestTruncateWordsToWholeSentence(t *testing.T) { } func TestTruncateWordsByRune(t *testing.T) { - c := newTestContentSpec() + type test struct { input, expected string max int @@ -153,7 +120,9 @@ func TestTruncateWordsByRune(t *testing.T) { {" \nThis is not a sentence\n ", "This is not", 3, true}, } for i, d := range data { - c.summaryLength = d.max + cfg := config.New() + cfg.Set("summaryLength", d.max) + c := newTestContentSpec(cfg) output, truncated := c.TruncateWordsByRune(strings.Fields(d.input)) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) @@ -168,7 +137,7 @@ func TestTruncateWordsByRune(t *testing.T) { func TestExtractTOCNormalContent(t *testing.T) { content := []byte("<nav>\n<ul>\nTOC<li><a href=\"#") - actualTocLessContent, actualToc := ExtractTOC(content) + actualTocLessContent, actualToc := helpers.ExtractTOC(content) expectedTocLess := []byte("TOC<li><a href=\"#") expectedToc := []byte("<nav id=\"TableOfContents\">\n<ul>\n") @@ -184,7 +153,7 @@ func TestExtractTOCNormalContent(t *testing.T) { func TestExtractTOCGreaterThanSeventy(t *testing.T) { content := []byte("<nav>\n<ul>\nTOC This is a very long content which will definitely be greater than seventy, I promise you that.<li><a href=\"#") - actualTocLessContent, actualToc := ExtractTOC(content) + actualTocLessContent, actualToc := helpers.ExtractTOC(content) // Because the start of Toc is greater than 70+startpoint of <li> content and empty TOC will be returned expectedToc := []byte("") @@ -200,7 +169,7 @@ func TestExtractTOCGreaterThanSeventy(t *testing.T) { func TestExtractNoTOC(t *testing.T) { content := []byte("TOC") - actualTocLessContent, actualToc := ExtractTOC(content) + actualTocLessContent, actualToc := helpers.ExtractTOC(content) expectedToc := []byte("") if !bytes.Equal(actualTocLessContent, content) { @@ -225,7 +194,7 @@ func TestTotalWords(t *testing.T) { {"One, Two, Three", 3}, {totalWordsBenchmarkString, 400}, } { - actualWordCount := TotalWords(this.s) + actualWordCount := helpers.TotalWords(this.s) if actualWordCount != this.words { t.Errorf("[%d] Actual word count (%d) for test string (%s) did not match %d", i, actualWordCount, this.s, this.words) @@ -236,7 +205,7 @@ func TestTotalWords(t *testing.T) { func BenchmarkTotalWords(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { - wordCount := TotalWords(totalWordsBenchmarkString) + wordCount := helpers.TotalWords(totalWordsBenchmarkString) if wordCount != 400 { b.Fatal("Wordcount error") } diff --git a/helpers/general.go b/helpers/general.go index 920376227..e8d8bdecc 100644 --- a/helpers/general.go +++ b/helpers/general.go @@ -43,20 +43,6 @@ import ( // FilePathSeparator as defined by os.Separator. const FilePathSeparator = string(filepath.Separator) -// FindAvailablePort returns an available and valid TCP port. -func FindAvailablePort() (*net.TCPAddr, error) { - l, err := net.Listen("tcp", ":0") - if err == nil { - defer l.Close() - addr := l.Addr() - if a, ok := addr.(*net.TCPAddr); ok { - return a, nil - } - return nil, fmt.Errorf("unable to obtain a valid tcp port: %v", addr) - } - return nil, err -} - // TCPListen starts listening on a valid TCP port. func TCPListen() (net.Listener, *net.TCPAddr, error) { l, err := net.Listen("tcp", ":0") diff --git a/helpers/general_test.go b/helpers/general_test.go index b2ee03f15..9b2e4fc58 100644 --- a/helpers/general_test.go +++ b/helpers/general_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Hugo Authors. All rights reserved. +// Copyright 2023 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package helpers +package helpers_test import ( "fmt" @@ -21,17 +21,14 @@ import ( "time" "github.com/gohugoio/hugo/common/loggers" - "github.com/gohugoio/hugo/config" + "github.com/gohugoio/hugo/helpers" qt "github.com/frankban/quicktest" "github.com/spf13/afero" ) func TestResolveMarkup(t *testing.T) { - c := qt.New(t) - cfg := config.NewWithTestDefaults() - spec, err := NewContentSpec(cfg, loggers.NewErrorLogger(), afero.NewMemMapFs(), nil) - c.Assert(err, qt.IsNil) + spec := newTestContentSpec(nil) for i, this := range []struct { in string @@ -61,7 +58,7 @@ func TestResolveMarkup(t *testing.T) { func TestDistinctLoggerDoesNotLockOnWarningPanic(t *testing.T) { // Testing to make sure logger mutex doesn't lock if warnings cause panics. // func Warnf() of DistinctLogger is defined in general.go - l := NewDistinctLogger(loggers.NewWarningLogger()) + l := helpers.NewDistinctLogger(loggers.NewWarningLogger()) // Set PanicOnWarning to true to reproduce issue 9380 // Ensure global variable loggers.PanicOnWarning is reset to old value after test @@ -123,7 +120,7 @@ func TestFirstUpper(t *testing.T) { {"", ""}, {"å", "Å"}, } { - result := FirstUpper(this.in) + result := helpers.FirstUpper(this.in) if result != this.expect { t.Errorf("[%d] got %s but expected %s", i, result, this.expect) } @@ -143,7 +140,7 @@ func TestHasStringsPrefix(t *testing.T) { {[]string{"abra", "ca", "dabra"}, []string{"abra", "ca"}, true}, {[]string{"abra", "ca"}, []string{"abra", "ca", "dabra"}, false}, } { - result := HasStringsPrefix(this.s, this.prefix) + result := helpers.HasStringsPrefix(this.s, this.prefix) if result != this.expect { t.Fatalf("[%d] got %t but expected %t", i, result, this.expect) } @@ -162,7 +159,7 @@ func TestHasStringsSuffix(t *testing.T) { {[]string{"abra", "ca", "dabra"}, []string{"abra", "ca"}, false}, {[]string{"abra", "ca", "dabra"}, []string{"ca", "dabra"}, true}, } { - result := HasStringsSuffix(this.s, this.suffix) + result := helpers.HasStringsSuffix(this.s, this.suffix) if result != this.expect { t.Fatalf("[%d] got %t but expected %t", i, result, this.expect) } @@ -239,7 +236,7 @@ func TestSliceToLower(t *testing.T) { } for _, test := range tests { - res := SliceToLower(test.value) + res := helpers.SliceToLower(test.value) for i, val := range res { if val != test.expected[i] { t.Errorf("Case mismatch. Expected %s, got %s", test.expected[i], res[i]) @@ -251,34 +248,34 @@ func TestSliceToLower(t *testing.T) { func TestReaderContains(t *testing.T) { c := qt.New(t) for i, this := range append(containsBenchTestData, containsAdditionalTestData...) { - result := ReaderContains(strings.NewReader(this.v1), this.v2) + result := helpers.ReaderContains(strings.NewReader(this.v1), this.v2) if result != this.expect { t.Errorf("[%d] got %t but expected %t", i, result, this.expect) } } - c.Assert(ReaderContains(nil, []byte("a")), qt.Equals, false) - c.Assert(ReaderContains(nil, nil), qt.Equals, false) + c.Assert(helpers.ReaderContains(nil, []byte("a")), qt.Equals, false) + c.Assert(helpers.ReaderContains(nil, nil), qt.Equals, false) } func TestGetTitleFunc(t *testing.T) { title := "somewhere over the rainbow" c := qt.New(t) - c.Assert(GetTitleFunc("go")(title), qt.Equals, "Somewhere Over The Rainbow") - c.Assert(GetTitleFunc("chicago")(title), qt.Equals, "Somewhere over the Rainbow") - c.Assert(GetTitleFunc("Chicago")(title), qt.Equals, "Somewhere over the Rainbow") - c.Assert(GetTitleFunc("ap")(title), qt.Equals, "Somewhere Over the Rainbow") - c.Assert(GetTitleFunc("ap")(title), qt.Equals, "Somewhere Over the Rainbow") - c.Assert(GetTitleFunc("")(title), qt.Equals, "Somewhere Over the Rainbow") - c.Assert(GetTitleFunc("unknown")(title), qt.Equals, "Somewhere Over the Rainbow") + c.Assert(helpers.GetTitleFunc("go")(title), qt.Equals, "Somewhere Over The Rainbow") + c.Assert(helpers.GetTitleFunc("chicago")(title), qt.Equals, "Somewhere over the Rainbow") + c.Assert(helpers.GetTitleFunc("Chicago")(title), qt.Equals, "Somewhere over the Rainbow") + c.Assert(helpers.GetTitleFunc("ap")(title), qt.Equals, "Somewhere Over the Rainbow") + c.Assert(helpers.GetTitleFunc("ap")(title), qt.Equals, "Somewhere Over the Rainbow") + c.Assert(helpers.GetTitleFunc("")(title), qt.Equals, "Somewhere Over the Rainbow") + c.Assert(helpers.GetTitleFunc("unknown")(title), qt.Equals, "Somewhere Over the Rainbow") } func BenchmarkReaderContains(b *testing.B) { b.ResetTimer() for i := 0; i < b.N; i++ { for i, this := range containsBenchTestData { - result := ReaderContains(strings.NewReader(this.v1), this.v2) + result := helpers.ReaderContains(strings.NewReader(this.v1), this.v2) if result != this.expect { b.Errorf("[%d] got %t but expected %t", i, result, this.expect) } @@ -288,7 +285,7 @@ func BenchmarkReaderContains(b *testing.B) { func TestUniqueStrings(t *testing.T) { in := []string{"a", "b", "a", "b", "c", "", "a", "", "d"} - output := UniqueStrings(in) + output := helpers.UniqueStrings(in) expected := []string{"a", "b", "c", "", "d"} if !reflect.DeepEqual(output, expected) { t.Errorf("Expected %#v, got %#v\n", expected, output) @@ -297,7 +294,7 @@ func TestUniqueStrings(t *testing.T) { func TestUniqueStringsReuse(t *testing.T) { in := []string{"a", "b", "a", "b", "c", "", "a", "", "d"} - output := UniqueStringsReuse(in) + output := helpers.UniqueStringsReuse(in) expected := []string{"a", "b", "c", "", "d"} if !reflect.DeepEqual(output, expected) { t.Errorf("Expected %#v, got %#v\n", expected, output) @@ -307,18 +304,10 @@ func TestUniqueStringsReuse(t *testing.T) { func TestUniqueStringsSorted(t *testing.T) { c := qt.New(t) in := []string{"a", "a", "b", "c", "b", "", "a", "", "d"} - output := UniqueStringsSorted(in) + output := helpers.UniqueStringsSorted(in) expected := []string{"", "a", "b", "c", "d"} c.Assert(output, qt.DeepEquals, expected) - c.Assert(UniqueStringsSorted(nil), qt.IsNil) -} - -func TestFindAvailablePort(t *testing.T) { - c := qt.New(t) - addr, err := FindAvailablePort() - c.Assert(err, qt.IsNil) - c.Assert(addr, qt.Not(qt.IsNil)) - c.Assert(addr.Port > 0, qt.Equals, true) + c.Assert(helpers.UniqueStringsSorted(nil), qt.IsNil) } func TestFastMD5FromFile(t *testing.T) { @@ -357,23 +346,23 @@ func TestFastMD5FromFile(t *testing.T) { defer bf1.Close() defer bf2.Close() - m1, err := MD5FromFileFast(sf1) + m1, err := helpers.MD5FromFileFast(sf1) c.Assert(err, qt.IsNil) c.Assert(m1, qt.Equals, "e9c8989b64b71a88b4efb66ad05eea96") - m2, err := MD5FromFileFast(sf2) + m2, err := helpers.MD5FromFileFast(sf2) c.Assert(err, qt.IsNil) c.Assert(m2, qt.Not(qt.Equals), m1) - m3, err := MD5FromFileFast(bf1) + m3, err := helpers.MD5FromFileFast(bf1) c.Assert(err, qt.IsNil) c.Assert(m3, qt.Not(qt.Equals), m2) - m4, err := MD5FromFileFast(bf2) + m4, err := helpers.MD5FromFileFast(bf2) c.Assert(err, qt.IsNil) c.Assert(m4, qt.Not(qt.Equals), m3) - m5, err := MD5FromReader(bf2) + m5, err := helpers.MD5FromReader(bf2) c.Assert(err, qt.IsNil) c.Assert(m5, qt.Not(qt.Equals), m4) } @@ -394,11 +383,11 @@ func BenchmarkMD5FromFileFast(b *testing.B) { } b.StartTimer() if full { - if _, err := MD5FromReader(f); err != nil { + if _, err := helpers.MD5FromReader(f); err != nil { b.Fatal(err) } } else { - if _, err := MD5FromFileFast(f); err != nil { + if _, err := helpers.MD5FromFileFast(f); err != nil { b.Fatal(err) } } @@ -413,7 +402,7 @@ func BenchmarkUniqueStrings(b *testing.B) { b.Run("Safe", func(b *testing.B) { for i := 0; i < b.N; i++ { - result := UniqueStrings(input) + result := helpers.UniqueStrings(input) if len(result) != 6 { b.Fatal(fmt.Sprintf("invalid count: %d", len(result))) } @@ -432,7 +421,7 @@ func BenchmarkUniqueStrings(b *testing.B) { for i := 0; i < b.N; i++ { inputc := inputs[i] - result := UniqueStringsReuse(inputc) + result := helpers.UniqueStringsReuse(inputc) if len(result) != 6 { b.Fatal(fmt.Sprintf("invalid count: %d", len(result))) } @@ -451,7 +440,7 @@ func BenchmarkUniqueStrings(b *testing.B) { for i := 0; i < b.N; i++ { inputc := inputs[i] - result := UniqueStringsSorted(inputc) + result := helpers.UniqueStringsSorted(inputc) if len(result) != 6 { b.Fatal(fmt.Sprintf("invalid count: %d", len(result))) } diff --git a/helpers/path.go b/helpers/path.go index 7bc216ec8..00c541bab 100644 --- a/helpers/path.go +++ b/helpers/path.go @@ -1,4 +1,4 @@ -// Copyright 2019 The Hugo Authors. All rights reserved. +// Copyright 2023 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -28,8 +28,6 @@ import ( "github.com/gohugoio/hugo/common/herrors" "github.com/gohugoio/hugo/common/text" - "github.com/gohugoio/hugo/config" - "github.com/gohugoio/hugo/hugofs" "github.com/gohugoio/hugo/common/hugio" @@ -54,7 +52,7 @@ func (p *PathSpec) MakePathsSanitized(paths []string) { // MakePathSanitized creates a Unicode-sanitized string, with the spaces replaced func (p *PathSpec) MakePathSanitized(s string) string { - if p.DisablePathToLower { + if p.Cfg.DisablePathToLower() { return p.MakePath(s) } return strings.ToLower(p.MakePath(s)) @@ -91,7 +89,7 @@ func ishex(c rune) bool { // Hyphens in the original input are maintained. // Spaces will be replaced with a single hyphen, and sequential replacement hyphens will be reduced to one. func (p *PathSpec) UnicodeSanitize(s string) string { - if p.RemovePathAccents { + if p.Cfg.RemovePathAccents() { s = text.RemoveAccentsString(s) } @@ -128,7 +126,7 @@ func (p *PathSpec) UnicodeSanitize(s string) string { return string(target) } -func makePathRelative(inPath string, possibleDirectories ...string) (string, error) { +func MakePathRelative(inPath string, possibleDirectories ...string) (string, error) { for _, currentPath := range possibleDirectories { if strings.HasPrefix(inPath, currentPath) { return strings.TrimPrefix(inPath, currentPath), nil @@ -394,8 +392,8 @@ func OpenFileForWriting(fs afero.Fs, filename string) (afero.File, error) { // GetCacheDir returns a cache dir from the given filesystem and config. // The dir will be created if it does not exist. -func GetCacheDir(fs afero.Fs, cfg config.Provider) (string, error) { - cacheDir := getCacheDir(cfg) +func GetCacheDir(fs afero.Fs, cacheDir string) (string, error) { + cacheDir = cacheDirDefault(cacheDir) if cacheDir != "" { exists, err := DirExists(cacheDir, fs) if err != nil { @@ -414,9 +412,8 @@ func GetCacheDir(fs afero.Fs, cfg config.Provider) (string, error) { return GetTempDir("hugo_cache", fs), nil } -func getCacheDir(cfg config.Provider) string { +func cacheDirDefault(cacheDir string) string { // Always use the cacheDir config if set. - cacheDir := cfg.GetString("cacheDir") if len(cacheDir) > 1 { return addTrailingFileSeparator(cacheDir) } diff --git a/helpers/path_test.go b/helpers/path_test.go index 1f206a881..85081c5be 100644 --- a/helpers/path_test.go +++ b/helpers/path_test.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Hugo Authors. All rights reserved. +// Copyright 2023 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package helpers +package helpers_test import ( "fmt" @@ -24,16 +24,12 @@ import ( "testing" "time" - "github.com/gohugoio/hugo/langs" - qt "github.com/frankban/quicktest" - - "github.com/gohugoio/hugo/hugofs" + "github.com/gohugoio/hugo/helpers" "github.com/spf13/afero" ) func TestMakePath(t *testing.T) { - c := qt.New(t) tests := []struct { input string expected string @@ -60,13 +56,7 @@ func TestMakePath(t *testing.T) { } for _, test := range tests { - v := newTestCfg() - v.Set("removePathAccents", test.removeAccents) - - l := langs.NewDefaultLanguage(v) - p, err := NewPathSpec(hugofs.NewMem(v), l, nil) - c.Assert(err, qt.IsNil) - + p := newTestPathSpec("removePathAccents", test.removeAccents) output := p.MakePath(test.input) if output != test.expected { t.Errorf("Expected %#v, got %#v\n", test.expected, output) @@ -75,9 +65,7 @@ func TestMakePath(t *testing.T) { } func TestMakePathSanitized(t *testing.T) { - v := newTestCfg() - - p, _ := NewPathSpec(hugofs.NewMem(v), v, nil) + p := newTestPathSpec() tests := []struct { input string @@ -100,12 +88,7 @@ func TestMakePathSanitized(t *testing.T) { } func TestMakePathSanitizedDisablePathToLower(t *testing.T) { - v := newTestCfg() - - v.Set("disablePathToLower", true) - - l := langs.NewDefaultLanguage(v) - p, _ := NewPathSpec(hugofs.NewMem(v), l, nil) + p := newTestPathSpec("disablePathToLower", true) tests := []struct { input string @@ -138,12 +121,12 @@ func TestMakePathRelative(t *testing.T) { } for i, d := range data { - output, _ := makePathRelative(d.inPath, d.path1, d.path2) + output, _ := helpers.MakePathRelative(d.inPath, d.path1, d.path2) if d.output != output { t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output) } } - _, error := makePathRelative("a/b/c.ss", "/a/c", "/d/c", "/e/f") + _, error := helpers.MakePathRelative("a/b/c.ss", "/a/c", "/d/c", "/e/f") if error == nil { t.Errorf("Test failed, expected error") @@ -181,7 +164,7 @@ func doTestGetDottedRelativePath(urlFixer func(string) string, t *testing.T) { {"/404.html", "./"}, } for i, d := range data { - output := GetDottedRelativePath(d.input) + output := helpers.GetDottedRelativePath(d.input) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } @@ -198,7 +181,7 @@ func TestMakeTitle(t *testing.T) { {"make_title", "make_title"}, } for i, d := range data { - output := MakeTitle(d.input) + output := helpers.MakeTitle(d.input) if d.expected != output { t.Errorf("Test %d failed. Expected %q got %q", i, d.expected, output) } @@ -219,7 +202,7 @@ func TestDirExists(t *testing.T) { {"./..", true}, {"./../", true}, {os.TempDir(), true}, - {os.TempDir() + FilePathSeparator, true}, + {os.TempDir() + helpers.FilePathSeparator, true}, {"/", true}, {"/some-really-random-directory-name", false}, {"/some/really/random/directory/name", false}, @@ -228,7 +211,7 @@ func TestDirExists(t *testing.T) { } for i, d := range data { - exists, _ := DirExists(filepath.FromSlash(d.input), new(afero.OsFs)) + exists, _ := helpers.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) } @@ -249,7 +232,7 @@ func TestIsDir(t *testing.T) { for i, d := range data { - exists, _ := IsDir(d.input, new(afero.OsFs)) + exists, _ := helpers.IsDir(d.input, new(afero.OsFs)) if d.expected != exists { t.Errorf("Test %d failed. Expected %t got %t", i, d.expected, exists) } @@ -310,7 +293,7 @@ func TestExists(t *testing.T) { {nonExistentDir, false, nil}, } for i, d := range data { - exists, err := Exists(d.input, new(afero.OsFs)) + exists, err := helpers.Exists(d.input, new(afero.OsFs)) if d.expectedResult != exists { t.Errorf("Test %d failed. Expected result %t got %t", i, d.expectedResult, exists) } @@ -341,7 +324,7 @@ func TestAbsPathify(t *testing.T) { for i, d := range data { // todo see comment in AbsPathify - ps := newTestDefaultPathSpec("workingDir", d.workingDir) + ps := newTestPathSpec("workingDir", d.workingDir) expected := ps.AbsPathify(d.inPath) if d.expected != expected { @@ -351,7 +334,7 @@ func TestAbsPathify(t *testing.T) { t.Logf("Running platform specific path tests for %s", runtime.GOOS) if runtime.GOOS == "windows" { for i, d := range windowsData { - ps := newTestDefaultPathSpec("workingDir", d.workingDir) + ps := newTestPathSpec("workingDir", d.workingDir) expected := ps.AbsPathify(d.inPath) if d.expected != expected { @@ -360,7 +343,7 @@ func TestAbsPathify(t *testing.T) { } } else { for i, d := range unixData { - ps := newTestDefaultPathSpec("workingDir", d.workingDir) + ps := newTestPathSpec("workingDir", d.workingDir) expected := ps.AbsPathify(d.inPath) if d.expected != expected { @@ -383,7 +366,7 @@ func TestExtractAndGroupRootPaths(t *testing.T) { inCopy := make([]string, len(in)) copy(inCopy, in) - result := ExtractAndGroupRootPaths(in) + result := helpers.ExtractAndGroupRootPaths(in) c := qt.New(t) c.Assert(fmt.Sprint(result), qt.Equals, filepath.FromSlash("[/a/b/{c,e} /c/d/e]")) @@ -405,7 +388,7 @@ func TestExtractRootPaths(t *testing.T) { }} for _, test := range tests { - output := ExtractRootPaths(test.input) + output := helpers.ExtractRootPaths(test.input) if !reflect.DeepEqual(output, test.expected) { t.Errorf("Expected %#v, got %#v\n", test.expected, output) } @@ -426,7 +409,7 @@ func TestFindCWD(t *testing.T) { // I really don't know a better way to test this function. - SPF 2014.11.04 } for i, d := range data { - dir, err := FindCWD() + dir, err := helpers.FindCWD() if d.expectedDir != dir { t.Errorf("Test %d failed. Expected %q but got %q", i, d.expectedDir, dir) } @@ -459,7 +442,7 @@ func TestSafeWriteToDisk(t *testing.T) { } for i, d := range data { - e := SafeWriteToDisk(d.filename, reader, new(afero.OsFs)) + e := helpers.SafeWriteToDisk(d.filename, reader, new(afero.OsFs)) if d.expectedErr != nil { if d.expectedErr.Error() != e.Error() { t.Errorf("Test %d failed. Expected error %q but got %q", i, d.expectedErr.Error(), e.Error()) @@ -498,7 +481,7 @@ func TestWriteToDisk(t *testing.T) { } for i, d := range data { - e := WriteToDisk(d.filename, reader, new(afero.OsFs)) + e := helpers.WriteToDisk(d.filename, reader, new(afero.OsFs)) if d.expectedErr != e { t.Errorf("Test %d failed. WriteToDisk Error Expected %q but got %q", i, d.expectedErr, e) } @@ -515,27 +498,27 @@ func TestWriteToDisk(t *testing.T) { func TestGetTempDir(t *testing.T) { dir := os.TempDir() - if FilePathSeparator != dir[len(dir)-1:] { - dir = dir + FilePathSeparator + if helpers.FilePathSeparator != dir[len(dir)-1:] { + dir = dir + helpers.FilePathSeparator } - testDir := "hugoTestFolder" + FilePathSeparator + testDir := "hugoTestFolder" + helpers.FilePathSeparator tests := []struct { input string expected string }{ {"", dir}, - {testDir + " Foo bar ", dir + testDir + " Foo bar " + FilePathSeparator}, - {testDir + "Foo.Bar/foo_Bar-Foo", dir + testDir + "Foo.Bar/foo_Bar-Foo" + FilePathSeparator}, - {testDir + "fOO,bar:foo%bAR", dir + testDir + "fOObarfoo%bAR" + FilePathSeparator}, - {testDir + "fOO,bar:foobAR", dir + testDir + "fOObarfoobAR" + FilePathSeparator}, - {testDir + "FOo/BaR.html", dir + testDir + "FOo/BaR.html" + FilePathSeparator}, - {testDir + "трям/трям", dir + testDir + "трям/трям" + FilePathSeparator}, - {testDir + "은행", dir + testDir + "은행" + FilePathSeparator}, - {testDir + "Банковский кассир", dir + testDir + "Банковский кассир" + FilePathSeparator}, + {testDir + " Foo bar ", dir + testDir + " Foo bar " + helpers.FilePathSeparator}, + {testDir + "Foo.Bar/foo_Bar-Foo", dir + testDir + "Foo.Bar/foo_Bar-Foo" + helpers.FilePathSeparator}, + {testDir + "fOO,bar:foo%bAR", dir + testDir + "fOObarfoo%bAR" + helpers.FilePathSeparator}, + {testDir + "fOO,bar:foobAR", dir + testDir + "fOObarfoobAR" + helpers.FilePathSeparator}, + {testDir + "FOo/BaR.html", dir + testDir + "FOo/BaR.html" + helpers.FilePathSeparator}, + {testDir + "трям/трям", dir + testDir + "трям/трям" + helpers.FilePathSeparator}, + {testDir + "은행", dir + testDir + "은행" + helpers.FilePathSeparator}, + {testDir + "Банковский кассир", dir + testDir + "Банковский кассир" + helpers.FilePathSeparator}, } for _, test := range tests { - output := GetTempDir(test.input, new(afero.MemMapFs)) + output := helpers.GetTempDir(test.input, new(afero.MemMapFs)) if output != test.expected { t.Errorf("Expected %#v, got %#v\n", test.expected, output) } diff --git a/helpers/pathspec.go b/helpers/pathspec.go index 28b5f71c3..c9bb49038 100644 --- a/helpers/pathspec.go +++ b/helpers/pathspec.go @@ -34,17 +34,17 @@ type PathSpec struct { Fs *hugofs.Fs // The config provider to use - Cfg config.Provider + Cfg config.AllProvider } // NewPathSpec creates a new PathSpec from the given filesystems and language. -func NewPathSpec(fs *hugofs.Fs, cfg config.Provider, logger loggers.Logger) (*PathSpec, error) { +func NewPathSpec(fs *hugofs.Fs, cfg config.AllProvider, logger loggers.Logger) (*PathSpec, error) { return NewPathSpecWithBaseBaseFsProvided(fs, cfg, logger, nil) } // NewPathSpecWithBaseBaseFsProvided creates a new PathSpec from the given filesystems and language. // If an existing BaseFs is provided, parts of that is reused. -func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.Provider, logger loggers.Logger, baseBaseFs *filesystems.BaseFs) (*PathSpec, error) { +func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.AllProvider, logger loggers.Logger, baseBaseFs *filesystems.BaseFs) (*PathSpec, error) { p, err := paths.New(fs, cfg) if err != nil { return nil, err @@ -69,11 +69,6 @@ func NewPathSpecWithBaseBaseFsProvided(fs *hugofs.Fs, cfg config.Provider, logge ProcessingStats: NewProcessingStats(p.Lang()), } - basePath := ps.BaseURL.Path() - if basePath != "" && basePath != "/" { - ps.BasePath = basePath - } - return ps, nil } diff --git a/helpers/pathspec_test.go b/helpers/pathspec_test.go deleted file mode 100644 index 84448050d..000000000 --- a/helpers/pathspec_test.go +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package helpers - -import ( - "path/filepath" - "testing" - - qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/hugofs" - - "github.com/gohugoio/hugo/langs" -) - -func TestNewPathSpecFromConfig(t *testing.T) { - c := qt.New(t) - v := newTestCfg() - l := langs.NewLanguage("no", v) - v.Set("disablePathToLower", true) - v.Set("removePathAccents", true) - v.Set("uglyURLs", true) - v.Set("canonifyURLs", true) - v.Set("paginatePath", "side") - v.Set("baseURL", "http://base.com/foo") - v.Set("themesDir", "thethemes") - v.Set("layoutDir", "thelayouts") - v.Set("workingDir", "thework") - v.Set("staticDir", "thestatic") - v.Set("theme", "thetheme") - langs.LoadLanguageSettings(v, nil) - - fs := hugofs.NewMem(v) - fs.Source.MkdirAll(filepath.FromSlash("thework/thethemes/thetheme"), 0777) - - p, err := NewPathSpec(fs, l, nil) - - c.Assert(err, qt.IsNil) - c.Assert(p.CanonifyURLs, qt.Equals, true) - c.Assert(p.DisablePathToLower, qt.Equals, true) - c.Assert(p.RemovePathAccents, qt.Equals, true) - c.Assert(p.UglyURLs, qt.Equals, true) - c.Assert(p.Language.Lang, qt.Equals, "no") - c.Assert(p.PaginatePath, qt.Equals, "side") - - c.Assert(p.BaseURL.String(), qt.Equals, "http://base.com/foo") - c.Assert(p.BaseURLString, qt.Equals, "http://base.com/foo") - c.Assert(p.BaseURLNoPathString, qt.Equals, "http://base.com") - - c.Assert(p.ThemesDir, qt.Equals, "thethemes") - c.Assert(p.WorkingDir, qt.Equals, "thework") -} diff --git a/helpers/testhelpers_test.go b/helpers/testhelpers_test.go index 00be3db25..be8983fdb 100644 --- a/helpers/testhelpers_test.go +++ b/helpers/testhelpers_test.go @@ -1,47 +1,47 @@ -package helpers +package helpers_test import ( "github.com/gohugoio/hugo/common/loggers" "github.com/gohugoio/hugo/config" - "github.com/spf13/afero" - + "github.com/gohugoio/hugo/config/testconfig" + "github.com/gohugoio/hugo/helpers" "github.com/gohugoio/hugo/hugofs" - "github.com/gohugoio/hugo/langs" - "github.com/gohugoio/hugo/modules" + "github.com/spf13/afero" ) -func newTestPathSpec(fs *hugofs.Fs, v config.Provider) *PathSpec { - l := langs.NewDefaultLanguage(v) - ps, _ := NewPathSpec(fs, l, nil) +func newTestPathSpecFromCfgAndLang(cfg config.Provider, lang string) *helpers.PathSpec { + mfs := afero.NewMemMapFs() + + configs := testconfig.GetTestConfigs(mfs, cfg) + var conf config.AllProvider + if lang == "" { + conf = configs.GetFirstLanguageConfig() + } else { + conf = configs.GetByLang(lang) + if conf == nil { + panic("no config for lang " + lang) + } + } + fs := hugofs.NewFrom(mfs, conf.BaseConfig()) + ps, err := helpers.NewPathSpec(fs, conf, loggers.NewErrorLogger()) + if err != nil { + panic(err) + } return ps } -func newTestDefaultPathSpec(configKeyValues ...any) *PathSpec { - cfg := newTestCfg() - fs := hugofs.NewMem(cfg) - +func newTestPathSpec(configKeyValues ...any) *helpers.PathSpec { + cfg := config.New() for i := 0; i < len(configKeyValues); i += 2 { cfg.Set(configKeyValues[i].(string), configKeyValues[i+1]) } - return newTestPathSpec(fs, cfg) -} - -func newTestCfg() config.Provider { - v := config.NewWithTestDefaults() - langs.LoadLanguageSettings(v, nil) - langs.LoadLanguageSettings(v, nil) - mod, err := modules.CreateProjectModule(v) - if err != nil { - panic(err) - } - v.Set("allModules", modules.Modules{mod}) - - return v + return newTestPathSpecFromCfgAndLang(cfg, "") } -func newTestContentSpec() *ContentSpec { - v := config.NewWithTestDefaults() - spec, err := NewContentSpec(v, loggers.NewErrorLogger(), afero.NewMemMapFs(), nil) +func newTestContentSpec(cfg config.Provider) *helpers.ContentSpec { + fs := afero.NewMemMapFs() + conf := testconfig.GetTestConfig(fs, cfg) + spec, err := helpers.NewContentSpec(conf, loggers.NewErrorLogger(), fs, nil) if err != nil { panic(err) } diff --git a/helpers/url.go b/helpers/url.go index 7cb998ca2..a4c20c6ad 100644 --- a/helpers/url.go +++ b/helpers/url.go @@ -71,8 +71,9 @@ func SanitizeURLKeepTrailingSlash(in string) string { // URLize is similar to MakePath, but with Unicode handling // Example: -// uri: Vim (text editor) -// urlize: vim-text-editor +// +// uri: Vim (text editor) +// urlize: vim-text-editor func (p *PathSpec) URLize(uri string) string { return p.URLEscape(p.MakePathSanitized(uri)) } @@ -141,16 +142,16 @@ func (p *PathSpec) AbsURL(in string, addLanguage bool) string { func (p *PathSpec) getBaseURLRoot(path string) string { if strings.HasPrefix(path, "/") { // Treat it as relative to the server root. - return p.BaseURLNoPathString + return p.Cfg.BaseURL().WithoutPath } else { // Treat it as relative to the baseURL. - return p.BaseURLString + return p.Cfg.BaseURL().WithPath } } func (p *PathSpec) RelURL(in string, addLanguage bool) string { baseURL := p.getBaseURLRoot(in) - canonifyURLs := p.CanonifyURLs + canonifyURLs := p.Cfg.CanonifyURLs() if (!strings.HasPrefix(in, baseURL) && strings.HasPrefix(in, "http")) || strings.HasPrefix(in, "//") { return in } @@ -217,25 +218,3 @@ func (p *PathSpec) PrependBasePath(rel string, isAbs bool) string { } return rel } - -// URLizeAndPrep applies misc sanitation to the given URL to get it in line -// with the Hugo standard. -func (p *PathSpec) URLizeAndPrep(in string) string { - return p.URLPrep(p.URLize(in)) -} - -// URLPrep applies misc sanitation to the given URL. -func (p *PathSpec) URLPrep(in string) string { - if p.UglyURLs { - return paths.Uglify(SanitizeURL(in)) - } - pretty := paths.PrettifyURL(SanitizeURL(in)) - if path.Ext(pretty) == ".xml" { - return pretty - } - url, err := purell.NormalizeURLString(pretty, purell.FlagAddTrailingSlash) - if err != nil { - return pretty - } - return url -} diff --git a/helpers/url_test.go b/helpers/url_test.go index e248036ae..787cdd6e8 100644 --- a/helpers/url_test.go +++ b/helpers/url_test.go @@ -1,4 +1,4 @@ -// Copyright 2015 The Hugo Authors. All rights reserved. +// Copyright 2023 The Hugo Authors. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,21 +11,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -package helpers +package helpers_test import ( + "fmt" "strings" "testing" qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/hugofs" - "github.com/gohugoio/hugo/langs" + "github.com/gohugoio/hugo/config" + "github.com/gohugoio/hugo/helpers" ) func TestURLize(t *testing.T) { - v := newTestCfg() - l := langs.NewDefaultLanguage(v) - p, _ := NewPathSpec(hugofs.NewMem(v), l, nil) + p := newTestPathSpec() tests := []struct { input string @@ -61,10 +60,6 @@ func TestAbsURL(t *testing.T) { func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, lang string) { c := qt.New(t) - v := newTestCfg() - v.Set("multilingual", multilingual) - v.Set("defaultContentLanguage", "en") - v.Set("defaultContentLanguageInSubdir", defaultInSubDir) tests := []struct { input string @@ -103,24 +98,42 @@ func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, } for _, test := range tests { - v.Set("baseURL", test.baseURL) - v.Set("contentDir", "content") - l := langs.NewLanguage(lang, v) - p, _ := NewPathSpec(hugofs.NewMem(v), l, nil) - - output := p.AbsURL(test.input, addLanguage) - expected := test.expected - if multilingual && addLanguage { - if !defaultInSubDir && lang == "en" { - expected = strings.Replace(expected, "MULTI", "", 1) + c.Run(fmt.Sprintf("%v/%t-%t-%t/%s", test, defaultInSubDir, addLanguage, multilingual, lang), func(c *qt.C) { + v := config.New() + if multilingual { + v.Set("languages", map[string]any{ + "fr": map[string]interface{}{ + "weight": 20, + }, + "en": map[string]interface{}{ + "weight": 10, + }, + }) + } + v.Set("defaultContentLanguage", "en") + v.Set("defaultContentLanguageInSubdir", defaultInSubDir) + v.Set("baseURL", test.baseURL) + + var configLang string + if multilingual { + configLang = lang + } + p := newTestPathSpecFromCfgAndLang(v, configLang) + + output := p.AbsURL(test.input, addLanguage) + expected := test.expected + if multilingual && addLanguage { + if !defaultInSubDir && lang == "en" { + expected = strings.Replace(expected, "MULTI", "", 1) + } else { + expected = strings.Replace(expected, "MULTI", lang+"/", 1) + } } else { - expected = strings.Replace(expected, "MULTI", lang+"/", 1) + expected = strings.Replace(expected, "MULTI", "", 1) } - } else { - expected = strings.Replace(expected, "MULTI", "", 1) - } - c.Assert(output, qt.Equals, expected) + c.Assert(output, qt.Equals, expected) + }) } } @@ -137,9 +150,19 @@ func TestRelURL(t *testing.T) { } func doTestRelURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, lang string) { + t.Helper() c := qt.New(t) - v := newTestCfg() - v.Set("multilingual", multilingual) + v := config.New() + if multilingual { + v.Set("languages", map[string]any{ + "fr": map[string]interface{}{ + "weight": 20, + }, + "en": map[string]interface{}{ + "weight": 10, + }, + }) + } v.Set("defaultContentLanguage", "en") v.Set("defaultContentLanguageInSubdir", defaultInSubDir) @@ -182,25 +205,31 @@ func doTestRelURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, } for i, test := range tests { - v.Set("baseURL", test.baseURL) - v.Set("canonifyURLs", test.canonify) - l := langs.NewLanguage(lang, v) - p, _ := NewPathSpec(hugofs.NewMem(v), l, nil) + c.Run(fmt.Sprintf("%v/%t%t%t/%s", test, defaultInSubDir, addLanguage, multilingual, lang), func(c *qt.C) { - output := p.RelURL(test.input, addLanguage) + v.Set("baseURL", test.baseURL) + v.Set("canonifyURLs", test.canonify) + var configLang string + if multilingual { + configLang = lang + } + p := newTestPathSpecFromCfgAndLang(v, configLang) - expected := test.expected - if multilingual && addLanguage { - if !defaultInSubDir && lang == "en" { - expected = strings.Replace(expected, "MULTI", "", 1) + output := p.RelURL(test.input, addLanguage) + + expected := test.expected + if multilingual && addLanguage { + if !defaultInSubDir && lang == "en" { + expected = strings.Replace(expected, "MULTI", "", 1) + } else { + expected = strings.Replace(expected, "MULTI", "/"+lang, 1) + } } else { - expected = strings.Replace(expected, "MULTI", "/"+lang, 1) + expected = strings.Replace(expected, "MULTI", "", 1) } - } else { - expected = strings.Replace(expected, "MULTI", "", 1) - } - c.Assert(output, qt.Equals, expected, qt.Commentf("[%d] %s", i, test.input)) + c.Assert(output, qt.Equals, expected, qt.Commentf("[%d] %s", i, test.input)) + }) } } @@ -216,8 +245,8 @@ func TestSanitizeURL(t *testing.T) { } for i, test := range tests { - o1 := SanitizeURL(test.input) - o2 := SanitizeURLKeepTrailingSlash(test.input) + o1 := helpers.SanitizeURL(test.input) + o2 := helpers.SanitizeURLKeepTrailingSlash(test.input) expected2 := test.expected @@ -233,28 +262,3 @@ func TestSanitizeURL(t *testing.T) { } } } - -func TestURLPrep(t *testing.T) { - type test struct { - ugly bool - input string - output string - } - - data := []test{ - {false, "/section/name.html", "/section/name/"}, - {true, "/section/name/index.html", "/section/name.html"}, - } - - for i, d := range data { - v := newTestCfg() - v.Set("uglyURLs", d.ugly) - l := langs.NewDefaultLanguage(v) - p, _ := NewPathSpec(hugofs.NewMem(v), l, nil) - - output := p.URLPrep(d.input) - if d.output != output { - t.Errorf("Test #%d failed. Expected %q got %q", i, d.output, output) - } - } -} |