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,191 @@
1
+ // ErrorContext.res
2
+ // Error context builder for generating code snippets with visual indicators
3
+ // Provides contextual information around error locations for better debugging
4
+
5
+ // Import core types
6
+ open Types
7
+
8
+ // ============================================================================
9
+ // Error Context Type
10
+ // ============================================================================
11
+
12
+ /**
13
+ * Contains contextual information about an error location.
14
+ * Includes a code snippet with surrounding lines and visual indicators.
15
+ */
16
+ type t = {
17
+ codeSnippet: option<string>, // Formatted code snippet with line numbers and markers
18
+ linesBefore: int, // Number of lines shown before error
19
+ linesAfter: int, // Number of lines shown after error
20
+ }
21
+
22
+ // ============================================================================
23
+ // Helper Functions
24
+ // ============================================================================
25
+
26
+ /**
27
+ * Convert a cellChar to a displayable string.
28
+ * This is used to render the grid characters in the error context.
29
+ */
30
+ let cellCharToString = (cell: cellChar): string => {
31
+ switch cell {
32
+ | Corner => "+"
33
+ | HLine => "-"
34
+ | VLine => "|"
35
+ | Divider => "="
36
+ | Space => " "
37
+ | Char(s) => s
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Build a formatted code snippet showing the error location.
43
+ *
44
+ * Features:
45
+ * - Line numbers (1-indexed, padded to 4 digits)
46
+ * - Arrow indicator (→) marking the error line
47
+ * - Column pointer (^) showing exact error position
48
+ * - Context lines before and after the error
49
+ *
50
+ * Format example:
51
+ * ```
52
+ * 1 │ +--------+
53
+ * 2 │ | Test |
54
+ * → 3 │ +-------+
55
+ * │ ^
56
+ * 4 │
57
+ * ```
58
+ *
59
+ * @param grid The grid containing the source code
60
+ * @param position The error position (row, col)
61
+ * @param radius Number of lines to show before and after
62
+ * @returns Formatted code snippet as a string
63
+ *
64
+ * REQ-18: Contextual Code Snippets
65
+ */
66
+ let buildCodeSnippet = (grid: Grid.t, position: Position.t, radius: int): string => {
67
+ // Calculate the range of lines to display
68
+ // Ensure we don't go out of bounds
69
+ let startRow = Js.Math.max_int(0, position.row - radius)
70
+ let endRow = Js.Math.min_int(grid.height - 1, position.row + radius)
71
+
72
+ // Helper function to pad string to the left
73
+ let padStart = (str: string, targetLength: int, padChar: string): string => {
74
+ let currentLength = String.length(str)
75
+ if currentLength >= targetLength {
76
+ str
77
+ } else {
78
+ let padLength = targetLength - currentLength
79
+ let padding = String.repeat(padChar, padLength)
80
+ padding ++ str
81
+ }
82
+ }
83
+
84
+ // Build the snippet line by line
85
+ let lines = []
86
+
87
+ for row in startRow to endRow {
88
+ // Format line number (1-indexed, padded to 4 spaces)
89
+ let lineNum = (row + 1)->Int.toString->padStart(4, " ")
90
+
91
+ // Add arrow indicator for error line, spaces for others
92
+ let prefix = if row == position.row { " → " } else { " " }
93
+
94
+ // Get the line content from the grid
95
+ switch Grid.getLine(grid, row) {
96
+ | Some(chars) => {
97
+ // Convert cell characters to string
98
+ let lineText = chars->Belt.Array.map(cellCharToString)->Js.Array2.joinWith("")
99
+
100
+ // Build the formatted line: " → 123 │ content"
101
+ let formattedLine = `${prefix}${lineNum} │ ${lineText}`
102
+ lines->Js.Array2.push(formattedLine)->ignore
103
+
104
+ // Add column pointer under error position
105
+ if row == position.row {
106
+ // Calculate spacing: account for prefix (4) + line number (4) + separator (2) = 10 chars
107
+ let spacingBeforePointer = 10 + position.col
108
+ let pointer = " "->Js.String2.repeat(spacingBeforePointer) ++ "^"
109
+ lines->Js.Array2.push(` │ ${pointer}`)->ignore
110
+ }
111
+ }
112
+ | None => {
113
+ // Handle missing lines gracefully (shouldn't happen in valid grid)
114
+ let formattedLine = `${prefix}${lineNum} │ `
115
+ lines->Js.Array2.push(formattedLine)->ignore
116
+ }
117
+ }
118
+ }
119
+
120
+ // Join all lines with newlines
121
+ lines->Js.Array2.joinWith("\n")
122
+ }
123
+
124
+ // ============================================================================
125
+ // Main Constructor
126
+ // ============================================================================
127
+
128
+ /**
129
+ * Create an error context from a grid and position.
130
+ * Automatically builds a code snippet with default or custom radius.
131
+ *
132
+ * @param grid The grid containing the source code
133
+ * @param position The error position
134
+ * @param radius Number of lines to show before/after (default: 2)
135
+ * @returns Error context with formatted code snippet
136
+ */
137
+ let make = (grid: Grid.t, position: Position.t, ~radius: int=2): t => {
138
+ // Calculate actual lines shown (may be less at boundaries)
139
+ let startRow = Js.Math.max_int(0, position.row - radius)
140
+ let endRow = Js.Math.min_int(grid.height - 1, position.row + radius)
141
+
142
+ let linesBefore = position.row - startRow
143
+ let linesAfter = endRow - position.row
144
+
145
+ // Build the code snippet
146
+ let snippet = buildCodeSnippet(grid, position, radius)
147
+
148
+ {
149
+ codeSnippet: Some(snippet),
150
+ linesBefore: linesBefore,
151
+ linesAfter: linesAfter,
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Create an empty error context (no snippet).
157
+ * Used when grid information is not available.
158
+ */
159
+ let empty = (): t => {
160
+ codeSnippet: None,
161
+ linesBefore: 0,
162
+ linesAfter: 0,
163
+ }
164
+
165
+ /**
166
+ * Get the code snippet from the context.
167
+ * Returns empty string if no snippet is available.
168
+ */
169
+ let getSnippet = (ctx: t): string => {
170
+ switch ctx.codeSnippet {
171
+ | Some(snippet) => snippet
172
+ | None => ""
173
+ }
174
+ }
175
+
176
+ /**
177
+ * Check if context has a code snippet.
178
+ */
179
+ let hasSnippet = (ctx: t): bool => {
180
+ switch ctx.codeSnippet {
181
+ | Some(_) => true
182
+ | None => false
183
+ }
184
+ }
185
+
186
+ /**
187
+ * Get the total number of context lines shown.
188
+ */
189
+ let totalLines = (ctx: t): int => {
190
+ ctx.linesBefore + 1 + ctx.linesAfter // +1 for the error line itself
191
+ }
@@ -0,0 +1,289 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as ErrorContext from "./ErrorContext.mjs";
4
+
5
+ function formatPosition(pos) {
6
+ return `row ` + (pos.row + 1 | 0).toString() + `, column ` + (pos.col + 1 | 0).toString();
7
+ }
8
+
9
+ function formatBoxName(name) {
10
+ if (name !== undefined) {
11
+ return `"` + name + `"`;
12
+ } else {
13
+ return "unnamed box";
14
+ }
15
+ }
16
+
17
+ function getTemplate(code) {
18
+ switch (code.TAG) {
19
+ case "InvalidInput" :
20
+ return {
21
+ title: "❌ Invalid input",
22
+ message: code.message + `
23
+
24
+ The input could not be processed due to formatting or content issues.`,
25
+ solution: `💡 Solution:
26
+ Check your input format:
27
+ • Ensure the wireframe text is properly formatted
28
+ • Use ASCII characters for box drawing
29
+ • Check for encoding issues if pasting from external sources`
30
+ };
31
+ case "InvalidStartPosition" :
32
+ return {
33
+ title: "❌ Invalid starting position",
34
+ message: `Position ` + formatPosition(code._0) + ` is not a valid corner for box tracing.
35
+
36
+ Box tracing must start from a '+' character that forms a valid corner.`,
37
+ solution: `💡 Solution:
38
+ Ensure the starting position:
39
+ • Contains a '+' character
40
+ • Is part of a complete box structure
41
+ • Has valid border characters adjacent to it`
42
+ };
43
+ case "UncloseBox" :
44
+ let direction = code.direction;
45
+ return {
46
+ title: "❌ Box is not closed",
47
+ message: `Box opened at ` + formatPosition(code.corner) + ` but never closed on the ` + direction + ` side.
48
+
49
+ The parser detected a '+' corner character that starts a box, but couldn't find the matching closing border. This usually happens when:
50
+ • The closing corner '+' is missing
51
+ • The border characters ('-' or '|') are broken or incomplete
52
+ • The box structure is malformed`,
53
+ solution: `💡 Solution:
54
+ Add the missing ` + direction + ` border to close the box:
55
+ • If ` + direction + ` is "top" or "bottom": use '+' corners and '-' characters
56
+ • If ` + direction + ` is "left" or "right": use '+' corners and '|' characters
57
+ • Ensure all four corners are present and borders are continuous`
58
+ };
59
+ case "MismatchedWidth" :
60
+ let bottomWidth = code.bottomWidth;
61
+ let topWidth = code.topWidth;
62
+ return {
63
+ title: "❌ Box width mismatch",
64
+ message: `Box starting at ` + formatPosition(code.topLeft) + ` has different widths on top and bottom borders:
65
+ • Top border: ` + topWidth.toString() + ` characters wide
66
+ • Bottom border: ` + bottomWidth.toString() + ` characters wide
67
+
68
+ All boxes must have matching top and bottom border widths to form a valid rectangle.`,
69
+ solution: `💡 Solution:
70
+ Make both borders the same width. Adjust the ` + (
71
+ topWidth > bottomWidth ? "bottom" : "top"
72
+ ) + ` border to match:
73
+ • Add ` + Math.abs(topWidth - bottomWidth | 0).toString() + ` ` + "dashes" + ` to make them equal
74
+ • Count carefully: include both corner '+' characters in the width
75
+ • Example: "+----+" is 6 characters wide (including corners)`
76
+ };
77
+ case "MisalignedPipe" :
78
+ let actualCol = code.actualCol;
79
+ let expectedCol = code.expectedCol;
80
+ return {
81
+ title: "❌ Vertical border misaligned",
82
+ message: `The '|' character at ` + formatPosition(code.position) + ` is not aligned with the box edge:
83
+ • Expected column: ` + (expectedCol + 1 | 0).toString() + `
84
+ • Actual column: ` + (actualCol + 1 | 0).toString() + `
85
+ • Off by: ` + Math.abs(expectedCol - actualCol | 0).toString() + ` ` + (
86
+ Math.abs(expectedCol - actualCol | 0) === 1 ? "space" : "spaces"
87
+ ) + `
88
+
89
+ Vertical borders must be perfectly aligned to form valid box sides.`,
90
+ solution: `💡 Solution:
91
+ Move the '|' character to column ` + (expectedCol + 1 | 0).toString() + `:
92
+ • ` + (
93
+ expectedCol > actualCol ? "Add" : "Remove"
94
+ ) + ` ` + Math.abs(expectedCol - actualCol | 0).toString() + ` space` + (
95
+ Math.abs(expectedCol - actualCol | 0) === 1 ? "" : "s"
96
+ ) + ` ` + (
97
+ expectedCol > actualCol ? "before" : "after"
98
+ ) + ` the '|' character
99
+ • Use a monospace font editor to ensure proper alignment
100
+ • Check that all '|' characters in this box are in the same column`
101
+ };
102
+ case "OverlappingBoxes" :
103
+ return {
104
+ title: "❌ Overlapping boxes detected",
105
+ message: `Two boxes overlap at ` + formatPosition(code.position) + ` but neither completely contains the other:
106
+ • Box 1: ` + formatBoxName(code.box1Name) + `
107
+ • Box 2: ` + formatBoxName(code.box2Name) + `
108
+
109
+ Boxes must either:
110
+ • Be completely nested (one fully inside the other), OR
111
+ • Be completely separate (no overlap at all)`,
112
+ solution: `💡 Solution:
113
+ Fix the overlap by either:
114
+ 1. Nesting: Make one box completely inside the other
115
+ • Ensure all four borders of the inner box are inside the outer box
116
+ 2. Separating: Move the boxes so they don't touch
117
+ • Add space between the boxes
118
+ • Or place them on different rows
119
+
120
+ Partial overlaps are not allowed in the wireframe syntax.`
121
+ };
122
+ case "InvalidElement" :
123
+ return {
124
+ title: "❌ Invalid element syntax",
125
+ message: `Unrecognized element syntax at ` + formatPosition(code.position) + `:
126
+ "` + code.content + `"
127
+
128
+ The parser couldn't match this content to any known element pattern:
129
+ • Buttons: [ Text ]
130
+ • Inputs: #fieldname
131
+ • Links: "Link Text"
132
+ • Checkboxes: [x] or [ ]
133
+ • Emphasis: * Text`,
134
+ solution: `💡 Solution:
135
+ Check the element syntax and fix any typos:
136
+ • Make sure brackets match: [ and ]
137
+ • Ensure quotes are paired: "text"
138
+ • Verify input fields start with #
139
+ • Use supported element patterns from the documentation
140
+
141
+ If this is plain text, it will be treated as a text element automatically.`
142
+ };
143
+ case "UnclosedBracket" :
144
+ return {
145
+ title: "❌ Unclosed bracket",
146
+ message: `Opening bracket '[' at ` + formatPosition(code.opening) + ` is never closed.
147
+
148
+ This bracket starts a button or checkbox but has no matching closing ']' bracket.`,
149
+ solution: `💡 Solution:
150
+ Add the closing ']' bracket to complete the element:
151
+ • For buttons: [ Button Text ]
152
+ • For checkboxes: [x] or [ ]
153
+
154
+ Make sure both brackets are on the same line.`
155
+ };
156
+ case "EmptyButton" :
157
+ return {
158
+ title: "❌ Empty button",
159
+ message: `Button at ` + formatPosition(code.position) + ` has no text content.
160
+
161
+ Buttons must have descriptive text between the brackets: [ Text ]`,
162
+ solution: `💡 Solution:
163
+ Add text between the brackets:
164
+ • Bad: [ ]
165
+ • Good: [ Submit ]
166
+ • Good: [ Click Here ]
167
+
168
+ Button text should clearly describe the action.`
169
+ };
170
+ case "InvalidInteractionDSL" :
171
+ let position = code.position;
172
+ let posInfo = position !== undefined ? ` at ` + formatPosition(position) : "";
173
+ return {
174
+ title: "❌ Invalid interaction syntax",
175
+ message: `Failed to parse interaction DSL` + posInfo + `:
176
+ ` + code.message + `
177
+
178
+ The interaction definition doesn't match the expected YAML-like syntax.`,
179
+ solution: `💡 Solution:
180
+ Check your interaction syntax:
181
+ • Scene declarations: @scene: sceneName
182
+ • Element selectors: #input: or [ button ]:
183
+ • Properties: indent with 2 spaces, use "key: value"
184
+ • Actions: @click -> goto(target)
185
+
186
+ Refer to the interaction DSL documentation for examples.`
187
+ };
188
+ case "UnusualSpacing" :
189
+ return {
190
+ title: "⚠️ Unusual spacing detected",
191
+ message: `Spacing issue at ` + formatPosition(code.position) + `:
192
+ ` + code.issue + `
193
+
194
+ While this may still parse correctly, it could cause alignment problems in some environments.`,
195
+ solution: `💡 Solution:
196
+ Normalize the spacing:
197
+ • Use spaces instead of tabs for alignment
198
+ • Use consistent spacing throughout the wireframe
199
+ • Use a monospace font to verify alignment visually
200
+
201
+ This is a warning - parsing will continue.`
202
+ };
203
+ case "DeepNesting" :
204
+ return {
205
+ title: "⚠️ Deep nesting detected",
206
+ message: `Box at ` + formatPosition(code.position) + ` is nested ` + code.depth.toString() + ` levels deep.
207
+
208
+ While technically valid, deeply nested boxes can:
209
+ • Reduce readability
210
+ • Make maintenance difficult
211
+ • Indicate overly complex UI structure`,
212
+ solution: `💡 Solution:
213
+ Consider simplifying the structure:
214
+ • Flatten the hierarchy where possible
215
+ • Split complex sections into separate scenes
216
+ • Use dividers (===) instead of nested boxes for simple grouping
217
+ • Keep nesting to 3-4 levels maximum for best readability
218
+
219
+ This is a warning - parsing will continue.`
220
+ };
221
+ }
222
+ }
223
+
224
+ function format(code) {
225
+ let template = getTemplate(code);
226
+ return template.title + `
227
+
228
+ ` + template.message + `
229
+
230
+ ` + template.solution;
231
+ }
232
+
233
+ function formatError(error) {
234
+ return format(error.code);
235
+ }
236
+
237
+ function formatWithContext(error) {
238
+ let template = getTemplate(error.code);
239
+ let parts = [];
240
+ parts.push(template.title);
241
+ parts.push("");
242
+ parts.push(template.message);
243
+ parts.push("");
244
+ let ctx = error.context;
245
+ if (ctx !== undefined) {
246
+ let snippet = ErrorContext.getSnippet(ctx);
247
+ parts.push("📍 Location:");
248
+ parts.push("");
249
+ parts.push(snippet);
250
+ parts.push("");
251
+ }
252
+ parts.push(template.solution);
253
+ return parts.join("\n");
254
+ }
255
+
256
+ function formatComplete(error) {
257
+ let match = error.context;
258
+ if (match !== undefined) {
259
+ return formatWithContext(error);
260
+ } else {
261
+ return format(error.code);
262
+ }
263
+ }
264
+
265
+ function getTitle(code) {
266
+ return getTemplate(code).title;
267
+ }
268
+
269
+ function getMessage(code) {
270
+ return getTemplate(code).message;
271
+ }
272
+
273
+ function getSolution(code) {
274
+ return getTemplate(code).solution;
275
+ }
276
+
277
+ export {
278
+ formatPosition,
279
+ formatBoxName,
280
+ getTemplate,
281
+ format,
282
+ formatError,
283
+ formatWithContext,
284
+ formatComplete,
285
+ getTitle,
286
+ getMessage,
287
+ getSolution,
288
+ }
289
+ /* ErrorContext Not a pure module */