d2js: updating render option processing, adding tests
This commit is contained in:
parent
b81f10c39c
commit
a0d855a4e1
7 changed files with 98 additions and 38 deletions
|
|
@ -154,26 +154,6 @@ func GetELKGraph(args []js.Value) (interface{}, error) {
|
||||||
return elk, nil
|
return elk, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func layoutResolver() func(engine string) (d2graph.LayoutGraph, error) {
|
|
||||||
cached := make(map[string]d2graph.LayoutGraph)
|
|
||||||
return func(engine string) (d2graph.LayoutGraph, error) {
|
|
||||||
if c, ok := cached[engine]; ok {
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
var layout d2graph.LayoutGraph
|
|
||||||
switch engine {
|
|
||||||
case "dagre":
|
|
||||||
layout = d2dagrelayout.DefaultLayout
|
|
||||||
case "elk":
|
|
||||||
layout = d2elklayout.DefaultLayout
|
|
||||||
default:
|
|
||||||
return nil, &WASMError{Message: fmt.Sprintf("layout option '%s' not recognized", engine), Code: 400}
|
|
||||||
}
|
|
||||||
cached[engine] = layout
|
|
||||||
return layout, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Compile(args []js.Value) (interface{}, error) {
|
func Compile(args []js.Value) (interface{}, error) {
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return nil, &WASMError{Message: "missing JSON argument", Code: 400}
|
return nil, &WASMError{Message: "missing JSON argument", Code: 400}
|
||||||
|
|
@ -192,8 +172,18 @@ func Compile(args []js.Value) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
compileOpts := &d2lib.CompileOptions{
|
compileOpts := &d2lib.CompileOptions{
|
||||||
UTF16Pos: true,
|
UTF16Pos: true,
|
||||||
LayoutResolver: layoutResolver(),
|
}
|
||||||
|
|
||||||
|
compileOpts.LayoutResolver = func(engine string) (d2graph.LayoutGraph, error) {
|
||||||
|
switch engine {
|
||||||
|
case "dagre":
|
||||||
|
return d2dagrelayout.DefaultLayout, nil
|
||||||
|
case "elk":
|
||||||
|
return d2elklayout.DefaultLayout, nil
|
||||||
|
default:
|
||||||
|
return nil, &WASMError{Message: fmt.Sprintf("layout option '%s' not recognized", engine), Code: 400}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
@ -212,9 +202,11 @@ func Compile(args []js.Value) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderOpts := &d2svg.RenderOpts{}
|
renderOpts := &d2svg.RenderOpts{}
|
||||||
if input.Opts != nil && input.Opts.Sketch != nil && *input.Opts.Sketch {
|
if input.Opts != nil && input.Opts.Sketch != nil {
|
||||||
compileOpts.FontFamily = go2.Pointer(d2fonts.HandDrawn)
|
|
||||||
renderOpts.Sketch = input.Opts.Sketch
|
renderOpts.Sketch = input.Opts.Sketch
|
||||||
|
if *input.Opts.Sketch {
|
||||||
|
compileOpts.FontFamily = go2.Pointer(d2fonts.HandDrawn)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if input.Opts != nil && input.Opts.Pad != nil {
|
if input.Opts != nil && input.Opts.Pad != nil {
|
||||||
renderOpts.Pad = input.Opts.Pad
|
renderOpts.Pad = input.Opts.Pad
|
||||||
|
|
@ -248,7 +240,7 @@ func Compile(args []js.Value) (interface{}, error) {
|
||||||
FS: input.FS,
|
FS: input.FS,
|
||||||
Diagram: *diagram,
|
Diagram: *diagram,
|
||||||
Graph: *g,
|
Graph: *g,
|
||||||
Options: RenderOptions{
|
RenderOptions: RenderOptions{
|
||||||
ThemeID: renderOpts.ThemeID,
|
ThemeID: renderOpts.ThemeID,
|
||||||
DarkThemeID: renderOpts.DarkThemeID,
|
DarkThemeID: renderOpts.DarkThemeID,
|
||||||
Sketch: renderOpts.Sketch,
|
Sketch: renderOpts.Sketch,
|
||||||
|
|
|
||||||
|
|
@ -52,10 +52,10 @@ type CompileOptions struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompileResponse struct {
|
type CompileResponse struct {
|
||||||
FS map[string]string `json:"fs"`
|
FS map[string]string `json:"fs"`
|
||||||
Diagram d2target.Diagram `json:"diagram"`
|
Diagram d2target.Diagram `json:"diagram"`
|
||||||
Graph d2graph.Graph `json:"graph"`
|
Graph d2graph.Graph `json:"graph"`
|
||||||
Options RenderOptions `json:"options"`
|
RenderOptions RenderOptions `json:"renderOptions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CompletionResponse struct {
|
type CompletionResponse struct {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ const result = await d2.compile('x -> y');
|
||||||
const svg = await d2.render(result.diagram, result.options);
|
const svg = await d2.render(result.diagram, result.options);
|
||||||
```
|
```
|
||||||
|
|
||||||
Additional Configuration:
|
Configuring render options (see [CompileOptions](#compileoptions) for all available options):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
import { D2 } from '@terrastruct/d2';
|
import { D2 } from '@terrastruct/d2';
|
||||||
|
|
@ -53,9 +53,9 @@ import { D2 } from '@terrastruct/d2';
|
||||||
const d2 = new D2();
|
const d2 = new D2();
|
||||||
|
|
||||||
const result = await d2.compile('x -> y', {
|
const result = await d2.compile('x -> y', {
|
||||||
sketch = true,
|
sketch: true,
|
||||||
});
|
});
|
||||||
const svg = await d2.render(result.diagram, result.options);
|
const svg = await d2.render(result.diagram, result.renderOptions);
|
||||||
```
|
```
|
||||||
|
|
||||||
## API Reference
|
## API Reference
|
||||||
|
|
@ -74,7 +74,7 @@ Renders a compiled diagram to SVG.
|
||||||
|
|
||||||
### `CompileOptions`
|
### `CompileOptions`
|
||||||
|
|
||||||
All `RenderOptions` properties in addition to:
|
All [RenderOptions](#renderoptions) properties in addition to:
|
||||||
|
|
||||||
- `layout`: Layout engine to use ('dagre' | 'elk') [default: 'dagre']
|
- `layout`: Layout engine to use ('dagre' | 'elk') [default: 'dagre']
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,7 +316,7 @@
|
||||||
center,
|
center,
|
||||||
forceAppendix,
|
forceAppendix,
|
||||||
});
|
});
|
||||||
const svg = await d2.render(result.diagram, result.options);
|
const svg = await d2.render(result.diagram, result.renderOptions);
|
||||||
document.getElementById("output").innerHTML = svg;
|
document.getElementById("output").innerHTML = svg;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,14 @@ export function setupMessageHandler(isNode, port, initWasm) {
|
||||||
// single-threaded WASM call cannot complete without giving control back
|
// single-threaded WASM call cannot complete without giving control back
|
||||||
// So we compute it, store it here, then during elk layout, instead
|
// So we compute it, store it here, then during elk layout, instead
|
||||||
// of computing again, we use this variable (and unset it for next call)
|
// of computing again, we use this variable (and unset it for next call)
|
||||||
|
// If the layout option has not been set, we generate the elk layout now
|
||||||
|
// anyway to support `layout-engine: elk` in d2-config vars
|
||||||
|
if (data.options.layout === "elk" || data.options.layout == null) {
|
||||||
|
const elkGraph = await d2.getELKGraph(JSON.stringify(data));
|
||||||
|
const elkGraph2 = JSON.parse(elkGraph).data;
|
||||||
|
const layout = await elk.layout(elkGraph2);
|
||||||
|
globalThis.elkResult = layout;
|
||||||
|
}
|
||||||
const elkGraph = await d2.getELKGraph(JSON.stringify(data));
|
const elkGraph = await d2.getELKGraph(JSON.stringify(data));
|
||||||
const elkGraph2 = JSON.parse(elkGraph).data;
|
const elkGraph2 = JSON.parse(elkGraph).data;
|
||||||
const layout = await elk.layout(elkGraph2);
|
const layout = await elk.layout(elkGraph2);
|
||||||
|
|
|
||||||
|
|
@ -27,10 +27,12 @@ export function setupMessageHandler(isNode, port, initWasm) {
|
||||||
|
|
||||||
case "compile":
|
case "compile":
|
||||||
try {
|
try {
|
||||||
const elkGraph = await d2.getELKGraph(JSON.stringify(data));
|
if (data.options.layout === "elk" || data.options.layout == null) {
|
||||||
const elkGraph2 = JSON.parse(elkGraph).data;
|
const elkGraph = await d2.getELKGraph(JSON.stringify(data));
|
||||||
const layout = await elk.layout(elkGraph2);
|
const elkGraph2 = JSON.parse(elkGraph).data;
|
||||||
globalThis.elkResult = layout;
|
const layout = await elk.layout(elkGraph2);
|
||||||
|
globalThis.elkResult = layout;
|
||||||
|
}
|
||||||
const result = await d2.compile(JSON.stringify(data));
|
const result = await d2.compile(JSON.stringify(data));
|
||||||
const response = JSON.parse(result);
|
const response = JSON.parse(result);
|
||||||
if (response.error) throw new Error(response.error.message);
|
if (response.error) throw new Error(response.error.message);
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,64 @@ describe("D2 Unit Tests", () => {
|
||||||
await d2.worker.terminate();
|
await d2.worker.terminate();
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
|
test("d2-config read correctly", async () => {
|
||||||
|
const d2 = new D2();
|
||||||
|
const result = await d2.compile(
|
||||||
|
`
|
||||||
|
vars: {
|
||||||
|
d2-config: {
|
||||||
|
theme-id: 4
|
||||||
|
dark-theme-id: 200
|
||||||
|
pad: 10
|
||||||
|
center: true
|
||||||
|
sketch: true
|
||||||
|
layout-engine: elk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x -> y
|
||||||
|
`
|
||||||
|
);
|
||||||
|
expect(result.renderOptions.sketch).toBe(true);
|
||||||
|
expect(result.renderOptions.themeID).toBe(4);
|
||||||
|
expect(result.renderOptions.darkThemeID).toBe(200);
|
||||||
|
// expect(result.renderOptions.center).toBe(true);
|
||||||
|
expect(result.renderOptions.pad).toBe(10);
|
||||||
|
await d2.worker.terminate();
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
test("render options take priority", async () => {
|
||||||
|
const d2 = new D2();
|
||||||
|
const result = await d2.compile(
|
||||||
|
`
|
||||||
|
vars: {
|
||||||
|
d2-config: {
|
||||||
|
theme-id: 4
|
||||||
|
dark-theme-id: 200
|
||||||
|
pad: 10
|
||||||
|
center: true
|
||||||
|
sketch: true
|
||||||
|
layout-engine: elk
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x -> y
|
||||||
|
`,
|
||||||
|
{
|
||||||
|
sketch: false,
|
||||||
|
themeID: 100,
|
||||||
|
darkThemeID: 300,
|
||||||
|
center: false,
|
||||||
|
pad: 0,
|
||||||
|
layout: "dagre",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
expect(result.renderOptions.sketch).toBe(false);
|
||||||
|
expect(result.renderOptions.themeID).toBe(100);
|
||||||
|
expect(result.renderOptions.darkThemeID).toBe(300);
|
||||||
|
expect(result.renderOptions.center).toBe(false);
|
||||||
|
expect(result.renderOptions.pad).toBe(0);
|
||||||
|
await d2.worker.terminate();
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
test("sketch render works", async () => {
|
test("sketch render works", async () => {
|
||||||
const d2 = new D2();
|
const d2 = new D2();
|
||||||
const result = await d2.compile("x -> y", { sketch: true });
|
const result = await d2.compile("x -> y", { sketch: true });
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue