Merge pull request #2218 from alixander/markdown-var
Replace substitutions in markdown
This commit is contained in:
commit
ad629356cb
10 changed files with 2623 additions and 0 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
#### Features 🚀
|
#### Features 🚀
|
||||||
|
|
||||||
|
- Vars: vars in markdown blocks are substituted [#2218](https://github.com/terrastruct/d2/pull/2218)
|
||||||
|
|
||||||
#### Improvements 🧹
|
#### Improvements 🧹
|
||||||
|
|
||||||
- Composition: links pointing to own board are purged [#2203](https://github.com/terrastruct/d2/pull/2203)
|
- Composition: links pointing to own board are purged [#2203](https://github.com/terrastruct/d2/pull/2203)
|
||||||
|
|
|
||||||
|
|
@ -2865,6 +2865,33 @@ x*: {
|
||||||
tassert.Equal(t, "x2.ok", g.Objects[3].AbsID())
|
tassert.Equal(t, "x2.ok", g.Objects[3].AbsID())
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "var_in_markdown",
|
||||||
|
text: `vars: {
|
||||||
|
v: ok
|
||||||
|
}
|
||||||
|
|
||||||
|
x: |md
|
||||||
|
m${v}y
|
||||||
|
|
||||||
|
` + "`hey ${v}`" + `
|
||||||
|
|
||||||
|
regular markdown
|
||||||
|
|
||||||
|
` + "```" + `
|
||||||
|
bye ${v}
|
||||||
|
` + "```" + `
|
||||||
|
|
|
||||||
|
`,
|
||||||
|
assertions: func(t *testing.T, g *d2graph.Graph) {
|
||||||
|
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}"))
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "var_in_vars",
|
name: "var_in_vars",
|
||||||
text: `vars: {
|
text: `vars: {
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"oss.terrastruct.com/d2/d2parser"
|
"oss.terrastruct.com/d2/d2parser"
|
||||||
"oss.terrastruct.com/d2/d2themes"
|
"oss.terrastruct.com/d2/d2themes"
|
||||||
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
|
"oss.terrastruct.com/d2/d2themes/d2themescatalog"
|
||||||
|
"oss.terrastruct.com/d2/lib/textmeasure"
|
||||||
)
|
)
|
||||||
|
|
||||||
type globContext struct {
|
type globContext struct {
|
||||||
|
|
@ -342,10 +343,32 @@ func (c *compiler) resolveSubstitutions(varsStack []*Map, node Node) (removedFie
|
||||||
if subbed {
|
if subbed {
|
||||||
s.Coalesce()
|
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
|
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 {
|
func (c *compiler) resolveSubstitution(vars *Map, node Node, substitution *d2ast.Substitution, isCurrentScopeVars bool) *Field {
|
||||||
if vars == nil {
|
if vars == nil {
|
||||||
return 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%)"
|
style.font-color: "linear-gradient(to bottom right, red 0%, yellow 25%, green 50%, cyan 75%, blue 100%)"
|
||||||
}
|
}
|
||||||
gradient -> colors
|
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
|
||||||
|
}
|
||||||
176
testdata/d2compiler/TestCompile/var_in_markdown.exp.json
generated
vendored
Normal file
176
testdata/d2compiler/TestCompile/var_in_markdown.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
||||||
|
{
|
||||||
|
"graph": {
|
||||||
|
"name": "",
|
||||||
|
"isFolderOnly": false,
|
||||||
|
"ast": {
|
||||||
|
"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-2:1:17",
|
||||||
|
"key": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-0:4:4",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"unquoted_string": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,0:0:0-0:4:4",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"string": "vars",
|
||||||
|
"raw_string": "vars"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"primary": {},
|
||||||
|
"value": {
|
||||||
|
"map": {
|
||||||
|
"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-1:7:15",
|
||||||
|
"key": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:2:10-1:3:11",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"unquoted_string": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:2:10-1:3:11",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"string": "v",
|
||||||
|
"raw_string": "v"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"primary": {},
|
||||||
|
"value": {
|
||||||
|
"unquoted_string": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,1:5:13-1:7:15",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"string": "ok",
|
||||||
|
"raw_string": "ok"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"map_key": {
|
||||||
|
"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,4:0:19-4:1:20",
|
||||||
|
"path": [
|
||||||
|
{
|
||||||
|
"unquoted_string": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:0:19-4:1:20",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"string": "x",
|
||||||
|
"raw_string": "x"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"primary": {},
|
||||||
|
"value": {
|
||||||
|
"block_string": {
|
||||||
|
"range": "d2/testdata/d2compiler/TestCompile/var_in_markdown.d2,4:3:22-14:1:89",
|
||||||
|
"quote": "",
|
||||||
|
"tag": "md",
|
||||||
|
"value": "moky\n\n`hey ${v}`\n\nregular markdown\n\n```\nbye ${v}\n```"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"id": "",
|
||||||
|
"id_val": "",
|
||||||
|
"attributes": {
|
||||||
|
"label": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"labelDimensions": {
|
||||||
|
"width": 0,
|
||||||
|
"height": 0
|
||||||
|
},
|
||||||
|
"style": {},
|
||||||
|
"near_key": null,
|
||||||
|
"shape": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"direction": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"constraint": null
|
||||||
|
},
|
||||||
|
"zIndex": 0
|
||||||
|
},
|
||||||
|
"edges": null,
|
||||||
|
"objects": [
|
||||||
|
{
|
||||||
|
"id": "x",
|
||||||
|
"id_val": "x",
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"key": {
|
||||||
|
"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,4:0:19-4:1:20",
|
||||||
|
"value": [
|
||||||
|
{
|
||||||
|
"string": "x",
|
||||||
|
"raw_string": "x"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"key_path_index": 0,
|
||||||
|
"map_key_edge_index": -1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"attributes": {
|
||||||
|
"label": {
|
||||||
|
"value": "moky\n\n`hey ${v}`\n\nregular markdown\n\n```\nbye ${v}\n```"
|
||||||
|
},
|
||||||
|
"labelDimensions": {
|
||||||
|
"width": 0,
|
||||||
|
"height": 0
|
||||||
|
},
|
||||||
|
"style": {},
|
||||||
|
"near_key": null,
|
||||||
|
"language": "markdown",
|
||||||
|
"shape": {
|
||||||
|
"value": "text"
|
||||||
|
},
|
||||||
|
"direction": {
|
||||||
|
"value": ""
|
||||||
|
},
|
||||||
|
"constraint": null
|
||||||
|
},
|
||||||
|
"zIndex": 0
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"err": null
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue