Beispiel #1
0
/*
Minify middleware is simple and generic using 'tdewolff/minify' package.
Middleware minifies HTML, Inline CSS and Inline JS. Compatible with Goji,
Gorilla, Gin & net/http (amongst many others).
Refer: https://github.com/jeevatkm/middleware/examples
*/
func Minify(h http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		mw := &minifyWriter{
			ResponseWriter: w,
			Body:           &bytes.Buffer{},
		}

		h.ServeHTTP(mw, r)

		hdr := w.Header()
		ct := hdr.Get("Content-Type")
		if mediaType.MatchString(ct) {
			rb, err := minify.Bytes(minifier, ct, mw.Body.Bytes())
			if err != nil {
				_ = err // unsupported mediatype error or internal
			}

			hdr.Del("Content-Length")
			hdr.Set("Content-Length", strconv.Itoa(len(rb)))

			w.Write(rb)
		} else {
			w.Write(mw.Body.Bytes())
		}
	})
}
Beispiel #2
0
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)
	}
}
Beispiel #3
0
func svg(path string, info os.FileInfo) error {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	min, err := minify.Bytes(minifier, "image/svg+xml", input)
	if err != nil {
		return fmt.Errorf("cannot minify svg: %v", err)
	}

	dst := filepath.Join(outputDir, path)
	if err := writeFile(dst, min); err != nil {
		return err
	}
	return nil
}
Beispiel #4
0
func graphvizDot(path string, info os.FileInfo) error {
	f, err := os.Open(path)
	if err != nil {
		return err
	}
	defer f.Close()
	cmd := exec.Command("dot", "-Tsvg")
	cmd.Stdin = f
	buf, err := cmd.Output()
	if err != nil {
		return fmt.Errorf("error running dot: %v", err)
	}

	min, err := minify.Bytes(minifier, "image/svg+xml", buf)
	if err != nil {
		return fmt.Errorf("cannot minify svg: %v", err)
	}

	dst := filepath.Join(outputDir, strings.TrimSuffix(path, ".dot")+".svg")
	if err := writeFile(dst, min); err != nil {
		return err
	}
	return nil
}
Beispiel #5
0
func markdown(path string, info os.FileInfo) error {
	input, err := ioutil.ReadFile(path)
	if err != nil {
		return err
	}

	// extract the header out of the markdown, so we can control the
	// layout better; blackfriday would put the toc above the h1, and
	// include the singular h1 in the toc, causing stutter.
	idx := bytes.IndexByte(input, '\n')
	if idx == -1 {
		return errors.New("markdown has no content")
	}
	titleMD, input := input[:idx], input[idx+1:]

	htmlFlags := (0 |
		blackfriday.HTML_USE_SMARTYPANTS |
		blackfriday.HTML_SMARTYPANTS_FRACTIONS |
		blackfriday.HTML_SMARTYPANTS_LATEX_DASHES |
		blackfriday.HTML_USE_XHTML |
		blackfriday.HTML_FOOTNOTE_RETURN_LINKS |
		0)
	// HtmlRenderer demands a title and a css path here, but we only
	// render a fragment so those are not used
	renderer := blackfriday.HtmlRenderer(htmlFlags, "", "")
	extensions := (0 |
		blackfriday.EXTENSION_NO_INTRA_EMPHASIS |
		blackfriday.EXTENSION_TABLES |
		blackfriday.EXTENSION_FENCED_CODE |
		blackfriday.EXTENSION_AUTOLINK |
		blackfriday.EXTENSION_STRIKETHROUGH |
		blackfriday.EXTENSION_SPACE_HEADERS |
		blackfriday.EXTENSION_FOOTNOTES |
		blackfriday.EXTENSION_HEADER_IDS |
		blackfriday.EXTENSION_AUTO_HEADER_IDS |
		0)
	titleHTML := blackfriday.Markdown(titleMD, renderer, extensions)
	contentHTML := blackfriday.Markdown(input, renderer, extensions)

	tocFlags := htmlFlags | blackfriday.HTML_TOC | blackfriday.HTML_OMIT_CONTENTS
	tocRenderer := blackfriday.HtmlRenderer(tocFlags, "", "")
	tocHTML := blackfriday.Markdown(input, tocRenderer, extensions)
	body := &html.Node{
		Type:     html.ElementNode,
		Data:     "body",
		DataAtom: atom.Body,
	}
	nodes, err := html.ParseFragment(bytes.NewReader(titleHTML), body)
	if err != nil {
		return fmt.Errorf("cannot parse generated html: %v", err)
	}
	if len(nodes) == 0 ||
		nodes[0].Type != html.ElementNode ||
		nodes[0].DataAtom != atom.H1 {
		return errors.New("markdown does not start with a header")
	}
	title := childText(nodes[0])

	var buf bytes.Buffer
	prettyPath := "/" + strings.TrimSuffix(path, ".md")
	if dir, file := filepath.Split(prettyPath); file == "index" {
		prettyPath = dir
	}
	data := struct {
		Path    string
		Title   string
		H1      template.HTML
		TOC     template.HTML
		Content template.HTML
	}{
		Path:    prettyPath,
		Title:   title,
		H1:      template.HTML(titleHTML),
		TOC:     template.HTML(tocHTML),
		Content: template.HTML(contentHTML),
	}
	if err := layout.Execute(&buf, data); err != nil {
		return fmt.Errorf("executing template: %v", err)
	}

	min, err := minify.Bytes(minifier, "text/html", buf.Bytes())
	if err != nil {
		return fmt.Errorf("cannot minify html: %v", err)
	}

	dst := filepath.Join(outputDir, strings.TrimSuffix(path, ".md")+".html")
	if err := writeFile(dst, min); err != nil {
		return err
	}
	return nil
}