bestax-migrate 2.30.0 → 2.31.1
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 +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/sources/bulma-classes/class-map.d.ts +36 -8
- package/dist/sources/bulma-classes/class-map.d.ts.map +1 -1
- package/dist/sources/bulma-classes/class-map.js +98 -19
- package/dist/sources/bulma-classes/plan.d.ts +7 -0
- package/dist/sources/bulma-classes/plan.d.ts.map +1 -1
- package/dist/sources/bulma-classes/plan.js +94 -20
- package/dist/sources/bulma-classes/transform.d.ts.map +1 -1
- package/dist/sources/bulma-classes/transform.js +20 -5
- package/dist/sources/react-bulma-components/mapping.js +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ Run it from your app root. `--param paths="src lib"` (default `src`) and `--para
|
|
|
88
88
|
| Flag | Description |
|
|
89
89
|
| -------------------- | ---------------------------------------------------------------------------------------------- |
|
|
90
90
|
| `--dry`, `-d` | Report what would change without writing files |
|
|
91
|
-
| `--print`, `-p` | Print transformed sources to stdout
|
|
91
|
+
| `--print`, `-p` | Print transformed sources to stdout, still writing them unless `--dry` is set |
|
|
92
92
|
| `--extensions`, `-e` | File extensions to include in a folder (default `js,jsx,ts,tsx,scss,sass`; `html` for pages) |
|
|
93
93
|
| `--css <mode>` | Stylesheet target: `bestax`, `bulma`, or `keep` (default `bestax`; `keep` for `bulma-classes`) |
|
|
94
94
|
| `--no-deps` | Skip updating package.json dependencies |
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;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,EAIV,eAAe,EAEhB,MAAM,YAAY,CAAC;AA2BpB;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,MAAM,EAAE,CAwBV;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;AA2QD;;;;;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,
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;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,EAIV,eAAe,EAEhB,MAAM,YAAY,CAAC;AA2BpB;;;;;GAKG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EAAE,EACjB,UAAU,EAAE,MAAM,EAAE,EACpB,KAAK,GAAE,SAAS,MAAM,EAAO,GAC5B,MAAM,EAAE,CAwBV;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;AA2QD;;;;;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,CAmJT"}
|
package/dist/cli.js
CHANGED
|
@@ -524,7 +524,7 @@ export function createCLI(io = { log: console.log, error: console.error }) {
|
|
|
524
524
|
.argument('<source>', `library to migrate from (${sourceNames().join(', ')})`)
|
|
525
525
|
.argument('<paths...>', 'files or directories to transform')
|
|
526
526
|
.option('-d, --dry', 'dry run — report what would change without writing', false)
|
|
527
|
-
.option('-p, --print', 'print transformed sources to stdout', false)
|
|
527
|
+
.option('-p, --print', 'print transformed sources to stdout (still writes them unless --dry)', false)
|
|
528
528
|
.option('-e, --extensions <list>', 'comma-separated file extensions to include in a folder (html for HTML pages)', 'js,jsx,ts,tsx,scss,sass')
|
|
529
529
|
.option('--css <mode>', `stylesheet target: ${CSS_MODES.join(', ')} (default bestax; keep for bulma-classes)`)
|
|
530
530
|
.option('--no-deps', 'skip updating package.json dependencies')
|
|
@@ -52,6 +52,14 @@ export interface Modifier {
|
|
|
52
52
|
readonly name: string;
|
|
53
53
|
readonly value: string;
|
|
54
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* Off the tags in `tagIn`, where the class stays a class, the prop that
|
|
57
|
+
* sizes the element the same without picking its tag (`textSize`, whose
|
|
58
|
+
* `is-size-4` Bulma sizes as it does `Title`'s `is-4`). The MCP lookup reads
|
|
59
|
+
* it, and the truth e2e holds it to Bulma's stylesheet; the codemod writes
|
|
60
|
+
* it nowhere, with no TODO either, since its class differs.
|
|
61
|
+
*/
|
|
62
|
+
readonly offTag?: PropWrite;
|
|
55
63
|
/**
|
|
56
64
|
* Another of the root's modifiers whose prop this one writes another value
|
|
57
65
|
* of, and that value renders that modifier's class too (`Field`'s
|
|
@@ -145,6 +153,14 @@ export interface Absorbs {
|
|
|
145
153
|
readonly to: string;
|
|
146
154
|
readonly beside: string;
|
|
147
155
|
}>>;
|
|
156
|
+
/**
|
|
157
|
+
* The bestax component that takes a `<label>` beside the child as its own
|
|
158
|
+
* `label` (`Select`, which renders a `Field` and a `Control` around the
|
|
159
|
+
* target, and so takes one only outside a `Field` or `Control`), for the
|
|
160
|
+
* TODO on an element holding one: the target renders no label, so the
|
|
161
|
+
* element stays markup.
|
|
162
|
+
*/
|
|
163
|
+
readonly label?: string;
|
|
148
164
|
}
|
|
149
165
|
/** How a target that renders a glyph from props reads one (`Icon`). */
|
|
150
166
|
export interface ReadsGlyph {
|
|
@@ -387,18 +403,23 @@ export interface RootEntry {
|
|
|
387
403
|
}
|
|
388
404
|
/**
|
|
389
405
|
* Whether a root's target renders this tag: the one it renders by itself (or
|
|
390
|
-
* `renders`, the
|
|
391
|
-
*
|
|
406
|
+
* `renders`, the one the element's classes pick: a heading's size, an
|
|
407
|
+
* `Image` ratio's <figure>), or one its `as` takes. A root that doesn't loses
|
|
408
|
+
* to one that does on the same element.
|
|
392
409
|
*/
|
|
393
410
|
export declare function reachesTag(entry: RootEntry, tag: string, renders?: string): boolean;
|
|
394
411
|
/**
|
|
395
|
-
* How well a root fits an element's tag, for picking one of two: 2 when
|
|
396
|
-
* tag
|
|
397
|
-
*
|
|
398
|
-
*
|
|
412
|
+
* How well a root fits an element's tag, for picking one of two: 2 when its
|
|
413
|
+
* target renders the tag with no `as` (`Hero`'s <section>, or `renders`, the
|
|
414
|
+
* tag the element's classes pick: an `Image` ratio's <figure>), 1 when it
|
|
415
|
+
* reaches it only through `as` (`Container`'s <section>), 0 when it can't
|
|
416
|
+
* render it. The higher wins, so `<section className="hero container">` is a
|
|
417
|
+
* `Hero`, and `<div className="media-left image is-1by1">` no `Image`, which
|
|
418
|
+
* that ratio puts on a <figure>.
|
|
399
419
|
*/
|
|
400
|
-
export declare function tagFit(entry: RootEntry, tag: string): number;
|
|
420
|
+
export declare function tagFit(entry: RootEntry, tag: string, renders?: string): number;
|
|
401
421
|
export declare const COLORS: readonly ["primary", "link", "info", "success", "warning", "danger", "black", "black-bis", "black-ter", "grey-darker", "grey-dark", "grey", "grey-light", "grey-lighter", "white", "white-bis", "white-ter", "light", "dark"];
|
|
422
|
+
export declare const COLOR_SHADES: readonly ["00", "05", "10", "15", "20", "25", "30", "35", "40", "45", "50", "55", "60", "65", "70", "75", "80", "85", "90", "95", "invert", "light", "dark", "soft", "bold", "on-scheme"];
|
|
402
423
|
export declare const SIZES: readonly ["0", "1", "2", "3", "4", "5", "6", "auto"];
|
|
403
424
|
export declare const TEXT_SIZES: readonly ["1", "2", "3", "4", "5", "6", "7"];
|
|
404
425
|
export declare const ALIGNMENTS: readonly ["centered", "justified", "left", "right"];
|
|
@@ -436,7 +457,9 @@ export declare const PLACED: Readonly<Record<string, RootEntry>>;
|
|
|
436
457
|
* where it sits. A better fit beats a higher place here (`tagFit`): `Image`
|
|
437
458
|
* takes a `<figure className="image container">`, which `Container` can't
|
|
438
459
|
* render, and `Hero` a `<section className="hero container">`, whose tag is
|
|
439
|
-
* its own and only reached through `as` by `Container`. The
|
|
460
|
+
* its own and only reached through `as` by `Container`. The fit is to the
|
|
461
|
+
* tag the element's classes make a root render, so `Image` with a ratio fits
|
|
462
|
+
* a <figure> as its own and a <div> only through `as`. The other root stays
|
|
440
463
|
* in `className`, which renders the same either way, and the element gets a
|
|
441
464
|
* TODO naming its component.
|
|
442
465
|
*/
|
|
@@ -490,6 +513,11 @@ export type HelperGroup = 'text-color' | 'background' | 'spacing' | 'gap' | 'typ
|
|
|
490
513
|
export interface HelperToken {
|
|
491
514
|
readonly group: HelperGroup;
|
|
492
515
|
readonly write: PropWrite;
|
|
516
|
+
/**
|
|
517
|
+
* A second prop the class needs beside `write`, which it converts only
|
|
518
|
+
* with (a color shade's `colorShade` beside its color).
|
|
519
|
+
*/
|
|
520
|
+
readonly also?: PropWrite;
|
|
493
521
|
}
|
|
494
522
|
export declare const HELPER_TOKENS: ReadonlyMap<string, HelperToken>;
|
|
495
523
|
/** Every helper prop name, for the attribute-collision check. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,uCAAuC;IACvC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,qEAAqE;IACrE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,MAAM,MAAM,MAAM,GAChB;IAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAE9E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,MAAM,EAAE,SAAS,SAAS,EAAE,CAAC;IACtC,6EAA6E;IAC7E,QAAQ,CAAC,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACvE;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB;;;;;;;;OAQG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;AAE9D;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,uBAAuB;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACrD;;;OAGG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C;;;;;;;OAOG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE;QAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IACxD;;;;OAIG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CACzB,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CACjE,CAAC;
|
|
1
|
+
{"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,8 +23,9 @@ export function inTagSet(set, tag) {
|
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
25
|
* Whether a root's target renders this tag: the one it renders by itself (or
|
|
26
|
-
* `renders`, the
|
|
27
|
-
*
|
|
26
|
+
* `renders`, the one the element's classes pick: a heading's size, an
|
|
27
|
+
* `Image` ratio's <figure>), or one its `as` takes. A root that doesn't loses
|
|
28
|
+
* to one that does on the same element.
|
|
28
29
|
*/
|
|
29
30
|
export function reachesTag(entry, tag, renders = entry.tag) {
|
|
30
31
|
if (tag === renders || entry.as === 'any')
|
|
@@ -32,15 +33,18 @@ export function reachesTag(entry, tag, renders = entry.tag) {
|
|
|
32
33
|
return entry.as?.includes(tag) ?? false;
|
|
33
34
|
}
|
|
34
35
|
/**
|
|
35
|
-
* How well a root fits an element's tag, for picking one of two: 2 when
|
|
36
|
-
* tag
|
|
37
|
-
*
|
|
38
|
-
*
|
|
36
|
+
* How well a root fits an element's tag, for picking one of two: 2 when its
|
|
37
|
+
* target renders the tag with no `as` (`Hero`'s <section>, or `renders`, the
|
|
38
|
+
* tag the element's classes pick: an `Image` ratio's <figure>), 1 when it
|
|
39
|
+
* reaches it only through `as` (`Container`'s <section>), 0 when it can't
|
|
40
|
+
* render it. The higher wins, so `<section className="hero container">` is a
|
|
41
|
+
* `Hero`, and `<div className="media-left image is-1by1">` no `Image`, which
|
|
42
|
+
* that ratio puts on a <figure>.
|
|
39
43
|
*/
|
|
40
|
-
export function tagFit(entry, tag) {
|
|
41
|
-
if (
|
|
44
|
+
export function tagFit(entry, tag, renders = entry.tag) {
|
|
45
|
+
if (tag === renders)
|
|
42
46
|
return 2;
|
|
43
|
-
return reachesTag(entry, tag) ? 1 : 0;
|
|
47
|
+
return reachesTag(entry, tag, renders) ? 1 : 0;
|
|
44
48
|
}
|
|
45
49
|
// ---- Value vocabularies (held to @allxsmith/bestax-bulma/constants) --------
|
|
46
50
|
export const COLORS = [
|
|
@@ -64,6 +68,34 @@ export const COLORS = [
|
|
|
64
68
|
'light',
|
|
65
69
|
'dark',
|
|
66
70
|
];
|
|
71
|
+
export const COLOR_SHADES = [
|
|
72
|
+
'00',
|
|
73
|
+
'05',
|
|
74
|
+
'10',
|
|
75
|
+
'15',
|
|
76
|
+
'20',
|
|
77
|
+
'25',
|
|
78
|
+
'30',
|
|
79
|
+
'35',
|
|
80
|
+
'40',
|
|
81
|
+
'45',
|
|
82
|
+
'50',
|
|
83
|
+
'55',
|
|
84
|
+
'60',
|
|
85
|
+
'65',
|
|
86
|
+
'70',
|
|
87
|
+
'75',
|
|
88
|
+
'80',
|
|
89
|
+
'85',
|
|
90
|
+
'90',
|
|
91
|
+
'95',
|
|
92
|
+
'invert',
|
|
93
|
+
'light',
|
|
94
|
+
'dark',
|
|
95
|
+
'soft',
|
|
96
|
+
'bold',
|
|
97
|
+
'on-scheme',
|
|
98
|
+
];
|
|
67
99
|
export const SIZES = ['0', '1', '2', '3', '4', '5', '6', 'auto'];
|
|
68
100
|
export const TEXT_SIZES = ['1', '2', '3', '4', '5', '6', '7'];
|
|
69
101
|
export const ALIGNMENTS = ['centered', 'justified', 'left', 'right'];
|
|
@@ -290,6 +322,21 @@ function perViewport(prefix, values, prop, viewports) {
|
|
|
290
322
|
function flags(map) {
|
|
291
323
|
return Object.fromEntries(Object.entries(map).map(([token, prop]) => [token, flag(prop)]));
|
|
292
324
|
}
|
|
325
|
+
/**
|
|
326
|
+
* `Title`'s and `SubTitle`'s `is-1` to `is-6`: `size`, exact only on the
|
|
327
|
+
* heading it names (or a <p>), since the size picks the heading. On any
|
|
328
|
+
* other tag the class stays, and `textSize` sizes it the same.
|
|
329
|
+
*/
|
|
330
|
+
function headingSizes() {
|
|
331
|
+
return Object.fromEntries(['1', '2', '3', '4', '5', '6'].map(n => [
|
|
332
|
+
`is-${n}`,
|
|
333
|
+
{
|
|
334
|
+
writes: [{ prop: 'size', value: n }],
|
|
335
|
+
tagIn: [`h${n}`, 'p'],
|
|
336
|
+
offTag: { prop: 'textSize', value: n },
|
|
337
|
+
},
|
|
338
|
+
]));
|
|
339
|
+
}
|
|
293
340
|
/** The same modifiers, each converting only beside `other`. */
|
|
294
341
|
function beside(other, modifiers) {
|
|
295
342
|
return Object.fromEntries(Object.entries(modifiers).map(([token, modifier]) => [
|
|
@@ -975,6 +1022,7 @@ export const ROOTS = {
|
|
|
975
1022
|
}),
|
|
976
1023
|
pairs: { multiple: 'is-multiple' },
|
|
977
1024
|
renames: { size: { to: 'multipleSize', beside: 'multiple' } },
|
|
1025
|
+
label: 'Select',
|
|
978
1026
|
},
|
|
979
1027
|
numberAttrs: ['multipleSize'],
|
|
980
1028
|
adoptsIdFrom: ['Field'],
|
|
@@ -1232,10 +1280,7 @@ export const ROOTS = {
|
|
|
1232
1280
|
as: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'],
|
|
1233
1281
|
sizeDrivesTag: true,
|
|
1234
1282
|
modifiers: {
|
|
1235
|
-
...
|
|
1236
|
-
`is-${n}`,
|
|
1237
|
-
{ writes: [{ prop: 'size', value: n }], tagIn: [`h${n}`, 'p'] },
|
|
1238
|
-
])),
|
|
1283
|
+
...headingSizes(),
|
|
1239
1284
|
...flags({ 'has-skeleton': 'hasSkeleton' }),
|
|
1240
1285
|
},
|
|
1241
1286
|
ownProps: ['size', 'as', 'hasSkeleton', 'textColor', 'bgColor'],
|
|
@@ -1314,10 +1359,7 @@ export const ROOTS = {
|
|
|
1314
1359
|
as: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'],
|
|
1315
1360
|
sizeDrivesTag: true,
|
|
1316
1361
|
modifiers: {
|
|
1317
|
-
...
|
|
1318
|
-
`is-${n}`,
|
|
1319
|
-
{ writes: [{ prop: 'size', value: n }], tagIn: [`h${n}`, 'p'] },
|
|
1320
|
-
])),
|
|
1362
|
+
...headingSizes(),
|
|
1321
1363
|
...flags({ 'is-spaced': 'isSpaced', 'has-skeleton': 'hasSkeleton' }),
|
|
1322
1364
|
},
|
|
1323
1365
|
ownProps: ['size', 'isSpaced', 'as', 'hasSkeleton', 'textColor', 'bgColor'],
|
|
@@ -1952,7 +1994,9 @@ export const PLACED = {
|
|
|
1952
1994
|
* where it sits. A better fit beats a higher place here (`tagFit`): `Image`
|
|
1953
1995
|
* takes a `<figure className="image container">`, which `Container` can't
|
|
1954
1996
|
* render, and `Hero` a `<section className="hero container">`, whose tag is
|
|
1955
|
-
* its own and only reached through `as` by `Container`. The
|
|
1997
|
+
* its own and only reached through `as` by `Container`. The fit is to the
|
|
1998
|
+
* tag the element's classes make a root render, so `Image` with a ratio fits
|
|
1999
|
+
* a <figure> as its own and a <div> only through `as`. The other root stays
|
|
1956
2000
|
* in `className`, which renders the same either way, and the element gets a
|
|
1957
2001
|
* TODO naming its component.
|
|
1958
2002
|
*/
|
|
@@ -2119,6 +2163,39 @@ function helperFlag(group, token, prop) {
|
|
|
2119
2163
|
}
|
|
2120
2164
|
/** The color helpers also take the two CSS keywords. */
|
|
2121
2165
|
const HELPER_COLORS = [...COLORS, 'inherit', 'current'];
|
|
2166
|
+
/**
|
|
2167
|
+
* The colors Bulma writes shade helpers for: its own palette, but `text`,
|
|
2168
|
+
* which bestax's color props don't take.
|
|
2169
|
+
*/
|
|
2170
|
+
const SHADED_COLORS = [
|
|
2171
|
+
'primary',
|
|
2172
|
+
'link',
|
|
2173
|
+
'info',
|
|
2174
|
+
'success',
|
|
2175
|
+
'warning',
|
|
2176
|
+
'danger',
|
|
2177
|
+
'black',
|
|
2178
|
+
'white',
|
|
2179
|
+
'light',
|
|
2180
|
+
'dark',
|
|
2181
|
+
];
|
|
2182
|
+
/**
|
|
2183
|
+
* `has-text-{color}-{shade}` → the color prop and `colorShade`, which render
|
|
2184
|
+
* it together; `has-background-…` the same with `backgroundColorShade`. The
|
|
2185
|
+
* color prop is a placeholder the planner swaps for the target's own, as for
|
|
2186
|
+
* the plain color helpers. A class with no single shade to write (`-100`,
|
|
2187
|
+
* `-30-invert`) is not one of these, and stays a class.
|
|
2188
|
+
*/
|
|
2189
|
+
function shadeTokens(group, prefix, prop, shadeProp) {
|
|
2190
|
+
return SHADED_COLORS.flatMap(color => COLOR_SHADES.map((shade) => [
|
|
2191
|
+
`${prefix}${color}-${shade}`,
|
|
2192
|
+
{
|
|
2193
|
+
group,
|
|
2194
|
+
write: { prop, value: color },
|
|
2195
|
+
also: { prop: shadeProp, value: shade },
|
|
2196
|
+
},
|
|
2197
|
+
]));
|
|
2198
|
+
}
|
|
2122
2199
|
const SPACING_PROPS = [
|
|
2123
2200
|
'm',
|
|
2124
2201
|
'mt',
|
|
@@ -2139,6 +2216,8 @@ export const HELPER_TOKENS = new Map([
|
|
|
2139
2216
|
// Colors: the prop is a placeholder the planner swaps for the target's own.
|
|
2140
2217
|
...helperTokens('text-color', 'has-text-', HELPER_COLORS, 'textColor'),
|
|
2141
2218
|
...helperTokens('background', 'has-background-', HELPER_COLORS, 'bgColor'),
|
|
2219
|
+
...shadeTokens('text-color', 'has-text-', 'textColor', 'colorShade'),
|
|
2220
|
+
...shadeTokens('background', 'has-background-', 'bgColor', 'backgroundColorShade'),
|
|
2142
2221
|
...SPACING_PROPS.flatMap(prop => helperTokens('spacing', `${prop}-`, SIZES, prop)),
|
|
2143
2222
|
// Bulma 0.9's, as the v1 helper that replaced each (`REPLACED_IN_V1`).
|
|
2144
2223
|
['is-marginless', { group: 'spacing', write: { prop: 'm', value: '0' } }],
|
|
@@ -2221,7 +2300,7 @@ export const HELPER_PROPS = new Set([
|
|
|
2221
2300
|
*/
|
|
2222
2301
|
export const PASSTHROUGH = [
|
|
2223
2302
|
{
|
|
2224
|
-
why: 'a color shade, a scheme color or a palette
|
|
2303
|
+
why: 'a color shade with no single shade for `colorShade` or `backgroundColorShade` to write (`-100`, or one with `-invert` on the end), a shade of the `text` color, a scheme color or a palette',
|
|
2225
2304
|
match: /^(?:has-(?:text|background)-[a-z]+(?:-[a-z]+)?-(?:\d{2,3}|invert|light|dark|soft|bold|on-scheme)(?:-invert)?|has-(?:text|background)-text|has-background|is-palette-[a-z]+|is-(?:bold|soft))$/,
|
|
2226
2305
|
},
|
|
2227
2306
|
{
|
|
@@ -63,6 +63,13 @@ export interface ElementFacts {
|
|
|
63
63
|
* component). What an entry that `countsChildren` reads.
|
|
64
64
|
*/
|
|
65
65
|
childElements?: readonly ChildFacts[];
|
|
66
|
+
/**
|
|
67
|
+
* The element's children as plain HTML elements, read as `childElements`
|
|
68
|
+
* is, when nothing else beside them renders but spaces (`{" "}` between
|
|
69
|
+
* them); left out when `childElements` is there. What the TODO on an
|
|
70
|
+
* element holding a <label> beside the child its target renders reads.
|
|
71
|
+
*/
|
|
72
|
+
spacedElements?: readonly ChildFacts[];
|
|
66
73
|
/** The bestax components already in the file inside this element. */
|
|
67
74
|
bestaxInside?: readonly string[];
|
|
68
75
|
/** The bestax components already in the file around this element. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -66,8 +66,10 @@ function tagsItReaches(entry) {
|
|
|
66
66
|
* (`columns box`). The class stays in `className`, which renders the same,
|
|
67
67
|
* but on a bestax component it is raw Bulma markup the lint rule reports, so
|
|
68
68
|
* each says which root won and why, and how to keep what the class does.
|
|
69
|
+
* `rendered` holds the tag the element's classes make each root's target
|
|
70
|
+
* render with no `as`, for the roots the planner picked from.
|
|
69
71
|
*/
|
|
70
|
-
function secondComponents(carried, fixed, root, target, tag) {
|
|
72
|
+
function secondComponents(carried, fixed, root, target, tag, rendered) {
|
|
71
73
|
return carried.flatMap(token => {
|
|
72
74
|
const other = rootFor(token);
|
|
73
75
|
if (token === root || other?.status !== 'mapped')
|
|
@@ -75,14 +77,21 @@ function secondComponents(carried, fixed, root, target, tag) {
|
|
|
75
77
|
const name = other.target;
|
|
76
78
|
if (name === target)
|
|
77
79
|
return [];
|
|
80
|
+
const fitsBetter = root !== undefined &&
|
|
81
|
+
tagFit(rootFor(root), tag, rendered.get(root)) >
|
|
82
|
+
tagFit(other, tag, rendered.get(token));
|
|
83
|
+
// The tag is the target's own, or one the element's classes pick.
|
|
84
|
+
const fits = root !== undefined && rootFor(root).tag === tag
|
|
85
|
+
? `${aTag(tag)} is \`${target}\`'s own element`
|
|
86
|
+
: `\`${target}\` renders ${aTag(tag)} with these classes and no \`as\``;
|
|
78
87
|
const why = !fixed.includes(token)
|
|
79
88
|
? `since \`.${token}\` is there only when its condition holds, and the codemod picks from the classes the element always carries`
|
|
80
89
|
: root === undefined
|
|
81
90
|
? 'since an item of a list converts by where it sits'
|
|
82
|
-
: !reachesTag(other, tag)
|
|
91
|
+
: !reachesTag(other, tag, rendered.get(token))
|
|
83
92
|
? `since \`${name}\` renders ${tagsItReaches(other)}, not ${aTag(tag)}`
|
|
84
|
-
:
|
|
85
|
-
? `since ${
|
|
93
|
+
: fitsBetter
|
|
94
|
+
? `since ${fits}, and \`${name}\` renders one only through \`as\``
|
|
86
95
|
: precedence(root) < precedence(token)
|
|
87
96
|
? `since the codemod ranks \`.${root}\` first, putting layout and parts ahead of surfaces`
|
|
88
97
|
: `since \`.${root}\` comes first on the element`;
|
|
@@ -179,14 +188,20 @@ function planElement(facts) {
|
|
|
179
188
|
: tokens.find(token => rootFor(token)?.status === 'fold');
|
|
180
189
|
if (wrapper)
|
|
181
190
|
return planFold(facts, wrapper, todos);
|
|
182
|
-
// Of two roots, the one that fits the element's tag best wins (
|
|
183
|
-
//
|
|
191
|
+
// Of two roots, the one that fits the element's tag best wins (the tag the
|
|
192
|
+
// element's classes make its target render with no `as`, then one `as`
|
|
193
|
+
// reaches), and the table's precedence decides a tie. So an `Image` ratio,
|
|
194
|
+
// which puts it on a <figure>, fits a <div> only through `as`.
|
|
184
195
|
const roots = placed
|
|
185
196
|
? []
|
|
186
197
|
: tokens
|
|
187
198
|
.filter(token => rootFor(token)?.status === 'mapped')
|
|
188
199
|
.sort((a, b) => precedence(a) - precedence(b));
|
|
189
|
-
const
|
|
200
|
+
const rendered = new Map(roots.map(token => [
|
|
201
|
+
token,
|
|
202
|
+
rendersWith(rootFor(token), tokens, tag, token, facts.attributes),
|
|
203
|
+
]));
|
|
204
|
+
const fit = (token) => tagFit(rootFor(token), tag, rendered.get(token));
|
|
190
205
|
const root = roots.reduce((best, token) => best === undefined || fit(token) > fit(best) ? token : best, undefined);
|
|
191
206
|
let entry;
|
|
192
207
|
if (placed) {
|
|
@@ -221,17 +236,10 @@ function planElement(facts) {
|
|
|
221
236
|
// On a tag the target can't render, the tag is the work that comes first:
|
|
222
237
|
// any other refusal would ask for work (an attribute added or dropped, a
|
|
223
238
|
// child moved) that a re-run then refuses on the tag anyway.
|
|
224
|
-
// What the classes write picks the tag the target renders with no `as
|
|
225
|
-
//
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
const picked = propsFrom(entry, tokens, tag, root, facts.attributes);
|
|
229
|
-
const size = picked.writes.get('size');
|
|
230
|
-
if (entry.sizeDrivesTag && tag !== 'p' && size !== undefined) {
|
|
231
|
-
renders = `h${size}`;
|
|
232
|
-
}
|
|
233
|
-
if (picked.rendersTag)
|
|
234
|
-
renders = picked.rendersTag;
|
|
239
|
+
// What the classes write picks the tag the target renders with no `as`
|
|
240
|
+
// (`rendersWith`), as it did when the root was picked.
|
|
241
|
+
const renders = (root && rendered.get(root)) ??
|
|
242
|
+
rendersWith(entry, tokens, tag, root, facts.attributes);
|
|
235
243
|
let as;
|
|
236
244
|
if (renders !== tag) {
|
|
237
245
|
if (!reachesTag(entry, tag, renders)) {
|
|
@@ -554,7 +562,7 @@ function planElement(facts) {
|
|
|
554
562
|
if (entry.classNameReplaces && (rest.length > 0 || conditionalStays)) {
|
|
555
563
|
return refuse('attr', 'className', `bestax \`${target}\` writes a \`className\` it's given in place of \`.${root}\`, so this converts only with no other class; keep it as markup`);
|
|
556
564
|
}
|
|
557
|
-
todos.push(...secondComponents(carried, tokens, root, target, tag));
|
|
565
|
+
todos.push(...secondComponents(carried, tokens, root, target, tag, rendered));
|
|
558
566
|
// A glyph the target renders from props takes the place of the only child.
|
|
559
567
|
const glyph = moved ?? (entry.readsGlyph ? readGlyph(facts.soleChild) : undefined);
|
|
560
568
|
return {
|
|
@@ -934,9 +942,17 @@ function propsFrom(entry, tokens, tag, root, attributes) {
|
|
|
934
942
|
if (entry.helpersLeftOut && Object.hasOwn(entry.helpersLeftOut, prop)) {
|
|
935
943
|
continue;
|
|
936
944
|
}
|
|
945
|
+
// A shade renders its class only together with its color, so it
|
|
946
|
+
// converts only when both props are free: a shade beside a color or
|
|
947
|
+
// shade already written stays a class.
|
|
948
|
+
const also = helper.also;
|
|
949
|
+
if (also && writes.has(also.prop))
|
|
950
|
+
continue;
|
|
937
951
|
writes.set(prop, helper.write.value ?? true);
|
|
938
952
|
sourceOf.set(prop, token);
|
|
939
953
|
groupOf.set(prop, helper.group);
|
|
954
|
+
if (also)
|
|
955
|
+
writes.set(also.prop, also.value ?? true);
|
|
940
956
|
converted.add(token);
|
|
941
957
|
}
|
|
942
958
|
const undo = (prop) => {
|
|
@@ -971,6 +987,64 @@ function propsFrom(entry, tokens, tag, root, attributes) {
|
|
|
971
987
|
}
|
|
972
988
|
return { writes, converted, numbers, rendersTag };
|
|
973
989
|
}
|
|
990
|
+
/**
|
|
991
|
+
* The tag a root's target renders with the element's classes and no `as`,
|
|
992
|
+
* from what `propsFrom` takes them as: the one class with a `rendersTag`
|
|
993
|
+
* (`Image`'s ratio) its tag, else the heading Title's `size` names, which
|
|
994
|
+
* only `as="p"` overrides, else the root's own.
|
|
995
|
+
*/
|
|
996
|
+
function rendersWith(entry, tokens, tag, root, attributes) {
|
|
997
|
+
const picked = propsFrom(entry, tokens, tag, root, attributes);
|
|
998
|
+
if (picked.rendersTag)
|
|
999
|
+
return picked.rendersTag;
|
|
1000
|
+
const size = picked.writes.get('size');
|
|
1001
|
+
return entry.sizeDrivesTag && tag !== 'p' && size !== undefined
|
|
1002
|
+
? `h${size}`
|
|
1003
|
+
: entry.tag;
|
|
1004
|
+
}
|
|
1005
|
+
/**
|
|
1006
|
+
* For an element whose children are the child its target renders and one
|
|
1007
|
+
* <label> beside it: where the label goes instead, when the table names a
|
|
1008
|
+
* component that takes one (`Select`'s `label`). Empty otherwise.
|
|
1009
|
+
*
|
|
1010
|
+
* That component renders the label in a `Field` of its own, which it renders
|
|
1011
|
+
* only outside one: inside a `Field` it drops `label` and `labelProps`, and
|
|
1012
|
+
* inside a bare `Control` it nests a `.field` in the `.control`. So inside
|
|
1013
|
+
* either the label stays a label of the page's, moved out beside the
|
|
1014
|
+
* element, or the child takes an `aria-label` in its place.
|
|
1015
|
+
*/
|
|
1016
|
+
function labelBeside(facts, spec, where) {
|
|
1017
|
+
const children = facts.childElements ?? facts.spacedElements ?? [];
|
|
1018
|
+
const label = children.find(child => child.tag === 'label');
|
|
1019
|
+
if (!spec.label ||
|
|
1020
|
+
children.length !== 2 ||
|
|
1021
|
+
!label ||
|
|
1022
|
+
!children.some(child => child.tag === spec.tag)) {
|
|
1023
|
+
return '';
|
|
1024
|
+
}
|
|
1025
|
+
const around = (name) => facts.bestaxAround?.includes(name) ||
|
|
1026
|
+
facts.classesAround?.includes(name.toLowerCase());
|
|
1027
|
+
const inForm = around('Field')
|
|
1028
|
+
? `inside a \`Field\` bestax's \`${spec.label}\` renders no label of its own and drops \`label\` and \`labelProps\``
|
|
1029
|
+
: around('Control')
|
|
1030
|
+
? `inside a \`Control\` with no \`Field\` around it, bestax's \`${spec.label}\` renders its label in a \`.field\` of its own inside the \`.control\`, which Bulma's styles aren't written for`
|
|
1031
|
+
: undefined;
|
|
1032
|
+
if (inForm) {
|
|
1033
|
+
return `; the <label> beside it can't stay inside the ${where} that bestax renders, and ${inForm}, so move the <label> out beside ${where}, its \`htmlFor\` on the <${spec.tag}>'s \`id\`, or give the <${spec.tag}> an \`aria-label\` in its place, then re-run`;
|
|
1034
|
+
}
|
|
1035
|
+
// A computed `className` (`null`) is one the codemod can't read, and it
|
|
1036
|
+
// may be what hides the label, so it is named rather than left out. So is
|
|
1037
|
+
// a spread, which can carry a `className` of its own.
|
|
1038
|
+
const classes = label.tokens === null
|
|
1039
|
+
? ', its `className`, which is computed, as `labelProps={{ className: … }}` with the same expression'
|
|
1040
|
+
: label.tokens?.length
|
|
1041
|
+
? `, its classes as \`labelProps={{ className: '${label.tokens.join(' ')}' }}\``
|
|
1042
|
+
: '';
|
|
1043
|
+
const spread = label.hasSpread
|
|
1044
|
+
? ', what its spread carries in `labelProps` too, since it can set a `className` of its own'
|
|
1045
|
+
: '';
|
|
1046
|
+
return `; the <label> beside it goes on bestax's \`${spec.label}\` instead, which renders ${where} inside a \`Field\` and a \`Control\`: the label's text as \`label\`${classes}${spread}, and \`${spec.label}\` points the label at the <${spec.tag}>'s \`id\` itself, so convert the two by hand`;
|
|
1047
|
+
}
|
|
974
1048
|
/** `a`, `a or b`, `a, b or c`, each in backticks. */
|
|
975
1049
|
function orList(names, word = 'or') {
|
|
976
1050
|
const quoted = names.map(name => `\`${name}\``);
|
|
@@ -1001,7 +1075,7 @@ function absorb(facts, where, entry, target, refuse) {
|
|
|
1001
1075
|
(next && next.tag !== after?.tag)) {
|
|
1002
1076
|
return refuse('children', target, after
|
|
1003
1077
|
? `${itself}, and a \`${after.target}\` after it from among its children, so this element converts only around a single <${spec.tag}>, and at most one <${after.tag}> after it, with nothing else beside them`
|
|
1004
|
-
: `${itself}, so this element converts only around a single <${spec.tag}>, with nothing else beside it`);
|
|
1078
|
+
: `${itself}, so this element converts only around a single <${spec.tag}>, with nothing else beside it${labelBeside(facts, spec, where)}`);
|
|
1005
1079
|
}
|
|
1006
1080
|
if (next &&
|
|
1007
1081
|
(next.tokens !== undefined ||
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AA+iCvD;;;;GAIG;AACH,eAAO,MAAM,UAAU,0DAKb,CAAC;AAGX,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA89BpB"}
|
|
@@ -662,15 +662,25 @@ function childFacts(child) {
|
|
|
662
662
|
isEmpty: (child.children ?? []).every(dropped),
|
|
663
663
|
};
|
|
664
664
|
}
|
|
665
|
+
/** A space React renders between elements: blank text, or `{" "}`. */
|
|
666
|
+
function space(child) {
|
|
667
|
+
const blank = (text) => /^[ \t\n\r]*$/.test(text);
|
|
668
|
+
if (child.type === 'JSXText')
|
|
669
|
+
return blank(child.value);
|
|
670
|
+
return (child.type === 'JSXExpressionContainer' &&
|
|
671
|
+
child.expression?.type === 'StringLiteral' &&
|
|
672
|
+
blank(child.expression.value));
|
|
673
|
+
}
|
|
665
674
|
/**
|
|
666
675
|
* An element's children as plain HTML elements, when that is every one
|
|
667
|
-
* React renders
|
|
668
|
-
* is known of
|
|
676
|
+
* React renders but what `skip` passes over (whitespace React drops);
|
|
677
|
+
* undefined when one is anything else. `more` adds what else is known of
|
|
678
|
+
* each.
|
|
669
679
|
*/
|
|
670
|
-
function childElementsOf(element, more = () => ({})) {
|
|
680
|
+
function childElementsOf(element, more = () => ({}), skip = dropped) {
|
|
671
681
|
const children = [];
|
|
672
682
|
for (const child of element.children ?? []) {
|
|
673
|
-
if (
|
|
683
|
+
if (skip(child))
|
|
674
684
|
continue;
|
|
675
685
|
const found = child.type === 'JSXElement' ? childFacts(child) : undefined;
|
|
676
686
|
if (!found)
|
|
@@ -1258,6 +1268,10 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
1258
1268
|
const className = classAttr ? staticClassName(classAttr) : '';
|
|
1259
1269
|
const surrounding = around(elementPath);
|
|
1260
1270
|
const sole = soleChild(element);
|
|
1271
|
+
const childElements = childElementsOf(element, readChild);
|
|
1272
|
+
const spaced = childElements
|
|
1273
|
+
? undefined
|
|
1274
|
+
: childElementsOf(element, undefined, space);
|
|
1261
1275
|
// A joiner call the codemod can read converts exactly: its fixed classes
|
|
1262
1276
|
// as for a static className, and each condition on a flag as its prop.
|
|
1263
1277
|
const joined = className === null
|
|
@@ -1275,7 +1289,8 @@ export default function transform(fileInfo, api, options = {}) {
|
|
|
1275
1289
|
childTargets: childTargets(elementPath),
|
|
1276
1290
|
soleChildTarget: planned.get(sole)?.conversion?.target,
|
|
1277
1291
|
soleChild: sole && childFacts(sole),
|
|
1278
|
-
childElements
|
|
1292
|
+
childElements,
|
|
1293
|
+
...(spaced && { spacedElements: spaced }),
|
|
1279
1294
|
bestaxInside: bestaxInside.get(element) ?? [],
|
|
1280
1295
|
bestaxAround: surrounding.bestax,
|
|
1281
1296
|
componentsAround: surrounding.other,
|
|
@@ -33,7 +33,7 @@ export const UNIVERSAL_PROPS = {
|
|
|
33
33
|
backgroundColor: { rename: 'bgColor' },
|
|
34
34
|
textColor: {},
|
|
35
35
|
colorVariant: {
|
|
36
|
-
todo: "no direct equivalent; use isLight (Button/Notification) or a color shade like
|
|
36
|
+
todo: "no direct equivalent; use isLight (Button/Notification) or a color shade like bgColor='primary' backgroundColorShade='90'",
|
|
37
37
|
},
|
|
38
38
|
// TypographyProps
|
|
39
39
|
textSize: { numberToString: true },
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bestax-migrate",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.31.1",
|
|
4
4
|
"description": "Codemods for migrating existing React apps from other Bulma libraries to @allxsmith/bestax-bulma",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"clean": "rimraf dist",
|
|
79
79
|
"release": "npx semantic-release"
|
|
80
80
|
},
|
|
81
|
-
"readme": "# bestax-migrate\n\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/bestax-migrate/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/bestax-migrate#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nCodemods that migrate existing React apps to [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — the actively maintained React component library for **Bulma v1**.\n\nCurrently supported sources:\n\n| Source | Status |\n| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |\n| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs) |\n| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs) |\n| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged) |\n| `bulma-classes`: Bulma's classes on plain JSX, no library | ✅ Converts an element only when bestax renders the same markup; the rest is flagged |\n| `bulma-classes` on HTML: static pages and templates styled with Bulma | ✅ Writes a React component beside each page; its head and scripts are flagged |\n\nPass the source as the first argument: `bestax-migrate <source> <paths…>`.\n\n## Requirements\n\n**Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the CLI\nexits immediately with an explicit upgrade message.\n\nThis applies only to the Node version the codemod itself runs on. It places no requirement on\nthe app being migrated — the source is read as text and is never executed.\n\n## Usage\n\n```bash\n# Preview what would change (no writes)\npnpm dlx bestax-migrate react-bulma-components src/ --dry\n# …or, for an rbx or bloomer app\npnpm dlx bestax-migrate rbx src/ --dry\npnpm dlx bestax-migrate bloomer src/ --dry\n# …or, for an app that writes Bulma's classes on plain JSX\npnpm dlx bestax-migrate bulma-classes src/ --dry\n# …or, for static HTML pages styled with Bulma: name a page, or walk a folder with -e html\n# (-e html,htm takes .htm pages too)\npnpm dlx bestax-migrate bulma-classes src/pages/login/index.html --dry\npnpm dlx bestax-migrate bulma-classes -e html src/pages/ --dry\n\n# Apply the migration\npnpm dlx bestax-migrate react-bulma-components src/\n```\n\nnpm and yarn work too: `npx bestax-migrate …` / `yarn dlx bestax-migrate …`.\n\nThe codemod uses [jscodeshift](https://github.com/facebook/jscodeshift) to:\n\n- rewrite the source library's imports to `@allxsmith/bestax-bulma` (including destructuring and namespace imports)\n- rename components and compound sub-components (`Form.Textarea` → `TextArea`, `Card.Footer.Item` → `Card.FooterItem`, `Hero.Footer` → `Hero.Foot`, …) — and, for bloomer, its flat names onto bestax's compounds (`CardHeaderTitle` → `Card.Header.Title`)\n- convert props (`renderAs` → `as`, `loading` → `isLoading`, numeric spacing/text sizes → string unions, `textAlign=\"center\"` → `textAlign=\"centered\"`, …)\n- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`) and bloomer's `isDisplay`/`isHidden` strings, arrays and objects (`isHidden=\"touch\"` → `visibilityTouch=\"hidden\"`)\n- for `bulma-classes`, turn raw Bulma markup into components and props (`<a className=\"button is-primary\">` → `<Button as=\"a\" color=\"primary\">`, `<p className=\"has-text-centered mt-4\">` → `<Paragraph textAlign=\"centered\" mt=\"4\">`), converting an element only when bestax renders exactly the same markup\n- for `bulma-classes` on an HTML page, write a React module beside it (`index.html` → `index.tsx`, or `.jsx` when the package isn't TypeScript) whose default export is the page's body as a component (`LoginPage`), converted as the same markup written as JSX would be. The page is never changed and an existing module is never overwritten; the head, the `<html>` and `<body>` attributes, the stylesheets and scripts it loads, and inline handlers are left as `html-*` TODOs, except that under `--css bestax` or `--css bulma` the module imports the stylesheet in place of the page's Bulma `<link>`\n- restructure patterns bestax models differently (`Table.Container`, Navbar dropdowns, `Form.Help`, icon-font children → `<Icon name=…>`)\n- migrate stylesheets: CSS imports converge on `@allxsmith/bestax-bulma/bestax.css`, and SCSS files move from Bulma 0.9's `@import` + `$var !default` overrides to `@use 'bulma/sass' with (…)` plus `@use '@allxsmith/bestax-bulma/scss/extras'`\n- update `package.json`: remove the source library, add `@allxsmith/bestax-bulma`, raise a declared pre-1.0 `bulma` to `^1` (adding it only when your sources import `bulma/…` directly — otherwise it arrives transitively), and swap the dead `node-sass` for dart `sass` (no install is ever run). Migrating **rbx** is what frees an app from Bulma 0.7.5: rbx pinned it as a _direct_ dependency, so the app could not choose its own Bulma version at all. The four Bulma extensions rbx also pulled in (`bulma-badge`, `bulma-divider`, `bulma-pageloader`, `bulma-tooltip`) are **reported rather than removed** — bestax replaces all four, but a manifest entry is a deliberate declaration and your own Sass may import them. A **bloomer** app declared its own Bulma 0.6, which is what gets bumped. For **bulma-classes** there is no library to remove, and by default (`--css keep`) the app's Bulma version, Sass and stylesheet imports all stay: its own Bulma already styles every class a converted element renders. `--css bestax` or `--css bulma` moves it to Bulma v1 like the other sources\n\nAnything without a safe automatic conversion is left in place with a `// TODO(bestax-migrate): …` comment, and the run ends with a report of every TODO by file and line. TODOs are expected output, not errors — resolve them with the migration guide ([react-bulma-components](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components), [rbx](https://bestax.io/docs/guides/getting-started/migration/rbx), [bloomer](https://bestax.io/docs/guides/getting-started/migration/bloomer), [Bulma classes](https://bestax.io/docs/guides/getting-started/migration/bulma-classes)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:\n\n```bash\nnpx skills add https://github.com/allxsmith/bestax --skill bestax-migrate\n```\n\n### Through the Codemod Registry\n\nbestax-migrate is also in the [Codemod Registry](https://app.codemod.com/registry) as `bestax-migrate`, for teams that run their migrations through Codemod. That package runs this CLI from npm at a pinned release, which can trail the newest one:\n\n```bash\n# Preview (no writes)\nnpx codemod bestax-migrate --workflow preview --param source=react-bulma-components\n# Apply\nnpx codemod bestax-migrate --param source=react-bulma-components\n```\n\nRun it from your app root. `--param paths=\"src lib\"` (default `src`) and `--param options=\"--css keep\"` pass through to the CLI. Codemod's own `--dry-run` skips the shell step this package runs, so use the `preview` workflow for a dry run.\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 in a folder (default `js,jsx,ts,tsx,scss,sass`; `html` for pages) |\n| `--css <mode>` | Stylesheet target: `bestax`, `bulma`, or `keep` (default `bestax`; `keep` for `bulma-classes`) |\n| `--no-deps` | Skip updating package.json dependencies |\n\n## After the codemod\n\n1. Run your package manager's install (the codemod rewrote `package.json` but never installs)\n2. Search for `TODO(bestax-migrate)` and resolve each comment\n3. Typecheck/build and review the rendered app\n\nFull walkthrough: [react-bulma-components migration guide](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components) · [rbx migration guide](https://bestax.io/docs/guides/getting-started/migration/rbx) · [bloomer migration guide](https://bestax.io/docs/guides/getting-started/migration/bloomer) · [Bulma classes migration guide](https://bestax.io/docs/guides/getting-started/migration/bulma-classes).\n\n## Hardened by default\n\nA codemod rewrites your source in place, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/bestax-migrate#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **The libraries this tool migrates away from are never installed here** — source fixtures are read as text only, so no unmaintained third-party package enters the dependency tree.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, and CodeQL, Dependency Review, and Dependabot run continuously alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`bestax-migrate` can send one **anonymous** usage event after a successful\nrun — only if you opt in when asked (once, on an interactive terminal). The\nevent is just the run's shape — source library, CSS mode, the dry/deps flags, a\ncapped changed-file count, and per-rule TODO counts — plus the CLI version,\nNode major version, and OS platform name. Never file paths, file contents,\ncode, names, IPs, or machine IDs, and no identifier exists that could link two\nevents together. Opt out any time with `--no-telemetry`,\n`BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## License\n\nSource code licensed MIT\n"
|
|
81
|
+
"readme": "# bestax-migrate\n\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://www.npmjs.com/package/bestax-migrate)\n[](https://opensource.org/licenses/MIT)\n[](https://socket.dev/npm/package/bestax-migrate/overview)\n[](https://scorecard.dev/viewer/?uri=github.com/allxsmith/bestax)\n[](https://www.bestpractices.dev/projects/14361)\n[](https://www.npmjs.com/package/bestax-migrate#provenance)\n[](https://github.com/allxsmith/bestax/blob/main/SECURITY.md)\n\nCodemods that migrate existing React apps to [`@allxsmith/bestax-bulma`](https://www.npmjs.com/package/@allxsmith/bestax-bulma) — the actively maintained React component library for **Bulma v1**.\n\nCurrently supported sources:\n\n| Source | Status |\n| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ |\n| [`react-bulma-components`](https://github.com/couds/react-bulma-components) (v4) | ✅ All 32 components mapped (a few patterns are flagged as TODOs) |\n| [`rbx`](https://github.com/dfee/rbx) (v2) | ✅ Full export surface mapped (a few patterns are flagged as TODOs) |\n| [`bloomer`](https://github.com/AlgusDark/bloomer) (0.6) | ✅ All 108 exports mapped (Font Awesome 4 icons and Bulma 0.4's `Nav` are flagged) |\n| `bulma-classes`: Bulma's classes on plain JSX, no library | ✅ Converts an element only when bestax renders the same markup; the rest is flagged |\n| `bulma-classes` on HTML: static pages and templates styled with Bulma | ✅ Writes a React component beside each page; its head and scripts are flagged |\n\nPass the source as the first argument: `bestax-migrate <source> <paths…>`.\n\n## Requirements\n\n**Node.js 22 or newer.** Node 18 and 20 are both past end-of-life. On an older runtime the CLI\nexits immediately with an explicit upgrade message.\n\nThis applies only to the Node version the codemod itself runs on. It places no requirement on\nthe app being migrated — the source is read as text and is never executed.\n\n## Usage\n\n```bash\n# Preview what would change (no writes)\npnpm dlx bestax-migrate react-bulma-components src/ --dry\n# …or, for an rbx or bloomer app\npnpm dlx bestax-migrate rbx src/ --dry\npnpm dlx bestax-migrate bloomer src/ --dry\n# …or, for an app that writes Bulma's classes on plain JSX\npnpm dlx bestax-migrate bulma-classes src/ --dry\n# …or, for static HTML pages styled with Bulma: name a page, or walk a folder with -e html\n# (-e html,htm takes .htm pages too)\npnpm dlx bestax-migrate bulma-classes src/pages/login/index.html --dry\npnpm dlx bestax-migrate bulma-classes -e html src/pages/ --dry\n\n# Apply the migration\npnpm dlx bestax-migrate react-bulma-components src/\n```\n\nnpm and yarn work too: `npx bestax-migrate …` / `yarn dlx bestax-migrate …`.\n\nThe codemod uses [jscodeshift](https://github.com/facebook/jscodeshift) to:\n\n- rewrite the source library's imports to `@allxsmith/bestax-bulma` (including destructuring and namespace imports)\n- rename components and compound sub-components (`Form.Textarea` → `TextArea`, `Card.Footer.Item` → `Card.FooterItem`, `Hero.Footer` → `Hero.Foot`, …) — and, for bloomer, its flat names onto bestax's compounds (`CardHeaderTitle` → `Card.Header.Title`)\n- convert props (`renderAs` → `as`, `loading` → `isLoading`, numeric spacing/text sizes → string unions, `textAlign=\"center\"` → `textAlign=\"centered\"`, …)\n- flatten responsive breakpoint objects (`mobile={{ size: 4 }}` → `sizeMobile={4}`) and bloomer's `isDisplay`/`isHidden` strings, arrays and objects (`isHidden=\"touch\"` → `visibilityTouch=\"hidden\"`)\n- for `bulma-classes`, turn raw Bulma markup into components and props (`<a className=\"button is-primary\">` → `<Button as=\"a\" color=\"primary\">`, `<p className=\"has-text-centered mt-4\">` → `<Paragraph textAlign=\"centered\" mt=\"4\">`), converting an element only when bestax renders exactly the same markup\n- for `bulma-classes` on an HTML page, write a React module beside it (`index.html` → `index.tsx`, or `.jsx` when the package isn't TypeScript) whose default export is the page's body as a component (`LoginPage`), converted as the same markup written as JSX would be. The page is never changed and an existing module is never overwritten; the head, the `<html>` and `<body>` attributes, the stylesheets and scripts it loads, and inline handlers are left as `html-*` TODOs, except that under `--css bestax` or `--css bulma` the module imports the stylesheet in place of the page's Bulma `<link>`\n- restructure patterns bestax models differently (`Table.Container`, Navbar dropdowns, `Form.Help`, icon-font children → `<Icon name=…>`)\n- migrate stylesheets: CSS imports converge on `@allxsmith/bestax-bulma/bestax.css`, and SCSS files move from Bulma 0.9's `@import` + `$var !default` overrides to `@use 'bulma/sass' with (…)` plus `@use '@allxsmith/bestax-bulma/scss/extras'`\n- update `package.json`: remove the source library, add `@allxsmith/bestax-bulma`, raise a declared pre-1.0 `bulma` to `^1` (adding it only when your sources import `bulma/…` directly — otherwise it arrives transitively), and swap the dead `node-sass` for dart `sass` (no install is ever run). Migrating **rbx** is what frees an app from Bulma 0.7.5: rbx pinned it as a _direct_ dependency, so the app could not choose its own Bulma version at all. The four Bulma extensions rbx also pulled in (`bulma-badge`, `bulma-divider`, `bulma-pageloader`, `bulma-tooltip`) are **reported rather than removed** — bestax replaces all four, but a manifest entry is a deliberate declaration and your own Sass may import them. A **bloomer** app declared its own Bulma 0.6, which is what gets bumped. For **bulma-classes** there is no library to remove, and by default (`--css keep`) the app's Bulma version, Sass and stylesheet imports all stay: its own Bulma already styles every class a converted element renders. `--css bestax` or `--css bulma` moves it to Bulma v1 like the other sources\n\nAnything without a safe automatic conversion is left in place with a `// TODO(bestax-migrate): …` comment, and the run ends with a report of every TODO by file and line. TODOs are expected output, not errors — resolve them with the migration guide ([react-bulma-components](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components), [rbx](https://bestax.io/docs/guides/getting-started/migration/rbx), [bloomer](https://bestax.io/docs/guides/getting-started/migration/bloomer), [Bulma classes](https://bestax.io/docs/guides/getting-started/migration/bulma-classes)), or let the [`bestax-migrate` Agent Skill](https://bestax.io/docs/skills/intro) walk them for you:\n\n```bash\nnpx skills add https://github.com/allxsmith/bestax --skill bestax-migrate\n```\n\n### Through the Codemod Registry\n\nbestax-migrate is also in the [Codemod Registry](https://app.codemod.com/registry) as `bestax-migrate`, for teams that run their migrations through Codemod. That package runs this CLI from npm at a pinned release, which can trail the newest one:\n\n```bash\n# Preview (no writes)\nnpx codemod bestax-migrate --workflow preview --param source=react-bulma-components\n# Apply\nnpx codemod bestax-migrate --param source=react-bulma-components\n```\n\nRun it from your app root. `--param paths=\"src lib\"` (default `src`) and `--param options=\"--css keep\"` pass through to the CLI. Codemod's own `--dry-run` skips the shell step this package runs, so use the `preview` workflow for a dry run.\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, still writing them unless `--dry` is set |\n| `--extensions`, `-e` | File extensions to include in a folder (default `js,jsx,ts,tsx,scss,sass`; `html` for pages) |\n| `--css <mode>` | Stylesheet target: `bestax`, `bulma`, or `keep` (default `bestax`; `keep` for `bulma-classes`) |\n| `--no-deps` | Skip updating package.json dependencies |\n\n## After the codemod\n\n1. Run your package manager's install (the codemod rewrote `package.json` but never installs)\n2. Search for `TODO(bestax-migrate)` and resolve each comment\n3. Typecheck/build and review the rendered app\n\nFull walkthrough: [react-bulma-components migration guide](https://bestax.io/docs/guides/getting-started/migration/react-bulma-components) · [rbx migration guide](https://bestax.io/docs/guides/getting-started/migration/rbx) · [bloomer migration guide](https://bestax.io/docs/guides/getting-started/migration/bloomer) · [Bulma classes migration guide](https://bestax.io/docs/guides/getting-started/migration/bulma-classes).\n\n## Hardened by default\n\nA codemod rewrites your source in place, so how it is built and published matters:\n\n- **Signed provenance** — every release carries a sigstore attestation linking the tarball to the exact commit and CI run that built it. Check the **Provenance** section on the [npm page](https://www.npmjs.com/package/bestax-migrate#provenance), or run `npm audit signatures`.\n- **npm OIDC trusted publishing** — short-lived, per-run credentials; no long-lived `NPM_TOKEN` exists to be stolen. Release commits and tags are GPG-signed.\n- **Socket.dev scans every PR** for malware, install scripts, obfuscated code, and privilege escalation before it can reach `main`.\n- **The libraries this tool migrates away from are never installed here** — source fixtures are read as text only, so no unmaintained third-party package enters the dependency tree.\n- **Dependencies are a deliberate act** — install scripts are blocked unless individually allow-listed, freshly published versions are refused for 3 days, and CI installs only what the reviewed lockfile resolves.\n- **Every GitHub Action is pinned to a full commit SHA**, and CodeQL, Dependency Review, and Dependabot run continuously alongside a high-severity `pnpm audit` gate.\n- **Layered AI review before merge** — [CodeRabbit](https://coderabbit.ai) plus an independent adversarial Claude review (a different model from the one writing AI-authored changes), on top of required green CI, an approving review, and a human merge.\n\nFull detail: [`SECURITY.md`](https://github.com/allxsmith/bestax/blob/main/SECURITY.md) · [Security guide](https://bestax.io/docs/guides/security)\n\n## Telemetry\n\n`bestax-migrate` can send one **anonymous** usage event after a successful\nrun — only if you opt in when asked (once, on an interactive terminal). The\nevent is just the run's shape — source library, CSS mode, the dry/deps flags, a\ncapped changed-file count, and per-rule TODO counts — plus the CLI version,\nNode major version, and OS platform name. Never file paths, file contents,\ncode, names, IPs, or machine IDs, and no identifier exists that could link two\nevents together. Opt out any time with `--no-telemetry`,\n`BESTAX_TELEMETRY=0`, or `DO_NOT_TRACK=1`.\n\nFull disclosure of every field and control: [Telemetry guide](https://bestax.io/docs/guides/telemetry)\n\n## License\n\nSource code licensed MIT\n"
|
|
82
82
|
}
|