@ts-graphviz/react 0.10.6 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +487 -0
- package/README.md +630 -67
- package/example/example.tsx +1 -1
- package/lib/react.d.ts +198 -96
- package/lib/react.js +558 -215
- package/package.json +15 -20
- package/tsconfig.test.json +11 -0
- package/lib/react.cjs +0 -457
- package/src/components/Digraph.spec.tsx +0 -18
- package/src/components/Digraph.tsx +0 -41
- package/src/components/Edge.tsx +0 -17
- package/src/components/Graph.spec.tsx +0 -18
- package/src/components/Graph.tsx +0 -36
- package/src/components/GraphPortal.tsx +0 -22
- package/src/components/Node.spec.tsx +0 -101
- package/src/components/Node.tsx +0 -21
- package/src/components/Subgraph.tsx +0 -30
- package/src/contexts/CurrentGraph.ts +0 -5
- package/src/contexts/GraphContainer.ts +0 -5
- package/src/contexts/GraphMap.ts +0 -5
- package/src/contexts/GraphvizContext.ts +0 -11
- package/src/hooks/__tests__/wrapper.tsx +0 -58
- package/src/hooks/useCurrentGraph.spec.ts +0 -56
- package/src/hooks/useCurrentGraph.ts +0 -18
- package/src/hooks/useDigraph.spec.ts +0 -15
- package/src/hooks/useDigraph.ts +0 -33
- package/src/hooks/useEdge.spec.ts +0 -46
- package/src/hooks/useEdge.ts +0 -35
- package/src/hooks/useGraph.spec.ts +0 -15
- package/src/hooks/useGraph.ts +0 -33
- package/src/hooks/useGraphAttributes.ts +0 -32
- package/src/hooks/useGraphContainer.spec.ts +0 -45
- package/src/hooks/useGraphContainer.ts +0 -10
- package/src/hooks/useGraphMap.ts +0 -7
- package/src/hooks/useGraphvizContext.spec.ts +0 -26
- package/src/hooks/useGraphvizContext.ts +0 -16
- package/src/hooks/useHasAttributes.ts +0 -16
- package/src/hooks/useHasComment.ts +0 -8
- package/src/hooks/useNode.spec.ts +0 -16
- package/src/hooks/useNode.ts +0 -29
- package/src/hooks/useRenderedID.spec.tsx +0 -28
- package/src/hooks/useRenderedID.ts +0 -6
- package/src/hooks/useSubgraph.spec.ts +0 -41
- package/src/hooks/useSubgraph.ts +0 -39
- package/src/react.ts +0 -16
- package/src/reconciler.ts +0 -272
- package/src/render.test.tsx +0 -71
- package/src/render.ts +0 -142
- package/src/renderHTMLLike.ts +0 -9
- package/src/renderId.ts +0 -9
- package/src/types.ts +0 -107
- package/tsconfig.json +0 -8
- package/typedoc.json +0 -5
- package/vite.config.ts +0 -31
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { renderHook } from '@testing-library/react';
|
|
3
|
-
import { Node } from 'ts-graphviz';
|
|
4
|
-
import { describe, expect, it } from 'vitest';
|
|
5
|
-
|
|
6
|
-
import { digraph } from './__tests__/wrapper.js';
|
|
7
|
-
import { useNode } from './useNode.js';
|
|
8
|
-
|
|
9
|
-
describe('useNode', () => {
|
|
10
|
-
it('returns Node instance', () => {
|
|
11
|
-
const { result } = renderHook(() => useNode('hoge'), {
|
|
12
|
-
wrapper: digraph(),
|
|
13
|
-
});
|
|
14
|
-
expect(result.current).toBeInstanceOf(Node);
|
|
15
|
-
});
|
|
16
|
-
});
|
package/src/hooks/useNode.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo } from 'react';
|
|
2
|
-
import type { NodeModel } from 'ts-graphviz';
|
|
3
|
-
import type { NodeOptions } from '../types.js';
|
|
4
|
-
import { useCurrentGraph } from './useCurrentGraph.js';
|
|
5
|
-
import { useHasAttributes } from './useHasAttributes.js';
|
|
6
|
-
import { useHasComment } from './useHasComment.js';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* `useNode` is a hook that creates an instance of Node
|
|
10
|
-
* according to the object given by props.
|
|
11
|
-
*/
|
|
12
|
-
export function useNode(id: string, options: NodeOptions = {}): NodeModel {
|
|
13
|
-
const { comment, ...attributes } = options;
|
|
14
|
-
const cluster = useCurrentGraph();
|
|
15
|
-
const node = useMemo(() => {
|
|
16
|
-
const n = cluster.createNode(id);
|
|
17
|
-
n.attributes.apply(attributes);
|
|
18
|
-
n.comment = comment;
|
|
19
|
-
return n;
|
|
20
|
-
}, [cluster, id, attributes, comment]);
|
|
21
|
-
useHasComment(node, comment);
|
|
22
|
-
useHasAttributes(node, attributes);
|
|
23
|
-
useEffect(() => {
|
|
24
|
-
return (): void => {
|
|
25
|
-
cluster.removeNode(node);
|
|
26
|
-
};
|
|
27
|
-
}, [cluster, node]);
|
|
28
|
-
return node;
|
|
29
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { renderHook } from '@testing-library/react';
|
|
3
|
-
import { describe, expect, it } from 'vitest';
|
|
4
|
-
import { context } from './__tests__/wrapper.js';
|
|
5
|
-
import { useRenderedID } from './useRenderedID.js';
|
|
6
|
-
|
|
7
|
-
describe('useRenderedID', () => {
|
|
8
|
-
it('should return the same value as the input, when input is string', () => {
|
|
9
|
-
const { result } = renderHook(() => useRenderedID('foo'), {
|
|
10
|
-
wrapper: context(),
|
|
11
|
-
});
|
|
12
|
-
expect(result.current).toBe('foo');
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it('should return the same value as the input, when input is HTMLLike string', () => {
|
|
16
|
-
const { result } = renderHook(() => useRenderedID('<<b>bold</b>>'), {
|
|
17
|
-
wrapper: context(),
|
|
18
|
-
});
|
|
19
|
-
expect(result.current).toBe('<<b>bold</b>>');
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it('should return the HTMLLike string, when input is JSX', () => {
|
|
23
|
-
const { result } = renderHook(() => useRenderedID(<dot:b>bold</dot:b>), {
|
|
24
|
-
wrapper: context(),
|
|
25
|
-
});
|
|
26
|
-
expect(result.current).toBe('<<b>bold</b>>');
|
|
27
|
-
});
|
|
28
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// @vitest-environment jsdom
|
|
2
|
-
import { renderHook } from '@testing-library/react';
|
|
3
|
-
import { Subgraph } from 'ts-graphviz';
|
|
4
|
-
import { describe, expect, it } from 'vitest';
|
|
5
|
-
import {
|
|
6
|
-
digraph,
|
|
7
|
-
digraphInSubgraph,
|
|
8
|
-
graph,
|
|
9
|
-
graphInSubgraph,
|
|
10
|
-
} from './__tests__/wrapper.js';
|
|
11
|
-
import { useSubgraph } from './useSubgraph.js';
|
|
12
|
-
|
|
13
|
-
describe('useSubgraph', () => {
|
|
14
|
-
it('returns Subgraph instance in digraph warper', () => {
|
|
15
|
-
const { result } = renderHook(() => useSubgraph(), {
|
|
16
|
-
wrapper: digraph(),
|
|
17
|
-
});
|
|
18
|
-
expect(result.current).toBeInstanceOf(Subgraph);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it('returns Subgraph instance in graph warper', () => {
|
|
22
|
-
const { result } = renderHook(() => useSubgraph(), {
|
|
23
|
-
wrapper: graph(),
|
|
24
|
-
});
|
|
25
|
-
expect(result.current).toBeInstanceOf(Subgraph);
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('returns Subgraph instance in graphInSubgraph warper', () => {
|
|
29
|
-
const { result } = renderHook(() => useSubgraph(), {
|
|
30
|
-
wrapper: graphInSubgraph(),
|
|
31
|
-
});
|
|
32
|
-
expect(result.current).toBeInstanceOf(Subgraph);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
it('returns Subgraph instance in digraphInSubgraph warper', () => {
|
|
36
|
-
const { result } = renderHook(() => useSubgraph(), {
|
|
37
|
-
wrapper: digraphInSubgraph(),
|
|
38
|
-
});
|
|
39
|
-
expect(result.current).toBeInstanceOf(Subgraph);
|
|
40
|
-
});
|
|
41
|
-
});
|
package/src/hooks/useSubgraph.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo } from 'react';
|
|
2
|
-
import { type GraphBaseModel, Subgraph, type SubgraphModel } from 'ts-graphviz';
|
|
3
|
-
import type { SubgraphOptions } from '../types.js';
|
|
4
|
-
import { useCurrentGraph } from './useCurrentGraph.js';
|
|
5
|
-
import { useGraphAttributes } from './useGraphAttributes.js';
|
|
6
|
-
import { useGraphvizContext } from './useGraphvizContext.js';
|
|
7
|
-
import { useHasComment } from './useHasComment.js';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* `useSubgraph` is a hook that creates an instance of Subgraph
|
|
11
|
-
* according to the object given by props.
|
|
12
|
-
*/
|
|
13
|
-
export function useSubgraph(props: SubgraphOptions = {}): SubgraphModel {
|
|
14
|
-
const { id, comment, edge, node, graph, ...attributes } = props;
|
|
15
|
-
const context = useGraphvizContext();
|
|
16
|
-
const cluster = useCurrentGraph();
|
|
17
|
-
const subgraph = useMemo(() => {
|
|
18
|
-
const g = new Subgraph(id);
|
|
19
|
-
if (cluster !== null) {
|
|
20
|
-
cluster.addSubgraph(g);
|
|
21
|
-
} else if (!context.container) {
|
|
22
|
-
context.container = g as GraphBaseModel;
|
|
23
|
-
}
|
|
24
|
-
g.comment = comment;
|
|
25
|
-
g.apply(attributes);
|
|
26
|
-
g.attributes.node.apply(node ?? {});
|
|
27
|
-
g.attributes.edge.apply(edge ?? {});
|
|
28
|
-
g.attributes.graph.apply(graph ?? {});
|
|
29
|
-
return g;
|
|
30
|
-
}, [context, cluster, id, comment, edge, node, graph, attributes]);
|
|
31
|
-
useHasComment(subgraph, comment);
|
|
32
|
-
useGraphAttributes(subgraph, attributes, { edge, node, graph });
|
|
33
|
-
useEffect(() => {
|
|
34
|
-
return (): void => {
|
|
35
|
-
cluster.removeSubgraph(subgraph);
|
|
36
|
-
};
|
|
37
|
-
}, [cluster, subgraph]);
|
|
38
|
-
return subgraph;
|
|
39
|
-
}
|
package/src/react.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export * from './types.js';
|
|
2
|
-
export * from './hooks/useGraphContainer.js';
|
|
3
|
-
export * from './hooks/useCurrentGraph.js';
|
|
4
|
-
export * from './hooks/useDigraph.js';
|
|
5
|
-
export * from './hooks/useGraph.js';
|
|
6
|
-
export * from './hooks/useSubgraph.js';
|
|
7
|
-
export * from './hooks/useEdge.js';
|
|
8
|
-
export * from './hooks/useNode.js';
|
|
9
|
-
export * from './components/Graph.js';
|
|
10
|
-
export * from './components/Digraph.js';
|
|
11
|
-
export * from './components/Subgraph.js';
|
|
12
|
-
export * from './components/Node.js';
|
|
13
|
-
export * from './components/Edge.js';
|
|
14
|
-
export * from './components/GraphPortal.js';
|
|
15
|
-
export * from './renderHTMLLike.js';
|
|
16
|
-
export * from './render.js';
|
package/src/reconciler.ts
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import type { FC } from 'react';
|
|
2
|
-
import ReactReconciler from 'react-reconciler';
|
|
3
|
-
|
|
4
|
-
type Type = FC;
|
|
5
|
-
type Props = any;
|
|
6
|
-
type Container = Record<string, never>;
|
|
7
|
-
|
|
8
|
-
type Instance = any;
|
|
9
|
-
type TextInstance = any;
|
|
10
|
-
type SuspenseInstance = any;
|
|
11
|
-
type HydratableInstance = any;
|
|
12
|
-
type PublicInstance = any;
|
|
13
|
-
type HostContext = any;
|
|
14
|
-
type UpdatePayload = any;
|
|
15
|
-
type ChildSet = any;
|
|
16
|
-
type TimeoutHandle = any;
|
|
17
|
-
type NoTimeout = any;
|
|
18
|
-
|
|
19
|
-
type OpaqueHandle = ReactReconciler.Fiber;
|
|
20
|
-
|
|
21
|
-
export class HostConfig
|
|
22
|
-
implements
|
|
23
|
-
ReactReconciler.HostConfig<
|
|
24
|
-
Type,
|
|
25
|
-
Props,
|
|
26
|
-
Container,
|
|
27
|
-
Instance,
|
|
28
|
-
TextInstance,
|
|
29
|
-
SuspenseInstance,
|
|
30
|
-
HydratableInstance,
|
|
31
|
-
PublicInstance,
|
|
32
|
-
HostContext,
|
|
33
|
-
UpdatePayload,
|
|
34
|
-
ChildSet, // TODO Placeholder for undocumented API
|
|
35
|
-
TimeoutHandle,
|
|
36
|
-
NoTimeout
|
|
37
|
-
>
|
|
38
|
-
{
|
|
39
|
-
preparePortalMount(containerInfo: Container): void {
|
|
40
|
-
// NoOp
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
scheduleTimeout(fn: (...args: unknown[]) => unknown, delay?: number) {
|
|
44
|
-
// NoOp
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
cancelTimeout(id: any): void {
|
|
48
|
-
// NoOp
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
queueMicrotask(fn: () => void): void {
|
|
52
|
-
// NoOp
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
cloneInstance?: any;
|
|
56
|
-
|
|
57
|
-
cloneFundamentalInstance?: any;
|
|
58
|
-
|
|
59
|
-
createContainerChildSet?: any;
|
|
60
|
-
|
|
61
|
-
appendChildToContainerChildSet?: any;
|
|
62
|
-
|
|
63
|
-
finalizeContainerChildren?: any;
|
|
64
|
-
|
|
65
|
-
replaceContainerChildren?: any;
|
|
66
|
-
|
|
67
|
-
cloneHiddenInstance?: any;
|
|
68
|
-
|
|
69
|
-
cloneHiddenTextInstance?: any;
|
|
70
|
-
|
|
71
|
-
public now = Date.now;
|
|
72
|
-
|
|
73
|
-
public setTimeout = setTimeout;
|
|
74
|
-
|
|
75
|
-
public clearTimeout = clearTimeout;
|
|
76
|
-
|
|
77
|
-
public noTimeout: NoTimeout = -1; // TODO
|
|
78
|
-
|
|
79
|
-
// Temporary workaround for scenario where multiple renderers concurrently
|
|
80
|
-
// render using the same context objects. E.g. React DOM and React ART on the
|
|
81
|
-
// same page. DOM is the primary renderer; ART is the secondary renderer.
|
|
82
|
-
public isPrimaryRenderer = false;
|
|
83
|
-
|
|
84
|
-
public supportsMutation = false;
|
|
85
|
-
|
|
86
|
-
public supportsPersistence = false;
|
|
87
|
-
|
|
88
|
-
public supportsHydration = false;
|
|
89
|
-
|
|
90
|
-
public getPublicInstance(instance: Instance | TextInstance): PublicInstance {
|
|
91
|
-
return instance;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
public getRootHostContext(rootContainerInstance: Container): HostContext {
|
|
95
|
-
return {};
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
public getChildHostContext(
|
|
99
|
-
parentHostContext: HostContext,
|
|
100
|
-
type: Type,
|
|
101
|
-
rootContainerInstance: Container,
|
|
102
|
-
): HostContext {
|
|
103
|
-
return parentHostContext;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
public prepareForCommit(
|
|
107
|
-
containerInfo: Container,
|
|
108
|
-
): Record<string, any> | null {
|
|
109
|
-
return null;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
public resetAfterCommit(containerInfo: Container): void {
|
|
113
|
-
// containerInfo.setRoot
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Create component instance
|
|
118
|
-
*/
|
|
119
|
-
public createInstance(
|
|
120
|
-
type: Type,
|
|
121
|
-
props: Props,
|
|
122
|
-
rootContainerInstance: Container,
|
|
123
|
-
hostContext: HostContext,
|
|
124
|
-
internalInstanceHandle: OpaqueHandle,
|
|
125
|
-
): Instance {
|
|
126
|
-
// NoOp
|
|
127
|
-
return type(props);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
public appendInitialChild(
|
|
131
|
-
parentInstance: Instance,
|
|
132
|
-
child: Instance | TextInstance,
|
|
133
|
-
): void {
|
|
134
|
-
parentInstance.appendChild(child);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public finalizeInitialChildren(
|
|
138
|
-
parentInstance: Instance,
|
|
139
|
-
type: Type,
|
|
140
|
-
props: Props,
|
|
141
|
-
rootContainerInstance: Container,
|
|
142
|
-
hostContext: HostContext,
|
|
143
|
-
): boolean {
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
public prepareUpdate(
|
|
148
|
-
instance: Instance,
|
|
149
|
-
type: Type,
|
|
150
|
-
oldProps: Props,
|
|
151
|
-
newProps: Props,
|
|
152
|
-
rootContainerInstance: Container,
|
|
153
|
-
hostContext: HostContext,
|
|
154
|
-
): null | UpdatePayload {
|
|
155
|
-
return {};
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
public shouldSetTextContent(type: Type, props: Props): boolean {
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
public shouldDeprioritizeSubtree(type: Type, props: Props): boolean {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
public createTextInstance(
|
|
167
|
-
text: string,
|
|
168
|
-
rootContainerInstance: Container,
|
|
169
|
-
hostContext: HostContext,
|
|
170
|
-
internalInstanceHandle: OpaqueHandle,
|
|
171
|
-
): TextInstance {
|
|
172
|
-
return text;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
public scheduleDeferredCallback(
|
|
176
|
-
callback: () => any,
|
|
177
|
-
options?: { timeout: number },
|
|
178
|
-
): any {
|
|
179
|
-
// NoOp
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
public cancelDeferredCallback(callbackID: any): void {
|
|
183
|
-
// NoOp
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// -------------------
|
|
187
|
-
// Mutation
|
|
188
|
-
// (optional)
|
|
189
|
-
// -------------------
|
|
190
|
-
public appendChild(
|
|
191
|
-
parentInstance: Instance,
|
|
192
|
-
child: Instance | TextInstance,
|
|
193
|
-
): void {
|
|
194
|
-
// NoOp
|
|
195
|
-
if (parentInstance.appendChild) {
|
|
196
|
-
parentInstance.appendChild(child);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
public appendChildToContainer(
|
|
201
|
-
container: Container,
|
|
202
|
-
child: Instance | TextInstance,
|
|
203
|
-
): void {
|
|
204
|
-
// if (container.appendChild) {
|
|
205
|
-
// container.appendChild(child);
|
|
206
|
-
// }
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
public commitTextUpdate(
|
|
210
|
-
textInstance: TextInstance,
|
|
211
|
-
oldText: string,
|
|
212
|
-
newText: string,
|
|
213
|
-
): void {
|
|
214
|
-
// NoOp
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
public commitMount(
|
|
218
|
-
instance: Instance,
|
|
219
|
-
type: Type,
|
|
220
|
-
newProps: Props,
|
|
221
|
-
internalInstanceHandle: OpaqueHandle,
|
|
222
|
-
): void {
|
|
223
|
-
// NoOp
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
public commitUpdate(
|
|
227
|
-
instance: Instance,
|
|
228
|
-
updatePayload: UpdatePayload,
|
|
229
|
-
type: Type,
|
|
230
|
-
oldProps: Props,
|
|
231
|
-
newProps: Props,
|
|
232
|
-
internalInstanceHandle: OpaqueHandle,
|
|
233
|
-
): void {
|
|
234
|
-
// NoOp
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
public insertBefore(
|
|
238
|
-
parentInstance: Instance,
|
|
239
|
-
child: Instance | TextInstance,
|
|
240
|
-
beforeChild: Instance | TextInstance,
|
|
241
|
-
): void {
|
|
242
|
-
// NoOp
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
public insertInContainerBefore(
|
|
246
|
-
container: Container,
|
|
247
|
-
child: Instance | TextInstance,
|
|
248
|
-
beforeChild: Instance | TextInstance,
|
|
249
|
-
): void {
|
|
250
|
-
// NoOp
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
public removeChild(
|
|
254
|
-
parentInstance: Instance,
|
|
255
|
-
child: Instance | TextInstance,
|
|
256
|
-
): void {
|
|
257
|
-
// NoOp
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
public removeChildFromContainer(
|
|
261
|
-
container: Container,
|
|
262
|
-
child: Instance | TextInstance,
|
|
263
|
-
): void {
|
|
264
|
-
// NoOp
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
public resetTextContent(instance: Instance): void {
|
|
268
|
-
// NoOp
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export const reconciler = ReactReconciler(new HostConfig());
|
package/src/render.test.tsx
DELETED
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { Digraph } from './components/Digraph.js';
|
|
3
|
-
import { Edge } from './components/Edge.js';
|
|
4
|
-
import { Graph } from './components/Graph.js';
|
|
5
|
-
import { Node } from './components/Node.js';
|
|
6
|
-
import { Subgraph } from './components/Subgraph.js';
|
|
7
|
-
import { renderToDot } from './render.js';
|
|
8
|
-
|
|
9
|
-
describe('renderToDot', () => {
|
|
10
|
-
it('should render a digraph', () => {
|
|
11
|
-
expect(
|
|
12
|
-
renderToDot(
|
|
13
|
-
<Digraph>
|
|
14
|
-
<Node id="a" label="Node A" />
|
|
15
|
-
<Node id="b" label={<dot:b>bold</dot:b>} />
|
|
16
|
-
<Subgraph id="cluster_x" label="Cluster X">
|
|
17
|
-
<Node id="c" label="Node C" />
|
|
18
|
-
</Subgraph>
|
|
19
|
-
<Edge targets={['a', 'b']} />
|
|
20
|
-
</Digraph>,
|
|
21
|
-
),
|
|
22
|
-
).toMatchInlineSnapshot(`
|
|
23
|
-
"digraph {
|
|
24
|
-
"a" [
|
|
25
|
-
label = "Node A";
|
|
26
|
-
];
|
|
27
|
-
"b" [
|
|
28
|
-
label = <<b>bold</b>>;
|
|
29
|
-
];
|
|
30
|
-
subgraph "cluster_x" {
|
|
31
|
-
label = "Cluster X";
|
|
32
|
-
"c" [
|
|
33
|
-
label = "Node C";
|
|
34
|
-
];
|
|
35
|
-
}
|
|
36
|
-
"a" -> "b";
|
|
37
|
-
}"
|
|
38
|
-
`);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it('should render a graph', () => {
|
|
42
|
-
expect(
|
|
43
|
-
renderToDot(
|
|
44
|
-
<Graph>
|
|
45
|
-
<Node id="a" label="Node A" />
|
|
46
|
-
<Node id="b" label="Node B" />
|
|
47
|
-
<Subgraph id="cluster_x" label="Cluster X">
|
|
48
|
-
<Node id="c" label="Node C" />
|
|
49
|
-
</Subgraph>
|
|
50
|
-
<Edge targets={['a', 'b']} />
|
|
51
|
-
</Graph>,
|
|
52
|
-
),
|
|
53
|
-
).toMatchInlineSnapshot(`
|
|
54
|
-
"graph {
|
|
55
|
-
"a" [
|
|
56
|
-
label = "Node A";
|
|
57
|
-
];
|
|
58
|
-
"b" [
|
|
59
|
-
label = "Node B";
|
|
60
|
-
];
|
|
61
|
-
subgraph "cluster_x" {
|
|
62
|
-
label = "Cluster X";
|
|
63
|
-
"c" [
|
|
64
|
-
label = "Node C";
|
|
65
|
-
];
|
|
66
|
-
}
|
|
67
|
-
"a" -- "b";
|
|
68
|
-
}"
|
|
69
|
-
`);
|
|
70
|
-
});
|
|
71
|
-
});
|
package/src/render.ts
DELETED
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
import { type ReactElement, createElement } from 'react';
|
|
2
|
-
import { type GraphBaseModel, type RootGraphModel, toDot } from 'ts-graphviz';
|
|
3
|
-
|
|
4
|
-
import { CurrentGraph } from './contexts/CurrentGraph.js';
|
|
5
|
-
import { GraphContainer } from './contexts/GraphContainer.js';
|
|
6
|
-
import { GraphMap } from './contexts/GraphMap.js';
|
|
7
|
-
import { type Context, GraphvizContext } from './contexts/GraphvizContext.js';
|
|
8
|
-
import { reconciler } from './reconciler.js';
|
|
9
|
-
|
|
10
|
-
const noop = (): void => undefined;
|
|
11
|
-
|
|
12
|
-
function clusterMap(
|
|
13
|
-
graph?: GraphBaseModel,
|
|
14
|
-
map: Map<string, GraphBaseModel> = new Map(),
|
|
15
|
-
): Map<string, GraphBaseModel> {
|
|
16
|
-
if (graph) {
|
|
17
|
-
if (graph.id) {
|
|
18
|
-
map.set(graph.id, graph);
|
|
19
|
-
}
|
|
20
|
-
for (const s of graph.subgraphs) {
|
|
21
|
-
clusterMap(s, map);
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return map;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Convert the given element to Graphviz model.
|
|
29
|
-
*
|
|
30
|
-
* @example Example of giving a cluster as a container with the second argument.
|
|
31
|
-
*
|
|
32
|
-
* ```tsx
|
|
33
|
-
* import React, { FC } from 'react';
|
|
34
|
-
* import { digraph, toDot } from 'ts-graphviz';
|
|
35
|
-
* import { Node, Subgraph, render, Edge } from '@ts-graphviz/react';
|
|
36
|
-
*
|
|
37
|
-
* const Example: FC = () => (
|
|
38
|
-
* <>
|
|
39
|
-
* <Node id="a" />
|
|
40
|
-
*
|
|
41
|
-
* <Subgraph id="my_cluster">
|
|
42
|
-
* <Node id="b" />
|
|
43
|
-
* </Subgraph>
|
|
44
|
-
* <Edge targets={['b', 'a']} />
|
|
45
|
-
* </>
|
|
46
|
-
* );
|
|
47
|
-
*
|
|
48
|
-
* const G = digraph((g) => render(<Example />, g));
|
|
49
|
-
* console.log(toDot(G));
|
|
50
|
-
* // digraph {
|
|
51
|
-
* // "a";
|
|
52
|
-
* // subgraph "my_cluster" {
|
|
53
|
-
* // "b";
|
|
54
|
-
* // }
|
|
55
|
-
* // "b" -> "a";
|
|
56
|
-
* // }
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
export function render<T extends GraphBaseModel>(
|
|
60
|
-
element: ReactElement,
|
|
61
|
-
container?: T,
|
|
62
|
-
): T {
|
|
63
|
-
const context: Context<T> = { container };
|
|
64
|
-
reconciler.updateContainer(
|
|
65
|
-
createElement(
|
|
66
|
-
GraphvizContext.Provider,
|
|
67
|
-
{ value: context },
|
|
68
|
-
createElement(
|
|
69
|
-
GraphMap.Provider,
|
|
70
|
-
{ value: clusterMap(container) },
|
|
71
|
-
createElement(
|
|
72
|
-
GraphContainer.Provider,
|
|
73
|
-
{ value: container ?? null },
|
|
74
|
-
container
|
|
75
|
-
? createElement(
|
|
76
|
-
CurrentGraph.Provider,
|
|
77
|
-
{ value: container },
|
|
78
|
-
element,
|
|
79
|
-
)
|
|
80
|
-
: element,
|
|
81
|
-
),
|
|
82
|
-
),
|
|
83
|
-
),
|
|
84
|
-
reconciler.createContainer(
|
|
85
|
-
{},
|
|
86
|
-
0,
|
|
87
|
-
null,
|
|
88
|
-
true,
|
|
89
|
-
null,
|
|
90
|
-
'@ts-graphviz/react',
|
|
91
|
-
noop,
|
|
92
|
-
null,
|
|
93
|
-
),
|
|
94
|
-
null,
|
|
95
|
-
noop,
|
|
96
|
-
);
|
|
97
|
-
if (!context.container) {
|
|
98
|
-
throw Error(
|
|
99
|
-
'There are no clusters of container(Subgraph, Digraph, Graph).',
|
|
100
|
-
);
|
|
101
|
-
}
|
|
102
|
-
return context.container;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Converts the given element to DOT language and returns it.
|
|
107
|
-
*
|
|
108
|
-
* @example
|
|
109
|
-
*
|
|
110
|
-
* ```tsx
|
|
111
|
-
* import React, { FC } from 'react';
|
|
112
|
-
* import { Digraph, Node, Subgraph, renderToDot, Edge } from '@ts-graphviz/react';
|
|
113
|
-
*
|
|
114
|
-
* const Example: FC = () => (
|
|
115
|
-
* <Digraph>
|
|
116
|
-
* <Node id="a" />
|
|
117
|
-
* <Subgraph id="my_cluster">
|
|
118
|
-
* <Node id="b" />
|
|
119
|
-
* </Subgraph>
|
|
120
|
-
* <Edge targets={['b', 'a']} />
|
|
121
|
-
* </Digraph>
|
|
122
|
-
* );
|
|
123
|
-
*
|
|
124
|
-
* const dot = renderToDot(<Example />);
|
|
125
|
-
* console.log(dot);
|
|
126
|
-
* // digraph {
|
|
127
|
-
* // "a";
|
|
128
|
-
* // subgraph "my_cluster" {
|
|
129
|
-
* // "b";
|
|
130
|
-
* // }
|
|
131
|
-
* // "b" -> "a";
|
|
132
|
-
* // }
|
|
133
|
-
* ```
|
|
134
|
-
*
|
|
135
|
-
* @returns Rendered dot string
|
|
136
|
-
*/
|
|
137
|
-
export function renderToDot(
|
|
138
|
-
element: ReactElement,
|
|
139
|
-
container?: RootGraphModel,
|
|
140
|
-
): string {
|
|
141
|
-
return toDot(render(element, container));
|
|
142
|
-
}
|
package/src/renderHTMLLike.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { ReactElement } from 'react';
|
|
2
|
-
import { renderToStaticMarkup } from 'react-dom/server';
|
|
3
|
-
|
|
4
|
-
export function renderHTMLLike(label?: ReactElement): string {
|
|
5
|
-
const htmlLike = renderToStaticMarkup(label)
|
|
6
|
-
.replace(/<dot:port>(.+?)<\/dot:port>/gi, '<$1>')
|
|
7
|
-
.replace(/<(\/?)dot:([a-z-]+)/gi, (_, $1, $2) => `<${$1}${$2}`);
|
|
8
|
-
return `<${htmlLike}>`;
|
|
9
|
-
}
|
package/src/renderId.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { type ReactElement, isValidElement } from 'react';
|
|
2
|
-
import { renderHTMLLike } from './renderHTMLLike.js';
|
|
3
|
-
|
|
4
|
-
export function renderId<T>(id?: ReactElement<T> | string): string | undefined {
|
|
5
|
-
if (isValidElement(id)) {
|
|
6
|
-
return renderHTMLLike(id);
|
|
7
|
-
}
|
|
8
|
-
return id;
|
|
9
|
-
}
|