Skip to content
Open
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
@@ -1,4 +1,5 @@
#### Features 🚀
- Ability to fade background shape on multiple style [#2509](https://github.com/terrastruct/d2/pull/2509)

- `cross` arrowhead shape is available [#2190](https://github.com/terrastruct/d2/pull/2190)
- `style.underline` support for class fields and methods [#2544](https://github.com/terrastruct/d2/pull/2544)
Expand Down
1 change: 1 addition & 0 deletions d2ast/keywords.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ var CompositeReservedKeywords = map[string]struct{}{
"constraint": {},
"label": {},
"icon": {},
"multiple": {},
}

// StyleKeywords are reserved keywords which cannot exist outside of the "style" keyword
Expand Down
29 changes: 29 additions & 0 deletions d2compiler/compile.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,35 @@ func (c *compiler) compileStyleField(styles *d2graph.Style, f *d2ir.Field) {
c.errorf(f.LastRef().AST(), `invalid style keyword: "%s"`, f.Name.ScalarString())
return
}

if f.Map() != nil {
for _, ff := range f.Map().Fields {
if ff.Name.ScalarString() == "opacity" && ff.Name.IsUnquoted() {
if ff.Primary() == nil {
c.errorf(ff.LastPrimaryKey(), `invalid "opacity" field`)
} else {
scalar := ff.Primary().Value
switch f.Name.ScalarString() {
case "multiple":
styles.MultipleOpacity = &d2graph.Scalar{MapKey: f.LastPrimaryKey()}
err := styles.Apply(f.Name.ScalarString()+ff.Name.ScalarString(), scalar.ScalarString())
if err != nil {
c.errorf(scalar, err.Error())
return
}
default:
c.errorf(f.Name, `invalid "opacity" style for "%s"`, f.Name.ScalarString())
return
}
}
} else {
if ff.LastPrimaryKey() != nil {
c.errorf(ff.LastPrimaryKey(), `unexpected field %s`, ff.Name.ScalarString())
}
}
}
}
Comment on lines +760 to +786
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be a code smell to you that you need this much extra code. There's a more precise place to make these changes

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, we can simplify the process by modifying

d2/d2compiler/compile.go

Lines 788 to 792 in b2841d5

func (c *compiler) compileStyle(styles *d2graph.Style, m *d2ir.Map) {
for _, f := range m.Fields {
c.compileStyleField(styles, f)
}
}

as:

func (c *compiler) compileStyle(styles *d2graph.Style, m *d2ir.Map) {
	for _, f := range m.Fields {
		c.compileStyleField(styles, f)
		if f.Map() != nil {
			for _, ff := range f.Map().Fields {
				c.compileStyleField(styles, ff)
			}
		}
	}
}

However, as it’s not possible to get the parent field of a particular field, we need to pass a new parameter to

func (c *compiler) compileStyleField(styles *d2graph.Style, f *d2ir.Field) {

to identify the parent field for opacity.


if f.Primary() == nil {
return
}
Expand Down
3 changes: 3 additions & 0 deletions d2exporter/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ func applyStyles(shape *d2target.Shape, obj *d2graph.Object) {
if obj.Style.Multiple != nil {
shape.Multiple, _ = strconv.ParseBool(obj.Style.Multiple.Value)
}
if obj.Style.MultipleOpacity != nil {
shape.MultipleOpacity, _ = strconv.ParseFloat(obj.Style.MultipleOpacity.Value, 64)
}
if obj.Style.BorderRadius != nil {
shape.BorderRadius, _ = strconv.Atoi(obj.Style.BorderRadius.Value)
}
Expand Down
50 changes: 30 additions & 20 deletions d2graph/d2graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,26 +281,27 @@ func (r Reference) InEdge() bool {
}

type Style struct {
Opacity *Scalar `json:"opacity,omitempty"`
Stroke *Scalar `json:"stroke,omitempty"`
Fill *Scalar `json:"fill,omitempty"`
FillPattern *Scalar `json:"fillPattern,omitempty"`
StrokeWidth *Scalar `json:"strokeWidth,omitempty"`
StrokeDash *Scalar `json:"strokeDash,omitempty"`
BorderRadius *Scalar `json:"borderRadius,omitempty"`
Shadow *Scalar `json:"shadow,omitempty"`
ThreeDee *Scalar `json:"3d,omitempty"`
Multiple *Scalar `json:"multiple,omitempty"`
Font *Scalar `json:"font,omitempty"`
FontSize *Scalar `json:"fontSize,omitempty"`
FontColor *Scalar `json:"fontColor,omitempty"`
Animated *Scalar `json:"animated,omitempty"`
Bold *Scalar `json:"bold,omitempty"`
Italic *Scalar `json:"italic,omitempty"`
Underline *Scalar `json:"underline,omitempty"`
Filled *Scalar `json:"filled,omitempty"`
DoubleBorder *Scalar `json:"doubleBorder,omitempty"`
TextTransform *Scalar `json:"textTransform,omitempty"`
Opacity *Scalar `json:"opacity,omitempty"`
Stroke *Scalar `json:"stroke,omitempty"`
Fill *Scalar `json:"fill,omitempty"`
FillPattern *Scalar `json:"fillPattern,omitempty"`
StrokeWidth *Scalar `json:"strokeWidth,omitempty"`
StrokeDash *Scalar `json:"strokeDash,omitempty"`
BorderRadius *Scalar `json:"borderRadius,omitempty"`
Shadow *Scalar `json:"shadow,omitempty"`
ThreeDee *Scalar `json:"3d,omitempty"`
Multiple *Scalar `json:"multiple,omitempty"`
MultipleOpacity *Scalar `json:"multipleOpacity,omitempty"`
Font *Scalar `json:"font,omitempty"`
FontSize *Scalar `json:"fontSize,omitempty"`
FontColor *Scalar `json:"fontColor,omitempty"`
Animated *Scalar `json:"animated,omitempty"`
Bold *Scalar `json:"bold,omitempty"`
Italic *Scalar `json:"italic,omitempty"`
Underline *Scalar `json:"underline,omitempty"`
Filled *Scalar `json:"filled,omitempty"`
DoubleBorder *Scalar `json:"doubleBorder,omitempty"`
TextTransform *Scalar `json:"textTransform,omitempty"`
}

// NoneTextTransform will return a boolean if the text should not have any
Expand Down Expand Up @@ -486,6 +487,15 @@ func (s *Style) Apply(key, value string) error {
return fmt.Errorf(`expected "text-transform" to be one of (%s)`, strings.Join(d2ast.TextTransforms, ", "))
}
s.TextTransform.Value = value
case "multipleopacity":
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where does this come from?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we only have access to the key and value in the Apply function, if we pass only the "opacity" keyword as the key, there’s no way to distinguish whether it specifies the global-level opacity or multiple opacity.

if s.MultipleOpacity == nil {
break
}
f, err := strconv.ParseFloat(value, 64)
if err != nil || (f < 0 || f > 1) {
return errors.New(`expected "opacity" to be a number between 0.0 and 1.0`)
}
s.MultipleOpacity.Value = value
default:
return fmt.Errorf("unknown style key: %s", key)
}
Expand Down
2 changes: 1 addition & 1 deletion d2renderers/d2sketch/testdata/dots-multiple/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.
2 changes: 1 addition & 1 deletion d2renderers/d2sketch/testdata/dots-real/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.
2 changes: 1 addition & 1 deletion d2renderers/d2sketch/testdata/paper-real/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.
2 changes: 1 addition & 1 deletion d2renderers/d2sketch/testdata/terminal/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.
2 changes: 1 addition & 1 deletion d2renderers/d2sketch/testdata/twitter/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.
2 changes: 1 addition & 1 deletion d2renderers/d2sketch/testdata/twitter_dark/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.
17 changes: 11 additions & 6 deletions d2renderers/d2svg/d2svg.go
Original file line number Diff line number Diff line change
Expand Up @@ -1466,6 +1466,11 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
opacityStyle = fmt.Sprintf(" style='opacity:%f'", targetShape.Opacity)
}

multipleOpacityStyle := ""
if targetShape.MultipleOpacity != 1.0 {
multipleOpacityStyle = fmt.Sprintf(" opacity:%f", targetShape.MultipleOpacity)
}

// this clipPath must be defined outside `g` element
if targetShape.BorderRadius != 0 && (targetShape.Type == d2target.ShapeClass || targetShape.Type == d2target.ShapeSQLTable) {
fmt.Fprint(writer, clipPathForBorderRadius(diagramHash, targetShape))
Expand Down Expand Up @@ -1553,7 +1558,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
case d2target.ShapeOval:
if targetShape.DoubleBorder {
if targetShape.Multiple {
fmt.Fprint(writer, renderDoubleOval(multipleTL, width, height, fill, "", stroke, style, inlineTheme))
fmt.Fprint(writer, renderDoubleOval(multipleTL, width, height, fill, "", stroke, style+multipleOpacityStyle, inlineTheme))
}
if jsRunner != nil {
out, err := d2sketch.DoubleOval(jsRunner, targetShape)
Expand All @@ -1566,7 +1571,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
}
} else {
if targetShape.Multiple {
fmt.Fprint(writer, renderOval(multipleTL, width, height, fill, "", stroke, style, inlineTheme))
fmt.Fprint(writer, renderOval(multipleTL, width, height, fill, "", stroke, style+multipleOpacityStyle, inlineTheme))
}
if jsRunner != nil {
out, err := d2sketch.Oval(jsRunner, targetShape)
Expand Down Expand Up @@ -1612,7 +1617,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
el.Height = float64(targetShape.Height)
el.Fill = fill
el.Stroke = stroke
el.Style = style
el.Style = style + multipleOpacityStyle
el.Rx = borderRadius
fmt.Fprint(writer, el.Render())
}
Expand Down Expand Up @@ -1645,7 +1650,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
el.Fill = fill
el.FillPattern = targetShape.FillPattern
el.Stroke = stroke
el.Style = style
el.Style = style + multipleOpacityStyle
el.Rx = borderRadius
fmt.Fprint(writer, el.Render())

Expand Down Expand Up @@ -1701,7 +1706,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
el := d2themes.NewThemableElement("path", inlineTheme)
el.Fill = fill
el.Stroke = stroke
el.Style = style
el.Style = style + multipleOpacityStyle
for _, pathData := range multiplePathData {
el.D = pathData
fmt.Fprint(writer, el.Render())
Expand Down Expand Up @@ -1733,7 +1738,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
el := d2themes.NewThemableElement("path", inlineTheme)
el.Fill = fill
el.Stroke = stroke
el.Style = style
el.Style = style + multipleOpacityStyle
for _, pathData := range multiplePathData {
el.D = pathData
fmt.Fprint(writer, el.Render())
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 6 additions & 5 deletions d2target/d2target.go
Original file line number Diff line number Diff line change
Expand Up @@ -497,11 +497,12 @@ type Shape struct {
FillPattern string `json:"fillPattern,omitempty"`
Stroke string `json:"stroke"`

Animated bool `json:"animated"`
Shadow bool `json:"shadow"`
ThreeDee bool `json:"3d"`
Multiple bool `json:"multiple"`
DoubleBorder bool `json:"double-border"`
Animated bool `json:"animated"`
Shadow bool `json:"shadow"`
ThreeDee bool `json:"3d"`
Multiple bool `json:"multiple"`
MultipleOpacity float64 `json:"multipleOpacity,omitempty"`
DoubleBorder bool `json:"double-border"`

Tooltip string `json:"tooltip"`
Link string `json:"link"`
Expand Down
2 changes: 1 addition & 1 deletion e2etests-cli/testdata/TestCLI_E2E/theme-override.exp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion e2etests/testdata/patterns/multiple/dagre/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.
2 changes: 1 addition & 1 deletion e2etests/testdata/patterns/real-lines/dagre/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.
2 changes: 1 addition & 1 deletion e2etests/testdata/patterns/real/dagre/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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading