mermaid-ast 0.2.0 → 0.3.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/README.md +74 -4
- package/dist/renderer/class-renderer.d.ts +2 -1
- package/dist/renderer/class-renderer.d.ts.map +1 -1
- package/dist/renderer/class-renderer.js +87 -121
- package/dist/renderer/doc.d.ts +318 -0
- package/dist/renderer/doc.d.ts.map +1 -0
- package/dist/renderer/doc.js +300 -0
- package/dist/renderer/flowchart-renderer.d.ts +2 -1
- package/dist/renderer/flowchart-renderer.d.ts.map +1 -1
- package/dist/renderer/flowchart-renderer.js +245 -85
- package/dist/renderer/index.d.ts +2 -2
- package/dist/renderer/index.d.ts.map +1 -1
- package/dist/renderer/index.js +4 -4
- package/dist/renderer/sequence-renderer.d.ts +2 -5
- package/dist/renderer/sequence-renderer.d.ts.map +1 -1
- package/dist/renderer/sequence-renderer.js +103 -128
- package/dist/renderer/state-renderer.d.ts +2 -1
- package/dist/renderer/state-renderer.d.ts.map +1 -1
- package/dist/renderer/state-renderer.js +71 -88
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/render-options.d.ts +57 -0
- package/dist/types/render-options.d.ts.map +1 -0
- package/dist/types/render-options.js +37 -0
- package/dist/vendored/LICENSE +21 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -131,6 +131,55 @@ detectDiagramType("classDiagram\n class Animal"); // "class"
|
|
|
131
131
|
detectDiagramType("unknown diagram"); // null
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
+
### Render Options (Pretty-Print)
|
|
135
|
+
|
|
136
|
+
All render functions accept an optional `RenderOptions` object to customize output formatting:
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { renderFlowchart, parseFlowchart } from "mermaid-ast";
|
|
140
|
+
import type { RenderOptions } from "mermaid-ast";
|
|
141
|
+
|
|
142
|
+
const ast = parseFlowchart(`flowchart LR
|
|
143
|
+
A[Start] --> B[Middle] --> C[End]
|
|
144
|
+
classDef highlight fill:#f9f
|
|
145
|
+
class A highlight`);
|
|
146
|
+
|
|
147
|
+
// Default output (4-space indent)
|
|
148
|
+
renderFlowchart(ast);
|
|
149
|
+
|
|
150
|
+
// Custom indent (2 spaces)
|
|
151
|
+
renderFlowchart(ast, { indent: 2 });
|
|
152
|
+
|
|
153
|
+
// Tab indent
|
|
154
|
+
renderFlowchart(ast, { indent: "tab" });
|
|
155
|
+
|
|
156
|
+
// Sort nodes alphabetically
|
|
157
|
+
renderFlowchart(ast, { sortNodes: true });
|
|
158
|
+
|
|
159
|
+
// Flowchart-specific: inline classes (A:::highlight instead of separate class statement)
|
|
160
|
+
renderFlowchart(ast, { inlineClasses: true });
|
|
161
|
+
|
|
162
|
+
// Flowchart-specific: chain links (A --> B --> C on one line)
|
|
163
|
+
renderFlowchart(ast, { compactLinks: true });
|
|
164
|
+
|
|
165
|
+
// Combine options
|
|
166
|
+
renderFlowchart(ast, {
|
|
167
|
+
indent: 2,
|
|
168
|
+
sortNodes: true,
|
|
169
|
+
inlineClasses: true,
|
|
170
|
+
compactLinks: true,
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### Available Options
|
|
175
|
+
|
|
176
|
+
| Option | Type | Default | Description |
|
|
177
|
+
|--------|------|---------|-------------|
|
|
178
|
+
| `indent` | `number \| "tab"` | `4` | Number of spaces for indentation, or `"tab"` for tabs |
|
|
179
|
+
| `sortNodes` | `boolean` | `false` | Sort node/actor/class declarations alphabetically |
|
|
180
|
+
| `inlineClasses` | `boolean` | `false` | (Flowchart only) Use `A:::className` instead of separate `class` statements |
|
|
181
|
+
| `compactLinks` | `boolean` | `false` | (Flowchart only) Chain consecutive links: `A --> B --> C` |
|
|
182
|
+
|
|
134
183
|
## API Reference
|
|
135
184
|
|
|
136
185
|
### Core Functions
|
|
@@ -138,7 +187,7 @@ detectDiagramType("unknown diagram"); // null
|
|
|
138
187
|
| Function | Description |
|
|
139
188
|
|----------|-------------|
|
|
140
189
|
| `parse(input: string): MermaidAST` | Parse any supported diagram |
|
|
141
|
-
| `render(ast: MermaidAST): string` | Render any supported AST |
|
|
190
|
+
| `render(ast: MermaidAST, options?: RenderOptions): string` | Render any supported AST |
|
|
142
191
|
| `detectDiagramType(input: string): DiagramType \| null` | Detect diagram type |
|
|
143
192
|
|
|
144
193
|
### Flowchart Functions
|
|
@@ -146,7 +195,7 @@ detectDiagramType("unknown diagram"); // null
|
|
|
146
195
|
| Function | Description |
|
|
147
196
|
|----------|-------------|
|
|
148
197
|
| `parseFlowchart(input: string): FlowchartAST` | Parse flowchart diagram |
|
|
149
|
-
| `renderFlowchart(ast: FlowchartAST): string` | Render flowchart AST |
|
|
198
|
+
| `renderFlowchart(ast: FlowchartAST, options?: RenderOptions): string` | Render flowchart AST |
|
|
150
199
|
| `isFlowchartDiagram(input: string): boolean` | Check if input is flowchart |
|
|
151
200
|
|
|
152
201
|
### Sequence Diagram Functions
|
|
@@ -154,7 +203,7 @@ detectDiagramType("unknown diagram"); // null
|
|
|
154
203
|
| Function | Description |
|
|
155
204
|
|----------|-------------|
|
|
156
205
|
| `parseSequence(input: string): SequenceAST` | Parse sequence diagram |
|
|
157
|
-
| `renderSequence(ast: SequenceAST): string` | Render sequence AST |
|
|
206
|
+
| `renderSequence(ast: SequenceAST, options?: RenderOptions): string` | Render sequence AST |
|
|
158
207
|
| `isSequenceDiagram(input: string): boolean` | Check if input is sequence |
|
|
159
208
|
|
|
160
209
|
### Class Diagram Functions
|
|
@@ -162,7 +211,7 @@ detectDiagramType("unknown diagram"); // null
|
|
|
162
211
|
| Function | Description |
|
|
163
212
|
|----------|-------------|
|
|
164
213
|
| `parseClassDiagram(input: string): ClassDiagramAST` | Parse class diagram |
|
|
165
|
-
| `renderClassDiagram(ast: ClassDiagramAST): string` | Render class diagram AST |
|
|
214
|
+
| `renderClassDiagram(ast: ClassDiagramAST, options?: RenderOptions): string` | Render class diagram AST |
|
|
166
215
|
| `isClassDiagram(input: string): boolean` | Check if input is class diagram |
|
|
167
216
|
|
|
168
217
|
## Supported Flowchart Features
|
|
@@ -186,6 +235,25 @@ detectDiagramType("unknown diagram"); // null
|
|
|
186
235
|
- **Notes**: `note left of`, `note right of`, `note over`
|
|
187
236
|
- **Actor lifecycle**: `create`, `destroy`
|
|
188
237
|
|
|
238
|
+
## Limitations
|
|
239
|
+
|
|
240
|
+
### Comments Not Preserved
|
|
241
|
+
|
|
242
|
+
Mermaid supports `%%` line comments, but **comments are not preserved** during parsing. The JISON parsers discard comments during lexing, so they are not included in the AST and will not appear in rendered output.
|
|
243
|
+
|
|
244
|
+
```mermaid
|
|
245
|
+
flowchart LR
|
|
246
|
+
%% This comment will be lost
|
|
247
|
+
A --> B
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
After round-trip, the comment is gone:
|
|
251
|
+
|
|
252
|
+
```mermaid
|
|
253
|
+
flowchart LR
|
|
254
|
+
A --> B
|
|
255
|
+
```
|
|
256
|
+
|
|
189
257
|
## Supported Class Diagram Features
|
|
190
258
|
|
|
191
259
|
- **Classes**: With labels, members (attributes and methods)
|
|
@@ -296,6 +364,8 @@ mermaid-ast/
|
|
|
296
364
|
|
|
297
365
|
MIT
|
|
298
366
|
|
|
367
|
+
This project includes JISON parsers from [mermaid.js](https://github.com/mermaid-js/mermaid) (MIT License, Copyright (c) 2014 - 2022 Knut Sveidqvist). See [THIRD-PARTY-NOTICES.md](./THIRD-PARTY-NOTICES.md) for details.
|
|
368
|
+
|
|
299
369
|
---
|
|
300
370
|
|
|
301
371
|
## How This Library Was Built
|
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
* Renders a Class Diagram AST back to Mermaid syntax.
|
|
5
5
|
*/
|
|
6
6
|
import type { ClassDiagramAST } from "../types/class.js";
|
|
7
|
+
import type { RenderOptions } from "../types/render-options.js";
|
|
7
8
|
/**
|
|
8
9
|
* Render a ClassDiagramAST to Mermaid syntax
|
|
9
10
|
*/
|
|
10
|
-
export declare function renderClassDiagram(ast: ClassDiagramAST): string;
|
|
11
|
+
export declare function renderClassDiagram(ast: ClassDiagramAST, options?: RenderOptions): string;
|
|
11
12
|
//# sourceMappingURL=class-renderer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"class-renderer.d.ts","sourceRoot":"","sources":["../../src/renderer/class-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"class-renderer.d.ts","sourceRoot":"","sources":["../../src/renderer/class-renderer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,eAAe,EAOhB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AA4KhE;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,eAAe,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CAgExF"}
|
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Renders a Class Diagram AST back to Mermaid syntax.
|
|
5
5
|
*/
|
|
6
|
+
import { resolveOptions } from "../types/render-options.js";
|
|
7
|
+
import { indent, when, block, render } from "./doc.js";
|
|
6
8
|
/**
|
|
7
9
|
* Render relation type to symbol
|
|
8
10
|
*/
|
|
@@ -30,167 +32,128 @@ function renderLineType(lineType) {
|
|
|
30
32
|
return lineType === "dotted" ? ".." : "--";
|
|
31
33
|
}
|
|
32
34
|
/**
|
|
33
|
-
* Render a relationship
|
|
35
|
+
* Render a relationship to a string
|
|
34
36
|
*/
|
|
35
37
|
function renderRelation(relation) {
|
|
36
38
|
const { id1, id2, relation: rel, relationTitle1, relationTitle2, title } = relation;
|
|
37
|
-
// Build the arrow
|
|
38
39
|
const startType = renderRelationType(rel.type1, true);
|
|
39
40
|
const endType = renderRelationType(rel.type2, false);
|
|
40
41
|
const line = renderLineType(rel.lineType);
|
|
41
|
-
|
|
42
|
-
// Build the full statement
|
|
42
|
+
const arrow = `${startType}${line}${endType}`;
|
|
43
43
|
let result = id1;
|
|
44
|
-
|
|
45
|
-
if (relationTitle1) {
|
|
44
|
+
if (relationTitle1)
|
|
46
45
|
result += ` "${relationTitle1}"`;
|
|
47
|
-
}
|
|
48
46
|
result += ` ${arrow}`;
|
|
49
|
-
|
|
50
|
-
if (relationTitle2) {
|
|
47
|
+
if (relationTitle2)
|
|
51
48
|
result += ` "${relationTitle2}"`;
|
|
52
|
-
}
|
|
53
49
|
result += ` ${id2}`;
|
|
54
|
-
|
|
55
|
-
if (title) {
|
|
50
|
+
if (title)
|
|
56
51
|
result += ` : ${title}`;
|
|
57
|
-
}
|
|
58
52
|
return result;
|
|
59
53
|
}
|
|
60
54
|
/**
|
|
61
|
-
* Render a class member
|
|
55
|
+
* Render a class member to a string
|
|
62
56
|
*/
|
|
63
57
|
function renderMember(member) {
|
|
64
58
|
const visibility = member.visibility || "";
|
|
65
59
|
return `${visibility}${member.text}`;
|
|
66
60
|
}
|
|
67
61
|
/**
|
|
68
|
-
* Render a class definition
|
|
62
|
+
* Render a class definition to a Doc
|
|
69
63
|
*/
|
|
70
|
-
function renderClass(cls,
|
|
71
|
-
const lines = [];
|
|
72
|
-
const indent = inNamespace ? " " : " ";
|
|
73
|
-
// Check if class needs a body
|
|
64
|
+
function renderClass(cls, isReferencedInRelations) {
|
|
74
65
|
const hasBody = cls.members.length > 0;
|
|
75
66
|
const hasLabel = cls.label && cls.label !== cls.id;
|
|
76
67
|
if (hasBody) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}
|
|
81
|
-
else {
|
|
82
|
-
lines.push(`${indent}class ${cls.id} {`);
|
|
83
|
-
}
|
|
84
|
-
// Render members
|
|
85
|
-
for (const member of cls.members) {
|
|
86
|
-
lines.push(`${indent} ${renderMember(member)}`);
|
|
87
|
-
}
|
|
88
|
-
lines.push(`${indent}}`);
|
|
68
|
+
const header = hasLabel
|
|
69
|
+
? `class ${cls.id}["${cls.label}"] {`
|
|
70
|
+
: `class ${cls.id} {`;
|
|
71
|
+
return block(header, cls.members.map(renderMember), "}");
|
|
89
72
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
lines.push(`${indent}class ${cls.id}["${cls.label}"]`);
|
|
73
|
+
if (hasLabel) {
|
|
74
|
+
return `class ${cls.id}["${cls.label}"]`;
|
|
93
75
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
76
|
+
// Class with no body, no label - only declare if not referenced in relations
|
|
77
|
+
if (!isReferencedInRelations) {
|
|
78
|
+
return `class ${cls.id}`;
|
|
97
79
|
}
|
|
98
|
-
//
|
|
99
|
-
return
|
|
80
|
+
// Implicitly declared via relations
|
|
81
|
+
return null;
|
|
100
82
|
}
|
|
101
83
|
/**
|
|
102
|
-
* Render annotations for a class
|
|
84
|
+
* Render annotations for a class to a Doc
|
|
103
85
|
*/
|
|
104
86
|
function renderAnnotations(cls) {
|
|
105
|
-
|
|
106
|
-
for (const annotation of cls.annotations) {
|
|
107
|
-
lines.push(` <<${annotation}>> ${cls.id}`);
|
|
108
|
-
}
|
|
109
|
-
return lines;
|
|
87
|
+
return cls.annotations.map((annotation) => `<<${annotation}>> ${cls.id}`);
|
|
110
88
|
}
|
|
111
89
|
/**
|
|
112
|
-
* Render a namespace
|
|
90
|
+
* Render a namespace to a Doc
|
|
113
91
|
*/
|
|
114
|
-
function renderNamespace(namespaceName, classIds, ast) {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
for (const classId of classIds) {
|
|
92
|
+
function renderNamespace(namespaceName, classIds, ast, classesInRelations) {
|
|
93
|
+
const classesDoc = classIds
|
|
94
|
+
.map((classId) => {
|
|
118
95
|
const cls = ast.classes.get(classId);
|
|
119
|
-
if (cls)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return
|
|
96
|
+
if (!cls)
|
|
97
|
+
return null;
|
|
98
|
+
return renderClass(cls, classesInRelations.has(classId));
|
|
99
|
+
})
|
|
100
|
+
.filter(Boolean);
|
|
101
|
+
return block(`namespace ${namespaceName} {`, classesDoc, "}");
|
|
125
102
|
}
|
|
126
103
|
/**
|
|
127
|
-
* Render notes
|
|
104
|
+
* Render notes to a Doc
|
|
128
105
|
*/
|
|
129
106
|
function renderNotes(notes) {
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
lines.push(` note for ${note.forClass} "${note.text}"`);
|
|
134
|
-
}
|
|
135
|
-
else {
|
|
136
|
-
lines.push(` note "${note.text}"`);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
return lines;
|
|
107
|
+
return notes.map((note) => note.forClass
|
|
108
|
+
? `note for ${note.forClass} "${note.text}"`
|
|
109
|
+
: `note "${note.text}"`);
|
|
140
110
|
}
|
|
141
111
|
/**
|
|
142
|
-
* Render class definitions (classDef)
|
|
112
|
+
* Render class definitions (classDef) to a Doc
|
|
143
113
|
*/
|
|
144
114
|
function renderClassDefs(ast) {
|
|
145
|
-
const
|
|
146
|
-
|
|
115
|
+
const entries = [...ast.classDefs.entries()];
|
|
116
|
+
return entries.map(([name, def]) => {
|
|
147
117
|
const styles = def.styles.join(",");
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
return lines;
|
|
118
|
+
return `classDef ${name} ${styles}`;
|
|
119
|
+
});
|
|
151
120
|
}
|
|
152
121
|
/**
|
|
153
|
-
* Render CSS class assignments
|
|
122
|
+
* Render CSS class assignments to a Doc
|
|
154
123
|
*/
|
|
155
124
|
function renderCssClasses(ast) {
|
|
156
|
-
const
|
|
125
|
+
const assignments = [];
|
|
157
126
|
for (const [, cls] of ast.classes) {
|
|
158
127
|
for (const cssClass of cls.cssClasses) {
|
|
159
|
-
|
|
128
|
+
assignments.push(`cssClass "${cls.id}" ${cssClass}`);
|
|
160
129
|
}
|
|
161
130
|
}
|
|
162
|
-
return
|
|
131
|
+
return assignments;
|
|
163
132
|
}
|
|
164
133
|
/**
|
|
165
|
-
* Render click handlers and links
|
|
134
|
+
* Render click handlers and links to a Doc
|
|
166
135
|
*/
|
|
167
136
|
function renderClicks(ast) {
|
|
168
|
-
const
|
|
137
|
+
const clicks = [];
|
|
169
138
|
for (const [, cls] of ast.classes) {
|
|
170
139
|
if (cls.link) {
|
|
171
140
|
const target = cls.linkTarget ? ` ${cls.linkTarget}` : "";
|
|
172
141
|
const tooltip = cls.tooltip ? ` "${cls.tooltip}"` : "";
|
|
173
|
-
|
|
142
|
+
clicks.push(`link ${cls.id} "${cls.link}"${tooltip}${target}`);
|
|
174
143
|
}
|
|
175
144
|
else if (cls.callback) {
|
|
176
145
|
const args = cls.callbackArgs ? `("${cls.callbackArgs}")` : "";
|
|
177
146
|
const tooltip = cls.tooltip ? ` "${cls.tooltip}"` : "";
|
|
178
|
-
|
|
147
|
+
clicks.push(`callback ${cls.id} "${cls.callback}"${args}${tooltip}`);
|
|
179
148
|
}
|
|
180
149
|
}
|
|
181
|
-
return
|
|
150
|
+
return clicks;
|
|
182
151
|
}
|
|
183
152
|
/**
|
|
184
153
|
* Render a ClassDiagramAST to Mermaid syntax
|
|
185
154
|
*/
|
|
186
|
-
export function renderClassDiagram(ast) {
|
|
187
|
-
const
|
|
188
|
-
// Header
|
|
189
|
-
lines.push("classDiagram");
|
|
190
|
-
// Direction if not default
|
|
191
|
-
if (ast.direction && ast.direction !== "TB") {
|
|
192
|
-
lines.push(` direction ${ast.direction}`);
|
|
193
|
-
}
|
|
155
|
+
export function renderClassDiagram(ast, options) {
|
|
156
|
+
const opts = resolveOptions(options);
|
|
194
157
|
// Track classes rendered in namespaces
|
|
195
158
|
const classesInNamespaces = new Set();
|
|
196
159
|
for (const [, ns] of ast.namespaces) {
|
|
@@ -204,35 +167,38 @@ export function renderClassDiagram(ast) {
|
|
|
204
167
|
classesInRelations.add(relation.id1);
|
|
205
168
|
classesInRelations.add(relation.id2);
|
|
206
169
|
}
|
|
207
|
-
//
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
170
|
+
// Get classes (optionally sorted)
|
|
171
|
+
let classEntries = [...ast.classes.entries()];
|
|
172
|
+
if (opts.sortNodes) {
|
|
173
|
+
classEntries.sort((a, b) => a[0].localeCompare(b[0]));
|
|
174
|
+
}
|
|
175
|
+
// Build the document
|
|
176
|
+
const doc = [
|
|
177
|
+
"classDiagram",
|
|
178
|
+
indent([
|
|
179
|
+
// Direction
|
|
180
|
+
when(ast.direction && ast.direction !== "TB", `direction ${ast.direction}`),
|
|
181
|
+
// Namespaces
|
|
182
|
+
...[...ast.namespaces.entries()].map(([name, ns]) => renderNamespace(name, ns.classes, ast, classesInRelations)),
|
|
183
|
+
// Annotations (before classes)
|
|
184
|
+
...classEntries
|
|
185
|
+
.filter(([, cls]) => cls.annotations.length > 0)
|
|
186
|
+
.map(([, cls]) => renderAnnotations(cls)),
|
|
187
|
+
// Classes not in namespaces
|
|
188
|
+
...classEntries
|
|
189
|
+
.filter(([classId]) => !classesInNamespaces.has(classId))
|
|
190
|
+
.map(([classId, cls]) => renderClass(cls, classesInRelations.has(classId))),
|
|
191
|
+
// Relations
|
|
192
|
+
...ast.relations.map(renderRelation),
|
|
193
|
+
// Notes
|
|
194
|
+
renderNotes(ast.notes),
|
|
195
|
+
// Class definitions
|
|
196
|
+
renderClassDefs(ast),
|
|
197
|
+
// CSS class assignments
|
|
198
|
+
renderCssClasses(ast),
|
|
199
|
+
// Click handlers
|
|
200
|
+
renderClicks(ast),
|
|
201
|
+
]),
|
|
202
|
+
];
|
|
203
|
+
return render(doc, opts.indent);
|
|
238
204
|
}
|