Skip to content

Commit 28e498a

Browse files
committed
d2js: updating target default + errors, readme
1 parent 1417ded commit 28e498a

File tree

4 files changed

+53
-9
lines changed

4 files changed

+53
-9
lines changed

ci/release/changelogs/next.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#### Improvements 🧹
66

7-
- d2js: Support `d2-config`. Support additional render options: [#2343](https://github.com/terrastruct/d2/pull/2343)
7+
- d2js: Support `d2-config`. Support additional options: [#2343](https://github.com/terrastruct/d2/pull/2343)
88
- `themeID`
99
- `darkThemeID`
1010
- `center`

d2js/d2wasm/functions.go

+12-7
Original file line numberDiff line numberDiff line change
@@ -271,27 +271,34 @@ func Render(args []js.Value) (interface{}, error) {
271271
return nil, &WASMError{Message: "missing 'diagram' field in input JSON", Code: 400}
272272
}
273273

274+
animateInterval := 0
275+
if input.Opts != nil && input.Opts.AnimateInterval != nil && *input.Opts.AnimateInterval > 0 {
276+
animateInterval = int(*input.Opts.AnimateInterval)
277+
}
278+
274279
var boardPath []string
275-
var noChildren bool
280+
noChildren := true
276281

277282
if input.Opts.Target != nil {
278283
switch *input.Opts.Target {
279284
case "*":
285+
noChildren = false
280286
case "":
281-
noChildren = true
282287
default:
283288
target := *input.Opts.Target
284289
if strings.HasSuffix(target, ".*") {
285290
target = target[:len(target)-2]
286-
} else {
287-
noChildren = true
291+
noChildren = false
288292
}
289293
key, err := d2parser.ParseKey(target)
290294
if err != nil {
291295
return nil, &WASMError{Message: fmt.Sprintf("target '%s' not recognized", target), Code: 400}
292296
}
293297
boardPath = key.StringIDA()
294298
}
299+
if !noChildren && animateInterval <= 0 {
300+
return nil, &WASMError{Message: fmt.Sprintf("target '%s' only supported for animated SVGs", *input.Opts.Target), Code: 500}
301+
}
295302
}
296303

297304
diagram := input.Diagram.GetBoard(boardPath)
@@ -310,9 +317,7 @@ func Render(args []js.Value) (interface{}, error) {
310317
renderOpts.Salt = input.Opts.Salt
311318
}
312319

313-
var animateInterval = 0
314-
if input.Opts != nil && input.Opts.AnimateInterval != nil && *input.Opts.AnimateInterval > 0 {
315-
animateInterval = int(*input.Opts.AnimateInterval)
320+
if animateInterval > 0 {
316321
masterID, err := diagram.HashID(renderOpts.Salt)
317322
if err != nil {
318323
return nil, &WASMError{Message: fmt.Sprintf("cannot process animate interval: %s", err.Error()), Code: 500}

d2js/js/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ All [RenderOptions](#renderoptions) properties in addition to:
8787
- `pad`: Pixels padded around the rendered diagram [default: 100]
8888
- `scale`: Scale the output. E.g., 0.5 to halve the default size. The default will render SVG's that will fit to screen. Setting to 1 turns off SVG fitting to screen.
8989
- `forceAppendix`: Adds an appendix for tooltips and links [default: false]
90-
- `target`: Target board to render. Pass an empty string to target root board. If target ends with '*', it will be rendered with all of its scenarios, steps, and layers. Otherwise, only the target board will be rendered. E.g. --target='' to render root board only or --target='layers.x.*' to render layer 'x' with all of its children.
90+
- `target`: Target board/s to render. If target ends with '*', it will be rendered with all of its scenarios, steps, and layers. Otherwise, only the target board will be rendered. Pass '*' to render all scenarios, steps, and layers. E.g. `target: 'layers.x.*'` to render layer 'x' with all of its children. Multi-board outputs are currently only supported for animated SVGs and so `animateInterval` must be set to a value greater than 0.
9191
- `animateInterval`: If given, multiple boards are packaged as 1 SVG which transitions through each board at the interval (in milliseconds).
9292
- `salt`: Add a salt value to ensure the output uses unique IDs. This is useful when generating multiple identical diagrams to be included in the same HTML doc, so that duplicate IDs do not cause invalid HTML. The salt value is a string that will be appended to IDs in the output.
9393
- `noXMLTag`: Omit XML tag `(<?xml ...?>)` from output SVG files. Useful when generating SVGs for direct HTML embedding.

d2js/js/test/unit/basic.test.js

+39
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,24 @@ x -> y
121121
await d2.worker.terminate();
122122
}, 20000);
123123

124+
test("animated multi-board works", async () => {
125+
const d2 = new D2();
126+
const source = `
127+
x -> y
128+
layers: {
129+
numbers: {
130+
1 -> 2
131+
}
132+
}
133+
`;
134+
const options = { target: "*", animateInterval: 1000 };
135+
const result = await d2.compile(source, options);
136+
const svg = await d2.render(result.diagram, result.renderOptions);
137+
expect(svg).toContain("<svg");
138+
expect(svg).toContain("</svg>");
139+
await d2.worker.terminate();
140+
}, 20000);
141+
124142
test("latex works", async () => {
125143
const d2 = new D2();
126144
const result = await d2.compile("x: |latex \\frac{f(x+h)-f(x)}{h} |");
@@ -141,4 +159,25 @@ x -> y
141159
}
142160
await d2.worker.terminate();
143161
}, 20000);
162+
163+
test("handles unanimated multi-board error correctly", async () => {
164+
const d2 = new D2();
165+
const source = `
166+
x -> y
167+
layers: {
168+
numbers: {
169+
1 -> 2
170+
}
171+
}
172+
`;
173+
const result = await d2.compile(source);
174+
try {
175+
await d2.render(result.diagram, { target: "*" });
176+
throw new Error("Should have thrown compile error");
177+
} catch (err) {
178+
expect(err).toBeDefined();
179+
expect(err.message).not.toContain("Should have thrown compile error");
180+
}
181+
await d2.worker.terminate();
182+
}, 20000);
144183
});

0 commit comments

Comments
 (0)