bestax-migrate 2.3.8 → 2.4.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 +21 -17
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +45 -11
- package/dist/sources/_shared/bestax-import.d.ts +48 -0
- package/dist/sources/_shared/bestax-import.d.ts.map +1 -0
- package/dist/sources/_shared/bestax-import.js +142 -0
- package/dist/sources/_shared/css-imports.d.ts +33 -0
- package/dist/sources/_shared/css-imports.d.ts.map +1 -0
- package/dist/sources/_shared/css-imports.js +103 -0
- package/dist/sources/_shared/deps-common.d.ts +51 -0
- package/dist/sources/_shared/deps-common.d.ts.map +1 -0
- package/dist/sources/_shared/deps-common.js +115 -0
- package/dist/sources/_shared/jsx-utils.d.ts +28 -0
- package/dist/sources/_shared/jsx-utils.d.ts.map +1 -1
- package/dist/sources/_shared/jsx-utils.js +59 -1
- package/dist/sources/_shared/make-styles-transform.d.ts +6 -2
- package/dist/sources/_shared/make-styles-transform.d.ts.map +1 -1
- package/dist/sources/_shared/make-styles-transform.js +12 -4
- package/dist/sources/_shared/props.d.ts.map +1 -1
- package/dist/sources/_shared/props.js +2 -2
- package/dist/sources/_shared/specials-utils.d.ts +1 -1
- package/dist/sources/_shared/specials-utils.d.ts.map +1 -1
- package/dist/sources/_shared/specials-utils.js +19 -1
- package/dist/sources/bloomer/deps.d.ts.map +1 -1
- package/dist/sources/bloomer/deps.js +14 -89
- package/dist/sources/bloomer/transform.d.ts.map +1 -1
- package/dist/sources/bloomer/transform.js +12 -186
- package/dist/sources/bulma-classes/class-map.d.ts +161 -0
- package/dist/sources/bulma-classes/class-map.d.ts.map +1 -0
- package/dist/sources/bulma-classes/class-map.js +1046 -0
- package/dist/sources/bulma-classes/deps.d.ts +14 -0
- package/dist/sources/bulma-classes/deps.d.ts.map +1 -0
- package/dist/sources/bulma-classes/deps.js +56 -0
- package/dist/sources/bulma-classes/index.d.ts +3 -0
- package/dist/sources/bulma-classes/index.d.ts.map +1 -0
- package/dist/sources/bulma-classes/index.js +35 -0
- package/dist/sources/bulma-classes/plan.d.ts +53 -0
- package/dist/sources/bulma-classes/plan.d.ts.map +1 -0
- package/dist/sources/bulma-classes/plan.js +231 -0
- package/dist/sources/bulma-classes/project.d.ts +40 -0
- package/dist/sources/bulma-classes/project.d.ts.map +1 -0
- package/dist/sources/bulma-classes/project.js +203 -0
- package/dist/sources/bulma-classes/rules.d.ts +16 -0
- package/dist/sources/bulma-classes/rules.d.ts.map +1 -0
- package/dist/sources/bulma-classes/rules.js +53 -0
- package/dist/sources/bulma-classes/styles.d.ts +13 -0
- package/dist/sources/bulma-classes/styles.d.ts.map +1 -0
- package/dist/sources/bulma-classes/styles.js +18 -0
- package/dist/sources/bulma-classes/transform.d.ts +21 -0
- package/dist/sources/bulma-classes/transform.d.ts.map +1 -0
- package/dist/sources/bulma-classes/transform.js +486 -0
- package/dist/sources/rbx/deps.d.ts.map +1 -1
- package/dist/sources/rbx/deps.js +29 -117
- package/dist/sources/rbx/mapping.d.ts.map +1 -1
- package/dist/sources/rbx/mapping.js +9 -1
- package/dist/sources/rbx/specials.d.ts.map +1 -1
- package/dist/sources/rbx/specials.js +20 -10
- package/dist/sources/rbx/transform.d.ts.map +1 -1
- package/dist/sources/rbx/transform.js +22 -204
- package/dist/sources/react-bulma-components/deps.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/deps.js +12 -87
- package/dist/sources/react-bulma-components/mapping.js +1 -1
- package/dist/sources/react-bulma-components/specials.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/specials.js +42 -4
- package/dist/sources/react-bulma-components/transform.d.ts.map +1 -1
- package/dist/sources/react-bulma-components/transform.js +16 -187
- package/dist/sources/registry.d.ts.map +1 -1
- package/dist/sources/registry.js +2 -0
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -4,28 +4,17 @@
|
|
|
4
4
|
* with dart-sass. Pure data-in/data-out — the CLI owns file IO, and no
|
|
5
5
|
* package manager is ever invoked (the report tells the user to install).
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
8
|
-
const BESTAX_RANGE = '^5';
|
|
9
|
-
const BULMA_RANGE = '^1.0.4';
|
|
10
|
-
// Bulma v1's sass tree uses `color.channel(…)` — needs dart-sass ≥ 1.79.
|
|
11
|
-
const SASS_RANGE = '^1.79.0';
|
|
12
|
-
const DEP_SECTIONS = ['dependencies', 'devDependencies'];
|
|
7
|
+
import { DEP_SECTIONS, addBestax, moveBulmaToV1, openManifest, replaceNodeSass, reportPeerRanges, } from '../_shared/deps-common.js';
|
|
13
8
|
export const updateDependencies = (filePath, pkg, collector, options) => {
|
|
14
|
-
const
|
|
15
|
-
const next = pkg;
|
|
16
|
-
const section = (name) => (next[name] ?? undefined);
|
|
17
|
-
const note = (message) => {
|
|
18
|
-
changes.push(message);
|
|
19
|
-
collector?.add({ file: filePath, line: null, rule: 'deps', message });
|
|
20
|
-
};
|
|
9
|
+
const manifest = openManifest(filePath, pkg, collector);
|
|
21
10
|
// react-bulma-components goes away entirely.
|
|
22
11
|
let removedSource = false;
|
|
23
12
|
for (const name of DEP_SECTIONS) {
|
|
24
|
-
const deps = section(name);
|
|
13
|
+
const deps = manifest.section(name);
|
|
25
14
|
if (deps && 'react-bulma-components' in deps) {
|
|
26
15
|
delete deps['react-bulma-components'];
|
|
27
16
|
removedSource = true;
|
|
28
|
-
note(`removed react-bulma-components from ${name}`);
|
|
17
|
+
manifest.note(`removed react-bulma-components from ${name}`);
|
|
29
18
|
}
|
|
30
19
|
}
|
|
31
20
|
// The transform deliberately RETAINS imports for components with no bestax
|
|
@@ -35,76 +24,12 @@ export const updateDependencies = (filePath, pkg, collector, options) => {
|
|
|
35
24
|
// letting them find out at build time. rbx has carried this warning since
|
|
36
25
|
// it shipped; this source retains imports the same way and did not.
|
|
37
26
|
if (removedSource && options.sourceStillImported) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const dependencies = (next.dependencies ??= {});
|
|
47
|
-
if (!dependencies['@allxsmith/bestax-bulma'] &&
|
|
48
|
-
!section('devDependencies')?.['@allxsmith/bestax-bulma']) {
|
|
49
|
-
dependencies['@allxsmith/bestax-bulma'] = BESTAX_RANGE;
|
|
50
|
-
note(`added @allxsmith/bestax-bulma ${BESTAX_RANGE} to dependencies`);
|
|
51
|
-
}
|
|
52
|
-
// Bulma: bump a pre-1 range; add only when sources still reference bulma/…
|
|
53
|
-
// directly (otherwise it arrives transitively via bestax-bulma).
|
|
54
|
-
let bulmaDeclared = false;
|
|
55
|
-
for (const name of DEP_SECTIONS) {
|
|
56
|
-
const deps = section(name);
|
|
57
|
-
if (deps?.bulma) {
|
|
58
|
-
bulmaDeclared = true;
|
|
59
|
-
if (isPreV1(deps.bulma)) {
|
|
60
|
-
deps.bulma = BULMA_RANGE;
|
|
61
|
-
note(`bumped bulma to ${BULMA_RANGE} in ${name} (was pre-1.0)`);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
if (!bulmaDeclared && options.bulmaReferenced) {
|
|
66
|
-
dependencies.bulma = BULMA_RANGE;
|
|
67
|
-
note(`added bulma ${BULMA_RANGE} to dependencies (sources import bulma/… directly)`);
|
|
68
|
-
}
|
|
69
|
-
// bestax-bulma requires React 18/19; RBC v4 also ran on 17. Report only —
|
|
70
|
-
// a React major upgrade is the app's own migration step.
|
|
71
|
-
for (const name of DEP_SECTIONS) {
|
|
72
|
-
const range = section(name)?.react;
|
|
73
|
-
if (range && /^[~^]?(?:[0-9]|1[0-7])(?:[.x]|$)/.test(range.trim())) {
|
|
74
|
-
collector?.add({
|
|
75
|
-
file: filePath,
|
|
76
|
-
line: null,
|
|
77
|
-
rule: 'peer-deps',
|
|
78
|
-
message: `react ${range} predates bestax-bulma's peer range (^18 || ^19) — upgrade react and react-dom to 18 or 19 before installing`,
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
// Font Awesome older than 6 conflicts with bestax-bulma's optional peer
|
|
83
|
-
// range and makes `npm install` fail with ERESOLVE. Report only — icon
|
|
84
|
-
// names change across FA majors, so upgrading is the app's decision.
|
|
85
|
-
for (const name of DEP_SECTIONS) {
|
|
86
|
-
const range = section(name)?.['@fortawesome/fontawesome-free'];
|
|
87
|
-
if (range && /^[~^]?[0-5](?:[.x]|$)/.test(range.trim())) {
|
|
88
|
-
collector?.add({
|
|
89
|
-
file: filePath,
|
|
90
|
-
line: null,
|
|
91
|
-
rule: 'peer-deps',
|
|
92
|
-
message: `@fortawesome/fontawesome-free ${range} predates bestax-bulma's optional peer range (^6.7.2 || ^7.0.0) — upgrade it, or install with \`npm install --legacy-peer-deps\``,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
// node-sass is dead; dart-sass replaces it in the same section.
|
|
97
|
-
for (const name of DEP_SECTIONS) {
|
|
98
|
-
const deps = section(name);
|
|
99
|
-
if (deps && 'node-sass' in deps) {
|
|
100
|
-
delete deps['node-sass'];
|
|
101
|
-
note(`removed node-sass from ${name}`);
|
|
102
|
-
const sassDeclared = DEP_SECTIONS.some(s => section(s)?.sass);
|
|
103
|
-
if (!sassDeclared) {
|
|
104
|
-
deps.sass = SASS_RANGE;
|
|
105
|
-
note(`added sass ${SASS_RANGE} to ${name} (replaces node-sass)`);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
return changes.length > 0 ? next : null;
|
|
27
|
+
manifest.report('deps', 'react-bulma-components was removed from package.json, but some files still import it for components with no bestax equivalent — resolve those `TODO(bestax-migrate)` imports before installing, or re-add react-bulma-components until you have');
|
|
28
|
+
}
|
|
29
|
+
addBestax(manifest);
|
|
30
|
+
moveBulmaToV1(manifest, options.bulmaReferenced);
|
|
31
|
+
// RBC v4 also ran on React 17, which bestax-bulma's peer range excludes.
|
|
32
|
+
reportPeerRanges(manifest);
|
|
33
|
+
replaceNodeSass(manifest);
|
|
34
|
+
return manifest.result();
|
|
110
35
|
};
|
|
@@ -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
|
|
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',
|
|
30
30
|
},
|
|
31
31
|
// ColorProps
|
|
32
32
|
backgroundColor: { rename: 'bgColor' },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"specials.d.ts","sourceRoot":"","sources":["../../../src/sources/react-bulma-components/specials.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAWL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAQL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,aAAa,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"specials.d.ts","sourceRoot":"","sources":["../../../src/sources/react-bulma-components/specials.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAWL,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAQL,KAAK,aAAa,EACnB,MAAM,8BAA8B,CAAC;AAEtC,YAAY,EAAE,aAAa,EAAE,CAAC;AA82B9B,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,EAClB,OAAO,EAAE,GAAG,GACX,aAAa,CAIf;AAED,kEAAkE;AAClE,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,QAAQ,CAGjE,CAAC"}
|
|
@@ -28,7 +28,7 @@ function keptAttrs(ctx, path, element, where, tag) {
|
|
|
28
28
|
const kept = new Set(stripModifierProps(ctx, path, attributesOf(element), where));
|
|
29
29
|
return (element.openingElement.attributes ?? []).filter((a) => a.type === 'JSXSpreadAttribute' || kept.has(a));
|
|
30
30
|
}
|
|
31
|
-
const stripModifierProps = makeStripModifierProps(UNIVERSAL_PROPS, RESPONSIVE_BREAKPOINTS);
|
|
31
|
+
const stripModifierProps = makeStripModifierProps(UNIVERSAL_PROPS, RESPONSIVE_BREAKPOINTS, 'domRef');
|
|
32
32
|
const SPECIALS = {
|
|
33
33
|
/**
|
|
34
34
|
* RBC defaults Columns `multiline` to TRUE (Bulma and bestax default to
|
|
@@ -490,7 +490,6 @@ const SPECIALS = {
|
|
|
490
490
|
removeAttr(element, activeAttr);
|
|
491
491
|
}
|
|
492
492
|
liClass = mergeClassName(ctx, path, element, liClass, 'Breadcrumb.Item');
|
|
493
|
-
const anchorAttrs = keptAttrs(ctx, path, element, 'Breadcrumb.Item', 'a');
|
|
494
493
|
const children = element.children ?? [];
|
|
495
494
|
const solidChildren = children.filter((c) => !(c.type === 'JSXText' && c.value.trim() === ''));
|
|
496
495
|
// `<Breadcrumb.Item><a href>…</a></Breadcrumb.Item>` already carries its
|
|
@@ -501,11 +500,37 @@ const SPECIALS = {
|
|
|
501
500
|
solidChildren[0].openingElement.name.name === 'a'
|
|
502
501
|
? solidChildren[0]
|
|
503
502
|
: null;
|
|
503
|
+
// The strip below renames `domRef` to `ref`, so a collision with a `ref`
|
|
504
|
+
// the anchor already sets is settled here, while the prop still carries
|
|
505
|
+
// the name the user wrote.
|
|
506
|
+
const domRefAttr = findAttr(element, 'domRef');
|
|
507
|
+
if (existingAnchor && domRefAttr && findAttr(existingAnchor, 'ref')) {
|
|
508
|
+
removeAttr(element, domRefAttr);
|
|
509
|
+
addTodo(ctx, path, 'prop:domRef', 'Breadcrumb.Item `domRef` was dropped: its <a> child already sets `ref` — reconcile by hand');
|
|
510
|
+
}
|
|
511
|
+
const anchorAttrs = keptAttrs(ctx, path, element, 'Breadcrumb.Item', 'a');
|
|
504
512
|
if (existingAnchor && anchorAttrs.length > 0) {
|
|
505
|
-
|
|
513
|
+
// Merging onto an anchor the user already wrote keeps the rule
|
|
514
|
+
// `collapseOntoChild` does: the item's spreads go FIRST, as one block in
|
|
515
|
+
// source order, so the anchor's explicit props still win over them; and
|
|
516
|
+
// a named prop both set keeps the anchor's value and is flagged, since
|
|
517
|
+
// writing it twice does not compile.
|
|
518
|
+
const spreads = anchorAttrs.filter((a) => a.type === 'JSXSpreadAttribute');
|
|
519
|
+
const merged = [
|
|
520
|
+
...spreads,
|
|
506
521
|
...(existingAnchor.openingElement.attributes ?? []),
|
|
507
|
-
...anchorAttrs,
|
|
508
522
|
];
|
|
523
|
+
for (const attr of anchorAttrs) {
|
|
524
|
+
if (attr.type === 'JSXSpreadAttribute')
|
|
525
|
+
continue;
|
|
526
|
+
const name = attr.name.name;
|
|
527
|
+
if (findAttr(existingAnchor, name)) {
|
|
528
|
+
addTodo(ctx, path, `prop:${name}`, `Breadcrumb.Item \`${name}\` was dropped: its <a> child already sets \`${name}\` — reconcile by hand`);
|
|
529
|
+
continue;
|
|
530
|
+
}
|
|
531
|
+
merged.push(attr);
|
|
532
|
+
}
|
|
533
|
+
existingAnchor.openingElement.attributes = merged;
|
|
509
534
|
}
|
|
510
535
|
const anchor = existingAnchor ?? plainElement(j, 'a', undefined, anchorAttrs, children);
|
|
511
536
|
path.replace(plainElement(j, 'li', liClass, [], [anchor]));
|
|
@@ -519,6 +544,19 @@ const SPECIALS = {
|
|
|
519
544
|
if (findAttr(element, 'className')) {
|
|
520
545
|
addTodo(ctx, path, 'prop:className', 'Table.Container className; the container folded into `isResponsive` on its Table — re-apply the class by hand');
|
|
521
546
|
}
|
|
547
|
+
// The container element is gone after the fold. What it carried
|
|
548
|
+
// (`domRef`, `id`, handlers) applied to the wrapping div, and moving it
|
|
549
|
+
// onto the Table would put it on the <table> instead, so it is reported
|
|
550
|
+
// rather than carried. Only `className` used to be reported.
|
|
551
|
+
for (const attr of attributesOf(element)) {
|
|
552
|
+
const name = attr?.name?.name;
|
|
553
|
+
if (!name || name === 'className')
|
|
554
|
+
continue;
|
|
555
|
+
addTodo(ctx, path, `prop:${name}`, `Table.Container \`${name}\` was dropped: the container folded into \`isResponsive\` on its Table, so there is no element left to carry it — re-apply by hand`);
|
|
556
|
+
}
|
|
557
|
+
if ((element.openingElement.attributes ?? []).some((a) => a.type === 'JSXSpreadAttribute')) {
|
|
558
|
+
addTodo(ctx, path, 'prop:spread', 'Table.Container spread props were dropped: the container folded into `isResponsive` on its Table, so there is no element left to carry them — re-apply by hand');
|
|
559
|
+
}
|
|
522
560
|
const child = children[0];
|
|
523
561
|
addAttr(child, makeAttr(ctx.j, 'isResponsive'));
|
|
524
562
|
path.replace(child);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/react-bulma-components/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/react-bulma-components/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAoCvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA6wBpB"}
|
|
@@ -14,32 +14,16 @@
|
|
|
14
14
|
* statement plus an entry in the run report.
|
|
15
15
|
*/
|
|
16
16
|
import { MAPPING, UNIVERSAL_PROPS, resolveMapping } from './mapping.js';
|
|
17
|
-
import { addTodo, attributesOf, jsxNameParts, renameElement, } from '../_shared/jsx-utils.js';
|
|
17
|
+
import { addTodo, attributesOf, forgetJsxParens, jsxNameParts, renameElement, reprintDirectives, } from '../_shared/jsx-utils.js';
|
|
18
18
|
import { applyPropAction, applyUniversalProps } from '../_shared/props.js';
|
|
19
19
|
import { enforcePolymorphicProps } from '../_shared/polymorphic.js';
|
|
20
|
+
import { bestaxValueLocals, buildBestaxImport, carryPrunedComments, placeBestaxImport, seedBestaxImport, } from '../_shared/bestax-import.js';
|
|
21
|
+
import { rewriteStylesheetImports } from '../_shared/css-imports.js';
|
|
20
22
|
import { collectBoundNames, makeAliasRegistry, makeReserve, nameOf, prefersTabs, resolvesToBinding, } from '../_shared/imports.js';
|
|
21
23
|
import { flattenResponsiveProps } from './responsive.js';
|
|
22
24
|
import { RESPONSIVE_KINDS, runSpecial } from './specials.js';
|
|
23
25
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
24
26
|
const RBC = 'react-bulma-components';
|
|
25
|
-
const BESTAX = '@allxsmith/bestax-bulma';
|
|
26
|
-
const BULMA_CSS = 'bulma/css/bulma.min.css';
|
|
27
|
-
const BESTAX_CSS = '@allxsmith/bestax-bulma/bestax.css';
|
|
28
|
-
const EXTRAS_CSS = '@allxsmith/bestax-bulma/extras.css';
|
|
29
|
-
const BULMA_CSS_SPECIFIERS = new Set([
|
|
30
|
-
'bulma/css/bulma.css',
|
|
31
|
-
'bulma/css/bulma.min.css',
|
|
32
|
-
]);
|
|
33
|
-
const BESTAX_CSS_SPECIFIERS = new Set([
|
|
34
|
-
BESTAX_CSS,
|
|
35
|
-
'@allxsmith/bestax-bulma/bestax.min.css',
|
|
36
|
-
'@allxsmith/bestax-bulma/dist/bestax.css',
|
|
37
|
-
'@allxsmith/bestax-bulma/dist/bestax.min.css',
|
|
38
|
-
]);
|
|
39
|
-
const EXTRAS_CSS_SPECIFIERS = new Set([
|
|
40
|
-
EXTRAS_CSS,
|
|
41
|
-
'@allxsmith/bestax-bulma/dist/extras.css',
|
|
42
|
-
]);
|
|
43
27
|
export default function transform(fileInfo, api, options = {}) {
|
|
44
28
|
const j = api.jscodeshift;
|
|
45
29
|
const root = j(fileInfo.source);
|
|
@@ -105,60 +89,12 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
105
89
|
addTodo(ctx, p, 'imports', `\`export * from '${RBC}'\` was not migrated; re-export the bestax components you need by hand`);
|
|
106
90
|
});
|
|
107
91
|
// ---- 1a. Stylesheet imports (mode-driven) -----------------------------
|
|
108
|
-
// `
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
.paths()
|
|
115
|
-
.some(p => BESTAX_CSS_SPECIFIERS.has(String(p.node.source.value)));
|
|
116
|
-
root.find(j.ImportDeclaration).forEach(path => {
|
|
117
|
-
const source = String(path.node.source.value);
|
|
118
|
-
const isRbcCss = source.startsWith(`${RBC}/`) && source.endsWith('.css');
|
|
119
|
-
const isBulmaCss = BULMA_CSS_SPECIFIERS.has(source);
|
|
120
|
-
const isExtrasCss = EXTRAS_CSS_SPECIFIERS.has(source);
|
|
121
|
-
if (!isRbcCss && !isBulmaCss && !isExtrasCss)
|
|
122
|
-
return;
|
|
123
|
-
if (cssMode === 'bestax') {
|
|
124
|
-
if (isRbcCss || isBulmaCss) {
|
|
125
|
-
if (sawBestaxCss) {
|
|
126
|
-
path.prune(); // bestax.css already imported elsewhere in this file
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
path.node.source = j.stringLiteral(BESTAX_CSS);
|
|
130
|
-
sawBestaxCss = true;
|
|
131
|
-
}
|
|
132
|
-
ctx.dirty = true;
|
|
133
|
-
}
|
|
134
|
-
else if (isExtrasCss && sawBestaxCss) {
|
|
135
|
-
// bestax.css already contains the extras.
|
|
136
|
-
path.prune();
|
|
137
|
-
ctx.dirty = true;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
else if (cssMode === 'bulma') {
|
|
141
|
-
if (isRbcCss) {
|
|
142
|
-
path.node.source = j.stringLiteral(BULMA_CSS);
|
|
143
|
-
ctx.dirty = true;
|
|
144
|
-
}
|
|
145
|
-
if ((isRbcCss || isBulmaCss) && !sawBestaxCss) {
|
|
146
|
-
const hasExtras = root
|
|
147
|
-
.find(j.ImportDeclaration)
|
|
148
|
-
.paths()
|
|
149
|
-
.some(p => EXTRAS_CSS_SPECIFIERS.has(String(p.node.source.value)));
|
|
150
|
-
if (!hasExtras) {
|
|
151
|
-
// Themed Radio/Checkbox need the bestax extras next to plain Bulma.
|
|
152
|
-
path.insertAfter(j.importDeclaration([], j.stringLiteral(EXTRAS_CSS)));
|
|
153
|
-
ctx.dirty = true;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
else if (isRbcCss) {
|
|
158
|
-
// keep: minimal fix — the v3 bundled CSS no longer exists at all.
|
|
159
|
-
path.node.source = j.stringLiteral(BULMA_CSS);
|
|
160
|
-
addTodo(ctx, path, 'css', `replaced the react-bulma-components CSS import with '${BULMA_CSS}'; install bulma@^1 (see https://bestax.io/docs/guides/getting-started/installation)`);
|
|
161
|
-
}
|
|
92
|
+
// `keep` touches only the dead RBC v3 CSS import.
|
|
93
|
+
rewriteStylesheetImports(ctx, root, options.cssMode ?? 'bestax', {
|
|
94
|
+
sourceCss: {
|
|
95
|
+
is: specifier => specifier.startsWith(`${RBC}/`) && specifier.endsWith('.css'),
|
|
96
|
+
label: 'the react-bulma-components CSS import',
|
|
97
|
+
},
|
|
162
98
|
});
|
|
163
99
|
if (imports.size === 0 && !ctx.dirty) {
|
|
164
100
|
return undefined;
|
|
@@ -343,46 +279,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
343
279
|
bound.add(head);
|
|
344
280
|
});
|
|
345
281
|
ctx.reserve = makeReserve(ctx, bound);
|
|
346
|
-
|
|
347
|
-
// existing bestax import's specifiers below (so JSX reuses their locals),
|
|
348
|
-
// and that seeding alone must not turn a type-only specifier into a value
|
|
349
|
-
// import nobody needed.
|
|
350
|
-
const requested = new Set();
|
|
351
|
-
const baseReserve = ctx.reserve;
|
|
352
|
-
ctx.reserve = root => {
|
|
353
|
-
requested.add(root);
|
|
354
|
-
return baseReserve(root);
|
|
355
|
-
};
|
|
356
|
-
// Merge with an existing bestax import: reuse its locals verbatim.
|
|
357
|
-
// Only a declaration made entirely of NAMED specifiers can be merged into.
|
|
358
|
-
// `import * as Bulma from '@allxsmith/bestax-bulma'` matches the source too,
|
|
359
|
-
// and appending named specifiers to it emitted
|
|
360
|
-
// `import * as Bulma, { Box } from …` — not valid JavaScript, so the whole
|
|
361
|
-
// file failed to parse after a migration that reported success.
|
|
362
|
-
const existingBestax = root
|
|
363
|
-
.find(j.ImportDeclaration, { source: { value: BESTAX } })
|
|
364
|
-
.paths()
|
|
365
|
-
.find(path =>
|
|
366
|
-
// A type-only declaration cannot take a value specifier: merging a
|
|
367
|
-
// component into `import type { … }` erases it at runtime.
|
|
368
|
-
path.node.importKind !== 'type' &&
|
|
369
|
-
(path.node.specifiers ?? []).every((spec) => spec.type === 'ImportSpecifier'));
|
|
370
|
-
const preExistingImports = new Set();
|
|
371
|
-
if (existingBestax) {
|
|
372
|
-
for (const spec of existingBestax.node.specifiers ?? []) {
|
|
373
|
-
if (spec.type === 'ImportSpecifier' && spec.local) {
|
|
374
|
-
// The local name is reused either way, so the JSX never needs an
|
|
375
|
-
// alias. But an inline `type` specifier (`import { type Box }`) is
|
|
376
|
-
// not a value binding: it is not counted as already imported, so the
|
|
377
|
-
// component is written as a value below — onto this specifier, which
|
|
378
|
-
// keeps its name, rather than as a duplicate.
|
|
379
|
-
ctx.needed.set(nameOf(spec.imported), nameOf(spec.local));
|
|
380
|
-
if (spec.importKind !== 'type') {
|
|
381
|
-
preExistingImports.add(nameOf(spec.imported));
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
}
|
|
282
|
+
const bestaxImportState = seedBestaxImport(ctx, root);
|
|
386
283
|
// ---- 2. Transform JSX elements ----------------------------------------
|
|
387
284
|
root.find(j.JSXElement).forEach(path => {
|
|
388
285
|
const element = path.node;
|
|
@@ -745,62 +642,13 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
745
642
|
// ---- 3. Rewrite imports -----------------------------------------------
|
|
746
643
|
if (imports.size > 0) {
|
|
747
644
|
const retainedNames = [...ctx.retained].sort((a, b) => a.localeCompare(b));
|
|
748
|
-
const
|
|
749
|
-
.filter(([imported]) => requested.has(imported) && !preExistingImports.has(imported))
|
|
750
|
-
.sort((a, b) => a[0].localeCompare(b[0]));
|
|
751
|
-
const bestaxImport = freshNames.length > 0
|
|
752
|
-
? j.importDeclaration(freshNames.map(([imported, local]) => j.importSpecifier(j.identifier(imported), j.identifier(local))), j.stringLiteral(BESTAX))
|
|
753
|
-
: null;
|
|
754
|
-
/**
|
|
755
|
-
|
|
756
|
-
* A pruned declaration takes its comments with it — a licence header, an
|
|
757
|
-
|
|
758
|
-
* eslint directive. Hand them to what replaces it, or to the next statement.
|
|
759
|
-
|
|
760
|
-
*/
|
|
761
|
-
const carryComments = (node, importPath) => {
|
|
762
|
-
const comments = node.comments ?? [];
|
|
763
|
-
if (comments.length === 0)
|
|
764
|
-
return;
|
|
765
|
-
const body = importPath.parent?.node?.body ?? [];
|
|
766
|
-
const index = body.indexOf(node);
|
|
767
|
-
// The fresh specifiers are merged INTO an existing bestax import when there
|
|
768
|
-
// is one, and the `bestaxImport` node is then discarded — so the comments
|
|
769
|
-
// have to follow the declaration that survives, not the one that does not.
|
|
770
|
-
const carrier = (existingBestax ? existingBestax.node : bestaxImport) ??
|
|
771
|
-
(index >= 0 ? body[index + 1] : undefined);
|
|
772
|
-
if (carrier) {
|
|
773
|
-
carrier.comments = [...comments, ...(carrier.comments ?? [])];
|
|
774
|
-
}
|
|
775
|
-
else if (index > 0) {
|
|
776
|
-
// The import was the last statement: the comments stay where they
|
|
777
|
-
// were, after what precedes it.
|
|
778
|
-
const previous = body[index - 1];
|
|
779
|
-
previous.comments = [
|
|
780
|
-
...(previous.comments ?? []),
|
|
781
|
-
...comments.map((c) => ({
|
|
782
|
-
...c,
|
|
783
|
-
leading: false,
|
|
784
|
-
trailing: true,
|
|
785
|
-
})),
|
|
786
|
-
];
|
|
787
|
-
}
|
|
788
|
-
else {
|
|
789
|
-
// The import was the only statement: the comments become the file's.
|
|
790
|
-
const program = importPath.parent?.node;
|
|
791
|
-
if (program)
|
|
792
|
-
program.comments = [...comments, ...(program.comments ?? [])];
|
|
793
|
-
}
|
|
794
|
-
node.comments = [];
|
|
795
|
-
};
|
|
645
|
+
const bestaxImport = buildBestaxImport(ctx, bestaxImportState);
|
|
796
646
|
let inserted = false;
|
|
797
647
|
// A retained RBC specifier must never collide with a bestax import local
|
|
798
648
|
// (possible when one component is both JSX-migrated and value-retained).
|
|
799
649
|
// Only a VALUE local can collide at runtime: a type-only specifier the
|
|
800
650
|
// seeding above recorded, and nothing promoted, binds no value.
|
|
801
|
-
const bestaxLocals =
|
|
802
|
-
.filter(([imported]) => requested.has(imported) || preExistingImports.has(imported))
|
|
803
|
-
.map(([, local]) => local));
|
|
651
|
+
const bestaxLocals = bestaxValueLocals(ctx, bestaxImportState);
|
|
804
652
|
for (const path of rbcImportPaths) {
|
|
805
653
|
const node = path.node;
|
|
806
654
|
const keepSpecifiers = (node.specifiers ?? []).filter((spec) => {
|
|
@@ -815,28 +663,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
815
663
|
!bestaxLocals.has(nameOf(spec.local)));
|
|
816
664
|
});
|
|
817
665
|
if (!inserted) {
|
|
818
|
-
|
|
819
|
-
const current = existingBestax.node.specifiers ?? [];
|
|
820
|
-
const appended = [];
|
|
821
|
-
for (const fresh of bestaxImport.specifiers) {
|
|
822
|
-
// A type-only specifier for the same name becomes the value
|
|
823
|
-
// import (a value import carries the type too); appending a
|
|
824
|
-
// second `Box` beside `type Box` would be a duplicate identifier.
|
|
825
|
-
const typeOnly = current.find((spec) => spec.type === 'ImportSpecifier' &&
|
|
826
|
-
spec.importKind === 'type' &&
|
|
827
|
-
nameOf(spec.imported) === nameOf(fresh.imported));
|
|
828
|
-
if (typeOnly) {
|
|
829
|
-
typeOnly.importKind = null;
|
|
830
|
-
}
|
|
831
|
-
else {
|
|
832
|
-
appended.push(fresh);
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
existingBestax.node.specifiers = [...current, ...appended];
|
|
836
|
-
}
|
|
837
|
-
else if (bestaxImport) {
|
|
838
|
-
path.insertBefore(bestaxImport);
|
|
839
|
-
}
|
|
666
|
+
placeBestaxImport(bestaxImportState, bestaxImport, path);
|
|
840
667
|
inserted = true;
|
|
841
668
|
}
|
|
842
669
|
if (keepSpecifiers.length > 0) {
|
|
@@ -848,7 +675,7 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
848
675
|
}
|
|
849
676
|
}
|
|
850
677
|
else {
|
|
851
|
-
|
|
678
|
+
carryPrunedComments(node, path, bestaxImportState.existing?.node ?? bestaxImport);
|
|
852
679
|
path.prune();
|
|
853
680
|
}
|
|
854
681
|
ctx.dirty = true;
|
|
@@ -856,6 +683,8 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
856
683
|
}
|
|
857
684
|
if (!ctx.dirty)
|
|
858
685
|
return undefined;
|
|
686
|
+
forgetJsxParens(j, root);
|
|
687
|
+
reprintDirectives(j, root);
|
|
859
688
|
// Double quotes match the dominant JSX-attribute convention; users run
|
|
860
689
|
// their own formatter afterwards anyway. Tab-indented sources keep tabs so
|
|
861
690
|
// reprinted nodes don't drift from the untouched lines around them.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sources/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/sources/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAMnD,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAKnD,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEnE;AAED,wBAAgB,WAAW,IAAI,MAAM,EAAE,CAEtC"}
|
package/dist/sources/registry.js
CHANGED
|
@@ -5,10 +5,12 @@
|
|
|
5
5
|
import { reactBulmaComponents } from './react-bulma-components/index.js';
|
|
6
6
|
import { rbx } from './rbx/index.js';
|
|
7
7
|
import { bloomer } from './bloomer/index.js';
|
|
8
|
+
import { bulmaClasses } from './bulma-classes/index.js';
|
|
8
9
|
export const SOURCES = {
|
|
9
10
|
[reactBulmaComponents.name]: reactBulmaComponents,
|
|
10
11
|
[rbx.name]: rbx,
|
|
11
12
|
[bloomer.name]: bloomer,
|
|
13
|
+
[bulmaClasses.name]: bulmaClasses,
|
|
12
14
|
};
|
|
13
15
|
export function getSource(name) {
|
|
14
16
|
return SOURCES[name];
|
package/dist/types.d.ts
CHANGED
|
@@ -141,6 +141,31 @@ export interface MigrationSource {
|
|
|
141
141
|
name: string;
|
|
142
142
|
/** Human-readable label for the report header. */
|
|
143
143
|
label: string;
|
|
144
|
+
/**
|
|
145
|
+
* The npm package this source migrates away from, when it is not `name`.
|
|
146
|
+
* `null` for a source with no package to move off: nothing is looked for
|
|
147
|
+
* in imports, and the manifest pass is never told the source is still
|
|
148
|
+
* imported.
|
|
149
|
+
*/
|
|
150
|
+
packageName?: string | null;
|
|
151
|
+
/**
|
|
152
|
+
* Facts about the project, read once from the run's targets and passed to
|
|
153
|
+
* every transform call as options.
|
|
154
|
+
*/
|
|
155
|
+
analyzeProject?: (targets: string[]) => object;
|
|
156
|
+
/** The `--css` mode when the run names none; `bestax` when omitted. */
|
|
157
|
+
defaultCssMode?: CssMode;
|
|
158
|
+
/**
|
|
159
|
+
* For a source with no package: the 1-based line of the first thing in an
|
|
160
|
+
* unparseable file (`.mdx`, `.vue`, …) that the source would have converted,
|
|
161
|
+
* or null. Such files are reported, never rewritten.
|
|
162
|
+
*/
|
|
163
|
+
findUnsupportedReference?: (text: string) => number | null;
|
|
164
|
+
/**
|
|
165
|
+
* Which of the unparseable formats `findUnsupportedReference` scans; all
|
|
166
|
+
* of them when omitted.
|
|
167
|
+
*/
|
|
168
|
+
unsupportedExtensions?: readonly string[];
|
|
144
169
|
transform: Transform;
|
|
145
170
|
transformStyles?: StylesTransform;
|
|
146
171
|
updateDependencies?: DependenciesUpdate;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bestax-migrate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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.16.
|
|
41
|
+
"@allxsmith/bestax-bulma": "^5.16.9"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@jest/globals": "^30.0.0",
|
|
@@ -67,10 +67,11 @@
|
|
|
67
67
|
"validate:corpus": "pnpm run build && node scripts/validate-corpus.mjs",
|
|
68
68
|
"validate:corpus:rbx": "pnpm run build && node scripts/validate-corpus-rbx.mjs",
|
|
69
69
|
"validate:corpus:bloomer": "pnpm run build && node scripts/validate-corpus-bloomer.mjs",
|
|
70
|
+
"validate:corpus:bulma-classes": "pnpm run build && node scripts/validate-corpus-bulma-classes.mjs",
|
|
70
71
|
"format": "prettier --write \"src/**/*.{ts,tsx}\" \"e2e/**/*.ts\"",
|
|
71
72
|
"format:check": "prettier --check \"src/**/*.{ts,tsx}\" \"e2e/**/*.ts\"",
|
|
72
73
|
"clean": "rimraf dist",
|
|
73
74
|
"release": "npx semantic-release"
|
|
74
75
|
},
|
|
75
|
-
"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 source libraries:\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\nPass the source library 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\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- 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\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)), 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` (default), `bulma`, or `keep` |\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).\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"
|
|
76
|
+
"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"
|
|
76
77
|
}
|