mirror of
https://github.com/danog/gojekyll.git
synced 2024-12-12 14:57:21 +01:00
117 lines
2.5 KiB
Go
117 lines
2.5 KiB
Go
package pipelines
|
|
|
|
import (
|
|
"bytes"
|
|
"io"
|
|
"regexp"
|
|
|
|
"github.com/russross/blackfriday"
|
|
"golang.org/x/net/html"
|
|
)
|
|
|
|
const blackfridayFlags = 0 |
|
|
blackfriday.HTML_USE_XHTML |
|
|
blackfriday.HTML_USE_SMARTYPANTS |
|
|
blackfriday.HTML_SMARTYPANTS_FRACTIONS |
|
|
blackfriday.HTML_SMARTYPANTS_DASHES |
|
|
blackfriday.HTML_SMARTYPANTS_LATEX_DASHES
|
|
|
|
const blackfridayExtensions = 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_HEADER_IDS |
|
|
blackfriday.EXTENSION_BACKSLASH_LINE_BREAK |
|
|
blackfriday.EXTENSION_DEFINITION_LISTS |
|
|
// added relative to commonExtensions
|
|
blackfriday.EXTENSION_AUTO_HEADER_IDS
|
|
|
|
func renderMarkdown(md []byte) []byte {
|
|
renderer := blackfriday.HtmlRenderer(blackfridayFlags, "", "")
|
|
html := blackfriday.MarkdownOptions(md, renderer, blackfriday.Options{
|
|
Extensions: blackfridayExtensions})
|
|
html, err := renderInnerMarkdown(html)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return html
|
|
}
|
|
|
|
var markdownAttrRE = regexp.MustCompile(`\s*markdown\s*=\s*("1"|'1'|1)\s*`)
|
|
|
|
func renderInnerMarkdown(b []byte) ([]byte, error) {
|
|
z := html.NewTokenizer(bytes.NewReader(b))
|
|
buf := new(bytes.Buffer)
|
|
outer:
|
|
for {
|
|
tt := z.Next()
|
|
switch tt {
|
|
case html.ErrorToken:
|
|
if z.Err() == io.EOF {
|
|
break outer
|
|
}
|
|
return nil, z.Err()
|
|
case html.StartTagToken:
|
|
if hasAttr(z) {
|
|
tag := markdownAttrRE.ReplaceAll(z.Raw(), []byte(" "))
|
|
tag = bytes.Replace(tag, []byte(" >"), []byte(">"), 1)
|
|
_, err := buf.Write(tag)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := processInnerMarkdown(buf, z); err != nil {
|
|
return nil, err
|
|
}
|
|
// the above leaves z set to the end token
|
|
}
|
|
}
|
|
_, err := buf.Write(z.Raw())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
func hasAttr(z *html.Tokenizer) bool {
|
|
for {
|
|
k, v, more := z.TagAttr()
|
|
switch {
|
|
case string(k) == "markdown" && string(v) == "1":
|
|
return true
|
|
case !more:
|
|
return false
|
|
}
|
|
}
|
|
}
|
|
|
|
func processInnerMarkdown(w io.Writer, z *html.Tokenizer) error {
|
|
buf := new(bytes.Buffer)
|
|
depth := 1
|
|
loop:
|
|
for {
|
|
tt := z.Next()
|
|
switch tt {
|
|
case html.ErrorToken:
|
|
return z.Err()
|
|
case html.StartTagToken:
|
|
depth++
|
|
case html.EndTagToken:
|
|
depth--
|
|
if depth == 0 {
|
|
break loop
|
|
}
|
|
}
|
|
_, err := buf.Write(z.Raw())
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
html := renderMarkdown(buf.Bytes())
|
|
_, err := w.Write(html)
|
|
return err
|
|
}
|