fix empty labels with class & sql_tables w/ premeasured texts
This commit is contained in:
parent
5abde05b86
commit
5059085f3c
9 changed files with 339 additions and 12 deletions
|
|
@ -707,6 +707,9 @@ func (obj *Object) GetLabelSize(mtexts []*d2target.MText, ruler *textmeasure.Rul
|
||||||
}
|
}
|
||||||
|
|
||||||
if dims == nil {
|
if dims == nil {
|
||||||
|
if obj.Text().Text == "" {
|
||||||
|
return d2target.NewTextDimensions(0, 0), nil
|
||||||
|
}
|
||||||
if shapeType == d2target.ShapeImage {
|
if shapeType == d2target.ShapeImage {
|
||||||
dims = d2target.NewTextDimensions(0, 0)
|
dims = d2target.NewTextDimensions(0, 0)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -728,7 +731,7 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
|
||||||
return d2target.NewTextDimensions(128, 128), nil
|
return d2target.NewTextDimensions(128, 128), nil
|
||||||
|
|
||||||
case d2target.ShapeClass:
|
case d2target.ShapeClass:
|
||||||
maxWidth := labelDims.Width
|
maxWidth := go2.Max(12, labelDims.Width)
|
||||||
|
|
||||||
for _, f := range obj.Class.Fields {
|
for _, f := range obj.Class.Fields {
|
||||||
fdims := GetTextDimensions(mtexts, ruler, f.Text(), go2.Pointer(d2fonts.SourceCodePro))
|
fdims := GetTextDimensions(mtexts, ruler, f.Text(), go2.Pointer(d2fonts.SourceCodePro))
|
||||||
|
|
@ -764,7 +767,7 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
|
||||||
rowHeight := GetTextDimensions(mtexts, ruler, anyRowText, go2.Pointer(d2fonts.SourceCodePro)).Height + 20
|
rowHeight := GetTextDimensions(mtexts, ruler, anyRowText, go2.Pointer(d2fonts.SourceCodePro)).Height + 20
|
||||||
dims.Height = rowHeight * (len(obj.Class.Fields) + len(obj.Class.Methods) + 2)
|
dims.Height = rowHeight * (len(obj.Class.Fields) + len(obj.Class.Methods) + 2)
|
||||||
} else {
|
} else {
|
||||||
dims.Height = labelDims.Height
|
dims.Height = go2.Max(12, labelDims.Height)
|
||||||
}
|
}
|
||||||
|
|
||||||
case d2target.ShapeSQLTable:
|
case d2target.ShapeSQLTable:
|
||||||
|
|
@ -804,10 +807,10 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R
|
||||||
}
|
}
|
||||||
|
|
||||||
// The rows get padded a little due to header font being larger than row font
|
// The rows get padded a little due to header font being larger than row font
|
||||||
dims.Height = labelDims.Height * (len(obj.SQLTable.Columns) + 1)
|
dims.Height = go2.Max(12, labelDims.Height*(len(obj.SQLTable.Columns)+1))
|
||||||
headerWidth := d2target.HeaderPadding + labelDims.Width + d2target.HeaderPadding
|
headerWidth := d2target.HeaderPadding + labelDims.Width + d2target.HeaderPadding
|
||||||
rowsWidth := d2target.NamePadding + maxNameWidth + d2target.TypePadding + maxTypeWidth + d2target.TypePadding + constraintWidth
|
rowsWidth := d2target.NamePadding + maxNameWidth + d2target.TypePadding + maxTypeWidth + d2target.TypePadding + constraintWidth
|
||||||
dims.Width = go2.Max(headerWidth, rowsWidth)
|
dims.Width = go2.Max(12, go2.Max(headerWidth, rowsWidth))
|
||||||
}
|
}
|
||||||
|
|
||||||
return &dims, nil
|
return &dims, nil
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ func TestE2E(t *testing.T) {
|
||||||
t.Run("stable", testStable)
|
t.Run("stable", testStable)
|
||||||
t.Run("regression", testRegression)
|
t.Run("regression", testRegression)
|
||||||
t.Run("todo", testTodo)
|
t.Run("todo", testTodo)
|
||||||
|
t.Run("measured", testMeasured)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSanity(t *testing.T) {
|
func testSanity(t *testing.T) {
|
||||||
|
|
@ -73,6 +74,7 @@ a -> c
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
script string
|
script string
|
||||||
|
mtexts []*d2target.MText
|
||||||
assertions func(t *testing.T, diagram *d2target.Diagram)
|
assertions func(t *testing.T, diagram *d2target.Diagram)
|
||||||
skip bool
|
skip bool
|
||||||
}
|
}
|
||||||
|
|
@ -118,12 +120,16 @@ func run(t *testing.T, tc testCase) {
|
||||||
ctx = log.WithTB(ctx, t, nil)
|
ctx = log.WithTB(ctx, t, nil)
|
||||||
ctx = log.Leveled(ctx, slog.LevelDebug)
|
ctx = log.Leveled(ctx, slog.LevelDebug)
|
||||||
|
|
||||||
ruler, err := textmeasure.NewRuler()
|
var ruler *textmeasure.Ruler
|
||||||
|
var err error
|
||||||
|
if tc.mtexts == nil {
|
||||||
|
ruler, err = textmeasure.NewRuler()
|
||||||
if !tassert.Nil(t, err) {
|
if !tassert.Nil(t, err) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
serde(t, tc, ruler)
|
serde(t, tc, ruler)
|
||||||
|
}
|
||||||
|
|
||||||
layoutsTested := []string{"dagre", "elk"}
|
layoutsTested := []string{"dagre", "elk"}
|
||||||
|
|
||||||
|
|
@ -132,10 +138,15 @@ func run(t *testing.T, tc testCase) {
|
||||||
if layoutName == "dagre" {
|
if layoutName == "dagre" {
|
||||||
layout = d2dagrelayout.DefaultLayout
|
layout = d2dagrelayout.DefaultLayout
|
||||||
} else if layoutName == "elk" {
|
} else if layoutName == "elk" {
|
||||||
|
// If measured texts exists, we are specifically exercising text measurements, no need to run on both layouts
|
||||||
|
if tc.mtexts != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
layout = d2elklayout.DefaultLayout
|
layout = d2elklayout.DefaultLayout
|
||||||
}
|
}
|
||||||
diagram, _, err := d2lib.Compile(ctx, tc.script, &d2lib.CompileOptions{
|
diagram, _, err := d2lib.Compile(ctx, tc.script, &d2lib.CompileOptions{
|
||||||
Ruler: ruler,
|
Ruler: ruler,
|
||||||
|
MeasuredTexts: tc.mtexts,
|
||||||
ThemeID: 0,
|
ThemeID: 0,
|
||||||
Layout: layout,
|
Layout: layout,
|
||||||
})
|
})
|
||||||
|
|
|
||||||
34
e2etests/measured_test.go
Normal file
34
e2etests/measured_test.go
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package e2etests
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"oss.terrastruct.com/d2/d2target"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testMeasured exercises the code paths that provide pre-measured texts
|
||||||
|
func testMeasured(t *testing.T) {
|
||||||
|
tcs := []testCase{
|
||||||
|
{
|
||||||
|
name: "empty-shape",
|
||||||
|
mtexts: []*d2target.MText{},
|
||||||
|
script: `a: ""
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty-class",
|
||||||
|
mtexts: []*d2target.MText{},
|
||||||
|
script: `a: "" { shape: class }
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty-sql_table",
|
||||||
|
mtexts: []*d2target.MText{},
|
||||||
|
script: `a: "" { shape: sql_table }
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runa(t, tcs)
|
||||||
|
}
|
||||||
49
e2etests/testdata/measured/empty-class/dagre/board.exp.json
generated
vendored
Normal file
49
e2etests/testdata/measured/empty-class/dagre/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"fontFamily": "SourceSansPro",
|
||||||
|
"shapes": [
|
||||||
|
{
|
||||||
|
"id": "a",
|
||||||
|
"type": "class",
|
||||||
|
"pos": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"width": 112,
|
||||||
|
"height": 12,
|
||||||
|
"opacity": 1,
|
||||||
|
"strokeDash": 0,
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"borderRadius": 0,
|
||||||
|
"fill": "#0A0F25",
|
||||||
|
"stroke": "#FFFFFF",
|
||||||
|
"shadow": false,
|
||||||
|
"3d": false,
|
||||||
|
"multiple": false,
|
||||||
|
"tooltip": "",
|
||||||
|
"link": "",
|
||||||
|
"icon": null,
|
||||||
|
"iconPosition": "",
|
||||||
|
"blend": false,
|
||||||
|
"fields": null,
|
||||||
|
"methods": null,
|
||||||
|
"columns": null,
|
||||||
|
"label": "",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": "DEFAULT",
|
||||||
|
"language": "",
|
||||||
|
"color": "#0A0F25",
|
||||||
|
"italic": false,
|
||||||
|
"bold": false,
|
||||||
|
"underline": false,
|
||||||
|
"labelWidth": 0,
|
||||||
|
"labelHeight": 0,
|
||||||
|
"zIndex": 0,
|
||||||
|
"level": 1,
|
||||||
|
"primaryAccentColor": "#0D32B2",
|
||||||
|
"secondaryAccentColor": "#4A6FF3",
|
||||||
|
"neutralAccentColor": "#676C7E"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": []
|
||||||
|
}
|
||||||
45
e2etests/testdata/measured/empty-class/dagre/sketch.exp.svg
vendored
Normal file
45
e2etests/testdata/measured/empty-class/dagre/sketch.exp.svg
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg
|
||||||
|
id="d2-svg"
|
||||||
|
style="background: white;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="316" height="216" viewBox="-102 -102 316 216"><style type="text/css">
|
||||||
|
<![CDATA[
|
||||||
|
.shape {
|
||||||
|
shape-rendering: geometricPrecision;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.connection {
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.blend {
|
||||||
|
mix-blend-mode: multiply;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</style><script type="application/javascript"><![CDATA[window.addEventListener("DOMContentLoaded", () => {
|
||||||
|
if (document.documentElement.getAttribute("id") !== "d2-svg") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const svgEl = document.documentElement;
|
||||||
|
let width = parseInt(svgEl.getAttribute("width"), 10);
|
||||||
|
let height = parseInt(svgEl.getAttribute("height"), 10);
|
||||||
|
let ratio;
|
||||||
|
if (width > height) {
|
||||||
|
if (width > window.innerWidth) {
|
||||||
|
ratio = window.innerWidth / width;
|
||||||
|
}
|
||||||
|
} else if (height > window.innerHeight) {
|
||||||
|
ratio = window.innerHeight / height;
|
||||||
|
}
|
||||||
|
if (ratio) {
|
||||||
|
svgEl.setAttribute("width", width * ratio - 16);
|
||||||
|
svgEl.setAttribute("height", height * ratio - 16);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
]]></script><g id="a"><g class="shape" ><rect class="shape" x="0" y="0" width="112" height="12" style="fill:#FFFFFF;stroke:#0A0F25;stroke-width:2;"/><rect class="class_header" x="0.000000" y="0.000000" width="112.000000" height="12.000000" fill="#0A0F25" /><line x1="0.000000" y1="12.000000" x2="112.000000" y2="12.000000" style="stroke-width:1;stroke:#0A0F25" /></g></g><mask id="2115119125" maskUnits="userSpaceOnUse" x="-100" y="-100" width="316" height="216">
|
||||||
|
<rect x="-100" y="-100" width="316" height="216" fill="white"></rect>
|
||||||
|
|
||||||
|
</mask><style type="text/css"><![CDATA[]]></style></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
46
e2etests/testdata/measured/empty-shape/dagre/board.exp.json
generated
vendored
Normal file
46
e2etests/testdata/measured/empty-shape/dagre/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"fontFamily": "SourceSansPro",
|
||||||
|
"shapes": [
|
||||||
|
{
|
||||||
|
"id": "a",
|
||||||
|
"type": "",
|
||||||
|
"pos": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"width": 100,
|
||||||
|
"height": 100,
|
||||||
|
"opacity": 1,
|
||||||
|
"strokeDash": 0,
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"borderRadius": 0,
|
||||||
|
"fill": "#F7F8FE",
|
||||||
|
"stroke": "#0D32B2",
|
||||||
|
"shadow": false,
|
||||||
|
"3d": false,
|
||||||
|
"multiple": false,
|
||||||
|
"tooltip": "",
|
||||||
|
"link": "",
|
||||||
|
"icon": null,
|
||||||
|
"iconPosition": "",
|
||||||
|
"blend": false,
|
||||||
|
"fields": null,
|
||||||
|
"methods": null,
|
||||||
|
"columns": null,
|
||||||
|
"label": "",
|
||||||
|
"fontSize": 16,
|
||||||
|
"fontFamily": "DEFAULT",
|
||||||
|
"language": "",
|
||||||
|
"color": "#0A0F25",
|
||||||
|
"italic": false,
|
||||||
|
"bold": true,
|
||||||
|
"underline": false,
|
||||||
|
"labelWidth": 0,
|
||||||
|
"labelHeight": 0,
|
||||||
|
"zIndex": 0,
|
||||||
|
"level": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": []
|
||||||
|
}
|
||||||
45
e2etests/testdata/measured/empty-shape/dagre/sketch.exp.svg
vendored
Normal file
45
e2etests/testdata/measured/empty-shape/dagre/sketch.exp.svg
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg
|
||||||
|
id="d2-svg"
|
||||||
|
style="background: white;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="304" height="304" viewBox="-102 -102 304 304"><style type="text/css">
|
||||||
|
<![CDATA[
|
||||||
|
.shape {
|
||||||
|
shape-rendering: geometricPrecision;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.connection {
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.blend {
|
||||||
|
mix-blend-mode: multiply;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</style><script type="application/javascript"><![CDATA[window.addEventListener("DOMContentLoaded", () => {
|
||||||
|
if (document.documentElement.getAttribute("id") !== "d2-svg") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const svgEl = document.documentElement;
|
||||||
|
let width = parseInt(svgEl.getAttribute("width"), 10);
|
||||||
|
let height = parseInt(svgEl.getAttribute("height"), 10);
|
||||||
|
let ratio;
|
||||||
|
if (width > height) {
|
||||||
|
if (width > window.innerWidth) {
|
||||||
|
ratio = window.innerWidth / width;
|
||||||
|
}
|
||||||
|
} else if (height > window.innerHeight) {
|
||||||
|
ratio = window.innerHeight / height;
|
||||||
|
}
|
||||||
|
if (ratio) {
|
||||||
|
svgEl.setAttribute("width", width * ratio - 16);
|
||||||
|
svgEl.setAttribute("height", height * ratio - 16);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
]]></script><g id="a"><g class="shape" ><rect x="0" y="0" width="100" height="100" style="fill:#F7F8FE;stroke:#0D32B2;stroke-width:2;" /></g></g><mask id="1236167803" maskUnits="userSpaceOnUse" x="-100" y="-100" width="304" height="304">
|
||||||
|
<rect x="-100" y="-100" width="304" height="304" fill="white"></rect>
|
||||||
|
|
||||||
|
</mask><style type="text/css"><![CDATA[]]></style></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
49
e2etests/testdata/measured/empty-sql_table/dagre/board.exp.json
generated
vendored
Normal file
49
e2etests/testdata/measured/empty-sql_table/dagre/board.exp.json
generated
vendored
Normal file
|
|
@ -0,0 +1,49 @@
|
||||||
|
{
|
||||||
|
"name": "",
|
||||||
|
"fontFamily": "SourceSansPro",
|
||||||
|
"shapes": [
|
||||||
|
{
|
||||||
|
"id": "a",
|
||||||
|
"type": "sql_table",
|
||||||
|
"pos": {
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"width": 50,
|
||||||
|
"height": 12,
|
||||||
|
"opacity": 1,
|
||||||
|
"strokeDash": 0,
|
||||||
|
"strokeWidth": 2,
|
||||||
|
"borderRadius": 0,
|
||||||
|
"fill": "#0A0F25",
|
||||||
|
"stroke": "#FFFFFF",
|
||||||
|
"shadow": false,
|
||||||
|
"3d": false,
|
||||||
|
"multiple": false,
|
||||||
|
"tooltip": "",
|
||||||
|
"link": "",
|
||||||
|
"icon": null,
|
||||||
|
"iconPosition": "",
|
||||||
|
"blend": false,
|
||||||
|
"fields": null,
|
||||||
|
"methods": null,
|
||||||
|
"columns": null,
|
||||||
|
"label": "",
|
||||||
|
"fontSize": 20,
|
||||||
|
"fontFamily": "DEFAULT",
|
||||||
|
"language": "",
|
||||||
|
"color": "#0A0F25",
|
||||||
|
"italic": false,
|
||||||
|
"bold": true,
|
||||||
|
"underline": false,
|
||||||
|
"labelWidth": 0,
|
||||||
|
"labelHeight": 0,
|
||||||
|
"zIndex": 0,
|
||||||
|
"level": 1,
|
||||||
|
"primaryAccentColor": "#0D32B2",
|
||||||
|
"secondaryAccentColor": "#4A6FF3",
|
||||||
|
"neutralAccentColor": "#676C7E"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"connections": []
|
||||||
|
}
|
||||||
45
e2etests/testdata/measured/empty-sql_table/dagre/sketch.exp.svg
vendored
Normal file
45
e2etests/testdata/measured/empty-sql_table/dagre/sketch.exp.svg
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg
|
||||||
|
id="d2-svg"
|
||||||
|
style="background: white;"
|
||||||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
width="254" height="216" viewBox="-102 -102 254 216"><style type="text/css">
|
||||||
|
<![CDATA[
|
||||||
|
.shape {
|
||||||
|
shape-rendering: geometricPrecision;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.connection {
|
||||||
|
stroke-linecap: round;
|
||||||
|
stroke-linejoin: round;
|
||||||
|
}
|
||||||
|
.blend {
|
||||||
|
mix-blend-mode: multiply;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
]]>
|
||||||
|
</style><script type="application/javascript"><![CDATA[window.addEventListener("DOMContentLoaded", () => {
|
||||||
|
if (document.documentElement.getAttribute("id") !== "d2-svg") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const svgEl = document.documentElement;
|
||||||
|
let width = parseInt(svgEl.getAttribute("width"), 10);
|
||||||
|
let height = parseInt(svgEl.getAttribute("height"), 10);
|
||||||
|
let ratio;
|
||||||
|
if (width > height) {
|
||||||
|
if (width > window.innerWidth) {
|
||||||
|
ratio = window.innerWidth / width;
|
||||||
|
}
|
||||||
|
} else if (height > window.innerHeight) {
|
||||||
|
ratio = window.innerHeight / height;
|
||||||
|
}
|
||||||
|
if (ratio) {
|
||||||
|
svgEl.setAttribute("width", width * ratio - 16);
|
||||||
|
svgEl.setAttribute("height", height * ratio - 16);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
]]></script><g id="a"><g class="shape" ><rect class="shape" x="0" y="0" width="50" height="12" style="fill:#FFFFFF;stroke:#0A0F25;stroke-width:2;"/><rect class="class_header" x="0.000000" y="0.000000" width="50.000000" height="12.000000" fill="#0A0F25" /></g></g><mask id="2389823220" maskUnits="userSpaceOnUse" x="-100" y="-100" width="254" height="216">
|
||||||
|
<rect x="-100" y="-100" width="254" height="216" fill="white"></rect>
|
||||||
|
|
||||||
|
</mask><style type="text/css"><![CDATA[]]></style></svg>
|
||||||
|
After Width: | Height: | Size: 1.6 KiB |
Loading…
Reference in a new issue