bestax-migrate 2.6.0 → 2.8.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.
@@ -16,6 +16,8 @@ export interface PropWrite {
16
16
  readonly prop: string;
17
17
  /** Omitted for a bare boolean prop. */
18
18
  readonly value?: string;
19
+ /** The prop is typed as a number, so the value is written as one. */
20
+ readonly numeric?: boolean;
19
21
  }
20
22
  export type TagSet = {
21
23
  readonly on: readonly string[];
@@ -73,7 +75,20 @@ export interface RootEntry {
73
75
  readonly in: string;
74
76
  readonly unless: readonly string[];
75
77
  readonly whenEmpty?: boolean;
78
+ /** Only when the element carries this class (`Field` with `is-horizontal`). */
79
+ readonly when?: string;
76
80
  };
81
+ /**
82
+ * The target provides context bestax's form controls read to skip wrappers
83
+ * of their own, so an element around a bestax component already in the file
84
+ * stays markup: that component would render differently.
85
+ */
86
+ readonly providesContext?: boolean;
87
+ /**
88
+ * Inside one of these bestax components already in the file, the target
89
+ * takes a generated `id` when the element has none of its own.
90
+ */
91
+ readonly adoptsIdFrom?: readonly string[];
77
92
  /** The target takes no helper props, so every helper class stays a class. */
78
93
  readonly noHelpers?: boolean;
79
94
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"class-map.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/class-map.ts"],"names":[],"mappings":"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"}
@@ -146,6 +146,8 @@ const COMPONENT_COLORS = [
146
146
  'light',
147
147
  'dark',
148
148
  ];
149
+ /** Bulma's whole-step spacing scale, as `Grid`'s gap props take it. */
150
+ const GAPS = ['0', '1', '2', '3', '4', '5', '6', '7', '8'];
149
151
  const COLUMN_SIZES = [
150
152
  '1',
151
153
  '2',
@@ -183,6 +185,13 @@ const flag = (prop) => ({ writes: [{ prop }] });
183
185
  const set = (prop, value) => ({
184
186
  writes: [{ prop, value }],
185
187
  });
188
+ /** `prefix + n` → `prop={n}` for `n` from 1 to `max`, for a prop typed as a number. */
189
+ function numbers(prefix, max, prop) {
190
+ return Object.fromEntries(Array.from({ length: max }, (_, i) => String(i + 1)).map(value => [
191
+ `${prefix}${value}`,
192
+ { writes: [{ prop, value, numeric: true }] },
193
+ ]));
194
+ }
186
195
  /** `prefix + value + suffix` → `prop = value`, for each value. */
187
196
  function tokens(prefix, values, prop, suffix = '') {
188
197
  return Object.fromEntries(values.map(value => [`${prefix}${value}${suffix}`, set(prop, value)]));
@@ -481,6 +490,59 @@ export const ROOTS = {
481
490
  'isNarrowFullhd',
482
491
  ],
483
492
  },
493
+ // Grid's gaps take a numeric string, but its column minimum and every Cell
494
+ // placement are typed as numbers. The half steps (`is-gap-0.5`) have no prop.
495
+ grid: {
496
+ ...BASE,
497
+ target: 'Grid',
498
+ tag: 'div',
499
+ modifiers: {
500
+ ...tokens('is-gap-', GAPS, 'gap'),
501
+ ...tokens('is-column-gap-', GAPS, 'columnGap'),
502
+ ...tokens('is-row-gap-', GAPS, 'rowGap'),
503
+ ...numbers('is-col-min-', 32, 'minCol'),
504
+ },
505
+ ownProps: [
506
+ 'isFixed',
507
+ 'gap',
508
+ 'columnGap',
509
+ 'rowGap',
510
+ 'minCol',
511
+ 'fixedCols',
512
+ 'fixedColsMobile',
513
+ 'fixedColsTablet',
514
+ 'fixedColsDesktop',
515
+ 'fixedColsWidescreen',
516
+ 'fixedColsFullhd',
517
+ 'textColor',
518
+ 'color',
519
+ 'bgColor',
520
+ ],
521
+ },
522
+ cell: {
523
+ ...BASE,
524
+ target: 'Cell',
525
+ tag: 'div',
526
+ modifiers: {
527
+ ...numbers('is-col-start-', 12, 'colStart'),
528
+ ...numbers('is-col-from-end-', 12, 'colFromEnd'),
529
+ ...numbers('is-col-span-', 12, 'colSpan'),
530
+ ...numbers('is-row-start-', 12, 'rowStart'),
531
+ ...numbers('is-row-from-end-', 12, 'rowFromEnd'),
532
+ ...numbers('is-row-span-', 12, 'rowSpan'),
533
+ },
534
+ ownProps: [
535
+ 'colStart',
536
+ 'colFromEnd',
537
+ 'colSpan',
538
+ 'rowStart',
539
+ 'rowFromEnd',
540
+ 'rowSpan',
541
+ 'textColor',
542
+ 'color',
543
+ 'bgColor',
544
+ ],
545
+ },
484
546
  container: {
485
547
  ...BASE,
486
548
  target: 'Container',
@@ -547,6 +609,168 @@ export const ROOTS = {
547
609
  ],
548
610
  passThrough: ['onClick'],
549
611
  },
612
+ // Form markup. `Field` and `Control` tell the bestax form controls inside
613
+ // them to skip wrappers of their own, and `InputBase` / `TextAreaBase` are
614
+ // the controls without wrappers (a `Field` with no `label` hands them no id).
615
+ field: {
616
+ ...BASE,
617
+ target: 'Field',
618
+ tag: 'div',
619
+ // `has-addons-centered`, `is-grouped-right` and the like stay classes:
620
+ // the prop values that render them render `has-addons` too.
621
+ modifiers: flags({
622
+ 'is-horizontal': 'horizontal',
623
+ 'is-grouped': 'grouped',
624
+ 'has-addons': 'hasAddons',
625
+ 'is-narrow': 'narrow',
626
+ }),
627
+ wrapsChildren: {
628
+ in: 'field-body',
629
+ unless: ['Field.Label', 'Field.Body'],
630
+ whenEmpty: true,
631
+ when: 'is-horizontal',
632
+ },
633
+ providesContext: true,
634
+ ownProps: [
635
+ 'horizontal',
636
+ 'grouped',
637
+ 'hasAddons',
638
+ 'narrow',
639
+ 'label',
640
+ 'labelSize',
641
+ 'labelProps',
642
+ 'textColor',
643
+ 'color',
644
+ 'bgColor',
645
+ ],
646
+ },
647
+ // Field.Label, Field.Body and Control spread their raw props onto the
648
+ // element as well, so a helper prop would reach it as an attribute too.
649
+ 'field-label': {
650
+ status: 'mapped',
651
+ target: 'Field.Label',
652
+ tag: 'div',
653
+ textColor: null,
654
+ bgColor: null,
655
+ noHelpers: true,
656
+ modifiers: tokens('is-', ['small', 'normal', 'medium', 'large'], 'size'),
657
+ ownProps: ['size', 'textColor', 'color', 'bgColor'],
658
+ },
659
+ 'field-body': {
660
+ status: 'mapped',
661
+ target: 'Field.Body',
662
+ tag: 'div',
663
+ textColor: null,
664
+ bgColor: null,
665
+ noHelpers: true,
666
+ ownProps: ['textColor', 'color', 'bgColor'],
667
+ },
668
+ control: {
669
+ status: 'mapped',
670
+ target: 'Control',
671
+ tag: 'div',
672
+ as: ['div', 'p'],
673
+ textColor: null,
674
+ bgColor: null,
675
+ noHelpers: true,
676
+ modifiers: {
677
+ ...flags({
678
+ 'has-icons-left': 'hasIconsLeft',
679
+ 'has-icons-right': 'hasIconsRight',
680
+ 'is-loading': 'isLoading',
681
+ 'is-expanded': 'isExpanded',
682
+ }),
683
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
684
+ },
685
+ providesContext: true,
686
+ ownProps: [
687
+ 'as',
688
+ 'hasIconsLeft',
689
+ 'hasIconsRight',
690
+ 'isLoading',
691
+ 'isExpanded',
692
+ 'size',
693
+ 'textColor',
694
+ 'color',
695
+ 'bgColor',
696
+ 'iconLeft',
697
+ 'iconRight',
698
+ 'iconLeftName',
699
+ 'iconLeftSize',
700
+ 'iconRightName',
701
+ 'iconRightSize',
702
+ ],
703
+ passThrough: ['ref'],
704
+ },
705
+ input: {
706
+ ...BASE,
707
+ target: 'InputBase',
708
+ tag: 'input',
709
+ // No text color prop, and `backgroundColor` is the one the base reads.
710
+ textColor: null,
711
+ bgColor: 'backgroundColor',
712
+ modifiers: {
713
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
714
+ ...flags({
715
+ 'is-rounded': 'isRounded',
716
+ 'is-static': 'isStatic',
717
+ 'is-hovered': 'isHovered',
718
+ 'is-focused': 'isFocused',
719
+ 'is-loading': 'isLoading',
720
+ }),
721
+ },
722
+ omits: Object.fromEntries(COMPONENT_COLORS.map(color => [
723
+ `is-${color}`,
724
+ '`color` renders `has-text-<color>` on the input as well',
725
+ ])),
726
+ adoptsIdFrom: ['Field'],
727
+ ownProps: [
728
+ 'color',
729
+ 'size',
730
+ 'isRounded',
731
+ 'isStatic',
732
+ 'isHovered',
733
+ 'isFocused',
734
+ 'isLoading',
735
+ ],
736
+ passThrough: ['disabled', 'readOnly', 'ref'],
737
+ },
738
+ textarea: {
739
+ ...BASE,
740
+ target: 'TextAreaBase',
741
+ tag: 'textarea',
742
+ textColor: null,
743
+ bgColor: 'backgroundColor',
744
+ // `isLoading` renders nothing here: Bulma puts `is-loading` on the control.
745
+ modifiers: {
746
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
747
+ ...flags({
748
+ 'is-rounded': 'isRounded',
749
+ 'is-static': 'isStatic',
750
+ 'is-hovered': 'isHovered',
751
+ 'is-focused': 'isFocused',
752
+ 'is-active': 'isActive',
753
+ 'has-fixed-size': 'hasFixedSize',
754
+ }),
755
+ },
756
+ omits: Object.fromEntries(COMPONENT_COLORS.map(color => [
757
+ `is-${color}`,
758
+ '`color` renders `has-text-<color>` on the textarea as well',
759
+ ])),
760
+ adoptsIdFrom: ['Field'],
761
+ ownProps: [
762
+ 'color',
763
+ 'size',
764
+ 'isRounded',
765
+ 'isStatic',
766
+ 'isHovered',
767
+ 'isFocused',
768
+ 'isLoading',
769
+ 'isActive',
770
+ 'hasFixedSize',
771
+ ],
772
+ passThrough: ['disabled', 'readOnly', 'rows', 'ref'],
773
+ },
550
774
  footer: {
551
775
  ...BASE,
552
776
  target: 'Footer',
@@ -863,19 +1087,11 @@ export const ROOTS = {
863
1087
  },
864
1088
  // ---- Families bestax has but that do not map element by element yet ------
865
1089
  breadcrumb: todo('Breadcrumb', 'bestax `Breadcrumb` renders the `<ul>` itself and adds an `aria-label`'),
866
- cell: todo('Cell', 'this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
867
- grid: todo('Grid', 'this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
868
- 'fixed-grid': todo('Grid', 'this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
1090
+ 'fixed-grid': todo('Grid', '`Grid isFixed` renders the `.fixed-grid` wrapper itself, from `fixedCols`; replace the wrapper and its `.grid` with one `Grid`, by hand'),
869
1091
  checkbox: todo('Checkbox', "bestax `Checkbox` renders its own styled markup, not Bulma's"),
870
1092
  checkboxes: todo('Checkboxes', 'bestax `Checkboxes` renders its own `.field` and `.control` wrappers'),
871
1093
  radio: todo('Radio', "bestax `Radio` renders its own styled markup, not Bulma's"),
872
1094
  radios: todo('Radios', 'bestax `Radios` renders its own `.field` and `.control` wrappers'),
873
- field: todo('Field', 'bestax form controls render their own `.field` and `.control` wrappers; see the unmappables reference'),
874
- 'field-label': part(),
875
- 'field-body': part(),
876
- control: part(),
877
- input: todo('Input', 'bestax `Input` renders its own `.field` and `.control` wrappers'),
878
- textarea: todo('TextArea', 'bestax `TextArea` renders its own `.field` and `.control` wrappers'),
879
1095
  select: todo('Select', 'bestax `Select` renders the `.select` wrapper and the `<select>` together'),
880
1096
  file: todo('File', 'bestax `File` renders the whole `.file-label` tree itself'),
881
1097
  'file-label': part(),
@@ -957,6 +1173,8 @@ function plain(why) {
957
1173
  export const PRECEDENCE = [
958
1174
  'columns',
959
1175
  'column',
1176
+ 'grid',
1177
+ 'cell',
960
1178
  'container',
961
1179
  'section',
962
1180
  'hero',
@@ -989,6 +1207,12 @@ export const PRECEDENCE = [
989
1207
  'navbar-item',
990
1208
  'navbar-dropdown',
991
1209
  'navbar-divider',
1210
+ 'field',
1211
+ 'field-label',
1212
+ 'field-body',
1213
+ 'control',
1214
+ 'input',
1215
+ 'textarea',
992
1216
  'buttons',
993
1217
  'tags',
994
1218
  'button',
@@ -1009,6 +1233,9 @@ export const FORWARDS_REF = [
1009
1233
  'Link',
1010
1234
  'Navbar',
1011
1235
  'Navbar.Item',
1236
+ 'Control',
1237
+ 'InputBase',
1238
+ 'TextAreaBase',
1012
1239
  ];
1013
1240
  /**
1014
1241
  * Plain tags bestax wraps, for an element with helper classes and no root
@@ -1156,8 +1383,12 @@ export const PASSTHROUGH = [
1156
1383
  match: /-(?:touch|tablet-only|desktop-only|widescreen-only)$/,
1157
1384
  },
1158
1385
  {
1159
- why: 'Grid and Cell layout, which this source leaves as markup',
1160
- match: /^(?:is-(?:col|row)-.+|has-\d+-cols(?:-.+)?|is-(?:column|row)-gap-\d+|is-gap-\d+|is-auto-fill)$/,
1386
+ why: 'a Grid or Cell class, which converts only on its own `.grid` or `.cell`, and only where bestax has a prop for it',
1387
+ match: /^(?:is-(?:col|row)-.+|is-(?:column|row)-gap-\d+|is-gap-\d+|is-auto-fill)$/,
1388
+ },
1389
+ {
1390
+ why: 'a `.fixed-grid` column count, which stays with its `.fixed-grid` (a family this source leaves as markup)',
1391
+ match: /^has-\d+-cols(?:-.+)?$/,
1161
1392
  },
1162
1393
  {
1163
1394
  why: 'an `.image` modifier; `.image` stays as markup',
@@ -28,6 +28,15 @@ export interface ElementFacts {
28
28
  * counts: one in an expression may not render.
29
29
  */
30
30
  childTargets?: readonly string[];
31
+ /** The bestax components already in the file inside this element. */
32
+ bestaxInside?: readonly string[];
33
+ /** The bestax components already in the file around this element. */
34
+ bestaxAround?: readonly string[];
35
+ /**
36
+ * The other components around this element (not bestax, not a fragment),
37
+ * any of which could render a bestax component around it.
38
+ */
39
+ componentsAround?: readonly string[];
31
40
  /**
32
41
  * The component this element is the only child of, if any (`Link` for
33
42
  * `<Link href="/x"><a className="button">`), since that component can
@@ -48,7 +57,10 @@ export interface Conversion {
48
57
  className: string | null;
49
58
  /** Attributes to remove: defaults the target renders by itself. */
50
59
  drop: string[];
51
- /** Attributes whose numeric string value becomes a number. */
60
+ /**
61
+ * Attributes, and props written above, whose numeric string value becomes
62
+ * a number (`minCol={4}`), because the target types them as numbers.
63
+ */
52
64
  numbers: string[];
53
65
  }
54
66
  export interface Plan {
@@ -1 +1 @@
1
- {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,8DAA8D;IAC9D,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AA+BD,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAwQ9C"}
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/plan.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAiBH,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;OAGG;IACH,UAAU,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,WAAW,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,qEAAqE;IACrE,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;;;OAGG;IACH,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,IAAI;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,KAAK,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC;IACnD,4DAA4D;IAC5D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,mEAAmE;IACnE,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;OAGG;IACH,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,KAAK,EAAE,IAAI,EAAE,CAAC;CACf;AA+BD,wBAAgB,IAAI,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CA+R9C"}
@@ -128,8 +128,21 @@ export function plan(facts) {
128
128
  if (entry.requiresChildren && !facts.hasChildren) {
129
129
  return refuse('children', target, `bestax \`${target}\` requires children, and this element has none; keep it as markup`);
130
130
  }
131
+ if (entry.providesContext && facts.bestaxInside?.length) {
132
+ return refuse('context', target, `bestax \`${target}\` tells the bestax form controls inside it to skip wrappers of their own, and this element already holds \`${facts.bestaxInside[0]}\`, which could render differently inside it; keep this element as markup, or convert it and check that component by hand`);
133
+ }
134
+ if (entry.adoptsIdFrom && !facts.attributes.has('id')) {
135
+ // Context follows the render tree, not the file: a component of the app
136
+ // around the element can render a labelled `Field` around it just as well.
137
+ const around = facts.bestaxAround?.find(name => entry.adoptsIdFrom.includes(name)) ??
138
+ facts.componentsAround?.[0];
139
+ if (around) {
140
+ return refuse('context', target, `this element has no \`id\` and sits inside \`<${around}>\`, which is or could render a bestax \`${entry.adoptsIdFrom.join('` or `')}\` with a \`label\`; bestax \`${target}\` would then take that generated \`id\`; give the element an \`id\` of its own, then re-run`);
141
+ }
142
+ }
131
143
  const wraps = entry.wrapsChildren;
132
144
  if (wraps &&
145
+ (!wraps.when || tokens.includes(wraps.when)) &&
133
146
  (facts.hasChildren || wraps.whenEmpty) &&
134
147
  !facts.childTargets?.some(child => wraps.unless.includes(child))) {
135
148
  const parts = wraps.unless.map(part => `\`${part}\``);
@@ -170,6 +183,8 @@ export function plan(facts) {
170
183
  for (const write of modifier.writes) {
171
184
  writes.set(write.prop, write.value ?? true);
172
185
  sourceOf.set(write.prop, token);
186
+ if (write.numeric)
187
+ numbers.push(write.prop);
173
188
  }
174
189
  converted.add(token);
175
190
  continue;
@@ -1 +1 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,eAAO,MAAM,KAAK,EAAE,WAAW,CAAC,MAAM,CAYpC,CAAC;AAuBH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1D"}
1
+ {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAUH,eAAO,MAAM,KAAK,EAAE,WAAW,CAAC,MAAM,CAapC,CAAC;AAuBH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAK1D"}
@@ -14,6 +14,7 @@ import { HELPER_PROPS, LEGACY_09, ROOTS, WRAPPERS, WRAPPER_OWN_PROPS, } from './
14
14
  export const KINDS = new Set([
15
15
  'attr',
16
16
  'children',
17
+ 'context',
17
18
  'defaults',
18
19
  'drops',
19
20
  'dynamic-class',
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmSvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA2SpB"}
1
+ {"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../../src/sources/bulma-classes/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAW,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE1D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAmSvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,EACR,OAAO,GAAE,gBAAqB,GAC7B,MAAM,GAAG,SAAS,CA8VpB"}
@@ -308,22 +308,64 @@ export default function transform(fileInfo, api, options = {}) {
308
308
  // a child that is one of its parts.
309
309
  const planned = new Map();
310
310
  const programScope = root.find(j.Program).paths()[0]?.scope;
311
+ /**
312
+ * The bestax component an element already is, when its name is the bestax
313
+ * import and not a local that shadows it; `scopePath` is where the name is
314
+ * looked up.
315
+ */
316
+ const bestaxTarget = (element, scopePath) => {
317
+ const parts = jsxNameParts(element.openingElement.name);
318
+ const owner = parts && bestaxNames.get(parts[0]);
319
+ if (!owner || !resolvesToBinding(scopePath, parts[0], programScope)) {
320
+ return undefined;
321
+ }
322
+ return [...owner, ...parts.slice(1)].join('.');
323
+ };
311
324
  const childTargets = (elementPath) => (elementPath.node.children ?? []).flatMap((child) => {
312
325
  if (child.type !== 'JSXElement')
313
326
  return [];
314
- const target = planned.get(child)?.conversion?.target;
315
- if (target)
316
- return [target];
317
- // A part the file already uses counts when its name is the bestax
318
- // import, not a local that shadows it. A direct child is looked up in
319
- // the element's own scope, which is the child's.
320
- const parts = jsxNameParts(child.openingElement.name);
321
- const owner = parts && bestaxNames.get(parts[0]);
322
- if (!owner || !resolvesToBinding(elementPath, parts[0], programScope)) {
323
- return [];
327
+ const target = planned.get(child)?.conversion?.target ??
328
+ // A direct child is looked up in the element's own scope, the child's.
329
+ bestaxTarget(child, elementPath);
330
+ return target ? [target] : [];
331
+ });
332
+ // For each element, the bestax components already in the file inside it:
333
+ // `Field` and `Control` change how bestax's form controls render.
334
+ const bestaxInside = new Map();
335
+ root.find(j.JSXElement).forEach(elementPath => {
336
+ const target = bestaxTarget(elementPath.node, elementPath);
337
+ if (!target)
338
+ return;
339
+ for (let up = elementPath.parent; up; up = up.parent) {
340
+ if (up.node?.type !== 'JSXElement')
341
+ continue;
342
+ bestaxInside.set(up.node, [...(bestaxInside.get(up.node) ?? []), target]);
324
343
  }
325
- return [[...owner, ...parts.slice(1)].join('.')];
326
344
  });
345
+ /**
346
+ * The components around an element: the bestax ones already in the file,
347
+ * and the rest (not an HTML tag, not a fragment), which could render one.
348
+ */
349
+ const around = (elementPath) => {
350
+ const bestax = [];
351
+ const other = [];
352
+ for (let up = elementPath.parent; up; up = up.parent) {
353
+ if (up.node?.type !== 'JSXElement')
354
+ continue;
355
+ const target = bestaxTarget(up.node, up);
356
+ if (target) {
357
+ bestax.push(target);
358
+ continue;
359
+ }
360
+ const parts = jsxNameParts(up.node.openingElement.name);
361
+ const name = parts?.join('.');
362
+ if (name && !INTRINSIC.test(name) && !name.includes('-')) {
363
+ if (!PASS_THROUGH_PARENTS.has(name))
364
+ other.push(name);
365
+ }
366
+ }
367
+ return { bestax, other };
368
+ };
327
369
  // `converts` is whether the element would become a component with its
328
370
  // classes written out, so it holds for a computed className too.
329
371
  const elements = [];
@@ -346,6 +388,7 @@ export default function transform(fileInfo, api, options = {}) {
346
388
  attributes.set(attributeName(attr), attributeValue(attr));
347
389
  }
348
390
  const className = staticClassName(classAttr);
391
+ const surrounding = around(elementPath);
349
392
  const facts = {
350
393
  tag: name.name,
351
394
  tokens: className === null
@@ -356,6 +399,9 @@ export default function transform(fileInfo, api, options = {}) {
356
399
  hasRef: attributes.has('ref'),
357
400
  hasChildren: (element.children ?? []).some(reachesReact),
358
401
  childTargets: childTargets(elementPath),
402
+ bestaxInside: bestaxInside.get(element) ?? [],
403
+ bestaxAround: surrounding.bestax,
404
+ componentsAround: surrounding.other,
359
405
  onlyChildOf: onlyChildOf(elementPath, bestaxLocals),
360
406
  };
361
407
  let result = plan(facts);
@@ -446,10 +492,6 @@ export default function transform(fileInfo, api, options = {}) {
446
492
  for (const name of conversion.drop) {
447
493
  attrs.splice(attrs.indexOf(findAttr(element, name)), 1);
448
494
  }
449
- for (const name of conversion.numbers) {
450
- const attr = findAttr(element, name);
451
- attr.value = j.jsxExpressionContainer(j.numericLiteral(Number(attributeValue(attr))));
452
- }
453
495
  const classAttr = findAttr(element, 'className');
454
496
  const replacement = conversion.props.map(([name, value]) => makeAttr(j, name, value === true ? undefined : value));
455
497
  if (conversion.className) {
@@ -480,6 +522,12 @@ export default function transform(fileInfo, api, options = {}) {
480
522
  ];
481
523
  }
482
524
  attrs.splice(attrs.indexOf(classAttr), 1, ...replacement);
525
+ // After the splice, so a prop the conversion wrote is found as well as
526
+ // an attribute the element already had.
527
+ for (const name of conversion.numbers) {
528
+ const attr = findAttr(element, name);
529
+ attr.value = j.jsxExpressionContainer(j.numericLiteral(Number(attributeValue(attr))));
530
+ }
483
531
  ctx.dirty = true;
484
532
  }
485
533
  // ---- 5. The bestax import ---------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bestax-migrate",
3
- "version": "2.6.0",
3
+ "version": "2.8.0",
4
4
  "description": "Codemods for migrating existing React apps from other Bulma libraries to @allxsmith/bestax-bulma",
5
5
  "type": "module",
6
6
  "bin": {