diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index f3c0d2a77..955808118 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -1,5 +1,5 @@ #### Features ๐Ÿš€ - +- Circle notation is now supported. [] #### Improvements ๐Ÿงน #### Bugfixes โ›‘๏ธ diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 678f0c2ae..91b18c54a 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -114,6 +114,12 @@ func arrowheadDimensions(arrowhead d2target.Arrowhead, strokeWidth float64) (wid case d2target.DiamondArrowhead: widthMultiplier = 11 heightMultiplier = 9 + case d2target.FilledCircleArrowhead: + widthMultiplier = 14 + heightMultiplier = 15 + case d2target.CircleArrowhead: + widthMultiplier = 14 + heightMultiplier = 15 case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired: widthMultiplier = 14 heightMultiplier = 15 @@ -224,6 +230,39 @@ func arrowheadMarker(isTarget bool, id string, connection d2target.Connection) s width*0.6, height*7/8, ) } + case d2target.FilledCircleArrowhead: + attrs := fmt.Sprintf(`class="connection" fill="%s" stroke-width="%d"`, connection.Stroke, connection.StrokeWidth) + offset := 4.0 + float64(connection.StrokeWidth*2) + if isTarget { + path = fmt.Sprintf(``, + attrs, + offset+9, height/2, + offset*1.2, + ) + } else { + path = fmt.Sprintf(``, + attrs, + offset+3, height/2, + offset*1.2, + ) + } + case d2target.CircleArrowhead: + attrs := fmt.Sprintf(`class="connection" fill="white" stroke="%s" stroke-width="%d"`, connection.Stroke, connection.StrokeWidth) + offset := 4.0 + float64(connection.StrokeWidth*2) + if isTarget { + path = fmt.Sprintf(``, + attrs, + offset+10, height/2, + offset*1.2, + ) + } else { + path = fmt.Sprintf(``, + attrs, + offset+6, height/2, + offset*1.2, + ) + } + case d2target.CfOne, d2target.CfMany, d2target.CfOneRequired, d2target.CfManyRequired: attrs := fmt.Sprintf(`class="connection" stroke="%s" stroke-width="%d" fill="white"`, connection.Stroke, connection.StrokeWidth) offset := 4.0 + float64(connection.StrokeWidth*2) @@ -277,6 +316,14 @@ func arrowheadMarker(isTarget bool, id string, connection d2target.Connection) s refX = width/8 + 0.6*strokeWidth } width *= 1.1 + + case d2target.CircleArrowhead: + if isTarget { + refX = width - 0.6*strokeWidth + } else { + refX = width/8 + 0.6*strokeWidth + } + width *= 1.1 default: if isTarget { refX = width - 1.5*strokeWidth diff --git a/d2target/d2target.go b/d2target/d2target.go index b426adfd9..b324e4ff6 100644 --- a/d2target/d2target.go +++ b/d2target/d2target.go @@ -277,6 +277,8 @@ const ( TriangleArrowhead Arrowhead = "triangle" DiamondArrowhead Arrowhead = "diamond" FilledDiamondArrowhead Arrowhead = "filled-diamond" + CircleArrowhead Arrowhead = "circle" + FilledCircleArrowhead Arrowhead = "circle-filled" // For fat arrows LineArrowhead Arrowhead = "line" @@ -294,6 +296,8 @@ var Arrowheads = map[string]struct{}{ string(TriangleArrowhead): {}, string(DiamondArrowhead): {}, string(FilledDiamondArrowhead): {}, + string(CircleArrowhead): {}, + string(FilledCircleArrowhead): {}, string(CfOne): {}, string(CfMany): {}, string(CfOneRequired): {}, @@ -307,6 +311,11 @@ func ToArrowhead(arrowheadType string, filled bool) Arrowhead { return FilledDiamondArrowhead } return DiamondArrowhead + case string(CircleArrowhead): + if filled { + return FilledCircleArrowhead + } + return CircleArrowhead case string(ArrowArrowhead): return ArrowArrowhead case string(CfOne): diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index a8acc138a..680a18045 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -1762,6 +1762,29 @@ e <--> f: { target-arrowhead: { shape: cf-one-required } +}`, + }, + { + name: "circle_arrowhead", + script: ` +a <-> b: circle { + source-arrowhead: { + shape: circle + } + target-arrowhead: { + shape: circle + } +} + +c <--> d: circle-filled { + source-arrowhead: { + shape: circle + style.filled: true + } + target-arrowhead: { + shape: circle + style.filled: true + } }`, }, }