-
Notifications
You must be signed in to change notification settings - Fork 27
/
markdown.go
84 lines (72 loc) · 2.24 KB
/
markdown.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
package main
import (
stdhtml "html"
"io"
"strings"
"github.com/gomarkdown/markdown"
"github.com/gomarkdown/markdown/ast"
"github.com/gomarkdown/markdown/html"
"github.com/gomarkdown/markdown/parser"
)
var mdrenderer = html.NewRenderer(html.RendererOptions{
Flags: html.HrefTargetBlank | html.SkipHTML,
RenderNodeHook: func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
switch v := node.(type) {
case *ast.HTMLSpan:
w.Write([]byte(stdhtml.EscapeString(string(v.Literal))))
return ast.GoToNext, true
case *ast.HTMLBlock:
w.Write([]byte(stdhtml.EscapeString(string(v.Literal))))
return ast.GoToNext, true
}
return ast.GoToNext, false
},
})
var tgivmdrenderer = html.NewRenderer(html.RendererOptions{
Flags: html.CommonFlags | html.HrefTargetBlank,
RenderNodeHook: func(w io.Writer, node ast.Node, entering bool) (ast.WalkStatus, bool) {
// telegram instant view really doesn't like when there is an image inside a paragraph (like <p><img></p>)
// so we use this custom thing to stop all paragraphs before the images, print the images then start a new
// paragraph afterwards.
if img, ok := node.(*ast.Image); ok {
if entering {
src := img.Destination
w.Write([]byte(`</p><img src="`))
html.EscLink(w, src)
w.Write([]byte(`" alt="`))
} else {
if img.Title != nil {
w.Write([]byte(`" title="`))
html.EscapeHTML(w, img.Title)
}
w.Write([]byte(`" /><p>`))
}
return ast.GoToNext, true
}
return ast.GoToNext, false
},
})
func mdToHTML(md string, usingTelegramInstantView bool) string {
md = strings.ReplaceAll(md, "\u00A0", " ")
// create markdown parser with extensions
// this parser is stateful so it must be reinitialized every time
doc := parser.NewWithExtensions(
parser.AutoHeadingIDs |
parser.NoIntraEmphasis |
parser.FencedCode |
parser.Autolink |
parser.Footnotes |
parser.SpaceHeadings,
).Parse([]byte(md))
renderer := mdrenderer
if usingTelegramInstantView {
renderer = tgivmdrenderer
}
// create HTML renderer with extensions
output := string(markdown.Render(doc, renderer))
// sanitize content
output = sanitizeXSS(output)
// nostr urls
output = replaceNostrURLsWithHTMLTags(nostrEveryMatcher, output)
return output
}