wyreframe 0.2.2 → 0.4.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/dist/index.d.ts +74 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +82 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/index.test.ts +252 -0
- package/src/index.ts +142 -0
- package/src/parser/Fixer/FixTypes.mjs +2 -0
- package/src/parser/Fixer/FixTypes.res +34 -0
- package/src/parser/Fixer/Fixer.gen.tsx +24 -0
- package/src/parser/Fixer/Fixer.mjs +447 -0
- package/src/parser/Fixer/Fixer.res +567 -0
- package/src/renderer/Renderer.gen.tsx +8 -1
- package/src/renderer/Renderer.mjs +21 -11
- package/src/renderer/Renderer.res +34 -4
package/dist/index.d.ts
CHANGED
|
@@ -99,6 +99,8 @@ export interface SceneManager {
|
|
|
99
99
|
/** Get all available scene IDs */
|
|
100
100
|
getSceneIds: () => string[];
|
|
101
101
|
}
|
|
102
|
+
/** Scene change callback type */
|
|
103
|
+
export type OnSceneChangeCallback = (fromScene: string | undefined, toScene: string) => void;
|
|
102
104
|
/** Render options */
|
|
103
105
|
export interface RenderOptions {
|
|
104
106
|
/** Theme name */
|
|
@@ -109,6 +111,13 @@ export interface RenderOptions {
|
|
|
109
111
|
injectStyles?: boolean;
|
|
110
112
|
/** Additional CSS class for container */
|
|
111
113
|
containerClass?: string;
|
|
114
|
+
/**
|
|
115
|
+
* Callback fired when navigating between scenes.
|
|
116
|
+
* Useful for implementing scene history, analytics, or state synchronization.
|
|
117
|
+
* @param fromScene - The scene ID navigating from (undefined if initial navigation)
|
|
118
|
+
* @param toScene - The scene ID navigating to
|
|
119
|
+
*/
|
|
120
|
+
onSceneChange?: OnSceneChangeCallback;
|
|
112
121
|
}
|
|
113
122
|
/** Render result */
|
|
114
123
|
export interface RenderResult {
|
|
@@ -148,6 +157,27 @@ export type CreateUIErrorResult = {
|
|
|
148
157
|
errors: ParseError[];
|
|
149
158
|
};
|
|
150
159
|
export type CreateUIResult = CreateUISuccessResult | CreateUIErrorResult;
|
|
160
|
+
/** Describes a single fix that was applied */
|
|
161
|
+
export interface FixedIssue {
|
|
162
|
+
original: ParseError;
|
|
163
|
+
description: string;
|
|
164
|
+
line: number;
|
|
165
|
+
column: number;
|
|
166
|
+
}
|
|
167
|
+
/** Successful fix result */
|
|
168
|
+
export type FixSuccessResult = {
|
|
169
|
+
success: true;
|
|
170
|
+
text: string;
|
|
171
|
+
fixed: FixedIssue[];
|
|
172
|
+
remaining: ParseError[];
|
|
173
|
+
};
|
|
174
|
+
/** Failed fix result */
|
|
175
|
+
export type FixErrorResult = {
|
|
176
|
+
success: false;
|
|
177
|
+
errors: ParseError[];
|
|
178
|
+
};
|
|
179
|
+
/** Result of fix operation */
|
|
180
|
+
export type FixResult = FixSuccessResult | FixErrorResult;
|
|
151
181
|
/**
|
|
152
182
|
* Parse mixed text containing wireframe and interactions.
|
|
153
183
|
*
|
|
@@ -252,6 +282,48 @@ export declare function createUI(text: string, options?: RenderOptions): CreateU
|
|
|
252
282
|
export declare function createUIOrThrow(text: string, options?: RenderOptions): RenderResult & {
|
|
253
283
|
ast: AST;
|
|
254
284
|
};
|
|
285
|
+
/**
|
|
286
|
+
* Attempt to auto-fix errors and warnings in the wireframe text.
|
|
287
|
+
*
|
|
288
|
+
* This function analyzes the text for common issues and automatically
|
|
289
|
+
* corrects them where possible. Fixable issues include:
|
|
290
|
+
* - MisalignedPipe: Adjusts pipe positions to correct columns
|
|
291
|
+
* - MisalignedClosingBorder: Fixes closing border alignment
|
|
292
|
+
* - UnusualSpacing: Replaces tabs with spaces
|
|
293
|
+
* - UnclosedBracket: Adds missing closing brackets
|
|
294
|
+
* - MismatchedWidth: Extends shorter borders to match
|
|
295
|
+
*
|
|
296
|
+
* @param text - The wireframe markdown text
|
|
297
|
+
* @returns Fix result with fixed text and details about applied fixes
|
|
298
|
+
*
|
|
299
|
+
* @example
|
|
300
|
+
* ```typescript
|
|
301
|
+
* const result = fix(text);
|
|
302
|
+
* if (result.success) {
|
|
303
|
+
* console.log(`Fixed ${result.fixed.length} issues`);
|
|
304
|
+
* if (result.remaining.length > 0) {
|
|
305
|
+
* console.warn('Some issues require manual fix:', result.remaining);
|
|
306
|
+
* }
|
|
307
|
+
* // Use the fixed text
|
|
308
|
+
* const parsed = parse(result.text);
|
|
309
|
+
* }
|
|
310
|
+
* ```
|
|
311
|
+
*/
|
|
312
|
+
export declare function fix(text: string): FixResult;
|
|
313
|
+
/**
|
|
314
|
+
* Convenience function - fix and return just the fixed text.
|
|
315
|
+
* Returns the original text if nothing was fixed or if fixing failed.
|
|
316
|
+
*
|
|
317
|
+
* @param text - The wireframe markdown text
|
|
318
|
+
* @returns The fixed text (or original if no fixes applied)
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```typescript
|
|
322
|
+
* const fixedText = fixOnly(rawMarkdown);
|
|
323
|
+
* const result = parse(fixedText);
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
326
|
+
export declare function fixOnly(text: string): string;
|
|
255
327
|
export declare const version: string;
|
|
256
328
|
export declare const implementation: string;
|
|
257
329
|
declare const _default: {
|
|
@@ -262,6 +334,8 @@ declare const _default: {
|
|
|
262
334
|
render: typeof render;
|
|
263
335
|
createUI: typeof createUI;
|
|
264
336
|
createUIOrThrow: typeof createUIOrThrow;
|
|
337
|
+
fix: typeof fix;
|
|
338
|
+
fixOnly: typeof fixOnly;
|
|
265
339
|
version: string;
|
|
266
340
|
implementation: string;
|
|
267
341
|
};
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
import * as Parser from '../src/parser/Parser.mjs';
|
|
11
11
|
// @ts-ignore - ReScript generated module
|
|
12
12
|
import * as Renderer from '../src/renderer/Renderer.mjs';
|
|
13
|
+
// @ts-ignore - ReScript generated module
|
|
14
|
+
import * as Fixer from '../src/parser/Fixer/Fixer.mjs';
|
|
13
15
|
// ============================================================================
|
|
14
16
|
// API Functions
|
|
15
17
|
// ============================================================================
|
|
@@ -198,6 +200,84 @@ export function createUIOrThrow(text, options) {
|
|
|
198
200
|
const { root, sceneManager } = render(ast, options);
|
|
199
201
|
return { root, sceneManager, ast };
|
|
200
202
|
}
|
|
203
|
+
/**
|
|
204
|
+
* Convert ReScript error to ParseError
|
|
205
|
+
*/
|
|
206
|
+
function convertReScriptError(err) {
|
|
207
|
+
// The ReScript error has a complex structure, extract what we need
|
|
208
|
+
return {
|
|
209
|
+
message: String(err.code) || 'Unknown error',
|
|
210
|
+
line: undefined,
|
|
211
|
+
column: undefined,
|
|
212
|
+
source: undefined,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Attempt to auto-fix errors and warnings in the wireframe text.
|
|
217
|
+
*
|
|
218
|
+
* This function analyzes the text for common issues and automatically
|
|
219
|
+
* corrects them where possible. Fixable issues include:
|
|
220
|
+
* - MisalignedPipe: Adjusts pipe positions to correct columns
|
|
221
|
+
* - MisalignedClosingBorder: Fixes closing border alignment
|
|
222
|
+
* - UnusualSpacing: Replaces tabs with spaces
|
|
223
|
+
* - UnclosedBracket: Adds missing closing brackets
|
|
224
|
+
* - MismatchedWidth: Extends shorter borders to match
|
|
225
|
+
*
|
|
226
|
+
* @param text - The wireframe markdown text
|
|
227
|
+
* @returns Fix result with fixed text and details about applied fixes
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* const result = fix(text);
|
|
232
|
+
* if (result.success) {
|
|
233
|
+
* console.log(`Fixed ${result.fixed.length} issues`);
|
|
234
|
+
* if (result.remaining.length > 0) {
|
|
235
|
+
* console.warn('Some issues require manual fix:', result.remaining);
|
|
236
|
+
* }
|
|
237
|
+
* // Use the fixed text
|
|
238
|
+
* const parsed = parse(result.text);
|
|
239
|
+
* }
|
|
240
|
+
* ```
|
|
241
|
+
*/
|
|
242
|
+
export function fix(text) {
|
|
243
|
+
const result = Fixer.fix(text);
|
|
244
|
+
if (result.TAG === 'Ok') {
|
|
245
|
+
const success = result._0;
|
|
246
|
+
return {
|
|
247
|
+
success: true,
|
|
248
|
+
text: success.text,
|
|
249
|
+
fixed: success.fixed.map((f) => ({
|
|
250
|
+
original: convertReScriptError(f.original),
|
|
251
|
+
description: f.description,
|
|
252
|
+
line: f.line,
|
|
253
|
+
column: f.column,
|
|
254
|
+
})),
|
|
255
|
+
remaining: success.remaining.map(convertReScriptError),
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
return {
|
|
260
|
+
success: false,
|
|
261
|
+
errors: result._0.map(convertReScriptError),
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Convenience function - fix and return just the fixed text.
|
|
267
|
+
* Returns the original text if nothing was fixed or if fixing failed.
|
|
268
|
+
*
|
|
269
|
+
* @param text - The wireframe markdown text
|
|
270
|
+
* @returns The fixed text (or original if no fixes applied)
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* const fixedText = fixOnly(rawMarkdown);
|
|
275
|
+
* const result = parse(fixedText);
|
|
276
|
+
* ```
|
|
277
|
+
*/
|
|
278
|
+
export function fixOnly(text) {
|
|
279
|
+
return Fixer.fixOnly(text);
|
|
280
|
+
}
|
|
201
281
|
// Version info
|
|
202
282
|
export const version = Parser.version;
|
|
203
283
|
export const implementation = Parser.implementation;
|
|
@@ -210,6 +290,8 @@ export default {
|
|
|
210
290
|
render,
|
|
211
291
|
createUI,
|
|
212
292
|
createUIOrThrow,
|
|
293
|
+
fix,
|
|
294
|
+
fixOnly,
|
|
213
295
|
version,
|
|
214
296
|
implementation,
|
|
215
297
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,0EAA0E;AAC1E,yFAAyF;AACzF,yCAAyC;AACzC,OAAO,KAAK,MAAM,MAAM,0BAA0B,CAAC;AACnD,yCAAyC;AACzC,OAAO,KAAK,QAAQ,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for TypeScript API wrapper input validation
|
|
3
|
+
*
|
|
4
|
+
* These tests verify that render() provides helpful error messages
|
|
5
|
+
* when called with incorrect arguments (Issue #1).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { describe, test, expect, vi } from 'vitest';
|
|
9
|
+
import { parse, render, createUI } from './index';
|
|
10
|
+
import type { AST, ParseResult, OnSceneChangeCallback } from './index';
|
|
11
|
+
|
|
12
|
+
describe('render() input validation (Issue #1)', () => {
|
|
13
|
+
const validWireframe = `
|
|
14
|
+
@scene: test
|
|
15
|
+
|
|
16
|
+
+-------+
|
|
17
|
+
| Hello |
|
|
18
|
+
+-------+
|
|
19
|
+
`;
|
|
20
|
+
|
|
21
|
+
test('throws descriptive error when passed successful ParseResult instead of AST', () => {
|
|
22
|
+
const result = parse(validWireframe);
|
|
23
|
+
|
|
24
|
+
// Verify we have a successful parse result
|
|
25
|
+
expect(result.success).toBe(true);
|
|
26
|
+
|
|
27
|
+
// This is the common mistake: passing result instead of result.ast
|
|
28
|
+
expect(() => {
|
|
29
|
+
render(result as unknown as AST);
|
|
30
|
+
}).toThrow('render() expects an AST object, but received a ParseResult');
|
|
31
|
+
|
|
32
|
+
expect(() => {
|
|
33
|
+
render(result as unknown as AST);
|
|
34
|
+
}).toThrow('Did you forget to extract .ast?');
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test('throws descriptive error when passed failed ParseResult', () => {
|
|
38
|
+
// Invalid wireframe that will fail to parse
|
|
39
|
+
const invalidWireframe = '+--incomplete';
|
|
40
|
+
const result = parse(invalidWireframe);
|
|
41
|
+
|
|
42
|
+
// This should be a failed parse
|
|
43
|
+
expect(result.success).toBe(false);
|
|
44
|
+
|
|
45
|
+
expect(() => {
|
|
46
|
+
render(result as unknown as AST);
|
|
47
|
+
}).toThrow('render() received a failed ParseResult');
|
|
48
|
+
|
|
49
|
+
expect(() => {
|
|
50
|
+
render(result as unknown as AST);
|
|
51
|
+
}).toThrow('Check parse errors before calling render');
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test('throws descriptive error when passed null or undefined', () => {
|
|
55
|
+
expect(() => {
|
|
56
|
+
render(null as unknown as AST);
|
|
57
|
+
}).toThrow('render() expects an AST object with a scenes array');
|
|
58
|
+
|
|
59
|
+
expect(() => {
|
|
60
|
+
render(undefined as unknown as AST);
|
|
61
|
+
}).toThrow('render() expects an AST object with a scenes array');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('throws descriptive error when passed object without scenes array', () => {
|
|
65
|
+
const invalidAST = { foo: 'bar' };
|
|
66
|
+
|
|
67
|
+
expect(() => {
|
|
68
|
+
render(invalidAST as unknown as AST);
|
|
69
|
+
}).toThrow('render() expects an AST object with a scenes array');
|
|
70
|
+
|
|
71
|
+
expect(() => {
|
|
72
|
+
render(invalidAST as unknown as AST);
|
|
73
|
+
}).toThrow('Did you pass ParseResult instead of ParseResult.ast?');
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Note: DOM-dependent tests are skipped in Node.js environment
|
|
77
|
+
// The renderer requires a browser or jsdom environment
|
|
78
|
+
test.skip('works correctly when passed valid AST (requires DOM)', () => {
|
|
79
|
+
const result = parse(validWireframe);
|
|
80
|
+
|
|
81
|
+
expect(result.success).toBe(true);
|
|
82
|
+
if (result.success) {
|
|
83
|
+
// This is the correct usage
|
|
84
|
+
const { root, sceneManager } = render(result.ast);
|
|
85
|
+
|
|
86
|
+
expect(root).toBeDefined();
|
|
87
|
+
expect(root).toBeInstanceOf(HTMLElement);
|
|
88
|
+
expect(sceneManager).toBeDefined();
|
|
89
|
+
expect(sceneManager.getSceneIds()).toContain('test');
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
describe('createUI() convenience function', () => {
|
|
95
|
+
test('handles parse errors gracefully', () => {
|
|
96
|
+
const invalidWireframe = '+--incomplete';
|
|
97
|
+
const result = createUI(invalidWireframe);
|
|
98
|
+
|
|
99
|
+
expect(result.success).toBe(false);
|
|
100
|
+
if (!result.success) {
|
|
101
|
+
expect(result.errors).toBeDefined();
|
|
102
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Note: DOM-dependent tests are skipped in Node.js environment
|
|
107
|
+
test.skip('works correctly with valid wireframe (requires DOM)', () => {
|
|
108
|
+
const validWireframe = `
|
|
109
|
+
@scene: test
|
|
110
|
+
|
|
111
|
+
+-------+
|
|
112
|
+
| Hello |
|
|
113
|
+
+-------+
|
|
114
|
+
`;
|
|
115
|
+
const result = createUI(validWireframe);
|
|
116
|
+
|
|
117
|
+
expect(result.success).toBe(true);
|
|
118
|
+
if (result.success) {
|
|
119
|
+
expect(result.root).toBeDefined();
|
|
120
|
+
expect(result.sceneManager).toBeDefined();
|
|
121
|
+
expect(result.ast).toBeDefined();
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('onSceneChange callback (Issue #2)', () => {
|
|
127
|
+
const multiSceneWireframe = `
|
|
128
|
+
@scene: login
|
|
129
|
+
|
|
130
|
+
+---------------+
|
|
131
|
+
| Login Screen |
|
|
132
|
+
+---------------+
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
@scene: dashboard
|
|
137
|
+
|
|
138
|
+
+---------------+
|
|
139
|
+
| Dashboard |
|
|
140
|
+
+---------------+
|
|
141
|
+
`;
|
|
142
|
+
|
|
143
|
+
test('OnSceneChangeCallback type is exported', () => {
|
|
144
|
+
// Verify the type is exported by using it
|
|
145
|
+
const callback: OnSceneChangeCallback = (_from, _to) => {};
|
|
146
|
+
expect(typeof callback).toBe('function');
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Note: DOM-dependent tests are skipped in Node.js environment
|
|
150
|
+
test.skip('render accepts onSceneChange option without throwing (requires DOM)', () => {
|
|
151
|
+
const result = parse(multiSceneWireframe);
|
|
152
|
+
expect(result.success).toBe(true);
|
|
153
|
+
|
|
154
|
+
if (result.success) {
|
|
155
|
+
const callback = vi.fn();
|
|
156
|
+
|
|
157
|
+
// This should not throw - just verify the API accepts the option
|
|
158
|
+
expect(() => {
|
|
159
|
+
render(result.ast, {
|
|
160
|
+
onSceneChange: callback,
|
|
161
|
+
});
|
|
162
|
+
}).not.toThrow();
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test.skip('createUI accepts onSceneChange option without throwing (requires DOM)', () => {
|
|
167
|
+
const callback = vi.fn();
|
|
168
|
+
|
|
169
|
+
// Verify the API accepts the option
|
|
170
|
+
expect(() => {
|
|
171
|
+
createUI(multiSceneWireframe, {
|
|
172
|
+
onSceneChange: callback,
|
|
173
|
+
});
|
|
174
|
+
}).not.toThrow();
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Note: DOM-dependent tests are skipped in Node.js environment
|
|
178
|
+
test.skip('onSceneChange is called on initial scene load (requires DOM)', () => {
|
|
179
|
+
const result = parse(multiSceneWireframe);
|
|
180
|
+
expect(result.success).toBe(true);
|
|
181
|
+
|
|
182
|
+
if (result.success) {
|
|
183
|
+
const callback = vi.fn();
|
|
184
|
+
render(result.ast, { onSceneChange: callback });
|
|
185
|
+
|
|
186
|
+
// Should be called once for initial scene
|
|
187
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
188
|
+
expect(callback).toHaveBeenCalledWith(undefined, 'login');
|
|
189
|
+
}
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test.skip('onSceneChange is called when navigating between scenes (requires DOM)', () => {
|
|
193
|
+
const result = parse(multiSceneWireframe);
|
|
194
|
+
expect(result.success).toBe(true);
|
|
195
|
+
|
|
196
|
+
if (result.success) {
|
|
197
|
+
const callback = vi.fn();
|
|
198
|
+
const { sceneManager } = render(result.ast, { onSceneChange: callback });
|
|
199
|
+
|
|
200
|
+
// Clear mock after initial call
|
|
201
|
+
callback.mockClear();
|
|
202
|
+
|
|
203
|
+
// Navigate to dashboard
|
|
204
|
+
sceneManager.goto('dashboard');
|
|
205
|
+
|
|
206
|
+
expect(callback).toHaveBeenCalledTimes(1);
|
|
207
|
+
expect(callback).toHaveBeenCalledWith('login', 'dashboard');
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test.skip('onSceneChange is not called when navigating to the same scene (requires DOM)', () => {
|
|
212
|
+
const result = parse(multiSceneWireframe);
|
|
213
|
+
expect(result.success).toBe(true);
|
|
214
|
+
|
|
215
|
+
if (result.success) {
|
|
216
|
+
const callback = vi.fn();
|
|
217
|
+
const { sceneManager } = render(result.ast, { onSceneChange: callback });
|
|
218
|
+
|
|
219
|
+
// Clear mock after initial call
|
|
220
|
+
callback.mockClear();
|
|
221
|
+
|
|
222
|
+
// Navigate to the same scene
|
|
223
|
+
sceneManager.goto('login');
|
|
224
|
+
|
|
225
|
+
expect(callback).not.toHaveBeenCalled();
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test.skip('onSceneChange receives correct fromScene and toScene values (requires DOM)', () => {
|
|
230
|
+
const result = parse(multiSceneWireframe);
|
|
231
|
+
expect(result.success).toBe(true);
|
|
232
|
+
|
|
233
|
+
if (result.success) {
|
|
234
|
+
const navigationHistory: Array<{ from: string | undefined; to: string }> = [];
|
|
235
|
+
const callback: OnSceneChangeCallback = (from, to) => {
|
|
236
|
+
navigationHistory.push({ from, to });
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
const { sceneManager } = render(result.ast, { onSceneChange: callback });
|
|
240
|
+
|
|
241
|
+
// Navigate through scenes
|
|
242
|
+
sceneManager.goto('dashboard');
|
|
243
|
+
sceneManager.goto('login');
|
|
244
|
+
|
|
245
|
+
expect(navigationHistory).toEqual([
|
|
246
|
+
{ from: undefined, to: 'login' }, // Initial
|
|
247
|
+
{ from: 'login', to: 'dashboard' },
|
|
248
|
+
{ from: 'dashboard', to: 'login' },
|
|
249
|
+
]);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
});
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
import * as Parser from '../src/parser/Parser.mjs';
|
|
12
12
|
// @ts-ignore - ReScript generated module
|
|
13
13
|
import * as Renderer from '../src/renderer/Renderer.mjs';
|
|
14
|
+
// @ts-ignore - ReScript generated module
|
|
15
|
+
import * as Fixer from '../src/parser/Fixer/Fixer.mjs';
|
|
14
16
|
|
|
15
17
|
// ============================================================================
|
|
16
18
|
// Type Definitions
|
|
@@ -146,6 +148,9 @@ export interface SceneManager {
|
|
|
146
148
|
getSceneIds: () => string[];
|
|
147
149
|
}
|
|
148
150
|
|
|
151
|
+
/** Scene change callback type */
|
|
152
|
+
export type OnSceneChangeCallback = (fromScene: string | undefined, toScene: string) => void;
|
|
153
|
+
|
|
149
154
|
/** Render options */
|
|
150
155
|
export interface RenderOptions {
|
|
151
156
|
/** Theme name */
|
|
@@ -156,6 +161,13 @@ export interface RenderOptions {
|
|
|
156
161
|
injectStyles?: boolean;
|
|
157
162
|
/** Additional CSS class for container */
|
|
158
163
|
containerClass?: string;
|
|
164
|
+
/**
|
|
165
|
+
* Callback fired when navigating between scenes.
|
|
166
|
+
* Useful for implementing scene history, analytics, or state synchronization.
|
|
167
|
+
* @param fromScene - The scene ID navigating from (undefined if initial navigation)
|
|
168
|
+
* @param toScene - The scene ID navigating to
|
|
169
|
+
*/
|
|
170
|
+
onSceneChange?: OnSceneChangeCallback;
|
|
159
171
|
}
|
|
160
172
|
|
|
161
173
|
/** Render result */
|
|
@@ -210,6 +222,35 @@ export type CreateUIErrorResult = {
|
|
|
210
222
|
|
|
211
223
|
export type CreateUIResult = CreateUISuccessResult | CreateUIErrorResult;
|
|
212
224
|
|
|
225
|
+
// ============================================================================
|
|
226
|
+
// Fix Result Types
|
|
227
|
+
// ============================================================================
|
|
228
|
+
|
|
229
|
+
/** Describes a single fix that was applied */
|
|
230
|
+
export interface FixedIssue {
|
|
231
|
+
original: ParseError;
|
|
232
|
+
description: string;
|
|
233
|
+
line: number;
|
|
234
|
+
column: number;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** Successful fix result */
|
|
238
|
+
export type FixSuccessResult = {
|
|
239
|
+
success: true;
|
|
240
|
+
text: string;
|
|
241
|
+
fixed: FixedIssue[];
|
|
242
|
+
remaining: ParseError[];
|
|
243
|
+
};
|
|
244
|
+
|
|
245
|
+
/** Failed fix result */
|
|
246
|
+
export type FixErrorResult = {
|
|
247
|
+
success: false;
|
|
248
|
+
errors: ParseError[];
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/** Result of fix operation */
|
|
252
|
+
export type FixResult = FixSuccessResult | FixErrorResult;
|
|
253
|
+
|
|
213
254
|
// ============================================================================
|
|
214
255
|
// Internal ReScript Result Type
|
|
215
256
|
// ============================================================================
|
|
@@ -437,6 +478,105 @@ export function createUIOrThrow(
|
|
|
437
478
|
return { root, sceneManager, ast };
|
|
438
479
|
}
|
|
439
480
|
|
|
481
|
+
// ============================================================================
|
|
482
|
+
// Fix API Functions
|
|
483
|
+
// ============================================================================
|
|
484
|
+
|
|
485
|
+
/**
|
|
486
|
+
* Internal ReScript Fix Result type
|
|
487
|
+
*/
|
|
488
|
+
interface ReScriptFixSuccess {
|
|
489
|
+
text: string;
|
|
490
|
+
fixed: Array<{
|
|
491
|
+
original: { code: unknown; severity: unknown; context: unknown };
|
|
492
|
+
description: string;
|
|
493
|
+
line: number;
|
|
494
|
+
column: number;
|
|
495
|
+
}>;
|
|
496
|
+
remaining: Array<{ code: unknown; severity: unknown; context: unknown }>;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Convert ReScript error to ParseError
|
|
501
|
+
*/
|
|
502
|
+
function convertReScriptError(err: { code: unknown; severity: unknown; context: unknown }): ParseError {
|
|
503
|
+
// The ReScript error has a complex structure, extract what we need
|
|
504
|
+
return {
|
|
505
|
+
message: String(err.code) || 'Unknown error',
|
|
506
|
+
line: undefined,
|
|
507
|
+
column: undefined,
|
|
508
|
+
source: undefined,
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Attempt to auto-fix errors and warnings in the wireframe text.
|
|
514
|
+
*
|
|
515
|
+
* This function analyzes the text for common issues and automatically
|
|
516
|
+
* corrects them where possible. Fixable issues include:
|
|
517
|
+
* - MisalignedPipe: Adjusts pipe positions to correct columns
|
|
518
|
+
* - MisalignedClosingBorder: Fixes closing border alignment
|
|
519
|
+
* - UnusualSpacing: Replaces tabs with spaces
|
|
520
|
+
* - UnclosedBracket: Adds missing closing brackets
|
|
521
|
+
* - MismatchedWidth: Extends shorter borders to match
|
|
522
|
+
*
|
|
523
|
+
* @param text - The wireframe markdown text
|
|
524
|
+
* @returns Fix result with fixed text and details about applied fixes
|
|
525
|
+
*
|
|
526
|
+
* @example
|
|
527
|
+
* ```typescript
|
|
528
|
+
* const result = fix(text);
|
|
529
|
+
* if (result.success) {
|
|
530
|
+
* console.log(`Fixed ${result.fixed.length} issues`);
|
|
531
|
+
* if (result.remaining.length > 0) {
|
|
532
|
+
* console.warn('Some issues require manual fix:', result.remaining);
|
|
533
|
+
* }
|
|
534
|
+
* // Use the fixed text
|
|
535
|
+
* const parsed = parse(result.text);
|
|
536
|
+
* }
|
|
537
|
+
* ```
|
|
538
|
+
*/
|
|
539
|
+
export function fix(text: string): FixResult {
|
|
540
|
+
const result = Fixer.fix(text) as ReScriptResult<ReScriptFixSuccess, Array<{ code: unknown; severity: unknown; context: unknown }>>;
|
|
541
|
+
|
|
542
|
+
if (result.TAG === 'Ok') {
|
|
543
|
+
const success = result._0;
|
|
544
|
+
return {
|
|
545
|
+
success: true,
|
|
546
|
+
text: success.text,
|
|
547
|
+
fixed: success.fixed.map((f) => ({
|
|
548
|
+
original: convertReScriptError(f.original),
|
|
549
|
+
description: f.description,
|
|
550
|
+
line: f.line,
|
|
551
|
+
column: f.column,
|
|
552
|
+
})),
|
|
553
|
+
remaining: success.remaining.map(convertReScriptError),
|
|
554
|
+
};
|
|
555
|
+
} else {
|
|
556
|
+
return {
|
|
557
|
+
success: false,
|
|
558
|
+
errors: result._0.map(convertReScriptError),
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Convenience function - fix and return just the fixed text.
|
|
565
|
+
* Returns the original text if nothing was fixed or if fixing failed.
|
|
566
|
+
*
|
|
567
|
+
* @param text - The wireframe markdown text
|
|
568
|
+
* @returns The fixed text (or original if no fixes applied)
|
|
569
|
+
*
|
|
570
|
+
* @example
|
|
571
|
+
* ```typescript
|
|
572
|
+
* const fixedText = fixOnly(rawMarkdown);
|
|
573
|
+
* const result = parse(fixedText);
|
|
574
|
+
* ```
|
|
575
|
+
*/
|
|
576
|
+
export function fixOnly(text: string): string {
|
|
577
|
+
return Fixer.fixOnly(text) as string;
|
|
578
|
+
}
|
|
579
|
+
|
|
440
580
|
// Version info
|
|
441
581
|
export const version: string = Parser.version;
|
|
442
582
|
export const implementation: string = Parser.implementation;
|
|
@@ -450,6 +590,8 @@ export default {
|
|
|
450
590
|
render,
|
|
451
591
|
createUI,
|
|
452
592
|
createUIOrThrow,
|
|
593
|
+
fix,
|
|
594
|
+
fixOnly,
|
|
453
595
|
version,
|
|
454
596
|
implementation,
|
|
455
597
|
};
|