@astryxdesign/cli 0.1.1-canary.a514b99 → 0.1.1-canary.d5f107c
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 +7 -7
- package/src/api/template.mjs +60 -10
- package/src/api/template.test.mjs +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astryxdesign/cli",
|
|
3
|
-
"version": "0.1.1-canary.
|
|
3
|
+
"version": "0.1.1-canary.d5f107c",
|
|
4
4
|
"displayName": "CLI",
|
|
5
5
|
"description": "Scaffold projects, browse templates, generate themes, and get agent-ready docs from the command line.",
|
|
6
6
|
"author": "Meta Open Source",
|
|
@@ -54,9 +54,9 @@
|
|
|
54
54
|
"jscodeshift": "^17.3.0"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@astryxdesign/core": "0.1.1-canary.
|
|
58
|
-
"@astryxdesign/lab": "0.1.1-canary.
|
|
59
|
-
"@astryxdesign/theme-neutral": "0.1.1-canary.
|
|
57
|
+
"@astryxdesign/core": "0.1.1-canary.d5f107c",
|
|
58
|
+
"@astryxdesign/lab": "0.1.1-canary.d5f107c",
|
|
59
|
+
"@astryxdesign/theme-neutral": "0.1.1-canary.d5f107c"
|
|
60
60
|
},
|
|
61
61
|
"peerDependenciesMeta": {
|
|
62
62
|
"@astryxdesign/core": {
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
}
|
|
71
71
|
},
|
|
72
72
|
"devDependencies": {
|
|
73
|
-
"@astryxdesign/core": "0.1.1-canary.
|
|
74
|
-
"@astryxdesign/lab": "0.1.1-canary.
|
|
75
|
-
"@astryxdesign/theme-neutral": "0.1.1-canary.
|
|
73
|
+
"@astryxdesign/core": "0.1.1-canary.d5f107c",
|
|
74
|
+
"@astryxdesign/lab": "0.1.1-canary.d5f107c",
|
|
75
|
+
"@astryxdesign/theme-neutral": "0.1.1-canary.d5f107c"
|
|
76
76
|
},
|
|
77
77
|
"scripts": {
|
|
78
78
|
"astryx": "node bin/astryx.mjs",
|
package/src/api/template.mjs
CHANGED
|
@@ -275,6 +275,65 @@ const STRUCTURAL = new Set([
|
|
|
275
275
|
'FormLayout', 'Center',
|
|
276
276
|
]);
|
|
277
277
|
|
|
278
|
+
const SPATIAL_PROPS = [
|
|
279
|
+
'padding', 'contentPadding', 'gap', 'rowGap', 'columnGap',
|
|
280
|
+
'columns', 'minChildWidth', 'hasDivider', 'defaultHasDividers',
|
|
281
|
+
'variant', 'density', 'role', 'height', 'width', 'maxWidth',
|
|
282
|
+
];
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Copy allowlisted layout props verbatim from a JSX opening-tag fragment.
|
|
286
|
+
* Uses quote/brace matching so object literals and spaced strings stay intact.
|
|
287
|
+
*
|
|
288
|
+
* @param {string} tagText
|
|
289
|
+
* @returns {string[]}
|
|
290
|
+
*/
|
|
291
|
+
function extractSpatialAttrs(tagText) {
|
|
292
|
+
const attrs = [];
|
|
293
|
+
for (const name of SPATIAL_PROPS) {
|
|
294
|
+
const eqMatch = tagText.match(new RegExp(`\\b${name}\\s*=\\s*`));
|
|
295
|
+
if (eqMatch) {
|
|
296
|
+
const start = eqMatch.index;
|
|
297
|
+
let i = eqMatch.index + eqMatch[0].length;
|
|
298
|
+
const rest = tagText.slice(i);
|
|
299
|
+
|
|
300
|
+
if (rest[0] === '"' || rest[0] === "'") {
|
|
301
|
+
const q = rest[0];
|
|
302
|
+
i += 1;
|
|
303
|
+
while (i < tagText.length && tagText[i] !== q) {
|
|
304
|
+
if (tagText[i] === '\\') i += 1;
|
|
305
|
+
i += 1;
|
|
306
|
+
}
|
|
307
|
+
if (i < tagText.length) i += 1;
|
|
308
|
+
} else if (rest[0] === '{') {
|
|
309
|
+
let depth = 0;
|
|
310
|
+
while (i < tagText.length) {
|
|
311
|
+
if (tagText[i] === '{') depth += 1;
|
|
312
|
+
else if (tagText[i] === '}') {
|
|
313
|
+
depth -= 1;
|
|
314
|
+
if (depth === 0) {
|
|
315
|
+
i += 1;
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
i += 1;
|
|
320
|
+
}
|
|
321
|
+
} else {
|
|
322
|
+
const bare = rest.match(/^[^\s/>]+/);
|
|
323
|
+
i += bare ? bare[0].length : 0;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
attrs.push(tagText.slice(start, i).trim());
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if (new RegExp(`\\b${name}(?=[\\s/>])`).test(tagText)) {
|
|
331
|
+
attrs.push(name);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return attrs;
|
|
335
|
+
}
|
|
336
|
+
|
|
278
337
|
function extractSkeleton(source) {
|
|
279
338
|
const lines = source.split('\n');
|
|
280
339
|
const out = [];
|
|
@@ -309,16 +368,7 @@ function extractSkeleton(source) {
|
|
|
309
368
|
if (lines[j].includes('>')) break;
|
|
310
369
|
}
|
|
311
370
|
|
|
312
|
-
const props =
|
|
313
|
-
const propRegex = /\b(padding|contentPadding|gap|rowGap|columnGap|columns|minChildWidth|hasDivider|defaultHasDividers|variant|density|role|height|width|maxWidth)\s*[=]\s*\{?\s*['"]?([^}'"\s,/>]+)/g;
|
|
314
|
-
let m;
|
|
315
|
-
while ((m = propRegex.exec(tagText)) !== null) {
|
|
316
|
-
const val = m[2];
|
|
317
|
-
if (val === 'true') props.push(m[1]);
|
|
318
|
-
else if (/^\d+$/.test(val)) props.push(`${m[1]}={${val}}`);
|
|
319
|
-
else props.push(`${m[1]}="${val}"`);
|
|
320
|
-
}
|
|
321
|
-
|
|
371
|
+
const props = extractSpatialAttrs(tagText);
|
|
322
372
|
const hasSpatialProps = props.length > 0;
|
|
323
373
|
const propStr = hasSpatialProps ? ' ' + props.join(' ') : '';
|
|
324
374
|
const isVStack = comp === 'VStack' || comp === 'HStack';
|
|
@@ -74,5 +74,7 @@ describe('template --skeleton component extraction (prefix-agnostic)', () => {
|
|
|
74
74
|
expect(result.data.skeleton.trim().length).toBeGreaterThan(0);
|
|
75
75
|
expect(result.data.skeleton).toMatch(/<[A-Z]\w+/);
|
|
76
76
|
expect(result.data.skeleton).not.toContain('<XDS');
|
|
77
|
+
|
|
78
|
+
expect(result.data.skeleton).toContain('columns={{minWidth: 200}}');
|
|
77
79
|
});
|
|
78
80
|
});
|