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
@@ -29,7 +29,7 @@ export declare function alignTarget(ctx: TransformContext, path: ASTPath<any>, e
29
29
  * bound for a plain HTML element (they only exist on bestax components),
30
30
  * leaving a TODO when any were dropped.
31
31
  */
32
- export declare function makeStripModifierProps(universalProps: Record<string, PropAction>, responsiveBreakpoints: Record<string, string | null>): (ctx: TransformContext, path: ASTPath<any>, attrs: any[], where: string) => any[];
32
+ export declare function makeStripModifierProps(universalProps: Record<string, PropAction>, responsiveBreakpoints: Record<string, string | null>, refProp?: string): (ctx: TransformContext, path: ASTPath<any>, attrs: any[], where: string) => any[];
33
33
  /**
34
34
  * Consume the element's `className` so a plain-element rewrite can merge it
35
35
  * with its hard-coded Bulma class instead of dropping it. A dynamic value
@@ -1 +1 @@
1
- {"version":3,"file":"specials-utils.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/specials-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"specials-utils.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/specials-utils.ts"],"names":[],"mappings":"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"}
@@ -39,12 +39,30 @@ export function alignTarget(ctx, path, element, prop, targets, fallback) {
39
39
  * bound for a plain HTML element (they only exist on bestax components),
40
40
  * leaving a TODO when any were dropped.
41
41
  */
42
- export function makeStripModifierProps(universalProps, responsiveBreakpoints) {
42
+ export function makeStripModifierProps(universalProps, responsiveBreakpoints, refProp) {
43
43
  return function stripModifierProps(ctx, path, attrs, where) {
44
44
  const kept = [];
45
45
  const dropped = [];
46
46
  for (const attr of attrs) {
47
47
  const name = attr?.name?.name;
48
+ // Both sources keep their ref escape hatch (`innerRef`, `domRef`) in
49
+ // the universal table so an unmapped one is flagged rather than passed
50
+ // through in silence. Neither is a Bulma modifier, and the intrinsic
51
+ // tag this rewrite produces takes a real `ref` — so it is renamed onto
52
+ // the tag here. Dropping it would delete a working ref and tell the
53
+ // user to "restyle with classes", which is advice for a modifier.
54
+ // The same collision `applyPropAction` guards: with a `ref` already on
55
+ // the element the rename would emit two, which does not compile.
56
+ if (refProp && name === refProp) {
57
+ if (attrs.some(other => other?.name?.name === 'ref')) {
58
+ addTodo(ctx, path, `prop:${refProp}`, `${where}: \`${refProp}\` maps to \`ref\`, but \`ref\` is already set on this element, so \`${refProp}\` was dropped — reconcile by hand`);
59
+ continue;
60
+ }
61
+ attr.name = ctx.j.jsxIdentifier('ref');
62
+ ctx.dirty = true;
63
+ kept.push(attr);
64
+ continue;
65
+ }
48
66
  if (name && (universalProps[name] || name in responsiveBreakpoints)) {
49
67
  dropped.push(name);
50
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/sources/bloomer/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUzD,eAAO,MAAM,kBAAkB,EAAE,kBAsHhC,CAAC"}
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/sources/bloomer/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAUzD,eAAO,MAAM,kBAAkB,EAAE,kBAwChC,CAAC"}
@@ -12,28 +12,17 @@
12
12
  * not the app's; if they appear here the app declared them for its own
13
13
  * reasons, so they are left alone.
14
14
  */
15
- import { isPreV1 } from '../_shared/semver-range.js';
16
- const BESTAX_RANGE = '^5';
17
- const BULMA_RANGE = '^1.0.4';
18
- // Bulma v1's sass tree uses `color.channel(…)` — needs dart-sass ≥ 1.79.
19
- const SASS_RANGE = '^1.79.0';
20
- const DEP_SECTIONS = ['dependencies', 'devDependencies'];
15
+ import { DEP_SECTIONS, addBestax, moveBulmaToV1, openManifest, replaceNodeSass, reportPeerRanges, } from '../_shared/deps-common.js';
21
16
  export const updateDependencies = (filePath, pkg, collector, options) => {
22
- const changes = [];
23
- const next = pkg;
24
- const section = (name) => (next[name] ?? undefined);
25
- const note = (message) => {
26
- changes.push(message);
27
- collector?.add({ file: filePath, line: null, rule: 'deps', message });
28
- };
17
+ const manifest = openManifest(filePath, pkg, collector);
29
18
  // bloomer goes away entirely.
30
19
  let removedSource = false;
31
20
  for (const name of DEP_SECTIONS) {
32
- const deps = section(name);
21
+ const deps = manifest.section(name);
33
22
  if (deps && 'bloomer' in deps) {
34
23
  delete deps.bloomer;
35
24
  removedSource = true;
36
- note(`removed bloomer from ${name}`);
25
+ manifest.note(`removed bloomer from ${name}`);
37
26
  }
38
27
  }
39
28
  // The transform deliberately RETAINS imports for components with no bestax
@@ -42,78 +31,14 @@ export const updateDependencies = (filePath, pkg, collector, options) => {
42
31
  // imports once the user runs the install the report asks for, so say so
43
32
  // rather than letting them find out at build time.
44
33
  if (removedSource && options.sourceStillImported) {
45
- collector?.add({
46
- file: filePath,
47
- line: null,
48
- rule: 'deps',
49
- message: 'bloomer 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 bloomer until you have',
50
- });
51
- }
52
- // @allxsmith/bestax-bulma comes in (runtime dependency).
53
- const dependencies = (next.dependencies ??= {});
54
- if (!dependencies['@allxsmith/bestax-bulma'] &&
55
- !section('devDependencies')?.['@allxsmith/bestax-bulma']) {
56
- dependencies['@allxsmith/bestax-bulma'] = BESTAX_RANGE;
57
- note(`added @allxsmith/bestax-bulma ${BESTAX_RANGE} to dependencies`);
58
- }
59
- // Bulma: bump a pre-1 range; add only when sources still reference bulma/…
60
- // directly (otherwise it arrives transitively via bestax-bulma).
61
- let bulmaDeclared = false;
62
- for (const name of DEP_SECTIONS) {
63
- const deps = section(name);
64
- if (deps?.bulma) {
65
- bulmaDeclared = true;
66
- if (isPreV1(deps.bulma)) {
67
- deps.bulma = BULMA_RANGE;
68
- note(`bumped bulma to ${BULMA_RANGE} in ${name} (was pre-1.0)`);
69
- }
70
- }
71
- }
72
- if (!bulmaDeclared && options.bulmaReferenced) {
73
- dependencies.bulma = BULMA_RANGE;
74
- note(`added bulma ${BULMA_RANGE} to dependencies (sources import bulma/… directly)`);
75
- }
76
- // bestax-bulma requires React 18/19; bloomer peer-depended on React ^16.2.
77
- // Report only — a React major upgrade is the app's own migration step.
78
- for (const name of DEP_SECTIONS) {
79
- const range = section(name)?.react;
80
- if (range && /^[~^]?(?:[0-9]|1[0-7])(?:[.x]|$)/.test(range.trim())) {
81
- collector?.add({
82
- file: filePath,
83
- line: null,
84
- rule: 'peer-deps',
85
- message: `react ${range} predates bestax-bulma's peer range (^18 || ^19) — upgrade react and react-dom to 18 or 19 before installing`,
86
- });
87
- }
88
- }
89
- // Font Awesome older than 6 conflicts with bestax-bulma's optional peer
90
- // range and makes `npm install` fail with ERESOLVE. Report only — icon
91
- // names change across FA majors, so upgrading is the app's decision. (A
92
- // bloomer-era app more often loads Font Awesome 4 from a CDN <link>, which
93
- // no manifest pass can see; the Icon conversion flags those in the code.)
94
- for (const name of DEP_SECTIONS) {
95
- const range = section(name)?.['@fortawesome/fontawesome-free'];
96
- if (range && /^[~^]?[0-5](?:[.x]|$)/.test(range.trim())) {
97
- collector?.add({
98
- file: filePath,
99
- line: null,
100
- rule: 'peer-deps',
101
- 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\``,
102
- });
103
- }
104
- }
105
- // node-sass is dead; dart-sass replaces it in the same section.
106
- for (const name of DEP_SECTIONS) {
107
- const deps = section(name);
108
- if (deps && 'node-sass' in deps) {
109
- delete deps['node-sass'];
110
- note(`removed node-sass from ${name}`);
111
- const sassDeclared = DEP_SECTIONS.some(s => section(s)?.sass);
112
- if (!sassDeclared) {
113
- deps.sass = SASS_RANGE;
114
- note(`added sass ${SASS_RANGE} to ${name} (replaces node-sass)`);
115
- }
116
- }
117
- }
118
- return changes.length > 0 ? next : null;
34
+ manifest.report('deps', 'bloomer 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 bloomer until you have');
35
+ }
36
+ addBestax(manifest);
37
+ moveBulmaToV1(manifest, options.bulmaReferenced);
38
+ // bloomer peer-depended on React ^16.2. A bloomer-era app more often loads
39
+ // Font Awesome 4 from a CDN <link>, which no manifest pass can see; the Icon
40
+ // conversion flags those in the code.
41
+ reportPeerRanges(manifest);
42
+ replaceNodeSass(manifest);
43
+ return manifest.result();
119
44
  };
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bloomer/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAwDvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA86BpB"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bloomer/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AA8CvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA4uBpB"}
@@ -25,28 +25,13 @@ import { HELPERLESS_TARGETS, MAPPING, NO_CLASSNAME_TARGETS, UNIVERSAL_PROPS, hel
25
25
  import { addTodo, attributesOf, jsxNameParts, literalValueOf, removeAttr, renameElement, } from '../_shared/jsx-utils.js';
26
26
  import { applyPropAction, applyUniversalProps, mergeClass, } from '../_shared/props.js';
27
27
  import { enforcePolymorphicProps } from '../_shared/polymorphic.js';
28
+ import { bestaxValueLocals, buildBestaxImport, carryPrunedComments, placeBestaxImport, seedBestaxImport, } from '../_shared/bestax-import.js';
29
+ import { rewriteStylesheetImports } from '../_shared/css-imports.js';
28
30
  import { collectBoundNames, makeReserve, nameOf, prefersTabs, resolvesToBinding, } from '../_shared/imports.js';
29
31
  import { flattenResponsiveProps, RESPONSIVE_KINDS } from './responsive.js';
30
32
  import { runSpecial } from './specials.js';
31
33
  /* eslint-disable @typescript-eslint/no-explicit-any */
32
34
  const BLOOMER = 'bloomer';
33
- const BESTAX = '@allxsmith/bestax-bulma';
34
- const BESTAX_CSS = '@allxsmith/bestax-bulma/bestax.css';
35
- const EXTRAS_CSS = '@allxsmith/bestax-bulma/extras.css';
36
- const BULMA_CSS_SPECIFIERS = new Set([
37
- 'bulma/css/bulma.css',
38
- 'bulma/css/bulma.min.css',
39
- ]);
40
- const BESTAX_CSS_SPECIFIERS = new Set([
41
- BESTAX_CSS,
42
- '@allxsmith/bestax-bulma/bestax.min.css',
43
- '@allxsmith/bestax-bulma/dist/bestax.css',
44
- '@allxsmith/bestax-bulma/dist/bestax.min.css',
45
- ]);
46
- const EXTRAS_CSS_SPECIFIERS = new Set([
47
- EXTRAS_CSS,
48
- '@allxsmith/bestax-bulma/dist/extras.css',
49
- ]);
50
35
  export default function transform(fileInfo, api, options = {}) {
51
36
  const j = api.jscodeshift;
52
37
  const root = j(fileInfo.source);
@@ -116,61 +101,8 @@ export default function transform(fileInfo, api, options = {}) {
116
101
  addTodo(ctx, p, 'imports', `\`export * from '${BLOOMER}'\` was not migrated; re-export the bestax components you need by hand`);
117
102
  });
118
103
  // ---- 1a. Stylesheet imports (mode-driven) -----------------------------
119
- // `bestax` (default): everything converges on the recommended combined
120
- // bundle. `bulma`: plain Bulma v1 CSS plus the separate extras file.
121
- // `keep`: nothing to do — bloomer has no stylesheet of its own.
122
- const cssMode = options.cssMode ?? 'bestax';
123
- let sawBestaxCss = root
124
- .find(j.ImportDeclaration)
125
- .paths()
126
- .some(p => BESTAX_CSS_SPECIFIERS.has(String(p.node.source.value)));
127
- // Whether some import in this file will become bestax.css, regardless of
128
- // where it sits relative to an existing extras import.
129
- const willAdoptBestaxCss = cssMode === 'bestax' &&
130
- root
131
- .find(j.ImportDeclaration)
132
- .paths()
133
- .some(p => BULMA_CSS_SPECIFIERS.has(String(p.node.source.value)));
134
- root.find(j.ImportDeclaration).forEach(path => {
135
- const source = String(path.node.source.value);
136
- const isBulmaCss = BULMA_CSS_SPECIFIERS.has(source);
137
- const isExtrasCss = EXTRAS_CSS_SPECIFIERS.has(source);
138
- if (!isBulmaCss && !isExtrasCss)
139
- return;
140
- if (cssMode === 'bestax') {
141
- if (isBulmaCss) {
142
- if (sawBestaxCss) {
143
- path.prune(); // bestax.css already imported elsewhere in this file
144
- }
145
- else {
146
- path.node.source = j.stringLiteral(BESTAX_CSS);
147
- sawBestaxCss = true;
148
- }
149
- ctx.dirty = true;
150
- }
151
- else if (isExtrasCss && (sawBestaxCss || willAdoptBestaxCss)) {
152
- // bestax.css already contains the extras. `willAdoptBestaxCss` covers
153
- // the case where the extras import comes FIRST in the file and the
154
- // bulma import that becomes bestax.css has not been visited yet —
155
- // previously the extras survived alongside it and double-loaded.
156
- path.prune();
157
- ctx.dirty = true;
158
- }
159
- }
160
- else if (cssMode === 'bulma') {
161
- if (isBulmaCss && !sawBestaxCss) {
162
- const hasExtras = root
163
- .find(j.ImportDeclaration)
164
- .paths()
165
- .some(p => EXTRAS_CSS_SPECIFIERS.has(String(p.node.source.value)));
166
- if (!hasExtras) {
167
- // Themed Radio/Checkbox need the bestax extras next to plain Bulma.
168
- path.insertAfter(j.importDeclaration([], j.stringLiteral(EXTRAS_CSS)));
169
- ctx.dirty = true;
170
- }
171
- }
172
- }
173
- });
104
+ // bloomer has no stylesheet of its own, so `keep` has nothing to do.
105
+ rewriteStylesheetImports(ctx, root, options.cssMode ?? 'bestax');
174
106
  if (imports.size === 0 && !ctx.dirty) {
175
107
  return undefined;
176
108
  }
@@ -283,45 +215,7 @@ export default function transform(fileInfo, api, options = {}) {
283
215
  bound.add(head);
284
216
  });
285
217
  ctx.reserve = makeReserve(ctx, bound);
286
- // Names the passes actually asked for. `ctx.needed` is also seeded from an
287
- // existing bestax import's specifiers below (so JSX reuses their locals),
288
- // and that seeding alone must not turn a type-only specifier into a value
289
- // import nobody needed.
290
- const requested = new Set();
291
- const baseReserve = ctx.reserve;
292
- ctx.reserve = root => {
293
- requested.add(root);
294
- return baseReserve(root);
295
- };
296
- // Merge with an existing bestax import: reuse its locals verbatim.
297
- // Only a declaration that already uses NAMED specifiers can absorb more of
298
- // them. `import * as Bestax from '…'` cannot: a namespace specifier may not
299
- // share a declaration with named ones, and appending to it emits a file
300
- // that does not parse.
301
- const existingBestax = root
302
- .find(j.ImportDeclaration, { source: { value: BESTAX } })
303
- .paths()
304
- .find(p =>
305
- // A type-only declaration cannot take a value specifier: merging a
306
- // component into `import type { … }` erases it at runtime.
307
- p.node.importKind !== 'type' &&
308
- (p.node.specifiers ?? []).every((spec) => spec.type === 'ImportSpecifier'));
309
- const preExistingImports = new Set();
310
- if (existingBestax) {
311
- for (const spec of existingBestax.node.specifiers ?? []) {
312
- if (spec.type === 'ImportSpecifier' && spec.local) {
313
- // The local name is reused either way, so the JSX never needs an
314
- // alias. But an inline `type` specifier (`import { type Box }`) is
315
- // not a value binding: it is not counted as already imported, so the
316
- // component is written as a value below — onto this specifier, which
317
- // keeps its name, rather than as a duplicate.
318
- ctx.needed.set(nameOf(spec.imported), nameOf(spec.local));
319
- if (spec.importKind !== 'type') {
320
- preExistingImports.add(nameOf(spec.imported));
321
- }
322
- }
323
- }
324
- }
218
+ const bestaxImportState = seedBestaxImport(ctx, root);
325
219
  // ---- 2. Transform JSX elements ----------------------------------------
326
220
  root.find(j.JSXElement).forEach(path => {
327
221
  const element = path.node;
@@ -693,62 +587,13 @@ export default function transform(fileInfo, api, options = {}) {
693
587
  // ---- 3. Rewrite imports -----------------------------------------------
694
588
  if (imports.size > 0) {
695
589
  const retainedNames = [...ctx.retained].sort((a, b) => a.localeCompare(b));
696
- const freshNames = [...ctx.needed.entries()]
697
- .filter(([imported]) => requested.has(imported) && !preExistingImports.has(imported))
698
- .sort((a, b) => a[0].localeCompare(b[0]));
699
- const bestaxImport = freshNames.length > 0
700
- ? j.importDeclaration(freshNames.map(([imported, local]) => j.importSpecifier(j.identifier(imported), j.identifier(local))), j.stringLiteral(BESTAX))
701
- : null;
702
- /**
703
-
704
- * A pruned declaration takes its comments with it — a licence header, an
705
-
706
- * eslint directive. Hand them to what replaces it, or to the next statement.
707
-
708
- */
709
- const carryComments = (node, importPath) => {
710
- const comments = node.comments ?? [];
711
- if (comments.length === 0)
712
- return;
713
- const body = importPath.parent?.node?.body ?? [];
714
- const index = body.indexOf(node);
715
- // The fresh specifiers are merged INTO an existing bestax import when there
716
- // is one, and the `bestaxImport` node is then discarded — so the comments
717
- // have to follow the declaration that survives, not the one that does not.
718
- const carrier = (existingBestax ? existingBestax.node : bestaxImport) ??
719
- (index >= 0 ? body[index + 1] : undefined);
720
- if (carrier) {
721
- carrier.comments = [...comments, ...(carrier.comments ?? [])];
722
- }
723
- else if (index > 0) {
724
- // The import was the last statement: the comments stay where they
725
- // were, after what precedes it.
726
- const previous = body[index - 1];
727
- previous.comments = [
728
- ...(previous.comments ?? []),
729
- ...comments.map((c) => ({
730
- ...c,
731
- leading: false,
732
- trailing: true,
733
- })),
734
- ];
735
- }
736
- else {
737
- // The import was the only statement: the comments become the file's.
738
- const program = importPath.parent?.node;
739
- if (program)
740
- program.comments = [...comments, ...(program.comments ?? [])];
741
- }
742
- node.comments = [];
743
- };
590
+ const bestaxImport = buildBestaxImport(ctx, bestaxImportState);
744
591
  let inserted = false;
745
592
  // A retained bloomer specifier must never collide with a bestax import local
746
593
  // (possible when one component is both JSX-migrated and value-retained).
747
594
  // Only a VALUE local can collide at runtime: a type-only specifier the
748
595
  // seeding above recorded, and nothing promoted, binds no value.
749
- const bestaxLocals = new Set([...ctx.needed.entries()]
750
- .filter(([imported]) => requested.has(imported) || preExistingImports.has(imported))
751
- .map(([, local]) => local));
596
+ const bestaxLocals = bestaxValueLocals(ctx, bestaxImportState);
752
597
  for (const path of sourceImportPaths) {
753
598
  const node = path.node;
754
599
  const keepSpecifiers = (node.specifiers ?? []).filter((spec) => {
@@ -766,28 +611,7 @@ export default function transform(fileInfo, api, options = {}) {
766
611
  !bestaxLocals.has(nameOf(spec.local)));
767
612
  });
768
613
  if (!inserted) {
769
- if (existingBestax && bestaxImport) {
770
- const current = existingBestax.node.specifiers ?? [];
771
- const appended = [];
772
- for (const fresh of bestaxImport.specifiers) {
773
- // A type-only specifier for the same name becomes the value
774
- // import (a value import carries the type too); appending a
775
- // second `Box` beside `type Box` would be a duplicate identifier.
776
- const typeOnly = current.find((spec) => spec.type === 'ImportSpecifier' &&
777
- spec.importKind === 'type' &&
778
- nameOf(spec.imported) === nameOf(fresh.imported));
779
- if (typeOnly) {
780
- typeOnly.importKind = null;
781
- }
782
- else {
783
- appended.push(fresh);
784
- }
785
- }
786
- existingBestax.node.specifiers = [...current, ...appended];
787
- }
788
- else if (bestaxImport) {
789
- path.insertBefore(bestaxImport);
790
- }
614
+ placeBestaxImport(bestaxImportState, bestaxImport, path);
791
615
  inserted = true;
792
616
  }
793
617
  const droppedOnCollision = (node.specifiers ?? []).filter((spec) => spec.type === 'ImportSpecifier' &&
@@ -810,7 +634,7 @@ export default function transform(fileInfo, api, options = {}) {
810
634
  }
811
635
  }
812
636
  else {
813
- carryComments(node, path);
637
+ carryPrunedComments(node, path, bestaxImportState.existing?.node ?? bestaxImport);
814
638
  path.prune();
815
639
  }
816
640
  ctx.dirty = true;
@@ -1 +1 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAsBzD,eAAO,MAAM,kBAAkB,EAAE,kBAqLhC,CAAC"}
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAwBzD,eAAO,MAAM,kBAAkB,EAAE,kBAgGhC,CAAC"}
@@ -13,11 +13,8 @@
13
13
  * see the note on that below.
14
14
  * says so by name.
15
15
  */
16
- import { isPreV1, isRecognisedRange } from '../_shared/semver-range.js';
17
- const BESTAX_RANGE = '^5';
18
- const BULMA_RANGE = '^1.0.4';
19
- // Bulma v1's sass tree uses `color.channel(…)` — needs dart-sass ≥ 1.79.
20
- const SASS_RANGE = '^1.79.0';
16
+ import { BULMA_RANGE, DEP_SECTIONS, addBestax, moveBulmaToV1, openManifest, replaceNodeSass, reportPeerRanges, } from '../_shared/deps-common.js';
17
+ import { isRecognisedRange } from '../_shared/semver-range.js';
21
18
  /**
22
19
  * The Bulma extensions rbx depends on directly. Bulma v1 and bestax cover all
23
20
  * four: badge and tooltip became bestax components, the page loader became
@@ -29,23 +26,16 @@ const RBX_STYLE_DEPS = [
29
26
  'bulma-pageloader',
30
27
  'bulma-tooltip',
31
28
  ];
32
- const DEP_SECTIONS = ['dependencies', 'devDependencies'];
33
29
  export const updateDependencies = (filePath, pkg, collector, options) => {
34
- const changes = [];
35
- const next = pkg;
36
- const section = (name) => (next[name] ?? undefined);
37
- const note = (message) => {
38
- changes.push(message);
39
- collector?.add({ file: filePath, line: null, rule: 'deps', message });
40
- };
30
+ const manifest = openManifest(filePath, pkg, collector);
41
31
  // rbx goes away entirely.
42
32
  const removed = [];
43
33
  for (const name of DEP_SECTIONS) {
44
- const deps = section(name);
34
+ const deps = manifest.section(name);
45
35
  if (deps && 'rbx' in deps) {
46
36
  delete deps.rbx;
47
37
  removed.push('rbx');
48
- note(`removed rbx from ${name}`);
38
+ manifest.note(`removed rbx from ${name}`);
49
39
  }
50
40
  }
51
41
  // The four Bulma extensions are REPORTED, not removed.
@@ -60,7 +50,7 @@ export const updateDependencies = (filePath, pkg, collector, options) => {
60
50
  const extensions = [];
61
51
  if (removed.includes('rbx')) {
62
52
  for (const name of DEP_SECTIONS) {
63
- const deps = section(name);
53
+ const deps = manifest.section(name);
64
54
  if (!deps)
65
55
  continue;
66
56
  for (const extension of RBX_STYLE_DEPS) {
@@ -70,56 +60,19 @@ export const updateDependencies = (filePath, pkg, collector, options) => {
70
60
  }
71
61
  }
72
62
  if (extensions.length > 0) {
73
- collector?.add({
74
- file: filePath,
75
- line: null,
76
- rule: 'deps',
77
- message: `${extensions.join(', ')} ${extensions.length === 1 ? 'is a Bulma extension' : 'are Bulma extensions'} rbx depended on, and bestax ships ${extensions.length === 1 ? 'its' : 'their'} equivalent${extensions.length === 1 ? '' : 's'} (Badge, Divider, Loading, Tooltip). Declared in this manifest, so removing ${extensions.length === 1 ? 'it' : 'them'} is your call — drop ${extensions.length === 1 ? 'it' : 'them'} unless your own Sass imports ${extensions.length === 1 ? 'it' : 'them'} directly`,
78
- });
79
- }
80
- // @allxsmith/bestax-bulma comes in (runtime dependency).
81
- const dependencies = (next.dependencies ??= {});
82
- if (!dependencies['@allxsmith/bestax-bulma'] &&
83
- !section('devDependencies')?.['@allxsmith/bestax-bulma']) {
84
- dependencies['@allxsmith/bestax-bulma'] = BESTAX_RANGE;
85
- note(`added @allxsmith/bestax-bulma ${BESTAX_RANGE} to dependencies`);
86
- }
87
- // Bulma: rbx pinned 0.7.5 as a direct dependency, so this almost always
88
- // fires. Add it back only when sources still reference bulma/… directly —
89
- // otherwise it arrives transitively via bestax-bulma.
90
- let bulmaDeclared = false;
91
- let declaredBulma = '';
92
- let bulmaBumped = false;
93
- let bulmaAdded = false;
94
- for (const name of DEP_SECTIONS) {
95
- const deps = section(name);
96
- if (deps?.bulma) {
97
- bulmaDeclared = true;
98
- declaredBulma = deps.bulma;
99
- if (isPreV1(deps.bulma)) {
100
- deps.bulma = BULMA_RANGE;
101
- bulmaBumped = true;
102
- note(`bumped bulma to ${BULMA_RANGE} in ${name} (was pre-1.0)`);
103
- }
104
- }
105
- }
106
- if (!bulmaDeclared && options.bulmaReferenced) {
107
- dependencies.bulma = BULMA_RANGE;
108
- bulmaAdded = true;
109
- note(`added bulma ${BULMA_RANGE} to dependencies (sources import bulma/… directly)`);
63
+ manifest.report('deps', `${extensions.join(', ')} ${extensions.length === 1 ? 'is a Bulma extension' : 'are Bulma extensions'} rbx depended on, and bestax ships ${extensions.length === 1 ? 'its' : 'their'} equivalent${extensions.length === 1 ? '' : 's'} (Badge, Divider, Loading, Tooltip). Declared in this manifest, so removing ${extensions.length === 1 ? 'it' : 'them'} is your call — drop ${extensions.length === 1 ? 'it' : 'them'} unless your own Sass imports ${extensions.length === 1 ? 'it' : 'them'} directly`);
110
64
  }
65
+ addBestax(manifest);
66
+ // rbx pinned Bulma 0.7.5 as a direct dependency, so the bump almost always
67
+ // fires.
68
+ const bulma = moveBulmaToV1(manifest, options.bulmaReferenced);
111
69
  // The transform deliberately keeps a trimmed rbx import for components
112
70
  // with no bestax equivalent (Tile, Generic, List, …) so a partially
113
71
  // migrated app still runs. Removing the package from the manifest strands
114
72
  // exactly those imports once the user runs the install the report asks for,
115
73
  // so say so rather than letting them find out at build time.
116
74
  if (removed.includes('rbx') && options.sourceStillImported) {
117
- collector?.add({
118
- file: filePath,
119
- line: null,
120
- rule: 'deps',
121
- message: 'rbx 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 rbx until you have',
122
- });
75
+ manifest.report('deps', 'rbx 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 rbx until you have');
123
76
  }
124
77
  // The headline result: rbx pinned Bulma 0.7.5 as a DIRECT dependency, so
125
78
  // removing rbx is what frees the app to choose its own Bulma version.
@@ -130,63 +83,22 @@ export const updateDependencies = (filePath, pkg, collector, options) => {
130
83
  // arrives transitively via bestax-bulma. Saying "bumped bulma" there
131
84
  // described a pin the user would not find in their manifest.
132
85
  if (removed.includes('rbx')) {
133
- collector?.add({
134
- file: filePath,
135
- line: null,
136
- rule: 'deps',
137
- message: `removed rbx ${bulmaBumped
138
- ? `and bumped bulma to ${BULMA_RANGE}`
139
- : bulmaAdded
140
- ? `and added bulma ${BULMA_RANGE}`
141
- : bulmaDeclared
142
- ? isRecognisedRange(declaredBulma)
143
- ? 'and left your declared bulma range alone (already v1)'
144
- : `and left your declared bulma specifier alone (${JSON.stringify(declaredBulma)} is not a version range this tool can read; make sure it resolves to Bulma 1.x)`
145
- : '— bulma now arrives transitively via @allxsmith/bestax-bulma'} — rbx pinned Bulma 0.7.5 as a direct dependency, so the app can now choose its own Bulma version${extensions.length > 0 ? `; ${extensions.length} Bulma extension(s) are reported above for you to remove` : ''}`,
146
- });
147
- }
148
- // bestax-bulma requires React 18/19; rbx peer-depends on ^16.8.6, and React
149
- // 19 removed the `defaultProps` its forwardRefAs base is built on — so this
150
- // is the other half of why an rbx app is stuck. Report only: a React major
151
- // upgrade is the app's own migration step.
152
- for (const name of DEP_SECTIONS) {
153
- const range = section(name)?.react;
154
- if (range && /^[~^]?(?:[0-9]|1[0-7])(?:[.x]|$)/.test(range.trim())) {
155
- collector?.add({
156
- file: filePath,
157
- line: null,
158
- rule: 'peer-deps',
159
- message: `react ${range} predates bestax-bulma's peer range (^18 || ^19) — upgrade react and react-dom to 18 or 19 before installing`,
160
- });
161
- }
162
- }
163
- // Font Awesome older than 6 conflicts with bestax-bulma's optional peer
164
- // range and makes `npm install` fail with ERESOLVE. Report only — icon
165
- // names change across FA majors, so upgrading is the app's decision.
166
- for (const name of DEP_SECTIONS) {
167
- const range = section(name)?.['@fortawesome/fontawesome-free'];
168
- if (range && /^[~^]?[0-5](?:[.x]|$)/.test(range.trim())) {
169
- collector?.add({
170
- file: filePath,
171
- line: null,
172
- rule: 'peer-deps',
173
- 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\``,
174
- });
175
- }
176
- }
177
- // node-sass is dead; dart-sass replaces it in the same section. rbx's own
178
- // customisation guide told people to install node-sass, so this is common.
179
- for (const name of DEP_SECTIONS) {
180
- const deps = section(name);
181
- if (deps && 'node-sass' in deps) {
182
- delete deps['node-sass'];
183
- note(`removed node-sass from ${name}`);
184
- const sassDeclared = DEP_SECTIONS.some(s => section(s)?.sass);
185
- if (!sassDeclared) {
186
- deps.sass = SASS_RANGE;
187
- note(`added sass ${SASS_RANGE} to ${name} (replaces node-sass)`);
188
- }
189
- }
86
+ manifest.report('deps', `removed rbx ${bulma.bumped
87
+ ? `and bumped bulma to ${BULMA_RANGE}`
88
+ : bulma.added
89
+ ? `and added bulma ${BULMA_RANGE}`
90
+ : bulma.declared !== null
91
+ ? isRecognisedRange(bulma.declared)
92
+ ? 'and left your declared bulma range alone (already v1)'
93
+ : `and left your declared bulma specifier alone (${JSON.stringify(bulma.declared)} is not a version range this tool can read; make sure it resolves to Bulma 1.x)`
94
+ : '— bulma now arrives transitively via @allxsmith/bestax-bulma'} — rbx pinned Bulma 0.7.5 as a direct dependency, so the app can now choose its own Bulma version${extensions.length > 0 ? `; ${extensions.length} Bulma extension(s) are reported above for you to remove` : ''}`);
190
95
  }
191
- return changes.length > 0 ? next : null;
96
+ // rbx peer-depends on React ^16.8.6, and React 19 removed the
97
+ // `defaultProps` its forwardRefAs base is built on — so an old React is the
98
+ // other half of why an rbx app is stuck.
99
+ reportPeerRanges(manifest);
100
+ // rbx's own customisation guide told people to install node-sass, so this
101
+ // is common.
102
+ replaceNodeSass(manifest);
103
+ return manifest.result();
192
104
  };
@@ -1 +1 @@
1
- {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA8BnE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAoCtD,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOrD,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAQvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAShE,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAktBpD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA2FhD,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAM3E"}
1
+ {"version":3,"file":"mapping.d.ts","sourceRoot":"","sources":["../../../src/sources/rbx/mapping.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AA8BnE;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CA6CtD,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAOrD,CAAC;AAEF,2DAA2D;AAC3D,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAQvD,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAShE,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAktBpD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CA2FhD,CAAC;AAEF,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,gBAAgB,GAAG,SAAS,CAM3E"}