-
Notifications
You must be signed in to change notification settings - Fork 0
/
html.go
85 lines (72 loc) · 2.35 KB
/
html.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package markdown
import (
"io"
"regexp"
"strings"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/ast"
mdhtml "github.com/gomarkdown/markdown/html"
)
func ToHTML(md string) string {
renderer := newCustomizedRender()
html := markdown.ToHTML([]byte(md), nil, renderer)
result := strings.TrimSpace(string(html))
// Support GLM Task lists
result = supportTaskLists(result)
return result
}
func ToInlineHTML(md string) string {
html := strings.TrimSpace(ToHTML(md))
if strings.HasPrefix(html, "<p>") && strings.HasSuffix(html, "</p>") {
html = strings.TrimPrefix(html, "<p>")
html = strings.TrimSuffix(html, "</p>")
}
return html
}
/* Extensions */
func supportTaskLists(html string) string {
// See https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#task-lists
rePendingTasks := regexp.MustCompile(`<li>\[ \]\s+(.*)</li>`)
reCompletedTasks := regexp.MustCompile(`<li>\[x\]\s+(.*)</li>`)
html = rePendingTasks.ReplaceAllString(html, `<li><input type="checkbox" /> $1</li>`)
html = reCompletedTasks.ReplaceAllString(html, `<li><input type="checkbox" checked="checked" /> $1</li>`)
return html
}
/* Customizations */
/* Read https://blog.kowalczyk.info/article/cxn3/advanced-markdown-processing-in-go.html */
func newCustomizedRender() *mdhtml.Renderer {
opts := mdhtml.RendererOptions{
Flags: mdhtml.CommonFlags | mdhtml.HrefTargetBlank,
RenderNodeHook: myRenderHook,
}
return mdhtml.NewRenderer(opts)
}
func myRenderHook(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
if image, ok := node.(*ast.Image); ok {
renderMedia(w, image, entering)
return ast.GoToNext, true
}
return ast.GoToNext, false
}
func renderMedia(w io.Writer, image *ast.Image, entering bool) {
if entering {
imageEnter(w, image)
} else {
imageExit(w, image)
}
}
func imageEnter(w io.Writer, image *ast.Image) {
attrs := mdhtml.BlockAttrs(image)
src := string(image.Destination)
oid := strings.TrimPrefix(src, "oid:")
s := mdhtml.TagWithAttributes("<media", attrs)
s = s[:len(s)-1] // hackish: strip off ">" from end
io.WriteString(w, s+` oid="`+oid+`" alt="`)
}
func imageExit(w io.Writer, image *ast.Image) {
if image.Title != nil {
io.WriteString(w, `" title="`)
mdhtml.EscapeHTML(w, image.Title)
}
io.WriteString(w, `" />`)
}