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.
- package/README.md +123 -0
- package/dist/index.d.ts +267 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +195 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
- package/src/parser/Core/Bounds.mjs +61 -0
- package/src/parser/Core/Bounds.res +65 -0
- package/src/parser/Core/Grid.mjs +268 -0
- package/src/parser/Core/Grid.res +265 -0
- package/src/parser/Core/Position.mjs +83 -0
- package/src/parser/Core/Position.res +54 -0
- package/src/parser/Core/Types.mjs +435 -0
- package/src/parser/Core/Types.res +331 -0
- package/src/parser/Core/__tests__/Bounds_test.mjs +326 -0
- package/src/parser/Core/__tests__/Bounds_test.res +412 -0
- package/src/parser/Core/__tests__/Grid_test.mjs +322 -0
- package/src/parser/Core/__tests__/Grid_test.res +319 -0
- package/src/parser/Core/__tests__/Types_test.mjs +614 -0
- package/src/parser/Core/__tests__/Types_test.res +650 -0
- package/src/parser/Detector/BoxTracer.mjs +302 -0
- package/src/parser/Detector/BoxTracer.res +374 -0
- package/src/parser/Detector/HierarchyBuilder.mjs +158 -0
- package/src/parser/Detector/HierarchyBuilder.res +315 -0
- package/src/parser/Detector/ShapeDetector.mjs +134 -0
- package/src/parser/Detector/ShapeDetector.res +236 -0
- package/src/parser/Detector/__tests__/BoxTracer_test.mjs +70 -0
- package/src/parser/Detector/__tests__/BoxTracer_test.res +92 -0
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.mjs +489 -0
- package/src/parser/Detector/__tests__/HierarchyBuilder_test.res +849 -0
- package/src/parser/Detector/__tests__/ShapeDetector_test.mjs +377 -0
- package/src/parser/Detector/__tests__/ShapeDetector_test.res +563 -0
- package/src/parser/Errors/ErrorContext.mjs +106 -0
- package/src/parser/Errors/ErrorContext.res +191 -0
- package/src/parser/Errors/ErrorMessages.mjs +289 -0
- package/src/parser/Errors/ErrorMessages.res +303 -0
- package/src/parser/Errors/ErrorTypes.mjs +105 -0
- package/src/parser/Errors/ErrorTypes.res +169 -0
- package/src/parser/Interactions/InteractionMerger.mjs +266 -0
- package/src/parser/Interactions/InteractionMerger.res +450 -0
- package/src/parser/Interactions/InteractionParser.mjs +88 -0
- package/src/parser/Interactions/InteractionParser.res +127 -0
- package/src/parser/Interactions/SimpleInteractionParser.mjs +278 -0
- package/src/parser/Interactions/SimpleInteractionParser.res +262 -0
- package/src/parser/Interactions/__tests__/InteractionMerger_test.mjs +576 -0
- package/src/parser/Interactions/__tests__/InteractionMerger_test.res +646 -0
- package/src/parser/Parser.gen.tsx +96 -0
- package/src/parser/Parser.mjs +212 -0
- package/src/parser/Parser.res +481 -0
- package/src/parser/Scanner/__tests__/Grid_manual.mjs +214 -0
- package/src/parser/Scanner/__tests__/Grid_manual.res +141 -0
- package/src/parser/Semantic/ASTBuilder.mjs +197 -0
- package/src/parser/Semantic/ASTBuilder.res +288 -0
- package/src/parser/Semantic/AlignmentCalc.mjs +41 -0
- package/src/parser/Semantic/AlignmentCalc.res +104 -0
- package/src/parser/Semantic/Elements/ButtonParser.mjs +58 -0
- package/src/parser/Semantic/Elements/ButtonParser.res +131 -0
- package/src/parser/Semantic/Elements/CheckboxParser.mjs +58 -0
- package/src/parser/Semantic/Elements/CheckboxParser.res +79 -0
- package/src/parser/Semantic/Elements/CodeTextParser.mjs +50 -0
- package/src/parser/Semantic/Elements/CodeTextParser.res +111 -0
- package/src/parser/Semantic/Elements/ElementParser.mjs +15 -0
- package/src/parser/Semantic/Elements/ElementParser.res +83 -0
- package/src/parser/Semantic/Elements/EmphasisParser.mjs +46 -0
- package/src/parser/Semantic/Elements/EmphasisParser.res +67 -0
- package/src/parser/Semantic/Elements/InputParser.mjs +41 -0
- package/src/parser/Semantic/Elements/InputParser.res +97 -0
- package/src/parser/Semantic/Elements/LinkParser.mjs +60 -0
- package/src/parser/Semantic/Elements/LinkParser.res +156 -0
- package/src/parser/Semantic/Elements/TextParser.mjs +19 -0
- package/src/parser/Semantic/Elements/TextParser.res +42 -0
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.mjs +189 -0
- package/src/parser/Semantic/Elements/__tests__/ButtonParser_test.res +257 -0
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.mjs +202 -0
- package/src/parser/Semantic/Elements/__tests__/CheckboxParser_test.res +250 -0
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.mjs +293 -0
- package/src/parser/Semantic/Elements/__tests__/CodeTextParser_manual.res +134 -0
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.mjs +253 -0
- package/src/parser/Semantic/Elements/__tests__/InputParser_test.res +304 -0
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.mjs +289 -0
- package/src/parser/Semantic/Elements/__tests__/LinkParser_test.res +402 -0
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.mjs +149 -0
- package/src/parser/Semantic/Elements/__tests__/TextParser_test.res +167 -0
- package/src/parser/Semantic/ParserRegistry.mjs +82 -0
- package/src/parser/Semantic/ParserRegistry.res +145 -0
- package/src/parser/Semantic/SemanticParser.mjs +850 -0
- package/src/parser/Semantic/SemanticParser.res +1368 -0
- package/src/parser/Semantic/__tests__/ASTBuilder_test.mjs +187 -0
- package/src/parser/Semantic/__tests__/ASTBuilder_test.res +192 -0
- package/src/parser/Semantic/__tests__/ParserRegistry_test.mjs +154 -0
- package/src/parser/Semantic/__tests__/ParserRegistry_test.res +191 -0
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.mjs +768 -0
- package/src/parser/Semantic/__tests__/SemanticParser_integration_test.res +1069 -0
- package/src/parser/Semantic/__tests__/SemanticParser_manual.mjs +1329 -0
- package/src/parser/Semantic/__tests__/SemanticParser_manual.res +544 -0
- package/src/parser/TestMain.mjs +21 -0
- package/src/parser/TestMain.res +14 -0
- package/src/parser/TextExtractor.mjs +179 -0
- package/src/parser/TextExtractor.res +264 -0
- package/src/parser/__tests__/GridScanner_integration.test.mjs +632 -0
- package/src/parser/__tests__/GridScanner_integration.test.res +816 -0
- package/src/parser/__tests__/Performance.test.mjs +244 -0
- package/src/parser/__tests__/Performance.test.res +371 -0
- package/src/parser/__tests__/PerformanceFixtures.mjs +200 -0
- package/src/parser/__tests__/PerformanceFixtures.res +284 -0
- package/src/parser/__tests__/WyreframeParser_integration.test.mjs +770 -0
- package/src/parser/__tests__/WyreframeParser_integration.test.res +1008 -0
- package/src/parser/__tests__/fixtures/alignment-test.txt +9 -0
- package/src/parser/__tests__/fixtures/all-elements.txt +16 -0
- package/src/parser/__tests__/fixtures/login-scene.txt +17 -0
- package/src/parser/__tests__/fixtures/multi-scene.txt +25 -0
- package/src/parser/__tests__/fixtures/nested-boxes.txt +15 -0
- package/src/parser/__tests__/fixtures/simple-box.txt +5 -0
- package/src/parser/__tests__/fixtures/with-dividers.txt +14 -0
- package/src/renderer/Renderer.gen.tsx +32 -0
- package/src/renderer/Renderer.mjs +391 -0
- 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 */
|