bestax-migrate 2.2.2 → 2.3.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 +12 -10
- package/dist/sources/_shared/imports.d.ts +28 -0
- package/dist/sources/_shared/imports.d.ts.map +1 -1
- package/dist/sources/_shared/imports.js +62 -0
- package/dist/sources/_shared/jsx-utils.d.ts +17 -0
- package/dist/sources/_shared/jsx-utils.d.ts.map +1 -1
- package/dist/sources/_shared/jsx-utils.js +49 -1
- package/dist/sources/_shared/props.d.ts +17 -0
- package/dist/sources/_shared/props.d.ts.map +1 -1
- package/dist/sources/_shared/props.js +72 -3
- package/dist/sources/_shared/specials-utils.d.ts +49 -3
- package/dist/sources/_shared/specials-utils.d.ts.map +1 -1
- package/dist/sources/_shared/specials-utils.js +165 -5
- package/dist/sources/_shared/viewports.d.ts +17 -0
- package/dist/sources/_shared/viewports.d.ts.map +1 -0
- package/dist/sources/_shared/viewports.js +32 -0
- package/dist/sources/bloomer/deps.d.ts +17 -0
- package/dist/sources/bloomer/deps.d.ts.map +1 -0
- package/dist/sources/bloomer/deps.js +119 -0
- package/dist/sources/bloomer/index.d.ts +3 -0
- package/dist/sources/bloomer/index.d.ts.map +1 -0
- package/dist/sources/bloomer/index.js +10 -0
- package/dist/sources/bloomer/mapping.d.ts +84 -0
- package/dist/sources/bloomer/mapping.d.ts.map +1 -0
- package/dist/sources/bloomer/mapping.js +988 -0
- package/dist/sources/bloomer/responsive.d.ts +39 -0
- package/dist/sources/bloomer/responsive.d.ts.map +1 -0
- package/dist/sources/bloomer/responsive.js +259 -0
- package/dist/sources/bloomer/specials.d.ts +19 -0
- package/dist/sources/bloomer/specials.d.ts.map +1 -0
- package/dist/sources/bloomer/specials.js +774 -0
- package/dist/sources/bloomer/styles.d.ts +13 -0
- package/dist/sources/bloomer/styles.d.ts.map +1 -0
- package/dist/sources/bloomer/styles.js +17 -0
- package/dist/sources/bloomer/transform.d.ts +27 -0
- package/dist/sources/bloomer/transform.d.ts.map +1 -0
- package/dist/sources/bloomer/transform.js +826 -0
- package/dist/sources/rbx/responsive.d.ts.map +1 -1
- package/dist/sources/rbx/responsive.js +1 -31
- package/dist/sources/rbx/specials.d.ts.map +1 -1
- package/dist/sources/rbx/specials.js +14 -91
- package/dist/sources/rbx/transform.d.ts.map +1 -1
- package/dist/sources/rbx/transform.js +168 -78
- package/dist/sources/react-bulma-components/responsive.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/responsive.js +2 -14
- package/dist/sources/react-bulma-components/specials.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/specials.js +33 -17
- package/dist/sources/react-bulma-components/transform.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/transform.js +168 -78
- package/dist/sources/registry.d.ts.map +1 -1
- package/dist/sources/registry.js +2 -0
- package/dist/types.d.ts +11 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -13,10 +13,11 @@ Codemods that migrate existing React apps to [`@allxsmith/bestax-bulma`](https:/
|
|
|
13
13
|
|
|
14
14
|
Currently supported source libraries:
|
|
15
15
|
|
|
16
|
-
| Source | Status
|
|
17
|
-
| -------------------------------------------------------------------------------- |
|
|
18
|
-
| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs)
|
|
19
|
-
| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs)
|
|
16
|
+
| Source | Status |
|
|
17
|
+
| -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
18
|
+
| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs) |
|
|
19
|
+
| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs) |
|
|
20
|
+
| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged) |
|
|
20
21
|
|
|
21
22
|
Pass the source library as the first argument: `bestax-migrate <source> <paths…>`.
|
|
22
23
|
|
|
@@ -33,8 +34,9 @@ the app being migrated — the source is read as text and is never executed.
|
|
|
33
34
|
```bash
|
|
34
35
|
# Preview what would change (no writes)
|
|
35
36
|
pnpm dlx bestax-migrate react-bulma-components src/ --dry
|
|
36
|
-
# …or, for an rbx app
|
|
37
|
+
# …or, for an rbx or bloomer app
|
|
37
38
|
pnpm dlx bestax-migrate rbx src/ --dry
|
|
39
|
+
pnpm dlx bestax-migrate bloomer src/ --dry
|
|
38
40
|
|
|
39
41
|
# Apply the migration
|
|
40
42
|
pnpm dlx bestax-migrate react-bulma-components src/
|
|
@@ -45,14 +47,14 @@ npm and yarn work too: `npx bestax-migrate …` / `yarn dlx bestax-migrate …`.
|
|
|
45
47
|
The codemod uses [jscodeshift](https://github.com/facebook/jscodeshift) to:
|
|
46
48
|
|
|
47
49
|
- rewrite the source library's imports to `@allxsmith/bestax-bulma` (including destructuring and namespace imports)
|
|
48
|
-
- rename components and compound sub-components (`Form.Textarea` → `TextArea`, `Card.Footer.Item` → `Card.FooterItem`, `Hero.Footer` → `Hero.Foot`, …)
|
|
50
|
+
- 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`)
|
|
49
51
|
- convert props (`renderAs` → `as`, `loading` → `isLoading`, numeric spacing/text sizes → string unions, `textAlign="center"` → `textAlign="centered"`, …)
|
|
50
|
-
- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`)
|
|
52
|
+
- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`) and bloomer's `isDisplay`/`isHidden` strings, arrays and objects (`isHidden="touch"` → `visibilityTouch="hidden"`)
|
|
51
53
|
- restructure patterns bestax models differently (`Table.Container`, Navbar dropdowns, `Form.Help`, icon-font children → `<Icon name=…>`)
|
|
52
54
|
- 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'`
|
|
53
|
-
- 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
|
|
55
|
+
- 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
|
|
54
56
|
|
|
55
|
-
Anything 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)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:
|
|
57
|
+
Anything 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)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:
|
|
56
58
|
|
|
57
59
|
```bash
|
|
58
60
|
npx skills add https://github.com/allxsmith/bestax --skill bestax-migrate
|
|
@@ -74,7 +76,7 @@ npx skills add https://github.com/allxsmith/bestax --skill bestax-migrate
|
|
|
74
76
|
2. Search for `TODO(bestax-migrate)` and resolve each comment
|
|
75
77
|
3. Typecheck/build and review the rendered app
|
|
76
78
|
|
|
77
|
-
Full 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).
|
|
79
|
+
Full 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).
|
|
78
80
|
|
|
79
81
|
## Hardened by default
|
|
80
82
|
|
|
@@ -43,4 +43,32 @@ export declare function prefersTabs(source: string): boolean;
|
|
|
43
43
|
* declarators at any depth.
|
|
44
44
|
*/
|
|
45
45
|
export declare function resolvesToBinding(path: ASTPath<any>, name: string, expected: unknown): boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Registry of `const { Item } = Card`-style aliases, keyed by the AST node
|
|
48
|
+
* that owns the declaring scope rather than by bare name. Two functions can
|
|
49
|
+
* each destructure `Header` from a different component; a name-keyed map let
|
|
50
|
+
* the second overwrite the first, and both declarations were then pruned
|
|
51
|
+
* while both `<Header…>` references were left resolving to nothing.
|
|
52
|
+
*
|
|
53
|
+
* Resolution walks the reference's ANCESTORS rather than consulting
|
|
54
|
+
* `scope.lookup`, because by the time references are rewritten the alias
|
|
55
|
+
* pass has already pruned the declaration -- so the binding is gone from the
|
|
56
|
+
* scope table, and `path.scope` objects are not identity-stable across
|
|
57
|
+
* traversals either.
|
|
58
|
+
*
|
|
59
|
+
* Source-agnostic: every transform resolves aliases the same way, and #613
|
|
60
|
+
* shipped this block duplicated in two of them.
|
|
61
|
+
*/
|
|
62
|
+
export interface AliasRegistry {
|
|
63
|
+
/** Record that `local` in the scope owned by `owner` names `target`. */
|
|
64
|
+
register(owner: unknown, local: string, target: string[]): void;
|
|
65
|
+
/**
|
|
66
|
+
* The canonical path `name` aliases at `at` (a reference's path), or
|
|
67
|
+
* undefined when no alias applies to that reference.
|
|
68
|
+
*/
|
|
69
|
+
aliasAt(name: string, at?: unknown): string[] | undefined;
|
|
70
|
+
/** Whether ANY scope aliases `name` — regardless of the reference. */
|
|
71
|
+
anyAlias(name: string): boolean;
|
|
72
|
+
}
|
|
73
|
+
export declare function makeAliasRegistry(): AliasRegistry;
|
|
46
74
|
//# sourceMappingURL=imports.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/imports.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,eAAO,MAAM,MAAM,GAAI,MAAM,GAAG,KAAG,MACyB,CAAC;AAE7D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,WAAW,EACd,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EACrB,gBAAgB,EAAE,MAAM,GACvB,GAAG,CAAC,MAAM,CAAC,CAmEb;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GACjB,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAiBlC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,GAChB,OAAO,CAST"}
|
|
1
|
+
{"version":3,"file":"imports.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/imports.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,eAAO,MAAM,MAAM,GAAI,MAAM,GAAG,KAAG,MACyB,CAAC;AAE7D;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,CAAC,EAAE,WAAW,EACd,IAAI,EAAE,UAAU,CAAC,GAAG,CAAC,EACrB,gBAAgB,EAAE,MAAM,GACvB,GAAG,CAAC,MAAM,CAAC,CAmEb;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,GACjB,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAiBlC;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,GAChB,OAAO,CAST;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,aAAa;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAChE;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;IAC1D,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,wBAAgB,iBAAiB,IAAI,aAAa,CAoEjD"}
|
|
@@ -150,3 +150,65 @@ export function resolvesToBinding(path, name, expected) {
|
|
|
150
150
|
// the shadowing case it guards against.
|
|
151
151
|
return !declaring || declaring === expected;
|
|
152
152
|
}
|
|
153
|
+
export function makeAliasRegistry() {
|
|
154
|
+
const aliasesByOwner = new Map();
|
|
155
|
+
const ownersFor = (name) => {
|
|
156
|
+
const owners = [];
|
|
157
|
+
for (const [owner, perScope] of aliasesByOwner) {
|
|
158
|
+
if (perScope.has(name))
|
|
159
|
+
owners.push(owner);
|
|
160
|
+
}
|
|
161
|
+
return owners;
|
|
162
|
+
};
|
|
163
|
+
const register = (owner, local, target) => {
|
|
164
|
+
let perScope = aliasesByOwner.get(owner);
|
|
165
|
+
if (!perScope) {
|
|
166
|
+
perScope = new Map();
|
|
167
|
+
aliasesByOwner.set(owner, perScope);
|
|
168
|
+
}
|
|
169
|
+
perScope.set(local, target);
|
|
170
|
+
};
|
|
171
|
+
const aliasAt = (name, at) => {
|
|
172
|
+
const owners = ownersFor(name);
|
|
173
|
+
if (owners.length === 0)
|
|
174
|
+
return undefined;
|
|
175
|
+
// Without a reference location there is nothing to walk, so the only
|
|
176
|
+
// owner is the best answer available. WITH one, always walk: an unrelated
|
|
177
|
+
// `Header` parameter in another function must not resolve to the alias
|
|
178
|
+
// merely because the alias is the only one by that name. A single-owner
|
|
179
|
+
// shortcut here rewrote such a parameter to `{ Header: Card.Header }`,
|
|
180
|
+
// which is not even valid syntax.
|
|
181
|
+
if (at === undefined) {
|
|
182
|
+
return owners.length === 1
|
|
183
|
+
? aliasesByOwner.get(owners[0]).get(name)
|
|
184
|
+
: undefined;
|
|
185
|
+
}
|
|
186
|
+
let cursor = at;
|
|
187
|
+
while (cursor) {
|
|
188
|
+
if (cursor.node !== undefined) {
|
|
189
|
+
const hit = aliasesByOwner.get(cursor.node)?.get(name);
|
|
190
|
+
if (hit) {
|
|
191
|
+
// The walk finds the nearest OWNER, but a binding can intervene
|
|
192
|
+
// between the reference and that owner: `function F(Header)` under
|
|
193
|
+
// a module-level `const { Header } = Card` shadows the alias, and
|
|
194
|
+
// resolving through it rewrote the parameter itself to
|
|
195
|
+
// `F(Card.Header)`. If the scope table still binds the name
|
|
196
|
+
// somewhere other than the owner, that nearer binding wins. (After
|
|
197
|
+
// the alias declaration is pruned the lookup returns nothing for
|
|
198
|
+
// the alias itself, which is the case this must keep allowing.)
|
|
199
|
+
const declaring = at.scope?.lookup(name)?.path?.node;
|
|
200
|
+
if (declaring !== undefined &&
|
|
201
|
+
declaring !== null &&
|
|
202
|
+
declaring !== cursor.node) {
|
|
203
|
+
return undefined;
|
|
204
|
+
}
|
|
205
|
+
return hit;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
cursor = cursor.parent;
|
|
209
|
+
}
|
|
210
|
+
return undefined;
|
|
211
|
+
};
|
|
212
|
+
const anyAlias = (name) => ownersFor(name).length > 0;
|
|
213
|
+
return { register, aliasAt, anyAlias };
|
|
214
|
+
}
|
|
@@ -62,6 +62,23 @@ export type LiteralValue = {
|
|
|
62
62
|
};
|
|
63
63
|
/** Extract the literal value of a JSX attribute, if it has one. */
|
|
64
64
|
export declare function literalValueOf(attr: any): LiteralValue;
|
|
65
|
+
/**
|
|
66
|
+
* The literal value of an expression node (as opposed to `literalValueOf`,
|
|
67
|
+
* which reads a JSX attribute): a string, number or boolean literal's value,
|
|
68
|
+
* otherwise undefined.
|
|
69
|
+
*/
|
|
70
|
+
export declare function literalOf(node: any): string | number | boolean | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Reuse a value node as a JSX attribute value: a string literal can sit bare
|
|
73
|
+
* (`size="one-third"`), anything else needs an expression container.
|
|
74
|
+
*/
|
|
75
|
+
export declare function attrValue(j: JSCodeshift, node: any): any;
|
|
76
|
+
/** The static key of an object property (`{ tablet: … }`, `{ 'inline-block': … }`). */
|
|
77
|
+
export declare function propKey(prop: any): string | undefined;
|
|
78
|
+
/** The ObjectExpression inside a JSX attribute value, or null. */
|
|
79
|
+
export declare function objectExpressionOf(value: any): any | null;
|
|
80
|
+
/** The ArrayExpression inside a JSX attribute value, or null. */
|
|
81
|
+
export declare function arrayExpressionOf(value: any): any | null;
|
|
65
82
|
export type Booleanish = 'truthy' | 'falsy' | 'expression';
|
|
66
83
|
/**
|
|
67
84
|
* Classify a JSX attribute by the truthiness the source library evaluates it
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"jsx-utils.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/jsx-utils.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"jsx-utils.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/jsx-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -74,6 +74,50 @@ export function literalValueOf(attr) {
|
|
|
74
74
|
}
|
|
75
75
|
return { kind: 'expression' };
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* The literal value of an expression node (as opposed to `literalValueOf`,
|
|
79
|
+
* which reads a JSX attribute): a string, number or boolean literal's value,
|
|
80
|
+
* otherwise undefined.
|
|
81
|
+
*/
|
|
82
|
+
export function literalOf(node) {
|
|
83
|
+
if (!node)
|
|
84
|
+
return undefined;
|
|
85
|
+
if (node.type === 'StringLiteral')
|
|
86
|
+
return node.value;
|
|
87
|
+
if (node.type === 'NumericLiteral')
|
|
88
|
+
return node.value;
|
|
89
|
+
if (node.type === 'BooleanLiteral')
|
|
90
|
+
return node.value;
|
|
91
|
+
return undefined;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Reuse a value node as a JSX attribute value: a string literal can sit bare
|
|
95
|
+
* (`size="one-third"`), anything else needs an expression container.
|
|
96
|
+
*/
|
|
97
|
+
export function attrValue(j, node) {
|
|
98
|
+
return node?.type === 'StringLiteral'
|
|
99
|
+
? j.stringLiteral(node.value)
|
|
100
|
+
: j.jsxExpressionContainer(node);
|
|
101
|
+
}
|
|
102
|
+
/** The static key of an object property (`{ tablet: … }`, `{ 'inline-block': … }`). */
|
|
103
|
+
export function propKey(prop) {
|
|
104
|
+
const key = prop.key?.name ?? prop.key?.value;
|
|
105
|
+
return typeof key === 'string' ? key : undefined;
|
|
106
|
+
}
|
|
107
|
+
/** The ObjectExpression inside a JSX attribute value, or null. */
|
|
108
|
+
export function objectExpressionOf(value) {
|
|
109
|
+
return value?.type === 'JSXExpressionContainer' &&
|
|
110
|
+
value.expression?.type === 'ObjectExpression'
|
|
111
|
+
? value.expression
|
|
112
|
+
: null;
|
|
113
|
+
}
|
|
114
|
+
/** The ArrayExpression inside a JSX attribute value, or null. */
|
|
115
|
+
export function arrayExpressionOf(value) {
|
|
116
|
+
return value?.type === 'JSXExpressionContainer' &&
|
|
117
|
+
value.expression?.type === 'ArrayExpression'
|
|
118
|
+
? value.expression
|
|
119
|
+
: null;
|
|
120
|
+
}
|
|
77
121
|
/**
|
|
78
122
|
* Classify a JSX attribute by the truthiness the source library evaluates it
|
|
79
123
|
* with at runtime (`!!value`): every statically-known literal (boolean,
|
|
@@ -140,7 +184,11 @@ export function addTodo(ctx, path, rule, message) {
|
|
|
140
184
|
export function plainElement(j, tag, className, attrs, children, selfClosing = false) {
|
|
141
185
|
const allAttrs = [...attrs];
|
|
142
186
|
if (className) {
|
|
143
|
-
|
|
187
|
+
// After the LAST spread, so a `className` inside one cannot replace the
|
|
188
|
+
// class this element exists for, while every other attribute keeps the
|
|
189
|
+
// place (and so the precedence) it had in the source.
|
|
190
|
+
const lastSpread = allAttrs.reduce((last, a, i) => a.type === 'JSXSpreadAttribute' ? i : last, -1);
|
|
191
|
+
allAttrs.splice(lastSpread + 1, 0, makeAttr(j, 'className', className));
|
|
144
192
|
}
|
|
145
193
|
const opening = j.jsxOpeningElement(j.jsxIdentifier(tag), allAttrs, selfClosing);
|
|
146
194
|
const closing = selfClosing
|
|
@@ -9,6 +9,23 @@
|
|
|
9
9
|
import type { ASTPath } from 'jscodeshift';
|
|
10
10
|
import type { PropAction } from '../../types.js';
|
|
11
11
|
import { type TransformContext } from './jsx-utils.js';
|
|
12
|
+
/**
|
|
13
|
+
* Add a converted attribute unless the target name is already present — two
|
|
14
|
+
* source props can map onto one bestax prop (e.g. RBC's `textTransform` +
|
|
15
|
+
* `italic`), and a silent duplicate would be invalid JSX.
|
|
16
|
+
*/
|
|
17
|
+
export declare function addConverted(ctx: TransformContext, path: ASTPath<any>, element: any, originalName: string, name: string, value: string | undefined): void;
|
|
18
|
+
/**
|
|
19
|
+
* The same refusal for an attribute the caller has already built — a numeric
|
|
20
|
+
* `size={6}` or a reused expression node, which `makeAttr` cannot express.
|
|
21
|
+
*/
|
|
22
|
+
export declare function addAttrOnce(ctx: TransformContext, path: ASTPath<any>, element: any, originalName: string, attr: any): void;
|
|
23
|
+
/**
|
|
24
|
+
* Merge a Bulma class into the element's `className`: appended to a string
|
|
25
|
+
* literal, written fresh when there is none, and a TODO when the existing
|
|
26
|
+
* value is dynamic (the class cannot be spliced into an expression safely).
|
|
27
|
+
*/
|
|
28
|
+
export declare function mergeClass(ctx: TransformContext, path: ASTPath<any>, element: any, cls: string, originalName: string): void;
|
|
12
29
|
/** Apply one PropAction to `attr` on `element`. */
|
|
13
30
|
export declare function applyPropAction(ctx: TransformContext, path: ASTPath<any>, element: any, attr: any, action: PropAction): void;
|
|
14
31
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/props.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EASL,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"props.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/props.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EASL,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AAIxB;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,SAAS,GACxB,IAAI,CAEN;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,GAAG,GACR,IAAI,CAmBN;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CACxB,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,GACnB,IAAI,CAoBN;AAED,mDAAmD;AACnD,wBAAgB,eAAe,CAC7B,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,IAAI,EAAE,GAAG,EACT,MAAM,EAAE,UAAU,GACjB,IAAI,CAqLN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,EACZ,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,EACpB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GACzC,IAAI,CAQN"}
|
|
@@ -13,12 +13,48 @@ import { addAttr, addTodo, attributesOf, findAttr, literalValueOf, makeAttr, rem
|
|
|
13
13
|
* source props can map onto one bestax prop (e.g. RBC's `textTransform` +
|
|
14
14
|
* `italic`), and a silent duplicate would be invalid JSX.
|
|
15
15
|
*/
|
|
16
|
-
function addConverted(ctx, path, element, originalName, name, value) {
|
|
16
|
+
export function addConverted(ctx, path, element, originalName, name, value) {
|
|
17
|
+
addAttrOnce(ctx, path, element, originalName, makeAttr(ctx.j, name, value));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The same refusal for an attribute the caller has already built — a numeric
|
|
21
|
+
* `size={6}` or a reused expression node, which `makeAttr` cannot express.
|
|
22
|
+
*/
|
|
23
|
+
export function addAttrOnce(ctx, path, element, originalName, attr) {
|
|
24
|
+
const name = attr.name.name;
|
|
17
25
|
if (findAttr(element, name)) {
|
|
18
|
-
|
|
26
|
+
const value = attr.value;
|
|
27
|
+
const rendered = value == null
|
|
28
|
+
? ''
|
|
29
|
+
: value.type === 'StringLiteral'
|
|
30
|
+
? `="${value.value}"`
|
|
31
|
+
: '={…}';
|
|
32
|
+
addTodo(ctx, path, `prop:${originalName}`, `\`${originalName}\` maps to \`${name}${rendered}\`, but \`${name}\` is already set on this element; reconcile by hand`);
|
|
19
33
|
return;
|
|
20
34
|
}
|
|
21
|
-
addAttr(element,
|
|
35
|
+
addAttr(element, attr);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Merge a Bulma class into the element's `className`: appended to a string
|
|
39
|
+
* literal, written fresh when there is none, and a TODO when the existing
|
|
40
|
+
* value is dynamic (the class cannot be spliced into an expression safely).
|
|
41
|
+
*/
|
|
42
|
+
export function mergeClass(ctx, path, element, cls, originalName) {
|
|
43
|
+
const { j } = ctx;
|
|
44
|
+
const existing = findAttr(element, 'className');
|
|
45
|
+
if (!existing) {
|
|
46
|
+
addAttr(element, makeAttr(j, 'className', cls));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const literal = literalValueOf(existing);
|
|
50
|
+
if (literal.kind === 'string') {
|
|
51
|
+
const classes = literal.value.split(/\s+/).filter(Boolean);
|
|
52
|
+
if (!classes.includes(cls))
|
|
53
|
+
classes.push(cls);
|
|
54
|
+
existing.value = j.stringLiteral(classes.join(' '));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
addTodo(ctx, path, `prop:${originalName}`, `\`${originalName}\` becomes the \`${cls}\` class, but \`className\` is dynamic here; add \`${cls}\` to it by hand`);
|
|
22
58
|
}
|
|
23
59
|
/** Apply one PropAction to `attr` on `element`. */
|
|
24
60
|
export function applyPropAction(ctx, path, element, attr, action) {
|
|
@@ -29,6 +65,30 @@ export function applyPropAction(ctx, path, element, attr, action) {
|
|
|
29
65
|
ctx.dirty = true;
|
|
30
66
|
return;
|
|
31
67
|
}
|
|
68
|
+
if (action.toClass) {
|
|
69
|
+
const resolved = resolveBooleanish(attr);
|
|
70
|
+
if (resolved === 'expression') {
|
|
71
|
+
addTodo(ctx, path, `prop:${originalName}`, `\`${originalName}\` has a dynamic value; bestax has no prop for it — add the \`${action.toClass}\` class conditionally by hand`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
removeAttr(element, attr);
|
|
75
|
+
ctx.dirty = true;
|
|
76
|
+
if (resolved === 'truthy') {
|
|
77
|
+
mergeClass(ctx, path, element, action.toClass, originalName);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (action.toClassPrefix) {
|
|
82
|
+
const value = literalValueOf(attr);
|
|
83
|
+
if (value.kind !== 'string') {
|
|
84
|
+
addTodo(ctx, path, `prop:${originalName}`, `\`${originalName}\` has a dynamic value; bestax has no prop for it — add the \`${action.toClassPrefix}<value>\` class by hand`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
removeAttr(element, attr);
|
|
88
|
+
ctx.dirty = true;
|
|
89
|
+
mergeClass(ctx, path, element, `${action.toClassPrefix}${value.value}`, originalName);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
32
92
|
if (action.todo) {
|
|
33
93
|
addTodo(ctx, path, `prop:${originalName}`, `\`${originalName}\` — ${action.todo}`);
|
|
34
94
|
return;
|
|
@@ -80,6 +140,15 @@ export function applyPropAction(ctx, path, element, attr, action) {
|
|
|
80
140
|
return;
|
|
81
141
|
}
|
|
82
142
|
let renamedTo = originalName;
|
|
143
|
+
if (action.rename &&
|
|
144
|
+
action.rename !== originalName &&
|
|
145
|
+
findAttr(element, action.rename)) {
|
|
146
|
+
// Two source props can converge on one bestax prop (`isSize` and
|
|
147
|
+
// `isFullHeight` both on `size`); renaming over the one already written
|
|
148
|
+
// produced a duplicate attribute, which is invalid JSX.
|
|
149
|
+
addTodo(ctx, path, `prop:${originalName}`, `\`${originalName}\` maps to \`${action.rename}\`, but \`${action.rename}\` is already set on this element; reconcile by hand`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
83
152
|
if (action.rename) {
|
|
84
153
|
attr.name = j.jsxIdentifier(action.rename);
|
|
85
154
|
renamedTo = action.rename;
|
|
@@ -36,10 +36,56 @@ export declare function makeStripModifierProps(universalProps: Record<string, Pr
|
|
|
36
36
|
* can't be merged safely — keep the base class and leave a TODO.
|
|
37
37
|
*/
|
|
38
38
|
export declare function mergeClassName(ctx: TransformContext, path: ASTPath<any>, element: any, base: string | undefined, where: string): string | undefined;
|
|
39
|
-
/**
|
|
40
|
-
export
|
|
39
|
+
/** What an icon-font class string says about a bestax `Icon`. */
|
|
40
|
+
export interface ParsedIconClasses {
|
|
41
41
|
name: string;
|
|
42
42
|
library?: string;
|
|
43
43
|
variant?: string;
|
|
44
|
-
|
|
44
|
+
/** Recognised modifier classes (`fa-spin`, `fa-2x`, `mdi-48px`) — bestax's `features`. */
|
|
45
|
+
features: string[];
|
|
46
|
+
/**
|
|
47
|
+
* Tokens that are neither the icon, its style, nor a modifier the library
|
|
48
|
+
* documents — an app's own class. bestax's Icon has nowhere to put them
|
|
49
|
+
* on the glyph, so a caller that wants exact markup keeps the child.
|
|
50
|
+
*/
|
|
51
|
+
leftovers: string[];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Parse an icon-font class string (`fas fa-home fa-spin`, `mdi mdi-account`)
|
|
55
|
+
* into bestax Icon props. Returns null when no icon name can be read.
|
|
56
|
+
*/
|
|
57
|
+
export declare function parseIconClasses(className: string): ParsedIconClasses | null;
|
|
58
|
+
/**
|
|
59
|
+
* Write a parsed icon onto a bestax `Icon`-shaped element: `name`, then
|
|
60
|
+
* `library`/`variant` when known, then `features` — one string, or an array
|
|
61
|
+
* literal when there are several — and make the element self-closing.
|
|
62
|
+
*/
|
|
63
|
+
export declare function applyIconProps(ctx: TransformContext, path: ASTPath<any>, element: any, parsed: ParsedIconClasses): void;
|
|
64
|
+
/**
|
|
65
|
+
* Turn a literal modifier prop into an `is-*` class fragment for an element
|
|
66
|
+
* on its way to becoming plain HTML. Returns the class (or undefined) and
|
|
67
|
+
* always removes the attribute.
|
|
68
|
+
*/
|
|
69
|
+
export declare function modifierClass(ctx: TransformContext, path: ASTPath<any>, element: any, prop: string, base: string, where: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* A source that puts `as` (or its own name for it) on every component can
|
|
72
|
+
* land, through a handler that picks its target from a prop value, on a
|
|
73
|
+
* bestax component that has no `as` — Media.Item resolves to
|
|
74
|
+
* Left/Content/Right where only Left declares one. Opting into `as` in the
|
|
75
|
+
* mapping table cannot express that, so the target has to be checked after
|
|
76
|
+
* it is picked.
|
|
77
|
+
*/
|
|
78
|
+
export declare function restrictAsToTargets(ctx: TransformContext, path: ASTPath<any>, element: any, target: string | undefined, allowed: string[], prop?: string): void;
|
|
79
|
+
/** Attribute filter a source applies before an element becomes plain HTML. */
|
|
80
|
+
export type AttrStrip = (ctx: TransformContext, path: ASTPath<any>, attrs: any[], where: string) => any[];
|
|
81
|
+
/**
|
|
82
|
+
* The two structural rewrites every source needs, bound to that source's own
|
|
83
|
+
* attribute strip (its modifier vocabulary is the one thing that differs):
|
|
84
|
+
* replacing an element with plain HTML, and folding a wrapper onto the single
|
|
85
|
+
* child it exists to wrap.
|
|
86
|
+
*/
|
|
87
|
+
export declare function makeStructuralHelpers(strip: AttrStrip): {
|
|
88
|
+
replaceWithPlain: (ctx: TransformContext, path: ASTPath<any>, element: any, tag: string, className: string | undefined, where: string) => SpecialResult;
|
|
89
|
+
collapseOntoChild: (ctx: TransformContext, path: ASTPath<any>, element: any, where: string, expected: string | string[]) => SpecialResult | null;
|
|
90
|
+
};
|
|
45
91
|
//# sourceMappingURL=specials-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specials-utils.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/specials-utils.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"specials-utils.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/specials-utils.ts"],"names":[],"mappings":"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"}
|