wyreframe 0.7.3 → 0.7.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wyreframe",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "ASCII wireframe + interaction DSL to HTML converter with scene transitions",
5
5
  "author": "wickedev",
6
6
  "repository": {
@@ -87,7 +87,24 @@ function findBottomRightCorner(grid, topLeft, topRight) {
87
87
  switch (match) {
88
88
  case "Corner" :
89
89
  lastCorner = pos;
90
- row = row + 1 | 0;
90
+ let nextRow = row + 1 | 0;
91
+ if (nextRow < grid.height) {
92
+ let nextPos = Types.Position.make(nextRow, topRight.col);
93
+ let match$1 = Grid.get(grid, nextPos);
94
+ if (match$1 === "Corner" && typeof match$1 !== "object") {
95
+ let nextLeftPos = Types.Position.make(nextRow, topLeft.col);
96
+ let match$2 = Grid.get(grid, nextLeftPos);
97
+ if (match$2 === "Corner" && typeof match$2 !== "object") {
98
+ $$continue = false;
99
+ } else {
100
+ row = row + 1 | 0;
101
+ }
102
+ } else {
103
+ row = row + 1 | 0;
104
+ }
105
+ } else {
106
+ row = row + 1 | 0;
107
+ }
91
108
  break;
92
109
  case "VLine" :
93
110
  row = row + 1 | 0;
@@ -135,6 +152,57 @@ function traceBox(grid, topLeft) {
135
152
  })
136
153
  };
137
154
  }
155
+ let nextRow = topLeft.row + 1 | 0;
156
+ let isValidTopEdge;
157
+ if (nextRow < grid.height) {
158
+ let nextLeftPos = Types.Position.make(nextRow, topLeft.col);
159
+ let nextRightPos = Types.Position.make(nextRow, topRightOpt.col);
160
+ let leftChar = Grid.get(grid, nextLeftPos);
161
+ let rightChar = Grid.get(grid, nextRightPos);
162
+ if (leftChar !== undefined && typeof leftChar !== "object") {
163
+ switch (leftChar) {
164
+ case "Corner" :
165
+ if (rightChar !== undefined && typeof rightChar !== "object") {
166
+ switch (rightChar) {
167
+ case "Corner" :
168
+ isValidTopEdge = false;
169
+ break;
170
+ default:
171
+ isValidTopEdge = true;
172
+ }
173
+ } else {
174
+ isValidTopEdge = true;
175
+ }
176
+ break;
177
+ case "VLine" :
178
+ if (rightChar !== undefined && typeof rightChar !== "object") {
179
+ switch (rightChar) {
180
+ default:
181
+ isValidTopEdge = true;
182
+ }
183
+ } else {
184
+ isValidTopEdge = true;
185
+ }
186
+ break;
187
+ default:
188
+ isValidTopEdge = true;
189
+ }
190
+ } else {
191
+ isValidTopEdge = true;
192
+ }
193
+ } else {
194
+ isValidTopEdge = false;
195
+ }
196
+ if (!isValidTopEdge) {
197
+ return {
198
+ TAG: "Error",
199
+ _0: ErrorTypes.makeSimple({
200
+ TAG: "InvalidElement",
201
+ content: "Not a valid box top-left corner (adjacent box detected)",
202
+ position: topLeft
203
+ })
204
+ };
205
+ }
138
206
  let topEdgeChars = topEdgeScan.map(param => param[1]);
139
207
  if (isDividerOnlyEdge(topEdgeChars)) {
140
208
  return {
@@ -114,6 +114,7 @@ let rowHasVLineInRange = (grid: Grid.t, row: int, leftCol: int, rightCol: int):
114
114
  * - Continues through rows with misaligned VLines (records for warnings)
115
115
  * - Stops at rows with no VLine at all in the box's column range (box boundary)
116
116
  * - Handles internal dividers (+=====+) correctly by finding the last corner
117
+ * - IMPORTANT: Stops when detecting vertically adjacent boxes (Issue #18)
117
118
  *
118
119
  * @param grid - The 2D character grid
119
120
  * @param topLeft - Position of top-left corner (for determining left boundary)
@@ -132,7 +133,40 @@ let findBottomRightCorner = (grid: Grid.t, topLeft: Position.t, topRight: Positi
132
133
  | Some(Corner) => {
133
134
  // Found a corner at the expected column - remember it
134
135
  lastCorner := Some(pos)
135
- row := row.contents + 1
136
+
137
+ // Issue #18 fix: Check if the NEXT row also has a Corner at the same column.
138
+ // If so, we've found the bottom of THIS box and the top of ANOTHER box.
139
+ // We should stop scanning here to avoid merging adjacent boxes.
140
+ let nextRow = row.contents + 1
141
+ if nextRow < grid.height {
142
+ let nextPos = Position.make(nextRow, topRight.col)
143
+ switch Grid.get(grid, nextPos) {
144
+ | Some(Corner) => {
145
+ // Next row also has a corner - this indicates adjacent boxes
146
+ // Also check if the next row starts a new box by checking left column
147
+ let nextLeftPos = Position.make(nextRow, topLeft.col)
148
+ switch Grid.get(grid, nextLeftPos) {
149
+ | Some(Corner) => {
150
+ // Both corners present in next row = new box starting
151
+ // Stop scanning - current corner is our bottom-right
152
+ continue := false
153
+ }
154
+ | _ => {
155
+ // Only right corner in next row - might be internal structure
156
+ // Continue scanning
157
+ row := row.contents + 1
158
+ }
159
+ }
160
+ }
161
+ | _ => {
162
+ // Next row doesn't have a corner - continue normally
163
+ row := row.contents + 1
164
+ }
165
+ }
166
+ } else {
167
+ // No more rows - we're done
168
+ row := row.contents + 1
169
+ }
136
170
  }
137
171
  | Some(VLine) => {
138
172
  // Found a VLine at the expected column - continue scanning
@@ -198,6 +232,41 @@ let traceBox = (grid: Grid.t, topLeft: Position.t): traceResult => {
198
232
  ),
199
233
  )
200
234
  | Some(topRight) => {
235
+ // Issue #18 fix: Validate this is a TRUE top edge, not a bottom edge
236
+ // of another box. A valid top edge should have VLine characters (|)
237
+ // in the next row at the left and right columns, NOT Corner characters (+).
238
+ // If the next row has corners at both positions, this is likely the
239
+ // bottom edge of one box immediately followed by the top edge of another.
240
+ let nextRow = topLeft.row + 1
241
+ let isValidTopEdge = if nextRow < grid.height {
242
+ let nextLeftPos = Position.make(nextRow, topLeft.col)
243
+ let nextRightPos = Position.make(nextRow, topRight.col)
244
+ let leftChar = Grid.get(grid, nextLeftPos)
245
+ let rightChar = Grid.get(grid, nextRightPos)
246
+ // Valid top edge: next row has VLine on both sides (content row)
247
+ // Invalid: next row has Corner on both sides (another box edge)
248
+ switch (leftChar, rightChar) {
249
+ | (Some(Corner), Some(Corner)) => false // This is a bottom edge, not a top
250
+ | (Some(VLine), Some(VLine)) => true // This is a valid top edge
251
+ | (Some(VLine), Some(Corner)) => true // Could be valid with internal structure
252
+ | (Some(Corner), Some(VLine)) => true // Could be valid with internal structure
253
+ | _ => true // Be permissive for other cases
254
+ }
255
+ } else {
256
+ false // No next row means this can't be a valid box top
257
+ }
258
+
259
+ if !isValidTopEdge {
260
+ // This corner is likely a bottom edge of another box, not a valid top-left
261
+ Error(
262
+ ErrorTypes.makeSimple(
263
+ ErrorTypes.InvalidElement({
264
+ content: "Not a valid box top-left corner (adjacent box detected)",
265
+ position: topLeft,
266
+ }),
267
+ ),
268
+ )
269
+ } else {
201
270
  // Step 3: Extract box name from top edge
202
271
  let topEdgeChars = Array.map(topEdgeScan, ((_, cell)) => cell)
203
272
 
@@ -427,6 +496,7 @@ let traceBox = (grid: Grid.t, topLeft: Position.t): traceResult => {
427
496
  }
428
497
  }
429
498
  } // Close else block for isDividerOnlyEdge
499
+ } // Close else block for isValidTopEdge
430
500
  }
431
501
  }
432
502
  | _ =>