bestax-migrate 2.7.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 +11 -1
- package/dist/sources/bulma-classes/class-map.d.ts.map +1 -1
- package/dist/sources/bulma-classes/class-map.js +94 -7
- package/dist/sources/bulma-classes/plan.d.ts +18 -1
- package/dist/sources/bulma-classes/plan.d.ts.map +1 -1
- package/dist/sources/bulma-classes/plan.js +59 -0
- package/dist/sources/bulma-classes/transform.d.ts.map +1 -1
- package/dist/sources/bulma-classes/transform.js +74 -22
- package/package.json +1 -1
|
@@ -16,6 +16,8 @@ export interface PropWrite {
|
|
|
16
16
|
readonly prop: string;
|
|
17
17
|
/** Omitted for a bare boolean prop. */
|
|
18
18
|
readonly value?: string;
|
|
19
|
+
/** The prop is typed as a number, so the value is written as one. */
|
|
20
|
+
readonly numeric?: boolean;
|
|
19
21
|
}
|
|
20
22
|
export type TagSet = {
|
|
21
23
|
readonly on: readonly string[];
|
|
@@ -33,8 +35,11 @@ export interface Modifier {
|
|
|
33
35
|
* - `todo`: bestax has a component, but the markup does not map element by
|
|
34
36
|
* element yet; the family's outermost class gets a TODO.
|
|
35
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`).
|
|
36
41
|
*/
|
|
37
|
-
export type RootStatus = 'mapped' | 'todo' | 'plain';
|
|
42
|
+
export type RootStatus = 'mapped' | 'todo' | 'plain' | 'fold';
|
|
38
43
|
export interface RootEntry {
|
|
39
44
|
readonly status: RootStatus;
|
|
40
45
|
/**
|
|
@@ -87,6 +92,11 @@ export interface RootEntry {
|
|
|
87
92
|
* takes a generated `id` when the element has none of its own.
|
|
88
93
|
*/
|
|
89
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[];
|
|
90
100
|
/** The target takes no helper props, so every helper class stays a class. */
|
|
91
101
|
readonly noHelpers?: boolean;
|
|
92
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;
|
|
1
|
+
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -146,6 +146,8 @@ const COMPONENT_COLORS = [
|
|
|
146
146
|
'light',
|
|
147
147
|
'dark',
|
|
148
148
|
];
|
|
149
|
+
/** Bulma's whole-step spacing scale, as `Grid`'s gap props take it. */
|
|
150
|
+
const GAPS = ['0', '1', '2', '3', '4', '5', '6', '7', '8'];
|
|
149
151
|
const COLUMN_SIZES = [
|
|
150
152
|
'1',
|
|
151
153
|
'2',
|
|
@@ -183,6 +185,16 @@ const flag = (prop) => ({ writes: [{ prop }] });
|
|
|
183
185
|
const set = (prop, value) => ({
|
|
184
186
|
writes: [{ prop, value }],
|
|
185
187
|
});
|
|
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 = '') {
|
|
193
|
+
return Object.fromEntries(Array.from({ length: max }, (_, i) => String(i + 1)).map(value => [
|
|
194
|
+
`${prefix}${value}${suffix}`,
|
|
195
|
+
{ writes: [{ prop, value, numeric: true }] },
|
|
196
|
+
]));
|
|
197
|
+
}
|
|
186
198
|
/** `prefix + value + suffix` → `prop = value`, for each value. */
|
|
187
199
|
function tokens(prefix, values, prop, suffix = '') {
|
|
188
200
|
return Object.fromEntries(values.map(value => [`${prefix}${value}${suffix}`, set(prop, value)]));
|
|
@@ -481,6 +493,59 @@ export const ROOTS = {
|
|
|
481
493
|
'isNarrowFullhd',
|
|
482
494
|
],
|
|
483
495
|
},
|
|
496
|
+
// Grid's gaps take a numeric string, but its column minimum and every Cell
|
|
497
|
+
// placement are typed as numbers. The half steps (`is-gap-0.5`) have no prop.
|
|
498
|
+
grid: {
|
|
499
|
+
...BASE,
|
|
500
|
+
target: 'Grid',
|
|
501
|
+
tag: 'div',
|
|
502
|
+
modifiers: {
|
|
503
|
+
...tokens('is-gap-', GAPS, 'gap'),
|
|
504
|
+
...tokens('is-column-gap-', GAPS, 'columnGap'),
|
|
505
|
+
...tokens('is-row-gap-', GAPS, 'rowGap'),
|
|
506
|
+
...numbers('is-col-min-', 32, 'minCol'),
|
|
507
|
+
},
|
|
508
|
+
ownProps: [
|
|
509
|
+
'isFixed',
|
|
510
|
+
'gap',
|
|
511
|
+
'columnGap',
|
|
512
|
+
'rowGap',
|
|
513
|
+
'minCol',
|
|
514
|
+
'fixedCols',
|
|
515
|
+
'fixedColsMobile',
|
|
516
|
+
'fixedColsTablet',
|
|
517
|
+
'fixedColsDesktop',
|
|
518
|
+
'fixedColsWidescreen',
|
|
519
|
+
'fixedColsFullhd',
|
|
520
|
+
'textColor',
|
|
521
|
+
'color',
|
|
522
|
+
'bgColor',
|
|
523
|
+
],
|
|
524
|
+
},
|
|
525
|
+
cell: {
|
|
526
|
+
...BASE,
|
|
527
|
+
target: 'Cell',
|
|
528
|
+
tag: 'div',
|
|
529
|
+
modifiers: {
|
|
530
|
+
...numbers('is-col-start-', 12, 'colStart'),
|
|
531
|
+
...numbers('is-col-from-end-', 12, 'colFromEnd'),
|
|
532
|
+
...numbers('is-col-span-', 12, 'colSpan'),
|
|
533
|
+
...numbers('is-row-start-', 12, 'rowStart'),
|
|
534
|
+
...numbers('is-row-from-end-', 12, 'rowFromEnd'),
|
|
535
|
+
...numbers('is-row-span-', 12, 'rowSpan'),
|
|
536
|
+
},
|
|
537
|
+
ownProps: [
|
|
538
|
+
'colStart',
|
|
539
|
+
'colFromEnd',
|
|
540
|
+
'colSpan',
|
|
541
|
+
'rowStart',
|
|
542
|
+
'rowFromEnd',
|
|
543
|
+
'rowSpan',
|
|
544
|
+
'textColor',
|
|
545
|
+
'color',
|
|
546
|
+
'bgColor',
|
|
547
|
+
],
|
|
548
|
+
},
|
|
484
549
|
container: {
|
|
485
550
|
...BASE,
|
|
486
551
|
target: 'Container',
|
|
@@ -1025,9 +1090,6 @@ export const ROOTS = {
|
|
|
1025
1090
|
},
|
|
1026
1091
|
// ---- Families bestax has but that do not map element by element yet ------
|
|
1027
1092
|
breadcrumb: todo('Breadcrumb', 'bestax `Breadcrumb` renders the `<ul>` itself and adds an `aria-label`'),
|
|
1028
|
-
cell: todo('Cell', 'this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
|
|
1029
|
-
grid: todo('Grid', 'this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
|
|
1030
|
-
'fixed-grid': todo('Grid', 'this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
|
|
1031
1093
|
checkbox: todo('Checkbox', "bestax `Checkbox` renders its own styled markup, not Bulma's"),
|
|
1032
1094
|
checkboxes: todo('Checkboxes', 'bestax `Checkboxes` renders its own `.field` and `.control` wrappers'),
|
|
1033
1095
|
radio: todo('Radio', "bestax `Radio` renders its own styled markup, not Bulma's"),
|
|
@@ -1078,9 +1140,28 @@ export const ROOTS = {
|
|
|
1078
1140
|
'panel-icon': part(),
|
|
1079
1141
|
'panel-list': part(),
|
|
1080
1142
|
tabs: todo('Tabs', "bestax `Tabs` renders each tab's `<li>` and `<a>` together, with tab roles"),
|
|
1081
|
-
'table-container': todo('Table', 'bestax renders `.table-container` from `Table isResponsive`'),
|
|
1082
1143
|
'skeleton-block': todo('Skeleton', 'bestax `Skeleton` renders its own markup'),
|
|
1083
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
|
+
},
|
|
1084
1165
|
// ---- Valid Bulma, nothing to convert to --------------------------------------
|
|
1085
1166
|
// The other sources emit these on purpose where bestax has no component.
|
|
1086
1167
|
help: plain('bestax renders `.help` only inside its form controls'),
|
|
@@ -1113,6 +1194,8 @@ function plain(why) {
|
|
|
1113
1194
|
export const PRECEDENCE = [
|
|
1114
1195
|
'columns',
|
|
1115
1196
|
'column',
|
|
1197
|
+
'grid',
|
|
1198
|
+
'cell',
|
|
1116
1199
|
'container',
|
|
1117
1200
|
'section',
|
|
1118
1201
|
'hero',
|
|
@@ -1321,8 +1404,12 @@ export const PASSTHROUGH = [
|
|
|
1321
1404
|
match: /-(?:touch|tablet-only|desktop-only|widescreen-only)$/,
|
|
1322
1405
|
},
|
|
1323
1406
|
{
|
|
1324
|
-
why: 'Grid
|
|
1325
|
-
match: /^(?:is-(?:col|row)-.+|
|
|
1407
|
+
why: 'a Grid or Cell class, which converts only on its own `.grid` or `.cell`, and only where bestax has a prop for it',
|
|
1408
|
+
match: /^(?:is-(?:col|row)-.+|is-(?:column|row)-gap-\d+|is-gap-\d+|is-auto-fill)$/,
|
|
1409
|
+
},
|
|
1410
|
+
{
|
|
1411
|
+
why: 'a `.fixed-grid` column count, which converts only on its own `.fixed-grid`',
|
|
1412
|
+
match: /^(?:has-\d+-cols(?:-.+)?|has-auto-count)$/,
|
|
1326
1413
|
},
|
|
1327
1414
|
{
|
|
1328
1415
|
why: 'an `.image` modifier; `.image` stays as markup',
|
|
@@ -1334,7 +1421,7 @@ export const PASSTHROUGH = [
|
|
|
1334
1421
|
},
|
|
1335
1422
|
{
|
|
1336
1423
|
why: 'a modifier of markup this source leaves alone, or one bestax has no prop for',
|
|
1337
|
-
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)$/,
|
|
1338
1425
|
},
|
|
1339
1426
|
];
|
|
1340
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. */
|
|
@@ -57,11 +62,23 @@ export interface Conversion {
|
|
|
57
62
|
className: string | null;
|
|
58
63
|
/** Attributes to remove: defaults the target renders by itself. */
|
|
59
64
|
drop: string[];
|
|
60
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Attributes, and props written above, whose numeric string value becomes
|
|
67
|
+
* a number (`minCol={4}`), because the target types them as numbers.
|
|
68
|
+
*/
|
|
61
69
|
numbers: string[];
|
|
62
70
|
}
|
|
63
71
|
export interface Plan {
|
|
64
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
|
+
};
|
|
65
82
|
todos: Todo[];
|
|
66
83
|
}
|
|
67
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
|
|
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];
|
|
@@ -183,6 +186,8 @@ export function plan(facts) {
|
|
|
183
186
|
for (const write of modifier.writes) {
|
|
184
187
|
writes.set(write.prop, write.value ?? true);
|
|
185
188
|
sourceOf.set(write.prop, token);
|
|
189
|
+
if (write.numeric)
|
|
190
|
+
numbers.push(write.prop);
|
|
186
191
|
}
|
|
187
192
|
converted.add(token);
|
|
188
193
|
continue;
|
|
@@ -255,3 +260,57 @@ export function plan(facts) {
|
|
|
255
260
|
todos,
|
|
256
261
|
};
|
|
257
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;
|
|
@@ -492,10 +554,6 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
492
554
|
for (const name of conversion.drop) {
|
|
493
555
|
attrs.splice(attrs.indexOf(findAttr(element, name)), 1);
|
|
494
556
|
}
|
|
495
|
-
for (const name of conversion.numbers) {
|
|
496
|
-
const attr = findAttr(element, name);
|
|
497
|
-
attr.value = j.jsxExpressionContainer(j.numericLiteral(Number(attributeValue(attr))));
|
|
498
|
-
}
|
|
499
557
|
const classAttr = findAttr(element, 'className');
|
|
500
558
|
const replacement = conversion.props.map(([name, value]) => makeAttr(j, name, value === true ? undefined : value));
|
|
501
559
|
if (conversion.className) {
|
|
@@ -510,22 +568,16 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
510
568
|
const carrier = replacement[0] ?? attrs.find((attr) => attr !== classAttr) ?? name;
|
|
511
569
|
carrier.comments = [
|
|
512
570
|
...(carrier.comments ?? []),
|
|
513
|
-
...classAttr.comments.map((comment) =>
|
|
514
|
-
if (carrier !== name)
|
|
515
|
-
return comment;
|
|
516
|
-
if (comment.type !== 'CommentLine') {
|
|
517
|
-
return { ...comment, leading: false, trailing: true };
|
|
518
|
-
}
|
|
519
|
-
return {
|
|
520
|
-
type: 'CommentBlock',
|
|
521
|
-
value: ` ${comment.value.trim().replace(/\*\//g, '*\\/')} `,
|
|
522
|
-
leading: false,
|
|
523
|
-
trailing: true,
|
|
524
|
-
};
|
|
525
|
-
}),
|
|
571
|
+
...classAttr.comments.map((comment) => carrier === name ? afterTagName(comment) : comment),
|
|
526
572
|
];
|
|
527
573
|
}
|
|
528
574
|
attrs.splice(attrs.indexOf(classAttr), 1, ...replacement);
|
|
575
|
+
// After the splice, so a prop the conversion wrote is found as well as
|
|
576
|
+
// an attribute the element already had.
|
|
577
|
+
for (const name of conversion.numbers) {
|
|
578
|
+
const attr = findAttr(element, name);
|
|
579
|
+
attr.value = j.jsxExpressionContainer(j.numericLiteral(Number(attributeValue(attr))));
|
|
580
|
+
}
|
|
529
581
|
ctx.dirty = true;
|
|
530
582
|
}
|
|
531
583
|
// ---- 5. The bestax import ---------------------------------------------------
|