Skip to content

Commit 3797086

Browse files
committed
d2 graph
1 parent a797c43 commit 3797086

File tree

7 files changed

+130
-17
lines changed

7 files changed

+130
-17
lines changed

packages/docs/src/components/vizdom.ts

+51
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,54 @@ document.querySelectorAll(".vizdom.shadow").forEach((container) => {
174174
}
175175
});
176176
});
177+
178+
// interactivity for d2 diagrams
179+
document.querySelectorAll(".d2.shadow").forEach((container) => {
180+
const data = container.getAttribute("data-beoe")
181+
? JSON.parse(container.getAttribute("data-beoe")!)
182+
: null;
183+
184+
if (!data) return;
185+
const graph = json.read(data);
186+
187+
function clear() {
188+
container
189+
.querySelectorAll(".shape,.connection")
190+
.forEach((node) => node.classList.remove("shadow"));
191+
}
192+
193+
function highlight(id: string) {
194+
container
195+
.querySelectorAll(".shape,.connection")
196+
.forEach((node) => node.classList.add("shadow"));
197+
alg.postorder(graph, [id]).forEach((node) => {
198+
container
199+
.querySelector(`#${CSS.escape(node)} .shape`)
200+
?.classList.remove("shadow");
201+
graph.outEdges(node)?.forEach(({ name }) => {
202+
container
203+
.querySelector(`#${CSS.escape(name!)}`)
204+
?.classList.remove("shadow");
205+
});
206+
});
207+
}
208+
209+
// highlight on hover
210+
let currentHover: string | null = null;
211+
container.addEventListener("mouseover", (e) => {
212+
// @ts-expect-error
213+
const node = e.target?.closest(".shape");
214+
215+
if (node) {
216+
const id = node.parentElement.getAttribute("id");
217+
if (currentHover == id) return;
218+
clear();
219+
highlight(id);
220+
currentHover = id;
221+
} else {
222+
if (currentHover == null) return;
223+
clear();
224+
currentHover = null;
225+
}
226+
});
227+
});

packages/docs/src/content/docs/diagrams/d2.mdx

+4-4
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,18 @@ Rehype plugin to generate [D2](https://d2lang.com/) diagrams in place of code fe
1010
<Tabs>
1111
<TabItem label="Diagram">
1212

13-
```d2
13+
```d2 strategy=inline darkScheme=false graphFormat=dagre class=shadow
1414
direction: right
15-
x.y.z -> a.b.c: Label
15+
a -> b -> c -> d -> e
1616
```
1717

1818
</TabItem>
1919
<TabItem label="Markdown">
2020

2121
````md
22-
```d2
22+
```d2 strategy=inline darkScheme=false graphFormat=dagre class=shadow
2323
direction: right
24-
x.y.z -> a.b.c: Label
24+
a -> b -> c -> d -> e
2525
```
2626
````
2727

packages/docs/src/content/docs/examples/d2-test.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ a2 -> b -> c -> d -> e
282282

283283
### `strategy=inline`
284284

285-
```d2 strategy=inline darkScheme=false
285+
```d2 strategy=inline darkScheme=false graphFormat=dagre class=shadow
286286
direction: right
287287
a -> b -> c -> d -> e
288288
```

packages/docs/src/styles/custom.css

+10
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,13 @@ html[data-theme="dark"] .beoe-light {
133133
.vizdom .style-me :first-child {
134134
fill: lightblue;
135135
}
136+
137+
.d2[data-beoe].shadow {
138+
.shadow {
139+
opacity: 0.4;
140+
}
141+
142+
.shape {
143+
cursor: default;
144+
}
145+
}

packages/rehype-d2/src/d2.ts

+55-6
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,63 @@ export type D2Options = {
55
layout?: "dagre" | "elk";
66
sketch?: boolean;
77
themeID?: number;
8+
graphFormat?: "graphology" | "dagre";
89
};
910

10-
export async function d2(
11-
code: string,
12-
options?: D2Options
13-
): Promise<string> {
11+
export async function d2(code: string, options: D2Options) {
1412
const d2Instance = new D2();
1513
const result = await d2Instance.compile(code, options);
16-
const svg = await d2Instance.render(result.diagram, options);
17-
return svg
14+
15+
let data;
16+
if (options.graphFormat) {
17+
if (options.graphFormat === "graphology") {
18+
data = {
19+
attributes: { name: "g" },
20+
options: { allowSelfLoops: true, multi: true, type: "directed" },
21+
nodes: result.diagram.shapes.map((node: any) => ({
22+
key: node.id,
23+
// attributes: {
24+
// label: node.label,
25+
// x: node.pos.x,
26+
// y: node.pos.y,
27+
// width: node.width,
28+
// height: node.height,
29+
// url: node.url,
30+
// },
31+
})),
32+
edges: result.diagram.connections.map((edge: any) => ({
33+
key: edge.id,
34+
source: edge.src,
35+
target: edge.dst,
36+
// attributes: {
37+
// label: edge.label,
38+
// url: edge.url,
39+
// },
40+
})),
41+
};
42+
}
43+
44+
if (options.graphFormat === "dagre") {
45+
data = {
46+
options: {
47+
directed: true,
48+
multigraph: true,
49+
compound: false,
50+
},
51+
nodes: result.diagram.shapes.map((node: any) => ({
52+
v: node.id,
53+
// value: {},
54+
})),
55+
edges: result.diagram.connections.map((edge: any) => ({
56+
v: edge.src,
57+
w: edge.dst,
58+
name: edge.id,
59+
// value: {},
60+
})),
61+
};
62+
}
63+
}
64+
65+
const svg = await d2Instance.render(result.diagram, options) as string;
66+
return { svg, data };
1867
}

packages/rehype-d2/src/index.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,18 @@ export const rehypeD2 = rehypeCodeHookImg<RehypeD2Config>({
2121
// @ts-ignore
2222
newD2Options.themeID = parseFloat(newD2Options.theme);
2323
}
24-
const svg = await d2(code, newD2Options);
25-
const darkSvg = darkMode
26-
? await d2(code, {
24+
const { svg, data } = await d2(code, newD2Options);
25+
let darkSvg;
26+
if (darkMode) {
27+
darkSvg = (
28+
await d2(code, {
2729
...newD2Options,
2830
// @ts-ignore
2931
themeID: parseFloat(newD2Options?.darkTheme ?? "200"),
3032
})
31-
: undefined;
32-
return { svg, darkSvg };
33+
).svg;
34+
}
35+
return { svg, darkSvg, data };
3336
},
3437
});
3538

packages/rehype-vizdom/src/render.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const render = async (code: string, options: RehypeVizdomConfig) => {
3030
// x: node.x,
3131
// y: node.y,
3232
// width: node.width,
33-
// height: node.width,
33+
// height: node.height,
3434
// url: node.url,
3535
// },
3636
})),

0 commit comments

Comments
 (0)