mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Fix class collector when running with --minify
Also add a related stresstest. Fixes #7161
This commit is contained in:
parent
27af5a339a
commit
f37e77f2d3
3 changed files with 116 additions and 15 deletions
|
@ -14,11 +14,16 @@
|
||||||
package hugolib
|
package hugolib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gohugoio/hugo/publisher"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
|
|
||||||
"github.com/markbates/inflect"
|
"github.com/markbates/inflect"
|
||||||
|
@ -982,39 +987,64 @@ func TestRefIssues(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClassCollector(t *testing.T) {
|
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]
|
[build]
|
||||||
writeStats = true
|
writeStats = true
|
||||||
|
|
||||||
`)
|
`, minify))
|
||||||
|
|
||||||
b.WithTemplates("index.html", `
|
b.WithTemplates("index.html", `
|
||||||
|
|
||||||
<div id="el1" class="a b c">Foo</div>
|
<div id="el1" class="a b c">Foo</div>
|
||||||
|
|
||||||
Some text.
|
Some text.
|
||||||
|
|
||||||
<div class="c d e" id="el2">Foo</div>
|
<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": {
|
"htmlElements": {
|
||||||
"tags": [
|
"tags": [
|
||||||
"div"
|
"a",
|
||||||
|
"div",
|
||||||
|
"span"
|
||||||
],
|
],
|
||||||
"classes": [
|
"classes": [
|
||||||
"a",
|
"a",
|
||||||
"b",
|
"b",
|
||||||
"c",
|
"c",
|
||||||
"d",
|
"d",
|
||||||
"e"
|
"e",
|
||||||
|
"hover:text-gradient",
|
||||||
|
"inline-block",
|
||||||
|
"lowercase",
|
||||||
|
"pb-1",
|
||||||
|
"px-3",
|
||||||
|
"rounded",
|
||||||
|
"text-base",
|
||||||
|
"z"
|
||||||
],
|
],
|
||||||
"ids": [
|
"ids": [
|
||||||
"el1",
|
"el1",
|
||||||
|
@ -1023,4 +1053,78 @@ Some text.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,11 +87,6 @@ func (w *cssClassCollectorWriter) Write(p []byte) (n int, err error) {
|
||||||
if w.isCollecting {
|
if w.isCollecting {
|
||||||
for ; i < len(p); i++ {
|
for ; i < len(p); i++ {
|
||||||
b := p[i]
|
b := p[i]
|
||||||
if !w.inQuote && b == '/' {
|
|
||||||
// End element, we don't care about those.
|
|
||||||
w.endCollecting(true)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
w.toggleIfQuote(b)
|
w.toggleIfQuote(b)
|
||||||
if !w.inQuote && b == '>' {
|
if !w.inQuote && b == '>' {
|
||||||
w.endCollecting(false)
|
w.endCollecting(false)
|
||||||
|
|
|
@ -51,6 +51,8 @@ func TestClassCollector(t *testing.T) {
|
||||||
{"duplicates", `<div class="b a b"></div>`, f("div", "a b", "")},
|
{"duplicates", `<div class="b a b"></div>`, f("div", "a b", "")},
|
||||||
{"single quote", `<body class='b a'></body>`, f("body", "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")},
|
{"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>
|
{"AlpineJS bind 1", `<body>
|
||||||
<div x-bind:class="{
|
<div x-bind:class="{
|
||||||
|
|
Loading…
Reference in a new issue