// Copyright 2020 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 publisher
import (
"bytes"
"fmt"
"strings"
"testing"
"github.com/gohugoio/hugo/media"
"github.com/gohugoio/hugo/minifiers"
"github.com/gohugoio/hugo/output"
qt "github.com/frankban/quicktest"
"github.com/spf13/viper"
)
func TestClassCollector(t *testing.T) {
c := qt.New((t))
f := func(tags, classes, ids string) HTMLElements {
var tagss, classess, idss []string
if tags != "" {
tagss = strings.Split(tags, " ")
}
if classes != "" {
classess = strings.Split(classes, " ")
}
if ids != "" {
idss = strings.Split(ids, " ")
}
return HTMLElements{
Tags: tagss,
Classes: classess,
IDs: idss,
}
}
skipMinifyTest := map[string]bool{
"Script tags content should be skipped": true, // https://github.com/tdewolff/minify/issues/396
}
for _, test := range []struct {
name string
html string
expect HTMLElements
}{
{"basic", `
`, f("body", "a b", "")},
{"duplicates", ``, f("div", "mobile:-translate-x-8 opacity-0 sm:-translate-y-8 transform", "")},
{"Vue bind", `
`, f("div", "active", "")},
// Issue #7746
{"Apostrophe inside attribute value", `
my text`, f("a div", "missingclass", "")},
// Issue #7567
{"Script tags content should be skipped", `
`, f("div script", "foo", "")},
{"Style tags content should be skipped", `
`, f("div style", "foo", "")},
{"Pre tags content should be skipped", `
foobar
`, f("div pre", "foo preclass", "")},
{"Textarea tags content should be skipped", `
`, f("div textarea", "foo textareaclass", "")},
{"DOCTYPE should beskipped", ``, f("", "", "")},
{"Comments should be skipped", ``, f("", "", "")},
// Issue #8417
{"Tabs inline", `
d
`, f("div hr", "bar foo", "a")},
{"Tabs on multiple rows", `
d
`, f("div form", "foo", "a b")},
} {
for _, minify := range []bool{false, true} {
c.Run(fmt.Sprintf("%s--minify-%t", test.name, minify), func(c *qt.C) {
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
if minify {
if skipMinifyTest[test.name] {
c.Skip("skip minify test")
}
v := viper.New()
m, _ := minifiers.New(media.DefaultTypes, output.DefaultFormats, v)
m.Minify(media.HTMLType, w, strings.NewReader(test.html))
} else {
fmt.Fprint(w, test.html)
}
got := w.collector.getHTMLElements()
c.Assert(got, qt.DeepEquals, test.expect)
})
}
}
}
func BenchmarkClassCollectorWriter(b *testing.B) {
const benchHTML = `
`
for i := 0; i < b.N; i++ {
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
fmt.Fprint(w, benchHTML)
}
}
const benchHTML = `
title
To force
line breaks
in a text,
use the br
element.
Month |
Savings |
January |
$100 |
February |
$200 |
|
$300 |
`
func BenchmarkElementsCollectorWriter(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
fmt.Fprint(w, benchHTML)
}
}
func BenchmarkElementsCollectorWriterMinified(b *testing.B) {
b.ReportAllocs()
v := viper.New()
m, _ := minifiers.New(media.DefaultTypes, output.DefaultFormats, v)
var buf bytes.Buffer
m.Minify(media.HTMLType, &buf, strings.NewReader(benchHTML))
b.ResetTimer()
for i := 0; i < b.N; i++ {
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
fmt.Fprint(w, buf.String())
}
}
func BenchmarkElementsCollectorWriterWithMinifyStream(b *testing.B) {
b.ReportAllocs()
v := viper.New()
m, _ := minifiers.New(media.DefaultTypes, output.DefaultFormats, v)
b.ResetTimer()
for i := 0; i < b.N; i++ {
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
m.Minify(media.HTMLType, w, strings.NewReader(benchHTML))
}
}
func BenchmarkElementsCollectorWriterWithMinifyString(b *testing.B) {
b.ReportAllocs()
v := viper.New()
m, _ := minifiers.New(media.DefaultTypes, output.DefaultFormats, v)
b.ResetTimer()
for i := 0; i < b.N; i++ {
var buf bytes.Buffer
m.Minify(media.HTMLType, &buf, strings.NewReader(benchHTML))
w := newHTMLElementsCollectorWriter(newHTMLElementsCollector())
fmt.Fprint(w, buf.String())
}
}