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.
Files changed (72) hide show
  1. package/README.md +21 -17
  2. package/dist/cli.d.ts +3 -0
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +45 -11
  5. package/dist/sources/_shared/bestax-import.d.ts +48 -0
  6. package/dist/sources/_shared/bestax-import.d.ts.map +1 -0
  7. package/dist/sources/_shared/bestax-import.js +142 -0
  8. package/dist/sources/_shared/css-imports.d.ts +33 -0
  9. package/dist/sources/_shared/css-imports.d.ts.map +1 -0
  10. package/dist/sources/_shared/css-imports.js +103 -0
  11. package/dist/sources/_shared/deps-common.d.ts +51 -0
  12. package/dist/sources/_shared/deps-common.d.ts.map +1 -0
  13. package/dist/sources/_shared/deps-common.js +115 -0
  14. package/dist/sources/_shared/jsx-utils.d.ts +28 -0
  15. package/dist/sources/_shared/jsx-utils.d.ts.map +1 -1
  16. package/dist/sources/_shared/jsx-utils.js +59 -1
  17. package/dist/sources/_shared/make-styles-transform.d.ts +6 -2
  18. package/dist/sources/_shared/make-styles-transform.d.ts.map +1 -1
  19. package/dist/sources/_shared/make-styles-transform.js +12 -4
  20. package/dist/sources/_shared/props.d.ts.map +1 -1
  21. package/dist/sources/_shared/props.js +2 -2
  22. package/dist/sources/_shared/specials-utils.d.ts +1 -1
  23. package/dist/sources/_shared/specials-utils.d.ts.map +1 -1
  24. package/dist/sources/_shared/specials-utils.js +19 -1
  25. package/dist/sources/bloomer/deps.d.ts.map +1 -1
  26. package/dist/sources/bloomer/deps.js +14 -89
  27. package/dist/sources/bloomer/transform.d.ts.map +1 -1
  28. package/dist/sources/bloomer/transform.js +12 -186
  29. package/dist/sources/bulma-classes/class-map.d.ts +161 -0
  30. package/dist/sources/bulma-classes/class-map.d.ts.map +1 -0
  31. package/dist/sources/bulma-classes/class-map.js +1046 -0
  32. package/dist/sources/bulma-classes/deps.d.ts +14 -0
  33. package/dist/sources/bulma-classes/deps.d.ts.map +1 -0
  34. package/dist/sources/bulma-classes/deps.js +56 -0
  35. package/dist/sources/bulma-classes/index.d.ts +3 -0
  36. package/dist/sources/bulma-classes/index.d.ts.map +1 -0
  37. package/dist/sources/bulma-classes/index.js +35 -0
  38. package/dist/sources/bulma-classes/plan.d.ts +53 -0
  39. package/dist/sources/bulma-classes/plan.d.ts.map +1 -0
  40. package/dist/sources/bulma-classes/plan.js +231 -0
  41. package/dist/sources/bulma-classes/project.d.ts +40 -0
  42. package/dist/sources/bulma-classes/project.d.ts.map +1 -0
  43. package/dist/sources/bulma-classes/project.js +203 -0
  44. package/dist/sources/bulma-classes/rules.d.ts +16 -0
  45. package/dist/sources/bulma-classes/rules.d.ts.map +1 -0
  46. package/dist/sources/bulma-classes/rules.js +53 -0
  47. package/dist/sources/bulma-classes/styles.d.ts +13 -0
  48. package/dist/sources/bulma-classes/styles.d.ts.map +1 -0
  49. package/dist/sources/bulma-classes/styles.js +18 -0
  50. package/dist/sources/bulma-classes/transform.d.ts +21 -0
  51. package/dist/sources/bulma-classes/transform.d.ts.map +1 -0
  52. package/dist/sources/bulma-classes/transform.js +486 -0
  53. package/dist/sources/rbx/deps.d.ts.map +1 -1
  54. package/dist/sources/rbx/deps.js +29 -117
  55. package/dist/sources/rbx/mapping.d.ts.map +1 -1
  56. package/dist/sources/rbx/mapping.js +9 -1
  57. package/dist/sources/rbx/specials.d.ts.map +1 -1
  58. package/dist/sources/rbx/specials.js +20 -10
  59. package/dist/sources/rbx/transform.d.ts.map +1 -1
  60. package/dist/sources/rbx/transform.js +22 -204
  61. package/dist/sources/react-bulma-components/deps.d.ts.map +1 -1
  62. package/dist/sources/react-bulma-components/deps.js +12 -87
  63. package/dist/sources/react-bulma-components/mapping.js +1 -1
  64. package/dist/sources/react-bulma-components/specials.d.ts.map +1 -1
  65. package/dist/sources/react-bulma-components/specials.js +42 -4
  66. package/dist/sources/react-bulma-components/transform.d.ts.map +1 -1
  67. package/dist/sources/react-bulma-components/transform.js +16 -187
  68. package/dist/sources/registry.d.ts.map +1 -1
  69. package/dist/sources/registry.js +2 -0
  70. package/dist/types.d.ts +25 -0
  71. package/dist/types.d.ts.map +1 -1
  72. package/package.json +4 -3
@@ -0,0 +1,1046 @@
1
+ /**
2
+ * The bulma-classes table: for a Bulma class on a plain JSX element, which
3
+ * bestax component renders that element, and which prop renders each of its
4
+ * other classes.
5
+ *
6
+ * Every conversion this table allows must render exactly the HTML the raw
7
+ * element rendered. That is a claim about bestax, and the render tests hold
8
+ * it: each root, modifier and helper here is rendered through the built
9
+ * library and compared with the raw markup it replaces.
10
+ *
11
+ * Data only, and written so a generator in another package can import it
12
+ * directly: nothing Node cannot strip, so no enums, no namespaces, type
13
+ * imports only.
14
+ */
15
+ export function inTagSet(set, tag) {
16
+ return 'on' in set ? set.on.includes(tag) : !set.except.includes(tag);
17
+ }
18
+ // ---- Value vocabularies (held to @allxsmith/bestax-bulma/constants) --------
19
+ export const COLORS = [
20
+ 'primary',
21
+ 'link',
22
+ 'info',
23
+ 'success',
24
+ 'warning',
25
+ 'danger',
26
+ 'black',
27
+ 'black-bis',
28
+ 'black-ter',
29
+ 'grey-darker',
30
+ 'grey-dark',
31
+ 'grey',
32
+ 'grey-light',
33
+ 'grey-lighter',
34
+ 'white',
35
+ 'white-bis',
36
+ 'white-ter',
37
+ 'light',
38
+ 'dark',
39
+ ];
40
+ export const SIZES = ['0', '1', '2', '3', '4', '5', '6', 'auto'];
41
+ export const TEXT_SIZES = ['1', '2', '3', '4', '5', '6', '7'];
42
+ export const ALIGNMENTS = ['centered', 'justified', 'left', 'right'];
43
+ export const TEXT_TRANSFORMS = [
44
+ 'capitalized',
45
+ 'lowercase',
46
+ 'uppercase',
47
+ 'italic',
48
+ ];
49
+ export const TEXT_WEIGHTS = [
50
+ 'light',
51
+ 'normal',
52
+ 'medium',
53
+ 'semibold',
54
+ 'bold',
55
+ ];
56
+ export const FONT_FAMILIES = [
57
+ 'sans-serif',
58
+ 'monospace',
59
+ 'primary',
60
+ 'secondary',
61
+ 'code',
62
+ ];
63
+ export const DISPLAYS = [
64
+ 'block',
65
+ 'flex',
66
+ 'inline',
67
+ 'inline-block',
68
+ 'inline-flex',
69
+ 'grid',
70
+ ];
71
+ export const FLEX_DIRECTIONS = [
72
+ 'row',
73
+ 'row-reverse',
74
+ 'column',
75
+ 'column-reverse',
76
+ ];
77
+ export const FLEX_WRAPS = ['nowrap', 'wrap', 'wrap-reverse'];
78
+ export const JUSTIFY_CONTENTS = [
79
+ 'flex-start',
80
+ 'flex-end',
81
+ 'center',
82
+ 'space-between',
83
+ 'space-around',
84
+ 'space-evenly',
85
+ 'start',
86
+ 'end',
87
+ 'left',
88
+ 'right',
89
+ ];
90
+ export const ALIGN_CONTENTS = [
91
+ 'flex-start',
92
+ 'flex-end',
93
+ 'center',
94
+ 'space-between',
95
+ 'space-around',
96
+ 'space-evenly',
97
+ 'stretch',
98
+ ];
99
+ export const ALIGN_ITEMS = [
100
+ 'stretch',
101
+ 'flex-start',
102
+ 'flex-end',
103
+ 'center',
104
+ 'baseline',
105
+ 'start',
106
+ 'end',
107
+ ];
108
+ export const ALIGN_SELFS = [
109
+ 'auto',
110
+ 'flex-start',
111
+ 'flex-end',
112
+ 'center',
113
+ 'baseline',
114
+ 'stretch',
115
+ ];
116
+ export const FLEX_GROW_SHRINK = ['0', '1', '2', '3', '4', '5'];
117
+ export const VIEWPORTS = [
118
+ 'mobile',
119
+ 'tablet',
120
+ 'tablet-only',
121
+ 'touch',
122
+ 'desktop',
123
+ 'desktop-only',
124
+ 'widescreen',
125
+ 'widescreen-only',
126
+ 'fullhd',
127
+ ];
128
+ /** The viewports bestax's per-breakpoint size and alignment props cover. */
129
+ const SIZE_VIEWPORTS = [
130
+ 'mobile',
131
+ 'tablet',
132
+ 'desktop',
133
+ 'widescreen',
134
+ 'fullhd',
135
+ ];
136
+ /** Colors Bulma styles on a component (`.button.is-primary`), not just text. */
137
+ const COMPONENT_COLORS = [
138
+ 'primary',
139
+ 'link',
140
+ 'info',
141
+ 'success',
142
+ 'warning',
143
+ 'danger',
144
+ 'black',
145
+ 'white',
146
+ 'light',
147
+ 'dark',
148
+ ];
149
+ const COLUMN_SIZES = [
150
+ '1',
151
+ '2',
152
+ '3',
153
+ '4',
154
+ '5',
155
+ '6',
156
+ '7',
157
+ '8',
158
+ '9',
159
+ '10',
160
+ '11',
161
+ '12',
162
+ 'full',
163
+ 'half',
164
+ 'one-third',
165
+ 'two-thirds',
166
+ 'one-quarter',
167
+ 'three-quarters',
168
+ 'one-fifth',
169
+ 'two-fifths',
170
+ 'three-fifths',
171
+ 'four-fifths',
172
+ ];
173
+ const OFFSETS = COLUMN_SIZES.filter(size => size !== 'full');
174
+ /** `tablet-only` → `TabletOnly`: the suffix bestax puts on per-viewport props. */
175
+ export function viewportSuffix(viewport) {
176
+ return viewport
177
+ .split('-')
178
+ .map(part => part[0].toUpperCase() + part.slice(1))
179
+ .join('');
180
+ }
181
+ // ---- Builders ---------------------------------------------------------------
182
+ const flag = (prop) => ({ writes: [{ prop }] });
183
+ const set = (prop, value) => ({
184
+ writes: [{ prop, value }],
185
+ });
186
+ /** `prefix + value + suffix` → `prop = value`, for each value. */
187
+ function tokens(prefix, values, prop, suffix = '') {
188
+ return Object.fromEntries(values.map(value => [`${prefix}${value}${suffix}`, set(prop, value)]));
189
+ }
190
+ /** The same, once per viewport: `is-6-mobile` → `sizeMobile="6"`. */
191
+ function perViewport(prefix, values, prop, viewports) {
192
+ return Object.assign({}, ...viewports.map(viewport => tokens(prefix, values, `${prop}${viewportSuffix(viewport)}`, `-${viewport}`)));
193
+ }
194
+ function flags(map) {
195
+ return Object.fromEntries(Object.entries(map).map(([token, prop]) => [token, flag(prop)]));
196
+ }
197
+ const BASE = {
198
+ status: 'mapped',
199
+ textColor: 'textColor',
200
+ bgColor: 'bgColor',
201
+ };
202
+ // ---- Roots ------------------------------------------------------------------
203
+ export const ROOTS = {
204
+ block: {
205
+ ...BASE,
206
+ target: 'Block',
207
+ tag: 'div',
208
+ ownProps: ['textColor', 'color', 'bgColor'],
209
+ },
210
+ box: {
211
+ ...BASE,
212
+ target: 'Box',
213
+ tag: 'div',
214
+ ownProps: ['textColor', 'color', 'bgColor', 'hasShadow'],
215
+ },
216
+ button: {
217
+ ...BASE,
218
+ target: 'Button',
219
+ tag: 'button',
220
+ as: 'any',
221
+ modifiers: {
222
+ ...tokens('is-', [
223
+ 'primary',
224
+ 'link',
225
+ 'info',
226
+ 'success',
227
+ 'warning',
228
+ 'danger',
229
+ 'white',
230
+ 'dark',
231
+ 'black',
232
+ 'text',
233
+ 'ghost',
234
+ ], 'color'),
235
+ ...tokens('is-', ['small', 'normal', 'medium', 'large'], 'size'),
236
+ // `color="light"` renders no class on a Button; `isLight` renders it.
237
+ ...flags({
238
+ 'is-light': 'isLight',
239
+ 'is-rounded': 'isRounded',
240
+ 'is-loading': 'isLoading',
241
+ 'is-static': 'isStatic',
242
+ 'is-fullwidth': 'isFullwidth',
243
+ 'is-outlined': 'isOutlined',
244
+ 'is-inverted': 'isInverted',
245
+ 'is-focused': 'isFocused',
246
+ 'is-active': 'isActive',
247
+ 'is-hovered': 'isHovered',
248
+ }),
249
+ // No `is-disabled`: `isDisabled` writes attributes as well as the class.
250
+ },
251
+ dropsAttr: {
252
+ // Kept only on the elements `disabled` means something on.
253
+ disabled: {
254
+ except: [
255
+ 'button',
256
+ 'fieldset',
257
+ 'input',
258
+ 'optgroup',
259
+ 'option',
260
+ 'select',
261
+ 'textarea',
262
+ ],
263
+ },
264
+ // The link attributes render only on the anchor path, which is every
265
+ // tag but a <button>.
266
+ href: { on: ['button'] },
267
+ target: { on: ['button'] },
268
+ rel: { on: ['button'] },
269
+ // The submit overrides are withheld from an <a>.
270
+ ...Object.fromEntries([
271
+ 'formAction',
272
+ 'formEncType',
273
+ 'formMethod',
274
+ 'formNoValidate',
275
+ 'formTarget',
276
+ ].map(name => [name, { on: ['a'] }])),
277
+ },
278
+ ownProps: [
279
+ 'as',
280
+ 'color',
281
+ 'size',
282
+ 'isLight',
283
+ 'isRounded',
284
+ 'isLoading',
285
+ 'isStatic',
286
+ 'isFullwidth',
287
+ 'isFullWidth',
288
+ 'isOutlined',
289
+ 'isInverted',
290
+ 'isFocused',
291
+ 'isActive',
292
+ 'isHovered',
293
+ 'isDisabled',
294
+ 'textColor',
295
+ 'bgColor',
296
+ ],
297
+ },
298
+ buttons: {
299
+ ...BASE,
300
+ target: 'Buttons',
301
+ tag: 'div',
302
+ requiresChildren: true,
303
+ modifiers: {
304
+ ...flags({
305
+ 'is-centered': 'isCentered',
306
+ 'is-right': 'isRight',
307
+ 'has-addons': 'hasAddons',
308
+ }),
309
+ ...tokens('are-', ['small', 'medium', 'large'], 'size'),
310
+ },
311
+ ownProps: [
312
+ 'textColor',
313
+ 'color',
314
+ 'bgColor',
315
+ 'isCentered',
316
+ 'isRight',
317
+ 'hasAddons',
318
+ 'size',
319
+ ],
320
+ },
321
+ columns: {
322
+ ...BASE,
323
+ target: 'Columns',
324
+ tag: 'div',
325
+ modifiers: {
326
+ ...flags({
327
+ 'is-centered': 'isCentered',
328
+ 'is-gapless': 'isGapless',
329
+ 'is-multiline': 'isMultiline',
330
+ 'is-vcentered': 'isVCentered',
331
+ 'is-mobile': 'isMobile',
332
+ 'is-desktop': 'isDesktop',
333
+ }),
334
+ ...tokens('is-', ['0', '1', '2', '3', '4', '5', '6', '7', '8'], 'gap'),
335
+ ...perViewport('is-', ['0', '1', '2', '3', '4', '5', '6', '7', '8'], 'gap', SIZE_VIEWPORTS),
336
+ },
337
+ ownProps: [
338
+ 'textColor',
339
+ 'color',
340
+ 'bgColor',
341
+ 'isCentered',
342
+ 'isGapless',
343
+ 'isMultiline',
344
+ 'isVCentered',
345
+ 'isMobile',
346
+ 'isDesktop',
347
+ 'gap',
348
+ 'gapMobile',
349
+ 'gapTablet',
350
+ 'gapDesktop',
351
+ 'gapWidescreen',
352
+ 'gapFullhd',
353
+ 'gapSize',
354
+ 'gapSizeMobile',
355
+ 'gapSizeTablet',
356
+ 'gapSizeDesktop',
357
+ 'gapSizeWidescreen',
358
+ 'gapSizeFullhd',
359
+ ],
360
+ },
361
+ column: {
362
+ ...BASE,
363
+ target: 'Column',
364
+ tag: 'div',
365
+ modifiers: {
366
+ ...tokens('is-', COLUMN_SIZES, 'size'),
367
+ ...perViewport('is-', COLUMN_SIZES, 'size', SIZE_VIEWPORTS),
368
+ // No `full`: Bulma has no full-width offset.
369
+ ...tokens('is-offset-', OFFSETS, 'offset'),
370
+ ...perViewport('is-offset-', OFFSETS, 'offset', SIZE_VIEWPORTS),
371
+ 'is-narrow': flag('isNarrow'),
372
+ ...Object.fromEntries([...SIZE_VIEWPORTS, 'touch'].map(viewport => [
373
+ `is-narrow-${viewport}`,
374
+ flag(`isNarrow${viewportSuffix(viewport)}`),
375
+ ])),
376
+ },
377
+ ownProps: [
378
+ 'textColor',
379
+ 'color',
380
+ 'bgColor',
381
+ 'size',
382
+ 'sizeMobile',
383
+ 'sizeTablet',
384
+ 'sizeDesktop',
385
+ 'sizeWidescreen',
386
+ 'sizeFullhd',
387
+ 'offset',
388
+ 'offsetMobile',
389
+ 'offsetTablet',
390
+ 'offsetDesktop',
391
+ 'offsetWidescreen',
392
+ 'offsetFullhd',
393
+ 'isNarrow',
394
+ 'isNarrowMobile',
395
+ 'isNarrowTablet',
396
+ 'isNarrowTouch',
397
+ 'isNarrowDesktop',
398
+ 'isNarrowWidescreen',
399
+ 'isNarrowFullhd',
400
+ ],
401
+ },
402
+ container: {
403
+ ...BASE,
404
+ target: 'Container',
405
+ tag: 'div',
406
+ modifiers: {
407
+ ...flags({
408
+ 'is-fluid': 'fluid',
409
+ 'is-widescreen': 'widescreen',
410
+ 'is-fullhd': 'fullhd',
411
+ }),
412
+ ...Object.fromEntries(['tablet', 'desktop', 'widescreen'].map(breakpoint => [
413
+ `is-max-${breakpoint}`,
414
+ {
415
+ writes: [
416
+ { prop: 'breakpoint', value: breakpoint },
417
+ { prop: 'isMax' },
418
+ ],
419
+ },
420
+ ])),
421
+ },
422
+ ownProps: [
423
+ 'textColor',
424
+ 'color',
425
+ 'bgColor',
426
+ 'fluid',
427
+ 'widescreen',
428
+ 'fullhd',
429
+ 'breakpoint',
430
+ 'isMax',
431
+ ],
432
+ },
433
+ content: {
434
+ ...BASE,
435
+ target: 'Content',
436
+ tag: 'div',
437
+ modifiers: tokens('is-', ['small', 'medium', 'large'], 'size'),
438
+ ownProps: ['textColor', 'color', 'bgColor', 'size'],
439
+ },
440
+ delete: {
441
+ ...BASE,
442
+ target: 'Delete',
443
+ tag: 'button',
444
+ modifiers: tokens('is-', ['small', 'medium', 'large'], 'size'),
445
+ defaults: { type: 'button', 'aria-label': 'Close' },
446
+ // DeleteProps takes a <button>'s global attributes, not its form ones.
447
+ untypedAttrs: [
448
+ 'type',
449
+ 'name',
450
+ 'value',
451
+ 'form',
452
+ 'formAction',
453
+ 'formEncType',
454
+ 'formMethod',
455
+ 'formNoValidate',
456
+ 'formTarget',
457
+ ],
458
+ ownProps: [
459
+ 'textColor',
460
+ 'color',
461
+ 'bgColor',
462
+ 'size',
463
+ 'ariaLabel',
464
+ 'disabled',
465
+ ],
466
+ passThrough: ['onClick'],
467
+ },
468
+ footer: {
469
+ ...BASE,
470
+ target: 'Footer',
471
+ tag: 'footer',
472
+ as: ['footer', 'div'],
473
+ ownProps: ['as', 'color', 'bgColor', 'textColor'],
474
+ },
475
+ hero: {
476
+ ...BASE,
477
+ target: 'Hero',
478
+ tag: 'section',
479
+ // Hero's `color` is the component color, and `textColor` reaches the DOM
480
+ // as an attribute rather than a class.
481
+ textColor: null,
482
+ modifiers: {
483
+ ...tokens('is-', COMPONENT_COLORS, 'color'),
484
+ ...tokens('is-', ['small', 'medium', 'large', 'fullheight', 'fullheight-with-navbar'], 'size'),
485
+ },
486
+ ownProps: ['color', 'size', 'bgColor', 'fullheightWithNavbar'],
487
+ },
488
+ 'hero-head': {
489
+ ...BASE,
490
+ target: 'Hero.Head',
491
+ tag: 'div',
492
+ ownProps: ['color', 'bgColor', 'textColor'],
493
+ },
494
+ 'hero-body': {
495
+ ...BASE,
496
+ target: 'Hero.Body',
497
+ tag: 'div',
498
+ ownProps: ['color', 'bgColor', 'textColor'],
499
+ },
500
+ 'hero-foot': {
501
+ ...BASE,
502
+ target: 'Hero.Foot',
503
+ tag: 'div',
504
+ ownProps: ['color', 'bgColor', 'textColor'],
505
+ },
506
+ level: {
507
+ ...BASE,
508
+ target: 'Level',
509
+ tag: 'nav',
510
+ modifiers: flags({ 'is-mobile': 'isMobile' }),
511
+ ownProps: ['isMobile', 'color', 'bgColor', 'textColor'],
512
+ },
513
+ 'level-left': {
514
+ ...BASE,
515
+ target: 'Level.Left',
516
+ tag: 'div',
517
+ ownProps: ['color', 'bgColor', 'textColor'],
518
+ },
519
+ 'level-right': {
520
+ ...BASE,
521
+ target: 'Level.Right',
522
+ tag: 'div',
523
+ ownProps: ['color', 'bgColor', 'textColor'],
524
+ },
525
+ 'level-item': {
526
+ ...BASE,
527
+ target: 'Level.Item',
528
+ tag: 'div',
529
+ as: ['div', 'p', 'a'],
530
+ // The anchor attributes, and `rel`, reach only an <a>
531
+ // (`STRIP_FROM_NON_ANCHOR` in bulma-ui's Level.tsx).
532
+ dropsAttr: Object.fromEntries([
533
+ 'href',
534
+ 'target',
535
+ 'download',
536
+ 'hrefLang',
537
+ 'ping',
538
+ 'referrerPolicy',
539
+ 'media',
540
+ 'type',
541
+ 'rel',
542
+ ].map(name => [name, { except: ['a'] }])),
543
+ ownProps: ['as', 'hasTextCentered', 'color', 'bgColor', 'textColor'],
544
+ },
545
+ media: {
546
+ ...BASE,
547
+ target: 'Media',
548
+ tag: 'article',
549
+ as: ['article', 'div'],
550
+ ownProps: ['as', 'color', 'bgColor', 'textColor'],
551
+ },
552
+ 'media-left': {
553
+ ...BASE,
554
+ target: 'Media.Left',
555
+ tag: 'figure',
556
+ as: ['figure', 'div'],
557
+ ownProps: ['as', 'color', 'bgColor', 'textColor'],
558
+ },
559
+ 'media-content': {
560
+ ...BASE,
561
+ target: 'Media.Content',
562
+ tag: 'div',
563
+ ownProps: ['color', 'bgColor', 'textColor'],
564
+ },
565
+ 'media-right': {
566
+ ...BASE,
567
+ target: 'Media.Right',
568
+ tag: 'div',
569
+ ownProps: ['color', 'bgColor', 'textColor'],
570
+ },
571
+ notification: {
572
+ ...BASE,
573
+ target: 'Notification',
574
+ tag: 'div',
575
+ // `bgColor` reaches the DOM as an attribute, and `backgroundColor`
576
+ // renders but is not in its props type.
577
+ bgColor: null,
578
+ modifiers: {
579
+ ...tokens('is-', COMPONENT_COLORS.filter(color => color !== 'light'), 'color'),
580
+ ...flags({ 'is-light': 'isLight' }),
581
+ },
582
+ ownProps: ['color', 'textColor', 'isLight', 'hasDelete', 'onDelete'],
583
+ },
584
+ progress: {
585
+ ...BASE,
586
+ target: 'Progress',
587
+ tag: 'progress',
588
+ textColor: null,
589
+ bgColor: null,
590
+ numberAttrs: ['value', 'max'],
591
+ modifiers: {
592
+ ...tokens('is-', COMPONENT_COLORS, 'color'),
593
+ ...tokens('is-', ['small', 'medium', 'large'], 'size'),
594
+ },
595
+ ownProps: ['color', 'size'],
596
+ passThrough: ['value', 'max'],
597
+ },
598
+ section: {
599
+ ...BASE,
600
+ target: 'Section',
601
+ tag: 'section',
602
+ modifiers: tokens('is-', ['medium', 'large'], 'size'),
603
+ ownProps: ['color', 'bgColor', 'textColor', 'size'],
604
+ },
605
+ subtitle: {
606
+ ...BASE,
607
+ target: 'SubTitle',
608
+ tag: 'h1',
609
+ as: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'],
610
+ sizeDrivesTag: true,
611
+ modifiers: {
612
+ ...Object.fromEntries(['1', '2', '3', '4', '5', '6'].map(n => [
613
+ `is-${n}`,
614
+ { writes: [{ prop: 'size', value: n }], tagIn: [`h${n}`, 'p'] },
615
+ ])),
616
+ ...flags({ 'has-skeleton': 'hasSkeleton' }),
617
+ },
618
+ ownProps: ['size', 'as', 'hasSkeleton', 'textColor', 'bgColor'],
619
+ },
620
+ table: {
621
+ ...BASE,
622
+ target: 'Table',
623
+ tag: 'table',
624
+ // Table's text color is its `color` prop; `textColor` and `bgColor`
625
+ // reach the DOM as attributes, and `backgroundColor` does not typecheck.
626
+ textColor: 'color',
627
+ bgColor: null,
628
+ modifiers: flags({
629
+ 'is-bordered': 'isBordered',
630
+ 'is-striped': 'isStriped',
631
+ 'is-narrow': 'isNarrow',
632
+ 'is-hoverable': 'isHoverable',
633
+ 'is-fullwidth': 'isFullwidth',
634
+ }),
635
+ ownProps: [
636
+ 'isBordered',
637
+ 'isStriped',
638
+ 'isNarrow',
639
+ 'isHoverable',
640
+ 'isFullwidth',
641
+ 'isFullWidth',
642
+ 'isResponsive',
643
+ ],
644
+ },
645
+ tag: {
646
+ ...BASE,
647
+ target: 'Tag',
648
+ tag: 'span',
649
+ textColor: null,
650
+ bgColor: 'backgroundColor',
651
+ modifiers: {
652
+ ...tokens('is-', COMPONENT_COLORS.filter(color => color !== 'light'), 'color'),
653
+ ...tokens('is-', ['medium', 'large'], 'size'),
654
+ ...flags({
655
+ 'is-light': 'isLight',
656
+ 'is-rounded': 'isRounded',
657
+ 'is-hoverable': 'isHoverable',
658
+ }),
659
+ // No `is-delete`: `isDelete` turns the tag into a <button>.
660
+ },
661
+ ownProps: [
662
+ 'color',
663
+ 'size',
664
+ 'isLight',
665
+ 'isRounded',
666
+ 'isDelete',
667
+ 'isHoverable',
668
+ 'onDelete',
669
+ ],
670
+ },
671
+ tags: {
672
+ ...BASE,
673
+ target: 'Tags',
674
+ tag: 'div',
675
+ // Tags types no color prop at all: `textColor` and `bgColor` reach the DOM
676
+ // as attributes, and the raw helper names render but do not typecheck.
677
+ textColor: null,
678
+ bgColor: null,
679
+ modifiers: {
680
+ ...flags({ 'has-addons': 'hasAddons' }),
681
+ ...tokens('are-', ['medium', 'large'], 'size'),
682
+ },
683
+ ownProps: ['hasAddons', 'isMultiline', 'size'],
684
+ },
685
+ title: {
686
+ ...BASE,
687
+ target: 'Title',
688
+ tag: 'h1',
689
+ as: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'p'],
690
+ sizeDrivesTag: true,
691
+ modifiers: {
692
+ ...Object.fromEntries(['1', '2', '3', '4', '5', '6'].map(n => [
693
+ `is-${n}`,
694
+ { writes: [{ prop: 'size', value: n }], tagIn: [`h${n}`, 'p'] },
695
+ ])),
696
+ ...flags({ 'is-spaced': 'isSpaced', 'has-skeleton': 'hasSkeleton' }),
697
+ },
698
+ ownProps: ['size', 'isSpaced', 'as', 'hasSkeleton', 'textColor', 'bgColor'],
699
+ },
700
+ // ---- Families bestax has but that do not map element by element yet ------
701
+ breadcrumb: todo('bestax `Breadcrumb` renders the `<ul>` itself and adds an `aria-label`'),
702
+ card: todo('bestax `Card` wraps any child that is not one of its parts in `.card-content`, so convert the card and its parts together, by hand'),
703
+ 'card-header': part(),
704
+ 'card-header-title': part(),
705
+ 'card-header-icon': part(),
706
+ 'card-image': part(),
707
+ 'card-content': part(),
708
+ 'card-footer': part(),
709
+ 'card-footer-item': part(),
710
+ cell: todo('this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
711
+ grid: todo('this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
712
+ 'fixed-grid': todo('this source leaves Grid markup as written; convert it to bestax `Grid` and `Cell` by hand (`Grid isFixed` renders the `.fixed-grid` wrapper itself)'),
713
+ checkbox: todo("bestax `Checkbox` renders its own styled markup, not Bulma's"),
714
+ checkboxes: todo('bestax `Checkboxes` renders its own `.field` and `.control` wrappers'),
715
+ radio: todo("bestax `Radio` renders its own styled markup, not Bulma's"),
716
+ radios: todo('bestax `Radios` renders its own `.field` and `.control` wrappers'),
717
+ field: todo('bestax form controls render their own `.field` and `.control` wrappers; see the unmappables reference'),
718
+ 'field-label': part(),
719
+ 'field-body': part(),
720
+ control: part(),
721
+ input: todo('bestax `Input` renders its own `.field` and `.control` wrappers'),
722
+ textarea: todo('bestax `TextArea` renders its own `.field` and `.control` wrappers'),
723
+ select: todo('bestax `Select` renders the `.select` wrapper and the `<select>` together'),
724
+ file: todo('bestax `File` renders the whole `.file-label` tree itself'),
725
+ 'file-label': part(),
726
+ 'file-input': part(),
727
+ 'file-cta': part(),
728
+ 'file-icon': part(),
729
+ 'file-name': part(),
730
+ dropdown: todo('bestax `Dropdown` renders its own trigger and menu from props'),
731
+ 'dropdown-menu': part(),
732
+ 'dropdown-content': part(),
733
+ 'dropdown-item': part(),
734
+ 'dropdown-divider': part(),
735
+ icon: todo('bestax `Icon` renders its own `<i>` and adds an `aria-label`'),
736
+ 'icon-text': todo('bestax `IconText` pairs with `Icon`, which renders its own `<i>`'),
737
+ image: todo('bestax `Image` renders its own `<img>`'),
738
+ menu: todo('bestax `Menu.Item` renders the `<li>` and the `<a>` together'),
739
+ 'menu-label': part(),
740
+ 'menu-list': part(),
741
+ 'menu-item': part(),
742
+ message: todo('bestax `Message` always wraps its children in `.message-body`'),
743
+ 'message-header': part(),
744
+ 'message-body': part(),
745
+ modal: todo('bestax `Modal` renders its own background and content parts, and adds dialog attributes'),
746
+ 'modal-background': part(),
747
+ 'modal-content': part(),
748
+ 'modal-card': part(),
749
+ 'modal-card-head': part(),
750
+ 'modal-card-title': part(),
751
+ 'modal-card-body': part(),
752
+ 'modal-card-foot': part(),
753
+ 'modal-close': part(),
754
+ navbar: todo('bestax `Navbar` adds navigation roles, and its burger renders its own spans'),
755
+ 'navbar-brand': part(),
756
+ 'navbar-burger': part(),
757
+ 'navbar-menu': part(),
758
+ 'navbar-start': part(),
759
+ 'navbar-end': part(),
760
+ 'navbar-item': part(),
761
+ 'navbar-link': part(),
762
+ 'navbar-dropdown': part(),
763
+ 'navbar-divider': part(),
764
+ 'navbar-content': part(),
765
+ 'navbar-tabs': part(),
766
+ pagination: todo('bestax `Pagination` renders its own list items and adds navigation roles'),
767
+ 'pagination-list': part(),
768
+ 'pagination-link': part(),
769
+ 'pagination-ellipsis': part(),
770
+ 'pagination-previous': part(),
771
+ 'pagination-next': part(),
772
+ panel: todo('bestax `Panel` parts render their own tags and attributes (`Panel.Block` is an `<a>`, `Panel.Icon` adds an `aria-label`)'),
773
+ 'panel-heading': part(),
774
+ 'panel-tabs': part(),
775
+ 'panel-block': part(),
776
+ 'panel-icon': part(),
777
+ 'panel-list': part(),
778
+ tabs: todo("bestax `Tabs` renders each tab's `<li>` and `<a>` together, with tab roles"),
779
+ 'table-container': todo('bestax renders `.table-container` from `Table isResponsive`'),
780
+ 'skeleton-block': todo('bestax `Skeleton` renders its own markup'),
781
+ 'skeleton-lines': todo('bestax `Skeleton` renders its own markup'),
782
+ // ---- Valid Bulma, nothing to convert to --------------------------------------
783
+ // The other sources emit these on purpose where bestax has no component.
784
+ help: plain('bestax renders `.help` only inside its form controls'),
785
+ label: plain('bestax renders `.label` only inside its form controls'),
786
+ loader: plain("bestax `Loading` is an overlay, not Bulma's inline spinner"),
787
+ 'hero-buttons': plain('a layout class inside `.hero`; bestax has no part for it'),
788
+ 'hero-video': plain('a layout class inside `.hero`; bestax has no part for it'),
789
+ 'theme-dark': plain('a theme scope; bestax sets themes through `Theme`'),
790
+ 'theme-light': plain('a theme scope; bestax sets themes through `Theme`'),
791
+ fa: plain("Font Awesome's own class, styled by Bulma inside `.icon`"),
792
+ marginless: plain('a Bulma helper with no bestax prop'),
793
+ paddingless: plain('a Bulma helper with no bestax prop'),
794
+ };
795
+ function todo(why) {
796
+ return { status: 'todo', why };
797
+ }
798
+ function part() {
799
+ return { status: 'todo', part: true };
800
+ }
801
+ function plain(why) {
802
+ return { status: 'plain', why };
803
+ }
804
+ /**
805
+ * Which root wins when an element carries two (`column box`): layout before
806
+ * surface, so the element keeps the role that decides where it sits. The
807
+ * other root stays in `className`, which renders the same either way.
808
+ */
809
+ export const PRECEDENCE = [
810
+ 'columns',
811
+ 'column',
812
+ 'container',
813
+ 'section',
814
+ 'hero',
815
+ 'hero-head',
816
+ 'hero-body',
817
+ 'hero-foot',
818
+ 'footer',
819
+ 'level',
820
+ 'level-left',
821
+ 'level-right',
822
+ 'level-item',
823
+ 'media',
824
+ 'media-left',
825
+ 'media-content',
826
+ 'media-right',
827
+ 'buttons',
828
+ 'tags',
829
+ 'button',
830
+ 'tag',
831
+ 'delete',
832
+ 'progress',
833
+ 'table',
834
+ 'title',
835
+ 'subtitle',
836
+ 'notification',
837
+ 'box',
838
+ 'content',
839
+ 'block',
840
+ ];
841
+ /** Refs reach the element only through these targets. */
842
+ export const FORWARDS_REF = ['Button', 'Link'];
843
+ /**
844
+ * Plain tags bestax wraps, for an element with helper classes and no root
845
+ * (`<p className="has-text-centered">` → `<Paragraph textAlign="centered">`).
846
+ */
847
+ export const WRAPPERS = {
848
+ p: 'Paragraph',
849
+ span: 'Span',
850
+ strong: 'Strong',
851
+ em: 'Emphasis',
852
+ code: 'Code',
853
+ pre: 'Pre',
854
+ a: 'Link',
855
+ li: 'ListItem',
856
+ ol: 'OrderedList',
857
+ ul: 'UnorderedList',
858
+ figure: 'Figure',
859
+ };
860
+ /** The wrappers' own props, as `ROOTS` lists them for the components. */
861
+ export const WRAPPER_OWN_PROPS = {
862
+ Paragraph: ['textColor', 'bgColor'],
863
+ Span: ['textColor', 'bgColor'],
864
+ Strong: ['textColor', 'bgColor'],
865
+ Emphasis: ['textColor', 'bgColor'],
866
+ Code: ['textColor', 'bgColor'],
867
+ Pre: ['textColor', 'bgColor'],
868
+ Link: ['as', 'textColor', 'bgColor', 'isActive'],
869
+ ListItem: ['textColor', 'bgColor'],
870
+ OrderedList: ['textColor', 'bgColor'],
871
+ UnorderedList: ['textColor', 'bgColor'],
872
+ Figure: ['textColor', 'bgColor'],
873
+ };
874
+ /** Bulma 0.9 classes v1 dropped, with what replaced them. */
875
+ export const LEGACY_09 = {
876
+ tile: 'Bulma v1 removed tiles; rebuild the layout with `Grid` and `Cell` (see the Bulma 0.9 to 1 guide)',
877
+ };
878
+ function helperTokens(group, prefix, values, prop, suffix = '') {
879
+ return values.map(value => [
880
+ `${prefix}${value}${suffix}`,
881
+ { group, write: { prop, value } },
882
+ ]);
883
+ }
884
+ function helperPerViewport(group, prefix, values, prop, viewports) {
885
+ return viewports.flatMap(viewport => helperTokens(group, prefix, values, `${prop}${viewportSuffix(viewport)}`, `-${viewport}`));
886
+ }
887
+ function helperFlag(group, token, prop) {
888
+ return [token, { group, write: { prop } }];
889
+ }
890
+ /** The color helpers also take the two CSS keywords. */
891
+ const HELPER_COLORS = [...COLORS, 'inherit', 'current'];
892
+ const SPACING_PROPS = [
893
+ 'm',
894
+ 'mt',
895
+ 'mr',
896
+ 'mb',
897
+ 'ml',
898
+ 'mx',
899
+ 'my',
900
+ 'p',
901
+ 'pt',
902
+ 'pr',
903
+ 'pb',
904
+ 'pl',
905
+ 'px',
906
+ 'py',
907
+ ];
908
+ export const HELPER_TOKENS = new Map([
909
+ // Colors: the prop is a placeholder the planner swaps for the target's own.
910
+ ...helperTokens('text-color', 'has-text-', HELPER_COLORS, 'textColor'),
911
+ ...helperTokens('background', 'has-background-', HELPER_COLORS, 'bgColor'),
912
+ ...SPACING_PROPS.flatMap(prop => helperTokens('spacing', `${prop}-`, SIZES, prop)),
913
+ ...helperTokens('typography', 'is-size-', TEXT_SIZES, 'textSize'),
914
+ ...helperPerViewport('typography', 'is-size-', TEXT_SIZES, 'textSize', SIZE_VIEWPORTS),
915
+ ...helperTokens('typography', 'has-text-', ALIGNMENTS, 'textAlign'),
916
+ ...helperPerViewport('typography', 'has-text-', ALIGNMENTS, 'textAlign', SIZE_VIEWPORTS),
917
+ ...helperTokens('typography', 'is-', TEXT_TRANSFORMS, 'textTransform'),
918
+ ...helperTokens('typography', 'has-text-weight-', TEXT_WEIGHTS, 'textWeight'),
919
+ ...helperTokens('typography', 'is-family-', FONT_FAMILIES, 'fontFamily'),
920
+ ...helperTokens('display', 'is-', DISPLAYS, 'display'),
921
+ ...helperPerViewport('display', 'is-', DISPLAYS, 'display', VIEWPORTS),
922
+ // `is-hidden` is a visibility, not a display: bestax drops a base
923
+ // `display` whenever a per-viewport one is set, and would lose it.
924
+ ...helperTokens('visibility', 'is-', ['hidden', 'invisible', 'sr-only'], 'visibility'),
925
+ ...helperPerViewport('visibility', 'is-', ['hidden', 'invisible'], 'visibility', VIEWPORTS),
926
+ ...helperTokens('flex-container', 'is-flex-direction-', FLEX_DIRECTIONS, 'flexDirection'),
927
+ ...helperTokens('flex-container', 'is-flex-wrap-', FLEX_WRAPS, 'flexWrap'),
928
+ ...helperTokens('flex-container', 'is-justify-content-', JUSTIFY_CONTENTS, 'justifyContent'),
929
+ ...helperTokens('flex-container', 'is-align-content-', ALIGN_CONTENTS, 'alignContent'),
930
+ ...helperTokens('flex-container', 'is-align-items-', ALIGN_ITEMS, 'alignItems'),
931
+ ...helperTokens('flex-item', 'is-align-self-', ALIGN_SELFS, 'alignSelf'),
932
+ ...helperTokens('flex-item', 'is-flex-grow-', FLEX_GROW_SHRINK, 'flexGrow'),
933
+ ...helperTokens('flex-item', 'is-flex-shrink-', FLEX_GROW_SHRINK, 'flexShrink'),
934
+ ...helperTokens('other', 'is-pulled-', ['left', 'right'], 'float'),
935
+ [
936
+ 'is-clipped',
937
+ { group: 'other', write: { prop: 'overflow', value: 'clipped' } },
938
+ ],
939
+ helperFlag('other', 'is-overlay', 'overlay'),
940
+ [
941
+ 'is-unselectable',
942
+ { group: 'other', write: { prop: 'interaction', value: 'unselectable' } },
943
+ ],
944
+ [
945
+ 'is-clickable',
946
+ { group: 'other', write: { prop: 'interaction', value: 'clickable' } },
947
+ ],
948
+ [
949
+ 'is-radiusless',
950
+ { group: 'other', write: { prop: 'radius', value: 'radiusless' } },
951
+ ],
952
+ [
953
+ 'is-shadowless',
954
+ { group: 'other', write: { prop: 'shadow', value: 'shadowless' } },
955
+ ],
956
+ ...helperTokens('other', 'is-', ['mobile', 'narrow'], 'responsive'),
957
+ helperFlag('other', 'is-skeleton', 'skeleton'),
958
+ helperFlag('other', 'is-clearfix', 'clearfix'),
959
+ helperFlag('other', 'is-relative', 'relative'),
960
+ ]);
961
+ /** Every helper prop name, for the attribute-collision check. */
962
+ export const HELPER_PROPS = new Set([
963
+ 'color',
964
+ 'backgroundColor',
965
+ 'textColor',
966
+ 'bgColor',
967
+ 'colorShade',
968
+ 'backgroundColorShade',
969
+ 'viewport',
970
+ ...[...HELPER_TOKENS.values()].map(token => token.write.prop),
971
+ ]);
972
+ // ---- Classes that stay classes ----------------------------------------------------
973
+ /**
974
+ * Bulma classes this source never turns into a prop, grouped by why. Any
975
+ * class not named above stays in `className` anyway; this list exists so
976
+ * every class in Bulma's stylesheet is accounted for, and a Bulma release
977
+ * that adds one fails a test until someone decides what it is.
978
+ */
979
+ export const PASSTHROUGH = [
980
+ {
981
+ why: 'a color shade, a scheme color or a palette; shades stay as classes',
982
+ 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))$/,
983
+ },
984
+ {
985
+ why: "a breakpoint bestax's per-viewport props do not cover",
986
+ match: /-(?:touch|tablet-only|desktop-only|widescreen-only)$/,
987
+ },
988
+ {
989
+ why: 'Grid and Cell layout, which this source leaves as markup',
990
+ match: /^(?:is-(?:col|row)-.+|has-\d+-cols(?:-.+)?|is-(?:column|row)-gap-\d+|is-gap-\d+|is-auto-fill)$/,
991
+ },
992
+ {
993
+ why: 'an `.image` modifier; `.image` stays as markup',
994
+ match: /^(?:is-\d+by\d+|is-\d+x\d+|is-square|is-aspect-ratio-.+|has-ratio)$/,
995
+ },
996
+ {
997
+ why: 'a Bulma helper with no bestax prop',
998
+ match: /^(?:is-display-.+|is-visibility-.+|is-overflow-.+|is-position-.+|is-float-.+|is-clear-.+|has-radius-.+|has-text-weight-extrabold|is-align-content-(?:baseline|start|end)|is-align-items-self-(?:start|end)|is-offset-0(?:-[a-z]+)?)$/,
999
+ },
1000
+ {
1001
+ why: 'a modifier of markup this source leaves alone, or one bestax has no prop for',
1002
+ match: /^(?:has-addons-.+|has-[a-z]+-separator|has-dropdown(?:-up)?|has-fixed-size|has-icons-(?:left|right)|has-name|has-(?:spaced-)?navbar-fixed-(?:top|bottom)(?:-desktop)?|has-shadow|has-auto-count|is-arrowless|is-boxed|is-center|is-current|is-delete|is-disabled|is-empty|is-expanded|is-fixed-(?:top|bottom)(?:-desktop)?|is-flexible|is-grouped(?:-.+)?|is-halfheight|is-horizontal|is-left|is-(?:lower|upper)-(?:alpha|roman)|is-multiple|is-responsive|is-selected|is-tab|is-toggle(?:-rounded)?|is-transparent|is-underlined|is-up|is-wrapped)$/,
1003
+ },
1004
+ ];
1005
+ /**
1006
+ * Why a class stays a class. Consult it only for a class nothing above
1007
+ * converts: a modifier converts on its own root and nowhere else, so the same
1008
+ * class can be both (`is-narrow-touch` is a Column prop, and a breakpoint
1009
+ * bestax has no prop for on anything else).
1010
+ */
1011
+ export function passthroughReason(token) {
1012
+ return PASSTHROUGH.find(group => group.match.test(token))?.why;
1013
+ }
1014
+ // ---- Lookups ------------------------------------------------------------------
1015
+ /*
1016
+ * Class tokens and tags come from the app's markup, and the tables above are
1017
+ * plain objects: `ROOTS.toString` is `Object.prototype.toString`. Every lookup
1018
+ * by an app-supplied key goes through these, which read own properties only.
1019
+ */
1020
+ function own(record, key) {
1021
+ return Object.hasOwn(record, key) ? record[key] : undefined;
1022
+ }
1023
+ /** The table's entry for a class. */
1024
+ export function rootFor(token) {
1025
+ return own(ROOTS, token);
1026
+ }
1027
+ /**
1028
+ * A class that decides what its element is, for a TODO: a root the table
1029
+ * converts or a family's outermost class. Parts and `plain` roots are not.
1030
+ */
1031
+ export function flaggableRoot(token) {
1032
+ const entry = rootFor(token);
1033
+ return entry && entry.status !== 'plain' && !entry.part ? entry : undefined;
1034
+ }
1035
+ /** A root's modifier for a class. */
1036
+ export function modifierFor(entry, token) {
1037
+ return entry.modifiers ? own(entry.modifiers, token) : undefined;
1038
+ }
1039
+ /** What replaced a Bulma 0.9 class v1 removed. */
1040
+ export function legacyHint(token) {
1041
+ return own(LEGACY_09, token);
1042
+ }
1043
+ /** The bestax wrapper for a plain tag. */
1044
+ export function wrapperFor(tag) {
1045
+ return own(WRAPPERS, tag);
1046
+ }