-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathreplacer.go
105 lines (95 loc) · 2.65 KB
/
replacer.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Package replacer is a extension for the goldmark
// (http://github.com/yuin/goldmark).
//
// This extension adds support for authomaticaly replacing text in markdowns.
package replacer
import (
"strings"
"github.com/yuin/goldmark"
"github.com/yuin/goldmark/ast"
"github.com/yuin/goldmark/renderer"
"github.com/yuin/goldmark/renderer/html"
"github.com/yuin/goldmark/util"
)
// replacer replaces a list of strings with replacements in markdown text.
type replacer struct {
html.Config
*strings.Replacer
}
// New returns a new Replacer from a list of old, new string pairs.
// Replacements are performed in the order they appear in the target string,
// without overlapping matches. The old string comparisons are done in argument
// order.
//
// It's panics if given an odd number of arguments.
func New(oldnew ...string) goldmark.Extender {
return &replacer{
Config: html.NewConfig(),
Replacer: strings.NewReplacer(oldnew...),
}
}
func (r *replacer) replace(source []byte) []byte {
return util.StringToReadOnlyBytes(
r.Replacer.Replace(util.BytesToReadOnlyString(source)))
}
func (r *replacer) renderText(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
return ast.WalkContinue, nil
}
var (
n = node.(*ast.Text)
text = r.replace(n.Text(source))
)
if n.IsRaw() {
r.Writer.RawWrite(w, text)
} else {
r.Writer.Write(w, text)
if n.HardLineBreak() || (n.SoftLineBreak() && r.HardWraps) {
if r.XHTML {
_, _ = w.WriteString("<br />\n")
} else {
_, _ = w.WriteString("<br>\n")
}
} else if n.SoftLineBreak() {
_ = w.WriteByte('\n')
}
}
return ast.WalkContinue, nil
}
func (r *replacer) renderString(w util.BufWriter, source []byte, node ast.Node, entering bool) (ast.WalkStatus, error) {
if !entering {
return ast.WalkContinue, nil
}
var (
n = node.(*ast.String)
text = r.replace(n.Value)
)
if n.IsCode() {
_, _ = w.Write(text)
} else {
if n.IsRaw() {
r.Writer.RawWrite(w, text)
} else {
r.Writer.Write(w, text)
}
}
return ast.WalkContinue, nil
}
// RegisterFuncs implements NodeRenderer.RegisterFuncs interface.
func (r *replacer) RegisterFuncs(reg renderer.NodeRendererFuncRegisterer) {
reg.Register(ast.KindText, r.renderText)
reg.Register(ast.KindString, r.renderString)
}
// Extend implement goldmark.Extender interface.
func (r *replacer) Extend(m goldmark.Markdown) {
if r.Replacer == nil {
return
}
m.Renderer().AddOptions(renderer.WithNodeRenderers(
util.Prioritized(r, 500),
))
}
// Options return initialized text replacer goldmark.Option.
func Options(oldnew ...string) goldmark.Option {
return goldmark.WithExtensions(New(oldnew...))
}