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,544 @@
1
+ // SemanticParser_test.res
2
+ // Unit tests for SemanticParser - Box Content Extraction
3
+
4
+ open Types
5
+
6
+ // Helper to create a simple grid for testing
7
+ let makeTestGrid = (lines: array<string>): Grid.t => {
8
+ Grid.fromLines(lines)
9
+ }
10
+
11
+ // Helper to create a box with bounds
12
+ let makeTestBox = (top: int, left: int, bottom: int, right: int): SemanticParser.box => {
13
+ {
14
+ name: None,
15
+ bounds: {top, left, bottom, right},
16
+ children: [],
17
+ }
18
+ }
19
+
20
+ // Test 1: Extract content from a simple box
21
+ let test_extractContentLines_simpleBox = () => {
22
+ let grid = makeTestGrid([
23
+ "+-------+",
24
+ "| Hello |",
25
+ "+-------+",
26
+ ])
27
+
28
+ let box = makeTestBox(0, 0, 2, 8)
29
+ let content = SemanticParser.extractContentLines(box, grid.cells)
30
+
31
+ // Should extract: [" Hello "]
32
+ assert(Array.length(content) === 1)
33
+ assert(Array.getUnsafe(content, 0) === " Hello ")
34
+ }
35
+
36
+ // Test 2: Extract content from box with multiple lines
37
+ let test_extractContentLines_multipleLines = () => {
38
+ let grid = makeTestGrid([
39
+ "+--Login--+",
40
+ "| #email |",
41
+ "| [Submit]|",
42
+ "+----------+",
43
+ ])
44
+
45
+ let box = makeTestBox(0, 0, 3, 10)
46
+ let content = SemanticParser.extractContentLines(box, grid.cells)
47
+
48
+ // Should extract: [" #email ", " [Submit]"]
49
+ assert(Array.length(content) === 2)
50
+ assert(Array.getUnsafe(content, 0) === " #email ")
51
+ assert(Array.getUnsafe(content, 1) === " [Submit]")
52
+ }
53
+
54
+ // Test 3: Extract content preserving internal whitespace
55
+ let test_extractContentLines_preserveWhitespace = () => {
56
+ let grid = makeTestGrid([
57
+ "+---------+",
58
+ "| a b |",
59
+ "+---------+",
60
+ ])
61
+
62
+ let box = makeTestBox(0, 0, 2, 10)
63
+ let content = SemanticParser.extractContentLines(box, grid.cells)
64
+
65
+ // Should preserve the exact spacing: " a b "
66
+ assert(Array.length(content) === 1)
67
+ assert(Array.getUnsafe(content, 0) === " a b ")
68
+ }
69
+
70
+ // Test 4: Empty box (no content area)
71
+ let test_extractContentLines_emptyBox = () => {
72
+ let grid = makeTestGrid([
73
+ "+---+",
74
+ "+---+",
75
+ ])
76
+
77
+ let box = makeTestBox(0, 0, 1, 4)
78
+ let content = SemanticParser.extractContentLines(box, grid.cells)
79
+
80
+ // Should return empty array for box with no content area
81
+ assert(Array.length(content) === 0)
82
+ }
83
+
84
+ // Test 5: Box with divider in content
85
+ let test_extractContentLines_withDivider = () => {
86
+ let grid = makeTestGrid([
87
+ "+------+",
88
+ "| Head |",
89
+ "|======|",
90
+ "| Body |",
91
+ "+------+",
92
+ ])
93
+
94
+ let box = makeTestBox(0, 0, 4, 7)
95
+ let content = SemanticParser.extractContentLines(box, grid.cells)
96
+
97
+ // Should extract all lines including divider
98
+ assert(Array.length(content) === 3)
99
+ assert(Array.getUnsafe(content, 0) === " Head ")
100
+ assert(Array.getUnsafe(content, 1) === "======")
101
+ assert(Array.getUnsafe(content, 2) === " Body ")
102
+ }
103
+
104
+ // Test 6: Box with empty lines
105
+ let test_extractContentLines_withEmptyLines = () => {
106
+ let grid = makeTestGrid([
107
+ "+-----+",
108
+ "| Top |",
109
+ "| |",
110
+ "| Bot |",
111
+ "+-----+",
112
+ ])
113
+
114
+ let box = makeTestBox(0, 0, 4, 6)
115
+ let content = SemanticParser.extractContentLines(box, grid.cells)
116
+
117
+ // Should extract all lines, empty line as spaces
118
+ assert(Array.length(content) === 3)
119
+ assert(Array.getUnsafe(content, 0) === " Top ")
120
+ assert(Array.getUnsafe(content, 1) === " ")
121
+ assert(Array.getUnsafe(content, 2) === " Bot ")
122
+ }
123
+
124
+ // Test 7: Nested box scenario (inner box content)
125
+ let test_extractContentLines_nestedBox = () => {
126
+ let grid = makeTestGrid([
127
+ "+-----------+",
128
+ "| +-------+ |",
129
+ "| | Inner | |",
130
+ "| +-------+ |",
131
+ "+-----------+",
132
+ ])
133
+
134
+ // Extract inner box content
135
+ let innerBox = makeTestBox(1, 2, 3, 9)
136
+ let innerContent = SemanticParser.extractContentLines(innerBox, grid.cells)
137
+
138
+ // Should extract: [" Inner "]
139
+ assert(Array.length(innerContent) === 1)
140
+ assert(Array.getUnsafe(innerContent, 0) === " Inner ")
141
+
142
+ // Extract outer box content (includes inner box structure)
143
+ let outerBox = makeTestBox(0, 0, 4, 12)
144
+ let outerContent = SemanticParser.extractContentLines(outerBox, grid.cells)
145
+
146
+ // Should extract outer content with inner box visible
147
+ assert(Array.length(outerContent) === 3)
148
+ assert(String.includes(Array.getUnsafe(outerContent, 0), "+-------+"))
149
+ }
150
+
151
+ // Test 8: Box with special characters in content
152
+ let test_extractContentLines_specialChars = () => {
153
+ let grid = makeTestGrid([
154
+ "+--------+",
155
+ "| a|b-c+ |",
156
+ "+--------+",
157
+ ])
158
+
159
+ let box = makeTestBox(0, 0, 2, 9)
160
+ let content = SemanticParser.extractContentLines(box, grid.cells)
161
+
162
+ // Should preserve special chars that appear in content
163
+ assert(Array.length(content) === 1)
164
+ assert(Array.getUnsafe(content, 0) === " a|b-c+ ")
165
+ }
166
+
167
+ // Test utility functions
168
+
169
+ // Test: hasContent with non-empty box
170
+ let test_hasContent_nonEmpty = () => {
171
+ let grid = makeTestGrid([
172
+ "+-----+",
173
+ "| Txt |",
174
+ "+-----+",
175
+ ])
176
+
177
+ let box = makeTestBox(0, 0, 2, 6)
178
+ assert(SemanticParser.hasContent(box, grid) === true)
179
+ }
180
+
181
+ // Test: hasContent with empty box
182
+ let test_hasContent_empty = () => {
183
+ let grid = makeTestGrid([
184
+ "+-----+",
185
+ "| |",
186
+ "+-----+",
187
+ ])
188
+
189
+ let box = makeTestBox(0, 0, 2, 6)
190
+ assert(SemanticParser.hasContent(box, grid) === false)
191
+ }
192
+
193
+ // Test: getContentLineCount
194
+ let test_getContentLineCount = () => {
195
+ let grid = makeTestGrid([
196
+ "+-----+",
197
+ "| L1 |",
198
+ "| L2 |",
199
+ "| L3 |",
200
+ "+-----+",
201
+ ])
202
+
203
+ let box = makeTestBox(0, 0, 4, 6)
204
+ assert(SemanticParser.getContentLineCount(box, grid) === 3)
205
+ }
206
+
207
+ // ============================================================================
208
+ // Scene Directive Parsing Tests
209
+ // ============================================================================
210
+
211
+ // Test: parseSceneDirectives with @scene
212
+ let test_parseSceneDirectives_scene = () => {
213
+ let lines = ["@scene: login", "+--Box--+", "| |", "+-------+"]
214
+ let (metadata, contentLines) = SemanticParser.parseSceneDirectives(lines)
215
+
216
+ assert(metadata.id === "login")
217
+ assert(metadata.title === "login")
218
+ assert(metadata.transition === "fade")
219
+ assert(Array.length(contentLines) === 3)
220
+ }
221
+
222
+ // Test: parseSceneDirectives with @title
223
+ let test_parseSceneDirectives_title = () => {
224
+ let lines = ["@scene: login", "@title: Login Page", "+--Box--+"]
225
+ let (metadata, _) = SemanticParser.parseSceneDirectives(lines)
226
+
227
+ assert(metadata.id === "login")
228
+ assert(metadata.title === "Login Page")
229
+ }
230
+
231
+ // Test: parseSceneDirectives removes quotes from @title
232
+ let test_parseSceneDirectives_titleQuotes = () => {
233
+ let lines = ["@scene: login", "@title: \"Login Page\"", "+--Box--+"]
234
+ let (metadata, _) = SemanticParser.parseSceneDirectives(lines)
235
+
236
+ assert(metadata.title === "Login Page")
237
+ }
238
+
239
+ // Test: parseSceneDirectives with @transition
240
+ let test_parseSceneDirectives_transition = () => {
241
+ let lines = ["@scene: login", "@transition: slide", "+--Box--+"]
242
+ let (metadata, _) = SemanticParser.parseSceneDirectives(lines)
243
+
244
+ assert(metadata.transition === "slide")
245
+ }
246
+
247
+ // Test: parseSceneDirectives all directives together
248
+ let test_parseSceneDirectives_allDirectives = () => {
249
+ let lines = [
250
+ "@scene: login",
251
+ "@title: Login Page",
252
+ "@transition: slide",
253
+ "",
254
+ "+--Login--+",
255
+ "| #email |",
256
+ "+----------+",
257
+ ]
258
+ let (metadata, contentLines) = SemanticParser.parseSceneDirectives(lines)
259
+
260
+ assert(metadata.id === "login")
261
+ assert(metadata.title === "Login Page")
262
+ assert(metadata.transition === "slide")
263
+ assert(Array.length(contentLines) === 4)
264
+ }
265
+
266
+ // Test: parseSceneDirectives defaults
267
+ let test_parseSceneDirectives_defaults = () => {
268
+ let lines = ["+--Box--+", "| |", "+-------+"]
269
+ let (metadata, _) = SemanticParser.parseSceneDirectives(lines)
270
+
271
+ assert(metadata.id === "main")
272
+ assert(metadata.title === "main")
273
+ assert(metadata.transition === "fade")
274
+ }
275
+
276
+ // Test: parseSceneDirectives ignores unknown directives
277
+ let test_parseSceneDirectives_unknownDirectives = () => {
278
+ let lines = ["@scene: login", "@unknown: something", "@custom: value", "+--Box--+"]
279
+ let (metadata, contentLines) = SemanticParser.parseSceneDirectives(lines)
280
+
281
+ assert(metadata.id === "login")
282
+ assert(Array.length(contentLines) === 1)
283
+ }
284
+
285
+ // Test: splitSceneBlocks with --- separator
286
+ let test_splitSceneBlocks_dashedSeparator = () => {
287
+ let input = `@scene: login
288
+ +--Login--+
289
+
290
+ ---
291
+
292
+ @scene: home
293
+ +--Home--+`
294
+
295
+ let blocks = SemanticParser.splitSceneBlocks(input)
296
+
297
+ assert(Array.length(blocks) === 2)
298
+ assert(String.includes(blocks[0]->Belt.Option.getExn, "@scene: login"))
299
+ assert(String.includes(blocks[1]->Belt.Option.getExn, "@scene: home"))
300
+ }
301
+
302
+ // Test: splitSceneBlocks with @scene separator
303
+ let test_splitSceneBlocks_sceneDirectiveSeparator = () => {
304
+ let input = `@scene: login
305
+ +--Login--+
306
+ @scene: home
307
+ +--Home--+`
308
+
309
+ let blocks = SemanticParser.splitSceneBlocks(input)
310
+
311
+ assert(Array.length(blocks) === 2)
312
+ }
313
+
314
+ // Test: splitSceneBlocks single scene
315
+ let test_splitSceneBlocks_singleScene = () => {
316
+ let input = `@scene: login
317
+ +--Login--+
318
+ | #email |
319
+ +----------+`
320
+
321
+ let blocks = SemanticParser.splitSceneBlocks(input)
322
+
323
+ assert(Array.length(blocks) === 1)
324
+ }
325
+
326
+ // Test: splitSceneBlocks filters empty blocks
327
+ let test_splitSceneBlocks_filtersEmpty = () => {
328
+ let input = `
329
+
330
+ ---
331
+
332
+ @scene: login
333
+ +--Box--+
334
+
335
+ ---
336
+
337
+ `
338
+
339
+ let blocks = SemanticParser.splitSceneBlocks(input)
340
+
341
+ assert(Array.length(blocks) === 1)
342
+ }
343
+
344
+ // Test: groupContentByScenes simple scene
345
+ let test_groupContentByScenes_simple = () => {
346
+ let input = `@scene: login
347
+ @title: Login Page
348
+ @transition: slide
349
+
350
+ +--Login--+
351
+ | #email |
352
+ +----------+`
353
+
354
+ let scenes = SemanticParser.groupContentByScenes(input)
355
+
356
+ assert(Array.length(scenes) === 1)
357
+
358
+ let (metadata, content) = scenes[0]->Belt.Option.getExn
359
+ assert(metadata.id === "login")
360
+ assert(metadata.title === "Login Page")
361
+ assert(metadata.transition === "slide")
362
+ assert(Array.length(content) > 0)
363
+ }
364
+
365
+ // Test: groupContentByScenes multiple scenes
366
+ let test_groupContentByScenes_multiple = () => {
367
+ let input = `@scene: login
368
+ +--Login--+
369
+
370
+ ---
371
+
372
+ @scene: home
373
+ +--Home--+
374
+
375
+ ---
376
+
377
+ @scene: settings
378
+ +--Settings--+`
379
+
380
+ let scenes = SemanticParser.groupContentByScenes(input)
381
+
382
+ assert(Array.length(scenes) === 3)
383
+
384
+ let (meta1, _) = scenes[0]->Belt.Option.getExn
385
+ let (meta2, _) = scenes[1]->Belt.Option.getExn
386
+ let (meta3, _) = scenes[2]->Belt.Option.getExn
387
+
388
+ assert(meta1.id === "login")
389
+ assert(meta2.id === "home")
390
+ assert(meta3.id === "settings")
391
+ }
392
+
393
+ // Test: groupContentByScenes default scene
394
+ let test_groupContentByScenes_default = () => {
395
+ let input = `+--Box--+
396
+ | Text |
397
+ +-------+`
398
+
399
+ let scenes = SemanticParser.groupContentByScenes(input)
400
+
401
+ assert(Array.length(scenes) === 1)
402
+
403
+ let (metadata, _) = scenes[0]->Belt.Option.getExn
404
+ assert(metadata.id === "main")
405
+ assert(metadata.title === "main")
406
+ assert(metadata.transition === "fade")
407
+ }
408
+
409
+ // Test: groupContentByScenes empty input
410
+ let test_groupContentByScenes_empty = () => {
411
+ let input = ""
412
+ let scenes = SemanticParser.groupContentByScenes(input)
413
+
414
+ assert(Array.length(scenes) === 0)
415
+ }
416
+
417
+ // Test: groupContentByScenes complex example
418
+ let test_groupContentByScenes_complex = () => {
419
+ let input = `@scene: login
420
+ @title: "Login Page"
421
+
422
+ +--Login----------------+
423
+ | * WYREFRAME |
424
+ | |
425
+ | #email |
426
+ | #password |
427
+ | |
428
+ | [ Login ] |
429
+ +----------------------+
430
+
431
+ ---
432
+
433
+ @scene: home
434
+ @transition: slide
435
+
436
+ +--Home-----------------+
437
+ | Welcome! |
438
+ +----------------------+`
439
+
440
+ let scenes = SemanticParser.groupContentByScenes(input)
441
+
442
+ assert(Array.length(scenes) === 2)
443
+
444
+ let (loginMeta, loginContent) = scenes[0]->Belt.Option.getExn
445
+ assert(loginMeta.id === "login")
446
+ assert(loginMeta.title === "Login Page")
447
+ assert(String.includes(Array.join(loginContent, "\n"), "#email"))
448
+
449
+ let (homeMeta, homeContent) = scenes[1]->Belt.Option.getExn
450
+ assert(homeMeta.id === "home")
451
+ assert(homeMeta.transition === "slide")
452
+ assert(String.includes(Array.join(homeContent, "\n"), "Welcome!"))
453
+ }
454
+
455
+ // Run all tests
456
+ let runTests = () => {
457
+ Console.log("Running SemanticParser tests...")
458
+ Console.log("\n=== Box Content Extraction ===")
459
+
460
+ test_extractContentLines_simpleBox()
461
+ Console.log("✓ Simple box content extraction")
462
+
463
+ test_extractContentLines_multipleLines()
464
+ Console.log("✓ Multiple lines extraction")
465
+
466
+ test_extractContentLines_preserveWhitespace()
467
+ Console.log("✓ Whitespace preservation")
468
+
469
+ test_extractContentLines_emptyBox()
470
+ Console.log("✓ Empty box handling")
471
+
472
+ test_extractContentLines_withDivider()
473
+ Console.log("✓ Box with divider")
474
+
475
+ test_extractContentLines_withEmptyLines()
476
+ Console.log("✓ Box with empty lines")
477
+
478
+ test_extractContentLines_nestedBox()
479
+ Console.log("✓ Nested box content")
480
+
481
+ test_extractContentLines_specialChars()
482
+ Console.log("✓ Special characters in content")
483
+
484
+ test_hasContent_nonEmpty()
485
+ Console.log("✓ hasContent (non-empty)")
486
+
487
+ test_hasContent_empty()
488
+ Console.log("✓ hasContent (empty)")
489
+
490
+ test_getContentLineCount()
491
+ Console.log("✓ getContentLineCount")
492
+
493
+ Console.log("\n=== Scene Directive Parsing ===")
494
+
495
+ test_parseSceneDirectives_scene()
496
+ Console.log("✓ Parse @scene directive")
497
+
498
+ test_parseSceneDirectives_title()
499
+ Console.log("✓ Parse @title directive")
500
+
501
+ test_parseSceneDirectives_titleQuotes()
502
+ Console.log("✓ Remove quotes from @title")
503
+
504
+ test_parseSceneDirectives_transition()
505
+ Console.log("✓ Parse @transition directive")
506
+
507
+ test_parseSceneDirectives_allDirectives()
508
+ Console.log("✓ Parse all directives together")
509
+
510
+ test_parseSceneDirectives_defaults()
511
+ Console.log("✓ Default metadata values")
512
+
513
+ test_parseSceneDirectives_unknownDirectives()
514
+ Console.log("✓ Ignore unknown directives")
515
+
516
+ test_splitSceneBlocks_dashedSeparator()
517
+ Console.log("✓ Split scenes by --- separator")
518
+
519
+ test_splitSceneBlocks_sceneDirectiveSeparator()
520
+ Console.log("✓ Split scenes by @scene directive")
521
+
522
+ test_splitSceneBlocks_singleScene()
523
+ Console.log("✓ Handle single scene")
524
+
525
+ test_splitSceneBlocks_filtersEmpty()
526
+ Console.log("✓ Filter empty blocks")
527
+
528
+ test_groupContentByScenes_simple()
529
+ Console.log("✓ Group simple scene with directives")
530
+
531
+ test_groupContentByScenes_multiple()
532
+ Console.log("✓ Group multiple scenes")
533
+
534
+ test_groupContentByScenes_default()
535
+ Console.log("✓ Create default scene")
536
+
537
+ test_groupContentByScenes_empty()
538
+ Console.log("✓ Handle empty input")
539
+
540
+ test_groupContentByScenes_complex()
541
+ Console.log("✓ Handle complex multi-scene example")
542
+
543
+ Console.log("\n✅ All SemanticParser tests passed!")
544
+ }
@@ -0,0 +1,21 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+
4
+ let projectName = "wyreframe-parser";
5
+
6
+ let version = "0.1.0";
7
+
8
+ function greet(name) {
9
+ return `Hello, ` + name + `! Welcome to ` + projectName + ` v` + version;
10
+ }
11
+
12
+ console.log("ReScript compiler is working correctly!");
13
+
14
+ console.log(greet("Developer"));
15
+
16
+ export {
17
+ projectName,
18
+ version,
19
+ greet,
20
+ }
21
+ /* Not a pure module */
@@ -0,0 +1,14 @@
1
+ // Minimal test file to verify ReScript compilation
2
+ // This validates the ReScript toolchain is properly configured
3
+
4
+ let projectName = "wyreframe-parser"
5
+ let version = "0.1.0"
6
+
7
+ // Simple function demonstrating ReScript type safety
8
+ let greet = (name: string): string => {
9
+ `Hello, ${name}! Welcome to ${projectName} v${version}`
10
+ }
11
+
12
+ // Verify compilation works
13
+ Console.log("ReScript compiler is working correctly!")
14
+ Console.log(greet("Developer"))