@ts-graphviz/ast 0.0.0-pr956-20240225073457

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.
Files changed (74) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/LICENSE +22 -0
  3. package/README.md +42 -0
  4. package/lib/ast.cjs +3952 -0
  5. package/lib/ast.d.ts +881 -0
  6. package/lib/ast.js +3952 -0
  7. package/package.json +52 -0
  8. package/src/ast.ts +8 -0
  9. package/src/builder/__snapshots__/create-element.test.ts.snap +166 -0
  10. package/src/builder/builder.test.ts +36 -0
  11. package/src/builder/builder.ts +44 -0
  12. package/src/builder/create-element.test.ts +110 -0
  13. package/src/builder/create-element.ts +13 -0
  14. package/src/builder/index.ts +3 -0
  15. package/src/builder/types.ts +226 -0
  16. package/src/dot-shim/index.ts +2 -0
  17. package/src/dot-shim/parser/__snapshots__/parse.test.ts.snap +2613 -0
  18. package/src/dot-shim/parser/dot.peggy +396 -0
  19. package/src/dot-shim/parser/index.ts +1 -0
  20. package/src/dot-shim/parser/parse.test.ts +263 -0
  21. package/src/dot-shim/parser/parse.ts +121 -0
  22. package/src/dot-shim/parser/peggy.options.json +15 -0
  23. package/src/dot-shim/printer/index.ts +6 -0
  24. package/src/dot-shim/printer/plugins/AttributeListPrintPlugin.ts +22 -0
  25. package/src/dot-shim/printer/plugins/AttributePrintPlugin.ts +11 -0
  26. package/src/dot-shim/printer/plugins/CommentPrintPlugin.ts +40 -0
  27. package/src/dot-shim/printer/plugins/DotPrintPlugin.ts +12 -0
  28. package/src/dot-shim/printer/plugins/EdgePrintPlugin.ts +27 -0
  29. package/src/dot-shim/printer/plugins/GraphPrintPlugin.ts +32 -0
  30. package/src/dot-shim/printer/plugins/LiteralPrintPlugin.ts +24 -0
  31. package/src/dot-shim/printer/plugins/NodePrintPlugin.ts +24 -0
  32. package/src/dot-shim/printer/plugins/NodeRefGroupPrintPlugin.ts +17 -0
  33. package/src/dot-shim/printer/plugins/NodeRefPrintPlugin.ts +18 -0
  34. package/src/dot-shim/printer/plugins/SubgraphPrintPlugin.ts +27 -0
  35. package/src/dot-shim/printer/plugins/index.ts +26 -0
  36. package/src/dot-shim/printer/plugins/utils/index.ts +1 -0
  37. package/src/dot-shim/printer/plugins/utils/tokens.ts +51 -0
  38. package/src/dot-shim/printer/printer.ts +46 -0
  39. package/src/dot-shim/printer/stringify.test.ts +823 -0
  40. package/src/dot-shim/printer/stringify.ts +19 -0
  41. package/src/dot-shim/printer/types.ts +74 -0
  42. package/src/model-shim/from-model/converter.ts +43 -0
  43. package/src/model-shim/from-model/from-model.ts +19 -0
  44. package/src/model-shim/from-model/index.ts +3 -0
  45. package/src/model-shim/from-model/plugins/AttributeListPlugin.ts +19 -0
  46. package/src/model-shim/from-model/plugins/EdgePlugin.ts +140 -0
  47. package/src/model-shim/from-model/plugins/GraphPlugin.ts +36 -0
  48. package/src/model-shim/from-model/plugins/NodePlugin.ts +33 -0
  49. package/src/model-shim/from-model/plugins/SubraphPlugin.ts +28 -0
  50. package/src/model-shim/from-model/plugins/index.ts +13 -0
  51. package/src/model-shim/from-model/plugins/utils/convert-attribute.ts +47 -0
  52. package/src/model-shim/from-model/plugins/utils/convert-cluster-children.ts +44 -0
  53. package/src/model-shim/from-model/plugins/utils/convert-comment.ts +16 -0
  54. package/src/model-shim/from-model/plugins/utils/index.ts +3 -0
  55. package/src/model-shim/from-model/types.ts +62 -0
  56. package/src/model-shim/index.ts +2 -0
  57. package/src/model-shim/to-model/converter.ts +42 -0
  58. package/src/model-shim/to-model/index.ts +3 -0
  59. package/src/model-shim/to-model/plugins/DotPlugin.ts +25 -0
  60. package/src/model-shim/to-model/plugins/EdgePlugin.ts +26 -0
  61. package/src/model-shim/to-model/plugins/GraphPlugin.ts +15 -0
  62. package/src/model-shim/to-model/plugins/NodePlugin.ts +25 -0
  63. package/src/model-shim/to-model/plugins/SubgraphPlugin.ts +14 -0
  64. package/src/model-shim/to-model/plugins/index.ts +13 -0
  65. package/src/model-shim/to-model/plugins/utils/apply-statments.ts +96 -0
  66. package/src/model-shim/to-model/plugins/utils/comment-holder.ts +31 -0
  67. package/src/model-shim/to-model/plugins/utils/convert-to-edge-target-tuple.ts +21 -0
  68. package/src/model-shim/to-model/to-model.test.ts +34 -0
  69. package/src/model-shim/to-model/to-model.ts +16 -0
  70. package/src/model-shim/to-model/types.ts +71 -0
  71. package/src/types.ts +370 -0
  72. package/tsconfig.json +8 -0
  73. package/typedoc.json +4 -0
  74. package/vite.config.ts +22 -0
@@ -0,0 +1,121 @@
1
+ import type {
2
+ ASTNode,
3
+ AttributeASTNode,
4
+ AttributeListASTNode,
5
+ ClusterStatementASTNode,
6
+ DotASTNode,
7
+ EdgeASTNode,
8
+ GraphASTNode,
9
+ NodeASTNode,
10
+ SubgraphASTNode,
11
+ } from '../../types.js';
12
+ import { PeggySyntaxError, parse as _parse } from './_parse.js';
13
+ /**
14
+ * @group Convert DOT to AST
15
+ */
16
+ export type Rule =
17
+ | 'Dot'
18
+ | 'Graph'
19
+ | 'Node'
20
+ | 'Edge'
21
+ | 'AttributeList'
22
+ | 'Attribute'
23
+ | 'Subgraph'
24
+ | 'ClusterStatements';
25
+
26
+ /**
27
+ * CommonParseOptions is an interface that defines the properties needed in order to parse a file.
28
+ * @group Convert DOT to AST
29
+ */
30
+ export interface CommonParseOptions {
31
+ /**
32
+ * filename (optional): A string value that is used to identify the file to be parsed.
33
+ */
34
+ filename?: string;
35
+ }
36
+
37
+ /**
38
+ * ParseOptions interface is used to provide additional information to the parser while parsing a rule.
39
+ * @template T The type of the rule to be parsed.
40
+ * @group Convert DOT to AST
41
+ */
42
+ export interface ParseOptions<T extends Rule> extends CommonParseOptions {
43
+ startRule?: T;
44
+ }
45
+
46
+ /**
47
+ * parse is a function that takes a string input and optional parse options and
48
+ * returns an ASTNode or an array of ClusterStatementASTNodes.
49
+ *
50
+ * Depending on the type of parse option specified, the function will return different types of ASTNodes.
51
+ *
52
+ * The types of ASTNodes that can be returned are:
53
+ *
54
+ * - {@link DotASTNode}
55
+ * - {@link GraphASTNode}
56
+ * - {@link NodeASTNode}
57
+ * - {@link EdgeASTNode}
58
+ * - {@link AttributeListASTNode}
59
+ * - {@link AttributeASTNode}
60
+ * - {@link SubgraphASTNode}
61
+ * - {@link ClusterStatementASTNode}
62
+ *
63
+ * @throws {@link SyntaxError}
64
+ * @group Convert DOT to AST
65
+ */
66
+ export function parse(input: string): DotASTNode;
67
+ export function parse(input: string, options?: ParseOptions<'Dot'>): DotASTNode;
68
+ export function parse(
69
+ input: string,
70
+ options?: ParseOptions<'Graph'>,
71
+ ): GraphASTNode;
72
+ export function parse(
73
+ input: string,
74
+ options?: ParseOptions<'Node'>,
75
+ ): NodeASTNode;
76
+ export function parse(
77
+ input: string,
78
+ options?: ParseOptions<'Edge'>,
79
+ ): EdgeASTNode;
80
+ export function parse(
81
+ input: string,
82
+ options?: ParseOptions<'AttributeList'>,
83
+ ): AttributeListASTNode;
84
+ export function parse(
85
+ input: string,
86
+ options?: ParseOptions<'Attribute'>,
87
+ ): AttributeASTNode;
88
+ export function parse(
89
+ input: string,
90
+ options?: ParseOptions<'Subgraph'>,
91
+ ): SubgraphASTNode;
92
+ export function parse(
93
+ input: string,
94
+ options?: ParseOptions<'ClusterStatements'>,
95
+ ): ClusterStatementASTNode[];
96
+ export function parse(
97
+ input: string,
98
+ options?: ParseOptions<Rule>,
99
+ ): ASTNode | ClusterStatementASTNode[];
100
+ export function parse(
101
+ input: string,
102
+ options?: ParseOptions<Rule>,
103
+ ): ASTNode | ClusterStatementASTNode[] {
104
+ try {
105
+ return _parse(input, options);
106
+ } catch (e) {
107
+ if (e instanceof PeggySyntaxError) {
108
+ throw new DotSyntaxError(e.message, e.expected, e.found, e.location);
109
+ }
110
+ throw e;
111
+ }
112
+ }
113
+ /**
114
+ * @group Convert DOT to AST
115
+ */
116
+ export class DotSyntaxError extends PeggySyntaxError {
117
+ constructor(...args: ConstructorParameters<typeof PeggySyntaxError>) {
118
+ super(...args);
119
+ this.name = 'DotSyntaxError';
120
+ }
121
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "allowedStartRules": [
3
+ "Dot",
4
+ "Graph",
5
+ "Subgraph",
6
+ "Node",
7
+ "Edge",
8
+ "AttributeList",
9
+ "Attribute",
10
+ "ClusterStatements"
11
+ ],
12
+ "tspegjs": {
13
+ "customHeader": "import { Builder } from '../../builder/index.js';"
14
+ }
15
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @module ts-graphviz/printer
3
+ */
4
+ export * from './types.js';
5
+ export * from './printer.js';
6
+ export * from './stringify.js';
@@ -0,0 +1,22 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { ASTNode, AttributeListASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { endOfLine, indent, joinBy, wrapByPair } from './utils/index.js';
5
+
6
+ export const AttributeListPrintPlugin: PrintPlugin<AttributeListASTNode> = {
7
+ match(ast: ASTNode) {
8
+ return ast.type === 'AttributeList';
9
+ },
10
+ print(context, ast): string {
11
+ if (ast.children.length === 0) {
12
+ return `${ast.kind.toLocaleLowerCase()} [];`;
13
+ }
14
+ const eol = endOfLine(context.endOfLine);
15
+ return pipe(
16
+ map(context.print),
17
+ joinBy(eol),
18
+ indent(context.indentStyle, context.indentSize, eol),
19
+ wrapByPair(`${ast.kind.toLocaleLowerCase()} [${eol}`, `${eol}];`),
20
+ )(ast.children);
21
+ },
22
+ };
@@ -0,0 +1,11 @@
1
+ import { ASTNode, AttributeASTNode } from '../../../types.js';
2
+ import { PrintPlugin } from '../types.js';
3
+
4
+ export const AttributePrintPlugin: PrintPlugin<AttributeASTNode> = {
5
+ match(ast: ASTNode) {
6
+ return ast.type === 'Attribute';
7
+ },
8
+ print(context, ast): string {
9
+ return `${context.print(ast.key)} = ${context.print(ast.value)};`;
10
+ },
11
+ };
@@ -0,0 +1,40 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { CommentASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import {
5
+ endOfLine,
6
+ joinBy,
7
+ leftPadWith,
8
+ splitByLine,
9
+ wrapByPair,
10
+ } from './utils/index.js';
11
+
12
+ export const CommentPrintPlugin: PrintPlugin<CommentASTNode> = {
13
+ match(ast) {
14
+ return ast.type === 'Comment';
15
+ },
16
+ print(context, ast): string {
17
+ const eol = endOfLine(context.endOfLine);
18
+ switch (ast.kind) {
19
+ case 'Block':
20
+ return pipe(
21
+ splitByLine,
22
+ map(leftPadWith(' * ')),
23
+ joinBy(eol),
24
+ wrapByPair(`/**${eol}`, `${eol} */`),
25
+ )(ast.value);
26
+ case 'Macro':
27
+ return pipe(
28
+ splitByLine,
29
+ map(leftPadWith('# ')),
30
+ joinBy(eol),
31
+ )(ast.value);
32
+ default:
33
+ return pipe(
34
+ splitByLine,
35
+ map(leftPadWith('// ')),
36
+ joinBy(eol),
37
+ )(ast.value);
38
+ }
39
+ },
40
+ };
@@ -0,0 +1,12 @@
1
+ import { DotASTNode } from '../../../types.js';
2
+ import { PrintPlugin } from '../types.js';
3
+ import { endOfLine } from './utils/index.js';
4
+
5
+ export const DotPrintPlugin: PrintPlugin<DotASTNode> = {
6
+ match(ast) {
7
+ return ast.type === 'Dot';
8
+ },
9
+ print(context, ast): string {
10
+ return ast.children.map(context.print).join(endOfLine(context.endOfLine));
11
+ },
12
+ };
@@ -0,0 +1,27 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { EdgeASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { endOfLine, indent, joinBy, wrapByPair } from './utils/index.js';
5
+
6
+ export const EdgePrintPlugin: PrintPlugin<EdgeASTNode> = {
7
+ match(ast) {
8
+ return ast.type === 'Edge';
9
+ },
10
+ print(context, ast): string {
11
+ const targets = pipe(
12
+ map(context.print),
13
+ joinBy(context.directed ? ' -> ' : ' -- '),
14
+ )(ast.targets);
15
+ if (ast.children.length === 0) {
16
+ return `${targets};`;
17
+ }
18
+ const eol = endOfLine(context.endOfLine);
19
+ const contents = pipe(
20
+ map(context.print),
21
+ joinBy(eol),
22
+ indent(context.indentStyle, context.indentSize, eol),
23
+ wrapByPair(`[${eol}`, `${eol}];`),
24
+ )(ast.children);
25
+ return `${targets} ${contents}`;
26
+ },
27
+ };
@@ -0,0 +1,32 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { GraphASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { endOfLine, indent, joinBy, wrapByPair } from './utils/index.js';
5
+
6
+ export const GraphPrintPlugin: PrintPlugin<GraphASTNode> = {
7
+ match(ast) {
8
+ return ast.type === 'Graph';
9
+ },
10
+ print(context, ast): string {
11
+ context.directed = ast.directed;
12
+ const parts: string[] = [];
13
+ if (ast.strict) {
14
+ parts.push('strict');
15
+ }
16
+ parts.push(ast.directed ? 'digraph' : 'graph');
17
+ if (ast.id) {
18
+ parts.push(context.print(ast.id));
19
+ }
20
+ if (ast.children.length === 0) {
21
+ return `${parts.join(' ')} {}`;
22
+ }
23
+ const eol = endOfLine(context.endOfLine);
24
+ const contents = pipe(
25
+ map(context.print),
26
+ joinBy(eol),
27
+ indent(context.indentStyle, context.indentSize, eol),
28
+ wrapByPair(`{${eol}`, `${eol}}`),
29
+ )(ast.children);
30
+ return `${parts.join(' ')} ${contents}`;
31
+ },
32
+ };
@@ -0,0 +1,24 @@
1
+ import { pipe } from '@ts-graphviz/common';
2
+ import { LiteralASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { escape, wrapByPair, wrapWith } from './utils/index.js';
5
+
6
+ const quoteLiteralValue = pipe(escape, wrapWith('"'));
7
+
8
+ const quoteHTMLLikeLiteralValue = wrapByPair('<', '>');
9
+
10
+ export const LiteralPrintPlugin: PrintPlugin<LiteralASTNode> = {
11
+ match(ast) {
12
+ return ast.type === 'Literal';
13
+ },
14
+ print(context, ast): string {
15
+ switch (ast.quoted) {
16
+ case 'html':
17
+ return quoteHTMLLikeLiteralValue(ast.value);
18
+ case true:
19
+ return quoteLiteralValue(ast.value);
20
+ default:
21
+ return escape(ast.value);
22
+ }
23
+ },
24
+ };
@@ -0,0 +1,24 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { NodeASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { endOfLine, indent, joinBy, wrapByPair } from './utils/index.js';
5
+
6
+ export const NodePrintPlugin: PrintPlugin<NodeASTNode> = {
7
+ match(ast) {
8
+ return ast.type === 'Node';
9
+ },
10
+ print(context, ast): string {
11
+ const id = context.print(ast.id);
12
+ if (ast.children.length === 0) {
13
+ return `${id};`;
14
+ }
15
+ const eol = endOfLine(context.endOfLine);
16
+ const contents = pipe(
17
+ map(context.print),
18
+ joinBy(eol),
19
+ indent(context.indentStyle, context.indentSize, eol),
20
+ wrapByPair(`[${eol}`, `${eol}];`),
21
+ )(ast.children);
22
+ return `${id} ${contents}`;
23
+ },
24
+ };
@@ -0,0 +1,17 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { NodeRefGroupASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { joinBy, wrapByPair } from './utils/index.js';
5
+
6
+ export const NodeRefGroupPrintPlugin: PrintPlugin<NodeRefGroupASTNode> = {
7
+ match(ast) {
8
+ return ast.type === 'NodeRefGroup';
9
+ },
10
+ print(context, ast): string {
11
+ return pipe(
12
+ map(context.print),
13
+ joinBy(' '),
14
+ wrapByPair('{', '}'),
15
+ )(ast.children);
16
+ },
17
+ };
@@ -0,0 +1,18 @@
1
+ import { NodeRefASTNode } from '../../../types.js';
2
+ import { PrintPlugin } from '../types.js';
3
+
4
+ export const NodeRefPrintPlugin: PrintPlugin<NodeRefASTNode> = {
5
+ match(ast) {
6
+ return ast.type === 'NodeRef';
7
+ },
8
+ print(context, ast): string {
9
+ const parts = [context.print(ast.id)];
10
+ if (ast.port) {
11
+ parts.push(context.print(ast.port));
12
+ }
13
+ if (ast.compass) {
14
+ parts.push(context.print(ast.compass));
15
+ }
16
+ return parts.join(':');
17
+ },
18
+ };
@@ -0,0 +1,27 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { SubgraphASTNode } from '../../../types.js';
3
+ import { PrintPlugin } from '../types.js';
4
+ import { endOfLine, indent, joinBy, wrapByPair } from './utils/index.js';
5
+
6
+ export const SubgraphPrintPlugin: PrintPlugin<SubgraphASTNode> = {
7
+ match(ast) {
8
+ return ast.type === 'Subgraph';
9
+ },
10
+ print(context, ast): string {
11
+ const parts: string[] = ['subgraph'];
12
+ if (ast.id) {
13
+ parts.push(context.print(ast.id));
14
+ }
15
+ if (ast.children.length === 0) {
16
+ return `${parts.join(' ')} {}`;
17
+ }
18
+ const eol = endOfLine(context.endOfLine);
19
+ const contents = pipe(
20
+ map(context.print),
21
+ joinBy(eol),
22
+ indent(context.indentStyle, context.indentSize, eol),
23
+ wrapByPair(`{${eol}`, `${eol}}`),
24
+ )(ast.children);
25
+ return `${parts.join(' ')} ${contents}`;
26
+ },
27
+ };
@@ -0,0 +1,26 @@
1
+ import { PrintPlugin } from '../types.js';
2
+ import { AttributeListPrintPlugin } from './AttributeListPrintPlugin.js';
3
+ import { AttributePrintPlugin } from './AttributePrintPlugin.js';
4
+ import { CommentPrintPlugin } from './CommentPrintPlugin.js';
5
+ import { DotPrintPlugin } from './DotPrintPlugin.js';
6
+ import { EdgePrintPlugin } from './EdgePrintPlugin.js';
7
+ import { GraphPrintPlugin } from './GraphPrintPlugin.js';
8
+ import { LiteralPrintPlugin } from './LiteralPrintPlugin.js';
9
+ import { NodePrintPlugin } from './NodePrintPlugin.js';
10
+ import { NodeRefGroupPrintPlugin } from './NodeRefGroupPrintPlugin.js';
11
+ import { NodeRefPrintPlugin } from './NodeRefPrintPlugin.js';
12
+ import { SubgraphPrintPlugin } from './SubgraphPrintPlugin.js';
13
+
14
+ export const defaultPlugins: PrintPlugin[] = [
15
+ AttributeListPrintPlugin,
16
+ AttributePrintPlugin,
17
+ CommentPrintPlugin,
18
+ DotPrintPlugin,
19
+ EdgePrintPlugin,
20
+ GraphPrintPlugin,
21
+ LiteralPrintPlugin,
22
+ NodePrintPlugin,
23
+ NodeRefGroupPrintPlugin,
24
+ NodeRefPrintPlugin,
25
+ SubgraphPrintPlugin,
26
+ ];
@@ -0,0 +1 @@
1
+ export * from './tokens.js';
@@ -0,0 +1,51 @@
1
+ import { map, pipe } from '@ts-graphviz/common';
2
+ import { EndOfLine, IndentStyle } from '../../types.js';
3
+
4
+ const EOL = /\r?\n/;
5
+
6
+ export function joinBy(sep: string): (value: string[]) => string {
7
+ return (value: string[]) => value.join(sep);
8
+ }
9
+
10
+ export function wrapWith(wrapper: string): (value: string) => string {
11
+ return (value: string) => wrapper + value + wrapper;
12
+ }
13
+
14
+ export function wrapByPair(l: string, r: string): (value: string) => string {
15
+ return (value: string) => l + value + r;
16
+ }
17
+
18
+ export function leftPadWith(left: string): (value: string) => string {
19
+ return (value: string) => left + value;
20
+ }
21
+
22
+ export function rightPadWith(right: string): (value: string) => string {
23
+ return (value: string) => value + right;
24
+ }
25
+
26
+ export const escape = (value: string): string =>
27
+ value
28
+ .replace(/\\/g, '\\\\')
29
+ .replace(/\r/g, '\\r')
30
+ .replace(/\n/g, '\\n')
31
+ .replace(/"/g, '\\"');
32
+ export const splitByLine = (value: string): string[] => value.split(EOL);
33
+
34
+ export const align = (padding: string, eol: string) =>
35
+ pipe(splitByLine, map(leftPadWith(padding)), joinBy(eol));
36
+
37
+ export const indent = (style: IndentStyle, size: number, eol: string) =>
38
+ pipe(
39
+ splitByLine,
40
+ map(leftPadWith(style === 'space' ? ' '.repeat(size) : '\n')),
41
+ joinBy(eol),
42
+ );
43
+
44
+ export const endOfLine = (eol: EndOfLine) => {
45
+ switch (eol) {
46
+ case 'crlf':
47
+ return '\r\n';
48
+ case 'lf':
49
+ return '\n';
50
+ }
51
+ };
@@ -0,0 +1,46 @@
1
+ import type { ASTNode } from '../../types.js';
2
+ import { defaultPlugins } from './plugins/index.js';
3
+ import type { PrintContext, PrintOptions, PrintPlugin } from './types.js';
4
+
5
+ /**
6
+ * Printer is a class responsible for converting an AST into a DOT string.
7
+ * @group Convert AST to DOT
8
+ */
9
+ export class Printer {
10
+ /** @internal */
11
+ #plugins: PrintPlugin[] = [...defaultPlugins];
12
+
13
+ /**
14
+ * @param options Options to be used when generating the DOT string.
15
+ */
16
+ constructor(private options: PrintOptions = {}) {}
17
+
18
+ /**
19
+ * Generates a DOT string from an ASTNode.
20
+ * @param ast The ASTNode to be converted into a DOT string.
21
+ * @returns The DOT string generated from the ASTNode.
22
+ */
23
+ public print(ast: ASTNode): string {
24
+ const plugins = [...this.#plugins];
25
+ const {
26
+ indentSize = 2,
27
+ indentStyle = 'space',
28
+ endOfLine = 'lf',
29
+ } = this.options;
30
+ const context: PrintContext = {
31
+ directed: true,
32
+ indentSize,
33
+ indentStyle,
34
+ endOfLine,
35
+ print(a: ASTNode): string {
36
+ for (const plugin of plugins) {
37
+ if (plugin.match(a)) {
38
+ return plugin.print(context, a);
39
+ }
40
+ }
41
+ throw Error();
42
+ },
43
+ };
44
+ return context.print(ast);
45
+ }
46
+ }