Skip to content

Commit 1e086e9

Browse files
authored
Merge pull request #15 from ts-graphviz/add-remark-tsgraphviz-plugin
Add ts-graphviz plugin to the remark plugins
2 parents 5b2a0d9 + 3f3c92e commit 1e086e9

File tree

6 files changed

+154
-18
lines changed

6 files changed

+154
-18
lines changed

docs/ts-graphviz/02-core-features/index.mdx renamed to docs/ts-graphviz/02-core-features/index.md

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
---
22
description: Explore core APIs for graph creation and manipulation.
33
---
4-
import TSGraphvizLiveEditor from '@site/src/components/TSGraphvizLiveEditor';
54

65

76
# Core Features
@@ -12,15 +11,14 @@ import TSGraphvizLiveEditor from '@site/src/components/TSGraphvizLiveEditor';
1211

1312
**Playground:**
1413

15-
<TSGraphvizLiveEditor
16-
script={`import { digraph, attribute as _ } from 'ts-graphviz';
14+
```ts ts-graphviz:read-only
15+
import { digraph, attribute as _ } from 'ts-graphviz';
1716

1817
const G = digraph('G', (g) => {
19-
g.node('A', { [_.color]: 'red' });
20-
g.edge(['A', 'B'], { [_.label]: 'A to B' });
21-
});`}
22-
readOnly
23-
/>
18+
g.node('A', { [_.color]: 'red' });
19+
g.edge(['A', 'B'], { [_.label]: 'A to B' });
20+
});
21+
```
2422

2523
:::tip
2624
Hover over `digraph` or `g.node` or `[_.color]` for type hints.

docusaurus.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type * as Preset from '@docusaurus/preset-classic';
22
import npm2yarn from '@docusaurus/remark-plugin-npm2yarn';
33
import type { Config } from '@docusaurus/types';
44
import { themes as prismThemes } from 'prism-react-renderer';
5+
import tsgraphviz from './plugins/remark-plugin-tsgraphviz';
56

67
const config: Config = {
78
title: 'ts-graphviz',
@@ -31,6 +32,7 @@ const config: Config = {
3132
'https://pr.new/github.com//ts-graphviz/ts-graphviz.github.io/edit/main/',
3233
remarkPlugins: [
3334
[npm2yarn, { sync: true, converters: ['yarn', 'pnpm'] }],
35+
[tsgraphviz, {}],
3436
],
3537
},
3638
blog: {
@@ -39,11 +41,13 @@ const config: Config = {
3941
'https://pr.new/github.com//ts-graphviz/ts-graphviz.github.io/edit/main/',
4042
remarkPlugins: [
4143
[npm2yarn, { sync: true, converters: ['yarn', 'pnpm'] }],
44+
[tsgraphviz, {}],
4245
],
4346
},
4447
pages: {
4548
remarkPlugins: [
4649
[npm2yarn, { sync: true, converters: ['yarn', 'pnpm'] }],
50+
[tsgraphviz, {}],
4751
],
4852
},
4953
theme: {

i18n/ja/docusaurus-plugin-content-docs/current/ts-graphviz/02-core-features/index.mdx renamed to i18n/ja/docusaurus-plugin-content-docs/current/ts-graphviz/02-core-features/index.md

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
---
22
description: グラフ作成と操作のためのts-graphvizの主要なAPIを紹介
33
---
4-
import TSGraphvizLiveEditor from '@site/src/components/TSGraphvizLiveEditor';
54

65
# コア機能
76

87
## TypeScript フレンドリーな API
98

109
`ts-graphviz` は TypeScript とシームレスに統合された API を提供し、強力な型定義と完全な IntelliSense サポートを備えています。これにより、開発中のエラーをより簡単に発見でき、開発者の体験が向上します。
1110

12-
**プレイグラウンド:**
13-
14-
<TSGraphvizLiveEditor
15-
script={`import { digraph, attribute as _ } from 'ts-graphviz';
11+
```ts ts-graphviz:read-only
12+
import { digraph, attribute as _ } from 'ts-graphviz';
1613

1714
const G = digraph('G', (g) => {
18-
g.node('A', { [_.color]: 'red' });
19-
g.edge(['A', 'B'], { [_.label]: 'A to B' });
20-
});`}
21-
readOnly
22-
/>
15+
g.node('A', { [_.color]: 'red' });
16+
g.edge(['A', 'B'], { [_.label]: 'A to B' });
17+
});
18+
```
2319

2420
:::tip
2521
`digraph``g.node``[_.color]` にカーソルを合わせると型のヒントが表示されます。

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,15 @@
4747
"@docusaurus/module-type-aliases": "3.6.0",
4848
"@docusaurus/tsconfig": "3.6.0",
4949
"@docusaurus/types": "3.6.0",
50+
"@types/mdast": "^4.0.4",
5051
"@types/node": "^22.9.0",
5152
"@types/react": "^18.3.12",
53+
"@types/unist": "^3.0.3",
54+
"mdast-util-mdx-jsx": "^3.1.3",
5255
"raw-loader": "^4.0.2",
5356
"typescript": "~5.6.3",
57+
"unified": "^11.0.5",
58+
"unist-util-visit": "^5.0.0",
5459
"utility-types": "^3.11.0"
5560
},
5661
"browserslist": {

plugins/remark-plugin-tsgraphviz.ts

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
import type { Code, Literal } from 'mdast';
2+
import type { MdxJsxFlowElement } from 'mdast-util-mdx-jsx';
3+
import type { Plugin, Transformer } from 'unified';
4+
import type { Node, Parent } from 'unist';
5+
6+
// biome-ignore lint/complexity/noBannedTypes: Preliminary implementation for future plugin extensibility.
7+
type PluginOptions = {};
8+
9+
type CodeBlockOptions = {
10+
readOnly: boolean;
11+
};
12+
13+
const transformNode = (code: Code): MdxJsxFlowElement[] => {
14+
const script = code.value;
15+
const options = getTSGraphvizOptions(code);
16+
return [
17+
{
18+
type: 'mdxJsxFlowElement',
19+
name: 'TSGraphvizLiveEditor',
20+
attributes: [
21+
{
22+
type: 'mdxJsxAttribute',
23+
name: 'script',
24+
value: script,
25+
},
26+
{
27+
type: 'mdxJsxAttribute',
28+
name: 'readOnly',
29+
value: options.readOnly ? 'true' : 'false',
30+
},
31+
],
32+
children: [],
33+
},
34+
];
35+
};
36+
37+
const isMdxEsmLiteral = (node: Node): node is Literal =>
38+
node.type === 'mdxjsEsm';
39+
40+
const isTSGraphvizLiveEditorImport = (node: Node): boolean =>
41+
isMdxEsmLiteral(node) &&
42+
node.value.includes('@site/src/components/TSGraphvizLiveEditor');
43+
44+
const isParent = (node: Node): node is Parent =>
45+
Array.isArray((node as Parent).children);
46+
const isTSGraphvizScript = (node: Node): node is Code =>
47+
node.type === 'code' && (node as Code).meta?.startsWith('ts-graphviz');
48+
49+
const getTSGraphvizOptions = (code: Code): CodeBlockOptions => {
50+
const options = code.meta ? code.meta.split(':').slice(1) : [];
51+
return {
52+
readOnly: options.includes('read-only'),
53+
};
54+
};
55+
56+
function createImportNode() {
57+
return {
58+
type: 'mdxjsEsm',
59+
value:
60+
"import TSGraphvizLiveEditor from '@site/src/components/TSGraphvizLiveEditor'",
61+
data: {
62+
estree: {
63+
type: 'Program',
64+
body: [
65+
{
66+
type: 'ImportDeclaration',
67+
specifiers: [
68+
{
69+
type: 'ImportDefaultSpecifier',
70+
local: { type: 'Identifier', name: 'TSGraphvizLiveEditor' },
71+
},
72+
],
73+
source: {
74+
type: 'Literal',
75+
value: '@site/src/components/TSGraphvizLiveEditor',
76+
raw: "'@site/src/components/TSGraphvizLiveEditor'",
77+
},
78+
},
79+
],
80+
sourceType: 'module',
81+
},
82+
},
83+
};
84+
}
85+
86+
const plugin: Plugin<[PluginOptions?]> = (options = {}): Transformer => {
87+
return async (root) => {
88+
const { visit } = await import('unist-util-visit');
89+
90+
let transformed = false;
91+
let alreadyImported = false;
92+
93+
visit(root, (node: Node) => {
94+
if (isTSGraphvizLiveEditorImport(node)) {
95+
alreadyImported = true;
96+
}
97+
98+
if (isParent(node)) {
99+
const newChildren: Node[] = [];
100+
for (const child of node.children) {
101+
if (isTSGraphvizScript(child)) {
102+
newChildren.push(...transformNode(child));
103+
transformed = true;
104+
} else {
105+
newChildren.push(child);
106+
}
107+
}
108+
node.children = newChildren;
109+
}
110+
});
111+
112+
if (transformed && !alreadyImported) {
113+
(root as Parent).children.unshift(createImportNode());
114+
}
115+
};
116+
};
117+
118+
export default plugin;

pnpm-lock.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)