diff options
author | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-01-04 18:24:36 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com> | 2023-05-16 18:01:29 +0200 |
commit | 241b21b0fd34d91fccb2ce69874110dceae6f926 (patch) | |
tree | d4e0118eac7e9c42f065815447a70805f8d6ad3e /helpers | |
parent | 6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff) |
Create a struct with all of Hugo's config options
Primary motivation is documentation, but it will also hopefully simplify the code.
Also,
* Lower case the default output format names; this is in line with the custom ones (map keys) and how
it's treated all the places. This avoids doing `stringds.EqualFold` everywhere.
Closes #10896
Closes #10620
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, _ |