bestax-migrate 2.3.7 → 2.3.9

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.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +16 -6
  5. package/dist/sources/_shared/bestax-import.d.ts +45 -0
  6. package/dist/sources/_shared/bestax-import.d.ts.map +1 -0
  7. package/dist/sources/_shared/bestax-import.js +141 -0
  8. package/dist/sources/_shared/css-imports.d.ts +33 -0
  9. package/dist/sources/_shared/css-imports.d.ts.map +1 -0
  10. package/dist/sources/_shared/css-imports.js +103 -0
  11. package/dist/sources/_shared/deps-common.d.ts +46 -0
  12. package/dist/sources/_shared/deps-common.d.ts.map +1 -0
  13. package/dist/sources/_shared/deps-common.js +98 -0
  14. package/dist/sources/_shared/make-styles-transform.d.ts +6 -2
  15. package/dist/sources/_shared/make-styles-transform.d.ts.map +1 -1
  16. package/dist/sources/_shared/make-styles-transform.js +12 -4
  17. package/dist/sources/_shared/specials-utils.d.ts +1 -1
  18. package/dist/sources/_shared/specials-utils.d.ts.map +1 -1
  19. package/dist/sources/_shared/specials-utils.js +19 -1
  20. package/dist/sources/bloomer/deps.d.ts.map +1 -1
  21. package/dist/sources/bloomer/deps.js +14 -89
  22. package/dist/sources/bloomer/transform.d.ts.map +1 -1
  23. package/dist/sources/bloomer/transform.js +9 -185
  24. package/dist/sources/rbx/deps.d.ts.map +1 -1
  25. package/dist/sources/rbx/deps.js +29 -117
  26. package/dist/sources/rbx/mapping.d.ts.map +1 -1
  27. package/dist/sources/rbx/mapping.js +9 -1
  28. package/dist/sources/rbx/specials.d.ts.map +1 -1
  29. package/dist/sources/rbx/specials.js +20 -10
  30. package/dist/sources/rbx/transform.d.ts.map +1 -1
  31. package/dist/sources/rbx/transform.js +19 -203
  32. package/dist/sources/react-bulma-components/deps.d.ts.map +1 -1
  33. package/dist/sources/react-bulma-components/deps.js +12 -87
  34. package/dist/sources/react-bulma-components/mapping.js +1 -1
  35. package/dist/sources/react-bulma-components/specials.d.ts.map +1 -1
  36. package/dist/sources/react-bulma-components/specials.js +42 -4
  37. package/dist/sources/react-bulma-components/transform.d.ts.map +1 -1
  38. package/dist/sources/react-bulma-components/transform.js +13 -186
  39. package/dist/types.d.ts +7 -0
  40. package/dist/types.d.ts.map +1 -1
  41. package/package.json +3 -3
@@ -17,29 +17,13 @@ import { MAPPING, UNIVERSAL_PROPS, resolveMapping } from './mapping.js';
17
17
  import { addTodo, attributesOf, jsxNameParts, renameElement, } 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
- // `bestax` (default): everything converges on the recommended combined
109
- // bundle. `bulma`: plain Bulma v1 CSS plus the separate extras file.
110
- // `keep`: only the dead RBC v3 CSS import is touched.
111
- const cssMode = options.cssMode ?? 'bestax';
112
- let sawBestaxCss = root
113
- .find(j.ImportDeclaration)
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
- // Names the passes actually asked for. `ctx.needed` is also seeded from an
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 freshNames = [...ctx.needed.entries()]
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 = new Set([...ctx.needed.entries()]
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
- if (existingBestax && bestaxImport) {
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
- carryComments(node, path);
678
+ carryPrunedComments(node, path, bestaxImportState.existing?.node ?? bestaxImport);
852
679
  path.prune();
853
680
  }
854
681
  ctx.dirty = true;
package/dist/types.d.ts CHANGED
@@ -141,6 +141,13 @@ 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;
144
151
  transform: Transform;
145
152
  transformStyles?: StylesTransform;
146
153
  updateDependencies?: DependenciesUpdate;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEjD;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAE1D,0DAA0D;AAC1D,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sEAAsE;IACtE,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,aAAa,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjD;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qCAAqC;IACrC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACpC;AAED,4EAA4E;AAC5E,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,kEAAkE;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CACzC;AAED,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,SAAS,EAAE,CAAC;CACpB;AAED,sEAAsE;AACtE,MAAM,WAAW,aAAa;IAC5B,GAAG,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,MAAM,MAAM,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAElD,uEAAuE;AACvE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;OAKG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,uDAAuD;AACvD,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,uEAAuE;IACvE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,mDAAmD;AACnD,MAAM,MAAM,SAAS,GAAG,CACtB,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,gBAAgB,KACtB,MAAM,GAAG,SAAS,CAAC;AAExB,+DAA+D;AAC/D,MAAM,MAAM,eAAe,GAAG,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,aAAa,GAAG,SAAS,EACpC,OAAO,EAAE,gBAAgB,KACtB,MAAM,GAAG,IAAI,CAAC;AAEnB,kEAAkE;AAClE,MAAM,MAAM,kBAAkB,GAAG,CAC/B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,EAAE,aAAa,GAAG,SAAS,EACpC,OAAO,EAAE,WAAW,KACjB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;AAEpC,kDAAkD;AAClD,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,kBAAkB,CAAC,EAAE,kBAAkB,CAAC;CACzC"}
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.7",
3
+ "version": "2.3.9",
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.4"
41
+ "@allxsmith/bestax-bulma": "^5.16.9"
42
42
  },
43
43
  "devDependencies": {
44
44
  "@jest/globals": "^30.0.0",
@@ -72,5 +72,5 @@
72
72
  "clean": "rimraf dist",
73
73
  "release": "npx semantic-release"
74
74
  },
75
- "readme": "# bestax-migrate\n\n[![npm version](https://img.shields.io/npm/v/bestax-migrate.svg)](https://www.npmjs.com/package/bestax-migrate)\n[![npm downloads](https://img.shields.io/npm/dm/bestax-migrate.svg)](https://www.npmjs.com/package/bestax-migrate)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Socket Badge](https://socket.dev/api/badge/npm/package/bestax-migrate)](https://socket.dev/npm/package/bestax-migrate/overview)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/allxsmith/bestax/badge)](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/14361/badge)](https://www.bestpractices.dev/projects/14361)\n[![npm provenance](https://img.shields.io/badge/npm-provenance-3fb950.svg)](https://www.npmjs.com/package/bestax-migrate#provenance)\n[![Security policy](https://img.shields.io/badge/security-policy-blue.svg)](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"
75
+ "readme": "# bestax-migrate\n\n[![npm version](https://img.shields.io/npm/v/bestax-migrate.svg)](https://www.npmjs.com/package/bestax-migrate)\n[![npm downloads](https://img.shields.io/npm/dm/bestax-migrate.svg)](https://www.npmjs.com/package/bestax-migrate)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Socket Badge](https://badge.socket.dev/npm/package/bestax-migrate/latest)](https://socket.dev/npm/package/bestax-migrate/overview)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/allxsmith/bestax/badge)](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/14361/badge)](https://www.bestpractices.dev/projects/14361)\n[![npm provenance](https://img.shields.io/badge/npm-provenance-3fb950.svg)](https://www.npmjs.com/package/bestax-migrate#provenance)\n[![Security policy](https://img.shields.io/badge/security-policy-blue.svg)](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
76
  }