d2ir: replace substitutions in markdown
This commit is contained in:
parent
c3fbf873bf
commit
7e6a3d8132
10 changed files with 2452 additions and 40 deletions
|
|
@ -1,5 +1,7 @@
|
|||
#### Features 🚀
|
||||
|
||||
- Vars: vars in markdown blocks are substituted [#2218](https://github.com/terrastruct/d2/pull/2218)
|
||||
|
||||
#### Improvements 🧹
|
||||
|
||||
- Composition: links pointing to own board are purged [#2203](https://github.com/terrastruct/d2/pull/2203)
|
||||
|
|
|
|||
|
|
@ -2868,17 +2868,28 @@ x*: {
|
|||
{
|
||||
name: "var_in_markdown",
|
||||
text: `vars: {
|
||||
v: {
|
||||
ok
|
||||
}
|
||||
v: ok
|
||||
}
|
||||
|
||||
x: |md
|
||||
m${v}y
|
||||
|
||||
` + "`hey ${v}`" + `
|
||||
|
||||
regular markdown
|
||||
|
||||
` + "```" + `
|
||||
bye ${v}
|
||||
` + "```" + `
|
||||
|
|
||||
`,
|
||||
assertions: func(t *testing.T, g *d2graph.Graph) {
|
||||
tassert.Equal(t, "moky", g.Objects[0].Attributes.Label.Value)
|
||||
tassert.True(t, strings.Contains(g.Objects[0].Attributes.Label.Value, "moky"))
|
||||
tassert.False(t, strings.Contains(g.Objects[0].Attributes.Label.Value, "m${v}y"))
|
||||
// Code spans untouched
|
||||
tassert.True(t, strings.Contains(g.Objects[0].Attributes.Label.Value, "hey ${v}"))
|
||||
// Code blocks untouched
|
||||
tassert.True(t, strings.Contains(g.Objects[0].Attributes.Label.Value, "bye ${v}"))
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"oss.terrastruct.com/d2/d2parser"
|
||||
"oss.terrastruct.com/d2/d2themes"
|
||||
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
|
||||
"oss.terrastruct.com/d2/lib/textmeasure"
|
||||
)
|
||||
|
||||
type globContext struct {
|
||||
|
|
@ -342,10 +343,32 @@ func (c *compiler) resolveSubstitutions(varsStack []*Map, node Node) (removedFie
|
|||
if subbed {
|
||||
s.Coalesce()
|
||||
}
|
||||
case *d2ast.BlockString:
|
||||
variables := make(map[string]string)
|
||||
for _, vars := range varsStack {
|
||||
c.collectVariables(vars, variables)
|
||||
}
|
||||
preprocessedValue := textmeasure.ReplaceSubstitutionsMarkdown(s.Value, variables)
|
||||
|
||||
// Update the block string value
|
||||
s.Value = preprocessedValue
|
||||
}
|
||||
return removedField
|
||||
}
|
||||
|
||||
func (c *compiler) collectVariables(vars *Map, variables map[string]string) {
|
||||
if vars == nil {
|
||||
return
|
||||
}
|
||||
for _, f := range vars.Fields {
|
||||
if f.Primary() != nil {
|
||||
variables[f.Name] = f.Primary().Value.ScalarString()
|
||||
} else if f.Map() != nil {
|
||||
c.collectVariables(f.Map(), variables)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *compiler) resolveSubstitution(vars *Map, node Node, substitution *d2ast.Substitution, isCurrentScopeVars bool) *Field {
|
||||
if vars == nil {
|
||||
return nil
|
||||
|
|
|
|||
306
e2etests/testdata/txtar/var_in_markdown/dagre/board.exp.json
generated
vendored
Normal file
306
e2etests/testdata/txtar/var_in_markdown/dagre/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
{
|
||||
"name": "",
|
||||
"isFolderOnly": false,
|
||||
"fontFamily": "SourceSansPro",
|
||||
"shapes": [
|
||||
{
|
||||
"id": "x",
|
||||
"type": "rectangle",
|
||||
"pos": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"width": 81,
|
||||
"height": 66,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "B6",
|
||||
"stroke": "B1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "Kube",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 36,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "description",
|
||||
"type": "text",
|
||||
"pos": {
|
||||
"x": 86,
|
||||
"y": 166
|
||||
},
|
||||
"width": 163,
|
||||
"height": 96,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "transparent",
|
||||
"stroke": "N1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "Kube is a service\n\n```\nLet ${y} be ${x}\n```",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "markdown",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 163,
|
||||
"labelHeight": 96,
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"type": "rectangle",
|
||||
"pos": {
|
||||
"x": 141,
|
||||
"y": 0
|
||||
},
|
||||
"width": 53,
|
||||
"height": 66,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "B6",
|
||||
"stroke": "B1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "b",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 8,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "a",
|
||||
"type": "rectangle",
|
||||
"pos": {
|
||||
"x": 141,
|
||||
"y": 362
|
||||
},
|
||||
"width": 53,
|
||||
"height": 66,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "B6",
|
||||
"stroke": "B1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "a",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 8,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"id": "(b -> description)[0]",
|
||||
"src": "b",
|
||||
"srcArrow": "none",
|
||||
"dst": "description",
|
||||
"dstArrow": "triangle",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "B1",
|
||||
"borderRadius": 10,
|
||||
"label": "",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N2",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 0,
|
||||
"labelHeight": 0,
|
||||
"labelPosition": "",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 66
|
||||
},
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 106
|
||||
},
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 126
|
||||
},
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 166
|
||||
}
|
||||
],
|
||||
"isCurve": true,
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
},
|
||||
{
|
||||
"id": "(description -> a)[0]",
|
||||
"src": "description",
|
||||
"srcArrow": "none",
|
||||
"dst": "a",
|
||||
"dstArrow": "triangle",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "B1",
|
||||
"borderRadius": 10,
|
||||
"label": "",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N2",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 0,
|
||||
"labelHeight": 0,
|
||||
"labelPosition": "",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 262
|
||||
},
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 302
|
||||
},
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 322
|
||||
},
|
||||
{
|
||||
"x": 167.5,
|
||||
"y": 362
|
||||
}
|
||||
],
|
||||
"isCurve": true,
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
}
|
||||
],
|
||||
"root": {
|
||||
"id": "",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"opacity": 0,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 0,
|
||||
"borderRadius": 0,
|
||||
"fill": "N7",
|
||||
"stroke": "",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "",
|
||||
"fontSize": 0,
|
||||
"fontFamily": "",
|
||||
"language": "",
|
||||
"color": "",
|
||||
"italic": false,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 0,
|
||||
"labelHeight": 0,
|
||||
"zIndex": 0,
|
||||
"level": 0
|
||||
}
|
||||
}
|
||||
855
e2etests/testdata/txtar/var_in_markdown/dagre/sketch.exp.svg
vendored
Normal file
855
e2etests/testdata/txtar/var_in_markdown/dagre/sketch.exp.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 39 KiB |
288
e2etests/testdata/txtar/var_in_markdown/elk/board.exp.json
generated
vendored
Normal file
288
e2etests/testdata/txtar/var_in_markdown/elk/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,288 @@
|
|||
{
|
||||
"name": "",
|
||||
"isFolderOnly": false,
|
||||
"fontFamily": "SourceSansPro",
|
||||
"shapes": [
|
||||
{
|
||||
"id": "x",
|
||||
"type": "rectangle",
|
||||
"pos": {
|
||||
"x": 12,
|
||||
"y": 12
|
||||
},
|
||||
"width": 81,
|
||||
"height": 66,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "B6",
|
||||
"stroke": "B1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "Kube",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 36,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "description",
|
||||
"type": "text",
|
||||
"pos": {
|
||||
"x": 58,
|
||||
"y": 148
|
||||
},
|
||||
"width": 163,
|
||||
"height": 96,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "transparent",
|
||||
"stroke": "N1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "Kube is a service\n\n```\nLet ${y} be ${x}\n```",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "markdown",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 163,
|
||||
"labelHeight": 96,
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "b",
|
||||
"type": "rectangle",
|
||||
"pos": {
|
||||
"x": 113,
|
||||
"y": 12
|
||||
},
|
||||
"width": 53,
|
||||
"height": 66,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "B6",
|
||||
"stroke": "B1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "b",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 8,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
},
|
||||
{
|
||||
"id": "a",
|
||||
"type": "rectangle",
|
||||
"pos": {
|
||||
"x": 113,
|
||||
"y": 314
|
||||
},
|
||||
"width": 53,
|
||||
"height": 66,
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"borderRadius": 0,
|
||||
"fill": "B6",
|
||||
"stroke": "B1",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "a",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N1",
|
||||
"italic": false,
|
||||
"bold": true,
|
||||
"underline": false,
|
||||
"labelWidth": 8,
|
||||
"labelHeight": 21,
|
||||
"labelPosition": "INSIDE_MIDDLE_CENTER",
|
||||
"zIndex": 0,
|
||||
"level": 1
|
||||
}
|
||||
],
|
||||
"connections": [
|
||||
{
|
||||
"id": "(b -> description)[0]",
|
||||
"src": "b",
|
||||
"srcArrow": "none",
|
||||
"dst": "description",
|
||||
"dstArrow": "triangle",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "B1",
|
||||
"borderRadius": 10,
|
||||
"label": "",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N2",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 0,
|
||||
"labelHeight": 0,
|
||||
"labelPosition": "",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 139.5,
|
||||
"y": 78
|
||||
},
|
||||
{
|
||||
"x": 139.5,
|
||||
"y": 148
|
||||
}
|
||||
],
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
},
|
||||
{
|
||||
"id": "(description -> a)[0]",
|
||||
"src": "description",
|
||||
"srcArrow": "none",
|
||||
"dst": "a",
|
||||
"dstArrow": "triangle",
|
||||
"opacity": 1,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 2,
|
||||
"stroke": "B1",
|
||||
"borderRadius": 10,
|
||||
"label": "",
|
||||
"fontSize": 16,
|
||||
"fontFamily": "DEFAULT",
|
||||
"language": "",
|
||||
"color": "N2",
|
||||
"italic": true,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 0,
|
||||
"labelHeight": 0,
|
||||
"labelPosition": "",
|
||||
"labelPercentage": 0,
|
||||
"route": [
|
||||
{
|
||||
"x": 139.5,
|
||||
"y": 244
|
||||
},
|
||||
{
|
||||
"x": 139.5,
|
||||
"y": 314
|
||||
}
|
||||
],
|
||||
"animated": false,
|
||||
"tooltip": "",
|
||||
"icon": null,
|
||||
"zIndex": 0
|
||||
}
|
||||
],
|
||||
"root": {
|
||||
"id": "",
|
||||
"type": "",
|
||||
"pos": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"width": 0,
|
||||
"height": 0,
|
||||
"opacity": 0,
|
||||
"strokeDash": 0,
|
||||
"strokeWidth": 0,
|
||||
"borderRadius": 0,
|
||||
"fill": "N7",
|
||||
"stroke": "",
|
||||
"shadow": false,
|
||||
"3d": false,
|
||||
"multiple": false,
|
||||
"double-border": false,
|
||||
"tooltip": "",
|
||||
"link": "",
|
||||
"icon": null,
|
||||
"iconPosition": "",
|
||||
"blend": false,
|
||||
"fields": null,
|
||||
"methods": null,
|
||||
"columns": null,
|
||||
"label": "",
|
||||
"fontSize": 0,
|
||||
"fontFamily": "",
|
||||
"language": "",
|
||||
"color": "",
|
||||
"italic": false,
|
||||
"bold": false,
|
||||
"underline": false,
|
||||
"labelWidth": 0,
|
||||
"labelHeight": 0,
|
||||
"zIndex": 0,
|
||||
"level": 0
|
||||
}
|
||||
}
|
||||
855
e2etests/testdata/txtar/var_in_markdown/elk/sketch.exp.svg
vendored
Normal file
855
e2etests/testdata/txtar/var_in_markdown/elk/sketch.exp.svg
vendored
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 39 KiB |
|
|
@ -469,3 +469,17 @@ colors: {
|
|||
style.font-color: "linear-gradient(to bottom right, red 0%, yellow 25%, green 50%, cyan 75%, blue 100%)"
|
||||
}
|
||||
gradient -> colors
|
||||
|
||||
-- var_in_markdown --
|
||||
vars: {
|
||||
service-x: Kube
|
||||
}
|
||||
x: ${service-x}
|
||||
description: |md
|
||||
${service-x} is a service
|
||||
|
||||
```
|
||||
Let ${y} be ${x}
|
||||
```
|
||||
|
|
||||
b -> description -> a
|
||||
|
|
|
|||
77
lib/textmeasure/substitutions.go
Normal file
77
lib/textmeasure/substitutions.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
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
|
||||
}
|
||||
53
testdata/d2compiler/TestCompile/var_in_markdown.exp.json
generated
vendored
53
testdata/d2compiler/TestCompile/var_in_markdown.exp.json
generated
vendored
|
|
@ -3,11 +3,11 @@
|
|||
"name": "",
|
||||
"isFolderOnly": false,
|
||||
"ast": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-9:0:47",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-15:0:90",
|
||||
"nodes": [
|
||||
{
|
||||
"map_key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-4:1:27",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-2:1:17",
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-0:4:4",
|
||||
"path": [
|
||||
|
|
@ -27,11 +27,11 @@
|
|||
"primary": {},
|
||||
"value": {
|
||||
"map": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:6:6-4:1:27",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:6:6-2:1:17",
|
||||
"nodes": [
|
||||
{
|
||||
"map_key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:2:10-3:3:25",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:2:10-1:7:15",
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:2:10-1:3:11",
|
||||
"path": [
|
||||
|
|
@ -50,31 +50,12 @@
|
|||
},
|
||||
"primary": {},
|
||||
"value": {
|
||||
"map": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:5:13-3:3:25",
|
||||
"nodes": [
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:5:13-1:7:15",
|
||||
"value": [
|
||||
{
|
||||
"map_key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,2:4:19-2:6:21",
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,2:4:19-2:6:21",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,2:4:19-2:6:21",
|
||||
"value": [
|
||||
{
|
||||
"string": "ok",
|
||||
"raw_string": "ok"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"primary": {},
|
||||
"value": {}
|
||||
}
|
||||
"string": "ok",
|
||||
"raw_string": "ok"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -88,13 +69,13 @@
|
|||
},
|
||||
{
|
||||
"map_key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,6:0:29-8:1:46",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:0:19-14:1:89",
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,6:0:29-6:1:30",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:0:19-4:1:20",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,6:0:29-6:1:30",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:0:19-4:1:20",
|
||||
"value": [
|
||||
{
|
||||
"string": "x",
|
||||
|
|
@ -108,10 +89,10 @@
|
|||
"primary": {},
|
||||
"value": {
|
||||
"block_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,6:3:32-8:1:46",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:3:22-14:1:89",
|
||||
"quote": "",
|
||||
"tag": "md",
|
||||
"value": "m${v}y"
|
||||
"value": "moky\n\n`hey ${v}`\n\nregular markdown\n\n```\nbye ${v}\n```"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -149,11 +130,11 @@
|
|||
"references": [
|
||||
{
|
||||
"key": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,6:0:29-6:1:30",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:0:19-4:1:20",
|
||||
"path": [
|
||||
{
|
||||
"unquoted_string": {
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,6:0:29-6:1:30",
|
||||
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:0:19-4:1:20",
|
||||
"value": [
|
||||
{
|
||||
"string": "x",
|
||||
|
|
@ -170,7 +151,7 @@
|
|||
],
|
||||
"attributes": {
|
||||
"label": {
|
||||
"value": "m${v}y"
|
||||
"value": "moky\n\n`hey ${v}`\n\nregular markdown\n\n```\nbye ${v}\n```"
|
||||
},
|
||||
"labelDimensions": {
|
||||
"width": 0,
|
||||
|
|
|
|||
Loading…
Reference in a new issue