bestax-migrate 2.8.0 → 2.9.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/sources/bulma-classes/class-map.d.ts +9 -1
- package/dist/sources/bulma-classes/class-map.d.ts.map +1 -1
- package/dist/sources/bulma-classes/class-map.js +29 -8
- package/dist/sources/bulma-classes/plan.d.ts +14 -0
- package/dist/sources/bulma-classes/plan.d.ts.map +1 -1
- package/dist/sources/bulma-classes/plan.js +57 -0
- package/dist/sources/bulma-classes/transform.d.ts.map +1 -1
- package/dist/sources/bulma-classes/transform.js +68 -18
- package/package.json +1 -1
|
@@ -35,8 +35,11 @@ export interface Modifier {
|
|
|
35
35
|
* - `todo`: bestax has a component, but the markup does not map element by
|
|
36
36
|
* element yet; the family's outermost class gets a TODO.
|
|
37
37
|
* - `plain`: valid Bulma with nothing to convert to; left alone, no TODO.
|
|
38
|
+
* - `fold`: a wrapper the `target` renders itself from a prop, so the element
|
|
39
|
+
* folds into the one `target` inside it (`.table-container` into
|
|
40
|
+
* `Table isResponsive`).
|
|
38
41
|
*/
|
|
39
|
-
export type RootStatus = 'mapped' | 'todo' | 'plain';
|
|
42
|
+
export type RootStatus = 'mapped' | 'todo' | 'plain' | 'fold';
|
|
40
43
|
export interface RootEntry {
|
|
41
44
|
readonly status: RootStatus;
|
|
42
45
|
/**
|
|
@@ -89,6 +92,11 @@ export interface RootEntry {
|
|
|
89
92
|
* takes a generated `id` when the element has none of its own.
|
|
90
93
|
*/
|
|
91
94
|
readonly adoptsIdFrom?: readonly string[];
|
|
95
|
+
/**
|
|
96
|
+
* For a `fold` root: the props that render it on the target inside. Its
|
|
97
|
+
* modifiers add their props beside these.
|
|
98
|
+
*/
|
|
99
|
+
readonly folds?: readonly PropWrite[];
|
|
92
100
|
/** The target takes no helper props, so every helper class stays a class. */
|
|
93
101
|
readonly noHelpers?: boolean;
|
|
94
102
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,MAAM,GAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED
|
|
1
|
+
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -185,10 +185,13 @@ const flag = (prop) => ({ writes: [{ prop }] });
|
|
|
185
185
|
const set = (prop, value) => ({
|
|
186
186
|
writes: [{ prop, value }],
|
|
187
187
|
});
|
|
188
|
-
/**
|
|
189
|
-
|
|
188
|
+
/**
|
|
189
|
+
* `prefix + n + suffix` → `prop={n}` for `n` from 1 to `max`, for a prop
|
|
190
|
+
* typed as a number.
|
|
191
|
+
*/
|
|
192
|
+
function numbers(prefix, max, prop, suffix = '') {
|
|
190
193
|
return Object.fromEntries(Array.from({ length: max }, (_, i) => String(i + 1)).map(value => [
|
|
191
|
-
`${prefix}${value}`,
|
|
194
|
+
`${prefix}${value}${suffix}`,
|
|
192
195
|
{ writes: [{ prop, value, numeric: true }] },
|
|
193
196
|
]));
|
|
194
197
|
}
|
|
@@ -1087,7 +1090,6 @@ export const ROOTS = {
|
|
|
1087
1090
|
},
|
|
1088
1091
|
// ---- Families bestax has but that do not map element by element yet ------
|
|
1089
1092
|
breadcrumb: todo('Breadcrumb', 'bestax `Breadcrumb` renders the `<ul>` itself and adds an `aria-label`'),
|
|
1090
|
-
'fixed-grid': todo('Grid', '`Grid isFixed` renders the `.fixed-grid` wrapper itself, from `fixedCols`; replace the wrapper and its `.grid` with one `Grid`, by hand'),
|
|
1091
1093
|
checkbox: todo('Checkbox', "bestax `Checkbox` renders its own styled markup, not Bulma's"),
|
|
1092
1094
|
checkboxes: todo('Checkboxes', 'bestax `Checkboxes` renders its own `.field` and `.control` wrappers'),
|
|
1093
1095
|
radio: todo('Radio', "bestax `Radio` renders its own styled markup, not Bulma's"),
|
|
@@ -1138,9 +1140,28 @@ export const ROOTS = {
|
|
|
1138
1140
|
'panel-icon': part(),
|
|
1139
1141
|
'panel-list': part(),
|
|
1140
1142
|
tabs: todo('Tabs', "bestax `Tabs` renders each tab's `<li>` and `<a>` together, with tab roles"),
|
|
1141
|
-
'table-container': todo('Table', 'bestax renders `.table-container` from `Table isResponsive`'),
|
|
1142
1143
|
'skeleton-block': todo('Skeleton', 'bestax `Skeleton` renders its own markup'),
|
|
1143
1144
|
'skeleton-lines': todo('Skeleton', 'bestax `Skeleton` renders its own markup'),
|
|
1145
|
+
// ---- Wrappers a component renders from a prop ---------------------------------
|
|
1146
|
+
// Each renders the wrapper with its own class and nothing else, so the
|
|
1147
|
+
// element folds only when it carries no attribute and no other class.
|
|
1148
|
+
'table-container': {
|
|
1149
|
+
status: 'fold',
|
|
1150
|
+
target: 'Table',
|
|
1151
|
+
tag: 'div',
|
|
1152
|
+
folds: [{ prop: 'isResponsive' }],
|
|
1153
|
+
},
|
|
1154
|
+
'fixed-grid': {
|
|
1155
|
+
status: 'fold',
|
|
1156
|
+
target: 'Grid',
|
|
1157
|
+
tag: 'div',
|
|
1158
|
+
folds: [{ prop: 'isFixed' }],
|
|
1159
|
+
modifiers: {
|
|
1160
|
+
...numbers('has-', 12, 'fixedCols', '-cols'),
|
|
1161
|
+
...Object.assign({}, ...SIZE_VIEWPORTS.map(viewport => numbers('has-', 12, `fixedCols${viewportSuffix(viewport)}`, `-cols-${viewport}`))),
|
|
1162
|
+
'has-auto-count': set('fixedCols', 'auto'),
|
|
1163
|
+
},
|
|
1164
|
+
},
|
|
1144
1165
|
// ---- Valid Bulma, nothing to convert to --------------------------------------
|
|
1145
1166
|
// The other sources emit these on purpose where bestax has no component.
|
|
1146
1167
|
help: plain('bestax renders `.help` only inside its form controls'),
|
|
@@ -1387,8 +1408,8 @@ export const PASSTHROUGH = [
|
|
|
1387
1408
|
match: /^(?:is-(?:col|row)-.+|is-(?:column|row)-gap-\d+|is-gap-\d+|is-auto-fill)$/,
|
|
1388
1409
|
},
|
|
1389
1410
|
{
|
|
1390
|
-
why: 'a `.fixed-grid` column count, which
|
|
1391
|
-
match: /^has-\d+-cols(?:-.+)
|
|
1411
|
+
why: 'a `.fixed-grid` column count, which converts only on its own `.fixed-grid`',
|
|
1412
|
+
match: /^(?:has-\d+-cols(?:-.+)?|has-auto-count)$/,
|
|
1392
1413
|
},
|
|
1393
1414
|
{
|
|
1394
1415
|
why: 'an `.image` modifier; `.image` stays as markup',
|
|
@@ -1400,7 +1421,7 @@ export const PASSTHROUGH = [
|
|
|
1400
1421
|
},
|
|
1401
1422
|
{
|
|
1402
1423
|
why: 'a modifier of markup this source leaves alone, or one bestax has no prop for',
|
|
1403
|
-
match: /^(?:has-addons-.+|has-[a-z]+-separator|has-dropdown(?:-up)?|has-fixed-size|has-icons-(?:left|right)|has-name|has-(?:spaced-)?navbar-fixed-(?:top|bottom)(?:-desktop)?|has-shadow|
|
|
1424
|
+
match: /^(?:has-addons-.+|has-[a-z]+-separator|has-dropdown(?:-up)?|has-fixed-size|has-icons-(?:left|right)|has-name|has-(?:spaced-)?navbar-fixed-(?:top|bottom)(?:-desktop)?|has-shadow|is-arrowless|is-boxed|is-center|is-current|is-delete|is-disabled|is-empty|is-expanded|is-fixed-(?:top|bottom)(?:-desktop)?|is-flexible|is-grouped(?:-.+)?|is-halfheight|is-horizontal|is-left|is-(?:lower|upper)-(?:alpha|roman)|is-multiple|is-responsive|is-selected|is-tab|is-toggle(?:-rounded)?|is-transparent|is-underlined|is-up|is-wrapped)$/,
|
|
1404
1425
|
},
|
|
1405
1426
|
];
|
|
1406
1427
|
/**
|
|
@@ -28,6 +28,11 @@ export interface ElementFacts {
|
|
|
28
28
|
* counts: one in an expression may not render.
|
|
29
29
|
*/
|
|
30
30
|
childTargets?: readonly string[];
|
|
31
|
+
/**
|
|
32
|
+
* What the element's only child converts to, when the element holds one
|
|
33
|
+
* element and nothing else (not even whitespace React would render).
|
|
34
|
+
*/
|
|
35
|
+
soleChildTarget?: string;
|
|
31
36
|
/** The bestax components already in the file inside this element. */
|
|
32
37
|
bestaxInside?: readonly string[];
|
|
33
38
|
/** The bestax components already in the file around this element. */
|
|
@@ -65,6 +70,15 @@ export interface Conversion {
|
|
|
65
70
|
}
|
|
66
71
|
export interface Plan {
|
|
67
72
|
conversion: Conversion | null;
|
|
73
|
+
/**
|
|
74
|
+
* The element is a wrapper its only child's component renders from these
|
|
75
|
+
* props: they join that child's conversion, and the element goes.
|
|
76
|
+
*/
|
|
77
|
+
fold?: {
|
|
78
|
+
target: string;
|
|
79
|
+
props: Array<[name: string, value: string | true]>;
|
|
80
|
+
numbers: string[];
|
|
81
|
+
};
|
|
68
82
|
todos: Todo[];
|
|
69
83
|
}
|
|
70
84
|
export declare function plan(facts: ElementFacts): Plan;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AA+BD,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B;;;OAGG;IACH,IAAI,CAAC,EAAE;QACL,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;QACnD,OAAO,EAAE,MAAM,EAAE,CAAC;KACnB,CAAC;IACF,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AA+BD,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAkS9C"}
|
|
@@ -61,6 +61,9 @@ export function plan(facts) {
|
|
|
61
61
|
});
|
|
62
62
|
return { conversion: null, todos };
|
|
63
63
|
}
|
|
64
|
+
const wrapper = tokens.find(token => rootFor(token)?.status === 'fold');
|
|
65
|
+
if (wrapper)
|
|
66
|
+
return planFold(facts, wrapper, todos);
|
|
64
67
|
const root = tokens
|
|
65
68
|
.filter(token => rootFor(token)?.status === 'mapped')
|
|
66
69
|
.sort((a, b) => precedence(a) - precedence(b))[0];
|
|
@@ -257,3 +260,57 @@ export function plan(facts) {
|
|
|
257
260
|
todos,
|
|
258
261
|
};
|
|
259
262
|
}
|
|
263
|
+
/**
|
|
264
|
+
* A wrapper the component inside it renders from a prop (`.table-container`
|
|
265
|
+
* from `Table isResponsive`). It folds into that component only when it is
|
|
266
|
+
* exactly what the component renders for it: its own tag and class, its own
|
|
267
|
+
* modifiers, no attribute, and one child that becomes the component.
|
|
268
|
+
*/
|
|
269
|
+
function planFold(facts, wrapper, todos) {
|
|
270
|
+
const entry = rootFor(wrapper);
|
|
271
|
+
const target = entry.target;
|
|
272
|
+
if (!target)
|
|
273
|
+
return { conversion: null, todos };
|
|
274
|
+
const folds = entry.folds ?? [];
|
|
275
|
+
const renders = `\`${target} ${folds.map(write => write.prop).join(' ')}\``;
|
|
276
|
+
const refuse = (kind, token, message) => ({
|
|
277
|
+
conversion: null,
|
|
278
|
+
todos: [...todos, { rule: ruleId(kind, token), message }],
|
|
279
|
+
});
|
|
280
|
+
if (facts.tag !== entry.tag) {
|
|
281
|
+
return refuse('tag', target, `bestax ${renders} renders \`.${wrapper}\` on a <${entry.tag}>, not a <${facts.tag}>; keep the markup, or change the tag and re-run`);
|
|
282
|
+
}
|
|
283
|
+
if (facts.hasSpread) {
|
|
284
|
+
return refuse('spread', target, `this element spreads props, and bestax ${renders} renders \`.${wrapper}\` with none of its own; keep it as markup`);
|
|
285
|
+
}
|
|
286
|
+
if (facts.onlyChildOf) {
|
|
287
|
+
return refuse('only-child', target, `this element is the only child of \`<${facts.onlyChildOf}>\`, which may hand it props or a ref with \`cloneElement\`, and folding it would move those onto the \`${target}\` inside; convert it by hand if \`<${facts.onlyChildOf}>\` only renders its children`);
|
|
288
|
+
}
|
|
289
|
+
const attribute = [...facts.attributes.keys()][0];
|
|
290
|
+
if (attribute) {
|
|
291
|
+
return refuse('attr', attribute, `bestax ${renders} renders \`.${wrapper}\` with no attributes, so this element's \`${attribute}\` would be lost; keep it as markup`);
|
|
292
|
+
}
|
|
293
|
+
const props = folds.map(write => [
|
|
294
|
+
write.prop,
|
|
295
|
+
write.value ?? true,
|
|
296
|
+
]);
|
|
297
|
+
const numbers = [];
|
|
298
|
+
for (const token of facts.tokens) {
|
|
299
|
+
if (token === wrapper)
|
|
300
|
+
continue;
|
|
301
|
+
const modifier = modifierFor(entry, token);
|
|
302
|
+
const taken = modifier?.writes.some(write => props.some(([prop]) => prop === write.prop));
|
|
303
|
+
if (!modifier || taken) {
|
|
304
|
+
return refuse('attr', 'className', `bestax ${renders} renders \`.${wrapper}\` with no class but its own and one of each of its modifiers, so \`${token}\` would be lost; keep this element as markup`);
|
|
305
|
+
}
|
|
306
|
+
for (const write of modifier.writes) {
|
|
307
|
+
props.push([write.prop, write.value ?? true]);
|
|
308
|
+
if (write.numeric)
|
|
309
|
+
numbers.push(write.prop);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
if (facts.soleChildTarget !== target) {
|
|
313
|
+
return refuse('children', target, `bestax ${renders} renders \`.${wrapper}\` itself, so this element converts only around a single element that becomes a \`${target}\`, with nothing else beside it`);
|
|
314
|
+
}
|
|
315
|
+
return { conversion: null, fold: { target, props, numbers }, todos };
|
|
316
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAoTvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CAqYpB"}
|
|
@@ -47,6 +47,22 @@ const JSX_FACTORY = /^\s*\*?\s*@jsx\s+(\S+)/m;
|
|
|
47
47
|
const HEADER_PRAGMA = /^[\s*]*(?:@ts-(?:no)?check|@flow|@noflow|eslint-disable(?!-)|@jsx|@jsxImportSource|@jsxRuntime|@license|@preserve)\b/;
|
|
48
48
|
/** Directives that act on the line after them, so must stay above it. */
|
|
49
49
|
const NEXT_LINE_DIRECTIVE = /^[\s*]*(?:eslint-disable-next-line|@ts-expect-error|@ts-ignore|prettier-ignore)\b/;
|
|
50
|
+
/**
|
|
51
|
+
* A comment moved to sit after a JSX tag name. It has to be a block comment
|
|
52
|
+
* there: recast prints a line comment as `<// …`, which TypeScript reads as a
|
|
53
|
+
* closing tag.
|
|
54
|
+
*/
|
|
55
|
+
function afterTagName(comment) {
|
|
56
|
+
if (comment.type !== 'CommentLine') {
|
|
57
|
+
return { ...comment, leading: false, trailing: true };
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
type: 'CommentBlock',
|
|
61
|
+
value: ` ${comment.value.trim().replace(/\*\//g, '*\\/')} `,
|
|
62
|
+
leading: false,
|
|
63
|
+
trailing: true,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
50
66
|
/** A lowercase intrinsic tag: not a component, not a custom element. */
|
|
51
67
|
const INTRINSIC = /^[a-z][a-z0-9]*$/;
|
|
52
68
|
/** Subtrees whose tags are not HTML. */
|
|
@@ -325,10 +341,21 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
325
341
|
if (child.type !== 'JSXElement')
|
|
326
342
|
return [];
|
|
327
343
|
const target = planned.get(child)?.conversion?.target ??
|
|
344
|
+
planned.get(child)?.fold?.target ??
|
|
328
345
|
// A direct child is looked up in the element's own scope, the child's.
|
|
329
346
|
bestaxTarget(child, elementPath);
|
|
330
347
|
return target ? [target] : [];
|
|
331
348
|
});
|
|
349
|
+
/**
|
|
350
|
+
* The one element an element holds, when it holds nothing else: no text
|
|
351
|
+
* React renders, and no comment, which folding the element would drop.
|
|
352
|
+
*/
|
|
353
|
+
const soleChild = (element) => {
|
|
354
|
+
const content = (element.children ?? []).filter((child) => child.type !== 'JSXText' || reachesReact(child));
|
|
355
|
+
return content.length === 1 && content[0].type === 'JSXElement'
|
|
356
|
+
? content[0]
|
|
357
|
+
: undefined;
|
|
358
|
+
};
|
|
332
359
|
// For each element, the bestax components already in the file inside it:
|
|
333
360
|
// `Field` and `Control` change how bestax's form controls render.
|
|
334
361
|
const bestaxInside = new Map();
|
|
@@ -399,17 +426,19 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
399
426
|
hasRef: attributes.has('ref'),
|
|
400
427
|
hasChildren: (element.children ?? []).some(reachesReact),
|
|
401
428
|
childTargets: childTargets(elementPath),
|
|
429
|
+
soleChildTarget: planned.get(soleChild(element))?.conversion?.target,
|
|
402
430
|
bestaxInside: bestaxInside.get(element) ?? [],
|
|
403
431
|
bestaxAround: surrounding.bestax,
|
|
404
432
|
componentsAround: surrounding.other,
|
|
405
433
|
onlyChildOf: onlyChildOf(elementPath, bestaxLocals),
|
|
406
434
|
};
|
|
407
435
|
let result = plan(facts);
|
|
408
|
-
const converts = result.conversion !== null;
|
|
409
|
-
|
|
436
|
+
const converts = result.conversion !== null || result.fold !== undefined;
|
|
437
|
+
const becomes = result.conversion?.target ?? result.fold?.target;
|
|
438
|
+
if (className === null && becomes) {
|
|
410
439
|
// The same element with a static className would convert; with a
|
|
411
440
|
// computed one, only a person can turn each condition into its prop.
|
|
412
|
-
const target =
|
|
441
|
+
const target = becomes;
|
|
413
442
|
result = {
|
|
414
443
|
conversion: null,
|
|
415
444
|
todos: [
|
|
@@ -421,8 +450,15 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
421
450
|
],
|
|
422
451
|
};
|
|
423
452
|
}
|
|
453
|
+
if (result.fold) {
|
|
454
|
+
// The wrapper's props join its child's conversion, which has not been
|
|
455
|
+
// applied yet: conversions are applied after every element is planned.
|
|
456
|
+
const inner = planned.get(soleChild(element)).conversion;
|
|
457
|
+
inner.props.push(...result.fold.props);
|
|
458
|
+
inner.numbers.push(...result.fold.numbers);
|
|
459
|
+
}
|
|
424
460
|
planned.set(element, result);
|
|
425
|
-
if (result.conversion || result.todos.length > 0) {
|
|
461
|
+
if (result.conversion || result.fold || result.todos.length > 0) {
|
|
426
462
|
elements.unshift({ path: elementPath, plan: result, converts });
|
|
427
463
|
}
|
|
428
464
|
}
|
|
@@ -436,7 +472,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
436
472
|
if (converting)
|
|
437
473
|
addTodo(ctx, elements[0].path, rule, message);
|
|
438
474
|
for (const element of elements) {
|
|
439
|
-
element.plan = { ...element.plan, conversion: null };
|
|
475
|
+
element.plan = { ...element.plan, conversion: null, fold: undefined };
|
|
440
476
|
}
|
|
441
477
|
};
|
|
442
478
|
const runtime = fileJsxRuntime(root, j) ??
|
|
@@ -482,6 +518,32 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
482
518
|
}
|
|
483
519
|
}
|
|
484
520
|
for (const { path: elementPath, plan: result } of [...elements].reverse()) {
|
|
521
|
+
if (result.fold) {
|
|
522
|
+
// The child inside has converted already (innermost first), with the
|
|
523
|
+
// wrapper's props on it; the wrapper itself goes, its comments with the
|
|
524
|
+
// child: one on the wrapper moves to the child, and one inside the
|
|
525
|
+
// wrapper's tags moves inside the child's opening tag.
|
|
526
|
+
const wrapper = elementPath.node;
|
|
527
|
+
const inner = soleChild(wrapper);
|
|
528
|
+
const { openingElement, closingElement } = wrapper;
|
|
529
|
+
const inTags = [
|
|
530
|
+
openingElement,
|
|
531
|
+
openingElement.name,
|
|
532
|
+
...(openingElement.attributes ?? []),
|
|
533
|
+
closingElement,
|
|
534
|
+
closingElement?.name,
|
|
535
|
+
].flatMap((node) => node?.comments ?? []);
|
|
536
|
+
if (inTags.length) {
|
|
537
|
+
const name = inner.openingElement.name;
|
|
538
|
+
name.comments = [...(name.comments ?? []), ...inTags.map(afterTagName)];
|
|
539
|
+
}
|
|
540
|
+
if (wrapper.comments?.length) {
|
|
541
|
+
inner.comments = [...wrapper.comments, ...(inner.comments ?? [])];
|
|
542
|
+
}
|
|
543
|
+
elementPath.replace(inner);
|
|
544
|
+
ctx.dirty = true;
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
485
547
|
const conversion = result.conversion;
|
|
486
548
|
if (!conversion)
|
|
487
549
|
continue;
|
|
@@ -506,19 +568,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
506
568
|
const carrier = replacement[0] ?? attrs.find((attr) => attr !== classAttr) ?? name;
|
|
507
569
|
carrier.comments = [
|
|
508
570
|
...(carrier.comments ?? []),
|
|
509
|
-
...classAttr.comments.map((comment) =>
|
|
510
|
-
if (carrier !== name)
|
|
511
|
-
return comment;
|
|
512
|
-
if (comment.type !== 'CommentLine') {
|
|
513
|
-
return { ...comment, leading: false, trailing: true };
|
|
514
|
-
}
|
|
515
|
-
return {
|
|
516
|
-
type: 'CommentBlock',
|
|
517
|
-
value: ` ${comment.value.trim().replace(/\*\//g, '*\\/')} `,
|
|
518
|
-
leading: false,
|
|
519
|
-
trailing: true,
|
|
520
|
-
};
|
|
521
|
-
}),
|
|
571
|
+
...classAttr.comments.map((comment) => carrier === name ? afterTagName(comment) : comment),
|
|
522
572
|
];
|
|
523
573
|
}
|
|
524
574
|
attrs.splice(attrs.indexOf(classAttr), 1, ...replacement);
|