79 lines
1.6 KiB
Go
79 lines
1.6 KiB
Go
//go:build !wasm
|
|
|
|
package textmeasure
|
|
|
|
import (
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/yuin/goldmark/ast"
|
|
"github.com/yuin/goldmark/text"
|
|
)
|
|
|
|
func ReplaceSubstitutionsMarkdown(mdText string, variables map[string]string) string {
|
|
source := []byte(mdText)
|
|
reader := text.NewReader(source)
|
|
doc := markdownRenderer.Parser().Parse(reader)
|
|
|
|
type substitution struct {
|
|
start int
|
|
stop int
|
|
newVal string
|
|
}
|
|
var substitutions []substitution
|
|
|
|
ast.Walk(doc, func(n ast.Node, entering bool) (ast.WalkStatus, error) {
|
|
if !entering {
|
|
return ast.WalkContinue, nil
|
|
}
|
|
|
|
if isCodeNode(n) {
|
|
return ast.WalkSkipChildren, nil
|
|
}
|
|
|
|
if textNode, ok := n.(*ast.Text); ok {
|
|
segment := textNode.Segment
|
|
originalText := string(segment.Value(source))
|
|
newText := replaceVariables(originalText, variables)
|
|
|
|
if originalText != newText {
|
|
substitutions = append(substitutions, substitution{
|
|
start: segment.Start,
|
|
stop: segment.Stop,
|
|
newVal: newText,
|
|
})
|
|
}
|
|
}
|
|
return ast.WalkContinue, nil
|
|
})
|
|
|
|
if len(substitutions) == 0 {
|
|
return mdText
|
|
}
|
|
|
|
sort.Slice(substitutions, func(i, j int) bool {
|
|
return substitutions[i].start > substitutions[j].start
|
|
})
|
|
|
|
result := string(source)
|
|
for _, sub := range substitutions {
|
|
result = result[:sub.start] + sub.newVal + result[sub.stop:]
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func isCodeNode(n ast.Node) bool {
|
|
switch n.Kind() {
|
|
case ast.KindCodeBlock, ast.KindFencedCodeBlock, ast.KindCodeSpan:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func replaceVariables(s string, vars map[string]string) string {
|
|
for k, v := range vars {
|
|
s = strings.ReplaceAll(s, "${"+k+"}", v)
|
|
}
|
|
return s
|
|
}
|