d2/lib/textmeasure/substitutions.go
Alexander Wang 2a561265c1
add wasm tag
2024-12-29 09:50:18 -07:00

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
}