func (e extractContent) prepareHTMLOut(a *Article) error { if a.TopNode == nil { return nil } m := minify.New() m.AddFunc("text/html", minhtml.Minify) var b bytes.Buffer html, _ := a.TopNode.Html() m.Minify("text/html", &b, strings.NewReader(html)) doc, _ := goquery.NewDocumentFromReader(&b) a.TopNode = doc.FindMatcher(bodyTag) // Quick-and-dirty node-to-text replacement a.TopNode.FindMatcher(replaceWithContentsTags).Each( func(i int, s *goquery.Selection) { s.Contents().Unwrap() }) a.addInlineArticleImageHTML(a.Meta.Title) return nil }
func (*minify) Process(ctx goldsmith.Context, f goldsmith.File) error { var ( buff bytes.Buffer err error ) switch m := min.New(); filepath.Ext(f.Path()) { case ".css": err = css.Minify(m, &buff, f, nil) case ".html", ".htm": err = html.Minify(m, &buff, f, nil) case ".js": err = js.Minify(m, &buff, f, nil) case ".json": err = json.Minify(m, &buff, f, nil) case ".svg": err = svg.Minify(m, &buff, f, nil) case ".xml": err = xml.Minify(m, &buff, f, nil) } if err != nil { return err } nf := goldsmith.NewFileFromData(f.Path(), buff.Bytes()) nf.CopyValues(f) ctx.DispatchFile(nf) return nil }
func TestHTMLURL(t *testing.T) { var 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) assert.Nil(t, Minify(m, w, r, nil), "Minify must not return error in "+tt.html) assert.Equal(t, tt.expected, w.String(), "Minify must give expected result in "+tt.html) } }
func TestWriterErrors(t *testing.T) { errorTests := []struct { css string n []int }{ {`@import 'file'`, []int{0, 2}}, {`@media all{}`, []int{0, 2, 3, 4}}, {`a[id^="L"]{margin:2in!important;color:red}`, []int{0, 4, 6, 7, 8, 9, 10, 11}}, {`a{color:rgb(255,0,0)}`, []int{4}}, {`a{color:rgb(255,255,255)}`, []int{4}}, {`a{color:hsl(0,100%,50%)}`, []int{4}}, {`a{color:hsl(360,100%,100%)}`, []int{4}}, {`a{color:f(arg)}`, []int{4}}, {`<!--`, []int{0}}, {`/*!comment*/`, []int{0, 1, 2}}, } m := minify.New() for _, tt := range errorTests { for _, n := range tt.n { r := bytes.NewBufferString(tt.css) w := test.NewErrorWriter(n) test.Error(t, Minify(m, w, r, nil), test.ErrPlain, "return error at write", n, "in", tt.css) } } }
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) } }
func TestWriterErrors(t *testing.T) { errorTests := []struct { svg string n []int }{ {`<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "foo.dtd" [ <!ENTITY x "bar"> ]>`, []int{0}}, {`abc`, []int{0}}, {`<style>abc</style>`, []int{2}}, {`<![CDATA[ <<<< ]]>`, []int{0}}, {`<![CDATA[ <<<<< ]]>`, []int{0}}, {`<path d="x"/>`, []int{0, 1, 2, 3, 4, 5}}, {`<path></path>`, []int{1}}, {`<svg>x</svg>`, []int{1, 3}}, {`<svg>x</svg >`, []int{3}}, } m := minify.New() for _, tt := range errorTests { for _, n := range tt.n { r := bytes.NewBufferString(tt.svg) w := test.NewErrorWriter(n) test.Error(t, Minify(m, w, r, nil), test.ErrPlain, "return error at write", n, "in", tt.svg) } } }
func createAppMinJsFile(appScripts []string, dir string) { appMinJsWrtr, err := os.Create(filepath.Join(dir, "app.min.js")) if err != nil { log.Fatal(err) } defer closeFile(appMinJsWrtr, true) var buffer bytes.Buffer for _, script := range appScripts { file, err := os.Open(filepath.Join(dir, script)) if err != nil { log.Fatal(err) } defer closeFile(file, false) _, err = io.Copy(&buffer, file) if err != nil { log.Fatalf("Error copying script file '%v' to buffer: %v", script, err) } } mimetype := "text/javascript" minifier := minify.New() minifier.AddFunc(mimetype, js.Minify) minified, err := minify.Bytes(minifier, mimetype, buffer.Bytes()) if err != nil { log.Fatalf("Error during minification: %v", err) } _, err = io.Copy(appMinJsWrtr, bytes.NewReader(minified)) if err != nil { log.Fatalf("Error copying to file app.min.js: %v", err) } }
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) } }
func assertSVG(t *testing.T, input, expected string) { m := minify.New() m.AddFunc("image/svg+xml", Minify) b := &bytes.Buffer{} assert.Nil(t, m.Minify("image/svg+xml", b, bytes.NewBufferString(input)), "Minify must not return error in "+input) assert.Equal(t, expected, b.String(), "Minify must give expected result in "+input) }
func Minify() gonzo.Stage { return func(ctx context.Context, in <-chan gonzo.File, out chan<- gonzo.File) error { for { select { case file, ok := <-in: if !ok { return nil } buff := new(bytes.Buffer) name := strings.TrimSuffix(file.FileInfo().Name(), ".css") + ".min.css" ctx.Infof("Compiling %s to %s", file.FileInfo().Name(), name) m := minify.New() m.AddFunc("text/css", css.Minify) err := m.Minify("text/css", buff, file) if err != nil { return err } file = gonzo.NewFile(ioutil.NopCloser(buff), file.FileInfo()) file.FileInfo().SetSize(int64(buff.Len())) file.FileInfo().SetName(name) out <- file case <-ctx.Done(): return ctx.Err() } } } }
func TestJS(t *testing.T) { var jsTests = []struct { js string expected string }{ {"/*comment*/", ""}, {"// comment\na", "a"}, {"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 } m := minify.New() for _, tt := range jsTests { b := &bytes.Buffer{} assert.Nil(t, Minify(m, b, bytes.NewBufferString(tt.js), nil), "Minify must not return error in "+tt.js) assert.Equal(t, tt.expected, b.String(), "Minify must give expected result in "+tt.js) } }
func Min(c *slurp.C, mediatype string) slurp.Stage { return func(in <-chan slurp.File, out chan<- slurp.File) { supported := make(map[string]uint8) supported["text/css"] = 1 supported["text/html"] = 1 supported["text/javascript"] = 1 var wg sync.WaitGroup defer wg.Wait() _, ok := supported[mediatype] if ok { for file := range in { m := minify.New() m.AddFunc("text/css", css.Minify) m.AddFunc("text/html", html.Minify) m.AddFunc("text/javascript", js.Minify) wg.Add(1) go func(file slurp.File) { defer wg.Done() minified := new(bytes.Buffer) if err := m.Minify(mediatype, minified, file.Reader); err != nil { log.Fatal("js.Minify:", err) } file.Reader = minified file.FileInfo.SetSize(int64(minified.Len())) out <- file }(file) } } } }
func TestWriterErrors(t *testing.T) { var errorTests = []struct { css string n []int }{ {`@import 'file'`, []int{0, 2}}, {`@media all{}`, []int{0, 2, 3, 4}}, {`a[id^="L"]{margin:2in!important;color:red}`, []int{0, 4, 6, 7, 8, 9, 10, 11}}, {`a{color:rgb(255,0,0)}`, []int{4}}, {`a{color:rgb(255,255,255)}`, []int{4}}, {`a{color:hsl(0,100%,50%)}`, []int{4}}, {`a{color:hsl(360,100%,100%)}`, []int{4}}, {`a{color:f(arg)}`, []int{4}}, {`<!--`, []int{0}}, } m := minify.New() for _, tt := range errorTests { for _, n := range tt.n { r := bytes.NewBufferString(tt.css) w := test.NewErrorWriter(n) assert.Equal(t, test.ErrPlain, Minify(m, w, r, nil), "Minify must return error in "+tt.css+" at write "+strconv.FormatInt(int64(n), 10)) } } }
func TestXML(t *testing.T) { var 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=\"'b"\"></x>", "<x a=\"'b"\"/>"}, {"<x a=\"""'\"></x>", "<x a='\"\"''/>"}, {"<!DOCTYPE foo SYSTEM \"Foo.dtd\">", "<!DOCTYPE foo SYSTEM \"Foo.dtd\">"}, {"text <!--comment--> text", "text text"}, } m := minify.New() for _, tt := range xmlTests { b := &bytes.Buffer{} assert.Nil(t, Minify(m, b, bytes.NewBufferString(tt.xml), nil), "Minify must not return error in "+tt.xml) assert.Equal(t, tt.expected, b.String(), "Minify must give expected result in "+tt.xml) } }
func ExampleMinify() { m := minify.New() m.AddFunc("text/css", Minify) if err := m.Minify("text/css", os.Stdout, os.Stdin); err != nil { fmt.Println("minify.Minify:", err) } }
func ExampleMinify() { m := minify.New() m.AddFuncRegexp(regexp.MustCompile("[/+]xml$"), Minify) if err := m.Minify("text/xml", os.Stdout, os.Stdin); err != nil { panic(err) } }
func init() { minifier = minify.New() minifier.AddFunc("text/css", css.Minify) minifier.AddFunc("text/html", html.Minify) minifier.AddFunc("text/javascript", js.Minify) mediaType = regexp.MustCompile("text/[html|css|javascript]") }
func Fuzz(data []byte) int { r := bytes.NewBuffer(data) err := xml.Minify(minify.New(), ioutil.Discard, r, nil) if err != nil { panic(err) } return 1 }
func ExampleMinify() { m := minify.New() m.AddFunc("text/css", Minify) if err := m.Minify("text/css", os.Stdout, os.Stdin); err != nil { panic(err) } }
func ExampleMinify() { m := minify.New() m.AddFuncRegexp(regexp.MustCompile("[/+]json$"), Minify) if err := m.Minify("application/json", os.Stdout, os.Stdin); err != nil { fmt.Println("minify.Minify:", err) } }
func Fuzz(data []byte) int { r := bytes.NewBuffer(data) err := json.Minify(minify.New(), ioutil.Discard, r, nil) if err != nil { return 0 } return 1 }
func TestCSSInlineMediatype(t *testing.T) { css := `color:red` m := minify.New() r := bytes.NewBufferString(css) w := &bytes.Buffer{} assert.Nil(t, Minify(m, "text/css ; inline = 1", w, r), "Minify must not return error in "+css) assert.Equal(t, css, w.String(), "Minify must give expected result in "+css) }
// Helper function to minify code func minifyScript(script string) string { m := minify.New() m.AddFunc("text/javascript", js.Minify) miny, err := m.String("text/javascript", script) if err != nil { log.Fatal("minify.String:", err) } return miny }
func ExampleMinify_writer() { m := minify.New() m.Add("text/html", &Minifier{}) w := m.Writer("text/html", os.Stdout) w.Write([]byte("<html><body><h1>Example</h1></body></html>")) w.Close() // Output: <h1>Example</h1> }
func Minify(input string, mime string) (result string) { if minifier == nil { log.Print("initializing minifier") minifier = minify.New() minifier.AddFunc("js", js.Minify) } result, err := minify.String(minifier, mime, input) CheckErrorPanic(err) return }
func initMinifier() { if m != nil { return } m = minify.New() m.AddFunc("text/css", css.Minify) m.AddFunc("text/javascript", js.Minify) }
func getMinifier() *minify.M { if minifier == nil { minifier = minify.New() minifier.AddFunc("text/css", css.Minify) minifier.AddFunc("application/javascript", js.Minify) minifier.AddFunc("application/json", json.Minify) minifier.AddFunc("image/svg+xml", svg.Minify) } return minifier }
func TestWriterErrors(t *testing.T) { var errorTests = []int{0, 1, 2, 3, 4, 5, 6, 7, 11, 12, 13, 14, 15, 16, 17, 18, 19} m := minify.New() for _, n := range errorTests { // writes: 0 1 2 3 45678901 23 4 5 6 7 8 9 r := bytes.NewBufferString(`<!DOCTYPE foo><?xml?><a x=y z="val"><b/><c></c></a><![CDATA[data<<<<<]]>text`) w := test.NewErrorWriter(n) assert.Equal(t, test.ErrPlain, Minify(m, w, r, nil), "Minify must return error at write "+strconv.FormatInt(int64(n), 10)) } }
func TestWriterErrors(t *testing.T) { var errorTests = []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 14} m := minify.New() for _, n := range errorTests { // writes: 0 1 2 34 56 78 9 0 12 3 4 r := bytes.NewBufferString(`<!doctype>text<style attr=val>css</style><code>code</code><!--comment-->`) w := test.NewErrorWriter(n) assert.Equal(t, test.ErrPlain, Minify(m, w, r, nil), "Minify must return error at write "+strconv.FormatInt(int64(n), 10)) } }
func ExampleMinify_options() { m := minify.New() m.Add("text/html", &Minifier{ KeepDefaultAttrVals: true, KeepWhitespace: true, }) if err := m.Minify("text/html", os.Stdout, os.Stdin); err != nil { panic(err) } }