language works for sequence diagram notes

This commit is contained in:
Alexander Wang 2024-08-02 08:01:26 -06:00
parent dd4e6bcf90
commit 44248e77eb
No known key found for this signature in database
GPG key ID: BE3937D0D52D8927
8 changed files with 2691 additions and 47 deletions

View file

@ -166,7 +166,7 @@ func toShape(obj *d2graph.Object, g *d2graph.Graph) d2target.Shape {
shape.Color = text.GetColor(shape.Italic)
applyStyles(shape, obj)
switch obj.Shape.Value {
switch strings.ToLower(obj.Shape.Value) {
case d2target.ShapeCode, d2target.ShapeText:
shape.Language = obj.Language
shape.Label = obj.Label.Value
@ -181,6 +181,10 @@ func toShape(obj *d2graph.Object, g *d2graph.Graph) d2target.Shape {
if obj.ContentAspectRatio != nil {
shape.ContentAspectRatio = go2.Pointer(*obj.ContentAspectRatio)
}
case d2target.ShapePage:
if obj.IsSequenceDiagramNote() {
shape.Language = obj.Language
}
}
shape.Label = text.Text
shape.LabelWidth = text.Dimensions.Width

View file

@ -583,8 +583,7 @@ func (obj *Object) GetFill() string {
func (obj *Object) GetStroke(dashGapSize interface{}) string {
shape := obj.Shape.Value
if strings.EqualFold(shape, d2target.ShapeCode) ||
strings.EqualFold(shape, d2target.ShapeText) {
if obj.Language != "" {
return color.N1
}
if strings.EqualFold(shape, d2target.ShapeClass) ||

View file

@ -1414,7 +1414,49 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
fontClass += " text-underline"
}
if targetShape.Type == d2target.ShapeCode {
if targetShape.Language == "latex" {
render, err := d2latex.Render(targetShape.Label)
if err != nil {
return labelMask, err
}
gEl := d2themes.NewThemableElement("g", inlineTheme)
gEl.SetTranslate(float64(box.TopLeft.X), float64(box.TopLeft.Y))
gEl.Color = targetShape.Stroke
gEl.Content = render
fmt.Fprint(writer, gEl.Render())
} else if targetShape.Language == "markdown" {
render, err := textmeasure.RenderMarkdown(targetShape.Label)
if err != nil {
return labelMask, err
}
fmt.Fprintf(writer, `<g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="%f" y="%f" width="%d" height="%d">`,
box.TopLeft.X, box.TopLeft.Y, targetShape.Width, targetShape.Height,
)
// we need the self closing form in this svg/xhtml context
render = strings.ReplaceAll(render, "<hr>", "<hr />")
mdEl := d2themes.NewThemableElement("div")
mdEl.ClassName = "md"
mdEl.Content = render
// We have to set with styles since within foreignObject, we're in html
// land and not SVG attributes
var styles []string
if targetShape.FontSize != textmeasure.MarkdownFontSize {
styles = append(styles, fmt.Sprintf("font-size:%vpx", targetShape.FontSize))
}
if targetShape.Fill != "" && targetShape.Fill != "transparent" {
styles = append(styles, fmt.Sprintf(`background-color:%s`, targetShape.Fill))
}
if !color.IsThemeColor(targetShape.Color) {
styles = append(styles, fmt.Sprintf(`color:%s`, targetShape.Color))
}
mdEl.Style = strings.Join(styles, ";")
fmt.Fprint(writer, mdEl.Render())
fmt.Fprint(writer, `</foreignObject></g>`)
} else if targetShape.Language != "" {
lexer := lexers.Get(targetShape.Language)
if lexer == nil {
lexer = lexers.Fallback
@ -1478,48 +1520,6 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
}
fmt.Fprint(writer, "</g></g>")
}
} else if targetShape.Type == d2target.ShapeText && targetShape.Language == "latex" {
render, err := d2latex.Render(targetShape.Label)
if err != nil {
return labelMask, err
}
gEl := d2themes.NewThemableElement("g", inlineTheme)
gEl.SetTranslate(float64(box.TopLeft.X), float64(box.TopLeft.Y))
gEl.Color = targetShape.Stroke
gEl.Content = render
fmt.Fprint(writer, gEl.Render())
} else if targetShape.Type == d2target.ShapeText && targetShape.Language != "" {
render, err := textmeasure.RenderMarkdown(targetShape.Label)
if err != nil {
return labelMask, err
}
fmt.Fprintf(writer, `<g><foreignObject requiredFeatures="http://www.w3.org/TR/SVG11/feature#Extensibility" x="%f" y="%f" width="%d" height="%d">`,
box.TopLeft.X, box.TopLeft.Y, targetShape.Width, targetShape.Height,
)
// we need the self closing form in this svg/xhtml context
render = strings.ReplaceAll(render, "<hr>", "<hr />")
mdEl := d2themes.NewThemableElement("div", inlineTheme)
mdEl.ClassName = "md"
mdEl.Content = render
// We have to set with styles since within foreignObject, we're in html
// land and not SVG attributes
var styles []string
if targetShape.FontSize != textmeasure.MarkdownFontSize {
styles = append(styles, fmt.Sprintf("font-size:%vpx", targetShape.FontSize))
}
if targetShape.Fill != "" && targetShape.Fill != "transparent" {
styles = append(styles, fmt.Sprintf(`background-color:%s`, targetShape.Fill))
}
if !color.IsThemeColor(targetShape.Color) {
styles = append(styles, fmt.Sprintf(`color:%s`, targetShape.Color))
}
mdEl.Style = strings.Join(styles, ";")
fmt.Fprint(writer, mdEl.Render())
fmt.Fprint(writer, `</foreignObject></g>`)
} else {
if targetShape.LabelFill != "" {
rectEl := d2themes.NewThemableElement("rect", inlineTheme)
@ -2075,7 +2075,7 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
hasMarkdown := false
for _, s := range diagram.Shapes {
if s.Label != "" && s.Type == d2target.ShapeText {
if s.Language == "markdown" {
hasMarkdown = true
break
}

View file

@ -0,0 +1,368 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "x",
"type": "rectangle",
"pos": {
"x": 12,
"y": 52
},
"width": 100,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"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": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "y",
"type": "rectangle",
"pos": {
"x": 242,
"y": 52
},
"width": 100,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"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": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "x.x",
"type": "page",
"pos": {
"x": -128,
"y": 258
},
"width": 380,
"height": 119,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"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": "## A man who fishes for marlin in ponds\n\n- ...dramatic pause\n\nwill put his money in Etruscan bonds.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 380,
"labelHeight": 119,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 2
},
{
"id": "y.z",
"type": "page",
"pos": {
"x": 211,
"y": 447
},
"width": 162,
"height": 41,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"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": "\\\\lim_{h \\\\rightarrow 0 } \\\\frac{f(x+h)-f(x)}{h}",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "latex",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 162,
"labelHeight": 41,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 2
},
{
"id": "x.z",
"type": "page",
"pos": {
"x": 10,
"y": 558
},
"width": 103,
"height": 37,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"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": "1 + 1 = 2",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "python",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 87,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 2
}
],
"connections": [
{
"id": "(x -> y)[0]",
"src": "x",
"srcArrow": "none",
"dst": "y",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "hello",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 33,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 62,
"y": 188
},
{
"x": 292,
"y": 188
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 4
},
{
"id": "(x -- )[0]",
"src": "x",
"srcArrow": "none",
"dst": "x-lifeline-end-1678191278",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"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": 62,
"y": 118
},
{
"x": 62,
"y": 665
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
},
{
"id": "(y -- )[0]",
"src": "y",
"srcArrow": "none",
"dst": "y-lifeline-end-35261543",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"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": 292,
"y": 118
},
{
"x": 292,
"y": 665
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
}
],
"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
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

View file

@ -0,0 +1,368 @@
{
"name": "",
"isFolderOnly": false,
"fontFamily": "SourceSansPro",
"shapes": [
{
"id": "x",
"type": "rectangle",
"pos": {
"x": 12,
"y": 52
},
"width": 100,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"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": "x",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 7,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "y",
"type": "rectangle",
"pos": {
"x": 242,
"y": 52
},
"width": 100,
"height": 66,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "B5",
"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": "y",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 8,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 0,
"level": 1
},
{
"id": "x.x",
"type": "page",
"pos": {
"x": -128,
"y": 258
},
"width": 380,
"height": 119,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"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": "## A man who fishes for marlin in ponds\n\n- ...dramatic pause\n\nwill put his money in Etruscan bonds.",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "markdown",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 380,
"labelHeight": 119,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 2
},
{
"id": "y.z",
"type": "page",
"pos": {
"x": 211,
"y": 447
},
"width": 162,
"height": 41,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"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": "\\\\lim_{h \\\\rightarrow 0 } \\\\frac{f(x+h)-f(x)}{h}",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "latex",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 162,
"labelHeight": 41,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 2
},
{
"id": "x.z",
"type": "page",
"pos": {
"x": 10,
"y": 558
},
"width": 103,
"height": 37,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"borderRadius": 0,
"fill": "N7",
"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": "1 + 1 = 2",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "python",
"color": "N1",
"italic": false,
"bold": false,
"underline": false,
"labelWidth": 87,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"zIndex": 5,
"level": 2
}
],
"connections": [
{
"id": "(x -> y)[0]",
"src": "x",
"srcArrow": "none",
"dst": "y",
"dstArrow": "triangle",
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
"stroke": "B1",
"borderRadius": 10,
"label": "hello",
"fontSize": 16,
"fontFamily": "DEFAULT",
"language": "",
"color": "N2",
"italic": true,
"bold": false,
"underline": false,
"labelWidth": 33,
"labelHeight": 21,
"labelPosition": "INSIDE_MIDDLE_CENTER",
"labelPercentage": 0,
"route": [
{
"x": 62,
"y": 188
},
{
"x": 292,
"y": 188
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 4
},
{
"id": "(x -- )[0]",
"src": "x",
"srcArrow": "none",
"dst": "x-lifeline-end-1678191278",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"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": 62,
"y": 118
},
{
"x": 62,
"y": 665
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
},
{
"id": "(y -- )[0]",
"src": "y",
"srcArrow": "none",
"dst": "y-lifeline-end-35261543",
"dstArrow": "none",
"opacity": 1,
"strokeDash": 6,
"strokeWidth": 2,
"stroke": "B2",
"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": 292,
"y": 118
},
{
"x": 292,
"y": 665
}
],
"animated": false,
"tooltip": "",
"icon": null,
"zIndex": 1
}
],
"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
}
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 62 KiB

View file

@ -805,3 +805,176 @@ softwareSystem -> externalSystem
}
# Include all connections/objects connected to an object
(** -> externalSystem)[*]: unsuspend
-- sequence-diagram-note-md --
shape: sequence_diagram
x -> y: hello
x.x: |md
## A man who fishes for marlin in ponds
- ...dramatic pause
will put his money in Etruscan bonds.
|
y.z: |latex
\\lim_{h \\rightarrow 0 } \\frac{f(x+h)-f(x)}{h}
|
x.z: |python
1 + 1 = 2
|
-- md-label --
rectangle.shape: rectangle
rectangle: |md
# hello
- world
blah blah
|
square.shape: square
square: |md
# hello
- world
blah blah
|
page.shape: page
page: |md
# hello
- world
blah blah
|
parallelogram.shape: parallelogram
parallelogram: |md
# hello
- world
blah blah
|
document.shape: document
document: |md
# hello
- world
blah blah
|
cylinder.shape: cylinder
cylinder: |md
# hello
- world
blah blah
|
queue.shape: queue
queue: |md
# hello
- world
blah blah
|
package.shape: package
package: |md
# hello
- world
blah blah
|
step.shape: step
step: |md
# hello
- world
blah blah
|
callout.shape: callout
callout: |md
# hello
- world
blah blah
|
stored_data.shape: stored_data
stored_data: |md
# hello
- world
blah blah
|
person.shape: person
person: |md
# hello
- world
blah blah
|
diamond.shape: diamond
diamond: |md
# hello
- world
blah blah
|
oval.shape: oval
oval: |md
# hello
- world
blah blah
|
circle.shape: circle
circle: |md
# hello
- world
blah blah
|
hexagon.shape: hexagon
hexagon: |md
# hello
- world
blah blah
|
cloud.shape: cloud
cloud: |md
# hello
- world
blah blah
|