wyreframe 0.1.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.
Files changed (117) hide show
  1. package/README.md +123 -0
  2. package/dist/index.d.ts +267 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +195 -0
  5. package/dist/index.js.map +1 -0
  6. package/package.json +63 -0
  7. package/src/parser/Core/Bounds.mjs +61 -0
  8. package/src/parser/Core/Bounds.res +65 -0
  9. package/src/parser/Core/Grid.mjs +268 -0
  10. package/src/parser/Core/Grid.res +265 -0
  11. package/src/parser/Core/Position.mjs +83 -0
  12. package/src/parser/Core/Position.res +54 -0
  13. package/src/parser/Core/Types.mjs +435 -0
  14. package/src/parser/Core/Types.res +331 -0
  15. package/src/parser/Core/__tests__/Bounds_test.mjs +326 -0
  16. package/src/parser/Core/__tests__/Bounds_test.res +412 -0
  17. package/src/parser/Core/__tests__/Grid_test.mjs +322 -0
  18. package/src/parser/Core/__tests__/Grid_test.res +319 -0
  19. package/src/parser/Core/__tests__/Types_test.mjs +614 -0
  20. package/src/parser/Core/__tests__/Types_test.res +650 -0
  21. package/src/parser/Detector/BoxTracer.mjs +302 -0
  22. package/src/parser/Detector/BoxTracer.res +374 -0
  23. package/src/parser/Detector/HierarchyBuilder.mjs +158 -0
  24. package/src/parser/Detector/HierarchyBuilder.res +315 -0
  25. package/src/parser/Detector/ShapeDetector.mjs +134 -0
  26. package/src/parser/Detector/ShapeDetector.res +236 -0
  27. package/src/parser/Detector/__tests__/BoxTracer_test.mjs +70 -0
  28. package/src/parser/Detector/__tests__/BoxTracer_test.res +92 -0
  29. package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +489 -0
  30. package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +849 -0
  31. package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +377 -0
  32. package/src/parser/Detector/__tests__/ShapeDetector_test.res +563 -0
  33. package/src/parser/Errors/ErrorContext.mjs +106 -0
  34. package/src/parser/Errors/ErrorContext.res +191 -0
  35. package/src/parser/Errors/ErrorMessages.mjs +289 -0
  36. package/src/parser/Errors/ErrorMessages.res +303 -0
  37. package/src/parser/Errors/ErrorTypes.mjs +105 -0
  38. package/src/parser/Errors/ErrorTypes.res +169 -0
  39. package/src/parser/Interactions/InteractionMerger.mjs +266 -0
  40. package/src/parser/Interactions/InteractionMerger.res +450 -0
  41. package/src/parser/Interactions/InteractionParser.mjs +88 -0
  42. package/src/parser/Interactions/InteractionParser.res +127 -0
  43. package/src/parser/Interactions/SimpleInteractionParser.mjs +278 -0
  44. package/src/parser/Interactions/SimpleInteractionParser.res +262 -0
  45. package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +576 -0
  46. package/src/parser/Interactions/__tests__/InteractionMerger_test.res +646 -0
  47. package/src/parser/Parser.gen.tsx +96 -0
  48. package/src/parser/Parser.mjs +212 -0
  49. package/src/parser/Parser.res +481 -0
  50. package/src/parser/Scanner/__tests__/Grid_manual.mjs +214 -0
  51. package/src/parser/Scanner/__tests__/Grid_manual.res +141 -0
  52. package/src/parser/Semantic/ASTBuilder.mjs +197 -0
  53. package/src/parser/Semantic/ASTBuilder.res +288 -0
  54. package/src/parser/Semantic/AlignmentCalc.mjs +41 -0
  55. package/src/parser/Semantic/AlignmentCalc.res +104 -0
  56. package/src/parser/Semantic/Elements/ButtonParser.mjs +58 -0
  57. package/src/parser/Semantic/Elements/ButtonParser.res +131 -0
  58. package/src/parser/Semantic/Elements/CheckboxParser.mjs +58 -0
  59. package/src/parser/Semantic/Elements/CheckboxParser.res +79 -0
  60. package/src/parser/Semantic/Elements/CodeTextParser.mjs +50 -0
  61. package/src/parser/Semantic/Elements/CodeTextParser.res +111 -0
  62. package/src/parser/Semantic/Elements/ElementParser.mjs +15 -0
  63. package/src/parser/Semantic/Elements/ElementParser.res +83 -0
  64. package/src/parser/Semantic/Elements/EmphasisParser.mjs +46 -0
  65. package/src/parser/Semantic/Elements/EmphasisParser.res +67 -0
  66. package/src/parser/Semantic/Elements/InputParser.mjs +41 -0
  67. package/src/parser/Semantic/Elements/InputParser.res +97 -0
  68. package/src/parser/Semantic/Elements/LinkParser.mjs +60 -0
  69. package/src/parser/Semantic/Elements/LinkParser.res +156 -0
  70. package/src/parser/Semantic/Elements/TextParser.mjs +19 -0
  71. package/src/parser/Semantic/Elements/TextParser.res +42 -0
  72. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +189 -0
  73. package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +257 -0
  74. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +202 -0
  75. package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +250 -0
  76. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +293 -0
  77. package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +134 -0
  78. package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +253 -0
  79. package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +304 -0
  80. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +289 -0
  81. package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +402 -0
  82. package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +149 -0
  83. package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +167 -0
  84. package/src/parser/Semantic/ParserRegistry.mjs +82 -0
  85. package/src/parser/Semantic/ParserRegistry.res +145 -0
  86. package/src/parser/Semantic/SemanticParser.mjs +850 -0
  87. package/src/parser/Semantic/SemanticParser.res +1368 -0
  88. package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +187 -0
  89. package/src/parser/Semantic/__tests__/ASTBuilder_test.res +192 -0
  90. package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +154 -0
  91. package/src/parser/Semantic/__tests__/ParserRegistry_test.res +191 -0
  92. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +768 -0
  93. package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +1069 -0
  94. package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +1329 -0
  95. package/src/parser/Semantic/__tests__/SemanticParser_manual.res +544 -0
  96. package/src/parser/TestMain.mjs +21 -0
  97. package/src/parser/TestMain.res +14 -0
  98. package/src/parser/TextExtractor.mjs +179 -0
  99. package/src/parser/TextExtractor.res +264 -0
  100. package/src/parser/__tests__/GridScanner_integration.test.mjs +632 -0
  101. package/src/parser/__tests__/GridScanner_integration.test.res +816 -0
  102. package/src/parser/__tests__/Performance.test.mjs +244 -0
  103. package/src/parser/__tests__/Performance.test.res +371 -0
  104. package/src/parser/__tests__/PerformanceFixtures.mjs +200 -0
  105. package/src/parser/__tests__/PerformanceFixtures.res +284 -0
  106. package/src/parser/__tests__/WyreframeParser_integration.test.mjs +770 -0
  107. package/src/parser/__tests__/WyreframeParser_integration.test.res +1008 -0
  108. package/src/parser/__tests__/fixtures/alignment-test.txt +9 -0
  109. package/src/parser/__tests__/fixtures/all-elements.txt +16 -0
  110. package/src/parser/__tests__/fixtures/login-scene.txt +17 -0
  111. package/src/parser/__tests__/fixtures/multi-scene.txt +25 -0
  112. package/src/parser/__tests__/fixtures/nested-boxes.txt +15 -0
  113. package/src/parser/__tests__/fixtures/simple-box.txt +5 -0
  114. package/src/parser/__tests__/fixtures/with-dividers.txt +14 -0
  115. package/src/renderer/Renderer.gen.tsx +32 -0
  116. package/src/renderer/Renderer.mjs +391 -0
  117. package/src/renderer/Renderer.res +558 -0
@@ -0,0 +1,850 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Grid from "../Core/Grid.mjs";
4
+ import * as Types from "../Core/Types.mjs";
5
+ import * as Core__Int from "@rescript/core/src/Core__Int.mjs";
6
+ import * as AlignmentCalc from "./AlignmentCalc.mjs";
7
+ import * as ParserRegistry from "./ParserRegistry.mjs";
8
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
9
+
10
+ function isWithinChildBoxGrid(row, col, children) {
11
+ return children.some(child => {
12
+ let b = child.bounds;
13
+ if (row >= b.top && row <= b.bottom && col >= b.left) {
14
+ return col <= b.right;
15
+ } else {
16
+ return false;
17
+ }
18
+ });
19
+ }
20
+
21
+ function extractContentLinesFromGrid(box, grid) {
22
+ let bounds = box.bounds;
23
+ let children = box.children;
24
+ let contentStartRow = bounds.top + 1 | 0;
25
+ let contentEndRow = bounds.bottom - 1 | 0;
26
+ if (contentStartRow > contentEndRow) {
27
+ return [];
28
+ }
29
+ let contentLines = [];
30
+ for (let row = contentStartRow; row <= contentEndRow; ++row) {
31
+ let rowCoveredByChild = children.some(child => {
32
+ let b = child.bounds;
33
+ if (row >= b.top && row <= b.bottom && b.left <= (bounds.left + 1 | 0)) {
34
+ return b.right >= (bounds.right - 1 | 0);
35
+ } else {
36
+ return false;
37
+ }
38
+ });
39
+ if (!rowCoveredByChild) {
40
+ let rowCells = Grid.getLine(grid, row);
41
+ if (rowCells !== undefined) {
42
+ let contentStartCol = bounds.left + 1 | 0;
43
+ let contentEndCol = bounds.right - 1 | 0;
44
+ if (contentStartCol <= contentEndCol) {
45
+ let lineChars = [];
46
+ for (let col = contentStartCol; col <= contentEndCol; ++col) {
47
+ if (!isWithinChildBoxGrid(row, col, children)) {
48
+ let cell = rowCells[col];
49
+ if (cell !== undefined) {
50
+ let char;
51
+ if (typeof cell !== "object") {
52
+ switch (cell) {
53
+ case "Corner" :
54
+ char = "+";
55
+ break;
56
+ case "HLine" :
57
+ char = "-";
58
+ break;
59
+ case "VLine" :
60
+ char = "|";
61
+ break;
62
+ case "Divider" :
63
+ char = "=";
64
+ break;
65
+ case "Space" :
66
+ char = " ";
67
+ break;
68
+ }
69
+ } else {
70
+ char = cell._0;
71
+ }
72
+ lineChars.push(char);
73
+ }
74
+ }
75
+ }
76
+ let line = lineChars.join("");
77
+ contentLines.push(line);
78
+ } else {
79
+ contentLines.push("");
80
+ }
81
+ } else {
82
+ contentLines.push("");
83
+ }
84
+ }
85
+ }
86
+ return contentLines;
87
+ }
88
+
89
+ function cellCharToString(cell) {
90
+ if (typeof cell === "object") {
91
+ return cell._0;
92
+ }
93
+ switch (cell) {
94
+ case "Corner" :
95
+ return "+";
96
+ case "HLine" :
97
+ return "-";
98
+ case "VLine" :
99
+ return "|";
100
+ case "Divider" :
101
+ return "=";
102
+ case "Space" :
103
+ return " ";
104
+ }
105
+ }
106
+
107
+ function cellCharsToString(cells) {
108
+ return cells.map(cellCharToString).join("");
109
+ }
110
+
111
+ function getBoxContentAsString(box, grid) {
112
+ let lines = extractContentLinesFromGrid(box, grid);
113
+ return lines.join("\n");
114
+ }
115
+
116
+ function hasContent(box, grid) {
117
+ let lines = extractContentLinesFromGrid(box, grid);
118
+ return lines.some(line => {
119
+ let trimmed = line.trim();
120
+ return trimmed.length > 0;
121
+ });
122
+ }
123
+
124
+ function getContentLineCount(box, _grid) {
125
+ let bounds = box.bounds;
126
+ let contentStartRow = bounds.top + 1 | 0;
127
+ let contentEndRow = bounds.bottom - 1 | 0;
128
+ if (contentStartRow > contentEndRow) {
129
+ return 0;
130
+ } else {
131
+ return (contentEndRow - contentStartRow | 0) + 1 | 0;
132
+ }
133
+ }
134
+
135
+ function defaultSceneMetadata() {
136
+ return {
137
+ id: "main",
138
+ title: "main",
139
+ transition: "fade",
140
+ device: "Desktop"
141
+ };
142
+ }
143
+
144
+ function parseSceneDirectives(lines) {
145
+ let sceneId = {
146
+ contents: undefined
147
+ };
148
+ let title = {
149
+ contents: undefined
150
+ };
151
+ let transition = {
152
+ contents: undefined
153
+ };
154
+ let device = {
155
+ contents: undefined
156
+ };
157
+ let contentLines = [];
158
+ lines.forEach(line => {
159
+ let trimmed = line.trim();
160
+ if (trimmed.startsWith("@scene:")) {
161
+ let id = trimmed.replace("@scene:", "").trim();
162
+ sceneId.contents = id;
163
+ return;
164
+ }
165
+ if (trimmed.startsWith("@title:")) {
166
+ let titleValue = trimmed.replace("@title:", "").trim().replaceAll("\"", "");
167
+ title.contents = titleValue;
168
+ return;
169
+ }
170
+ if (trimmed.startsWith("@transition:")) {
171
+ let transitionValue = trimmed.replace("@transition:", "").trim();
172
+ transition.contents = transitionValue;
173
+ return;
174
+ }
175
+ if (!trimmed.startsWith("@device:")) {
176
+ if (trimmed.startsWith("@")) {
177
+ return;
178
+ } else {
179
+ contentLines.push(line);
180
+ return;
181
+ }
182
+ }
183
+ let deviceValue = trimmed.replace("@device:", "").trim();
184
+ let d = Types.parseDeviceType(deviceValue);
185
+ if (d !== undefined) {
186
+ device.contents = d;
187
+ return;
188
+ }
189
+ });
190
+ let id = sceneId.contents;
191
+ let finalId = id !== undefined ? id : "main";
192
+ let match = title.contents;
193
+ let match$1 = sceneId.contents;
194
+ let finalTitle = match !== undefined ? match : (
195
+ match$1 !== undefined ? match$1 : "main"
196
+ );
197
+ let t = transition.contents;
198
+ let finalTransition = t !== undefined ? t : "fade";
199
+ let d = device.contents;
200
+ let finalDevice = d !== undefined ? d : "Desktop";
201
+ let metadata = {
202
+ id: finalId,
203
+ title: finalTitle,
204
+ transition: finalTransition,
205
+ device: finalDevice
206
+ };
207
+ return [
208
+ metadata,
209
+ contentLines
210
+ ];
211
+ }
212
+
213
+ function splitSceneBlocks(wireframeText) {
214
+ let lines = wireframeText.split("\n");
215
+ let blocks = [];
216
+ let currentBlock = {
217
+ contents: []
218
+ };
219
+ lines.forEach(line => {
220
+ let trimmed = line.trim();
221
+ if (trimmed === "---") {
222
+ if (currentBlock.contents.length > 0) {
223
+ blocks.push(currentBlock.contents.join("\n"));
224
+ currentBlock.contents = [];
225
+ return;
226
+ } else {
227
+ return;
228
+ }
229
+ } else {
230
+ if (trimmed.startsWith("@scene:") && currentBlock.contents.length > 0) {
231
+ blocks.push(currentBlock.contents.join("\n"));
232
+ currentBlock.contents = [line];
233
+ } else {
234
+ currentBlock.contents = currentBlock.contents.concat([line]);
235
+ }
236
+ return;
237
+ }
238
+ });
239
+ if (currentBlock.contents.length > 0) {
240
+ blocks.push(currentBlock.contents.join("\n"));
241
+ }
242
+ return blocks.filter(block => block.trim() !== "");
243
+ }
244
+
245
+ function groupContentByScenes(wireframeText) {
246
+ let blocks = splitSceneBlocks(wireframeText);
247
+ if (blocks.length !== 0) {
248
+ return blocks.map(block => parseSceneDirectives(block.split("\n")));
249
+ }
250
+ let trimmed = wireframeText.trim();
251
+ if (trimmed !== "") {
252
+ return [[
253
+ {
254
+ id: "main",
255
+ title: "main",
256
+ transition: "fade",
257
+ device: "Desktop"
258
+ },
259
+ [wireframeText]
260
+ ]];
261
+ } else {
262
+ return [];
263
+ }
264
+ }
265
+
266
+ function isWithinChildBox(row, col, children) {
267
+ return children.some(child => {
268
+ let b = child.bounds;
269
+ if (row >= b.top && row <= b.bottom && col >= b.left) {
270
+ return col <= b.right;
271
+ } else {
272
+ return false;
273
+ }
274
+ });
275
+ }
276
+
277
+ function rowIntersectsChildBox(row, children) {
278
+ return children.some(child => {
279
+ let b = child.bounds;
280
+ if (row >= b.top) {
281
+ return row <= b.bottom;
282
+ } else {
283
+ return false;
284
+ }
285
+ });
286
+ }
287
+
288
+ function extractContentLines(box, gridCells) {
289
+ let bounds = box.bounds;
290
+ let children = box.children;
291
+ let contentStartRow = bounds.top + 1 | 0;
292
+ let contentEndRow = bounds.bottom - 1 | 0;
293
+ if (contentStartRow > contentEndRow) {
294
+ return [];
295
+ }
296
+ let contentLines = [];
297
+ let gridHeight = gridCells.length;
298
+ for (let row = contentStartRow; row <= contentEndRow; ++row) {
299
+ let rowCoveredByChild = children.some(child => {
300
+ let b = child.bounds;
301
+ if (row >= b.top && row <= b.bottom && b.left <= (bounds.left + 1 | 0)) {
302
+ return b.right >= (bounds.right - 1 | 0);
303
+ } else {
304
+ return false;
305
+ }
306
+ });
307
+ if (!rowCoveredByChild && row >= 0 && row < gridHeight) {
308
+ let rowCells = gridCells[row];
309
+ if (rowCells !== undefined) {
310
+ let leftBorderCell = rowCells[bounds.left];
311
+ let startsWithCorner = leftBorderCell === "Corner" && typeof leftBorderCell !== "object";
312
+ let contentStartCol = startsWithCorner ? bounds.left : bounds.left + 1 | 0;
313
+ let contentEndCol = bounds.right - 1 | 0;
314
+ let lineChars = [];
315
+ for (let col = contentStartCol; col <= contentEndCol; ++col) {
316
+ if (!isWithinChildBox(row, col, children) && col >= 0 && col < rowCells.length) {
317
+ let cell = rowCells[col];
318
+ if (typeof cell !== "object") {
319
+ switch (cell) {
320
+ case "Corner" :
321
+ lineChars.push("+");
322
+ break;
323
+ case "HLine" :
324
+ lineChars.push("-");
325
+ break;
326
+ case "VLine" :
327
+ lineChars.push("|");
328
+ break;
329
+ case "Divider" :
330
+ lineChars.push("=");
331
+ break;
332
+ case "Space" :
333
+ lineChars.push(" ");
334
+ break;
335
+ }
336
+ } else {
337
+ lineChars.push(cell._0);
338
+ }
339
+ }
340
+ }
341
+ let line = lineChars.join("");
342
+ contentLines.push(line);
343
+ }
344
+ }
345
+ }
346
+ return contentLines;
347
+ }
348
+
349
+ function isCheckboxContent(content) {
350
+ let trimmed = content.trim();
351
+ let lowerContent = trimmed.toLowerCase();
352
+ if (lowerContent === "x") {
353
+ return true;
354
+ } else {
355
+ return trimmed === "";
356
+ }
357
+ }
358
+
359
+ function splitInlineSegments(line) {
360
+ let segments = [];
361
+ let currentText = "";
362
+ let currentTextStart = 0;
363
+ let i = 0;
364
+ let len = line.length;
365
+ while (i < len) {
366
+ let char = line.charAt(i);
367
+ if (char === "[") {
368
+ let buttonStart = i;
369
+ let start = i + 1 | 0;
370
+ let endPos;
371
+ let j = start;
372
+ while (j < len && endPos === undefined) {
373
+ if (line.charAt(j) === "]") {
374
+ endPos = j;
375
+ }
376
+ j = j + 1 | 0;
377
+ };
378
+ let end = endPos;
379
+ if (end !== undefined) {
380
+ let bracketContent = line.slice(start, end);
381
+ if (isCheckboxContent(bracketContent)) {
382
+ if (currentText === "") {
383
+ currentTextStart = i;
384
+ }
385
+ let checkboxText = "[" + bracketContent + "]";
386
+ currentText = currentText + checkboxText;
387
+ i = end + 1 | 0;
388
+ } else {
389
+ let text = currentText.trim();
390
+ if (text !== "") {
391
+ let leadingSpaces = currentText.length - currentText.trimStart().length | 0;
392
+ segments.push({
393
+ TAG: "TextSegment",
394
+ _0: text,
395
+ _1: currentTextStart + leadingSpaces | 0
396
+ });
397
+ }
398
+ currentText = "";
399
+ let buttonText = bracketContent.trim();
400
+ if (buttonText !== "") {
401
+ segments.push({
402
+ TAG: "ButtonSegment",
403
+ _0: buttonText,
404
+ _1: buttonStart
405
+ });
406
+ }
407
+ i = end + 1 | 0;
408
+ currentTextStart = i;
409
+ }
410
+ } else {
411
+ if (currentText === "") {
412
+ currentTextStart = i;
413
+ }
414
+ currentText = currentText + char;
415
+ i = i + 1 | 0;
416
+ }
417
+ } else {
418
+ if (currentText === "") {
419
+ currentTextStart = i;
420
+ }
421
+ currentText = currentText + char;
422
+ i = i + 1 | 0;
423
+ }
424
+ };
425
+ let text$1 = currentText.trim();
426
+ if (text$1 !== "") {
427
+ let leadingSpaces$1 = currentText.length - currentText.trimStart().length | 0;
428
+ segments.push({
429
+ TAG: "TextSegment",
430
+ _0: text$1,
431
+ _1: currentTextStart + leadingSpaces$1 | 0
432
+ });
433
+ }
434
+ return segments;
435
+ }
436
+
437
+ function hasInlineElements(line) {
438
+ let segments = splitInlineSegments(line);
439
+ if (segments.length > 1) {
440
+ return true;
441
+ }
442
+ let match = segments[0];
443
+ if (match === undefined) {
444
+ return false;
445
+ }
446
+ switch (match.TAG) {
447
+ case "TextSegment" :
448
+ return false;
449
+ case "ButtonSegment" :
450
+ case "LinkSegment" :
451
+ return true;
452
+ }
453
+ }
454
+
455
+ function isDividerLine(line) {
456
+ let trimmed = line.trim();
457
+ let pureEqualsPattern = /^=+$/;
458
+ let cornerDividerPattern = /^\+=+\+?$/;
459
+ let length = trimmed.length;
460
+ if (length >= 3) {
461
+ if (pureEqualsPattern.test(trimmed)) {
462
+ return true;
463
+ } else {
464
+ return cornerDividerPattern.test(trimmed);
465
+ }
466
+ } else {
467
+ return false;
468
+ }
469
+ }
470
+
471
+ function extractSectionName(line) {
472
+ let trimmed = line.trim();
473
+ let sectionPattern = /^\+?-{2,}([^-+]+)-{2,}\+?\s*$/;
474
+ let result = sectionPattern.exec(trimmed);
475
+ if (result === null) {
476
+ return;
477
+ }
478
+ let match = result[1];
479
+ if (match === undefined) {
480
+ return;
481
+ }
482
+ let name = Primitive_option.valFromOption(match);
483
+ if (name == null) {
484
+ return;
485
+ }
486
+ let cleanName = name.trim();
487
+ if (cleanName !== "") {
488
+ return cleanName;
489
+ }
490
+ }
491
+
492
+ function isSectionFooter(line) {
493
+ let trimmed = line.trim();
494
+ let footerPattern = /^\+?-{3,}\+?\s*$/;
495
+ return footerPattern.test(trimmed);
496
+ }
497
+
498
+ function stripSectionBorders(line) {
499
+ let trimmed = line.trim();
500
+ let withoutLeading = trimmed.startsWith("| ") ? trimmed.slice(2) : (
501
+ trimmed.startsWith("|") ? trimmed.slice(1) : trimmed
502
+ );
503
+ if (withoutLeading.endsWith(" |")) {
504
+ return withoutLeading.slice(0, withoutLeading.length - 2 | 0);
505
+ } else if (withoutLeading.endsWith("|")) {
506
+ return withoutLeading.slice(0, withoutLeading.length - 1 | 0);
507
+ } else {
508
+ return withoutLeading;
509
+ }
510
+ }
511
+
512
+ function segmentToElement(segment, basePosition, baseCol, bounds) {
513
+ switch (segment.TAG) {
514
+ case "TextSegment" :
515
+ let text = segment._0;
516
+ let actualCol = baseCol + segment._1 | 0;
517
+ let position = Types.Position.make(basePosition.row, actualCol);
518
+ let align = AlignmentCalc.calculateWithStrategy(text, position, bounds, "RespectPosition");
519
+ return {
520
+ TAG: "Text",
521
+ content: text,
522
+ emphasis: false,
523
+ position: position,
524
+ align: align
525
+ };
526
+ case "ButtonSegment" :
527
+ let text$1 = segment._0;
528
+ let actualCol$1 = baseCol + segment._1 | 0;
529
+ let position$1 = Types.Position.make(basePosition.row, actualCol$1);
530
+ let id = text$1.trim().toLowerCase().replace(/\\s+/g, "-").replace(/[^a-z0-9-]/g, "").replace(/-+/g, "-").replace(/^-+|-+$/g, "");
531
+ let buttonContent = "[ " + text$1 + " ]";
532
+ let align$1 = AlignmentCalc.calculateWithStrategy(buttonContent, position$1, bounds, "RespectPosition");
533
+ return {
534
+ TAG: "Button",
535
+ id: id,
536
+ text: text$1,
537
+ position: position$1,
538
+ align: align$1,
539
+ actions: []
540
+ };
541
+ case "LinkSegment" :
542
+ let text$2 = segment._0;
543
+ let actualCol$2 = baseCol + segment._1 | 0;
544
+ let position$2 = Types.Position.make(basePosition.row, actualCol$2);
545
+ let id$1 = text$2.trim().toLowerCase().replace(/\\s+/g, "-").replace(/[^a-z0-9-]/g, "");
546
+ let align$2 = AlignmentCalc.calculateWithStrategy(text$2, position$2, bounds, "RespectPosition");
547
+ return {
548
+ TAG: "Link",
549
+ id: id$1,
550
+ text: text$2,
551
+ position: position$2,
552
+ align: align$2,
553
+ actions: []
554
+ };
555
+ }
556
+ }
557
+
558
+ function parseContentLine(line, lineIndex, contentStartRow, box, registry) {
559
+ let trimmed = line.trim();
560
+ if (trimmed === "") {
561
+ return;
562
+ }
563
+ let row = contentStartRow + lineIndex | 0;
564
+ let baseCol = box.bounds.left + 1 | 0;
565
+ let basePosition = Types.Position.make(row, baseCol);
566
+ let segments = splitInlineSegments(trimmed);
567
+ if (segments.length > 1) {
568
+ let rowChildren = segments.map(segment => segmentToElement(segment, basePosition, baseCol, box.bounds));
569
+ return {
570
+ TAG: "Row",
571
+ children: rowChildren,
572
+ align: "Left"
573
+ };
574
+ }
575
+ if (segments.length === 1) {
576
+ let trimmedStart = line.trimStart();
577
+ let leadingSpaces = line.length - trimmedStart.length | 0;
578
+ let match = segments[0];
579
+ if (match !== undefined) {
580
+ switch (match.TAG) {
581
+ case "TextSegment" :
582
+ break;
583
+ case "ButtonSegment" :
584
+ let actualCol = (baseCol + leadingSpaces | 0) + match._1 | 0;
585
+ let position = Types.Position.make(row, actualCol);
586
+ let buttonContent = "[ " + match._0 + " ]";
587
+ return ParserRegistry.parse(registry, buttonContent, position, box.bounds);
588
+ case "LinkSegment" :
589
+ let colOffset = match._1;
590
+ let actualCol$1 = (baseCol + leadingSpaces | 0) + colOffset | 0;
591
+ let adjustedPosition = Types.Position.make(basePosition.row, actualCol$1);
592
+ return segmentToElement({
593
+ TAG: "LinkSegment",
594
+ _0: match._0,
595
+ _1: colOffset
596
+ }, adjustedPosition, baseCol + leadingSpaces | 0, box.bounds);
597
+ }
598
+ }
599
+ let position$1 = Types.Position.make(row, baseCol + leadingSpaces | 0);
600
+ return ParserRegistry.parse(registry, trimmed, position$1, box.bounds);
601
+ }
602
+ let trimmedStart$1 = line.trimStart();
603
+ let leadingSpaces$1 = line.length - trimmedStart$1.length | 0;
604
+ let position$2 = Types.Position.make(row, baseCol + leadingSpaces$1 | 0);
605
+ return ParserRegistry.parse(registry, trimmed, position$2, box.bounds);
606
+ }
607
+
608
+ function parseBoxContent(box, gridCells, registry) {
609
+ let contentLines = extractContentLines(box, gridCells);
610
+ let elements = [];
611
+ let contentStartRow = box.bounds.top + 1 | 0;
612
+ let currentSection;
613
+ let i = 0;
614
+ while (i < contentLines.length) {
615
+ let lineOpt = contentLines[i];
616
+ if (lineOpt !== undefined) {
617
+ let lineIndex = i;
618
+ if (isDividerLine(lineOpt)) {
619
+ let row = contentStartRow + lineIndex | 0;
620
+ let col = box.bounds.left + 1 | 0;
621
+ elements.push({
622
+ TAG: "Divider",
623
+ position: Types.Position.make(row, col)
624
+ });
625
+ i = i + 1 | 0;
626
+ } else {
627
+ let sectionName = extractSectionName(lineOpt);
628
+ if (sectionName !== undefined) {
629
+ let sectionContent = [];
630
+ i = i + 1 | 0;
631
+ let foundFooter = false;
632
+ while (i < contentLines.length && !foundFooter) {
633
+ let contentLine = contentLines[i];
634
+ if (contentLine !== undefined) {
635
+ if (isSectionFooter(contentLine)) {
636
+ foundFooter = true;
637
+ i = i + 1 | 0;
638
+ } else {
639
+ sectionContent.push([
640
+ contentLine,
641
+ i
642
+ ]);
643
+ i = i + 1 | 0;
644
+ }
645
+ } else {
646
+ i = i + 1 | 0;
647
+ }
648
+ };
649
+ let sectionElements = [];
650
+ sectionContent.forEach(param => {
651
+ let strippedLine = stripSectionBorders(param[0]);
652
+ let elem = parseContentLine(strippedLine, param[1], contentStartRow, box, registry);
653
+ if (elem !== undefined) {
654
+ sectionElements.push(elem);
655
+ return;
656
+ }
657
+ });
658
+ let sectionElement = {
659
+ TAG: "Section",
660
+ name: sectionName,
661
+ children: sectionElements
662
+ };
663
+ elements.push(sectionElement);
664
+ } else if (isSectionFooter(lineOpt)) {
665
+ i = i + 1 | 0;
666
+ } else {
667
+ let elem = parseContentLine(lineOpt, lineIndex, contentStartRow, box, registry);
668
+ if (elem !== undefined) {
669
+ elements.push(elem);
670
+ }
671
+ i = i + 1 | 0;
672
+ }
673
+ }
674
+ } else {
675
+ i = i + 1 | 0;
676
+ }
677
+ };
678
+ let match = currentSection;
679
+ if (match !== undefined) {
680
+ let sectionElements$1 = [];
681
+ match[2].forEach(param => {
682
+ let strippedLine = stripSectionBorders(param[0]);
683
+ let elem = parseContentLine(strippedLine, param[1], contentStartRow, box, registry);
684
+ if (elem !== undefined) {
685
+ sectionElements$1.push(elem);
686
+ return;
687
+ }
688
+ });
689
+ elements.push({
690
+ TAG: "Section",
691
+ name: match[0],
692
+ children: sectionElements$1
693
+ });
694
+ }
695
+ return elements;
696
+ }
697
+
698
+ function getElementRow(_elem) {
699
+ while (true) {
700
+ let elem = _elem;
701
+ switch (elem.TAG) {
702
+ case "Box" :
703
+ return elem.bounds.top;
704
+ case "Divider" :
705
+ return elem.position.row;
706
+ case "Row" :
707
+ let child = elem.children[0];
708
+ if (child === undefined) {
709
+ return 0;
710
+ }
711
+ _elem = child;
712
+ continue;
713
+ case "Section" :
714
+ let child$1 = elem.children[0];
715
+ if (child$1 === undefined) {
716
+ return Core__Int.Constants.maxValue;
717
+ }
718
+ _elem = child$1;
719
+ continue;
720
+ default:
721
+ return elem.position.row;
722
+ }
723
+ };
724
+ }
725
+
726
+ function parseBoxRecursive(box, gridCells, registry) {
727
+ let contentElements = parseBoxContent(box, gridCells, registry);
728
+ let childBoxElements = box.children.map(childBox => parseBoxRecursive(childBox, gridCells, registry));
729
+ let allChildren = contentElements.concat(childBoxElements);
730
+ let sortedChildren = allChildren.toSorted((a, b) => {
731
+ let rowA = getElementRow(a);
732
+ let rowB = getElementRow(b);
733
+ return rowA - rowB | 0;
734
+ });
735
+ return {
736
+ TAG: "Box",
737
+ name: box.name,
738
+ bounds: box.bounds,
739
+ children: sortedChildren
740
+ };
741
+ }
742
+
743
+ function buildScene(metadata, elements) {
744
+ return {
745
+ id: metadata.id,
746
+ title: metadata.title,
747
+ transition: metadata.transition,
748
+ device: metadata.device,
749
+ elements: elements
750
+ };
751
+ }
752
+
753
+ function buildAST(scenes) {
754
+ return {
755
+ scenes: scenes
756
+ };
757
+ }
758
+
759
+ function parse(context) {
760
+ let errors = [];
761
+ if (context.shapes.length === 0) {
762
+ return {
763
+ TAG: "Ok",
764
+ _0: {
765
+ scenes: []
766
+ }
767
+ };
768
+ }
769
+ let scenes = context.shapes.map(box => {
770
+ let boxElement = parseBoxRecursive(box, context.gridCells, context.registry);
771
+ let elements;
772
+ elements = boxElement.TAG === "Box" ? boxElement.children : [];
773
+ let name = box.name;
774
+ let metadata = name !== undefined ? ({
775
+ id: name,
776
+ title: name,
777
+ transition: "fade",
778
+ device: "Desktop"
779
+ }) : ({
780
+ id: "main",
781
+ title: "main",
782
+ transition: "fade",
783
+ device: "Desktop"
784
+ });
785
+ return buildScene(metadata, elements);
786
+ });
787
+ let ast = {
788
+ scenes: scenes
789
+ };
790
+ if (errors.length > 0) {
791
+ return {
792
+ TAG: "Error",
793
+ _0: errors
794
+ };
795
+ } else {
796
+ return {
797
+ TAG: "Ok",
798
+ _0: ast
799
+ };
800
+ }
801
+ }
802
+
803
+ function parseWithSceneDirectives(wireframeText, context) {
804
+ let sceneGroups = groupContentByScenes(wireframeText);
805
+ let scenes = sceneGroups.map(param => {
806
+ let elements = context.shapes.map(box => parseBoxRecursive(box, context.gridCells, context.registry));
807
+ return buildScene(param[0], elements);
808
+ });
809
+ let ast = {
810
+ scenes: scenes
811
+ };
812
+ return {
813
+ TAG: "Ok",
814
+ _0: ast
815
+ };
816
+ }
817
+
818
+ export {
819
+ isWithinChildBoxGrid,
820
+ extractContentLinesFromGrid,
821
+ cellCharToString,
822
+ cellCharsToString,
823
+ getBoxContentAsString,
824
+ hasContent,
825
+ getContentLineCount,
826
+ defaultSceneMetadata,
827
+ parseSceneDirectives,
828
+ splitSceneBlocks,
829
+ groupContentByScenes,
830
+ isWithinChildBox,
831
+ rowIntersectsChildBox,
832
+ extractContentLines,
833
+ isCheckboxContent,
834
+ splitInlineSegments,
835
+ hasInlineElements,
836
+ isDividerLine,
837
+ extractSectionName,
838
+ isSectionFooter,
839
+ stripSectionBorders,
840
+ segmentToElement,
841
+ parseContentLine,
842
+ parseBoxContent,
843
+ getElementRow,
844
+ parseBoxRecursive,
845
+ buildScene,
846
+ buildAST,
847
+ parse,
848
+ parseWithSceneDirectives,
849
+ }
850
+ /* Grid Not a pure module */