fix(formatter): expand large structured prop defaults
Quality / quality (windows-latest) (push) Waiting to run
Quality / quality (ubuntu-latest) (push) Failing after 21s

This commit is contained in:
2026-08-24 21:25:07 +05:30
parent a1a2947910
commit 4ec5dad60a
9 changed files with 121 additions and 6 deletions
+1 -1
View File
@@ -668,7 +668,7 @@
}, },
"packages/syntax": { "packages/syntax": {
"name": "@wrnexus/syntax", "name": "@wrnexus/syntax",
"version": "0.8.16", "version": "0.8.17",
}, },
"packages/test": { "packages/test": {
"name": "@wrnexus/test", "name": "@wrnexus/test",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "wrnexus", "name": "wrnexus",
"displayName": "WRNexus Language Support", "displayName": "WRNexus Language Support",
"description": "Complete WRNexus v0.8.3 language support for typed imports, props, state, outputs, runtime functions, stores, diagnostics, formatting, navigation, and migration assistance.", "description": "Complete WRNexus v0.8.3 language support for typed imports, props, state, outputs, runtime functions, stores, diagnostics, formatting, navigation, and migration assistance.",
"version": "0.8.9", "version": "0.8.10",
"publisher": "wrnexus", "publisher": "wrnexus",
"private": true, "private": true,
"license": "SEE LICENSE IN LICENSE", "license": "SEE LICENSE IN LICENSE",
+27 -1
View File
@@ -1,6 +1,6 @@
"use strict"; "use strict";
// Generated by scripts/build-editor-compiler.mjs. Do not edit directly. // Generated by scripts/build-editor-compiler.mjs. Do not edit directly.
// WRN editor compiler source hash: 884c9faffb5517c907321484014e00562654ea0ba96e432bec319e0001934446 // WRN editor compiler source hash: edac5449f97a341e79ee7bf7e7f3676f42bbb4ec6aac4432f5ace9ff88f4f85c
// WRN editor compiler generator hash: f8c1094b47e695151205899de28cd63d574356d26ac49219c4a43db0f2391ef5 // WRN editor compiler generator hash: f8c1094b47e695151205899de28cd63d574356d26ac49219c4a43db0f2391ef5
// Generated with TypeScript: 6.0.3 // Generated with TypeScript: 6.0.3
const __nodeRequire = require; const __nodeRequire = require;
@@ -6227,6 +6227,26 @@ function expandStructuredStateDeclarations(lines, unit) {
} }
}); });
} }
function formatStructuredPropDeclaration(value, unit, depth, printWidth) {
const match = /^([A-Za-z_$][\w$]*\??\s*(?::\s*[^=]+?)?\s*=\s*)([\[{][\s\S]*)$/.exec(value);
if (!match)
return null;
try {
const parsed = JSON.parse(match[2].trim());
const compact = JSON.stringify(parsed);
const indentation = unit.repeat(depth);
if (indentation.length + match[1].length + compact.length <= printWidth)
return null;
const jsonLines = JSON.stringify(parsed, null, unit).split("\n");
return [
`${indentation}${match[1]}${jsonLines[0]}`,
...jsonLines.slice(1).map((jsonLine) => `${indentation}${jsonLine}`),
];
}
catch {
return null;
}
}
function formatWrnPass(source, options = {}) { function formatWrnPass(source, options = {}) {
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4); const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
const printWidth = options.printWidth ?? 100; const printWidth = options.printWidth ?? 100;
@@ -6282,6 +6302,12 @@ function formatWrnPass(source, options = {}) {
index += 1; index += 1;
continue; continue;
} }
const structuredProp = formatStructuredPropDeclaration(value, unit, codeDepth + htmlDepth + controlDepth, printWidth);
if (structuredProp) {
output.push(...structuredProp);
index += 1;
continue;
}
const leadingClosingBraces = countLeadingClosingBraces(value); const leadingClosingBraces = countLeadingClosingBraces(value);
const closesControlBlock = isControlBlockClose(value); const closesControlBlock = isControlBlockClose(value);
const continuesControlBlock = isControlBlockMiddle(value); const continuesControlBlock = isControlBlockMiddle(value);
+1 -1
View File
@@ -1,4 +1,4 @@
// WRN editor extension source hash: 8e634610c27521e6ccbf4e7293eb4320ecaac29944bde5236bb286ff84422203 // WRN editor extension source hash: 2f8a27685e497dffd4c27303333c9c34fb7571b0add2e6a781240f7353f1c86b
// WRN editor extension generator hash: 456d1d614e44e5fb1f19b784176c09cf2ade9b64ef73a17934c2698150b62728 // WRN editor extension generator hash: 456d1d614e44e5fb1f19b784176c09cf2ade9b64ef73a17934c2698150b62728
"use strict"; "use strict";
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
+27 -1
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env node #!/usr/bin/env node
// WRN editor language server source hash: 64ecd72706de345e7e8891089d2c3d1aa5c1c2beaa7cf9b816ba32a9c4ad6c54 // WRN editor language server source hash: 6d790d593fb074f5e55837db3f757162f0e59e77cd6f8643afd1e93e6ff4a2ef
// WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72 // WRN editor language server generator hash: f593a44aaf05495b789ce7a3086bee1eebb951b884d41c0e017bbcfe5f547e72
// @bun @bun-cjs // @bun @bun-cjs
(function(exports, require, module, __filename, __dirname) {var __create = Object.create; (function(exports, require, module, __filename, __dirname) {var __create = Object.create;
@@ -170722,6 +170722,26 @@ function expandStructuredStateDeclarations(lines, unit) {
} }
}); });
} }
function formatStructuredPropDeclaration(value, unit, depth, printWidth) {
const match = /^([A-Za-z_$][\w$]*\??\s*(?::\s*[^=]+?)?\s*=\s*)([\[{][\s\S]*)$/.exec(value);
if (!match)
return null;
try {
const parsed = JSON.parse(match[2].trim());
const compact = JSON.stringify(parsed);
const indentation = unit.repeat(depth);
if (indentation.length + match[1].length + compact.length <= printWidth)
return null;
const jsonLines = JSON.stringify(parsed, null, unit).split(`
`);
return [
`${indentation}${match[1]}${jsonLines[0]}`,
...jsonLines.slice(1).map((jsonLine) => `${indentation}${jsonLine}`)
];
} catch {
return null;
}
}
function formatWrnPass(source, options = {}) { function formatWrnPass(source, options = {}) {
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4); const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
const printWidth = options.printWidth ?? 100; const printWidth = options.printWidth ?? 100;
@@ -170778,6 +170798,12 @@ function formatWrnPass(source, options = {}) {
index += 1; index += 1;
continue; continue;
} }
const structuredProp = formatStructuredPropDeclaration(value, unit, codeDepth + htmlDepth + controlDepth, printWidth);
if (structuredProp) {
output.push(...structuredProp);
index += 1;
continue;
}
const leadingClosingBraces = countLeadingClosingBraces(value); const leadingClosingBraces = countLeadingClosingBraces(value);
const closesControlBlock = isControlBlockClose(value); const closesControlBlock = isControlBlockClose(value);
const continuesControlBlock = isControlBlockMiddle(value); const continuesControlBlock = isControlBlockMiddle(value);
+14
View File
@@ -20,6 +20,20 @@ test("preserves nested prop defaults while formatting", () => {
assert.equal(formatWrn(formatted, { insertSpaces: true, tabSize: 2 }), formatted); assert.equal(formatWrn(formatted, { insertSpaces: true, tabSize: 2 }), formatted);
}); });
test("formats large typed JSON prop defaults with the bundled formatter", () => {
const source = `component Catalog {
props {
categories: unknown[] = [{"label":"Platform & Core","apps":[{"label":"Home","href":"/home"},{"label":"SSO","href":"/sso"}]},{"label":"Sales","apps":[{"label":"CRM","href":"/crm"}]}]
}
view { <div></div> }
}`;
const formatted = formatWrn(source, { insertSpaces: true, tabSize: 2, printWidth: 70 });
assert.match(formatted, /categories: unknown\[\] = \[\n \{/);
assert.match(formatted, /"apps": \[\n \{/);
assert.equal(formatWrn(formatted, { insertSpaces: true, tabSize: 2, printWidth: 70 }), formatted);
});
test("formats native JSON state values with readable indentation", () => { test("formats native JSON state values with readable indentation", () => {
const source = `component Footer { const source = `component Footer {
state footerItems = [{"label":"Accessibility","href":"/accessibility","value":"accessibility"},{"label":"Privacy","href":"/privacy","value":"privacy"}] state footerItems = [{"label":"Accessibility","href":"/accessibility","value":"accessibility"},{"label":"Privacy","href":"/privacy","value":"privacy"}]
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@wrnexus/syntax", "name": "@wrnexus/syntax",
"version": "0.8.16", "version": "0.8.17",
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
"exports": { "exports": {
+34
View File
@@ -767,6 +767,28 @@ function expandStructuredStateDeclarations(lines, unit) {
}); });
} }
function formatStructuredPropDeclaration(value, unit, depth, printWidth) {
const match = /^([A-Za-z_$][\w$]*\??\s*(?::\s*[^=]+?)?\s*=\s*)([\[{][\s\S]*)$/.exec(
value,
);
if (!match) return null;
try {
const parsed = JSON.parse(match[2].trim());
const compact = JSON.stringify(parsed);
const indentation = unit.repeat(depth);
if (indentation.length + match[1].length + compact.length <= printWidth) return null;
const jsonLines = JSON.stringify(parsed, null, unit).split("\n");
return [
`${indentation}${match[1]}${jsonLines[0]}`,
...jsonLines.slice(1).map((jsonLine) => `${indentation}${jsonLine}`),
];
} catch {
return null;
}
}
function formatWrnPass(source: string, options: FormatWrnOptions = {}): string { function formatWrnPass(source: string, options: FormatWrnOptions = {}): string {
const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4); const unit = options.insertSpaces === false ? "\t" : " ".repeat(options.tabSize ?? 4);
@@ -844,6 +866,18 @@ function formatWrnPass(source: string, options: FormatWrnOptions = {}): string {
continue; continue;
} }
const structuredProp = formatStructuredPropDeclaration(
value,
unit,
codeDepth + htmlDepth + controlDepth,
printWidth,
);
if (structuredProp) {
output.push(...structuredProp);
index += 1;
continue;
}
const leadingClosingBraces = countLeadingClosingBraces(value); const leadingClosingBraces = countLeadingClosingBraces(value);
const closesControlBlock = isControlBlockClose(value); const closesControlBlock = isControlBlockClose(value);
+15
View File
@@ -83,3 +83,18 @@ test("preserves balanced compact sibling markup without indentation drift", () =
expect(formatted).toContain('<div class="strip"><span>Page</span><b>→</b><span>API</span></div>'); expect(formatted).toContain('<div class="strip"><span>Page</span><b>→</b><span>API</span></div>');
expect(formatWrn(formatted, { tabSize: 2, printWidth: 80 })).toBe(formatted); expect(formatWrn(formatted, { tabSize: 2, printWidth: 80 })).toBe(formatted);
}); });
test("formats large typed JSON prop defaults and remains idempotent", () => {
const source = `component Catalog {
props {
categories: unknown[] = [{"label":"Platform & Core","value":"platform","apps":[{"label":"WRNexus Home / Business Command Center","href":"/products/home","number":"01"},{"label":"SSO & Account","href":"/products/sso","number":"02"}]},{"label":"Sales & Customer","value":"sales","apps":[{"label":"CRM","href":"/products/crm","number":"11"}]}]
}
view { <div></div> }
}`;
const formatted = formatWrn(source, options);
expect(formatted).toContain(`categories: unknown[] = [\n {\n "label": "Platform & Core"`);
expect(formatted).toContain(`"apps": [\n {`);
expect(formatWrn(formatted, options)).toBe(formatted);
expect(() => parse(formatted)).not.toThrow();
});