fix sketch tests, better trigger system

This commit is contained in:
Vojtěch Fošnár 2023-02-19 14:26:24 +01:00
parent 331cf95284
commit 46766d0f04
No known key found for this signature in database
GPG key ID: 657727E71C40859A
295 changed files with 4385 additions and 4696 deletions

File diff suppressed because one or more lines are too long

View file

@ -14,6 +14,7 @@ import (
tassert "github.com/stretchr/testify/assert" tassert "github.com/stretchr/testify/assert"
"oss.terrastruct.com/util-go/assert" "oss.terrastruct.com/util-go/assert"
"oss.terrastruct.com/util-go/diff"
"oss.terrastruct.com/util-go/go2" "oss.terrastruct.com/util-go/go2"
"oss.terrastruct.com/d2/d2layouts/d2dagrelayout" "oss.terrastruct.com/d2/d2layouts/d2dagrelayout"
@ -558,4 +559,7 @@ func run(t *testing.T, tc testCase) {
var xmlParsed interface{} var xmlParsed interface{}
err = xml.Unmarshal(svgBytes, &xmlParsed) err = xml.Unmarshal(svgBytes, &xmlParsed)
assert.Success(t, err) assert.Success(t, err)
err = diff.Testdata(filepath.Join(dataPath, "sketch"), ".svg", svgBytes)
assert.Success(t, err)
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 386 KiB

After

Width:  |  Height:  |  Size: 298 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 284 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 405 KiB

After

Width:  |  Height:  |  Size: 334 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 228 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 296 KiB

After

Width:  |  Height:  |  Size: 280 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 227 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 277 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 301 KiB

After

Width:  |  Height:  |  Size: 333 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 357 KiB

After

Width:  |  Height:  |  Size: 340 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 229 KiB

After

Width:  |  Height:  |  Size: 229 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 115 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 513 KiB

After

Width:  |  Height:  |  Size: 419 KiB

View file

@ -16,7 +16,7 @@ func classHeader(shape d2target.Shape, box *geo.Box, text string, textWidth, tex
rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y
rectEl.Width, rectEl.Height = box.Width, box.Height rectEl.Width, rectEl.Height = box.Width, box.Height
rectEl.Fill = shape.Fill rectEl.Fill = shape.Fill
rectEl.Class = "class_header" rectEl.ClassName = "class_header"
str := rectEl.Render() str := rectEl.Render()
if text != "" { if text != "" {
@ -31,7 +31,7 @@ func classHeader(shape d2target.Shape, box *geo.Box, text string, textWidth, tex
textEl.X = tl.X + textWidth/2 textEl.X = tl.X + textWidth/2
textEl.Y = tl.Y + textHeight*3/4 textEl.Y = tl.Y + textHeight*3/4
textEl.Fill = shape.Stroke textEl.Fill = shape.Stroke
textEl.Class = "text-mono" textEl.ClassName = "text-mono"
textEl.Style = fmt.Sprintf(`text-anchor:%s;font-size:%vpx;`, textEl.Style = fmt.Sprintf(`text-anchor:%s;font-size:%vpx;`,
"middle", 4+fontSize, "middle", 4+fontSize,
) )
@ -61,7 +61,7 @@ func classRow(shape d2target.Shape, box *geo.Box, prefix, nameText, typeText str
textEl.X = prefixTL.X textEl.X = prefixTL.X
textEl.Y = prefixTL.Y + fontSize*3/4 textEl.Y = prefixTL.Y + fontSize*3/4
textEl.Fill = shape.PrimaryAccentColor textEl.Fill = shape.PrimaryAccentColor
textEl.Class = "text-mono" textEl.ClassName = "text-mono"
textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "start", fontSize) textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "start", fontSize)
textEl.Content = prefix textEl.Content = prefix
out := textEl.Render() out := textEl.Render()

View file

@ -84,7 +84,7 @@ func arrowheadMarkerID(isTarget bool, connection d2target.Connection) string {
} }
return fmt.Sprintf("mk-%s", hash(fmt.Sprintf("%s,%t,%d,%s", return fmt.Sprintf("mk-%s", hash(fmt.Sprintf("%s,%t,%d,%s",
arrowhead, isTarget, connection.StrokeWidth, d2themes.ConnectionTheme(connection), arrowhead, isTarget, connection.StrokeWidth, connection.Stroke,
))) )))
} }
@ -131,8 +131,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
switch arrowhead { switch arrowhead {
case d2target.ArrowArrowhead: case d2target.ArrowArrowhead:
polygonEl := d2themes.NewThemableElement("polygon") polygonEl := d2themes.NewThemableElement("polygon")
polygonEl.Fill = d2themes.ConnectionTheme(connection) polygonEl.Fill = connection.Stroke
polygonEl.Class = "connection" polygonEl.ClassName = "connection"
polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
if isTarget { if isTarget {
@ -153,8 +153,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
path = polygonEl.Render() path = polygonEl.Render()
case d2target.TriangleArrowhead: case d2target.TriangleArrowhead:
polygonEl := d2themes.NewThemableElement("polygon") polygonEl := d2themes.NewThemableElement("polygon")
polygonEl.Fill = d2themes.ConnectionTheme(connection) polygonEl.Fill = connection.Stroke
polygonEl.Class = "connection" polygonEl.ClassName = "connection"
polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
if isTarget { if isTarget {
@ -174,8 +174,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
case d2target.LineArrowhead: case d2target.LineArrowhead:
polylineEl := d2themes.NewThemableElement("polyline") polylineEl := d2themes.NewThemableElement("polyline")
polylineEl.Fill = color.None polylineEl.Fill = color.None
polylineEl.Class = "connection" polylineEl.ClassName = "connection"
polylineEl.Stroke = d2themes.ConnectionTheme(connection) polylineEl.Stroke = connection.Stroke
polylineEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) polylineEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
if isTarget { if isTarget {
@ -194,8 +194,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
path = polylineEl.Render() path = polylineEl.Render()
case d2target.FilledDiamondArrowhead: case d2target.FilledDiamondArrowhead:
polygonEl := d2themes.NewThemableElement("polygon") polygonEl := d2themes.NewThemableElement("polygon")
polygonEl.Class = "connection" polygonEl.ClassName = "connection"
polygonEl.Fill = d2themes.ConnectionTheme(connection) polygonEl.Fill = connection.Stroke
polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
if isTarget { if isTarget {
@ -216,9 +216,9 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
path = polygonEl.Render() path = polygonEl.Render()
case d2target.DiamondArrowhead: case d2target.DiamondArrowhead:
polygonEl := d2themes.NewThemableElement("polygon") polygonEl := d2themes.NewThemableElement("polygon")
polygonEl.Class = "connection" polygonEl.ClassName = "connection"
polygonEl.Fill = bgColor polygonEl.Fill = bgColor
polygonEl.Stroke = d2themes.ConnectionTheme(connection) polygonEl.Stroke = connection.Stroke
polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) polygonEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
if isTarget { if isTarget {
@ -244,7 +244,7 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
circleEl.Cy = radius circleEl.Cy = radius
circleEl.R = radius - strokeWidth/2 // @alixander says there maybe should be a plus sign instead circleEl.R = radius - strokeWidth/2 // @alixander says there maybe should be a plus sign instead
circleEl.Fill = connection.Stroke circleEl.Fill = connection.Stroke
circleEl.Class = "connection" circleEl.ClassName = "connection"
circleEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) circleEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
if isTarget { if isTarget {
@ -282,8 +282,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
offset, height, offset, height,
) )
modifierEl.Fill = bgColor modifierEl.Fill = bgColor
modifierEl.Stroke = d2themes.ConnectionTheme(connection) modifierEl.Stroke = connection.Stroke
modifierEl.Class = "connection" modifierEl.ClassName = "connection"
modifierEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) modifierEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
} else { } else {
modifierEl = d2themes.NewThemableElement("circle") modifierEl = d2themes.NewThemableElement("circle")
@ -291,8 +291,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
modifierEl.Cy = height / 2.0 modifierEl.Cy = height / 2.0
modifierEl.R = offset / 2.0 modifierEl.R = offset / 2.0
modifierEl.Fill = bgColor modifierEl.Fill = bgColor
modifierEl.Stroke = d2themes.ConnectionTheme(connection) modifierEl.Stroke = connection.Stroke
modifierEl.Class = "connection" modifierEl.ClassName = "connection"
modifierEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) modifierEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
} }
@ -320,8 +320,8 @@ func arrowheadMarker(isTarget bool, id string, bgColor string, connection d2targ
gEl.Transform = fmt.Sprintf("scale(-1) translate(-%f, -%f)", width, height) gEl.Transform = fmt.Sprintf("scale(-1) translate(-%f, -%f)", width, height)
} }
gEl.Fill = bgColor gEl.Fill = bgColor
gEl.Stroke = d2themes.ConnectionTheme(connection) gEl.Stroke = connection.Stroke
gEl.Class = "connection" gEl.ClassName = "connection"
gEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth) gEl.Attributes = fmt.Sprintf(`stroke-width="%d"`, connection.StrokeWidth)
gEl.Content = fmt.Sprintf("%s%s", gEl.Content = fmt.Sprintf("%s%s",
modifierEl.Render(), childPathEl.Render(), modifierEl.Render(), childPathEl.Render(),
@ -545,8 +545,8 @@ func drawConnection(writer io.Writer, bgColor string, fgColor string, labelMaskI
pathEl := d2themes.NewThemableElement("path") pathEl := d2themes.NewThemableElement("path")
pathEl.D = path pathEl.D = path
pathEl.Fill = color.None pathEl.Fill = color.None
pathEl.Stroke = d2themes.ConnectionTheme(connection) pathEl.Stroke = connection.Stroke
pathEl.Class = fmt.Sprintf("connection%s", animatedClass) pathEl.ClassName = fmt.Sprintf("connection%s", animatedClass)
pathEl.Style = connection.CSSStyle() pathEl.Style = connection.CSSStyle()
pathEl.Attributes = fmt.Sprintf("%s%s%s", markerStart, markerEnd, mask) pathEl.Attributes = fmt.Sprintf("%s%s%s", markerStart, markerEnd, mask)
fmt.Fprint(writer, pathEl.Render()) fmt.Fprint(writer, pathEl.Render())
@ -576,7 +576,7 @@ func drawConnection(writer io.Writer, bgColor string, fgColor string, labelMaskI
textEl.X = labelTL.X + float64(connection.LabelWidth)/2 textEl.X = labelTL.X + float64(connection.LabelWidth)/2
textEl.Y = labelTL.Y + float64(connection.FontSize) textEl.Y = labelTL.Y + float64(connection.FontSize)
textEl.Fill = fontColor textEl.Fill = fontColor
textEl.Class = fontClass textEl.ClassName = fontClass
textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "middle", connection.FontSize) textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "middle", connection.FontSize)
textEl.Content = RenderText(connection.Label, textEl.X, float64(connection.LabelHeight)) textEl.Content = RenderText(connection.Label, textEl.X, float64(connection.LabelHeight))
fmt.Fprint(writer, textEl.Render()) fmt.Fprint(writer, textEl.Render())
@ -612,7 +612,7 @@ func renderArrowheadLabel(fgColor string, connection d2target.Connection, text s
textEl.X = labelTL.X + width/2 textEl.X = labelTL.X + width/2
textEl.Y = labelTL.Y + float64(connection.FontSize) textEl.Y = labelTL.Y + float64(connection.FontSize)
textEl.Fill = fgColor textEl.Fill = fgColor
textEl.Class = "text-italic" textEl.ClassName = "text-italic"
textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "middle", connection.FontSize) textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "middle", connection.FontSize)
textEl.Content = RenderText(text, textEl.X, height) textEl.Content = RenderText(text, textEl.X, height)
return textEl.Render() return textEl.Render()
@ -625,7 +625,7 @@ func renderOval(tl *geo.Point, width, height float64, fill, stroke, style string
el.Cx = tl.X + el.Rx el.Cx = tl.X + el.Rx
el.Cy = tl.Y + el.Ry el.Cy = tl.Y + el.Ry
el.Fill, el.Stroke = fill, stroke el.Fill, el.Stroke = fill, stroke
el.Class = "shape" el.ClassName = "shape"
el.Style = style el.Style = style
return el.Render() return el.Render()
} }
@ -707,7 +707,7 @@ func render3dRect(targetShape d2target.Shape) string {
mainShape.Y = float64(targetShape.Pos.Y) mainShape.Y = float64(targetShape.Pos.Y)
mainShape.Width = float64(targetShape.Width) mainShape.Width = float64(targetShape.Width)
mainShape.Height = float64(targetShape.Height) mainShape.Height = float64(targetShape.Height)
mainShape.Mask = fmt.Sprintf("url(#%s)", maskID) mainShape.SetMaskUrl(maskID)
mainShapeFill, _ := d2themes.ShapeTheme(targetShape) mainShapeFill, _ := d2themes.ShapeTheme(targetShape)
mainShape.Fill = mainShapeFill mainShape.Fill = mainShapeFill
mainShape.Stroke = color.None mainShape.Stroke = color.None
@ -736,7 +736,7 @@ func render3dRect(targetShape d2target.Shape) string {
sideShape := d2themes.NewThemableElement("polygon") sideShape := d2themes.NewThemableElement("polygon")
sideShape.Fill = darkerColor sideShape.Fill = darkerColor
sideShape.Points = strings.Join(sidePoints, " ") sideShape.Points = strings.Join(sidePoints, " ")
sideShape.Mask = fmt.Sprintf("url(#%s)", maskID) sideShape.SetMaskUrl(maskID)
sideShape.Style = targetShape.CSSStyle() sideShape.Style = targetShape.CSSStyle()
renderedSides := sideShape.Render() renderedSides := sideShape.Render()
@ -1062,7 +1062,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
rectEl.Width = float64(targetShape.Width) rectEl.Width = float64(targetShape.Width)
rectEl.Height = float64(targetShape.Height) rectEl.Height = float64(targetShape.Height)
rectEl.Stroke = targetShape.Stroke rectEl.Stroke = targetShape.Stroke
rectEl.Class = "shape" rectEl.ClassName = "shape"
rectEl.Style = fmt.Sprintf(`fill:%s`, style.Get(chroma.Background).Background.String()) rectEl.Style = fmt.Sprintf(`fill:%s`, style.Get(chroma.Background).Background.String())
fmt.Fprint(writer, rectEl.Render()) fmt.Fprint(writer, rectEl.Render())
// Padding // Padding
@ -1105,7 +1105,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
mdEl := d2themes.NewThemableElement("div") mdEl := d2themes.NewThemableElement("div")
mdEl.Xmlns = "http://www.w3.org/1999/xhtml" mdEl.Xmlns = "http://www.w3.org/1999/xhtml"
mdEl.Class = "md" mdEl.ClassName = "md"
mdEl.Content = render mdEl.Content = render
fmt.Fprint(writer, mdEl.Render()) fmt.Fprint(writer, mdEl.Render())
fmt.Fprint(writer, `</foreignObject></g>`) fmt.Fprint(writer, `</foreignObject></g>`)
@ -1128,7 +1128,7 @@ func drawShape(writer io.Writer, targetShape d2target.Shape, sketchRunner *d2ske
// text is vertically positioned at its baseline which is at labelTL+FontSize // text is vertically positioned at its baseline which is at labelTL+FontSize
textEl.Y = labelTL.Y + float64(targetShape.FontSize) textEl.Y = labelTL.Y + float64(targetShape.FontSize)
textEl.Fill = fontColor textEl.Fill = fontColor
textEl.Class = fontClass textEl.ClassName = fontClass
textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "middle", targetShape.FontSize) textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "middle", targetShape.FontSize)
textEl.Content = RenderText(targetShape.Label, textEl.X, float64(targetShape.LabelHeight)) textEl.Content = RenderText(targetShape.Label, textEl.X, float64(targetShape.LabelHeight))
fmt.Fprint(writer, textEl.Render()) fmt.Fprint(writer, textEl.Render())
@ -1186,19 +1186,18 @@ func RenderText(text string, x, height float64) string {
return strings.Join(rendered, "") return strings.Join(rendered, "")
} }
func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string { func embedFonts(buf *bytes.Buffer, source string, fontFamily *d2fonts.FontFamily) {
content := buf.String() fmt.Fprint(buf, `<style type="text/css"><![CDATA[`)
out := `<style type="text/css"><![CDATA[`
triggers := []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text"`, `class="text"`,
`class="text `, `class="text `,
`class="md"`, `class="md"`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
out += fmt.Sprintf(`
.text { .text {
font-family: "font-regular"; font-family: "font-regular";
} }
@ -1206,65 +1205,58 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-regular; font-family: font-regular;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[fontFamily.Font(0, d2fonts.FONT_STYLE_REGULAR)]) d2fonts.FontEncodings[fontFamily.Font(0, d2fonts.FONT_STYLE_REGULAR)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`text-underline`, `text-underline`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
.text-underline { .text-underline {
text-decoration: underline; text-decoration: underline;
}` }`,
break )
}
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`animated-connection`, `animated-connection`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
@keyframes dashdraw { @keyframes dashdraw {
from { from {
stroke-dashoffset: 0; stroke-dashoffset: 0;
} }
} }
` `,
break )
}
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`appendix-icon`, `appendix-icon`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
.appendix-icon { .appendix-icon {
filter: drop-shadow(0px 0px 32px rgba(31, 36, 58, 0.1)); filter: drop-shadow(0px 0px 32px rgba(31, 36, 58, 0.1));
}` }`,
break )
}
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-bold`, `class="text-bold`,
`<b>`, `<b>`,
`<strong>`, `<strong>`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
out += fmt.Sprintf(`
.text-bold { .text-bold {
font-family: "font-bold"; font-family: "font-bold";
} }
@ -1272,20 +1264,19 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-bold; font-family: font-bold;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[fontFamily.Font(0, d2fonts.FONT_STYLE_BOLD)]) d2fonts.FontEncodings[fontFamily.Font(0, d2fonts.FONT_STYLE_BOLD)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-italic`, `class="text-italic`,
`<em>`, `<em>`,
`<dfn>`, `<dfn>`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
out += fmt.Sprintf(`
.text-italic { .text-italic {
font-family: "font-italic"; font-family: "font-italic";
} }
@ -1293,22 +1284,21 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-italic; font-family: font-italic;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[fontFamily.Font(0, d2fonts.FONT_STYLE_ITALIC)]) d2fonts.FontEncodings[fontFamily.Font(0, d2fonts.FONT_STYLE_ITALIC)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-mono`, `class="text-mono`,
`<pre>`, `<pre>`,
`<code>`, `<code>`,
`<kbd>`, `<kbd>`,
`<samp>`, `<samp>`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
out += fmt.Sprintf(`
.text-mono { .text-mono {
font-family: "font-mono"; font-family: "font-mono";
} }
@ -1316,18 +1306,17 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-mono; font-family: font-mono;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_REGULAR)]) d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_REGULAR)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-mono-bold"`, `class="text-mono-bold"`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
fmt.Fprintf(buf, `
.text-mono-bold { .text-mono-bold {
font-family: "font-mono-bold"; font-family: "font-mono-bold";
} }
@ -1335,18 +1324,17 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-mono-bold; font-family: font-mono-bold;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_BOLD)]) d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_BOLD)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-mono-italic"`, `class="text-mono-italic"`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
fmt.Fprintf(buf, `
.text-mono-italic { .text-mono-italic {
font-family: "font-mono-italic"; font-family: "font-mono-italic";
} }
@ -1354,18 +1342,17 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-mono-italic; font-family: font-mono-italic;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_ITALIC)]) d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_ITALIC)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-mono-bold"`, `class="text-mono-bold"`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
fmt.Fprintf(buf, `
.text-mono-bold { .text-mono-bold {
font-family: "font-mono-bold"; font-family: "font-mono-bold";
} }
@ -1373,18 +1360,17 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-mono-bold; font-family: font-mono-bold;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_BOLD)]) d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_BOLD)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`class="text-mono-italic"`, `class="text-mono-italic"`,
} },
fmt.Sprintf(`
for _, t := range triggers {
if strings.Contains(content, t) {
fmt.Fprintf(buf, `
.text-mono-italic { .text-mono-italic {
font-family: "font-mono-italic"; font-family: "font-mono-italic";
} }
@ -1392,73 +1378,72 @@ func embedFonts(buf *bytes.Buffer, fontFamily *d2fonts.FontFamily) string {
font-family: font-mono-italic; font-family: font-mono-italic;
src: url("%s"); src: url("%s");
}`, }`,
d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_ITALIC)]) d2fonts.FontEncodings[d2fonts.SourceCodePro.Font(0, d2fonts.FONT_STYLE_ITALIC)],
break ),
} )
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`sketch-overlay-bright`, `sketch-overlay-bright`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
.sketch-overlay-bright { .sketch-overlay-bright {
fill: url(#streaks-bright); fill: url(#streaks-bright);
mix-blend-mode: darken; mix-blend-mode: darken;
}` }`,
break )
}
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`sketch-overlay-normal`, `sketch-overlay-normal`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
.sketch-overlay-normal { .sketch-overlay-normal {
fill: url(#streaks-normal); fill: url(#streaks-normal);
mix-blend-mode: color-burn; mix-blend-mode: color-burn;
}` }`,
break )
}
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`sketch-overlay-dark`, `sketch-overlay-dark`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
.sketch-overlay-dark { .sketch-overlay-dark {
fill: url(#streaks-dark); fill: url(#streaks-dark);
mix-blend-mode: overlay; mix-blend-mode: overlay;
}` }`,
break )
}
}
triggers = []string{ appendOnTrigger(
buf,
source,
[]string{
`sketch-overlay-darker`, `sketch-overlay-darker`,
} },
`
for _, t := range triggers {
if strings.Contains(content, t) {
out += `
.sketch-overlay-darker { .sketch-overlay-darker {
fill: url(#streaks-darker); fill: url(#streaks-darker);
mix-blend-mode: lighten; mix-blend-mode: lighten;
}` }`,
)
fmt.Fprint(buf, `]]></style>`)
}
func appendOnTrigger(buf *bytes.Buffer, source string, triggers []string, newContent string) {
for _, trigger := range triggers {
if strings.Contains(source, trigger) {
fmt.Fprint(buf, newContent)
break break
} }
} }
out += `]]></style>`
return out
} }
//go:embed fitToScreen.js //go:embed fitToScreen.js
@ -1568,14 +1553,15 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
backgroundEl.Fill = color.N7 backgroundEl.Fill = color.N7
// generate elements that will be appended to the SVG tag // generate elements that will be appended to the SVG tag
upperBuf := &bytes.Buffer{}
themeStylesheet, err := themeCSS(themeID, darkThemeID) themeStylesheet, err := themeCSS(themeID, darkThemeID)
if err != nil { if err != nil {
return nil, err return nil, err
} }
svgOut := fmt.Sprintf(`<style type="text/css"><![CDATA[%s%s]]></style>`, baseStylesheet, themeStylesheet) fmt.Fprintf(upperBuf, `<style type="text/css"><![CDATA[%s%s]]></style>`, baseStylesheet, themeStylesheet)
// this script won't run in --watch mode because script tags are ignored when added via el.innerHTML = element // this script won't run in --watch mode because script tags are ignored when added via el.innerHTML = element
// https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML // https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
svgOut += fmt.Sprintf(`<script type="application/javascript"><![CDATA[%s]]></script>`, fitToScreenScript) fmt.Fprintf(upperBuf, `<script type="application/javascript"><![CDATA[%s]]></script>`, fitToScreenScript)
hasMarkdown := false hasMarkdown := false
for _, s := range diagram.Shapes { for _, s := range diagram.Shapes {
if s.Label != "" && s.Type == d2target.ShapeText { if s.Label != "" && s.Type == d2target.ShapeText {
@ -1584,17 +1570,16 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
} }
} }
if hasMarkdown { if hasMarkdown {
svgOut += fmt.Sprintf(`<style type="text/css">%s</style>`, mdCSS) fmt.Fprintf(upperBuf, `<style type="text/css">%s</style>`, mdCSS)
} }
embedFonts(upperBuf, buf.String(), diagram.FontFamily) // embedFonts *must* run before d2sketch.DefineFillPatterns
if sketchRunner != nil { if sketchRunner != nil {
svgOut += d2sketch.DefineFillPatterns() d2sketch.DefineFillPatterns(upperBuf)
} }
svgOut += embedFonts(buf, diagram.FontFamily)
// render the document
docRendered := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?><svg id="d2-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="%d" height="%d" viewBox="%d %d %d %d">%s%s%s</svg>`, docRendered := fmt.Sprintf(`<?xml version="1.0" encoding="utf-8"?><svg id="d2-svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="%d" height="%d" viewBox="%d %d %d %d">%s%s%s</svg>`,
w, h, left, top, w, h, w, h, left, top, w, h,
svgOut, upperBuf.String(),
backgroundEl.Render(), backgroundEl.Render(),
buf.String(), buf.String(),
) )

View file

@ -17,7 +17,7 @@ func tableHeader(shape d2target.Shape, box *geo.Box, text string, textWidth, tex
rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y
rectEl.Width, rectEl.Height = box.Width, box.Height rectEl.Width, rectEl.Height = box.Width, box.Height
rectEl.Fill = shape.Fill rectEl.Fill = shape.Fill
rectEl.Class = "class_header" rectEl.ClassName = "class_header"
str := rectEl.Render() str := rectEl.Render()
if text != "" { if text != "" {
@ -32,7 +32,7 @@ func tableHeader(shape d2target.Shape, box *geo.Box, text string, textWidth, tex
textEl.X = tl.X textEl.X = tl.X
textEl.Y = tl.Y + textHeight*3/4 textEl.Y = tl.Y + textHeight*3/4
textEl.Fill = shape.Stroke textEl.Fill = shape.Stroke
textEl.Class = "text" textEl.ClassName = "text"
textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx",
"start", 4+fontSize, "start", 4+fontSize,
) )
@ -62,7 +62,7 @@ func tableRow(shape d2target.Shape, box *geo.Box, nameText, typeText, constraint
textEl.X = nameTL.X textEl.X = nameTL.X
textEl.Y = nameTL.Y + fontSize*3/4 textEl.Y = nameTL.Y + fontSize*3/4
textEl.Fill = shape.PrimaryAccentColor textEl.Fill = shape.PrimaryAccentColor
textEl.Class = "text" textEl.ClassName = "text"
textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "start", fontSize) textEl.Style = fmt.Sprintf("text-anchor:%s;font-size:%vpx", "start", fontSize)
textEl.Content = svg.EscapeText(nameText) textEl.Content = svg.EscapeText(nameText)
out := textEl.Render() out := textEl.Render()
@ -89,7 +89,7 @@ func drawTable(writer io.Writer, targetShape d2target.Shape) {
rectEl.Width = float64(targetShape.Width) rectEl.Width = float64(targetShape.Width)
rectEl.Height = float64(targetShape.Height) rectEl.Height = float64(targetShape.Height)
rectEl.Fill, rectEl.Stroke = d2themes.ShapeTheme(targetShape) rectEl.Fill, rectEl.Stroke = d2themes.ShapeTheme(targetShape)
rectEl.Class = "shape" rectEl.ClassName = "shape"
rectEl.Style = targetShape.CSSStyle() rectEl.Style = targetShape.CSSStyle()
fmt.Fprint(writer, rectEl.Render()) fmt.Fprint(writer, rectEl.Render())

View file

@ -17,7 +17,3 @@ func ShapeTheme(shape d2target.Shape) (fill, stroke string) {
} }
return fill, stroke return fill, stroke
} }
func ConnectionTheme(connection d2target.Connection) (stroke string) {
return connection.Stroke
}

View file

@ -40,7 +40,7 @@ type ThemableElement struct {
BackgroundColor string BackgroundColor string
Color string Color string
Class string ClassName string
Style string Style string
Attributes string Attributes string
@ -84,6 +84,10 @@ func (el *ThemableElement) SetTranslate(x, y float64) {
el.Transform = fmt.Sprintf("translate(%f %f)", x, y) el.Transform = fmt.Sprintf("translate(%f %f)", x, y)
} }
func (el *ThemableElement) SetMaskUrl(url string) {
el.Mask = fmt.Sprintf("url(#%s)", url)
}
func (el *ThemableElement) Render() string { func (el *ThemableElement) Render() string {
out := "<" + el.tag out := "<" + el.tag
@ -146,7 +150,7 @@ func (el *ThemableElement) Render() string {
out += fmt.Sprintf(` xmlns="%s"`, el.Xmlns) out += fmt.Sprintf(` xmlns="%s"`, el.Xmlns)
} }
class := el.Class class := el.ClassName
style := el.Style style := el.Style
// Add class {property}-{theme color} if the color is from a theme, set the property otherwise // Add class {property}-{theme color} if the color is from a theme, set the property otherwise

View file

@ -21,13 +21,13 @@ func NewThemableSketchOverlay(el *ThemableElement, fill string) *ThemableSketchO
// WARNING: Do not reuse the element afterwards as this function changes the Class propery // WARNING: Do not reuse the element afterwards as this function changes the Class propery
func (o *ThemableSketchOverlay) Render() (string, error) { func (o *ThemableSketchOverlay) Render() (string, error) {
if color.IsThemeColor(o.fill) { if color.IsThemeColor(o.fill) {
o.el.Class += fmt.Sprintf(" sketch-overlay-%s", o.fill) // e.g. sketch-overlay-B3 o.el.ClassName += fmt.Sprintf(" sketch-overlay-%s", o.fill) // e.g. sketch-overlay-B3
} else { } else {
lc, err := color.LuminanceCategory(o.fill) lc, err := color.LuminanceCategory(o.fill)
if err != nil { if err != nil {
return "", err return "", err
} }
o.el.Class += fmt.Sprintf(" sketch-overlay-%s", lc) // e.g. sketch-overlay-dark o.el.ClassName += fmt.Sprintf(" sketch-overlay-%s", lc) // e.g. sketch-overlay-dark
} }
return o.el.Render(), nil return o.el.Render(), nil

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 519 KiB

After

Width:  |  Height:  |  Size: 519 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 519 KiB

After

Width:  |  Height:  |  Size: 519 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 694 KiB

After

Width:  |  Height:  |  Size: 694 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 694 KiB

After

Width:  |  Height:  |  Size: 694 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 842 KiB

After

Width:  |  Height:  |  Size: 842 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 842 KiB

After

Width:  |  Height:  |  Size: 842 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 849 KiB

After

Width:  |  Height:  |  Size: 849 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 849 KiB

After

Width:  |  Height:  |  Size: 849 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 695 KiB

After

Width:  |  Height:  |  Size: 695 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 694 KiB

After

Width:  |  Height:  |  Size: 694 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 694 KiB

After

Width:  |  Height:  |  Size: 695 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 694 KiB

After

Width:  |  Height:  |  Size: 694 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1 MiB

After

Width:  |  Height:  |  Size: 1 MiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 1 MiB

After

Width:  |  Height:  |  Size: 1 MiB