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
package/README.md
CHANGED
|
@@ -11,15 +11,16 @@
|
|
|
11
11
|
|
|
12
12
|
Codemods 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**.
|
|
13
13
|
|
|
14
|
-
Currently supported
|
|
14
|
+
Currently supported sources:
|
|
15
15
|
|
|
16
|
-
| Source | Status
|
|
17
|
-
| -------------------------------------------------------------------------------- |
|
|
18
|
-
| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs)
|
|
19
|
-
| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs)
|
|
20
|
-
| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged)
|
|
16
|
+
| Source | Status |
|
|
17
|
+
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |
|
|
18
|
+
| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs) |
|
|
19
|
+
| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs) |
|
|
20
|
+
| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged) |
|
|
21
|
+
| `bulma-classes`: Bulma's classes on plain JSX, no library | ✅ Converts an element only when bestax renders the same markup; the rest is flagged |
|
|
21
22
|
|
|
22
|
-
Pass the source
|
|
23
|
+
Pass the source as the first argument: `bestax-migrate <source> <paths…>`.
|
|
23
24
|
|
|
24
25
|
## Requirements
|
|
25
26
|
|
|
@@ -37,6 +38,8 @@ pnpm dlx bestax-migrate react-bulma-components src/ --dry
|
|
|
37
38
|
# …or, for an rbx or bloomer app
|
|
38
39
|
pnpm dlx bestax-migrate rbx src/ --dry
|
|
39
40
|
pnpm dlx bestax-migrate bloomer src/ --dry
|
|
41
|
+
# …or, for an app that writes Bulma's classes on plain JSX
|
|
42
|
+
pnpm dlx bestax-migrate bulma-classes src/ --dry
|
|
40
43
|
|
|
41
44
|
# Apply the migration
|
|
42
45
|
pnpm dlx bestax-migrate react-bulma-components src/
|
|
@@ -50,11 +53,12 @@ The codemod uses [jscodeshift](https://github.com/facebook/jscodeshift) to:
|
|
|
50
53
|
- 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`)
|
|
51
54
|
- convert props (`renderAs` → `as`, `loading` → `isLoading`, numeric spacing/text sizes → string unions, `textAlign="center"` → `textAlign="centered"`, …)
|
|
52
55
|
- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`) and bloomer's `isDisplay`/`isHidden` strings, arrays and objects (`isHidden="touch"` → `visibilityTouch="hidden"`)
|
|
56
|
+
- 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
|
|
53
57
|
- restructure patterns bestax models differently (`Table.Container`, Navbar dropdowns, `Form.Help`, icon-font children → `<Icon name=…>`)
|
|
54
58
|
- 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'`
|
|
55
|
-
- update `package.json`: remove the source library, add `@allxsmith/bestax-bulma`, raise a declared pre-1.0 `bulma` to `^1` (adding it only when your sources import `bulma/…` directly — otherwise it arrives transitively), and swap the dead `node-sass` for dart `sass` (no install is ever run). Migrating **rbx** is what frees an app from Bulma 0.7.5: rbx pinned it as a _direct_ dependency, so the app could not choose its own Bulma version at all. The four Bulma extensions rbx also pulled in (`bulma-badge`, `bulma-divider`, `bulma-pageloader`, `bulma-tooltip`) are **reported rather than removed** — bestax replaces all four, but a manifest entry is a deliberate declaration and your own Sass may import them. A **bloomer** app declared its own Bulma 0.6, which is what gets bumped
|
|
59
|
+
- 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
|
|
56
60
|
|
|
57
|
-
Anything without a safe automatic conversion is left in place with a `// TODO(bestax-migrate): …` comment, and the run ends with a report of every TODO by file and line. TODOs are expected output, not errors — resolve them with the migration guide ([react-bulma-components](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components), [rbx](https://bestax.io/docs/guides/getting-started/migration/rbx), [bloomer](https://bestax.io/docs/guides/getting-started/migration/bloomer)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:
|
|
61
|
+
Anything without a safe automatic conversion is left in place with a `// TODO(bestax-migrate): …` comment, and the run ends with a report of every TODO by file and line. TODOs are expected output, not errors — resolve them with the migration guide ([react-bulma-components](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components), [rbx](https://bestax.io/docs/guides/getting-started/migration/rbx), [bloomer](https://bestax.io/docs/guides/getting-started/migration/bloomer), [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:
|
|
58
62
|
|
|
59
63
|
```bash
|
|
60
64
|
npx skills add https://github.com/allxsmith/bestax --skill bestax-migrate
|
|
@@ -62,13 +66,13 @@ npx skills add https://github.com/allxsmith/bestax --skill bestax-migrate
|
|
|
62
66
|
|
|
63
67
|
## Options
|
|
64
68
|
|
|
65
|
-
| Flag | Description
|
|
66
|
-
| -------------------- |
|
|
67
|
-
| `--dry`, `-d` | Report what would change without writing files
|
|
68
|
-
| `--print`, `-p` | Print transformed sources to stdout
|
|
69
|
-
| `--extensions`, `-e` | File extensions to include (default `js,jsx,ts,tsx,scss,sass`)
|
|
70
|
-
| `--css <mode>` | Stylesheet target: `bestax
|
|
71
|
-
| `--no-deps` | Skip updating package.json dependencies
|
|
69
|
+
| Flag | Description |
|
|
70
|
+
| -------------------- | ---------------------------------------------------------------------------------------------- |
|
|
71
|
+
| `--dry`, `-d` | Report what would change without writing files |
|
|
72
|
+
| `--print`, `-p` | Print transformed sources to stdout |
|
|
73
|
+
| `--extensions`, `-e` | File extensions to include (default `js,jsx,ts,tsx,scss,sass`) |
|
|
74
|
+
| `--css <mode>` | Stylesheet target: `bestax`, `bulma`, or `keep` (default `bestax`; `keep` for `bulma-classes`) |
|
|
75
|
+
| `--no-deps` | Skip updating package.json dependencies |
|
|
72
76
|
|
|
73
77
|
## After the codemod
|
|
74
78
|
|
|
@@ -76,7 +80,7 @@ npx skills add https://github.com/allxsmith/bestax --skill bestax-migrate
|
|
|
76
80
|
2. Search for `TODO(bestax-migrate)` and resolve each comment
|
|
77
81
|
3. Typecheck/build and review the rendered app
|
|
78
82
|
|
|
79
|
-
Full walkthrough: [react-bulma-components migration guide](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components) · [rbx migration guide](https://bestax.io/docs/guides/getting-started/migration/rbx) · [bloomer migration guide](https://bestax.io/docs/guides/getting-started/migration/bloomer).
|
|
83
|
+
Full walkthrough: [react-bulma-components migration guide](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components) · [rbx migration guide](https://bestax.io/docs/guides/getting-started/migration/rbx) · [bloomer migration guide](https://bestax.io/docs/guides/getting-started/migration/bloomer) · [Bulma classes migration guide](https://bestax.io/docs/guides/getting-started/migration/bulma-classes).
|
|
80
84
|
|
|
81
85
|
## Hardened by default
|
|
82
86
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { createInterface } from 'node:readline/promises';
|
|
|
15
15
|
import type { Readable, Writable } from 'node:stream';
|
|
16
16
|
import { Command } from 'commander';
|
|
17
17
|
import { type MigrateRunStats } from './telemetry.js';
|
|
18
|
+
import type { MigrationSource } from './types.js';
|
|
18
19
|
export declare function collectFiles(targets: string[], extensions: string[]): string[];
|
|
19
20
|
/** Nearest package.json for each target, walking up to the filesystem root. */
|
|
20
21
|
export declare function findPackageJsons(targets: string[]): string[];
|
|
@@ -75,6 +76,8 @@ export declare function blankComments(text: string): string;
|
|
|
75
76
|
* short as `rbx`: prose and a sibling package like `rbx-utils` both counted.
|
|
76
77
|
*/
|
|
77
78
|
export declare function makeSourceImportRe(name: string): RegExp;
|
|
79
|
+
/** The package a source migrates away from, or null when it has none. */
|
|
80
|
+
export declare function sourcePackage(source: MigrationSource): string | null;
|
|
78
81
|
/**
|
|
79
82
|
* One-question consent prompt (readline — this package carries no interactive
|
|
80
83
|
* prompt dependency). Returns null when the question is cancelled (Ctrl-C /
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,KAAK,EAAW,eAAe,EAAE,MAAM,YAAY,CAAC;AAoB3D,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,GACnB,MAAM,EAAE,CAkBV;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAkB5D;AAED,MAAM,WAAW,KAAK;IACpB,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AASD;;;;;;;;;;;;;;;;;;;GAmBG;AACH;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAgDlD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAsBvD;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAEpE;AA4LD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,KAAK,EACT,KAAK,GAAE,QAAwB,EAC/B,MAAM,GAAE,QAAyB,EAGjC,aAAa,GAAE,OAAO,eAAiC,GACtD,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAyBzB;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,eAAe,EACtB,IAAI,EAAE,OAAO,GAAG,SAAS,EACzB,EAAE,EAAE,KAAK,EACT,aAAa,GAAE,CAAC,EAAE,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAA0B,GAC7E,OAAO,CAAC,IAAI,CAAC,CAqBf;AAYD,wBAAgB,SAAS,CACvB,EAAE,GAAE,KAAkD,GACrD,OAAO,CA0HT"}
|
package/dist/cli.js
CHANGED
|
@@ -201,10 +201,19 @@ export function makeSourceImportRe(name) {
|
|
|
201
201
|
`${lead}(?:import|require(?:\\.resolve)?)\\s*\\(\\s*${spec}`,
|
|
202
202
|
].join('|'));
|
|
203
203
|
}
|
|
204
|
-
|
|
204
|
+
/** The package a source migrates away from, or null when it has none. */
|
|
205
|
+
export function sourcePackage(source) {
|
|
206
|
+
return source.packageName === undefined ? source.name : source.packageName;
|
|
207
|
+
}
|
|
208
|
+
/** Whether `text` still imports the source's package (never, without one). */
|
|
209
|
+
function importsSource(importRe, text) {
|
|
210
|
+
return importRe !== null && importRe.test(blankComments(text));
|
|
211
|
+
}
|
|
212
|
+
function migrateFiles(source, files, reporter, io, options, project) {
|
|
205
213
|
let bulmaReferenced = false;
|
|
206
214
|
let sourceStillImported = false;
|
|
207
|
-
const
|
|
215
|
+
const pkg = sourcePackage(source);
|
|
216
|
+
const sourceImportRe = pkg === null ? null : makeSourceImportRe(pkg);
|
|
208
217
|
for (const file of files) {
|
|
209
218
|
const sourceText = fs.readFileSync(file, 'utf8');
|
|
210
219
|
const collector = reporter.startFile();
|
|
@@ -221,6 +230,7 @@ function migrateFiles(source, files, reporter, io, options) {
|
|
|
221
230
|
}
|
|
222
231
|
else {
|
|
223
232
|
output = runTransform(source.transform, file, sourceText, collector, {
|
|
233
|
+
...project,
|
|
224
234
|
cssMode: options.cssMode,
|
|
225
235
|
}).output;
|
|
226
236
|
}
|
|
@@ -233,7 +243,7 @@ function migrateFiles(source, files, reporter, io, options) {
|
|
|
233
243
|
// the file still imports it, we just couldn't rewrite it.
|
|
234
244
|
if (/['"](?:~?bulma\/)/.test(sourceText))
|
|
235
245
|
bulmaReferenced = true;
|
|
236
|
-
if (sourceImportRe
|
|
246
|
+
if (importsSource(sourceImportRe, sourceText))
|
|
237
247
|
sourceStillImported = true;
|
|
238
248
|
reporter.finishFile(file, false, collector.entries);
|
|
239
249
|
continue;
|
|
@@ -241,7 +251,7 @@ function migrateFiles(source, files, reporter, io, options) {
|
|
|
241
251
|
if (/['"](?:~?bulma\/)/.test(output ?? sourceText)) {
|
|
242
252
|
bulmaReferenced = true;
|
|
243
253
|
}
|
|
244
|
-
if (sourceImportRe
|
|
254
|
+
if (importsSource(sourceImportRe, output ?? sourceText)) {
|
|
245
255
|
sourceStillImported = true;
|
|
246
256
|
}
|
|
247
257
|
if (output !== null) {
|
|
@@ -259,14 +269,36 @@ function migrateFiles(source, files, reporter, io, options) {
|
|
|
259
269
|
* source library, so a migration never silently skips them.
|
|
260
270
|
*/
|
|
261
271
|
function reportUnsupportedFiles(source, targets, reporter, extensions) {
|
|
262
|
-
const unsupported = UNSUPPORTED_EXTENSIONS.filter(ext => !extensions.includes(ext)
|
|
272
|
+
const unsupported = UNSUPPORTED_EXTENSIONS.filter(ext => !extensions.includes(ext) &&
|
|
273
|
+
(source.unsupportedExtensions?.includes(ext) ?? true));
|
|
274
|
+
const pkg = sourcePackage(source);
|
|
263
275
|
if (unsupported.length === 0)
|
|
264
276
|
return false;
|
|
277
|
+
if (pkg === null) {
|
|
278
|
+
// No package to look for: the source says what it would have converted.
|
|
279
|
+
const find = source.findUnsupportedReference;
|
|
280
|
+
if (!find)
|
|
281
|
+
return false;
|
|
282
|
+
for (const file of collectFiles(targets, unsupported)) {
|
|
283
|
+
const line = find(fs.readFileSync(file, 'utf8'));
|
|
284
|
+
if (line === null)
|
|
285
|
+
continue;
|
|
286
|
+
const collector = reporter.startFile();
|
|
287
|
+
collector.add({
|
|
288
|
+
file,
|
|
289
|
+
line,
|
|
290
|
+
rule: 'unsupported-file',
|
|
291
|
+
message: `has markup the ${source.name} source would convert, but ${path.extname(file)} files cannot be parsed by the codemod — migrate this file by hand`,
|
|
292
|
+
});
|
|
293
|
+
reporter.finishFile(file, false, collector.entries);
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
265
297
|
// Whether any unsupported file still references the source package. These
|
|
266
298
|
// are reported but never rewritten, so the reference survives the run —
|
|
267
299
|
// and the manifest pass must not remove the package out from under it.
|
|
268
300
|
let stillImported = false;
|
|
269
|
-
const importRe = makeSourceImportRe(
|
|
301
|
+
const importRe = makeSourceImportRe(pkg);
|
|
270
302
|
for (const file of collectFiles(targets, unsupported)) {
|
|
271
303
|
const text = fs.readFileSync(file, 'utf8');
|
|
272
304
|
// A substring match is not evidence of an import. `rbx` is three
|
|
@@ -283,7 +315,7 @@ function reportUnsupportedFiles(source, targets, reporter, extensions) {
|
|
|
283
315
|
file,
|
|
284
316
|
line,
|
|
285
317
|
rule: 'unsupported-file',
|
|
286
|
-
message: `imports ${
|
|
318
|
+
message: `imports ${pkg}, but ${path.extname(file)} files cannot be parsed by the codemod — migrate this file by hand`,
|
|
287
319
|
});
|
|
288
320
|
reporter.finishFile(file, false, collector.entries);
|
|
289
321
|
}
|
|
@@ -419,7 +451,7 @@ export function createCLI(io = { log: console.log, error: console.error }) {
|
|
|
419
451
|
.option('-d, --dry', 'dry run — report what would change without writing', false)
|
|
420
452
|
.option('-p, --print', 'print transformed sources to stdout', false)
|
|
421
453
|
.option('-e, --extensions <list>', 'comma-separated file extensions to include', 'js,jsx,ts,tsx,scss,sass')
|
|
422
|
-
.option('--css <mode>', `stylesheet target: ${CSS_MODES.join(', ')}
|
|
454
|
+
.option('--css <mode>', `stylesheet target: ${CSS_MODES.join(', ')} (default bestax; keep for bulma-classes)`)
|
|
423
455
|
.option('--no-deps', 'skip updating package.json dependencies')
|
|
424
456
|
.option('--telemetry', 'enable anonymous usage telemetry (https://bestax.io/docs/guides/telemetry)')
|
|
425
457
|
.option('--no-telemetry', 'disable anonymous usage telemetry')
|
|
@@ -430,7 +462,8 @@ export function createCLI(io = { log: console.log, error: console.error }) {
|
|
|
430
462
|
program.error('', { exitCode: 1 });
|
|
431
463
|
return;
|
|
432
464
|
}
|
|
433
|
-
|
|
465
|
+
const cssMode = options.css ?? source.defaultCssMode ?? 'bestax';
|
|
466
|
+
if (!CSS_MODES.includes(cssMode)) {
|
|
434
467
|
io.error(`${chalk.red('Unknown --css mode')} "${options.css}". Valid modes: ${CSS_MODES.join(', ')}`);
|
|
435
468
|
program.error('', { exitCode: 1 });
|
|
436
469
|
return;
|
|
@@ -452,10 +485,11 @@ export function createCLI(io = { log: console.log, error: console.error }) {
|
|
|
452
485
|
dry: Boolean(options.dry),
|
|
453
486
|
print: Boolean(options.print),
|
|
454
487
|
deps: options.deps !== false,
|
|
455
|
-
cssMode
|
|
488
|
+
cssMode,
|
|
456
489
|
};
|
|
457
490
|
const reporter = new Reporter();
|
|
458
|
-
const
|
|
491
|
+
const project = source.analyzeProject?.(targets) ?? {};
|
|
492
|
+
const depSignals = migrateFiles(source, files, reporter, io, runOptions, project);
|
|
459
493
|
const unsupportedImports = reportUnsupportedFiles(source, targets, reporter, extensions);
|
|
460
494
|
if (unsupportedImports)
|
|
461
495
|
depSignals.sourceStillImported = true;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `@allxsmith/bestax-bulma` import a migrated file ends up with.
|
|
3
|
+
*
|
|
4
|
+
* Every source does the same three things: seed the components an existing
|
|
5
|
+
* bestax import already binds (so the JSX reuses their locals), record which
|
|
6
|
+
* components the passes actually ask for, and then either merge the new ones
|
|
7
|
+
* into that existing import or write a fresh declaration. Where the fresh
|
|
8
|
+
* declaration goes is the caller's call; a library source puts it where the
|
|
9
|
+
* library's own import was.
|
|
10
|
+
*/
|
|
11
|
+
import type { TransformContext } from './jsx-utils.js';
|
|
12
|
+
export declare const BESTAX = "@allxsmith/bestax-bulma";
|
|
13
|
+
export interface BestaxImportState {
|
|
14
|
+
/** The existing declaration new specifiers merge into, if any. */
|
|
15
|
+
existing: any | undefined;
|
|
16
|
+
/** Components the existing declaration already binds as values. */
|
|
17
|
+
preExisting: Set<string>;
|
|
18
|
+
/** Components the passes asked for through `ctx.reserve`. */
|
|
19
|
+
requested: Set<string>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Call once `ctx.reserve` is final and before any pass reserves a name: it
|
|
23
|
+
* wraps `reserve` to record requests and seeds `ctx.needed` from an existing
|
|
24
|
+
* bestax import.
|
|
25
|
+
*/
|
|
26
|
+
export declare function seedBestaxImport(ctx: TransformContext, root: any): BestaxImportState;
|
|
27
|
+
/** The fresh declaration for components not already imported, or null. */
|
|
28
|
+
export declare function buildBestaxImport(ctx: TransformContext, state: BestaxImportState): any | null;
|
|
29
|
+
/**
|
|
30
|
+
* Locals that bind a bestax VALUE once the import is written. A type-only
|
|
31
|
+
* specifier the seeding recorded, and nothing promoted, binds no value.
|
|
32
|
+
*/
|
|
33
|
+
export declare function bestaxValueLocals(ctx: TransformContext, state: BestaxImportState): Set<string>;
|
|
34
|
+
/**
|
|
35
|
+
* Merge `fresh` into the existing bestax import, or insert it through
|
|
36
|
+
* `anchor` when there is none. An AST path is an anchor: the fresh import
|
|
37
|
+
* goes before it.
|
|
38
|
+
*/
|
|
39
|
+
export declare function placeBestaxImport(state: BestaxImportState, fresh: any | null, anchor: {
|
|
40
|
+
insertBefore(node: any): unknown;
|
|
41
|
+
}): void;
|
|
42
|
+
/**
|
|
43
|
+
* A pruned declaration takes its comments with it — a licence header, an
|
|
44
|
+
* eslint directive. Hand them to `carrier` (the bestax import that survives),
|
|
45
|
+
* or to the next statement, or keep them where they were.
|
|
46
|
+
*/
|
|
47
|
+
export declare function carryPrunedComments(node: any, importPath: any, carrier: any | null): void;
|
|
48
|
+
//# sourceMappingURL=bestax-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bestax-import.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/bestax-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAIvD,eAAO,MAAM,MAAM,4BAA4B,CAAC;AAEhD,MAAM,WAAW,iBAAiB;IAChC,kEAAkE;IAClE,QAAQ,EAAE,GAAG,GAAG,SAAS,CAAC;IAC1B,mEAAmE;IACnE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,6DAA6D;IAC7D,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,GAAG,GACR,iBAAiB,CA+CnB;AAED,0EAA0E;AAC1E,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,iBAAiB,GACvB,GAAG,GAAG,IAAI,CAgBZ;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,iBAAiB,GACvB,GAAG,CAAC,MAAM,CAAC,CASb;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,iBAAiB,EACxB,KAAK,EAAE,GAAG,GAAG,IAAI,EACjB,MAAM,EAAE;IAAE,YAAY,CAAC,IAAI,EAAE,GAAG,GAAG,OAAO,CAAA;CAAE,GAC3C,IAAI,CAyBN;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,GAAG,EACT,UAAU,EAAE,GAAG,EACf,OAAO,EAAE,GAAG,GAAG,IAAI,GAClB,IAAI,CAsBN"}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `@allxsmith/bestax-bulma` import a migrated file ends up with.
|
|
3
|
+
*
|
|
4
|
+
* Every source does the same three things: seed the components an existing
|
|
5
|
+
* bestax import already binds (so the JSX reuses their locals), record which
|
|
6
|
+
* components the passes actually ask for, and then either merge the new ones
|
|
7
|
+
* into that existing import or write a fresh declaration. Where the fresh
|
|
8
|
+
* declaration goes is the caller's call; a library source puts it where the
|
|
9
|
+
* library's own import was.
|
|
10
|
+
*/
|
|
11
|
+
import { nameOf } from './imports.js';
|
|
12
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
13
|
+
export const BESTAX = '@allxsmith/bestax-bulma';
|
|
14
|
+
/**
|
|
15
|
+
* Call once `ctx.reserve` is final and before any pass reserves a name: it
|
|
16
|
+
* wraps `reserve` to record requests and seeds `ctx.needed` from an existing
|
|
17
|
+
* bestax import.
|
|
18
|
+
*/
|
|
19
|
+
export function seedBestaxImport(ctx, root) {
|
|
20
|
+
const { j } = ctx;
|
|
21
|
+
// Names the passes actually asked for. `ctx.needed` is also seeded from an
|
|
22
|
+
// existing bestax import's specifiers below (so JSX reuses their locals),
|
|
23
|
+
// and that seeding alone must not turn a type-only specifier into a value
|
|
24
|
+
// import nobody needed.
|
|
25
|
+
const requested = new Set();
|
|
26
|
+
const baseReserve = ctx.reserve;
|
|
27
|
+
ctx.reserve = name => {
|
|
28
|
+
requested.add(name);
|
|
29
|
+
return baseReserve(name);
|
|
30
|
+
};
|
|
31
|
+
// Only a declaration made entirely of NAMED specifiers can be merged into.
|
|
32
|
+
// `import * as Bulma from '@allxsmith/bestax-bulma'` matches the source too,
|
|
33
|
+
// and appending named specifiers to it emitted
|
|
34
|
+
// `import * as Bulma, { Box } from …` — not valid JavaScript, so the whole
|
|
35
|
+
// file failed to parse after a migration that reported success.
|
|
36
|
+
const existing = root
|
|
37
|
+
.find(j.ImportDeclaration, { source: { value: BESTAX } })
|
|
38
|
+
.paths()
|
|
39
|
+
.find((path) =>
|
|
40
|
+
// A type-only declaration cannot take a value specifier: merging a
|
|
41
|
+
// component into `import type { … }` erases it at runtime.
|
|
42
|
+
path.node.importKind !== 'type' &&
|
|
43
|
+
(path.node.specifiers ?? []).every((spec) => spec.type === 'ImportSpecifier'));
|
|
44
|
+
const preExisting = new Set();
|
|
45
|
+
if (existing) {
|
|
46
|
+
for (const spec of existing.node.specifiers ?? []) {
|
|
47
|
+
if (spec.type === 'ImportSpecifier' && spec.local) {
|
|
48
|
+
// The local name is reused either way, so the JSX never needs an
|
|
49
|
+
// alias. But an inline `type` specifier (`import { type Box }`) is
|
|
50
|
+
// not a value binding: it is not counted as already imported, so the
|
|
51
|
+
// component is written as a value below — onto this specifier, which
|
|
52
|
+
// keeps its name, rather than as a duplicate.
|
|
53
|
+
ctx.needed.set(nameOf(spec.imported), nameOf(spec.local));
|
|
54
|
+
if (spec.importKind !== 'type') {
|
|
55
|
+
preExisting.add(nameOf(spec.imported));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return { existing, preExisting, requested };
|
|
61
|
+
}
|
|
62
|
+
/** The fresh declaration for components not already imported, or null. */
|
|
63
|
+
export function buildBestaxImport(ctx, state) {
|
|
64
|
+
const { j } = ctx;
|
|
65
|
+
const freshNames = [...ctx.needed.entries()]
|
|
66
|
+
.filter(([imported]) => state.requested.has(imported) && !state.preExisting.has(imported))
|
|
67
|
+
.sort((a, b) => a[0].localeCompare(b[0]));
|
|
68
|
+
return freshNames.length > 0
|
|
69
|
+
? j.importDeclaration(freshNames.map(([imported, local]) => j.importSpecifier(j.identifier(imported), j.identifier(local))), j.stringLiteral(BESTAX))
|
|
70
|
+
: null;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Locals that bind a bestax VALUE once the import is written. A type-only
|
|
74
|
+
* specifier the seeding recorded, and nothing promoted, binds no value.
|
|
75
|
+
*/
|
|
76
|
+
export function bestaxValueLocals(ctx, state) {
|
|
77
|
+
return new Set([...ctx.needed.entries()]
|
|
78
|
+
.filter(([imported]) => state.requested.has(imported) || state.preExisting.has(imported))
|
|
79
|
+
.map(([, local]) => local));
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Merge `fresh` into the existing bestax import, or insert it through
|
|
83
|
+
* `anchor` when there is none. An AST path is an anchor: the fresh import
|
|
84
|
+
* goes before it.
|
|
85
|
+
*/
|
|
86
|
+
export function placeBestaxImport(state, fresh, anchor) {
|
|
87
|
+
if (!fresh)
|
|
88
|
+
return;
|
|
89
|
+
if (!state.existing) {
|
|
90
|
+
anchor.insertBefore(fresh);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const current = state.existing.node.specifiers ?? [];
|
|
94
|
+
const appended = [];
|
|
95
|
+
for (const spec of fresh.specifiers) {
|
|
96
|
+
// A type-only specifier for the same name becomes the value
|
|
97
|
+
// import (a value import carries the type too); appending a
|
|
98
|
+
// second `Box` beside `type Box` would be a duplicate identifier.
|
|
99
|
+
const typeOnly = current.find((existingSpec) => existingSpec.type === 'ImportSpecifier' &&
|
|
100
|
+
existingSpec.importKind === 'type' &&
|
|
101
|
+
nameOf(existingSpec.imported) === nameOf(spec.imported));
|
|
102
|
+
if (typeOnly) {
|
|
103
|
+
typeOnly.importKind = null;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
appended.push(spec);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
state.existing.node.specifiers = [...current, ...appended];
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* A pruned declaration takes its comments with it — a licence header, an
|
|
113
|
+
* eslint directive. Hand them to `carrier` (the bestax import that survives),
|
|
114
|
+
* or to the next statement, or keep them where they were.
|
|
115
|
+
*/
|
|
116
|
+
export function carryPrunedComments(node, importPath, carrier) {
|
|
117
|
+
const comments = node.comments ?? [];
|
|
118
|
+
if (comments.length === 0)
|
|
119
|
+
return;
|
|
120
|
+
const body = importPath.parent?.node?.body ?? [];
|
|
121
|
+
const index = body.indexOf(node);
|
|
122
|
+
const target = carrier ?? (index >= 0 ? body[index + 1] : undefined);
|
|
123
|
+
if (target) {
|
|
124
|
+
target.comments = [...comments, ...(target.comments ?? [])];
|
|
125
|
+
}
|
|
126
|
+
else if (index > 0) {
|
|
127
|
+
// The import was the last statement: the comments stay where they
|
|
128
|
+
// were, after what precedes it.
|
|
129
|
+
const previous = body[index - 1];
|
|
130
|
+
previous.comments = [
|
|
131
|
+
...(previous.comments ?? []),
|
|
132
|
+
...comments.map((c) => ({ ...c, leading: false, trailing: true })),
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// The import was the only statement: the comments become the file's.
|
|
137
|
+
const program = importPath.parent?.node;
|
|
138
|
+
if (program)
|
|
139
|
+
program.comments = [...comments, ...(program.comments ?? [])];
|
|
140
|
+
}
|
|
141
|
+
node.comments = [];
|
|
142
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stylesheet-import pass every source runs before its JSX work.
|
|
3
|
+
*
|
|
4
|
+
* `--css bestax` (the default) converges every Bulma stylesheet import on the
|
|
5
|
+
* combined `bestax.css` bundle, which already carries the extras; `bulma`
|
|
6
|
+
* keeps plain Bulma v1 CSS and adds the extras import beside it; `keep`
|
|
7
|
+
* leaves the app's own Bulma import alone and only retargets a source
|
|
8
|
+
* library's stylesheet, which no longer resolves once the library is gone.
|
|
9
|
+
*
|
|
10
|
+
* What differs per source is the source's own stylesheet (react-bulma-components'
|
|
11
|
+
* v3 bundle, `rbx/index.css`; bloomer ships none) and anything the source
|
|
12
|
+
* handles before the shared rules (rbx's extension stylesheets).
|
|
13
|
+
*/
|
|
14
|
+
import type { CssMode } from '../../types.js';
|
|
15
|
+
import { type TransformContext } from './jsx-utils.js';
|
|
16
|
+
export interface StylesheetImportOptions {
|
|
17
|
+
/**
|
|
18
|
+
* The source library's own stylesheet, retargeted wherever Bulma's is:
|
|
19
|
+
* which specifiers are it, and how the keep-mode TODO names it (e.g.
|
|
20
|
+
* "rbx's CSS import"). One object, so a matcher never lacks its label.
|
|
21
|
+
*/
|
|
22
|
+
sourceCss?: {
|
|
23
|
+
is: (specifier: string) => boolean;
|
|
24
|
+
label: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Runs first for every import; returning true means the source handled it
|
|
28
|
+
* and the shared rules skip it.
|
|
29
|
+
*/
|
|
30
|
+
handleOwn?: (path: any, specifier: string) => boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function rewriteStylesheetImports(ctx: TransformContext, root: any, cssMode: CssMode, options?: StylesheetImportOptions): void;
|
|
33
|
+
//# sourceMappingURL=css-imports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"css-imports.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/css-imports.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAW,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAuBhE,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,SAAS,CAAC,EAAE;QAAE,EAAE,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC;CACvD;AAED,wBAAgB,wBAAwB,CACtC,GAAG,EAAE,gBAAgB,EACrB,IAAI,EAAE,GAAG,EACT,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,uBAA4B,GACpC,IAAI,CA4EN"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stylesheet-import pass every source runs before its JSX work.
|
|
3
|
+
*
|
|
4
|
+
* `--css bestax` (the default) converges every Bulma stylesheet import on the
|
|
5
|
+
* combined `bestax.css` bundle, which already carries the extras; `bulma`
|
|
6
|
+
* keeps plain Bulma v1 CSS and adds the extras import beside it; `keep`
|
|
7
|
+
* leaves the app's own Bulma import alone and only retargets a source
|
|
8
|
+
* library's stylesheet, which no longer resolves once the library is gone.
|
|
9
|
+
*
|
|
10
|
+
* What differs per source is the source's own stylesheet (react-bulma-components'
|
|
11
|
+
* v3 bundle, `rbx/index.css`; bloomer ships none) and anything the source
|
|
12
|
+
* handles before the shared rules (rbx's extension stylesheets).
|
|
13
|
+
*/
|
|
14
|
+
import { addTodo } from './jsx-utils.js';
|
|
15
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
16
|
+
const BULMA_CSS = 'bulma/css/bulma.min.css';
|
|
17
|
+
const BESTAX_CSS = '@allxsmith/bestax-bulma/bestax.css';
|
|
18
|
+
const EXTRAS_CSS = '@allxsmith/bestax-bulma/extras.css';
|
|
19
|
+
const BULMA_CSS_SPECIFIERS = new Set([
|
|
20
|
+
'bulma/css/bulma.css',
|
|
21
|
+
'bulma/css/bulma.min.css',
|
|
22
|
+
]);
|
|
23
|
+
const BESTAX_CSS_SPECIFIERS = new Set([
|
|
24
|
+
BESTAX_CSS,
|
|
25
|
+
'@allxsmith/bestax-bulma/bestax.min.css',
|
|
26
|
+
'@allxsmith/bestax-bulma/dist/bestax.css',
|
|
27
|
+
'@allxsmith/bestax-bulma/dist/bestax.min.css',
|
|
28
|
+
]);
|
|
29
|
+
const EXTRAS_CSS_SPECIFIERS = new Set([
|
|
30
|
+
EXTRAS_CSS,
|
|
31
|
+
'@allxsmith/bestax-bulma/dist/extras.css',
|
|
32
|
+
]);
|
|
33
|
+
export function rewriteStylesheetImports(ctx, root, cssMode, options = {}) {
|
|
34
|
+
const { j } = ctx;
|
|
35
|
+
const isSourceCss = options.sourceCss?.is ?? (() => false);
|
|
36
|
+
const specifierOf = (p) => String(p.node.source.value);
|
|
37
|
+
let sawBestaxCss = root
|
|
38
|
+
.find(j.ImportDeclaration)
|
|
39
|
+
.paths()
|
|
40
|
+
.some((p) => BESTAX_CSS_SPECIFIERS.has(specifierOf(p)));
|
|
41
|
+
// Whether some import in this file will become bestax.css, regardless of
|
|
42
|
+
// where it sits relative to an existing extras import.
|
|
43
|
+
const willAdoptBestaxCss = cssMode === 'bestax' &&
|
|
44
|
+
root
|
|
45
|
+
.find(j.ImportDeclaration)
|
|
46
|
+
.paths()
|
|
47
|
+
.some((p) => {
|
|
48
|
+
const specifier = specifierOf(p);
|
|
49
|
+
return isSourceCss(specifier) || BULMA_CSS_SPECIFIERS.has(specifier);
|
|
50
|
+
});
|
|
51
|
+
root.find(j.ImportDeclaration).forEach((path) => {
|
|
52
|
+
const source = specifierOf(path);
|
|
53
|
+
if (options.handleOwn?.(path, source))
|
|
54
|
+
return;
|
|
55
|
+
const isOwnCss = isSourceCss(source);
|
|
56
|
+
const isBulmaCss = BULMA_CSS_SPECIFIERS.has(source);
|
|
57
|
+
const isExtrasCss = EXTRAS_CSS_SPECIFIERS.has(source);
|
|
58
|
+
if (!isOwnCss && !isBulmaCss && !isExtrasCss)
|
|
59
|
+
return;
|
|
60
|
+
if (cssMode === 'bestax') {
|
|
61
|
+
if (isOwnCss || isBulmaCss) {
|
|
62
|
+
if (sawBestaxCss) {
|
|
63
|
+
path.prune(); // bestax.css already imported elsewhere in this file
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
path.node.source = j.stringLiteral(BESTAX_CSS);
|
|
67
|
+
sawBestaxCss = true;
|
|
68
|
+
}
|
|
69
|
+
ctx.dirty = true;
|
|
70
|
+
}
|
|
71
|
+
else if (isExtrasCss && (sawBestaxCss || willAdoptBestaxCss)) {
|
|
72
|
+
// bestax.css already contains the extras. `willAdoptBestaxCss` covers
|
|
73
|
+
// the case where the extras import comes FIRST in the file and the
|
|
74
|
+
// import that becomes bestax.css has not been visited yet —
|
|
75
|
+
// otherwise the extras survive alongside it and double-load.
|
|
76
|
+
path.prune();
|
|
77
|
+
ctx.dirty = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (cssMode === 'bulma') {
|
|
81
|
+
if (isOwnCss) {
|
|
82
|
+
path.node.source = j.stringLiteral(BULMA_CSS);
|
|
83
|
+
ctx.dirty = true;
|
|
84
|
+
}
|
|
85
|
+
if ((isOwnCss || isBulmaCss) && !sawBestaxCss) {
|
|
86
|
+
const hasExtras = root
|
|
87
|
+
.find(j.ImportDeclaration)
|
|
88
|
+
.paths()
|
|
89
|
+
.some((p) => EXTRAS_CSS_SPECIFIERS.has(specifierOf(p)));
|
|
90
|
+
if (!hasExtras) {
|
|
91
|
+
// Themed Radio/Checkbox need the bestax extras next to plain Bulma.
|
|
92
|
+
path.insertAfter(j.importDeclaration([], j.stringLiteral(EXTRAS_CSS)));
|
|
93
|
+
ctx.dirty = true;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if (isOwnCss && options.sourceCss) {
|
|
98
|
+
// keep: minimal fix — the source's stylesheet goes with the source.
|
|
99
|
+
path.node.source = j.stringLiteral(BULMA_CSS);
|
|
100
|
+
addTodo(ctx, path, 'css', `replaced ${options.sourceCss.label} with '${BULMA_CSS}'; install bulma@^1 (see https://bestax.io/docs/guides/getting-started/installation)`);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The package.json steps every source's manifest pass takes once the source
|
|
3
|
+
* library itself is dealt with: bring in bestax-bulma, move the app's Bulma to
|
|
4
|
+
* v1, report peer ranges bestax-bulma cannot install beside, and swap the
|
|
5
|
+
* dead node-sass for dart-sass. Pure data-in/data-out, like the passes that
|
|
6
|
+
* call it: no package manager is ever invoked.
|
|
7
|
+
*/
|
|
8
|
+
import type { TodoCollector } from '../../types.js';
|
|
9
|
+
export declare const BULMA_RANGE = "^1.0.4";
|
|
10
|
+
export declare const DEP_SECTIONS: readonly ["dependencies", "devDependencies"];
|
|
11
|
+
type Section = (typeof DEP_SECTIONS)[number];
|
|
12
|
+
export interface Manifest {
|
|
13
|
+
/** The manifest being edited in place. */
|
|
14
|
+
next: Record<string, Record<string, string> | unknown>;
|
|
15
|
+
section(name: Section): Record<string, string> | undefined;
|
|
16
|
+
/** Record a change: it counts as an edit and lands in the report. */
|
|
17
|
+
note(message: string): void;
|
|
18
|
+
/** Report without counting as an edit. */
|
|
19
|
+
report(rule: string, message: string): void;
|
|
20
|
+
/** The edited manifest, or null when nothing changed. */
|
|
21
|
+
result(): Record<string, unknown> | null;
|
|
22
|
+
}
|
|
23
|
+
export declare function openManifest(filePath: string, pkg: Record<string, unknown>, collector: TodoCollector | undefined): Manifest;
|
|
24
|
+
/**
|
|
25
|
+
* @allxsmith/bestax-bulma comes in as a runtime dependency. An older major
|
|
26
|
+
* already declared is reported, not raised: the migrated code is written for
|
|
27
|
+
* the current one, and moving the app's existing bestax code across majors is
|
|
28
|
+
* the app's own step.
|
|
29
|
+
*/
|
|
30
|
+
export declare function addBestax(manifest: Manifest): void;
|
|
31
|
+
export interface BulmaOutcome {
|
|
32
|
+
/** The declared range before any bump, or null when none was declared. */
|
|
33
|
+
declared: string | null;
|
|
34
|
+
bumped: boolean;
|
|
35
|
+
added: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Bump a pre-1 Bulma range; add one only when sources still reference
|
|
39
|
+
* bulma/… directly (otherwise it arrives transitively via bestax-bulma).
|
|
40
|
+
*/
|
|
41
|
+
export declare function moveBulmaToV1(manifest: Manifest, bulmaReferenced: boolean | undefined): BulmaOutcome;
|
|
42
|
+
/**
|
|
43
|
+
* Report ranges bestax-bulma's peers cannot install beside. Report only: a
|
|
44
|
+
* React major and a Font Awesome major (whose icon names change) are the
|
|
45
|
+
* app's own migration steps.
|
|
46
|
+
*/
|
|
47
|
+
export declare function reportPeerRanges(manifest: Manifest): void;
|
|
48
|
+
/** node-sass is dead; dart-sass replaces it in the same section. */
|
|
49
|
+
export declare function replaceNodeSass(manifest: Manifest): void;
|
|
50
|
+
export {};
|
|
51
|
+
//# sourceMappingURL=deps-common.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deps-common.d.ts","sourceRoot":"","sources":["../../../src/sources/_shared/deps-common.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAIpD,eAAO,MAAM,WAAW,WAAW,CAAC;AAIpC,eAAO,MAAM,YAAY,8CAA+C,CAAC;AACzE,KAAK,OAAO,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAE7C,MAAM,WAAW,QAAQ;IACvB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC;IACvD,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAAC;IAC3D,qEAAqE;IACrE,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,0CAA0C;IAC1C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C,yDAAyD;IACzD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;CAC1C;AAED,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,SAAS,EAAE,aAAa,GAAG,SAAS,GACnC,QAAQ,CAiBV;AAaD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAmBlD;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,QAAQ,EAClB,eAAe,EAAE,OAAO,GAAG,SAAS,GACnC,YAAY,CA2Bd;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAqBzD;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,IAAI,CAexD"}
|