Beispiel #1
0
func TestJS(t *testing.T) {
	jsTests := []struct {
		js       string
		expected string
	}{
		{"/*comment*/", ""},
		{"// comment\na", "a"},
		{"/*! bang  comment */", "/*!bang comment*/"},
		{"function x(){}", "function x(){}"},
		{"function x(a, b){}", "function x(a,b){}"},
		{"a  b", "a b"},
		{"a\n\nb", "a\nb"},
		{"a// comment\nb", "a\nb"},
		{"''\na", "''\na"},
		{"''\n''", "''''"},
		{"]\n0", "]\n0"},
		{"a\n{", "a\n{"},
		{";\na", ";a"},
		{",\na", ",a"},
		{"}\na", "}\na"},
		{"+\na", "+\na"},
		{"+\n(", "+\n("},
		{"+\n\"\"", "+\"\""},
		{"a + ++b", "a+ ++b"},                                          // JSMin caution
		{"var a=/\\s?auto?\\s?/i\nvar", "var a=/\\s?auto?\\s?/i\nvar"}, // #14
		{"`\n", "`"}, // go fuzz
	}

	m := minify.New()
	for _, tt := range jsTests {
		r := bytes.NewBufferString(tt.js)
		w := &bytes.Buffer{}
		test.Minify(t, tt.js, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #2
0
func TestHTMLKeepWhitespace(t *testing.T) {
	htmlTests := []struct {
		html     string
		expected string
	}{
		{`cats  and 	dogs `, `cats and dogs`},
		{` <div> <i> test </i> <b> test </b> </div> `, `<div> <i> test </i> <b> test </b> </div>`},
		{`<strong>x </strong>y`, `<strong>x </strong>y`},
		{`<strong>x </strong> y`, `<strong>x </strong> y`},
		{"<strong>x </strong>\ny", "<strong>x </strong>\ny"},
		{`<p>x </p>y`, `<p>x </p>y`},
		{`x <p>y</p>`, `x <p>y`},
		{` <!doctype html> <!--comment--> <html> <body><p></p></body></html> `, `<!doctype html><p>`}, // spaces before html and at the start of html are dropped
		{`<p>x<br> y`, `<p>x<br> y`},
		{`<p>x </b> <b> y`, `<p>x </b> <b> y`},
		{`a <code>code</code> b`, `a <code>code</code> b`},
		{`a <code></code> b`, `a <code></code> b`},
		{`a <script>script</script> b`, `a <script>script</script> b`},
		{"text\n<!--comment-->\ntext", "text\ntext"},
		{"text\n<!--comment-->text<!--comment--> text", "text\ntext text"},
		{"abc\n</body>\ndef", "abc\ndef"},
		{"<x>\n<!--y-->\n</x>", "<x>\n</x>"},
		{"<style>lala{color:red}</style>", "<style>lala{color:red}</style>"},
	}

	m := minify.New()
	htmlMinifier := &Minifier{KeepWhitespace: true}
	for _, tt := range htmlTests {
		r := bytes.NewBufferString(tt.html)
		w := &bytes.Buffer{}
		test.Minify(t, tt.html, htmlMinifier.Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #3
0
func TestHTMLURL(t *testing.T) {
	htmlTests := []struct {
		url      string
		html     string
		expected string
	}{
		{`http://example.com/`, `<a href=http://example.com/>link</a>`, `<a href=//example.com/>link</a>`},
		{`https://example.com/`, `<a href=http://example.com/>link</a>`, `<a href=http://example.com/>link</a>`},
		{`http://example.com/`, `<a href=https://example.com/>link</a>`, `<a href=https://example.com/>link</a>`},
		{`https://example.com/`, `<a href=https://example.com/>link</a>`, `<a href=//example.com/>link</a>`},
		{`http://example.com/`, `<a href="   http://example.com  ">x</a>`, `<a href=//example.com>x</a>`},
		{`http://example.com/`, `<link rel="stylesheet" type="text/css" href="http://example.com">`, `<link rel=stylesheet href=//example.com>`},
		{`http://example.com/`, `<!doctype html> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> <head profile="http://dublincore.org/documents/dcq-html/"> <!-- Barlesque 2.75.0 --> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />`,
			`<!doctype html><html xmlns=//www.w3.org/1999/xhtml xml:lang=en><head profile=//dublincore.org/documents/dcq-html/><meta charset=utf-8>`},
		{`http://example.com/`, `<svg xmlns="http://www.w3.org/2000/svg"></svg>`, `<svg xmlns=//www.w3.org/2000/svg></svg>`},
		{`https://example.com/`, `<svg xmlns="http://www.w3.org/2000/svg"></svg>`, `<svg xmlns=http://www.w3.org/2000/svg></svg>`},
		{`http://example.com/`, `<svg xmlns="https://www.w3.org/2000/svg"></svg>`, `<svg xmlns=https://www.w3.org/2000/svg></svg>`},
		{`https://example.com/`, `<svg xmlns="https://www.w3.org/2000/svg"></svg>`, `<svg xmlns=//www.w3.org/2000/svg></svg>`},
	}

	m := minify.New()
	m.AddFunc("text/html", Minify)
	for _, tt := range htmlTests {
		r := bytes.NewBufferString(tt.html)
		w := &bytes.Buffer{}
		m.URL, _ = url.Parse(tt.url)
		test.Minify(t, tt.html, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #4
0
func TestDataURI(t *testing.T) {
	dataURITests := []struct {
		dataURI  string
		expected string
	}{
		{"data:,text", "data:,text"},
		{"data:text/plain;charset=us-ascii,text", "data:,text"},
		{"data:TEXT/PLAIN;CHARSET=US-ASCII,text", "data:,text"},
		{"data:text/plain;charset=us-asciiz,text", "data:;charset=us-asciiz,text"},
		{"data:;base64,dGV4dA==", "data:,text"},
		{"data:text/svg+xml;base64,PT09PT09", "data:text/svg+xml;base64,PT09PT09"},
		{"data:text/xml;version=2.0,content", "data:text/xml;version=2.0,content"},
		{"data:text/xml; version = 2.0,content", "data:text/xml;version=2.0,content"},
		{"data:,=====", "data:,%3D%3D%3D%3D%3D"},
		{"data:,======", "data:;base64,PT09PT09"},
		{"data:text/x,<?x?>", "data:text/x,%3C%3Fx%3F%3E"},
	}
	m := New()
	m.AddFunc("text/x", func(_ *M, w io.Writer, r io.Reader, _ map[string]string) error {
		b, _ := ioutil.ReadAll(r)
		test.String(t, string(b), "<?x?>")
		w.Write(b)
		return nil
	})
	for _, tt := range dataURITests {
		test.Minify(t, tt.dataURI, nil, string(DataURI(m, []byte(tt.dataURI))), tt.expected)
	}
}
Beispiel #5
0
func TestContentType(t *testing.T) {
	contentTypeTests := []struct {
		contentType string
		expected    string
	}{
		{"text/html", "text/html"},
		{"text/html; charset=UTF-8", "text/html;charset=utf-8"},
		{"text/html; charset=UTF-8 ; param = \" ; \"", "text/html;charset=utf-8;param=\" ; \""},
		{"text/html, text/css", "text/html,text/css"},
	}
	for _, tt := range contentTypeTests {
		test.Minify(t, tt.contentType, nil, string(ContentType([]byte(tt.contentType))), tt.expected)
	}
}
Beispiel #6
0
func TestSVGDecimals(t *testing.T) {
	var svgTests = []struct {
		svg      string
		expected string
	}{
		{`<svg x="1.234" y="0.001" width="1.001"><path/></svg>`, `<svg x="1.2" width="1"><path/></svg>`},
	}

	m := minify.New()
	o := &Minifier{Decimals: 1}
	for _, tt := range svgTests {
		r := bytes.NewBufferString(tt.svg)
		w := &bytes.Buffer{}
		test.Minify(t, tt.svg, o.Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #7
0
func TestSpecialTagClosing(t *testing.T) {
	m := minify.New()
	m.AddFunc("text/html", Minify)
	m.AddFunc("text/css", func(_ *minify.M, w io.Writer, r io.Reader, _ map[string]string) error {
		b, err := ioutil.ReadAll(r)
		test.Error(t, err, nil)
		test.String(t, string(b), "</script>")
		_, err = w.Write(b)
		return err
	})

	html := `<style></script></style>`
	r := bytes.NewBufferString(html)
	w := &bytes.Buffer{}
	test.Minify(t, html, Minify(m, w, r, nil), w.String(), html)
}
Beispiel #8
0
func TestJSON(t *testing.T) {
	jsonTests := []struct {
		json     string
		expected string
	}{
		{"{ \"a\": [1, 2] }", "{\"a\":[1,2]}"},
		{"[{ \"a\": [{\"x\": null}, true] }]", "[{\"a\":[{\"x\":null},true]}]"},
		{"{ \"a\": 1, \"b\": 2 }", "{\"a\":1,\"b\":2}"},
	}

	m := minify.New()
	for _, tt := range jsonTests {
		r := bytes.NewBufferString(tt.json)
		w := &bytes.Buffer{}
		test.Minify(t, tt.json, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #9
0
func TestSVGStyle(t *testing.T) {
	svgTests := []struct {
		svg      string
		expected string
	}{
		{`<style> a > b {} </style>`, `<style>a>b{}</style>`},
		{`<style> <![CDATA[ @media x < y {} ]]> </style>`, `<style>@media x &lt; y{}</style>`},
		{`<style> <![CDATA[ * { content: '<<<<<'; } ]]> </style>`, `<style><![CDATA[*{content:'<<<<<'}]]></style>`},
		{`<style/><![CDATA[ * { content: '<<<<<'; ]]>`, `<style/><![CDATA[ * { content: '<<<<<'; ]]>`},
		{`<path style="fill: black; stroke: #ff0000;"/>`, `<path style="fill:#000;stroke:red"/>`},
	}

	m := minify.New()
	m.AddFunc("text/css", css.Minify)
	for _, tt := range svgTests {
		r := bytes.NewBufferString(tt.svg)
		w := &bytes.Buffer{}
		test.Minify(t, tt.svg, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #10
0
func TestCSS(t *testing.T) {
	cssTests := []struct {
		css      string
		expected string
	}{
		{"/*comment*/", ""},
		{"/*! bang  comment */", "/*!bang comment*/"},
		{"i{}/*! bang  comment */", "i{}/*!bang comment*/"},
		{"i { key: value; key2: value; }", "i{key:value;key2:value}"},
		{".cla .ss > #id { x:y; }", ".cla .ss>#id{x:y}"},
		{".cla[id ^= L] { x:y; }", ".cla[id^=L]{x:y}"},
		{"area:focus { outline : 0;}", "area:focus{outline:0}"},
		{"@import 'file';", "@import 'file'"},
		{"@font-face { x:y; }", "@font-face{x:y}"},

		{"input[type=\"radio\"]{x:y}", "input[type=radio]{x:y}"},
		{"DIV{margin:1em}", "div{margin:1em}"},
		{".CLASS{margin:1em}", ".CLASS{margin:1em}"},
		{"@MEDIA all{}", "@media all{}"},
		{"@media only screen and (max-width : 800px){}", "@media only screen and (max-width:800px){}"},
		{"@media (-webkit-min-device-pixel-ratio:1.5),(min-resolution:1.5dppx){}", "@media(-webkit-min-device-pixel-ratio:1.5),(min-resolution:1.5dppx){}"},
		{"[class^=icon-] i[class^=icon-],i[class*=\" icon-\"]{x:y}", "[class^=icon-] i[class^=icon-],i[class*=\" icon-\"]{x:y}"},
		{"html{line-height:1;}html{line-height:1;}", "html{line-height:1}html{line-height:1}"},
		{".clearfix { *zoom: 1; }", ".clearfix{*zoom:1}"},
		{"a { b: 1", "a{b:1}"},

		// coverage
		{"a, b + c { x:y; }", "a,b+c{x:y}"},

		// go-fuzz
		{"input[type=\"\x00\"] {  a: b\n}.a{}", "input[type=\"\x00\"]{a:b}.a{}"},
		{"a{a:)'''", "a{a:)'''}"},
	}

	m := minify.New()
	for _, tt := range cssTests {
		r := bytes.NewBufferString(tt.css)
		w := &bytes.Buffer{}
		test.Minify(t, tt.css, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #11
0
func TestWildcard(t *testing.T) {
	mimetypeTests := []struct {
		mimetype string
		expected string
	}{
		{"type/sub", "type/sub"},
		{"type/*", "type/*"},
		{"*/*", "*/*"},
		{"type/sub2", "type/*"},
		{"type2/sub", "*/*"},
		{"dummy/charset;charset=UTF-8", "UTF-8"},
		{"dummy/charset; charset = UTF-8 ", "UTF-8"},
		{"dummy/params;type=type;sub=two2", "type/*"},
	}

	for _, tt := range mimetypeTests {
		r := bytes.NewBufferString("")
		w := &bytes.Buffer{}
		test.Minify(t, tt.mimetype, m.Minify(tt.mimetype, w, r), w.String(), tt.expected)
	}
}
Beispiel #12
0
func TestXML(t *testing.T) {
	xmlTests := []struct {
		xml      string
		expected string
	}{
		{"<!-- comment -->", ""},
		{"<A>x</A>", "<A>x</A>"},
		{"<a><b>x</b></a>", "<a><b>x</b></a>"},
		{"<a><b>x\ny</b></a>", "<a><b>x\ny</b></a>"},
		{"<a> <![CDATA[ a ]]> </a>", "<a>a</a>"},
		{"<a >a</a >", "<a>a</a>"},
		{"<?xml  version=\"1.0\" ?>", "<?xml version=\"1.0\"?>"},
		{"<x></x>", "<x/>"},
		{"<x> </x>", "<x/>"},
		{"<x a=\"b\"></x>", "<x a=\"b\"/>"},
		{"<x a=\"\"></x>", "<x a=\"\"/>"},
		{"<x a=a></x>", "<x a=a/>"},
		{"<x a=\" a \n\r\t b \"/>", "<x a=\" a     b \"/>"},
		{"<x a=\"&apos;b&quot;\"></x>", "<x a=\"'b&#34;\"/>"},
		{"<x a=\"&quot;&quot;'\"></x>", "<x a='\"\"&#39;'/>"},
		{"<!DOCTYPE foo SYSTEM \"Foo.dtd\">", "<!DOCTYPE foo SYSTEM \"Foo.dtd\">"},
		{"text <!--comment--> text", "text text"},
		{"text\n<!--comment-->\ntext", "text\ntext"},
		{"<!doctype html>", "<!doctype html=>"}, // bad formatted, doctype must be uppercase and html must have attribute value
		{"<x>\n<!--y-->\n</x>", "<x></x>"},
		{"<style>lala{color:red}</style>", "<style>lala{color:red}</style>"},
		{`cats  and 	dogs `, `cats and dogs`},

		{`</0`, `</0`}, // go fuzz
	}

	m := minify.New()
	for _, tt := range xmlTests {
		r := bytes.NewBufferString(tt.xml)
		w := &bytes.Buffer{}
		test.Minify(t, tt.xml, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #13
0
func TestNumberTruncate(t *testing.T) {
	numberTests := []struct {
		number   string
		truncate int
		expected string
	}{
		{"0.1", 1, ".1"},
		{"0.0001", 1, "1e-4"},
		{"0.111", 1, ".1"},
		{"0.111", 0, "0"},
		{"0.075", 1, ".1"},
		{"0.025", 1, "0"},
		{"9.99", 1, "10"},
		{"8.88", 1, "8.9"},
		{"8.88", 0, "9"},
		{"8.00", 0, "8"},
		{".88", 0, "1"},
		{"1.234", 1, "1.2"},
	}
	for _, tt := range numberTests {
		test.Minify(t, tt.number, nil, string(Number([]byte(tt.number), tt.truncate)), tt.expected, "truncate to", tt.truncate)
	}
}
Beispiel #14
0
func TestPathData(t *testing.T) {
	var pathDataTests = []struct {
		pathData string
		expected string
	}{
		{"M10 10 20 10", "M10 10H20"},
		{"M10 10 10 20", "M10 10V20"},
		{"M50 50 100 100", "M50 50l50 50"},
		{"m50 50 40 40m50 50", "m50 50 40 40m50 50"},
		{"M10 10zM15 15", "M10 10zm5 5"},
		{"M50 50H55V55", "M50 50h5v5"},
		{"M10 10L11 10 11 11", "M10 10h1v1"},
		{"M10 10l1 0 0 1", "M10 10h1v1"},
		{"M10 10L11 11 0 0", "M10 10l1 1L0 0"},
		{"M246.614 51.028L246.614-5.665 189.922-5.665", "M246.614 51.028V-5.665H189.922"},
		{"M100,200 C100,100 250,100 250,200 S400,300 400,200", "M1e2 2e2c0-1e2 150-1e2 150 0s150 1e2 150 0"},
		{"M200,300 Q400,50 600,300 T1000,300", "M2e2 3e2q2e2-250 4e2.0t4e2.0"},
		{"M300,200 h-150 a150,150 0 1,0 150,-150 z", "M3e2 2e2H150A150 150 0 1 0 3e2 50z"},
		{"x5 5L10 10", "L10 10"},

		{"M.0.1", "M0 .1"},
		{"M200.0.1", "M2e2.1"},

		// fuzz
		{"", ""},
		{"ML", ""},
		{".8.00c0", ""},
		{".1.04h0e6.0e6.0e0.0", "h0 0 0 0"},
		{"M.1.0.0.2Z", "M.1.0.0.2z"},
		{"A.0.0.0.0.3.2e3.7.0.0.0.0.0.1.3.0.0.0.0.2.3.2.0.0.0.0.20.2e-10.0.0.0.0.0.0.0.0", "A0 0 0 0 .3 2e2.7.0.0.0.0.0.1.3.0.0.0.0.2.3.2.0.0.0.0.2 2e-11.0.0.0.0.0.0.0.0"},
	}

	p := NewPathData(&Minifier{Decimals: -1})
	for _, tt := range pathDataTests {
		test.Minify(t, tt.pathData, nil, string(p.ShortenPathData([]byte(tt.pathData))), tt.expected)
	}
}
Beispiel #15
0
func TestXMLKeepWhitespace(t *testing.T) {
	xmlTests := []struct {
		xml      string
		expected string
	}{
		{`cats  and 	dogs `, `cats and dogs`},
		{` <div> <i> test </i> <b> test </b> </div> `, `<div> <i> test </i> <b> test </b> </div>`},
		{"text\n<!--comment-->\ntext", "text\ntext"},
		{"text\n<!--comment-->text<!--comment--> text", "text\ntext text"},
		{"<x>\n<!--y-->\n</x>", "<x>\n</x>"},
		{"<style>lala{color:red}</style>", "<style>lala{color:red}</style>"},
		{"<x> <?xml?> </x>", "<x><?xml?> </x>"},
		{"<x> <![CDATA[ x ]]> </x>", "<x> x </x>"},
		{"<x> <![CDATA[ <<<<< ]]> </x>", "<x><![CDATA[ <<<<< ]]></x>"},
	}

	m := minify.New()
	xmlMinifier := &Minifier{KeepWhitespace: true}
	for _, tt := range xmlTests {
		r := bytes.NewBufferString(tt.xml)
		w := &bytes.Buffer{}
		test.Minify(t, tt.xml, xmlMinifier.Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #16
0
func TestSVG(t *testing.T) {
	svgTests := []struct {
		svg      string
		expected string
	}{
		{`<!-- comment -->`, ``},
		{`<!DOCTYPE svg SYSTEM "foo.dtd">`, ``},
		{`<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "foo.dtd" [ <!ENTITY x "bar"> ]>`, `<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "foo.dtd" [ <!ENTITY x "bar"> ]>`},
		{`<!DOCTYPE svg SYSTEM "foo.dtd">`, ``},
		{`<?xml version="1.0" ?>`, ``},
		{`<style> <![CDATA[ x ]]> </style>`, `<style>x</style>`},
		{`<style> <![CDATA[ <<<< ]]> </style>`, `<style>&lt;&lt;&lt;&lt;</style>`},
		{`<style> <![CDATA[ <<<<< ]]> </style>`, `<style><![CDATA[ <<<<< ]]></style>`},
		{`<style/><![CDATA[ <<<<< ]]>`, `<style/><![CDATA[ <<<<< ]]>`},
		{`<svg version="1.0"></svg>`, ``},
		{`<svg version="1.1" x="0" y="0px" width="100%" height="100%"><path/></svg>`, `<svg><path/></svg>`},
		{`<path x="a"> </path>`, `<path x="a"/>`},
		{`<path x=" a "/>`, `<path x="a"/>`},
		{"<path x=\" a \n b \"/>", `<path x="a b"/>`},
		{`<path x="5.0px" y="0%"/>`, `<path x="5" y="0"/>`},
		{`<svg viewBox="5.0px 5px 240IN px"><path/></svg>`, `<svg viewBox="5 5 240in px"><path/></svg>`},
		{`<svg viewBox="5.0!5px"><path/></svg>`, `<svg viewBox="5!5px"><path/></svg>`},
		{`<path d="M 100 100 L 300 100 L 200 100 z"/>`, `<path d="M1e2 1e2H3e2 2e2z"/>`},
		{`<path d="M100 -100M200 300z"/>`, `<path d="M1e2-1e2M2e2 3e2z"/>`},
		{`<path d="M0.5 0.6 M -100 0.5z"/>`, `<path d="M.5.6M-1e2.5z"/>`},
		{`<path d="M01.0 0.6 z"/>`, `<path d="M1 .6z"/>`},
		{`<path d="M20 20l-10-10z"/>`, `<path d="M20 20 10 10z"/>`},
		{`<?xml version="1.0" encoding="utf-8"?>`, ``},
		{`<svg viewbox="0 0 16 16"><path/></svg>`, `<svg viewbox="0 0 16 16"><path/></svg>`},
		{`<g></g>`, ``},
		{`<g><path/></g>`, `<path/>`},
		{`<g id="a"><g><path/></g></g>`, `<g id="a"><path/></g>`},
		{`<path fill="#ffffff"/>`, `<path fill="#fff"/>`},
		{`<path fill="#fff"/>`, `<path fill="#fff"/>`},
		{`<path fill="white"/>`, `<path fill="#fff"/>`},
		{`<path fill="#ff0000"/>`, `<path fill="red"/>`},
		{`<line x1="5" y1="10" x2="20" y2="40"/>`, `<path d="M5 10 20 40z"/>`},
		{`<rect x="5" y="10" width="20" height="40"/>`, `<path d="M5 10h20v40H5z"/>`},
		{`<rect x="-5.669" y="147.402" fill="#843733" width="252.279" height="14.177"/>`, `<path fill="#843733" d="M-5.669 147.402h252.279v14.177H-5.669z"/>`},
		{`<rect x="5" y="10" rx="2" ry="3"/>`, `<rect x="5" y="10" rx="2" ry="3"/>`},
		{`<rect x="5" y="10" height="40"/>`, ``},
		{`<rect x="5" y="10" width="30" height="0"/>`, ``},
		{`<polygon points="1,2 3,4"/>`, `<path d="M1 2 3 4z"/>`},
		{`<polyline points="1,2 3,4"/>`, `<path d="M1 2 3 4"/>`},
		{`<svg contentStyleType="text/json ; charset=iso-8859-1"><style>{a : true}</style></svg>`, `<svg contentStyleType="text/json;charset=iso-8859-1"><style>{a : true}</style></svg>`},
		{`<metadata><dc:title /></metadata>`, ``},

		// from SVGO
		{`<!DOCTYPE bla><?xml?><!-- comment --><metadata/>`, ``},

		{`<polygon fill="none" stroke="#000" points="-0.1,"/>`, `<polygon fill="none" stroke="#000" points="-0.1,"/>`}, // #45

		// go fuzz
		{`<0 d=09e9.6e-9e0`, `<0 d=""`},
		{`<line`, `<line`},
	}

	m := minify.New()
	for _, tt := range svgTests {
		r := bytes.NewBufferString(tt.svg)
		w := &bytes.Buffer{}
		test.Minify(t, tt.svg, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #17
0
func TestHTML(t *testing.T) {
	htmlTests := []struct {
		html     string
		expected string
	}{
		{`html`, `html`},
		{`<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML+RDFa 1.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml-rdfa-1.dtd">`, `<!doctype html>`},
		{`<!-- comment -->`, ``},
		{`<!--[if IE 6]>html<![endif]-->`, `<!--[if IE 6]>html<![endif]-->`},
		{`<!--[if IE 6]><!--html--><![endif]-->`, `<!--[if IE 6]><!--html--><![endif]-->`},
		{`<!--[if IE 6]><style><!--\ncss\n--></style><![endif]-->`, `<!--[if IE 6]><style><!--\ncss\n--></style><![endif]-->`},
		{`<style><!--\ncss\n--></style>`, `<style><!--\ncss\n--></style>`},
		{`<style>&</style>`, `<style>&</style>`},
		{`<html><head></head><body>x</body></html>`, `x`},
		{`<meta http-equiv="content-type" content="text/html; charset=utf-8">`, `<meta charset=utf-8>`},
		{`<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />`, `<meta charset=utf-8>`},
		{`<meta name="keywords" content="a, b">`, `<meta name=keywords content=a,b>`},
		{`<meta name="viewport" content="width = 996" />`, `<meta name=viewport content="width=996">`},
		{`<span attr="test"></span>`, `<span attr=test></span>`},
		{`<span attr='test&apos;test'></span>`, `<span attr="test'test"></span>`},
		{`<span attr="test&quot;test"></span>`, `<span attr='test"test'></span>`},
		{`<span attr='test""&apos;&amp;test'></span>`, `<span attr='test""&#39;&amp;test'></span>`},
		{`<span attr="test/test"></span>`, `<span attr=test/test></span>`},
		{`<span>&amp;</span>`, `<span>&amp;</span>`},
		{`<span clear=none method=GET></span>`, `<span></span>`},
		{`<span onload="javascript:x;"></span>`, `<span onload=x;></span>`},
		{`<span selected="selected"></span>`, `<span selected></span>`},
		{`<noscript><html><img id="x"></noscript>`, `<noscript><img id=x></noscript>`},
		{`<body id="main"></body>`, `<body id=main>`},
		{`<style><![CDATA[x]]></style>`, `<style>x</style>`},
		{`<link href="data:text/plain, data">`, `<link href=data:,+data>`},
		{`<svg width="100" height="100"><circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /></svg>`, `<svg width=100 height=100><circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" /></svg>`},
		{`</span >`, `</span>`},
		{`<meta name=viewport content="width=0.1, initial-scale=1.0 , maximum-scale=1000">`, `<meta name=viewport content="width=.1,initial-scale=1,maximum-scale=1e3">`},
		{`<br/>`, `<br>`},

		// increase coverage
		{`<script style="css">js</script>`, `<script style=css>js</script>`},
		{`<meta http-equiv="content-type" content="text/plain, text/html">`, `<meta http-equiv=content-type content=text/plain,text/html>`},
		{`<meta http-equiv="content-style-type" content="text/less">`, `<meta http-equiv=content-style-type content=text/less>`},
		{`<meta http-equiv="content-style-type" content="text/less; charset=utf-8">`, `<meta http-equiv=content-style-type content="text/less;charset=utf-8">`},
		{`<meta http-equiv="content-script-type" content="application/js">`, `<meta http-equiv=content-script-type content=application/js>`},
		{`<span attr=""></span>`, `<span attr></span>`},
		{`<code>x</code>`, `<code>x</code>`},
		{`<p></p><p></p>`, `<p><p>`},
		{`<ul><li></li> <li></li></ul>`, `<ul><li><li></ul>`},
		{`<p></p><a></a>`, `<p></p><a></a>`},
		{`<p></p>x<a></a>`, `<p></p>x<a></a>`},
		{`<span style=>`, `<span>`},
		{`<button onclick=>`, `<button>`},

		// whitespace
		{`cats  and 	dogs `, `cats and dogs`},
		{` <div> <i> test </i> <b> test </b> </div> `, `<div><i>test</i> <b>test</b></div>`},
		{`<strong>x </strong>y`, `<strong>x </strong>y`},
		{`<strong>x </strong> y`, `<strong>x</strong> y`},
		{"<strong>x </strong>\ny", "<strong>x</strong>\ny"},
		{`<p>x </p>y`, `<p>x</p>y`},
		{`x <p>y</p>`, `x<p>y`},
		{` <!doctype html> <!--comment--> <html> <body><p></p></body></html> `, `<!doctype html><p>`}, // spaces before html and at the start of html are dropped
		{`<p>x<br> y`, `<p>x<br>y`},
		{`<p>x </b> <b> y`, `<p>x</b> <b>y`},
		{`a <code>code</code> b`, `a <code>code</code> b`},
		{`a <code></code> b`, `a <code></code>b`},
		{`a <script>script</script> b`, `a <script>script</script>b`},
		{"text\n<!--comment-->\ntext", "text\ntext"},
		{"abc\n</body>\ndef", "abc\ndef"},
		{"<x>\n<!--y-->\n</x>", "<x></x>"},

		// from HTML Minifier
		{`<DIV TITLE="blah">boo</DIV>`, `<div title=blah>boo</div>`},
		{"<p title\n\n\t  =\n     \"bar\">foo</p>", `<p title=bar>foo`},
		{`<p class=" foo      ">foo bar baz</p>`, `<p class=foo>foo bar baz`},
		{`<input maxlength="     5 ">`, `<input maxlength=5>`},
		{`<input type="text">`, `<input>`},
		{`<form method="get">`, `<form>`},
		{`<script language="Javascript">alert(1)</script>`, `<script>alert(1)</script>`},
		{`<script></script>`, ``},
		{`<p onclick=" JavaScript: x">x</p>`, `<p onclick=" x">x`},
		{`<span Selected="selected"></span>`, `<span selected></span>`},
		{`<table><thead><tr><th>foo</th><th>bar</th></tr></thead><tfoot><tr><th>baz</th><th>qux</th></tr></tfoot><tbody><tr><td>boo</td><td>moo</td></tr></tbody></table>`,
			`<table><thead><tr><th>foo<th>bar<tfoot><tr><th>baz<th>qux<tbody><tr><td>boo<td>moo</table>`},
		{`<select><option>foo</option><option>bar</option></select>`, `<select><option>foo<option>bar</select>`},
		{`<meta name="keywords" content="A, B">`, `<meta name=keywords content=A,B>`},
		{`<script type="text/html"><![CDATA[ <img id="x"> ]]></script>`, `<script type=text/html><img id=x></script>`},
		{`<iframe><html> <p> x </p> </html></iframe>`, `<iframe><p>x</iframe>`},
		{`<math> &int;_a_^b^{f(x)<over>1+x} dx </math>`, `<math> &int;_a_^b^{f(x)<over>1+x} dx </math>`},
		{`<script language="x" charset="x" src="y"></script>`, `<script src=y></script>`},
		{`<style media="all">x</style>`, `<style>x</style>`},
		{`<a id="abc" name="abc">y</a>`, `<a id=abc>y</a>`},
		{`<a id="" value="">y</a>`, `<a value>y</a>`},

		// from Kangax html-minfier
		{`<span style="font-family:&quot;Helvetica Neue&quot;,&quot;Helvetica&quot;,Helvetica,Arial,sans-serif">text</span>`, `<span style='font-family:"Helvetica Neue","Helvetica",Helvetica,Arial,sans-serif'>text</span>`},

		// go-fuzz
		{`<meta e t n content=ful><a b`, `<meta e t n content=ful><a b>`},
		{`<img alt=a'b="">`, `<img alt='a&#39;b=""'>`},
		{`</b`, `</b`},
	}

	m := minify.New()
	m.AddFunc("text/html", Minify)
	m.AddFunc("text/css", func(_ *minify.M, w io.Writer, r io.Reader, _ map[string]string) error {
		_, err := io.Copy(w, r)
		return err
	})
	m.AddFunc("text/javascript", func(_ *minify.M, w io.Writer, r io.Reader, _ map[string]string) error {
		_, err := io.Copy(w, r)
		return err
	})
	for _, tt := range htmlTests {
		r := bytes.NewBufferString(tt.html)
		w := &bytes.Buffer{}
		test.Minify(t, tt.html, Minify(m, w, r, nil), w.String(), tt.expected)
	}
}
Beispiel #18
0
func TestCSSInline(t *testing.T) {
	cssTests := []struct {
		css      string
		expected string
	}{
		{"/*comment*/", ""},
		{"/*! bang  comment */", ""},
		{";", ""},
		{"empty:", "empty:"},
		{"key: value;", "key:value"},
		{"margin: 0 1; padding: 0 1;", "margin:0 1;padding:0 1"},
		{"color: #FF0000;", "color:red"},
		{"color: #000000;", "color:#000"},
		{"color: black;", "color:#000"},
		{"color: rgb(255,255,255);", "color:#fff"},
		{"color: rgb(100%,100%,100%);", "color:#fff"},
		{"color: rgba(255,0,0,1);", "color:red"},
		{"color: rgba(255,0,0,2);", "color:red"},
		{"color: rgba(255,0,0,0.5);", "color:rgba(255,0,0,.5)"},
		{"color: rgba(255,0,0,-1);", "color:transparent"},
		{"color: hsl(0,100%,50%);", "color:red"},
		{"color: hsla(1,2%,3%,1);", "color:#080807"},
		{"color: hsla(1,2%,3%,0);", "color:transparent"},
		{"color: hsl(48,100%,50%);", "color:#fc0"},
		{"font-weight: bold; font-weight: normal;", "font-weight:700;font-weight:400"},
		{"font: bold \"Times new Roman\",\"Sans-Serif\";", "font:700 times new roman,\"sans-serif\""},
		{"outline: none;", "outline:0"},
		{"outline: none !important;", "outline:0!important"},
		{"border-left: none;", "border-left:0"},
		{"margin: 1 1 1 1;", "margin:1"},
		{"margin: 1 2 1 2;", "margin:1 2"},
		{"margin: 1 2 3 2;", "margin:1 2 3"},
		{"margin: 1 2 3 4;", "margin:1 2 3 4"},
		{"margin: 1 1 1 a;", "margin:1 1 1 a"},
		{"margin: 1 1 1 1 !important;", "margin:1!important"},
		{"padding:.2em .4em .2em", "padding:.2em .4em"},
		{"margin: 0em;", "margin:0"},
		{"font-family:'Arial', 'Times New Roman';", "font-family:arial,times new roman"},
		{"background:url('http://domain.com/image.png');", "background:url(http://domain.com/image.png)"},
		{"filter: progid : DXImageTransform.Microsoft.BasicImage(rotation=1);", "filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"},
		{"filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=0);", "filter:alpha(opacity=0)"},
		{"content: \"a\\\nb\";", "content:\"ab\""},
		{"content: \"a\\\r\nb\\\r\nc\";", "content:\"abc\""},
		{"content: \"\";", "content:\"\""},

		{"font:27px/13px arial,sans-serif", "font:27px/13px arial,sans-serif"},
		{"text-decoration: none !important", "text-decoration:none!important"},
		{"color:#fff", "color:#fff"},
		{"border:2px rgb(255,255,255);", "border:2px #fff"},
		{"margin:-1px", "margin:-1px"},
		{"margin:+1px", "margin:1px"},
		{"margin:0.5em", "margin:.5em"},
		{"margin:-0.5em", "margin:-.5em"},
		{"margin:05em", "margin:5em"},
		{"margin:.50em", "margin:.5em"},
		{"margin:5.0em", "margin:5em"},
		{"margin:5000em", "margin:5e3em"},
		{"color:#c0c0c0", "color:silver"},
		{"-ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)\";", "-ms-filter:\"alpha(opacity=80)\""},
		{"filter: progid:DXImageTransform.Microsoft.Alpha(Opacity = 80);", "filter:alpha(opacity=80)"},
		{"MARGIN:1EM", "margin:1em"},
		{"color:CYAN", "color:cyan"},
		{"background:URL(x.PNG);", "background:url(x.PNG)"},
		{"background:url(/*nocomment*/)", "background:url(/*nocomment*/)"},
		{"background:url(data:,text)", "background:url(data:,text)"},
		{"background:url('data:text/xml; version = 2.0,content')", "background:url(data:text/xml;version=2.0,content)"},
		{"background:url('data:\\'\",text')", "background:url('data:\\'\",text')"},
		{"margin:0 0 18px 0;", "margin:0 0 18px"},
		{"background:none", "background:0 0"},
		{"background:none 1 1", "background:none 1 1"},
		{"z-index:1000", "z-index:1000"},

		// coverage
		{"margin: 1 1;", "margin:1"},
		{"margin: 1 2;", "margin:1 2"},
		{"margin: 1 1 1;", "margin:1"},
		{"margin: 1 2 1;", "margin:1 2"},
		{"margin: 1 2 3;", "margin:1 2 3"},
		{"margin: 0%;", "margin:0"},
		{"color: rgb(255,64,64);", "color:#ff4040"},
		{"color: rgb(256,-34,2342435);", "color:#f0f"},
		{"color: rgb(120%,-45%,234234234%);", "color:#f0f"},
		{"color: rgb(0, 1, ident);", "color:rgb(0,1,ident)"},
		{"color: rgb(ident);", "color:rgb(ident)"},
		{"margin: rgb(ident);", "margin:rgb(ident)"},
		{"filter: progid:b().c.Alpha(rgba(x));", "filter:progid:b().c.Alpha(rgba(x))"},

		// go-fuzz
		{"FONT-FAMILY: ru\"", "font-family:ru\""},
	}

	m := minify.New()
	params := map[string]string{"inline": "1"}
	for _, tt := range cssTests {
		r := bytes.NewBufferString(tt.css)
		w := &bytes.Buffer{}
		test.Minify(t, tt.css, Minify(m, w, r, params), w.String(), tt.expected)
	}
}
Beispiel #19
0
func TestNumber(t *testing.T) {
	numberTests := []struct {
		number   string
		expected string
	}{
		{"0", "0"},
		{".0", "0"},
		{"1.0", "1"},
		{"0.1", ".1"},
		{"+1", "1"},
		{"-1", "-1"},
		{"-0.1", "-.1"},
		{"10", "10"},
		{"100", "100"},
		{"1000", "1e3"},
		{"0.001", ".001"},
		{"0.0001", "1e-4"},
		{"100e1", "1e3"},
		{"1.1e+1", "11"},
		{"1.1e6", "11e5"},
		{"0.252", ".252"},
		{"1.252", "1.252"},
		{"-1.252", "-1.252"},
		{"0.075", ".075"},
		{"789012345678901234567890123456789e9234567890123456789", "789012345678901234567890123456789e9234567890123456789"},
		{".000100009", "100009e-9"},
		{".0001000009", ".0001000009"},
		{".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009", ".0001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009"},
		{"E\x1f", "E\x1f"}, // fuzz
		{"1e9223372036854775807", "1e9223372036854775807"},
		{"11e9223372036854775807", "11e9223372036854775807"},
		{".01e-9223372036854775808", ".01e-9223372036854775808"},
		{".011e-9223372036854775808", ".011e-9223372036854775808"},

		{".12345e8", "12345e3"},
		{".12345e7", "1234500"},
		{".12345e6", "123450"},
		{".12345e5", "12345"},
		{".012345e6", "12345"},
		{".12345e4", "1234.5"},
		{"-.12345e4", "-1234.5"},
		{".12345e0", ".12345"},
		{".12345e-1", ".012345"},
		{".12345e-2", ".0012345"},
		{".12345e-3", "12345e-8"},
		{".12345e-4", "12345e-9"},
		{".12345e-5", "12345e-10"},

		{".123456e-3", "123456e-9"},
		{".123456e-2", ".00123456"},
		{".1234567e-4", "1234567e-11"},
		{".1234567e-3", ".0001234567"},

		{"12345678e-1", "1234567.8"},
		{"72.e-3", ".072"},
		{"7640e-2", "76.4"},
		{"10.e-3", ".01"},
		{".0319e3", "31.9"},
		{"39.7e-2", ".397"},
		{"39.7e-3", ".0397"},
		{".01e1", ".1"},
		{".001e1", ".01"},
		{"39.7e-5", "397e-6"},
	}
	for _, tt := range numberTests {
		test.Minify(t, tt.number, nil, string(Number([]byte(tt.number), -1)), tt.expected)
	}
}