bestax-migrate 2.23.1 → 2.25.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/README.md +13 -0
- package/dist/sources/_shared/polymorphic.d.ts.map +1 -1
- package/dist/sources/_shared/polymorphic.js +54 -0
- package/dist/sources/bulma-classes/class-map.d.ts +27 -3
- package/dist/sources/bulma-classes/class-map.d.ts.map +1 -1
- package/dist/sources/bulma-classes/class-map.js +157 -14
- package/dist/sources/bulma-classes/plan.d.ts +38 -0
- package/dist/sources/bulma-classes/plan.d.ts.map +1 -1
- package/dist/sources/bulma-classes/plan.js +129 -2
- package/dist/sources/bulma-classes/transform.d.ts.map +1 -1
- package/dist/sources/bulma-classes/transform.js +151 -12
- package/dist/sources/rbx/mapping.js +1 -1
- package/dist/sources/react-bulma-components/mapping.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/mapping.js +4 -3
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -64,6 +64,19 @@ Anything without a safe automatic conversion is left in place with a `// TODO(be
|
|
|
64
64
|
npx skills add https://github.com/allxsmith/bestax --skill bestax-migrate
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
### Through the Codemod Registry
|
|
68
|
+
|
|
69
|
+
bestax-migrate is also in the [Codemod Registry](https://app.codemod.com/registry) as `bestax-migrate`, for teams that run their migrations through Codemod. That package runs this CLI from npm at a pinned release, which can trail the newest one:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# Preview (no writes)
|
|
73
|
+
npx codemod bestax-migrate --workflow preview --param source=react-bulma-components
|
|
74
|
+
# Apply
|
|
75
|
+
npx codemod bestax-migrate --param source=react-bulma-components
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Run it from your app root. `--param paths="src lib"` (default `src`) and `--param options="--css keep"` pass through to the CLI. Codemod's own `--dry-run` skips the shell step this package runs, so use the `preview` workflow for a dry run.
|
|
79
|
+
|
|
67
80
|
## Options
|
|
68
81
|
|
|
69
82
|
| Flag | Description |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"polymorphic.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/polymorphic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AA0BxB,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAkB,CAAC;AAmK3E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,GACtB,UAAU,MAAM,GAAG,SAAS,EAC5B,eAAa,KACZ,MAmBF,CAAC;AAMF,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAQD,mDAAmD;AACnD,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAW,CAAC;AAC1D,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAAuB,CAAC;AAkEpE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAAkC,CAAC;AAE9E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAwH5C,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AASD,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG3E;AAED,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAAoC,CAAC;AAE7E,6CAA6C;AAC7C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAC1C,CAAC;
|
|
1
|
+
{"version":3,"file":"polymorphic.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/polymorphic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAML,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AA0BxB,eAAO,MAAM,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAkB,CAAC;AAmK3E;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,WAAW,GACtB,UAAU,MAAM,GAAG,SAAS,EAC5B,eAAa,KACZ,MAmBF,CAAC;AAMF,oDAAoD;AACpD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAElD;AAQD,mDAAmD;AACnD,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAW,CAAC;AAC1D,eAAO,MAAM,cAAc,EAAE,SAAS,MAAM,EAAuB,CAAC;AAkEpE;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,SAAS,MAAM,EAAkC,CAAC;AAE9E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,EAAE,SAAS,MAAM,EAwH5C,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AASD,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAG3E;AAED,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,SAAS,MAAM,EAAoC,CAAC;AAE7E,6CAA6C;AAC7C,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAC1C,CAAC;AAqPrB;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,MAAM,EAAE,MAAM;AACd;;;;;;;;;GASG;AACH,gBAAgB,UAAQ,GACvB,IAAI,CAuEN"}
|
|
@@ -592,6 +592,59 @@ function dropInertLinkAttrs(ctx, path, element, target, rendered) {
|
|
|
592
592
|
ctx.dirty = true;
|
|
593
593
|
}
|
|
594
594
|
}
|
|
595
|
+
/**
|
|
596
|
+
* The targets that write `type="button"` on the <button> an `as` makes them
|
|
597
|
+
* render, in place of a missing `type` or one HTML does not define
|
|
598
|
+
* (`buttonType` in bulma-ui). A plain <button> with neither submits the form
|
|
599
|
+
* around it, and every source here rendered the tag it was given, so a source
|
|
600
|
+
* element asking for a <button> with no usable `type` was a submit button that
|
|
601
|
+
* the migrated one no longer is.
|
|
602
|
+
*
|
|
603
|
+
* `Button` is not here: bestax leaves its `type` to the caller, as the sources
|
|
604
|
+
* did. Nor are `Card.Header.Icon`, `Delete` and the other targets that always
|
|
605
|
+
* render a <button>. The author never asked for a <button> there, so what the
|
|
606
|
+
* source rendered is a question about the source library, not this element.
|
|
607
|
+
*/
|
|
608
|
+
const TYPES_ITS_BUTTON = new Set([
|
|
609
|
+
'Dropdown.Item',
|
|
610
|
+
'Menu.Item',
|
|
611
|
+
'Navbar.Item',
|
|
612
|
+
'Navbar.Link',
|
|
613
|
+
]);
|
|
614
|
+
/** The `type` values a <button> keeps under `buttonType`. */
|
|
615
|
+
const BUTTON_TYPES = ['button', 'submit', 'reset'];
|
|
616
|
+
/**
|
|
617
|
+
* Flag a <button> that submitted its form in the source and will not once
|
|
618
|
+
* migrated. Only where the element is known to be a <button> and its `type`
|
|
619
|
+
* is known: a dynamic `type` may hold any value, and a spread may carry one,
|
|
620
|
+
* and either is the author's to know. A spread decides only when nothing
|
|
621
|
+
* literal follows it, since JSX applies attributes last-write-wins, so a
|
|
622
|
+
* literal `type` written after every spread is the one that renders.
|
|
623
|
+
*/
|
|
624
|
+
function flagButtonType(ctx, path, element, target, rendered) {
|
|
625
|
+
if (rendered !== 'button' || !TYPES_ITS_BUTTON.has(target))
|
|
626
|
+
return;
|
|
627
|
+
let attr;
|
|
628
|
+
let spreadWins = false;
|
|
629
|
+
for (const a of element.openingElement.attributes) {
|
|
630
|
+
if (a.type === 'JSXSpreadAttribute')
|
|
631
|
+
spreadWins = true;
|
|
632
|
+
else if (a.name.name === 'type') {
|
|
633
|
+
attr = a;
|
|
634
|
+
spreadWins = false;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
if (spreadWins)
|
|
638
|
+
return;
|
|
639
|
+
if (attr) {
|
|
640
|
+
const literal = literalValueOf(attr);
|
|
641
|
+
if (literal.kind !== 'string' || BUTTON_TYPES.includes(literal.value)) {
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
addTodo(ctx, path, 'prop:type', `bestax \`${target}\` writes \`type="button"\` on its <button> ${attr ? 'in place of a `type` HTML does not define' : 'when none is given'}, so it no longer submits the form around it the way a plain <button> does -- add \`type="submit"\` if this one should`);
|
|
646
|
+
ctx.dirty = true;
|
|
647
|
+
}
|
|
595
648
|
/**
|
|
596
649
|
* The `as` attribute only if no spread can overwrite it. `findAttr` reads by
|
|
597
650
|
* name and knows nothing about `{...rest}`, which JSX applies last-write-wins.
|
|
@@ -677,6 +730,7 @@ spreadCanCarryAs = false) {
|
|
|
677
730
|
? undefined
|
|
678
731
|
: HREF_OK[target];
|
|
679
732
|
dropInertLinkAttrs(ctx, path, element, target, rendered);
|
|
733
|
+
flagButtonType(ctx, path, element, target, rendered);
|
|
680
734
|
restrictAsValue(ctx, path, element, target, attr, literal);
|
|
681
735
|
// Only now, and only if something element-dependent actually survived. The
|
|
682
736
|
// first version fired on every `as` beside a spread -- `<Title as="h2"
|
|
@@ -49,7 +49,7 @@ export interface Modifier {
|
|
|
49
49
|
* - `mapped`: converts to `target`.
|
|
50
50
|
* - `todo`: bestax has a component, but the markup does not map element by
|
|
51
51
|
* element yet; the family's outermost class gets a TODO.
|
|
52
|
-
* - `plain`: valid Bulma
|
|
52
|
+
* - `plain`: valid Bulma, left alone with no TODO.
|
|
53
53
|
* - `fold`: a wrapper the `target` renders itself from a prop, so the element
|
|
54
54
|
* folds into the one `target` inside it (`.table-container` into
|
|
55
55
|
* `Table isResponsive`).
|
|
@@ -250,8 +250,22 @@ export interface RootEntry {
|
|
|
250
250
|
* and each `.icon` converts on its own; they go.
|
|
251
251
|
*/
|
|
252
252
|
readonly buildsIcons?: boolean;
|
|
253
|
+
/**
|
|
254
|
+
* The target renders the whole `.file` tree from props (`File`): its
|
|
255
|
+
* `<input>`, button text, icons and file name. The element converts only
|
|
256
|
+
* when its tree is exactly that one, and only inside a `Field`, since
|
|
257
|
+
* outside one the target renders a `.field` of its own around it.
|
|
258
|
+
*/
|
|
259
|
+
readonly buildsFile?: boolean;
|
|
253
260
|
/** The target takes no helper props, so every helper class stays a class. */
|
|
254
261
|
readonly noHelpers?: boolean;
|
|
262
|
+
/**
|
|
263
|
+
* Helper props the target does not take as helpers, each with why, so their
|
|
264
|
+
* classes stay classes: its props type leaves the helper out, or a prop of
|
|
265
|
+
* its own by that name renders something else (`Columns`' `gap` is its
|
|
266
|
+
* gutter). The reason is for the MCP lookup.
|
|
267
|
+
*/
|
|
268
|
+
readonly helpersLeftOut?: Readonly<Record<string, string>>;
|
|
255
269
|
/**
|
|
256
270
|
* Tags the target doesn't render, on which the element is valid Bulma that
|
|
257
271
|
* bestax renders some other way, so it stays markup with no `tag` TODO
|
|
@@ -305,6 +319,13 @@ export declare const ALIGN_CONTENTS: readonly ["flex-start", "flex-end", "center
|
|
|
305
319
|
export declare const ALIGN_ITEMS: readonly ["stretch", "flex-start", "flex-end", "center", "baseline", "start", "end"];
|
|
306
320
|
export declare const ALIGN_SELFS: readonly ["auto", "flex-start", "flex-end", "center", "baseline", "stretch"];
|
|
307
321
|
export declare const FLEX_GROW_SHRINK: readonly ["0", "1", "2", "3", "4", "5"];
|
|
322
|
+
/** Bulma's gap scale, whole and half steps, as the gap props take it. */
|
|
323
|
+
export declare const GAPS: readonly ["0", "0.5", "1", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", "5", "5.5", "6", "6.5", "7", "7.5", "8"];
|
|
324
|
+
export declare const POSITIONS: readonly ["absolute", "fixed", "relative", "static", "sticky"];
|
|
325
|
+
/** The CSS keywords `overflow`, `overflowX` and `overflowY` take. */
|
|
326
|
+
export declare const AXIS_OVERFLOWS: readonly ["auto", "clip", "hidden", "scroll", "visible"];
|
|
327
|
+
export declare const RADII: readonly ["radiusless", "small", "normal", "large", "rounded"];
|
|
328
|
+
export declare const ASPECT_RATIOS: readonly ["1by1", "5by4", "4by3", "3by2", "5by3", "16by9", "2by1", "3by1", "4by5", "3by4", "2by3", "3by5", "9by16", "1by2", "1by3"];
|
|
308
329
|
export declare const VIEWPORTS: readonly ["mobile", "tablet", "tablet-only", "touch", "desktop", "desktop-only", "widescreen", "widescreen-only", "fullhd"];
|
|
309
330
|
/** `tablet-only` → `TabletOnly`: the suffix bestax puts on per-viewport props. */
|
|
310
331
|
export declare function viewportSuffix(viewport: string): string;
|
|
@@ -342,9 +363,12 @@ export declare const LEGACY_09: Readonly<Record<string, string>>;
|
|
|
342
363
|
/**
|
|
343
364
|
* `text-color` and `background` resolve to a per-target prop (`RootEntry`'s
|
|
344
365
|
* `textColor`/`bgColor`); `flex-container` only renders beside a flex
|
|
345
|
-
* `display`; `display` cannot mix a base value with per-viewport ones.
|
|
366
|
+
* `display`; `display` cannot mix a base value with per-viewport ones. In
|
|
367
|
+
* `gap`, `position` and `overflow`, one prop decides what another renders:
|
|
368
|
+
* a `gap` drops `gapless`, a `pos` drops `relative`, and beside an axis prop
|
|
369
|
+
* `overflow` is written per axis.
|
|
346
370
|
*/
|
|
347
|
-
export type HelperGroup = 'text-color' | 'background' | 'spacing' | 'typography' | 'display' | 'visibility' | 'flex-container' | 'flex-item' | 'other';
|
|
371
|
+
export type HelperGroup = 'text-color' | 'background' | 'spacing' | 'gap' | 'typography' | 'display' | 'visibility' | 'flex-container' | 'flex-item' | 'position' | 'overflow' | 'other';
|
|
348
372
|
export interface HelperToken {
|
|
349
373
|
readonly group: HelperGroup;
|
|
350
374
|
readonly write: PropWrite;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -114,6 +114,65 @@ export const ALIGN_SELFS = [
|
|
|
114
114
|
'stretch',
|
|
115
115
|
];
|
|
116
116
|
export const FLEX_GROW_SHRINK = ['0', '1', '2', '3', '4', '5'];
|
|
117
|
+
/** Bulma's gap scale, whole and half steps, as the gap props take it. */
|
|
118
|
+
export const GAPS = [
|
|
119
|
+
'0',
|
|
120
|
+
'0.5',
|
|
121
|
+
'1',
|
|
122
|
+
'1.5',
|
|
123
|
+
'2',
|
|
124
|
+
'2.5',
|
|
125
|
+
'3',
|
|
126
|
+
'3.5',
|
|
127
|
+
'4',
|
|
128
|
+
'4.5',
|
|
129
|
+
'5',
|
|
130
|
+
'5.5',
|
|
131
|
+
'6',
|
|
132
|
+
'6.5',
|
|
133
|
+
'7',
|
|
134
|
+
'7.5',
|
|
135
|
+
'8',
|
|
136
|
+
];
|
|
137
|
+
export const POSITIONS = [
|
|
138
|
+
'absolute',
|
|
139
|
+
'fixed',
|
|
140
|
+
'relative',
|
|
141
|
+
'static',
|
|
142
|
+
'sticky',
|
|
143
|
+
];
|
|
144
|
+
/** The CSS keywords `overflow`, `overflowX` and `overflowY` take. */
|
|
145
|
+
export const AXIS_OVERFLOWS = [
|
|
146
|
+
'auto',
|
|
147
|
+
'clip',
|
|
148
|
+
'hidden',
|
|
149
|
+
'scroll',
|
|
150
|
+
'visible',
|
|
151
|
+
];
|
|
152
|
+
export const RADII = [
|
|
153
|
+
'radiusless',
|
|
154
|
+
'small',
|
|
155
|
+
'normal',
|
|
156
|
+
'large',
|
|
157
|
+
'rounded',
|
|
158
|
+
];
|
|
159
|
+
export const ASPECT_RATIOS = [
|
|
160
|
+
'1by1',
|
|
161
|
+
'5by4',
|
|
162
|
+
'4by3',
|
|
163
|
+
'3by2',
|
|
164
|
+
'5by3',
|
|
165
|
+
'16by9',
|
|
166
|
+
'2by1',
|
|
167
|
+
'3by1',
|
|
168
|
+
'4by5',
|
|
169
|
+
'3by4',
|
|
170
|
+
'2by3',
|
|
171
|
+
'3by5',
|
|
172
|
+
'9by16',
|
|
173
|
+
'1by2',
|
|
174
|
+
'1by3',
|
|
175
|
+
];
|
|
117
176
|
export const VIEWPORTS = [
|
|
118
177
|
'mobile',
|
|
119
178
|
'tablet',
|
|
@@ -146,8 +205,6 @@ const COMPONENT_COLORS = [
|
|
|
146
205
|
'light',
|
|
147
206
|
'dark',
|
|
148
207
|
];
|
|
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'];
|
|
151
208
|
const COLUMN_SIZES = [
|
|
152
209
|
'1',
|
|
153
210
|
'2',
|
|
@@ -211,6 +268,8 @@ const BASE = {
|
|
|
211
268
|
textColor: 'textColor',
|
|
212
269
|
bgColor: 'bgColor',
|
|
213
270
|
};
|
|
271
|
+
/** Why the column and row gap helpers stay classes on a `.columns`. */
|
|
272
|
+
const COLUMNS_AXIS_GAPS = 'bestax `Columns` leaves the column and row gap helpers out: the gutter is padding inside each column, which CSS `gap` would add to';
|
|
214
273
|
// ---- Roots ------------------------------------------------------------------
|
|
215
274
|
export const ROOTS = {
|
|
216
275
|
block: {
|
|
@@ -387,6 +446,13 @@ export const ROOTS = {
|
|
|
387
446
|
target: 'Card.Header.Icon',
|
|
388
447
|
tag: 'button',
|
|
389
448
|
defaults: { 'aria-label': 'more options' },
|
|
449
|
+
writesAttr: {
|
|
450
|
+
type: {
|
|
451
|
+
on: ['button'],
|
|
452
|
+
fallback: 'button',
|
|
453
|
+
keeps: ['button', 'submit', 'reset'],
|
|
454
|
+
},
|
|
455
|
+
},
|
|
390
456
|
ownProps: ['color', 'bgColor', 'textColor'],
|
|
391
457
|
},
|
|
392
458
|
'card-image': {
|
|
@@ -486,6 +552,11 @@ export const ROOTS = {
|
|
|
486
552
|
'gapSizeWidescreen',
|
|
487
553
|
'gapSizeFullhd',
|
|
488
554
|
],
|
|
555
|
+
helpersLeftOut: {
|
|
556
|
+
gap: "bestax `Columns`' own `gap` is the columns gutter (`is-<value>`), not the gap helper",
|
|
557
|
+
columnGap: COLUMNS_AXIS_GAPS,
|
|
558
|
+
rowGap: COLUMNS_AXIS_GAPS,
|
|
559
|
+
},
|
|
489
560
|
},
|
|
490
561
|
column: {
|
|
491
562
|
...BASE,
|
|
@@ -528,8 +599,9 @@ export const ROOTS = {
|
|
|
528
599
|
'isNarrowFullhd',
|
|
529
600
|
],
|
|
530
601
|
},
|
|
531
|
-
// Grid's gaps take a numeric string, but its column
|
|
532
|
-
// placement are typed as numbers.
|
|
602
|
+
// Grid's gaps take a numeric string, half steps included, but its column
|
|
603
|
+
// minimum and every Cell placement are typed as numbers. Its gap props are
|
|
604
|
+
// its own, and render the same classes as the gap helpers.
|
|
533
605
|
grid: {
|
|
534
606
|
...BASE,
|
|
535
607
|
target: 'Grid',
|
|
@@ -1021,6 +1093,13 @@ export const ROOTS = {
|
|
|
1021
1093
|
tag: 'a',
|
|
1022
1094
|
as: 'any',
|
|
1023
1095
|
modifiers: flags({ 'is-active': 'active' }),
|
|
1096
|
+
writesAttr: {
|
|
1097
|
+
type: {
|
|
1098
|
+
on: ['button'],
|
|
1099
|
+
fallback: 'button',
|
|
1100
|
+
keeps: ['button', 'submit', 'reset'],
|
|
1101
|
+
},
|
|
1102
|
+
},
|
|
1024
1103
|
ownProps: ['as', 'active', 'textColor', 'bgColor'],
|
|
1025
1104
|
},
|
|
1026
1105
|
'navbar-dropdown': {
|
|
@@ -1218,7 +1297,59 @@ export const ROOTS = {
|
|
|
1218
1297
|
checkboxes: todo('Checkboxes', 'bestax `Checkboxes` renders its own `.field` and `.control` wrappers'),
|
|
1219
1298
|
radio: todo('Radio', "bestax `Radio` renders its own styled markup, not Bulma's"),
|
|
1220
1299
|
radios: todo('Radios', 'bestax `Radios` renders its own `.field` and `.control` wrappers'),
|
|
1221
|
-
|
|
1300
|
+
// `File` renders the whole `.file` tree from props, and puts the
|
|
1301
|
+
// attributes it's given on its `<input>`. `color` renders `has-text-<color>`
|
|
1302
|
+
// too, so a color stays a class, and `isCentered` renders nothing beside
|
|
1303
|
+
// `isRight`.
|
|
1304
|
+
file: {
|
|
1305
|
+
...BASE,
|
|
1306
|
+
target: 'File',
|
|
1307
|
+
tag: 'div',
|
|
1308
|
+
textColor: null,
|
|
1309
|
+
bgColor: 'backgroundColor',
|
|
1310
|
+
modifiers: {
|
|
1311
|
+
...tokens('is-', ['small', 'medium', 'large'], 'size'),
|
|
1312
|
+
...flags({
|
|
1313
|
+
'is-boxed': 'isBoxed',
|
|
1314
|
+
'is-fullwidth': 'isFullwidth',
|
|
1315
|
+
'is-right': 'isRight',
|
|
1316
|
+
}),
|
|
1317
|
+
// `File` renders `{hasName && fileName && …}`, so a condition handed to
|
|
1318
|
+
// it as it is would render a falsy number (`0`) as text.
|
|
1319
|
+
'has-name': { writes: [{ prop: 'hasName' }], onlyTrue: true },
|
|
1320
|
+
},
|
|
1321
|
+
omits: {
|
|
1322
|
+
...Object.fromEntries(COMPONENT_COLORS.map(color => [
|
|
1323
|
+
`is-${color}`,
|
|
1324
|
+
'`color` renders `has-text-<color>` on the `.file` as well',
|
|
1325
|
+
])),
|
|
1326
|
+
'is-centered': '`isCentered` renders nothing beside `isRight`',
|
|
1327
|
+
},
|
|
1328
|
+
buildsFile: true,
|
|
1329
|
+
ownProps: [
|
|
1330
|
+
'label',
|
|
1331
|
+
'labelSize',
|
|
1332
|
+
'labelProps',
|
|
1333
|
+
'horizontal',
|
|
1334
|
+
'message',
|
|
1335
|
+
'messageColor',
|
|
1336
|
+
'fieldClassName',
|
|
1337
|
+
'color',
|
|
1338
|
+
'size',
|
|
1339
|
+
'isBoxed',
|
|
1340
|
+
'isFullwidth',
|
|
1341
|
+
'isFullWidth',
|
|
1342
|
+
'isRight',
|
|
1343
|
+
'isCentered',
|
|
1344
|
+
'hasName',
|
|
1345
|
+
'buttonLabel',
|
|
1346
|
+
'iconLeft',
|
|
1347
|
+
'iconRight',
|
|
1348
|
+
'inputClassName',
|
|
1349
|
+
'fileName',
|
|
1350
|
+
],
|
|
1351
|
+
passThrough: ['ref'],
|
|
1352
|
+
},
|
|
1222
1353
|
'file-label': part(),
|
|
1223
1354
|
'file-input': part(),
|
|
1224
1355
|
'file-cta': part(),
|
|
@@ -1654,12 +1785,12 @@ export const ROOTS = {
|
|
|
1654
1785
|
'has-auto-count': set('fixedCols', 'auto'),
|
|
1655
1786
|
},
|
|
1656
1787
|
},
|
|
1657
|
-
// ---- Valid Bulma,
|
|
1658
|
-
// The other sources emit these on purpose
|
|
1788
|
+
// ---- Valid Bulma, left as markup ---------------------------------------------
|
|
1789
|
+
// The other sources emit these on purpose.
|
|
1659
1790
|
help: plain('bestax renders `.help` only inside its form controls'),
|
|
1660
1791
|
'panel-list': plain('nothing in bestax renders `.panel-list`'),
|
|
1661
1792
|
label: plain('bestax renders `.label` only inside its form controls'),
|
|
1662
|
-
loader: plain("bestax `
|
|
1793
|
+
loader: plain("bestax's `Loader` draws the same ring; swap it in by hand for its progressbar role and accessible name"),
|
|
1663
1794
|
'hero-buttons': plain('a layout class inside `.hero`; bestax has no part for it'),
|
|
1664
1795
|
'hero-video': plain('a layout class inside `.hero`; bestax has no part for it'),
|
|
1665
1796
|
'navbar-content': plain('a layout class inside `.navbar`; bestax has no part for it'),
|
|
@@ -1788,6 +1919,7 @@ export const FORWARDS_REF = [
|
|
|
1788
1919
|
'InputBase',
|
|
1789
1920
|
'TextAreaBase',
|
|
1790
1921
|
'SelectBase',
|
|
1922
|
+
'File',
|
|
1791
1923
|
];
|
|
1792
1924
|
/**
|
|
1793
1925
|
* Plain tags bestax wraps, for an element with helper classes and no root
|
|
@@ -1880,11 +2012,20 @@ export const HELPER_TOKENS = new Map([
|
|
|
1880
2012
|
...helperTokens('flex-item', 'is-align-self-', ALIGN_SELFS, 'alignSelf'),
|
|
1881
2013
|
...helperTokens('flex-item', 'is-flex-grow-', FLEX_GROW_SHRINK, 'flexGrow'),
|
|
1882
2014
|
...helperTokens('flex-item', 'is-flex-shrink-', FLEX_GROW_SHRINK, 'flexShrink'),
|
|
1883
|
-
...helperTokens('
|
|
2015
|
+
...helperTokens('gap', 'is-gap-', GAPS, 'gap'),
|
|
2016
|
+
...helperTokens('gap', 'is-column-gap-', GAPS, 'columnGap'),
|
|
2017
|
+
...helperTokens('gap', 'is-row-gap-', GAPS, 'rowGap'),
|
|
2018
|
+
helperFlag('gap', 'is-gapless', 'gapless'),
|
|
2019
|
+
...helperTokens('position', 'is-position-', POSITIONS, 'pos'),
|
|
2020
|
+
helperFlag('position', 'is-relative', 'relative'),
|
|
1884
2021
|
[
|
|
1885
2022
|
'is-clipped',
|
|
1886
|
-
{ group: '
|
|
2023
|
+
{ group: 'overflow', write: { prop: 'overflow', value: 'clipped' } },
|
|
1887
2024
|
],
|
|
2025
|
+
...helperTokens('overflow', 'is-overflow-', AXIS_OVERFLOWS, 'overflow'),
|
|
2026
|
+
...helperTokens('overflow', 'is-overflow-x-', AXIS_OVERFLOWS, 'overflowX'),
|
|
2027
|
+
...helperTokens('overflow', 'is-overflow-y-', AXIS_OVERFLOWS, 'overflowY'),
|
|
2028
|
+
...helperTokens('other', 'is-pulled-', ['left', 'right'], 'float'),
|
|
1888
2029
|
helperFlag('other', 'is-overlay', 'overlay'),
|
|
1889
2030
|
[
|
|
1890
2031
|
'is-unselectable',
|
|
@@ -1898,6 +2039,7 @@ export const HELPER_TOKENS = new Map([
|
|
|
1898
2039
|
'is-radiusless',
|
|
1899
2040
|
{ group: 'other', write: { prop: 'radius', value: 'radiusless' } },
|
|
1900
2041
|
],
|
|
2042
|
+
...helperTokens('other', 'has-radius-', RADII.filter(radius => radius !== 'radiusless'), 'radius'),
|
|
1901
2043
|
[
|
|
1902
2044
|
'is-shadowless',
|
|
1903
2045
|
{ group: 'other', write: { prop: 'shadow', value: 'shadowless' } },
|
|
@@ -1905,7 +2047,7 @@ export const HELPER_TOKENS = new Map([
|
|
|
1905
2047
|
...helperTokens('other', 'is-', ['mobile', 'narrow'], 'responsive'),
|
|
1906
2048
|
helperFlag('other', 'is-skeleton', 'skeleton'),
|
|
1907
2049
|
helperFlag('other', 'is-clearfix', 'clearfix'),
|
|
1908
|
-
|
|
2050
|
+
...helperTokens('other', 'is-aspect-ratio-', ASPECT_RATIOS, 'aspectRatio'),
|
|
1909
2051
|
]);
|
|
1910
2052
|
/** Every helper prop name, for the attribute-collision check. */
|
|
1911
2053
|
export const HELPER_PROPS = new Set([
|
|
@@ -1936,7 +2078,8 @@ export const PASSTHROUGH = [
|
|
|
1936
2078
|
},
|
|
1937
2079
|
{
|
|
1938
2080
|
why: 'a Grid or Cell class, which converts only on its own `.grid` or `.cell`, and only where bestax has a prop for it',
|
|
1939
|
-
|
|
2081
|
+
// `is-row-gap-*` is a gap helper.
|
|
2082
|
+
match: /^(?:is-(?:col|row)-(?!gap-).+|is-auto-fill)$/,
|
|
1940
2083
|
},
|
|
1941
2084
|
{
|
|
1942
2085
|
why: 'a `.fixed-grid` column count, which converts only on its own `.fixed-grid`',
|
|
@@ -1944,11 +2087,11 @@ export const PASSTHROUGH = [
|
|
|
1944
2087
|
},
|
|
1945
2088
|
{
|
|
1946
2089
|
why: 'an `.image` modifier, which converts only on its own `.image`, and only where bestax has a prop for it',
|
|
1947
|
-
match: /^(?:is-\d+by\d+|is-\d+x\d+|is-square|
|
|
2090
|
+
match: /^(?:is-\d+by\d+|is-\d+x\d+|is-square|has-ratio)$/,
|
|
1948
2091
|
},
|
|
1949
2092
|
{
|
|
1950
2093
|
why: 'a Bulma helper with no bestax prop',
|
|
1951
|
-
match: /^(?:is-display-.+|is-visibility-.+|is-
|
|
2094
|
+
match: /^(?:is-display-.+|is-visibility-.+|is-float-.+|is-clear-.+|has-text-weight-extrabold|is-align-content-(?:baseline|start|end)|is-align-items-self-(?:start|end)|is-offset-0(?:-[a-z]+)?)$/,
|
|
1952
2095
|
},
|
|
1953
2096
|
{
|
|
1954
2097
|
why: 'a `.breadcrumb` separator, which converts only on its own `.breadcrumb`',
|
|
@@ -129,6 +129,13 @@ export interface ChildFacts {
|
|
|
129
129
|
becomes?: Conversion;
|
|
130
130
|
soleChild?: ChildFacts;
|
|
131
131
|
text?: string;
|
|
132
|
+
/**
|
|
133
|
+
* Its own `childElements`, read the same way, and whether its content is
|
|
134
|
+
* static: text and elements only, at least one of them rendered. What an
|
|
135
|
+
* entry that `buildsFile` reads, down the tree.
|
|
136
|
+
*/
|
|
137
|
+
children?: readonly ChildFacts[];
|
|
138
|
+
staticContent?: boolean;
|
|
132
139
|
}
|
|
133
140
|
export interface Todo {
|
|
134
141
|
rule: string;
|
|
@@ -188,7 +195,38 @@ export interface Conversion {
|
|
|
188
195
|
* has a text, which becomes its children.
|
|
189
196
|
*/
|
|
190
197
|
icons?: BuiltIcon[];
|
|
198
|
+
/**
|
|
199
|
+
* The target renders the element's whole tree from props (`File`): the
|
|
200
|
+
* `<input>`'s attributes join the element's, and the parts below become
|
|
201
|
+
* props. The tree goes, and the element closes itself.
|
|
202
|
+
*/
|
|
203
|
+
file?: BuiltFile;
|
|
191
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* The `.file` tree a target that `buildsFile` renders from props. The one
|
|
207
|
+
* child of the element is its `.file-label` <label>, holding the <input>,
|
|
208
|
+
* the `.file-cta` and at most one `.file-name`.
|
|
209
|
+
*/
|
|
210
|
+
export interface BuiltFile {
|
|
211
|
+
/** The <input>'s classes but `file-input`, as `inputClassName`, or null. */
|
|
212
|
+
inputClassName: string | null;
|
|
213
|
+
/**
|
|
214
|
+
* Which of the `.file-cta`'s children holds the button text, when it isn't
|
|
215
|
+
* the text the target renders by default.
|
|
216
|
+
*/
|
|
217
|
+
buttonLabel?: number;
|
|
218
|
+
/** Which of them holds the icon before that text, and after it. */
|
|
219
|
+
iconLeft?: number;
|
|
220
|
+
iconRight?: number;
|
|
221
|
+
/** The `.file-name`'s text. */
|
|
222
|
+
fileName?: string;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Why a target that `buildsFile` stays markup outside a `Field`, for the
|
|
226
|
+
* planner here and for the transform, which can see whether the `.field`
|
|
227
|
+
* around it converts.
|
|
228
|
+
*/
|
|
229
|
+
export declare function fileContextTodo(target: string): Todo;
|
|
192
230
|
/** One icon a target that `buildsIcons` builds from props. */
|
|
193
231
|
export interface BuiltIcon {
|
|
194
232
|
/** Which of the element's `childElements` its `.icon` is. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAoBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,EAAE,CAAC;IAC7C;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B;;;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;;;OAGG;IACH,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB;;;;OAIG;IACH,aAAa,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACtC,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;;;OAGG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,WAAW,CAAC,EAAE,UAAU,CAAC;IACzB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAAC;IAClC;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IAC/D,SAAS,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;;OAIG;IACH,OAAO,CAAC,EAAE,UAAU,CAAC;IACrB,SAAS,CAAC,EAAE,UAAU,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,6 +12,19 @@
|
|
|
12
12
|
import { FORWARDS_REF, HELPER_PROPS, HELPER_TOKENS, inTagSet, legacyHint, modifierFor, numberAttrsOf, placedFor, PRECEDENCE, rootFor, WRAPPER_OWN_PROPS, wrapperFor, } from './class-map.js';
|
|
13
13
|
import { readGlyph } from './glyph.js';
|
|
14
14
|
import { ruleId } from './rules.js';
|
|
15
|
+
/** The button text `File` renders when it's given none. */
|
|
16
|
+
const DEFAULT_FILE_LABEL = 'Choose a file\u2026';
|
|
17
|
+
/**
|
|
18
|
+
* Why a target that `buildsFile` stays markup outside a `Field`, for the
|
|
19
|
+
* planner here and for the transform, which can see whether the `.field`
|
|
20
|
+
* around it converts.
|
|
21
|
+
*/
|
|
22
|
+
export function fileContextTodo(target) {
|
|
23
|
+
return {
|
|
24
|
+
rule: ruleId('context', target),
|
|
25
|
+
message: `bestax \`${target}\` renders a \`.field\` of its own around the \`.file\` unless it sits inside a \`Field\`, and nothing around this element is one or becomes one here; keep it as markup, or convert the \`.field\` around it, then re-run`,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
15
28
|
function wrapperEntry(tag) {
|
|
16
29
|
const target = wrapperFor(tag);
|
|
17
30
|
if (!target)
|
|
@@ -114,6 +127,16 @@ export function plan(facts) {
|
|
|
114
127
|
if (facts.hasSpread) {
|
|
115
128
|
return refuse('spread', target, `this element spreads props, which bestax \`${target}\` may read differently than the element did (a spread \`className\` merges with its classes instead of replacing them); convert it to \`${target}\` by hand`);
|
|
116
129
|
}
|
|
130
|
+
if (entry.buildsFile) {
|
|
131
|
+
const own = [...facts.attributes.keys()].find(name => name !== 'key');
|
|
132
|
+
if (own) {
|
|
133
|
+
return refuse('attr', own, `bestax \`${target}\` puts the attributes it's given on its <input>, so this element's \`${own}\` would move there; move it onto the <input> if that's what you want, then re-run`);
|
|
134
|
+
}
|
|
135
|
+
if (!facts.bestaxAround?.includes('Field') &&
|
|
136
|
+
!facts.classesAround?.includes('field')) {
|
|
137
|
+
return { conversion: null, todos: [...todos, fileContextTodo(target)] };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
117
140
|
if (facts.hasRef && !FORWARDS_REF.includes(target)) {
|
|
118
141
|
return refuse('ref', target, `bestax \`${target}\` does not forward refs, so this \`ref\` would stop reaching the DOM node; keep this element as markup`);
|
|
119
142
|
}
|
|
@@ -324,6 +347,14 @@ export function plan(facts) {
|
|
|
324
347
|
return refuse('children', target, built.why);
|
|
325
348
|
icons = built.icons;
|
|
326
349
|
}
|
|
350
|
+
let file;
|
|
351
|
+
if (entry.buildsFile) {
|
|
352
|
+
const built = buildFile(facts.childElements, entry, writes.has('hasName'));
|
|
353
|
+
if ('why' in built)
|
|
354
|
+
return refuse(built.kind, built.token, built.why);
|
|
355
|
+
file = built.file;
|
|
356
|
+
numbers.push(...built.numbers);
|
|
357
|
+
}
|
|
327
358
|
const props = [];
|
|
328
359
|
if (as)
|
|
329
360
|
props.push(['as', as]);
|
|
@@ -388,10 +419,91 @@ export function plan(facts) {
|
|
|
388
419
|
...(parent ? { replacesParent: true } : {}),
|
|
389
420
|
...(conditional.length > 0 ? { conditional } : {}),
|
|
390
421
|
...(icons ? { icons } : {}),
|
|
422
|
+
...(file ? { file } : {}),
|
|
391
423
|
},
|
|
392
424
|
todos,
|
|
393
425
|
};
|
|
394
426
|
}
|
|
427
|
+
/**
|
|
428
|
+
* The tree a target that `buildsFile` renders from props, read from an
|
|
429
|
+
* element's children: exactly the one it renders, with static content where
|
|
430
|
+
* it takes a prop. The <input>'s attributes become the target's, so one it
|
|
431
|
+
* reads as a prop of its own refuses.
|
|
432
|
+
*/
|
|
433
|
+
function buildFile(children, entry, hasName) {
|
|
434
|
+
const target = entry.target;
|
|
435
|
+
const shape = {
|
|
436
|
+
kind: 'children',
|
|
437
|
+
token: target,
|
|
438
|
+
why: `bestax \`${target}\` renders the whole \`.file\` tree itself, so this converts only when its tree is the one it renders: one bare \`.file-label\` <label> holding a \`.file-input\` <input type="file">, a bare \`.file-cta\` <span> with a bare \`.file-label\` <span> of static content and at most one bare \`.file-icon\` <span> of static content on each side of it, and, with \`has-name\`, at most one bare \`.file-name\` <span> of static text; keep it as markup, or convert it by hand`,
|
|
439
|
+
};
|
|
440
|
+
const bare = (child, tag, token) => child?.tag === tag &&
|
|
441
|
+
child.tokens?.length === 1 &&
|
|
442
|
+
child.tokens[0] === token &&
|
|
443
|
+
child.attributes.size === 0 &&
|
|
444
|
+
!child.hasSpread;
|
|
445
|
+
const [label, ...beside] = children ?? [];
|
|
446
|
+
if (beside.length > 0 || !bare(label, 'label', 'file-label'))
|
|
447
|
+
return shape;
|
|
448
|
+
const [input, cta, name, ...more] = label.children ?? [];
|
|
449
|
+
if (more.length > 0 ||
|
|
450
|
+
input?.tag !== 'input' ||
|
|
451
|
+
!input.tokens?.includes('file-input') ||
|
|
452
|
+
input.attributes.get('type') !== 'file' ||
|
|
453
|
+
input.attributes.has('key') ||
|
|
454
|
+
input.hasSpread ||
|
|
455
|
+
!bare(cta, 'span', 'file-cta')) {
|
|
456
|
+
return shape;
|
|
457
|
+
}
|
|
458
|
+
const parts = cta.children ?? [];
|
|
459
|
+
const at = parts.findIndex(part => bare(part, 'span', 'file-label'));
|
|
460
|
+
const icons = parts.filter((_, index) => index !== at);
|
|
461
|
+
if (at === -1 ||
|
|
462
|
+
at > 1 ||
|
|
463
|
+
parts.length - at > 2 ||
|
|
464
|
+
!parts[at].staticContent ||
|
|
465
|
+
!icons.every(icon => bare(icon, 'span', 'file-icon') && icon.staticContent)) {
|
|
466
|
+
return shape;
|
|
467
|
+
}
|
|
468
|
+
if (name && !(hasName && bare(name, 'span', 'file-name') && name.text)) {
|
|
469
|
+
return shape;
|
|
470
|
+
}
|
|
471
|
+
const numbers = [];
|
|
472
|
+
for (const [attribute, value] of input.attributes) {
|
|
473
|
+
if (attribute === 'type')
|
|
474
|
+
continue;
|
|
475
|
+
if (entry.ownProps?.includes(attribute) || HELPER_PROPS.has(attribute)) {
|
|
476
|
+
return {
|
|
477
|
+
kind: 'attr',
|
|
478
|
+
token: attribute,
|
|
479
|
+
why: `bestax \`${target}\` takes the <input>'s attributes as its own props, and \`${attribute}\` is one it reads differently; rename or drop the attribute, then re-run`,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
if (!numberAttrsOf(entry).includes(attribute))
|
|
483
|
+
continue;
|
|
484
|
+
if (typeof value !== 'string')
|
|
485
|
+
continue;
|
|
486
|
+
if (!/^-?\d+(?:\.\d+)?$/.test(value) || String(Number(value)) !== value) {
|
|
487
|
+
return {
|
|
488
|
+
kind: 'attr',
|
|
489
|
+
token: attribute,
|
|
490
|
+
why: `bestax \`${target}\` types \`${attribute}\` as a number, and \`${value}\` is not a number spelled the way it renders; keep this element as markup`,
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
numbers.push(attribute);
|
|
494
|
+
}
|
|
495
|
+
const inputClasses = input.tokens.filter(token => token !== 'file-input');
|
|
496
|
+
return {
|
|
497
|
+
file: {
|
|
498
|
+
inputClassName: inputClasses.length > 0 ? inputClasses.join(' ') : null,
|
|
499
|
+
...(parts[at].text !== DEFAULT_FILE_LABEL && { buttonLabel: at }),
|
|
500
|
+
...(at === 1 && { iconLeft: 0 }),
|
|
501
|
+
...(parts.length - at === 2 && { iconRight: at + 1 }),
|
|
502
|
+
...(name && { fileName: name.text }),
|
|
503
|
+
},
|
|
504
|
+
numbers,
|
|
505
|
+
};
|
|
506
|
+
}
|
|
395
507
|
/**
|
|
396
508
|
* The icons a target that `buildsIcons` builds from an element's children:
|
|
397
509
|
* each `.icon` that converts to `Icon` on its own and holds a glyph `Icon`
|
|
@@ -464,8 +576,8 @@ function buildIcons(children, target) {
|
|
|
464
576
|
* write, the classes that leave `className`, and the props written as
|
|
465
577
|
* numbers. The group rules apply, so a helper the target would drop (a
|
|
466
578
|
* base `display` beside a per-viewport one, a flex-container helper with no
|
|
467
|
-
* flex `display`) stays a class,
|
|
468
|
-
* attribute it needs.
|
|
579
|
+
* flex `display`, `gapless` beside a `gap`) stays a class, as does one it
|
|
580
|
+
* leaves out, and so does a modifier missing the attribute it needs.
|
|
469
581
|
*/
|
|
470
582
|
function propsFrom(entry, tokens, tag, root, attributes) {
|
|
471
583
|
const numbers = [];
|
|
@@ -506,6 +618,9 @@ function propsFrom(entry, tokens, tag, root, attributes) {
|
|
|
506
618
|
: helper.write.prop;
|
|
507
619
|
if (!prop || writes.has(prop))
|
|
508
620
|
continue;
|
|
621
|
+
if (entry.helpersLeftOut && Object.hasOwn(entry.helpersLeftOut, prop)) {
|
|
622
|
+
continue;
|
|
623
|
+
}
|
|
509
624
|
writes.set(prop, helper.write.value ?? true);
|
|
510
625
|
sourceOf.set(prop, token);
|
|
511
626
|
groupOf.set(prop, helper.group);
|
|
@@ -529,6 +644,18 @@ function propsFrom(entry, tokens, tag, root, attributes) {
|
|
|
529
644
|
undo(prop);
|
|
530
645
|
}
|
|
531
646
|
}
|
|
647
|
+
// Props one helper wrote that another drops (`groupOf` holds only what
|
|
648
|
+
// helpers wrote). A `gap` drops `gapless`, though `Grid`'s own `gap`, a
|
|
649
|
+
// modifier, does not; `pos` drops `relative`; and beside an axis prop,
|
|
650
|
+
// `overflow` is written per axis instead of as its own class.
|
|
651
|
+
if (groupOf.has('gap') && groupOf.has('gapless'))
|
|
652
|
+
undo('gapless');
|
|
653
|
+
if (groupOf.has('pos') && groupOf.has('relative'))
|
|
654
|
+
undo('relative');
|
|
655
|
+
if (groupOf.has('overflow') &&
|
|
656
|
+
(groupOf.has('overflowX') || groupOf.has('overflowY'))) {
|
|
657
|
+
undo('overflow');
|
|
658
|
+
}
|
|
532
659
|
return { writes, converted, numbers };
|
|
533
660
|
}
|
|
534
661
|
/** `a`, `a or b`, `a, b or c`, each in backticks. */
|
|
@@ -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;AA+6BvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA02BpB"}
|
|
@@ -21,7 +21,7 @@ import { addTodo, findAttr, forgetJsxParens, jsxNameParts, literalValueOf, makeA
|
|
|
21
21
|
import { collectBoundNames, makeReserve, prefersTabs, resolvesToBinding, } from '../_shared/imports.js';
|
|
22
22
|
import { rewriteStylesheetImports } from '../_shared/css-imports.js';
|
|
23
23
|
import { BESTAX, buildBestaxImport, placeBestaxImport, seedBestaxImport, } from '../_shared/bestax-import.js';
|
|
24
|
-
import { plan, } from './plan.js';
|
|
24
|
+
import { fileContextTodo, plan, } from './plan.js';
|
|
25
25
|
import { REACT_RUNTIMES, } from './project.js';
|
|
26
26
|
import { PLACED, placedFor, ROOTS, rootFor } from './class-map.js';
|
|
27
27
|
import { ruleId } from './rules.js';
|
|
@@ -711,6 +711,47 @@ function textChild(j, text) {
|
|
|
711
711
|
? j.jsxText(text)
|
|
712
712
|
: j.jsxExpressionContainer(j.stringLiteral(text));
|
|
713
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* A text as an attribute value: quoted when JSX reads it as written there,
|
|
716
|
+
* and as a string otherwise. A JSX attribute string has no escapes, so a
|
|
717
|
+
* quote would end it, a backslash would print doubled, and an `&` could be
|
|
718
|
+
* read as an entity.
|
|
719
|
+
*/
|
|
720
|
+
function textValue(j, text) {
|
|
721
|
+
return /^[^"&\\\r\n]*$/.test(text)
|
|
722
|
+
? j.stringLiteral(text)
|
|
723
|
+
: j.jsxExpressionContainer(j.stringLiteral(text));
|
|
724
|
+
}
|
|
725
|
+
/** Whether an element's content is text and elements only, and renders. */
|
|
726
|
+
function staticContent(element) {
|
|
727
|
+
const content = (element.children ?? []).filter(reachesReact);
|
|
728
|
+
return (content.length > 0 &&
|
|
729
|
+
content.every((child) => child.type === 'JSXText' ||
|
|
730
|
+
child.type === 'JSXElement' ||
|
|
731
|
+
child.type === 'JSXFragment' ||
|
|
732
|
+
(child.type === 'JSXExpressionContainer' &&
|
|
733
|
+
child.expression.type === 'StringLiteral' &&
|
|
734
|
+
child.expression.value !== '')));
|
|
735
|
+
}
|
|
736
|
+
/**
|
|
737
|
+
* An element's content as one prop value: its one element, or its text, or
|
|
738
|
+
* a fragment of them all, each text written as the string it renders.
|
|
739
|
+
*/
|
|
740
|
+
function contentValue(j, element) {
|
|
741
|
+
const content = (element.children ?? []).filter((child) => !dropped(child));
|
|
742
|
+
if (content.length === 1) {
|
|
743
|
+
const [only] = content;
|
|
744
|
+
if (only.type === 'JSXText') {
|
|
745
|
+
return textValue(j, jsxTextRenders(only.value));
|
|
746
|
+
}
|
|
747
|
+
if (only.type === 'JSXExpressionContainer')
|
|
748
|
+
return only;
|
|
749
|
+
return j.jsxExpressionContainer(only);
|
|
750
|
+
}
|
|
751
|
+
return j.jsxExpressionContainer(j.jsxFragment(j.jsxOpeningFragment(), j.jsxClosingFragment(), content.map((child) => child.type === 'JSXText'
|
|
752
|
+
? textChild(j, jsxTextRenders(child.value))
|
|
753
|
+
: child)));
|
|
754
|
+
}
|
|
714
755
|
function insideForeignContent(elementPath) {
|
|
715
756
|
let current = elementPath.parent;
|
|
716
757
|
while (current) {
|
|
@@ -943,6 +984,33 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
943
984
|
? root
|
|
944
985
|
: undefined;
|
|
945
986
|
};
|
|
987
|
+
/**
|
|
988
|
+
* What the planner reads of a child element, down its tree: what it
|
|
989
|
+
* converts to on its own (children are planned first), its only child,
|
|
990
|
+
* its text and whether its content is static, and its own children the
|
|
991
|
+
* same way. Each element is read once, since every element around it
|
|
992
|
+
* reads it again: a plan that changes afterwards forgets its reading.
|
|
993
|
+
*/
|
|
994
|
+
const readings = new Map();
|
|
995
|
+
const readChild = (child) => {
|
|
996
|
+
const known = readings.get(child);
|
|
997
|
+
if (known)
|
|
998
|
+
return known;
|
|
999
|
+
const becomes = planned.get(child)?.conversion;
|
|
1000
|
+
const only = soleChild(child);
|
|
1001
|
+
const inner = only && childFacts(only);
|
|
1002
|
+
const text = textOf(child);
|
|
1003
|
+
const children = childElementsOf(child, readChild);
|
|
1004
|
+
const reading = {
|
|
1005
|
+
...(becomes && { becomes }),
|
|
1006
|
+
...(inner && { soleChild: inner }),
|
|
1007
|
+
...(text !== undefined && { text }),
|
|
1008
|
+
...(children && { children }),
|
|
1009
|
+
...(staticContent(child) && { staticContent: true }),
|
|
1010
|
+
};
|
|
1011
|
+
readings.set(child, reading);
|
|
1012
|
+
return reading;
|
|
1013
|
+
};
|
|
946
1014
|
/** The element directly around this one, when this is its only child. */
|
|
947
1015
|
const holderOf = (elementPath) => {
|
|
948
1016
|
const up = elementPath.parent?.node;
|
|
@@ -982,17 +1050,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
982
1050
|
childTargets: childTargets(elementPath),
|
|
983
1051
|
soleChildTarget: planned.get(sole)?.conversion?.target,
|
|
984
1052
|
soleChild: sole && childFacts(sole),
|
|
985
|
-
childElements: childElementsOf(element,
|
|
986
|
-
const becomes = planned.get(child)?.conversion;
|
|
987
|
-
const only = soleChild(child);
|
|
988
|
-
const inner = only && childFacts(only);
|
|
989
|
-
const text = textOf(child);
|
|
990
|
-
return {
|
|
991
|
-
...(becomes && { becomes }),
|
|
992
|
-
...(inner && { soleChild: inner }),
|
|
993
|
-
...(text !== undefined && { text }),
|
|
994
|
-
};
|
|
995
|
-
}),
|
|
1053
|
+
childElements: childElementsOf(element, readChild),
|
|
996
1054
|
bestaxInside: bestaxInside.get(element) ?? [],
|
|
997
1055
|
bestaxAround: surrounding.bestax,
|
|
998
1056
|
componentsAround: surrounding.other,
|
|
@@ -1067,6 +1125,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
1067
1125
|
const node = inside[icon.index];
|
|
1068
1126
|
const own = { conversion: null, todos: planned.get(node).todos };
|
|
1069
1127
|
planned.set(node, own);
|
|
1128
|
+
readings.delete(node);
|
|
1070
1129
|
const at = elements.findIndex(found => found.path.node === node);
|
|
1071
1130
|
if (at === -1)
|
|
1072
1131
|
continue;
|
|
@@ -1121,6 +1180,30 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
1121
1180
|
found.converts = false;
|
|
1122
1181
|
planned.set(found.path.node, found.plan);
|
|
1123
1182
|
}
|
|
1183
|
+
// A target that renders a `.field` of its own outside a `Field` converts
|
|
1184
|
+
// only inside one: a bestax `Field` already around it, or a `.field`
|
|
1185
|
+
// around it that converts here.
|
|
1186
|
+
for (const found of elements) {
|
|
1187
|
+
const conversion = found.plan.conversion;
|
|
1188
|
+
if (!conversion?.file)
|
|
1189
|
+
continue;
|
|
1190
|
+
let inField = false;
|
|
1191
|
+
for (let up = found.path.parent; up && !inField; up = up.parent) {
|
|
1192
|
+
if (up.node?.type !== 'JSXElement')
|
|
1193
|
+
continue;
|
|
1194
|
+
inField =
|
|
1195
|
+
(bestaxTarget(up.node, up) ??
|
|
1196
|
+
planned.get(up.node)?.conversion?.target) === 'Field';
|
|
1197
|
+
}
|
|
1198
|
+
if (inField)
|
|
1199
|
+
continue;
|
|
1200
|
+
found.plan = {
|
|
1201
|
+
conversion: null,
|
|
1202
|
+
todos: [...found.plan.todos, fileContextTodo(conversion.target)],
|
|
1203
|
+
};
|
|
1204
|
+
found.converts = false;
|
|
1205
|
+
planned.set(found.path.node, found.plan);
|
|
1206
|
+
}
|
|
1124
1207
|
if (elements.length === 0)
|
|
1125
1208
|
return print();
|
|
1126
1209
|
// ---- 3. File-level gates ------------------------------------------------------
|
|
@@ -1264,6 +1347,62 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
1264
1347
|
name.comments = [...(name.comments ?? []), ...gone.map(afterTagName)];
|
|
1265
1348
|
}
|
|
1266
1349
|
}
|
|
1350
|
+
if (conversion.file) {
|
|
1351
|
+
// The target renders the whole tree from props: the <input>'s
|
|
1352
|
+
// attributes join the element's, the parts below become props, and
|
|
1353
|
+
// the tree goes, its comments moving to the name that stays.
|
|
1354
|
+
const built = conversion.file;
|
|
1355
|
+
const inside = (node) => (node.children ?? []).filter((child) => !dropped(child));
|
|
1356
|
+
const [label] = inside(element);
|
|
1357
|
+
const [input, cta, name] = inside(label);
|
|
1358
|
+
const parts = inside(cta);
|
|
1359
|
+
const given = (input.openingElement.attributes ?? []).filter((attr) => !['className', 'type'].includes(attributeName(attr)));
|
|
1360
|
+
const props = [...given];
|
|
1361
|
+
const prop = (key, value) => props.push(j.jsxAttribute(j.jsxIdentifier(key), value));
|
|
1362
|
+
if (built.inputClassName !== null) {
|
|
1363
|
+
prop('inputClassName', textValue(j, built.inputClassName));
|
|
1364
|
+
}
|
|
1365
|
+
for (const key of ['buttonLabel', 'iconLeft', 'iconRight']) {
|
|
1366
|
+
const index = built[key];
|
|
1367
|
+
if (index !== undefined)
|
|
1368
|
+
prop(key, contentValue(j, parts[index]));
|
|
1369
|
+
}
|
|
1370
|
+
if (built.fileName !== undefined) {
|
|
1371
|
+
prop('fileName', textValue(j, built.fileName));
|
|
1372
|
+
}
|
|
1373
|
+
element.openingElement.attributes = [
|
|
1374
|
+
...(element.openingElement.attributes ?? []),
|
|
1375
|
+
...props,
|
|
1376
|
+
];
|
|
1377
|
+
const commentChildren = (node) => (node.children ?? [])
|
|
1378
|
+
.filter((child) => child.type === 'JSXExpressionContainer' &&
|
|
1379
|
+
child.expression.type === 'JSXEmptyExpression')
|
|
1380
|
+
.flatMap((child) => commentsWithin(child));
|
|
1381
|
+
const moved = [
|
|
1382
|
+
...[label, input, cta, name, ...parts]
|
|
1383
|
+
.filter(Boolean)
|
|
1384
|
+
.flatMap((node) => [
|
|
1385
|
+
...(node.comments ?? []),
|
|
1386
|
+
...tagComments(node),
|
|
1387
|
+
]),
|
|
1388
|
+
...[label, cta, name, ...parts]
|
|
1389
|
+
.filter(Boolean)
|
|
1390
|
+
.flatMap((node) => node.openingElement.attributes ?? [])
|
|
1391
|
+
.flatMap((attr) => commentsWithin(attr)),
|
|
1392
|
+
...(input.openingElement.attributes ?? [])
|
|
1393
|
+
.filter((attr) => !given.includes(attr))
|
|
1394
|
+
.flatMap((attr) => commentsWithin(attr)),
|
|
1395
|
+
...[element, label, cta].flatMap(commentChildren),
|
|
1396
|
+
...[element.closingElement, element.closingElement?.name].flatMap((node) => node?.comments ?? []),
|
|
1397
|
+
];
|
|
1398
|
+
element.children = [];
|
|
1399
|
+
element.openingElement.selfClosing = true;
|
|
1400
|
+
element.closingElement = null;
|
|
1401
|
+
if (moved.length) {
|
|
1402
|
+
const tag = element.openingElement.name;
|
|
1403
|
+
tag.comments = [...(tag.comments ?? []), ...moved.map(afterTagName)];
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1267
1406
|
if (conversion.icons) {
|
|
1268
1407
|
// The target builds its children from props: one icon as `iconProps`,
|
|
1269
1408
|
// with its text as the children, or several as `items`. The children
|
|
@@ -128,7 +128,7 @@ export const MAPPING = {
|
|
|
128
128
|
},
|
|
129
129
|
forwardRefAs: {
|
|
130
130
|
status: 'todo',
|
|
131
|
-
todo: '`forwardRefAs` is rbx-internal and has no counterpart. bestax forwards a ref from the form controls, plus `Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `Link`, `LinkButton`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`, `Navbar.Item`, `Navbar.Link`, `Sidebar` and `Toast` — pass `ref` directly on those, though not on the `Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers, which forward none. Mind the `Navbar.Dropdown` collision: your rbx `Navbar.Dropdown` is the menu and becomes `Navbar.DropdownMenu`, which forwards no ref, while bestax `Navbar.Dropdown` — the container your `<Navbar.Item dropdown>` becomes — does. The rest, `Box` included, forward no ref: React 18 drops it with a warning, React 19 leaves it wherever the rest props go, so put the ref on a wrapping element you control',
|
|
131
|
+
todo: '`forwardRefAs` is rbx-internal and has no counterpart. bestax forwards a ref from the form controls, plus `Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`, `Navbar.Item`, `Navbar.Link`, `Sidebar` and `Toast` — pass `ref` directly on those, though not on the `Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers, which forward none. Mind the `Navbar.Dropdown` collision: your rbx `Navbar.Dropdown` is the menu and becomes `Navbar.DropdownMenu`, which forwards no ref, while bestax `Navbar.Dropdown` — the container your `<Navbar.Item dropdown>` becomes — does. The rest, `Box` included, forward no ref: React 18 drops it with a warning, React 19 leaves it wherever the rest props go, so put the ref on a wrapping element you control',
|
|
132
132
|
},
|
|
133
133
|
// ---- elements -----------------------------------------------------------
|
|
134
134
|
Block: { status: 'mapped', target: 'Block' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../src/sources/react-bulma-components/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOnE;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAgFtD,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAUhE,CAAC;AAIF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../src/sources/react-bulma-components/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAOnE;;;;GAIG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAgFtD,CAAC;AAEF,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAUhE,CAAC;AAIF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAuqBpD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAsEhD,CAAC;AAEF,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAM3E"}
|
|
@@ -26,7 +26,7 @@ export const UNIVERSAL_PROPS = {
|
|
|
26
26
|
todo: 'this bestax component has no `as` prop; restructure the element instead',
|
|
27
27
|
},
|
|
28
28
|
domRef: {
|
|
29
|
-
todo: 'bestax-bulma has no `domRef`. The form controls, plus `Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `Link`, `LinkButton`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`, `Navbar.Item`, `Navbar.Link`, `Sidebar` and `Toast` forward a ref — on those, rename `domRef` to `ref`, though not on the `Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers, which forward none. Mind the `Navbar.Dropdown` collision: the `Navbar.Item` that wrapped your dropdown became bestax `Navbar.Dropdown` and forwards one, while your `Navbar.Dropdown` became `Navbar.DropdownMenu` and does not. The rest forward no ref: React 18 drops it with a warning, React 19 leaves it wherever the rest props go, so put the ref on a DOM child or wrap the component',
|
|
29
|
+
todo: 'bestax-bulma has no `domRef`. The form controls, plus `Avatar`, `Button`, `Carousel`, `CarouselItem`, `Dialog`, `Dropdown`, `Link`, `LinkButton`, `Loader`, `Menu.Item`, `Modal`, `Navbar`, `Navbar.Burger`, `Navbar.Dropdown`, `Navbar.Item`, `Navbar.Link`, `Sidebar` and `Toast` forward a ref — on those, rename `domRef` to `ref`, though not on the `Field`, `Field.Label`, `Field.Body`, `Checkboxes` and `Radios` wrappers, which forward none. Mind the `Navbar.Dropdown` collision: the `Navbar.Item` that wrapped your dropdown became bestax `Navbar.Dropdown` and forwards one, while your `Navbar.Dropdown` became `Navbar.DropdownMenu` and does not. The rest forward no ref: React 18 drops it with a warning, React 19 leaves it wherever the rest props go, so put the ref on a DOM child or wrap the component',
|
|
30
30
|
},
|
|
31
31
|
// ColorProps
|
|
32
32
|
backgroundColor: { rename: 'bgColor' },
|
|
@@ -506,8 +506,9 @@ export const MAPPING = {
|
|
|
506
506
|
},
|
|
507
507
|
Loader: {
|
|
508
508
|
// RBC Loader is literally <div class="loader"> and Bulma v1 still ships
|
|
509
|
-
// that class
|
|
510
|
-
//
|
|
509
|
+
// that class, so a plain element is the faithful conversion. bestax's
|
|
510
|
+
// Loader draws the same ring on a span with a progressbar role and an
|
|
511
|
+
// accessible name; swapping it in is left to the user.
|
|
511
512
|
status: 'mapped',
|
|
512
513
|
special: 'plain-loader',
|
|
513
514
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bestax-migrate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.25.0",
|
|
4
4
|
"description": "Codemods for migrating existing React apps from other Bulma libraries to @allxsmith/bestax-bulma",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"chalk": "^6.0.0",
|
|
39
39
|
"commander": "^15.0.0",
|
|
40
40
|
"jscodeshift": "^17.3.0",
|
|
41
|
-
"@allxsmith/bestax-bulma": "^5.
|
|
41
|
+
"@allxsmith/bestax-bulma": "^5.26.4"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@jest/globals": "^30.0.0",
|
|
@@ -75,5 +75,5 @@
|
|
|
75
75
|
"clean": "rimraf dist",
|
|
76
76
|
"release": "npx semantic-release"
|
|
77
77
|
},
|
|
78
|
-
"readme": "# bestax-migrate\n\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/bestax-migrate/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/bestax-migrate#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nCodemods that migrate existing React apps to [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — the actively maintained React component library for **Bulma v1**.\n\nCurrently supported sources:\n\n| Source | Status |\n| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |\n| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs) |\n| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs) |\n| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged) |\n| `bulma-classes`: Bulma's classes on plain JSX, no library | ✅ Converts an element only when bestax renders the same markup; the rest is flagged |\n\nPass the source as the first argument: `bestax-migrate <source> <paths…>`.\n\n## Requirements\n\n**Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the CLI\nexits immediately with an explicit upgrade message.\n\nThis applies only to the Node version the codemod itself runs on. It places no requirement on\nthe app being migrated — the source is read as text and is never executed.\n\n## Usage\n\n```bash\n# Preview what would change (no writes)\npnpm dlx bestax-migrate react-bulma-components src/ --dry\n# …or, for an rbx or bloomer app\npnpm dlx bestax-migrate rbx src/ --dry\npnpm dlx bestax-migrate bloomer src/ --dry\n# …or, for an app that writes Bulma's classes on plain JSX\npnpm dlx bestax-migrate bulma-classes src/ --dry\n\n# Apply the migration\npnpm dlx bestax-migrate react-bulma-components src/\n```\n\nnpm and yarn work too: `npx bestax-migrate …` / `yarn dlx bestax-migrate …`.\n\nThe codemod uses [jscodeshift](https://github.com/facebook/jscodeshift) to:\n\n- rewrite the source library's imports to `@allxsmith/bestax-bulma` (including destructuring and namespace imports)\n- rename components and compound sub-components (`Form.Textarea` → `TextArea`, `Card.Footer.Item` → `Card.FooterItem`, `Hero.Footer` → `Hero.Foot`, …) — and, for bloomer, its flat names onto bestax's compounds (`CardHeaderTitle` → `Card.Header.Title`)\n- convert props (`renderAs` → `as`, `loading` → `isLoading`, numeric spacing/text sizes → string unions, `textAlign=\"center\"` → `textAlign=\"centered\"`, …)\n- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`) and bloomer's `isDisplay`/`isHidden` strings, arrays and objects (`isHidden=\"touch\"` → `visibilityTouch=\"hidden\"`)\n- for `bulma-classes`, turn raw Bulma markup into components and props (`<a className=\"button is-primary\">` → `<Button as=\"a\" color=\"primary\">`, `<p className=\"has-text-centered mt-4\">` → `<Paragraph textAlign=\"centered\" mt=\"4\">`), converting an element only when bestax renders exactly the same markup\n- restructure patterns bestax models differently (`Table.Container`, Navbar dropdowns, `Form.Help`, icon-font children → `<Icon name=…>`)\n- migrate stylesheets: CSS imports converge on `@allxsmith/bestax-bulma/bestax.css`, and SCSS files move from Bulma 0.9's `@import` + `$var !default` overrides to `@use 'bulma/sass' with (…)` plus `@use '@allxsmith/bestax-bulma/scss/extras'`\n- update `package.json`: remove the source library, add `@allxsmith/bestax-bulma`, raise a declared pre-1.0 `bulma` to `^1` (adding it only when your sources import `bulma/…` directly — otherwise it arrives transitively), and swap the dead `node-sass` for dart `sass` (no install is ever run). Migrating **rbx** is what frees an app from Bulma 0.7.5: rbx pinned it as a _direct_ dependency, so the app could not choose its own Bulma version at all. The four Bulma extensions rbx also pulled in (`bulma-badge`, `bulma-divider`, `bulma-pageloader`, `bulma-tooltip`) are **reported rather than removed** — bestax replaces all four, but a manifest entry is a deliberate declaration and your own Sass may import them. A **bloomer** app declared its own Bulma 0.6, which is what gets bumped. For **bulma-classes** there is no library to remove, and by default (`--css keep`) the app's Bulma version, Sass and stylesheet imports all stay: its own Bulma already styles every class a converted element renders. `--css bestax` or `--css bulma` moves it to Bulma v1 like the other sources\n\nAnything without a safe automatic conversion is left in place with a `// TODO(bestax-migrate): …` comment, and the run ends with a report of every TODO by file and line. TODOs are expected output, not errors — resolve them with the migration guide ([react-bulma-components](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components), [rbx](https://bestax.io/docs/guides/getting-started/migration/rbx), [bloomer](https://bestax.io/docs/guides/getting-started/migration/bloomer), [Bulma classes](https://bestax.io/docs/guides/getting-started/migration/bulma-classes)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:\n\n```bash\nnpx skills add https://github.com/allxsmith/bestax --skill bestax-migrate\n```\n\n## Options\n\n| Flag | Description |\n| -------------------- | ---------------------------------------------------------------------------------------------- |\n| `--dry`, `-d` | Report what would change without writing files |\n| `--print`, `-p` | Print transformed sources to stdout |\n| `--extensions`, `-e` | File extensions to include (default `js,jsx,ts,tsx,scss,sass`) |\n| `--css <mode>` | Stylesheet target: `bestax`, `bulma`, or `keep` (default `bestax`; `keep` for `bulma-classes`) |\n| `--no-deps` | Skip updating package.json dependencies |\n\n## After the codemod\n\n1. Run your package manager's install (the codemod rewrote `package.json` but never installs)\n2. Search for `TODO(bestax-migrate)` and resolve each comment\n3. Typecheck/build and review the rendered app\n\nFull walkthrough: [react-bulma-components migration guide](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components) · [rbx migration guide](https://bestax.io/docs/guides/getting-started/migration/rbx) · [bloomer migration guide](https://bestax.io/docs/guides/getting-started/migration/bloomer) · [Bulma classes migration guide](https://bestax.io/docs/guides/getting-started/migration/bulma-classes).\n\n## Hardened by default\n\nA codemod rewrites your source in place, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/bestax-migrate#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **The libraries this tool migrates away from are never installed here** — source fixtures are read as text only, so no unmaintained third-party package enters the dependency tree.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, and CodeQL, Dependency Review, and Dependabot run continuously alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`bestax-migrate` can send one **anonymous** usage event after a successful\nrun — only if you opt in when asked (once, on an interactive terminal). The\nevent is just the run's shape — source library, CSS mode, the dry/deps flags, a\ncapped changed-file count, and per-rule TODO counts — plus the CLI version,\nNode major version, and OS platform name. Never file paths, file contents,\ncode, names, IPs, or machine IDs, and no identifier exists that could link two\nevents together. Opt out any time with `--no-telemetry`,\n`BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## License\n\nSource code licensed MIT\n"
|
|
78
|
+
"readme": "# bestax-migrate\n\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/bestax-migrate/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/bestax-migrate#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nCodemods that migrate existing React apps to [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — the actively maintained React component library for **Bulma v1**.\n\nCurrently supported sources:\n\n| Source | Status |\n| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |\n| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs) |\n| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs) |\n| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged) |\n| `bulma-classes`: Bulma's classes on plain JSX, no library | ✅ Converts an element only when bestax renders the same markup; the rest is flagged |\n\nPass the source as the first argument: `bestax-migrate <source> <paths…>`.\n\n## Requirements\n\n**Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the CLI\nexits immediately with an explicit upgrade message.\n\nThis applies only to the Node version the codemod itself runs on. It places no requirement on\nthe app being migrated — the source is read as text and is never executed.\n\n## Usage\n\n```bash\n# Preview what would change (no writes)\npnpm dlx bestax-migrate react-bulma-components src/ --dry\n# …or, for an rbx or bloomer app\npnpm dlx bestax-migrate rbx src/ --dry\npnpm dlx bestax-migrate bloomer src/ --dry\n# …or, for an app that writes Bulma's classes on plain JSX\npnpm dlx bestax-migrate bulma-classes src/ --dry\n\n# Apply the migration\npnpm dlx bestax-migrate react-bulma-components src/\n```\n\nnpm and yarn work too: `npx bestax-migrate …` / `yarn dlx bestax-migrate …`.\n\nThe codemod uses [jscodeshift](https://github.com/facebook/jscodeshift) to:\n\n- rewrite the source library's imports to `@allxsmith/bestax-bulma` (including destructuring and namespace imports)\n- rename components and compound sub-components (`Form.Textarea` → `TextArea`, `Card.Footer.Item` → `Card.FooterItem`, `Hero.Footer` → `Hero.Foot`, …) — and, for bloomer, its flat names onto bestax's compounds (`CardHeaderTitle` → `Card.Header.Title`)\n- convert props (`renderAs` → `as`, `loading` → `isLoading`, numeric spacing/text sizes → string unions, `textAlign=\"center\"` → `textAlign=\"centered\"`, …)\n- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`) and bloomer's `isDisplay`/`isHidden` strings, arrays and objects (`isHidden=\"touch\"` → `visibilityTouch=\"hidden\"`)\n- for `bulma-classes`, turn raw Bulma markup into components and props (`<a className=\"button is-primary\">` → `<Button as=\"a\" color=\"primary\">`, `<p className=\"has-text-centered mt-4\">` → `<Paragraph textAlign=\"centered\" mt=\"4\">`), converting an element only when bestax renders exactly the same markup\n- restructure patterns bestax models differently (`Table.Container`, Navbar dropdowns, `Form.Help`, icon-font children → `<Icon name=…>`)\n- migrate stylesheets: CSS imports converge on `@allxsmith/bestax-bulma/bestax.css`, and SCSS files move from Bulma 0.9's `@import` + `$var !default` overrides to `@use 'bulma/sass' with (…)` plus `@use '@allxsmith/bestax-bulma/scss/extras'`\n- update `package.json`: remove the source library, add `@allxsmith/bestax-bulma`, raise a declared pre-1.0 `bulma` to `^1` (adding it only when your sources import `bulma/…` directly — otherwise it arrives transitively), and swap the dead `node-sass` for dart `sass` (no install is ever run). Migrating **rbx** is what frees an app from Bulma 0.7.5: rbx pinned it as a _direct_ dependency, so the app could not choose its own Bulma version at all. The four Bulma extensions rbx also pulled in (`bulma-badge`, `bulma-divider`, `bulma-pageloader`, `bulma-tooltip`) are **reported rather than removed** — bestax replaces all four, but a manifest entry is a deliberate declaration and your own Sass may import them. A **bloomer** app declared its own Bulma 0.6, which is what gets bumped. For **bulma-classes** there is no library to remove, and by default (`--css keep`) the app's Bulma version, Sass and stylesheet imports all stay: its own Bulma already styles every class a converted element renders. `--css bestax` or `--css bulma` moves it to Bulma v1 like the other sources\n\nAnything without a safe automatic conversion is left in place with a `// TODO(bestax-migrate): …` comment, and the run ends with a report of every TODO by file and line. TODOs are expected output, not errors — resolve them with the migration guide ([react-bulma-components](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components), [rbx](https://bestax.io/docs/guides/getting-started/migration/rbx), [bloomer](https://bestax.io/docs/guides/getting-started/migration/bloomer), [Bulma classes](https://bestax.io/docs/guides/getting-started/migration/bulma-classes)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:\n\n```bash\nnpx skills add https://github.com/allxsmith/bestax --skill bestax-migrate\n```\n\n### Through the Codemod Registry\n\nbestax-migrate is also in the [Codemod Registry](https://app.codemod.com/registry) as `bestax-migrate`, for teams that run their migrations through Codemod. That package runs this CLI from npm at a pinned release, which can trail the newest one:\n\n```bash\n# Preview (no writes)\nnpx codemod bestax-migrate --workflow preview --param source=react-bulma-components\n# Apply\nnpx codemod bestax-migrate --param source=react-bulma-components\n```\n\nRun it from your app root. `--param paths=\"src lib\"` (default `src`) and `--param options=\"--css keep\"` pass through to the CLI. Codemod's own `--dry-run` skips the shell step this package runs, so use the `preview` workflow for a dry run.\n\n## Options\n\n| Flag | Description |\n| -------------------- | ---------------------------------------------------------------------------------------------- |\n| `--dry`, `-d` | Report what would change without writing files |\n| `--print`, `-p` | Print transformed sources to stdout |\n| `--extensions`, `-e` | File extensions to include (default `js,jsx,ts,tsx,scss,sass`) |\n| `--css <mode>` | Stylesheet target: `bestax`, `bulma`, or `keep` (default `bestax`; `keep` for `bulma-classes`) |\n| `--no-deps` | Skip updating package.json dependencies |\n\n## After the codemod\n\n1. Run your package manager's install (the codemod rewrote `package.json` but never installs)\n2. Search for `TODO(bestax-migrate)` and resolve each comment\n3. Typecheck/build and review the rendered app\n\nFull walkthrough: [react-bulma-components migration guide](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components) · [rbx migration guide](https://bestax.io/docs/guides/getting-started/migration/rbx) · [bloomer migration guide](https://bestax.io/docs/guides/getting-started/migration/bloomer) · [Bulma classes migration guide](https://bestax.io/docs/guides/getting-started/migration/bulma-classes).\n\n## Hardened by default\n\nA codemod rewrites your source in place, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/bestax-migrate#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **The libraries this tool migrates away from are never installed here** — source fixtures are read as text only, so no unmaintained third-party package enters the dependency tree.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, and CodeQL, Dependency Review, and Dependabot run continuously alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`bestax-migrate` can send one **anonymous** usage event after a successful\nrun — only if you opt in when asked (once, on an interactive terminal). The\nevent is just the run's shape — source library, CSS mode, the dry/deps flags, a\ncapped changed-file count, and per-rule TODO counts — plus the CLI version,\nNode major version, and OS platform name. Never file paths, file contents,\ncode, names, IPs, or machine IDs, and no identifier exists that could link two\nevents together. Opt out any time with `--no-telemetry`,\n`BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## License\n\nSource code licensed MIT\n"
|
|
79
79
|
}
|