@protomarkdown/parser 1.0.1 → 1.0.3
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 +9 -0
- package/dist/HtmlGenerator.d.ts +35 -0
- package/dist/HtmlGenerator.d.ts.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +329 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +329 -0
- package/dist/index.js.map +1 -1
- package/dist/parser/MarkdownParser.d.ts +1 -0
- package/dist/parser/MarkdownParser.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -174,6 +174,15 @@ const code = generator.generate(nodes: MarkdownNode[]);
|
|
|
174
174
|
|
|
175
175
|
**Returns:** Complete React component code as a string with necessary Shadcn UI imports
|
|
176
176
|
|
|
177
|
+
### HtmlGenerator
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
const generator = new HtmlGenerator();
|
|
181
|
+
const html = generator.generate(nodes: MarkdownNode[]);
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**Returns:** HTML string for VS Code extension preview rendering
|
|
185
|
+
|
|
177
186
|
## Examples
|
|
178
187
|
|
|
179
188
|
### Login Form
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MarkdownNode } from "./parser/types";
|
|
2
|
+
/**
|
|
3
|
+
* Generates HTML from a Proto Markdown AST
|
|
4
|
+
* Used for VS Code extension preview rendering
|
|
5
|
+
*/
|
|
6
|
+
export declare class HtmlGenerator {
|
|
7
|
+
/**
|
|
8
|
+
* Generate HTML from markdown AST
|
|
9
|
+
*/
|
|
10
|
+
generate(nodes: MarkdownNode[]): string;
|
|
11
|
+
private renderNode;
|
|
12
|
+
private renderHeader;
|
|
13
|
+
private renderText;
|
|
14
|
+
private renderBold;
|
|
15
|
+
private renderItalic;
|
|
16
|
+
private renderInlineNodes;
|
|
17
|
+
private renderInlineNode;
|
|
18
|
+
private renderInput;
|
|
19
|
+
private renderTextarea;
|
|
20
|
+
private renderCheckbox;
|
|
21
|
+
private renderRadioGroup;
|
|
22
|
+
private renderDropdown;
|
|
23
|
+
private renderButton;
|
|
24
|
+
private renderCard;
|
|
25
|
+
private renderContainer;
|
|
26
|
+
private renderGrid;
|
|
27
|
+
private renderDiv;
|
|
28
|
+
private renderTable;
|
|
29
|
+
private renderImage;
|
|
30
|
+
private renderWorkflow;
|
|
31
|
+
private renderScreen;
|
|
32
|
+
private parseGridConfig;
|
|
33
|
+
private escapeHtml;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=HtmlGenerator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HtmlGenerator.d.ts","sourceRoot":"","sources":["../src/HtmlGenerator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C;;;GAGG;AACH,qBAAa,aAAa;IACxB;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,YAAY,EAAE,GAAG,MAAM;IAIvC,OAAO,CAAC,UAAU;IA2ClB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,UAAU;IAQlB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,iBAAiB;IAIzB,OAAO,CAAC,gBAAgB;IAsBxB,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,cAAc;IAUtB,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,YAAY;IAiBpB,OAAO,CAAC,UAAU;IAsBlB,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,SAAS;IAOjB,OAAO,CAAC,WAAW;IAwBnB,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,cAAc;IA+BtB,OAAO,CAAC,YAAY;IAapB,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,UAAU;CAQnB"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -151,6 +151,13 @@ class MarkdownParser {
|
|
|
151
151
|
break;
|
|
152
152
|
}
|
|
153
153
|
}
|
|
154
|
+
// Check for table (line with pipes starting with |)
|
|
155
|
+
if (screenLine.includes("|") && screenLine.trim().startsWith("|")) {
|
|
156
|
+
const result = this.parseTable(lines, i, "]");
|
|
157
|
+
screenChildren.push(result.node);
|
|
158
|
+
i = result.nextIndex;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
154
161
|
// Check for nested card opening
|
|
155
162
|
if (screenLine.match(/^\[--\s*(.*)$/)) {
|
|
156
163
|
const nestedTitle = screenLine.match(/^\[--\s*(.*)$/)?.[1] || undefined;
|
|
@@ -192,6 +199,48 @@ class MarkdownParser {
|
|
|
192
199
|
nextIndex: i + 1,
|
|
193
200
|
};
|
|
194
201
|
}
|
|
202
|
+
parseTable(lines, startIndex, closingDelimiter) {
|
|
203
|
+
const line = this.options.preserveWhitespace ? lines[startIndex] : lines[startIndex].trim();
|
|
204
|
+
const headers = line
|
|
205
|
+
.split("|")
|
|
206
|
+
.map((h) => h.trim())
|
|
207
|
+
.filter((h) => h.length > 0);
|
|
208
|
+
let i = startIndex + 1;
|
|
209
|
+
// Skip separator line (|---|---|)
|
|
210
|
+
if (i < lines.length) {
|
|
211
|
+
const separatorLine = this.options.preserveWhitespace
|
|
212
|
+
? lines[i]
|
|
213
|
+
: lines[i].trim();
|
|
214
|
+
if (separatorLine.includes("-") && separatorLine.includes("|")) {
|
|
215
|
+
i++;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// Parse table rows
|
|
219
|
+
const rows = [];
|
|
220
|
+
while (i < lines.length) {
|
|
221
|
+
const rowLine = this.options.preserveWhitespace
|
|
222
|
+
? lines[i]
|
|
223
|
+
: lines[i].trim();
|
|
224
|
+
// Stop at closing delimiter or empty line or non-table line
|
|
225
|
+
if (!rowLine || !rowLine.includes("|") || (closingDelimiter && rowLine === closingDelimiter)) {
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
const cells = rowLine
|
|
229
|
+
.split("|")
|
|
230
|
+
.map((c) => c.trim())
|
|
231
|
+
.filter((c) => c.length > 0);
|
|
232
|
+
rows.push(cells);
|
|
233
|
+
i++;
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
node: {
|
|
237
|
+
type: "table",
|
|
238
|
+
headers,
|
|
239
|
+
rows,
|
|
240
|
+
},
|
|
241
|
+
nextIndex: i,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
195
244
|
parseCard(lines, startIndex, title) {
|
|
196
245
|
const cardChildren = [];
|
|
197
246
|
let i = startIndex + 1;
|
|
@@ -206,6 +255,13 @@ class MarkdownParser {
|
|
|
206
255
|
break;
|
|
207
256
|
}
|
|
208
257
|
}
|
|
258
|
+
// Check for table (line with pipes starting with |)
|
|
259
|
+
if (cardLine.includes("|") && cardLine.trim().startsWith("|")) {
|
|
260
|
+
const result = this.parseTable(lines, i, "--]");
|
|
261
|
+
cardChildren.push(result.node);
|
|
262
|
+
i = result.nextIndex;
|
|
263
|
+
continue;
|
|
264
|
+
}
|
|
209
265
|
// Check for nested card opening (must be before div check)
|
|
210
266
|
if (cardLine.match(/^\[--\s*(.*)$/)) {
|
|
211
267
|
const nestedTitle = cardLine.match(/^\[--\s*(.*)$/)?.[1] || undefined;
|
|
@@ -261,6 +317,13 @@ class MarkdownParser {
|
|
|
261
317
|
break;
|
|
262
318
|
}
|
|
263
319
|
}
|
|
320
|
+
// Check for table (line with pipes starting with |)
|
|
321
|
+
if (containerLine.includes("|") && containerLine.trim().startsWith("|")) {
|
|
322
|
+
const result = this.parseTable(lines, i, "]");
|
|
323
|
+
containerChildren.push(result.node);
|
|
324
|
+
i = result.nextIndex;
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
264
327
|
// Check for nested card opening (must be before div check)
|
|
265
328
|
if (containerLine.match(/^\[--\s*(.*)$/)) {
|
|
266
329
|
const nestedTitle = containerLine.match(/^\[--\s*(.*)$/)?.[1] || undefined;
|
|
@@ -1003,5 +1066,270 @@ ${this.indent()}</div>`;
|
|
|
1003
1066
|
}
|
|
1004
1067
|
}
|
|
1005
1068
|
|
|
1006
|
-
|
|
1069
|
+
/**
|
|
1070
|
+
* Generates HTML from a Proto Markdown AST
|
|
1071
|
+
* Used for VS Code extension preview rendering
|
|
1072
|
+
*/
|
|
1073
|
+
class HtmlGenerator {
|
|
1074
|
+
/**
|
|
1075
|
+
* Generate HTML from markdown AST
|
|
1076
|
+
*/
|
|
1077
|
+
generate(nodes) {
|
|
1078
|
+
return nodes.map((node) => this.renderNode(node)).join("\n");
|
|
1079
|
+
}
|
|
1080
|
+
renderNode(node) {
|
|
1081
|
+
switch (node.type) {
|
|
1082
|
+
case "header":
|
|
1083
|
+
return this.renderHeader(node);
|
|
1084
|
+
case "text":
|
|
1085
|
+
return this.renderText(node);
|
|
1086
|
+
case "bold":
|
|
1087
|
+
return this.renderBold(node);
|
|
1088
|
+
case "italic":
|
|
1089
|
+
return this.renderItalic(node);
|
|
1090
|
+
case "input":
|
|
1091
|
+
return this.renderInput(node);
|
|
1092
|
+
case "textarea":
|
|
1093
|
+
return this.renderTextarea(node);
|
|
1094
|
+
case "checkbox":
|
|
1095
|
+
return this.renderCheckbox(node);
|
|
1096
|
+
case "radiogroup":
|
|
1097
|
+
return this.renderRadioGroup(node);
|
|
1098
|
+
case "dropdown":
|
|
1099
|
+
return this.renderDropdown(node);
|
|
1100
|
+
case "button":
|
|
1101
|
+
return this.renderButton(node);
|
|
1102
|
+
case "card":
|
|
1103
|
+
return this.renderCard(node);
|
|
1104
|
+
case "container":
|
|
1105
|
+
return this.renderContainer(node);
|
|
1106
|
+
case "grid":
|
|
1107
|
+
return this.renderGrid(node);
|
|
1108
|
+
case "div":
|
|
1109
|
+
return this.renderDiv(node);
|
|
1110
|
+
case "table":
|
|
1111
|
+
return this.renderTable(node);
|
|
1112
|
+
case "image":
|
|
1113
|
+
return this.renderImage(node);
|
|
1114
|
+
case "workflow":
|
|
1115
|
+
return this.renderWorkflow(node);
|
|
1116
|
+
case "screen":
|
|
1117
|
+
return this.renderScreen(node);
|
|
1118
|
+
default:
|
|
1119
|
+
return `<div class="proto-unknown">${JSON.stringify(node)}</div>`;
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
renderHeader(node) {
|
|
1123
|
+
const level = node.level || 1;
|
|
1124
|
+
let content;
|
|
1125
|
+
if (node.children && node.children.length > 0) {
|
|
1126
|
+
content = this.renderInlineNodes(node.children);
|
|
1127
|
+
}
|
|
1128
|
+
else {
|
|
1129
|
+
content = this.escapeHtml(node.content || "");
|
|
1130
|
+
}
|
|
1131
|
+
return `<h${level} class="proto-header">${content}</h${level}>`;
|
|
1132
|
+
}
|
|
1133
|
+
renderText(node) {
|
|
1134
|
+
if (node.children && node.children.length > 0) {
|
|
1135
|
+
const content = this.renderInlineNodes(node.children);
|
|
1136
|
+
return `<p class="proto-text">${content}</p>`;
|
|
1137
|
+
}
|
|
1138
|
+
return `<p class="proto-text">${this.escapeHtml(node.content || "")}</p>`;
|
|
1139
|
+
}
|
|
1140
|
+
renderBold(node) {
|
|
1141
|
+
if (node.children && node.children.length > 0) {
|
|
1142
|
+
return `<strong>${this.renderInlineNodes(node.children)}</strong>`;
|
|
1143
|
+
}
|
|
1144
|
+
return `<strong>${this.escapeHtml(node.content || "")}</strong>`;
|
|
1145
|
+
}
|
|
1146
|
+
renderItalic(node) {
|
|
1147
|
+
if (node.children && node.children.length > 0) {
|
|
1148
|
+
return `<em>${this.renderInlineNodes(node.children)}</em>`;
|
|
1149
|
+
}
|
|
1150
|
+
return `<em>${this.escapeHtml(node.content || "")}</em>`;
|
|
1151
|
+
}
|
|
1152
|
+
renderInlineNodes(nodes) {
|
|
1153
|
+
return nodes.map((node) => this.renderInlineNode(node)).join("");
|
|
1154
|
+
}
|
|
1155
|
+
renderInlineNode(node) {
|
|
1156
|
+
switch (node.type) {
|
|
1157
|
+
case "bold":
|
|
1158
|
+
if (node.children && node.children.length > 0) {
|
|
1159
|
+
return `<strong>${this.renderInlineNodes(node.children)}</strong>`;
|
|
1160
|
+
}
|
|
1161
|
+
return `<strong>${this.escapeHtml(node.content || "")}</strong>`;
|
|
1162
|
+
case "italic":
|
|
1163
|
+
if (node.children && node.children.length > 0) {
|
|
1164
|
+
return `<em>${this.renderInlineNodes(node.children)}</em>`;
|
|
1165
|
+
}
|
|
1166
|
+
return `<em>${this.escapeHtml(node.content || "")}</em>`;
|
|
1167
|
+
case "text":
|
|
1168
|
+
if (node.children && node.children.length > 0) {
|
|
1169
|
+
return this.renderInlineNodes(node.children);
|
|
1170
|
+
}
|
|
1171
|
+
return this.escapeHtml(node.content || "");
|
|
1172
|
+
default:
|
|
1173
|
+
return this.escapeHtml(node.content || "");
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
renderInput(node) {
|
|
1177
|
+
const placeholder = node.inputType === "password" ? "••••••••" : "";
|
|
1178
|
+
return `
|
|
1179
|
+
<div class="proto-field">
|
|
1180
|
+
<label class="proto-label">${this.escapeHtml(node.label || "")}</label>
|
|
1181
|
+
<input type="${node.inputType || "text"}" class="proto-input" placeholder="${placeholder}" disabled />
|
|
1182
|
+
</div>`;
|
|
1183
|
+
}
|
|
1184
|
+
renderTextarea(node) {
|
|
1185
|
+
return `
|
|
1186
|
+
<div class="proto-field">
|
|
1187
|
+
<label class="proto-label">${this.escapeHtml(node.label || "")}</label>
|
|
1188
|
+
<textarea class="proto-textarea" disabled></textarea>
|
|
1189
|
+
</div>`;
|
|
1190
|
+
}
|
|
1191
|
+
renderCheckbox(node) {
|
|
1192
|
+
return `
|
|
1193
|
+
<div class="proto-checkbox">
|
|
1194
|
+
<input type="checkbox" class="proto-checkbox-input" disabled />
|
|
1195
|
+
<label class="proto-checkbox-label">${this.escapeHtml(node.label || "")}</label>
|
|
1196
|
+
</div>`;
|
|
1197
|
+
}
|
|
1198
|
+
renderRadioGroup(node) {
|
|
1199
|
+
const options = (node.options || [])
|
|
1200
|
+
.map((opt) => `
|
|
1201
|
+
<div class="proto-radio-option">
|
|
1202
|
+
<input type="radio" class="proto-radio-input" name="${this.escapeHtml(node.label || "")}" disabled />
|
|
1203
|
+
<label class="proto-radio-label">${this.escapeHtml(opt)}</label>
|
|
1204
|
+
</div>`)
|
|
1205
|
+
.join("");
|
|
1206
|
+
return `
|
|
1207
|
+
<div class="proto-radiogroup">
|
|
1208
|
+
<label class="proto-label">${this.escapeHtml(node.label || "")}</label>
|
|
1209
|
+
<div class="proto-radio-options">${options}</div>
|
|
1210
|
+
</div>`;
|
|
1211
|
+
}
|
|
1212
|
+
renderDropdown(node) {
|
|
1213
|
+
const options = (node.options || ["Select an option"])
|
|
1214
|
+
.map((opt) => `<option>${this.escapeHtml(opt)}</option>`)
|
|
1215
|
+
.join("");
|
|
1216
|
+
return `
|
|
1217
|
+
<div class="proto-field">
|
|
1218
|
+
<label class="proto-label">${this.escapeHtml(node.label || "")}</label>
|
|
1219
|
+
<select class="proto-select" disabled>${options}</select>
|
|
1220
|
+
</div>`;
|
|
1221
|
+
}
|
|
1222
|
+
renderButton(node) {
|
|
1223
|
+
const btnClass = node.variant === "default"
|
|
1224
|
+
? "proto-button-default"
|
|
1225
|
+
: "proto-button-outline";
|
|
1226
|
+
const navIndicator = node.navigateTo
|
|
1227
|
+
? ` <span class="proto-nav-indicator">→ ${this.escapeHtml(node.navigateTo)}</span>`
|
|
1228
|
+
: "";
|
|
1229
|
+
return `<button class="proto-button ${btnClass}" disabled>${this.escapeHtml(node.content || "")}${navIndicator}</button>`;
|
|
1230
|
+
}
|
|
1231
|
+
renderCard(node) {
|
|
1232
|
+
let cardTitle = "";
|
|
1233
|
+
if (node.titleChildren && node.titleChildren.length > 0) {
|
|
1234
|
+
cardTitle = `<div class="proto-card-header">${this.renderInlineNodes(node.titleChildren)}</div>`;
|
|
1235
|
+
}
|
|
1236
|
+
else if (node.title) {
|
|
1237
|
+
cardTitle = `<div class="proto-card-header">${this.escapeHtml(node.title)}</div>`;
|
|
1238
|
+
}
|
|
1239
|
+
const cardChildren = node.children ? this.generate(node.children) : "";
|
|
1240
|
+
return `
|
|
1241
|
+
<div class="proto-card">
|
|
1242
|
+
${cardTitle}
|
|
1243
|
+
<div class="proto-card-content">${cardChildren}</div>
|
|
1244
|
+
</div>`;
|
|
1245
|
+
}
|
|
1246
|
+
renderContainer(node) {
|
|
1247
|
+
const children = node.children ? this.generate(node.children) : "";
|
|
1248
|
+
return `<div class="proto-container">${children}</div>`;
|
|
1249
|
+
}
|
|
1250
|
+
renderGrid(node) {
|
|
1251
|
+
const children = node.children ? this.generate(node.children) : "";
|
|
1252
|
+
const gridConfig = this.parseGridConfig(node.gridConfig || "");
|
|
1253
|
+
return `<div class="proto-grid" style="${gridConfig}">${children}</div>`;
|
|
1254
|
+
}
|
|
1255
|
+
renderDiv(node) {
|
|
1256
|
+
const children = node.children ? this.generate(node.children) : "";
|
|
1257
|
+
return `<div class="proto-div ${this.escapeHtml(node.className || "")}">${children}</div>`;
|
|
1258
|
+
}
|
|
1259
|
+
renderTable(node) {
|
|
1260
|
+
const headerCells = (node.headers || [])
|
|
1261
|
+
.map((h) => `<th class="proto-table-th">${this.escapeHtml(h)}</th>`)
|
|
1262
|
+
.join("");
|
|
1263
|
+
const bodyRows = (node.rows || [])
|
|
1264
|
+
.map((row) => `<tr>${row
|
|
1265
|
+
.map((cell) => `<td class="proto-table-td">${this.escapeHtml(cell)}</td>`)
|
|
1266
|
+
.join("")}</tr>`)
|
|
1267
|
+
.join("");
|
|
1268
|
+
return `
|
|
1269
|
+
<table class="proto-table">
|
|
1270
|
+
<thead><tr>${headerCells}</tr></thead>
|
|
1271
|
+
<tbody>${bodyRows}</tbody>
|
|
1272
|
+
</table>`;
|
|
1273
|
+
}
|
|
1274
|
+
renderImage(node) {
|
|
1275
|
+
return `<img class="proto-image" src="${this.escapeHtml(node.src || "")}" alt="${this.escapeHtml(node.alt || "")}" />`;
|
|
1276
|
+
}
|
|
1277
|
+
renderWorkflow(node) {
|
|
1278
|
+
const screens = (node.children || [])
|
|
1279
|
+
.map((screen, idx) => {
|
|
1280
|
+
const isInitial = screen.id === node.initialScreen || idx === 0;
|
|
1281
|
+
const screenContent = screen.children
|
|
1282
|
+
? this.generate(screen.children)
|
|
1283
|
+
: "";
|
|
1284
|
+
const screenId = screen.id || "";
|
|
1285
|
+
return `
|
|
1286
|
+
<div class="proto-screen${isInitial ? " proto-screen-active" : ""}" data-screen-id="${this.escapeHtml(screenId)}">
|
|
1287
|
+
<div class="proto-screen-header">
|
|
1288
|
+
<span class="proto-screen-badge">${this.escapeHtml(screenId)}</span>
|
|
1289
|
+
${isInitial
|
|
1290
|
+
? '<span class="proto-screen-initial">Initial</span>'
|
|
1291
|
+
: ""}
|
|
1292
|
+
</div>
|
|
1293
|
+
<div class="proto-screen-content">${screenContent}</div>
|
|
1294
|
+
</div>`;
|
|
1295
|
+
})
|
|
1296
|
+
.join("");
|
|
1297
|
+
return `<div class="proto-workflow">${screens}</div>`;
|
|
1298
|
+
}
|
|
1299
|
+
renderScreen(node) {
|
|
1300
|
+
const screenChildren = node.children ? this.generate(node.children) : "";
|
|
1301
|
+
const screenId = node.id || "";
|
|
1302
|
+
return `
|
|
1303
|
+
<div class="proto-screen" data-screen-id="${this.escapeHtml(screenId)}">
|
|
1304
|
+
<div class="proto-screen-header">
|
|
1305
|
+
<span class="proto-screen-badge">${this.escapeHtml(screenId)}</span>
|
|
1306
|
+
</div>
|
|
1307
|
+
<div class="proto-screen-content">${screenChildren}</div>
|
|
1308
|
+
</div>`;
|
|
1309
|
+
}
|
|
1310
|
+
parseGridConfig(config) {
|
|
1311
|
+
const styles = [];
|
|
1312
|
+
// Parse cols-N
|
|
1313
|
+
const colsMatch = config.match(/cols-(\d+)/);
|
|
1314
|
+
if (colsMatch) {
|
|
1315
|
+
styles.push(`grid-template-columns: repeat(${colsMatch[1]}, 1fr)`);
|
|
1316
|
+
}
|
|
1317
|
+
// Parse gap-N
|
|
1318
|
+
const gapMatch = config.match(/gap-(\d+)/);
|
|
1319
|
+
if (gapMatch) {
|
|
1320
|
+
styles.push(`gap: ${parseInt(gapMatch[1]) * 4}px`);
|
|
1321
|
+
}
|
|
1322
|
+
return styles.join("; ");
|
|
1323
|
+
}
|
|
1324
|
+
escapeHtml(text) {
|
|
1325
|
+
return text
|
|
1326
|
+
.replace(/&/g, "&")
|
|
1327
|
+
.replace(/</g, "<")
|
|
1328
|
+
.replace(/>/g, ">")
|
|
1329
|
+
.replace(/"/g, """)
|
|
1330
|
+
.replace(/'/g, "'");
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
export { HtmlGenerator, MarkdownParser, ShadcnCodeGenerator };
|
|
1007
1335
|
//# sourceMappingURL=index.esm.js.map
|