diff options
author | Bjørn Erik Pedersen <[email protected]> | 2024-08-13 15:49:56 +0200 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2024-08-29 16:45:21 +0200 |
commit | 37609262dcddac6d3358412b10214111b4d4dc3d (patch) | |
tree | 60f1370ec79454742c7eb727ca1bb9156aecb296 /helpers | |
parent | 2b5c335e933cbd8e4e8569f206add5ec1bccd8e9 (diff) | |
download | hugo-37609262dcddac6d3358412b10214111b4d4dc3d.tar.gz hugo-37609262dcddac6d3358412b10214111b4d4dc3d.zip |
Add Page.Contents with scope support
Note that this also adds a new `.ContentWithoutSummary` method, and to do that we had to unify the different summary types:
Both `auto` and `manual` now returns HTML. Before this commit, `auto` would return plain text. This could be considered to be a slightly breaking change, but for the better: Now you can treat the `.Summary` the same without thinking about where it comes from, and if you want plain text, pipe it into `{{ .Summary | plainify }}`.
Fixes #8680
Fixes #12761
Fixes #12778
Fixes #716
Diffstat (limited to 'helpers')
-rw-r--r-- | helpers/content.go | 74 | ||||
-rw-r--r-- | helpers/content_test.go | 79 |
2 files changed, 0 insertions, 153 deletions
diff --git a/helpers/content.go b/helpers/content.go index 49283d526..9d74a3d31 100644 --- a/helpers/content.go +++ b/helpers/content.go @@ -22,7 +22,6 @@ import ( "html/template" "strings" "unicode" - "unicode/utf8" "github.com/gohugoio/hugo/common/hexec" "github.com/gohugoio/hugo/common/loggers" @@ -165,75 +164,6 @@ func TotalWords(s string) int { return n } -// TruncateWordsByRune truncates words by runes. -func (c *ContentSpec) TruncateWordsByRune(in []string) (string, bool) { - words := make([]string, len(in)) - copy(words, in) - - count := 0 - for index, word := range words { - 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.Cfg.SummaryLength() { - count += runeCount - } else { - for ri := range word { - if count >= c.Cfg.SummaryLength() { - truncatedWords := append(words[:index], word[:ri]) - return strings.Join(truncatedWords, " "), true - } - count++ - } - } - } - - return strings.Join(words, " "), false -} - -// TruncateWordsToWholeSentence takes content and truncates to whole sentence -// limited by max number of words. It also returns whether it is truncated. -func (c *ContentSpec) TruncateWordsToWholeSentence(s string) (string, bool) { - var ( - wordCount = 0 - lastWordIndex = -1 - ) - - for i, r := range s { - if unicode.IsSpace(r) { - wordCount++ - lastWordIndex = i - - if wordCount >= c.Cfg.SummaryLength() { - break - } - - } - } - - if lastWordIndex == -1 { - return s, false - } - - endIndex := -1 - - for j, r := range s[lastWordIndex:] { - if isEndOfSentence(r) { - endIndex = j + lastWordIndex + utf8.RuneLen(r) - break - } - } - - if endIndex == -1 { - return s, false - } - - return strings.TrimSpace(s[:endIndex]), endIndex < len(s) -} - // TrimShortHTML removes the outer tags from HTML input where (a) the opening // tag is present only once with the input, and (b) the opening and closing // tags wrap the input after white space removal. @@ -256,7 +186,3 @@ func (c *ContentSpec) TrimShortHTML(input []byte, markup string) []byte { } return input } - -func isEndOfSentence(r rune) bool { - return r == '.' || r == '?' || r == '!' || r == '"' || r == '\n' -} diff --git a/helpers/content_test.go b/helpers/content_test.go index 22d468191..dd7c5a4c5 100644 --- a/helpers/content_test.go +++ b/helpers/content_test.go @@ -20,7 +20,6 @@ import ( "testing" qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/config" "github.com/gohugoio/hugo/helpers" ) @@ -66,84 +65,6 @@ func TestBytesToHTML(t *testing.T) { 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(nil) - b.ResetTimer() - for i := 0; i < b.N; i++ { - c.TruncateWordsToWholeSentence(benchmarkTruncateString) - } -} - -func TestTruncateWordsToWholeSentence(t *testing.T) { - type test struct { - input, expected string - max int - truncated bool - } - data := []test{ - {"a b c", "a b c", 12, false}, - {"a b c", "a b c", 3, false}, - {"a", "a", 1, false}, - {"This is a sentence.", "This is a sentence.", 5, false}, - {"This is also a sentence!", "This is also a sentence!", 1, false}, - {"To be. Or not to be. That's the question.", "To be.", 1, true}, - {" \nThis is not a sentence\nAnd this is another", "This is not a sentence", 4, true}, - {"", "", 10, false}, - {"This... is a more difficult test?", "This... is a more difficult test?", 1, false}, - } - for i, d := range data { - 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) - } - - if d.truncated != truncated { - t.Errorf("Test %d failed. Expected truncated=%t got %t", i, d.truncated, truncated) - } - } -} - -func TestTruncateWordsByRune(t *testing.T) { - type test struct { - input, expected string - max int - truncated bool - } - data := []test{ - {"", "", 1, false}, - {"a b c", "a b c", 12, false}, - {"a b c", "a b c", 3, false}, - {"a", "a", 1, false}, - {"Hello 中国", "", 0, true}, - {"这是中文,全中文。", "这是中文,", 5, true}, - {"Hello 中国", "Hello 中", 2, true}, - {"Hello 中国", "Hello 中国", 3, false}, - {"Hello中国 Good 好的", "Hello中国 Good 好", 9, true}, - {"This is a sentence.", "This is", 2, true}, - {"This is also a sentence!", "This", 1, true}, - {"To be. Or not to be. That's the question.", "To be. Or not", 4, true}, - {" \nThis is not a sentence\n ", "This is not", 3, true}, - } - for i, d := range data { - 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) - } - - if d.truncated != truncated { - t.Errorf("Test %d failed. Expected truncated=%t got %t", i, d.truncated, truncated) - } - } -} - func TestExtractTOCNormalContent(t *testing.T) { content := []byte("<nav>\n<ul>\nTOC<li><a href=\"#") |