Skip to content

Commit 08300bc

Browse files
committed
refactoring
1 parent 15a1ce8 commit 08300bc

File tree

10 files changed

+401
-244
lines changed

10 files changed

+401
-244
lines changed

README.md

+9-4
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,12 @@ The logo is an illustration from [Oliver Byrne's Elements of Euclid: The First S
4747

4848
## TODO
4949

50-
- [ ] try to implement external file strategy (with vfile)
51-
- [ ] reuse [svgStrategy](packages/rehype-d2/src/svgStrategy.ts) in all plugins
52-
- [ ] add `processMeta` to all plugins, so it would be possible to configure `class` and `strategy`
53-
- [ ] maybe rename strategies
50+
- rehype-code-hook-svg maybe
51+
- [ ] try to implement external file strategy (with vfile)
52+
- `basePath: "src/.generated"`?
53+
- https://docs.astro.build/en/guides/images/#images-in-markdown-files
54+
- `loading="lazy" decoding="async"`
55+
- [`~/.generated/*`](https://github.com/withastro/astro/issues/6490)
56+
- [ ] reuse [svgStrategy](packages/rehype-d2/src/svgStrategy.ts) in all plugins
57+
- [ ] add `processMeta` to all plugins, so it would be possible to configure `class` and `strategy`
58+
- [ ] maybe rename strategies

packages/demo/src/content/docs/examples/vizdom-test.md

+14-48
Original file line numberDiff line numberDiff line change
@@ -7,55 +7,21 @@ draft: true
77

88
### works with dark mode
99

10-
```vizdom dataGraph=dagre
10+
```vizdom
1111
digraph TD {
12-
cluster=true
13-
node [shape=box]
14-
subgraph Watcher {
15-
label="watch"
16-
Watch [label="FS Notifier"]
17-
}
18-
Watch -> TailW [label="*.rs & input.css"]
19-
Watch -> Sass [label="*.sass & *.scss"]
20-
Watch -> Append [label="*.css"]
21-
Watch -> WASM [label="*.rs"]
22-
Watch -> BIN [label="*.rs"]
23-
Watch -> Mirror [label="assets/**"]
24-
subgraph style {
25-
label=style
26-
TailW [label="Tailwind CSS"]
27-
Sass
28-
CSSProc [label="CSS Processor\nLightning CSS"]
29-
Append [label="append"]
30-
}
31-
TailW -> Append
32-
Sass -> Append
33-
Append -> CSSProc
34-
subgraph rust {
35-
label=rust
36-
WASM [label="Client WASM"]
37-
BIN [label="Server BIN"]
38-
}
39-
subgraph asset {
40-
label=asset
41-
Mirror
42-
}
43-
subgraph update {
44-
label=update
45-
WOC [label="target/site/\nWrite-on-change FS"]
46-
Live [label="Live Reload"]
47-
Server
48-
}
49-
Mirror -> WOC [label="site/**"]
50-
WASM -> WOC [label="site/pkg/app.wasm"]
51-
BIN -> WOC [label="server/app"]
52-
CSSProc -> WOC [label="site/pkg/app.css"]
53-
Live -> Server [label="Port scan", style=dashed]
54-
WOC -> Server [label="target/server/app\nsite/**"]
55-
WOC -> Live [label="site/pkg/app.css,\nclient & server change"]
56-
Live -> Browser [label="Reload all or\nupdate app.css"]
57-
Browser;
58-
Server -> Browser [style=dashed, arrowhead=none]
12+
node [shape=box]
13+
rankdir="LR"
14+
a -> b -> c -> d -> e -> f -> g
15+
}
16+
```
17+
18+
### `strategy=img`
19+
20+
```vizdom strategy=img
21+
digraph TD {
22+
node [shape=box]
23+
rankdir="LR"
24+
a -> b -> c -> d -> e -> f -> g
5925
}
6026
```
6127

+54
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,57 @@
11
---
22
title: Diagram All The Things
33
---
4+
5+
```vizdom
6+
digraph TD {
7+
cluster=true
8+
node [shape=box]
9+
10+
rehypePlugin -> defaults
11+
12+
codeFence -> code
13+
codeFence -> meta
14+
15+
merge -> svgo
16+
merge -> class
17+
merge -> graphStrategy
18+
merge -> strategy
19+
20+
subgraph configParts {
21+
label=configParts
22+
meta -> parseMeta -> merge
23+
defaults -> merge
24+
}
25+
26+
svgo[label="svgo config"]
27+
28+
strategy -> render
29+
30+
graphStrategy -> render
31+
code -> render -> hw
32+
33+
subgraph renderParts {
34+
render
35+
render -> svg
36+
render -> g
37+
38+
svg[label="light, dark"]
39+
g[label="graph"]
40+
41+
svg -> optimize
42+
svgo -> optimize
43+
}
44+
45+
hw[label="height, width"]
46+
47+
subgraph mdastParts {
48+
toMdast
49+
}
50+
51+
optimize -> toMdast
52+
class -> toMdast
53+
hw -> toMdast
54+
g -> toMdast
55+
strategy -> toMdast
56+
}
57+
```

packages/rehype-vizdom/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@
3636
"@vizdom/vizdom-ts-node": "^0.1.17",
3737
"fenceparser": "^2.2.0",
3838
"hast-util-from-html-isomorphic": "^2.0.0",
39-
"svgo": "^3.3.2"
39+
"svgo": "^3.3.2",
40+
"hastscript": "^9.0.0",
41+
"mini-svg-data-uri": "^1.4.4"
4042
},
4143
"devDependencies": {
4244
"@types/hast": "^3.0.4",

packages/rehype-vizdom/src/index.ts

+13-103
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,35 @@
11
import type { Plugin } from "unified";
22
import type { Root } from "hast";
33
import { rehypeCodeHook, type MapLike } from "@beoe/rehype-code-hook";
4-
import { type Config as SvgoConfig } from "svgo";
5-
import { processVizdomSvg } from "./vizdom.js";
6-
import { DotParser } from "@vizdom/vizdom-ts-node";
7-
import { lex as lexMeta, parse as parseMeta } from "fenceparser";
4+
import { render, RenderOptions } from "./render.js";
5+
import { metaWithDefaults, svgStrategyCbAsync } from "./svgStrategy.js";
86

9-
const processMeta = (meta?: string): Record<string, any> =>
10-
meta ? parseMeta(lexMeta(meta)) : {};
11-
12-
// it is possible to add other formats, like Graphology etc.
13-
type GraphFormat = "dagre" | "graphology";
14-
15-
async function dotToSvg(code: string, dataGraph?: GraphFormat) {
16-
const parser = new DotParser();
17-
const dotGraph = parser.parse(code);
18-
const directedGraph = dotGraph.to_directed();
19-
const positioned = directedGraph.layout();
20-
const svg = await positioned.to_svg().to_string();
21-
22-
let graph;
23-
if (dataGraph) {
24-
const obj = positioned.to_json().to_obj();
25-
if (dataGraph === "graphology") {
26-
graph = {
27-
attributes: { name: "g" },
28-
options: { allowSelfLoops: true, multi: true, type: "directed" },
29-
nodes: obj.nodes.map((node) => ({
30-
key: node.unique_id,
31-
// attributes: {
32-
// label: node.label,
33-
// x: node.x,
34-
// y: node.y,
35-
// width: node.width,
36-
// height: node.width,
37-
// url: node.url,
38-
// },
39-
})),
40-
edges: obj.edges.map((edge) => ({
41-
key: edge.unique_id,
42-
source: edge.source,
43-
target: edge.target,
44-
// attributes: {
45-
// label: edge.label,
46-
// url: edge.url,
47-
// },
48-
})),
49-
};
50-
}
51-
52-
if (dataGraph === "dagre") {
53-
graph = {
54-
options: {
55-
directed: true,
56-
multigraph: true,
57-
compound: false,
58-
},
59-
nodes: obj.nodes.map((node) => ({
60-
v: node.unique_id,
61-
// value: {},
62-
})),
63-
edges: obj.edges.map((edge) => ({
64-
v: edge.source,
65-
w: edge.target,
66-
name: edge.unique_id,
67-
// value: {},
68-
})),
69-
};
70-
}
71-
}
72-
73-
return {
74-
svg,
75-
graph,
76-
};
77-
}
78-
79-
export type RenderVizdomOptions = {
80-
code: string;
81-
class?: string;
82-
svgo?: SvgoConfig | boolean;
83-
};
84-
85-
export { processVizdomSvg };
86-
87-
export type RehypeVizdomConfig = {
7+
export type RehypeVizdomConfig = RenderOptions & {
888
cache?: MapLike;
89-
class?: string;
90-
svgo?: SvgoConfig | boolean;
91-
// adds data-graph to each figure with JSON representation of graph
92-
dataGraph?: GraphFormat;
939
};
9410

9511
export const rehypeVizdom: Plugin<[RehypeVizdomConfig?], Root> = (
9612
options = {}
9713
) => {
98-
const salt = {
14+
const defaults = {
9915
class: options.class,
10016
svgo: options.svgo,
17+
strategy: options.strategy,
10118
dataGraph: options.dataGraph,
10219
};
20+
const language = "vizdom";
10321
// @ts-expect-error
10422
return rehypeCodeHook({
10523
...options,
106-
salt,
107-
language: "vizdom",
24+
salt: defaults,
25+
language,
10826
code: ({ code, meta }) => {
109-
const metaOptions = processMeta(meta);
110-
const dataGraph =
111-
metaOptions.datagraph !== undefined
112-
? metaOptions.datagraph
113-
: options.dataGraph;
114-
const cssClass = `${options.class || ""} ${
115-
metaOptions.class || ""
116-
}`.trim();
117-
const svgo =
118-
metaOptions.svgo !== undefined ? metaOptions.svgo : options.svgo;
27+
const opts = metaWithDefaults(language, defaults, meta);
11928

120-
return dotToSvg(code, dataGraph).then(({ svg, graph }) =>
121-
processVizdomSvg(svg, cssClass, svgo, dataGraph ? graph : undefined)
122-
);
29+
return svgStrategyCbAsync(opts.strategy, opts.class, async () => {
30+
const { svg: lightSvg, width, height, graph } = await render(code, opts);
31+
return { lightSvg, width, height, graph };
32+
});
12333
},
12434
});
12535
};

0 commit comments

Comments
 (0)