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,489 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Types from "../../Core/Types.mjs";
4
+ import * as Vitest from "rescript-vitest/src/Vitest.mjs";
5
+ import * as HierarchyBuilder from "../HierarchyBuilder.mjs";
6
+
7
+ Vitest.describe("HierarchyBuilder - Containment Detection", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
8
+ Vitest.test("contains returns true when outer completely contains inner", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
9
+ let outer = Types.Bounds.make(0, 0, 10, 10);
10
+ let inner = Types.Bounds.make(2, 2, 8, 8);
11
+ t.expect(HierarchyBuilder.contains(outer, inner)).toBe(true);
12
+ });
13
+ Vitest.test("contains returns false when boxes are equal", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
14
+ let bounds = Types.Bounds.make(0, 0, 10, 10);
15
+ t.expect(HierarchyBuilder.contains(bounds, bounds)).toBe(false);
16
+ });
17
+ Vitest.test("contains returns false when boxes are disjoint", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
18
+ let box1 = Types.Bounds.make(0, 0, 5, 5);
19
+ let box2 = Types.Bounds.make(10, 10, 15, 15);
20
+ t.expect(HierarchyBuilder.contains(box1, box2)).toBe(false);
21
+ });
22
+ Vitest.test("contains returns false when boxes partially overlap", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
23
+ let box1 = Types.Bounds.make(0, 0, 10, 10);
24
+ let box2 = Types.Bounds.make(5, 5, 15, 15);
25
+ t.expect(HierarchyBuilder.contains(box1, box2)).toBe(false);
26
+ });
27
+ Vitest.test("contains returns false when inner touches outer's edge", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
28
+ let outer = Types.Bounds.make(0, 0, 10, 10);
29
+ let inner = Types.Bounds.make(0, 0, 5, 5);
30
+ t.expect(HierarchyBuilder.contains(outer, inner)).toBe(false);
31
+ });
32
+ });
33
+
34
+ Vitest.describe("HierarchyBuilder - findParent", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
35
+ Vitest.test("findParent returns None for root box (no container)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
36
+ let box = HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 10, 10));
37
+ let candidates = [box];
38
+ t.expect(HierarchyBuilder.findParent(box, candidates)).toEqual(undefined);
39
+ });
40
+ Vitest.test("findParent returns immediate parent (smallest containing box)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
41
+ let grandparent = HierarchyBuilder.makeBox("Grandparent", Types.Bounds.make(0, 0, 20, 20));
42
+ let parent = HierarchyBuilder.makeBox("Parent", Types.Bounds.make(2, 2, 18, 18));
43
+ let child = HierarchyBuilder.makeBox("Child", Types.Bounds.make(4, 4, 16, 16));
44
+ let candidates = [
45
+ grandparent,
46
+ parent,
47
+ child
48
+ ];
49
+ t.expect(HierarchyBuilder.findParent(child, candidates)).toEqual(parent);
50
+ });
51
+ Vitest.test("findParent ignores boxes that don't contain the target", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
52
+ let box1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 5, 5));
53
+ let box2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(10, 10, 15, 15));
54
+ let candidates = [
55
+ box1,
56
+ box2
57
+ ];
58
+ t.expect(HierarchyBuilder.findParent(box2, candidates)).toEqual(undefined);
59
+ });
60
+ });
61
+
62
+ Vitest.describe("HierarchyBuilder - buildHierarchy - 2-level nesting", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
63
+ Vitest.test("builds hierarchy with one root and one child", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
64
+ let parent = HierarchyBuilder.makeBox("Parent", Types.Bounds.make(0, 0, 10, 10));
65
+ let child = HierarchyBuilder.makeBox("Child", Types.Bounds.make(2, 2, 8, 8));
66
+ let boxes = [
67
+ parent,
68
+ child
69
+ ];
70
+ let result = HierarchyBuilder.buildHierarchy(boxes);
71
+ if (result.TAG !== "Ok") {
72
+ return t.expect(true).toBe(false);
73
+ }
74
+ let roots = result._0;
75
+ t.expect(roots.length).toBe(1);
76
+ let root = roots[0];
77
+ if (root === undefined) {
78
+ return t.expect(true).toBe(false);
79
+ }
80
+ t.expect(root.name).toEqual("Parent");
81
+ t.expect(root.children.length).toBe(1);
82
+ let childBox = root.children[0];
83
+ if (childBox !== undefined) {
84
+ return t.expect(childBox.name).toEqual("Child");
85
+ } else {
86
+ return t.expect(true).toBe(false);
87
+ }
88
+ });
89
+ Vitest.test("builds hierarchy with one root and multiple children", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
90
+ let parent = HierarchyBuilder.makeBox("Parent", Types.Bounds.make(0, 0, 20, 20));
91
+ let child1 = HierarchyBuilder.makeBox("Child1", Types.Bounds.make(2, 2, 8, 8));
92
+ let child2 = HierarchyBuilder.makeBox("Child2", Types.Bounds.make(12, 12, 18, 18));
93
+ let boxes = [
94
+ parent,
95
+ child1,
96
+ child2
97
+ ];
98
+ let result = HierarchyBuilder.buildHierarchy(boxes);
99
+ if (result.TAG !== "Ok") {
100
+ return t.expect(true).toBe(false);
101
+ }
102
+ let roots = result._0;
103
+ t.expect(roots.length).toBe(1);
104
+ let root = roots[0];
105
+ if (root !== undefined) {
106
+ t.expect(root.name).toEqual("Parent");
107
+ return t.expect(root.children.length).toBe(2);
108
+ } else {
109
+ return t.expect(true).toBe(false);
110
+ }
111
+ });
112
+ });
113
+
114
+ Vitest.describe("HierarchyBuilder - buildHierarchy - 3-level nesting", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
115
+ Vitest.test("builds hierarchy with 3 levels: root -> child -> grandchild", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
116
+ let root = HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 30, 30));
117
+ let child = HierarchyBuilder.makeBox("Child", Types.Bounds.make(5, 5, 25, 25));
118
+ let grandchild = HierarchyBuilder.makeBox("Grandchild", Types.Bounds.make(10, 10, 20, 20));
119
+ let boxes = [
120
+ root,
121
+ child,
122
+ grandchild
123
+ ];
124
+ let result = HierarchyBuilder.buildHierarchy(boxes);
125
+ if (result.TAG !== "Ok") {
126
+ return t.expect(true).toBe(false);
127
+ }
128
+ let roots = result._0;
129
+ t.expect(roots.length).toBe(1);
130
+ let rootBox = roots[0];
131
+ if (rootBox === undefined) {
132
+ return t.expect(true).toBe(false);
133
+ }
134
+ t.expect(rootBox.name).toEqual("Root");
135
+ t.expect(rootBox.children.length).toBe(1);
136
+ let childBox = rootBox.children[0];
137
+ if (childBox === undefined) {
138
+ return t.expect(true).toBe(false);
139
+ }
140
+ t.expect(childBox.name).toEqual("Child");
141
+ t.expect(childBox.children.length).toBe(1);
142
+ let grandchildBox = childBox.children[0];
143
+ if (grandchildBox !== undefined) {
144
+ return t.expect(grandchildBox.name).toEqual("Grandchild");
145
+ } else {
146
+ return t.expect(true).toBe(false);
147
+ }
148
+ });
149
+ Vitest.test("getDepth correctly calculates depth for 3-level hierarchy", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
150
+ let root = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 30, 30));
151
+ let child = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(5, 5, 25, 25));
152
+ let grandchild = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(10, 10, 20, 20));
153
+ let allBoxes = [
154
+ root,
155
+ child,
156
+ grandchild
157
+ ];
158
+ t.expect(HierarchyBuilder.getDepth(root, allBoxes)).toBe(0);
159
+ t.expect(HierarchyBuilder.getDepth(child, allBoxes)).toBe(1);
160
+ t.expect(HierarchyBuilder.getDepth(grandchild, allBoxes)).toBe(2);
161
+ });
162
+ });
163
+
164
+ Vitest.describe("HierarchyBuilder - buildHierarchy - 4-level nesting", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
165
+ Vitest.test("builds hierarchy with 4 levels: root -> child -> grandchild -> great-grandchild", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
166
+ let root = HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 40, 40));
167
+ let child = HierarchyBuilder.makeBox("Child", Types.Bounds.make(5, 5, 35, 35));
168
+ let grandchild = HierarchyBuilder.makeBox("Grandchild", Types.Bounds.make(10, 10, 30, 30));
169
+ let greatGrandchild = HierarchyBuilder.makeBox("GreatGrandchild", Types.Bounds.make(15, 15, 25, 25));
170
+ let boxes = [
171
+ root,
172
+ child,
173
+ grandchild,
174
+ greatGrandchild
175
+ ];
176
+ let result = HierarchyBuilder.buildHierarchy(boxes);
177
+ if (result.TAG !== "Ok") {
178
+ return t.expect(true).toBe(false);
179
+ }
180
+ let roots = result._0;
181
+ t.expect(roots.length).toBe(1);
182
+ let rootBox = roots[0];
183
+ if (rootBox === undefined) {
184
+ return t.expect(true).toBe(false);
185
+ }
186
+ t.expect(rootBox.name).toEqual("Root");
187
+ t.expect(rootBox.children.length).toBe(1);
188
+ let childBox = rootBox.children[0];
189
+ if (childBox === undefined) {
190
+ return t.expect(true).toBe(false);
191
+ }
192
+ t.expect(childBox.name).toEqual("Child");
193
+ t.expect(childBox.children.length).toBe(1);
194
+ let grandchildBox = childBox.children[0];
195
+ if (grandchildBox === undefined) {
196
+ return t.expect(true).toBe(false);
197
+ }
198
+ t.expect(grandchildBox.name).toEqual("Grandchild");
199
+ t.expect(grandchildBox.children.length).toBe(1);
200
+ let greatGrandchildBox = grandchildBox.children[0];
201
+ if (greatGrandchildBox !== undefined) {
202
+ return t.expect(greatGrandchildBox.name).toEqual("GreatGrandchild");
203
+ } else {
204
+ return t.expect(true).toBe(false);
205
+ }
206
+ });
207
+ Vitest.test("getDepth correctly calculates depth for 4-level hierarchy", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
208
+ let root = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 40, 40));
209
+ let child = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(5, 5, 35, 35));
210
+ let grandchild = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(10, 10, 30, 30));
211
+ let greatGrandchild = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(15, 15, 25, 25));
212
+ let allBoxes = [
213
+ root,
214
+ child,
215
+ grandchild,
216
+ greatGrandchild
217
+ ];
218
+ t.expect(HierarchyBuilder.getDepth(root, allBoxes)).toBe(0);
219
+ t.expect(HierarchyBuilder.getDepth(child, allBoxes)).toBe(1);
220
+ t.expect(HierarchyBuilder.getDepth(grandchild, allBoxes)).toBe(2);
221
+ t.expect(HierarchyBuilder.getDepth(greatGrandchild, allBoxes)).toBe(3);
222
+ });
223
+ });
224
+
225
+ Vitest.describe("HierarchyBuilder - buildHierarchy - Multiple roots", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => Vitest.test("handles multiple root boxes with children", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
226
+ let root1 = HierarchyBuilder.makeBox("Root1", Types.Bounds.make(0, 0, 10, 10));
227
+ let root1Child = HierarchyBuilder.makeBox("Root1Child", Types.Bounds.make(2, 2, 8, 8));
228
+ let root2 = HierarchyBuilder.makeBox("Root2", Types.Bounds.make(20, 20, 30, 30));
229
+ let root2Child = HierarchyBuilder.makeBox("Root2Child", Types.Bounds.make(22, 22, 28, 28));
230
+ let boxes = [
231
+ root1,
232
+ root1Child,
233
+ root2,
234
+ root2Child
235
+ ];
236
+ let result = HierarchyBuilder.buildHierarchy(boxes);
237
+ if (result.TAG !== "Ok") {
238
+ return t.expect(true).toBe(false);
239
+ }
240
+ let roots = result._0;
241
+ t.expect(roots.length).toBe(2);
242
+ roots.forEach(root => t.expect(root.children.length).toBe(1));
243
+ }));
244
+
245
+ Vitest.describe("HierarchyBuilder - buildHierarchy - Error cases", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
246
+ Vitest.test("detects overlapping boxes (invalid partial overlap)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
247
+ let box1 = HierarchyBuilder.makeBox("Box1", Types.Bounds.make(0, 0, 10, 10));
248
+ let box2 = HierarchyBuilder.makeBox("Box2", Types.Bounds.make(5, 5, 15, 15));
249
+ let boxes = [
250
+ box1,
251
+ box2
252
+ ];
253
+ let result = HierarchyBuilder.buildHierarchy(boxes);
254
+ if (result.TAG === "Ok") {
255
+ return t.expect(true).toBe(false);
256
+ }
257
+ let match = result._0;
258
+ if (typeof match !== "object") {
259
+ return t.expect(true).toBe(false);
260
+ }
261
+ let b2 = match.box2;
262
+ let b1 = match.box1;
263
+ t.expect(b1 === box1 || b1 === box2).toBe(true);
264
+ t.expect(b2 === box1 || b2 === box2).toBe(true);
265
+ t.expect(b1 !== b2).toBe(true);
266
+ });
267
+ Vitest.test("allows disjoint boxes (no overlap)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
268
+ let box1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 5, 5));
269
+ let box2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(10, 10, 15, 15));
270
+ let boxes = [
271
+ box1,
272
+ box2
273
+ ];
274
+ let result = HierarchyBuilder.buildHierarchy(boxes);
275
+ if (result.TAG === "Ok") {
276
+ return t.expect(result._0.length).toBe(2);
277
+ } else {
278
+ return t.expect(true).toBe(false);
279
+ }
280
+ });
281
+ Vitest.test("allows nested boxes (one contains the other)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
282
+ let outer = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 10, 10));
283
+ let inner = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(2, 2, 8, 8));
284
+ let boxes = [
285
+ outer,
286
+ inner
287
+ ];
288
+ let result = HierarchyBuilder.buildHierarchy(boxes);
289
+ if (result.TAG !== "Ok") {
290
+ return t.expect(true).toBe(false);
291
+ }
292
+ let roots = result._0;
293
+ t.expect(roots.length).toBe(1);
294
+ let root = roots[0];
295
+ if (root !== undefined) {
296
+ return t.expect(root.children.length).toBe(1);
297
+ } else {
298
+ return t.expect(true).toBe(false);
299
+ }
300
+ });
301
+ });
302
+
303
+ Vitest.describe("HierarchyBuilder - Deep Nesting Detection", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
304
+ Vitest.describe("collectDeepNestingWarnings", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
305
+ Vitest.test("should not warn for boxes at or below threshold (depth 0-4)", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
306
+ let root = HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 10, 10));
307
+ let warnings0 = HierarchyBuilder.collectDeepNestingWarnings(root, 0, 4);
308
+ t.expect(warnings0.length).toBe(0);
309
+ let warnings4 = HierarchyBuilder.collectDeepNestingWarnings(root, 4, 4);
310
+ t.expect(warnings4.length).toBe(0);
311
+ });
312
+ Vitest.test("should warn when depth exceeds threshold of 4", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
313
+ let deepBox = HierarchyBuilder.makeBox("DeepBox", Types.Bounds.make(5, 5, 8, 8));
314
+ let warnings = HierarchyBuilder.collectDeepNestingWarnings(deepBox, 5, 4);
315
+ t.expect(warnings.length).toBe(1);
316
+ let warning = warnings[0];
317
+ t.expect(warning.severity).toEqual("Warning");
318
+ let match = warning.code;
319
+ if (match.TAG !== "DeepNesting") {
320
+ return t.expect(true).toBe(false);
321
+ }
322
+ let position = match.position;
323
+ t.expect(match.depth).toBe(5);
324
+ t.expect(position.row).toBe(5);
325
+ t.expect(position.col).toBe(5);
326
+ });
327
+ Vitest.test("should collect warnings from all children recursively", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
328
+ let parent = HierarchyBuilder.makeBox("Parent", Types.Bounds.make(0, 0, 20, 20));
329
+ let child1 = HierarchyBuilder.makeBox("Child1", Types.Bounds.make(2, 2, 8, 8));
330
+ let child2 = HierarchyBuilder.makeBox("Child2", Types.Bounds.make(12, 12, 18, 18));
331
+ parent.children.push(child1);
332
+ parent.children.push(child2);
333
+ let warnings = HierarchyBuilder.collectDeepNestingWarnings(parent, 4, 4);
334
+ t.expect(warnings.length).toBe(2);
335
+ });
336
+ Vitest.test("should handle custom threshold", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
337
+ let box = HierarchyBuilder.makeBox("Box", Types.Bounds.make(0, 0, 5, 5));
338
+ let warnings = HierarchyBuilder.collectDeepNestingWarnings(box, 3, 2);
339
+ t.expect(warnings.length).toBe(1);
340
+ let warnings2 = HierarchyBuilder.collectDeepNestingWarnings(box, 3, 5);
341
+ t.expect(warnings2.length).toBe(0);
342
+ });
343
+ });
344
+ Vitest.describe("detectDeepNesting", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
345
+ Vitest.test("should detect deep nesting in complete hierarchy", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
346
+ let root = HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 50, 50));
347
+ let level1 = HierarchyBuilder.makeBox("Level1", Types.Bounds.make(2, 2, 48, 48));
348
+ let level2 = HierarchyBuilder.makeBox("Level2", Types.Bounds.make(4, 4, 46, 46));
349
+ let level3 = HierarchyBuilder.makeBox("Level3", Types.Bounds.make(6, 6, 44, 44));
350
+ let level4 = HierarchyBuilder.makeBox("Level4", Types.Bounds.make(8, 8, 42, 42));
351
+ let level5 = HierarchyBuilder.makeBox("Level5", Types.Bounds.make(10, 10, 40, 40));
352
+ root.children.push(level1);
353
+ level1.children.push(level2);
354
+ level2.children.push(level3);
355
+ level3.children.push(level4);
356
+ level4.children.push(level5);
357
+ let warnings = HierarchyBuilder.detectDeepNesting([root], 4);
358
+ t.expect(warnings.length).toBe(1);
359
+ let warning = warnings[0];
360
+ if (warning === undefined) {
361
+ return t.expect(true).toBe(false);
362
+ }
363
+ let match = warning.code;
364
+ if (match.TAG !== "DeepNesting") {
365
+ return t.expect(true).toBe(false);
366
+ }
367
+ let position = match.position;
368
+ t.expect(match.depth).toBe(5);
369
+ t.expect(position.row).toBe(10);
370
+ t.expect(position.col).toBe(10);
371
+ });
372
+ Vitest.test("should detect multiple deep boxes in different branches", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
373
+ let root = HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 100, 100));
374
+ let b1_l1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(2, 2, 48, 48));
375
+ let b1_l2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(4, 4, 46, 46));
376
+ let b1_l3 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(6, 6, 44, 44));
377
+ let b1_l4 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(8, 8, 42, 42));
378
+ let b1_l5 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(10, 10, 40, 40));
379
+ let b2_l1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(52, 52, 98, 98));
380
+ let b2_l2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(54, 54, 96, 96));
381
+ let b2_l3 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(56, 56, 94, 94));
382
+ let b2_l4 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(58, 58, 92, 92));
383
+ let b2_l5 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(60, 60, 90, 90));
384
+ let b2_l6 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(62, 62, 88, 88));
385
+ root.children.push(b1_l1);
386
+ root.children.push(b2_l1);
387
+ b1_l1.children.push(b1_l2);
388
+ b1_l2.children.push(b1_l3);
389
+ b1_l3.children.push(b1_l4);
390
+ b1_l4.children.push(b1_l5);
391
+ b2_l1.children.push(b2_l2);
392
+ b2_l2.children.push(b2_l3);
393
+ b2_l3.children.push(b2_l4);
394
+ b2_l4.children.push(b2_l5);
395
+ b2_l5.children.push(b2_l6);
396
+ let warnings = HierarchyBuilder.detectDeepNesting([root], 4);
397
+ t.expect(warnings.length).toBe(3);
398
+ });
399
+ Vitest.test("should handle multiple root boxes", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
400
+ let root1 = HierarchyBuilder.makeBox("Root1", Types.Bounds.make(0, 0, 30, 30));
401
+ let root1_child = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(2, 2, 28, 28));
402
+ let root2 = HierarchyBuilder.makeBox("Root2", Types.Bounds.make(40, 40, 90, 90));
403
+ let root2_l1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(42, 42, 88, 88));
404
+ let root2_l2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(44, 44, 86, 86));
405
+ let root2_l3 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(46, 46, 84, 84));
406
+ let root2_l4 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(48, 48, 82, 82));
407
+ let root2_l5 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(50, 50, 80, 80));
408
+ root1.children.push(root1_child);
409
+ root2.children.push(root2_l1);
410
+ root2_l1.children.push(root2_l2);
411
+ root2_l2.children.push(root2_l3);
412
+ root2_l3.children.push(root2_l4);
413
+ root2_l4.children.push(root2_l5);
414
+ let warnings = HierarchyBuilder.detectDeepNesting([
415
+ root1,
416
+ root2
417
+ ], 4);
418
+ t.expect(warnings.length).toBe(1);
419
+ });
420
+ Vitest.test("should return empty array when no deep nesting", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
421
+ let root = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 30, 30));
422
+ let child1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(2, 2, 14, 14));
423
+ let child2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(16, 16, 28, 28));
424
+ root.children.push(child1);
425
+ root.children.push(child2);
426
+ let warnings = HierarchyBuilder.detectDeepNesting([root], 4);
427
+ t.expect(warnings.length).toBe(0);
428
+ });
429
+ });
430
+ Vitest.describe("getMaxDepth", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => {
431
+ Vitest.test("should return 0 for empty array", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
432
+ let maxDepth = HierarchyBuilder.getMaxDepth([]);
433
+ t.expect(maxDepth).toBe(0);
434
+ });
435
+ Vitest.test("should return 0 for single root box with no children", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
436
+ let root = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 10, 10));
437
+ let maxDepth = HierarchyBuilder.getMaxDepth([root]);
438
+ t.expect(maxDepth).toBe(0);
439
+ });
440
+ Vitest.test("should calculate max depth for single branch", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
441
+ let root = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 30, 30));
442
+ let level1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(2, 2, 28, 28));
443
+ let level2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(4, 4, 26, 26));
444
+ root.children.push(level1);
445
+ level1.children.push(level2);
446
+ let maxDepth = HierarchyBuilder.getMaxDepth([root]);
447
+ t.expect(maxDepth).toBe(2);
448
+ });
449
+ Vitest.test("should find max depth across multiple branches", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
450
+ let root = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(0, 0, 100, 100));
451
+ let b1_l1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(2, 2, 20, 20));
452
+ let b1_l2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(4, 4, 18, 18));
453
+ let b2_l1 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(30, 30, 98, 98));
454
+ let b2_l2 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(32, 32, 96, 96));
455
+ let b2_l3 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(34, 34, 94, 94));
456
+ let b2_l4 = HierarchyBuilder.makeBox(undefined, Types.Bounds.make(36, 36, 92, 92));
457
+ root.children.push(b1_l1);
458
+ root.children.push(b2_l1);
459
+ b1_l1.children.push(b1_l2);
460
+ b2_l1.children.push(b2_l2);
461
+ b2_l2.children.push(b2_l3);
462
+ b2_l3.children.push(b2_l4);
463
+ let maxDepth = HierarchyBuilder.getMaxDepth([root]);
464
+ t.expect(maxDepth).toBe(4);
465
+ });
466
+ });
467
+ Vitest.describe("Integration with buildHierarchy", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, () => Vitest.test("should detect deep nesting after building hierarchy from flat array", undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, t => {
468
+ let boxes = [
469
+ HierarchyBuilder.makeBox("Root", Types.Bounds.make(0, 0, 50, 50)),
470
+ HierarchyBuilder.makeBox("L1", Types.Bounds.make(2, 2, 48, 48)),
471
+ HierarchyBuilder.makeBox("L2", Types.Bounds.make(4, 4, 46, 46)),
472
+ HierarchyBuilder.makeBox("L3", Types.Bounds.make(6, 6, 44, 44)),
473
+ HierarchyBuilder.makeBox("L4", Types.Bounds.make(8, 8, 42, 42)),
474
+ HierarchyBuilder.makeBox("L5", Types.Bounds.make(10, 10, 40, 40))
475
+ ];
476
+ let result = HierarchyBuilder.buildHierarchy(boxes);
477
+ if (result.TAG !== "Ok") {
478
+ return t.expect(true).toBe(false);
479
+ }
480
+ let roots = result._0;
481
+ t.expect(roots.length).toBe(1);
482
+ let warnings = HierarchyBuilder.detectDeepNesting(roots, 4);
483
+ t.expect(warnings.length).toBe(1);
484
+ let maxDepth = HierarchyBuilder.getMaxDepth(roots);
485
+ t.expect(maxDepth).toBe(5);
486
+ }));
487
+ });
488
+
489
+ /* Not a pure module */