Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

d2target: add support for box arrowheads #2256

Merged
merged 4 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ci/release/changelogs/next.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
- Connections now support `link` [#1955](https://github.com/terrastruct/d2/pull/1955)
- Vars: vars in markdown blocks are substituted [#2218](https://github.com/terrastruct/d2/pull/2218)
- Markdown: Github-flavored tables work in `md` blocks [#2221](https://github.com/terrastruct/d2/pull/2221)
- Render: adds box arrowheads [#2227](https://github.com/terrastruct/d2/issues/2227)
- `d2 fmt` now supports a `--check` flag [#2253](https://github.com/terrastruct/d2/pull/2253)
- CLI: PNG output to stdout is supported using `--stdout-format png -` [#2291](https://github.com/terrastruct/d2/pull/2291)
- Globs: `&connected` and `&leaf` filters are implemented [#2299](https://github.com/terrastruct/d2/pull/2299)
Expand Down
16 changes: 16 additions & 0 deletions d2renderers/d2sketch/sketch.go
Original file line number Diff line number Diff line change
Expand Up @@ -840,6 +840,22 @@ func ArrowheadJS(r jsrunner.JSRunner, arrowhead d2target.Arrowhead, stroke strin
stroke,
BG_COLOR,
)
case d2target.BoxArrowhead:
arrowJS = fmt.Sprintf(
`node = rc.polygon(%s, { strokeWidth: %d, stroke: "%s", fill: "%s", fillStyle: "solid", seed: 1})`,
`[[0, -10], [0, 10], [-20, 10], [-20, -10]]`,
strokeWidth,
stroke,
BG_COLOR,
)
case d2target.FilledBoxArrowhead:
arrowJS = fmt.Sprintf(
`node = rc.polygon(%s, { strokeWidth: %d, stroke: "%s", fill: "%s", fillStyle: "solid", seed: 1})`,
`[[0, -10], [0, 10], [-20, 10], [-20, -10]]`,
strokeWidth,
stroke,
stroke,
)
}
return
}
Expand Down
14 changes: 14 additions & 0 deletions d2renderers/d2sketch/sketch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,20 @@ a.9 <-> b.9: cf-one-required {
source-arrowhead.shape: cf-one-required
target-arrowhead.shape: cf-one-required
}
a.10 <-> b.10: box {
source-arrowhead.shape: box
target-arrowhead.shape: box
}
a.11 <-> b.11: box-filled {
source-arrowhead: {
shape: box
style.filled: true
}
target-arrowhead: {
shape: box
style.filled: true
}
}
`,
},
{
Expand Down
178 changes: 92 additions & 86 deletions d2renderers/d2sketch/testdata/arrowheads/sketch.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
48 changes: 48 additions & 0 deletions d2renderers/d2svg/d2svg.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,54 @@ func arrowheadMarker(isTarget bool, id string, connection d2target.Connection, i
}

path = circleEl.Render()
case d2target.FilledBoxArrowhead:
polygonEl := d2themes.NewThemableElement("polygon", inlineTheme)
polygonEl.ClassName = "connection"
polygonEl.Fill = connection.Stroke
polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)

if isTarget {
polygonEl.Points = fmt.Sprintf("%f,%f %f,%f %f,%f %f,%f",
0., 0.,
0., height,
width, height,
width, 0.,
)
} else {
polygonEl.Points = fmt.Sprintf("%f,%f %f,%f %f,%f %f,%f",
0., 0.,
0., height,
width, height,
width, 0.,
alixander marked this conversation as resolved.
Show resolved Hide resolved
)
}

path = polygonEl.Render()
case d2target.BoxArrowhead:
polygonEl := d2themes.NewThemableElement("polygon", inlineTheme)
polygonEl.ClassName = "connection"
polygonEl.Fill = d2target.BG_COLOR
polygonEl.Stroke = connection.Stroke
polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
polygonEl.Style = fmt.Sprintf("%sstroke-linejoin:miter;", polygonEl.Style)

inset := strokeWidth / 2
if isTarget {
polygonEl.Points = fmt.Sprintf("%f,%f %f,%f %f,%f %f,%f",
inset, inset,
inset, height-inset,
width-inset, height-inset,
width-inset, inset,
)
} else {
polygonEl.Points = fmt.Sprintf("%f,%f %f,%f %f,%f %f,%f",
inset, inset,
inset, height-inset,
width-inset, height-inset,
width-inset, inset,
)
}
path = polygonEl.Render()
case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired:
offset := 3.0 + float64(connection.StrokeWidth)*1.8

Expand Down
13 changes: 13 additions & 0 deletions d2target/d2target.go
Original file line number Diff line number Diff line change
Expand Up @@ -755,6 +755,8 @@ const (
FilledDiamondArrowhead Arrowhead = "filled-diamond"
CircleArrowhead Arrowhead = "circle"
FilledCircleArrowhead Arrowhead = "filled-circle"
BoxArrowhead Arrowhead = "box"
FilledBoxArrowhead Arrowhead = "filled-box"

// For fat arrows
LineArrowhead Arrowhead = "line"
Expand All @@ -775,6 +777,7 @@ var Arrowheads = map[string]struct{}{
string(TriangleArrowhead): {},
string(DiamondArrowhead): {},
string(CircleArrowhead): {},
string(BoxArrowhead): {},
string(CfOne): {},
string(CfMany): {},
string(CfOneRequired): {},
Expand Down Expand Up @@ -802,6 +805,11 @@ func ToArrowhead(arrowheadType string, filled *bool) Arrowhead {
return UnfilledTriangleArrowhead
}
return TriangleArrowhead
case string(BoxArrowhead):
if filled != nil && *filled {
return FilledBoxArrowhead
}
return BoxArrowhead
case string(CfOne):
return CfOne
case string(CfMany):
Expand Down Expand Up @@ -856,6 +864,11 @@ func (arrowhead Arrowhead) Dimensions(strokeWidth float64) (width, height float6
baseHeight = 8
widthMultiplier = 5
heightMultiplier = 5
case FilledBoxArrowhead, BoxArrowhead:
baseWidth = 6
baseHeight = 6
widthMultiplier = 5
heightMultiplier = 5
case CfOne, CfMany, CfOneRequired, CfManyRequired:
baseWidth = 9
baseHeight = 9
Expand Down
23 changes: 23 additions & 0 deletions e2etests/stable_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2325,6 +2325,29 @@ c <-> d: filled-circle {
shape: circle
style.filled: true
}
}`,
},
{
name: "box_arrowhead",
script: `
a <-> b: box {
source-arrowhead: {
shape: box
}
target-arrowhead: {
shape: box
}
}

c <-> d: filled-box {
source-arrowhead: {
shape: box
style.filled: true
}
target-arrowhead: {
shape: box
style.filled: true
}
}`,
},
{
Expand Down
72 changes: 72 additions & 0 deletions e2etests/testdata/files/arrowhead_scaling.d2
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,78 @@ filled circle: {
}
}

box: {
start: ""
end: ""

start.1 <-> end.1: 1 {
style.stroke-width: 1
source-arrowhead.shape: box
target-arrowhead.shape: box
}
start.2 <-> end.2: 2 {
style.stroke-width: 2
source-arrowhead.shape: box
target-arrowhead.shape: box
}
start.4 <-> end.4: 4 {
style.stroke-width: 4
source-arrowhead.shape: box
target-arrowhead.shape: box
}
start.8 <-> end.8: 8 {
style.stroke-width: 8
source-arrowhead.shape: box
target-arrowhead.shape: box
}
start.15 <-> end.15: 15 {
style.stroke-width: 15
source-arrowhead.shape: box
target-arrowhead.shape: box
}
}

filled-box: {
start: ""
end: ""

start.1 <-> end.1: 1 {
style.stroke-width: 1
source-arrowhead.shape: box
target-arrowhead.shape: box
source-arrowhead.style.filled: true
target-arrowhead.style.filled: true
}
start.2 <-> end.2: 2 {
style.stroke-width: 2
source-arrowhead.shape: box
target-arrowhead.shape: box
source-arrowhead.style.filled: true
target-arrowhead.style.filled: true
}
start.4 <-> end.4: 4 {
style.stroke-width: 4
source-arrowhead.shape: box
target-arrowhead.shape: box
source-arrowhead.style.filled: true
target-arrowhead.style.filled: true
}
start.8 <-> end.8: 8 {
style.stroke-width: 8
source-arrowhead.shape: box
target-arrowhead.shape: box
source-arrowhead.style.filled: true
target-arrowhead.style.filled: true
}
start.15 <-> end.15: 15 {
style.stroke-width: 15
source-arrowhead.shape: box
target-arrowhead.shape: box
source-arrowhead.style.filled: true
target-arrowhead.style.filled: true
}
}

cf one: {
start: ""
end: ""
Expand Down
Loading