shithub: hugo

Download patch

ref: f37e77f2d338cf876cfa637a662acd76f0f2009b
parent: 27af5a339a4d3c5712b5ed946a636a8c21916039
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Tue Apr 21 08:57:45 EDT 2020

Fix class collector when running with --minify

Also add a related stresstest.

Fixes #7161

--- a/hugolib/site_test.go
+++ b/hugolib/site_test.go
@@ -14,11 +14,16 @@
 package hugolib
 
 import (
+	"encoding/json"
 	"fmt"
+	"io/ioutil"
+	"os"
 	"path/filepath"
 	"strings"
 	"testing"
 
+	"github.com/gohugoio/hugo/publisher"
+
 	"github.com/spf13/viper"
 
 	"github.com/markbates/inflect"
@@ -982,15 +987,24 @@
 }
 
 func TestClassCollector(t *testing.T) {
-	b := newTestSitesBuilder(t)
-	b.WithConfigFile("toml", `
 
+	for _, minify := range []bool{false, true} {
+		t.Run(fmt.Sprintf("minify-%t", minify), func(t *testing.T) {
+			statsFilename := "hugo_stats.json"
+			defer os.Remove(statsFilename)
+
+			b := newTestSitesBuilder(t)
+			b.WithConfigFile("toml", fmt.Sprintf(`
+			
+			
+minify = %t
+
 [build]
   writeStats = true
 
-`)
+`, minify))
 
-	b.WithTemplates("index.html", `
+			b.WithTemplates("index.html", `
 	
 <div id="el1" class="a b c">Foo</div>
 
@@ -997,17 +1011,25 @@
 Some text.
 
 <div class="c d e" id="el2">Foo</div>
+
+<span class=z>FOO</span>
+
+ <a class="text-base hover:text-gradient inline-block px-3 pb-1 rounded lowercase" href="{{ .RelPermalink }}">{{ .Title }}</a>
+
+
 `)
 
-	b.WithContent("p1.md", "")
+			b.WithContent("p1.md", "")
 
-	b.Build(BuildCfg{})
+			b.Build(BuildCfg{})
 
-	b.AssertFileContent("hugo_stats.json", `
-{
+			b.AssertFileContent("hugo_stats.json", `
+ {
           "htmlElements": {
             "tags": [
-              "div"
+              "a",
+              "div",
+              "span"
             ],
             "classes": [
               "a",
@@ -1014,7 +1036,15 @@
               "b",
               "c",
               "d",
-              "e"
+              "e",
+              "hover:text-gradient",
+              "inline-block",
+              "lowercase",
+              "pb-1",
+              "px-3",
+              "rounded",
+              "text-base",
+              "z"
             ],
             "ids": [
               "el1",
@@ -1023,4 +1053,78 @@
           }
         }
 `)
+
+		})
+
+	}
+}
+
+func TestClassCollectorStress(t *testing.T) {
+	statsFilename := "hugo_stats.json"
+	defer os.Remove(statsFilename)
+
+	b := newTestSitesBuilder(t)
+	b.WithConfigFile("toml", `
+	
+disableKinds = ["home", "section", "taxonomy", "taxonomyTerm" ]
+
+[languages]
+[languages.en]
+[languages.nb]
+[languages.no]
+[languages.sv]
+
+
+[build]
+  writeStats = true
+
+`)
+
+	b.WithTemplates("_default/single.html", `
+<div class="c d e" id="el2">Foo</div>
+
+Some text.
+
+{{ $n := index (shuffle (seq 1 20)) 0 }}
+
+{{ "<span class=_a>Foo</span>" | strings.Repeat $n | safeHTML }}
+
+<div class="{{ .Title }}">
+ABC.
+</div>
+
+<div class="f"></div>
+
+{{ $n := index (shuffle (seq 1 5)) 0 }}
+
+{{ "<hr class=p-3>" | safeHTML }}
+
+`)
+
+	for _, lang := range []string{"en", "nb", "no", "sv"} {
+
+		for i := 100; i <= 999; i++ {
+			b.WithContent(fmt.Sprintf("p%d.%s.md", i, lang), fmt.Sprintf("---\ntitle: p%s%d\n---", lang, i))
+		}
+	}
+
+	b.Build(BuildCfg{})
+
+	contentMem := b.FileContent(statsFilename)
+	cb, err := ioutil.ReadFile(statsFilename)
+	b.Assert(err, qt.IsNil)
+	contentFile := string(cb)
+
+	for _, content := range []string{contentMem, contentFile} {
+
+		stats := &publisher.PublishStats{}
+		b.Assert(json.Unmarshal([]byte(content), stats), qt.IsNil)
+
+		els := stats.HTMLElements
+
+		b.Assert(els.Classes, qt.HasLen, 3606) // (4 * 900) + 4 +2
+		b.Assert(els.Tags, qt.HasLen, 8)
+		b.Assert(els.IDs, qt.HasLen, 1)
+	}
+
 }
--- a/publisher/htmlElementsCollector.go
+++ b/publisher/htmlElementsCollector.go
@@ -87,11 +87,6 @@
 		if w.isCollecting {
 			for ; i < len(p); i++ {
 				b := p[i]
-				if !w.inQuote && b == '/' {
-					// End element, we don't care about those.
-					w.endCollecting(true)
-					break
-				}
 				w.toggleIfQuote(b)
 				if !w.inQuote && b == '>' {
 					w.endCollecting(false)
--- a/publisher/htmlElementsCollector_test.go
+++ b/publisher/htmlElementsCollector_test.go
@@ -51,6 +51,8 @@
 		{"duplicates", `<div class="b a b"></div>`, f("div", "a b", "")},
 		{"single quote", `<body class='b a'></body>`, f("body", "a b", "")},
 		{"no quote", `<body class=b id=myelement></body>`, f("body", "b", "myelement")},
+		// https://github.com/gohugoio/hugo/issues/7161
+		{"minified a href", `<a class="b a" href=/></a>`, f("a", "a b", "")},
 
 		{"AlpineJS bind 1", `<body>
 			<div x-bind:class="{