create-bestax 4.2.18 → 4.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -3
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +69 -1
- package/dist/file-system.d.ts +5 -1
- package/dist/file-system.d.ts.map +1 -1
- package/dist/file-system.js +11 -1
- package/dist/library-range.d.ts +16 -0
- package/dist/library-range.d.ts.map +1 -0
- package/dist/library-range.js +40 -0
- package/dist/project-creator.d.ts +8 -0
- package/dist/project-creator.d.ts.map +1 -1
- package/dist/project-creator.js +62 -3
- package/dist/prompts.d.ts +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +15 -1
- package/package.json +8 -8
- package/templates/skills/bestax-custom-component/references/component-catalog.md +5 -1
- package/templates/skills/bestax-form/SKILL.md +40 -15
- package/templates/skills/bestax-form/references/api.md +10 -8
- package/templates/skills/bestax-form/references/patterns.md +68 -0
- package/templates/skills/bestax-icons/references/icon-libraries.md +14 -1
- package/templates/skills/bestax-layout-scaffold/SKILL.md +31 -5
- package/templates/skills/bestax-layout-scaffold/references/archetypes.md +2 -2
- package/templates/skills/bestax-layout-scaffold/references/layout-components.md +52 -5
- package/templates/skills/bestax-migrate/SKILL.md +19 -5
- package/templates/skills/bestax-migrate/references/bloomer/component-map.md +1 -1
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +9 -6
- package/templates/skills/bestax-migrate/references/bloomer/unmappables.md +4 -1
- package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +182 -105
- package/templates/skills/bestax-migrate/references/bulma-classes/prop-map.md +50 -17
- package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +372 -64
- package/templates/skills/bestax-migrate/references/css-migration.md +12 -5
- package/templates/skills/bestax-migrate/references/rbx/prop-map.md +20 -14
- package/templates/skills/bestax-migrate/references/react-bulma-components/prop-map.md +27 -22
- package/templates/skills/bestax-migrate/references/react-bulma-components/unmappables.md +3 -3
- package/templates/skills/bestax-optimize/references/modular-build.md +59 -17
- package/templates/skills/bestax-theming/SKILL.md +22 -8
- package/templates/skills/bestax-theming/examples/dark-mode.tsx +100 -17
- package/templates/skills/bestax-theming/examples/theme-config.tsx +20 -8
- package/templates/skills/bestax-theming/references/css-variables.md +268 -20
- package/templates/skills/bestax-theming/references/themeable-components.md +4 -0
- package/templates/vite/README.md +2 -2
- package/templates/vite/_oxlintrc.json +8 -0
- package/templates/vite/package.json +9 -13
- package/templates/vite/src/main.jsx +1 -1
- package/templates/vite/vite.config.js +1 -1
- package/templates/vite-ts/README.md +2 -2
- package/templates/vite-ts/_oxlintrc.json +8 -0
- package/templates/vite-ts/package.json +11 -16
- package/templates/vite-ts/src/main.tsx +1 -1
- package/templates/vite/eslint.config.js +0 -29
- package/templates/vite-ts/eslint.config.js +0 -26
|
@@ -92,7 +92,35 @@ give the `<nav>` both, with your own label if you like. `Breadcrumb` renders
|
|
|
92
92
|
makes one named by `aria-label` or `aria-labelledby` an image, with `role="img"`. Give a decorative
|
|
93
93
|
`.icon` `aria-hidden="true"`, and a meaningful one an `aria-label` that says what it means and
|
|
94
94
|
`role="img"`. One whose name is an expression may render with no name, so it needs a `role` of its
|
|
95
|
-
own.
|
|
95
|
+
own. `Icon` writes `aria-hidden` on the `.icon` and never on the `<i>` inside. Font Awesome's own
|
|
96
|
+
markup, `<i class="fas fa-envelope" aria-hidden="true">` alone in a `.icon` that carries
|
|
97
|
+
nothing but its classes, an `id`, a `style` and `data-` attributes, converts anyway, with the
|
|
98
|
+
attribute moved up onto the `.icon`, an exception to identical markup. A `.icon` that
|
|
99
|
+
carries anything more never takes the move. A `role` or `tabIndex` written out converts around
|
|
100
|
+
the `<i>` as it is, since `Icon` then hides nothing itself. Anything else, or either of those as
|
|
101
|
+
an expression, keeps the `.icon` as markup: a `title` or a description would be hidden with it,
|
|
102
|
+
and beside a `role` or `tabIndex` `Icon` writes no `aria-hidden` at all. Give a meaningful one an
|
|
103
|
+
`aria-label` and `role="img"`, or drop the attribute from a decorative one, then re-run. An `<i>`
|
|
104
|
+
that carries it beside something else,
|
|
105
|
+
an `id` say, keeps its `.icon` as markup too: the `.icon` holds nothing else, so the attribute
|
|
106
|
+
hides the same glyph on the `.icon`. Move it up and re-run, and the `.icon` converts around the
|
|
107
|
+
`<i>`. An icon around a bare glyph in a `<button>`, or a link, that its own `aria-label` or
|
|
108
|
+
`aria-labelledby` names converts as it is, another exception: the label is what assistive tech
|
|
109
|
+
reads for the control, so the icon is decoration there, and `Icon` hides it. That takes the same
|
|
110
|
+
`.icon` as the move: its classes, an `id`, a `style` and `data-` attributes, and no
|
|
111
|
+
`aria-hidden`. An icon in a control its text names is decoration too, so give it
|
|
112
|
+
`aria-hidden="true"`, and so is one in a named control it doesn't convert in (a `title` on the
|
|
113
|
+
`.icon`, say). An `<a>` with no `href` is no link and has no role, and ARIA lets nothing name it,
|
|
114
|
+
so its `aria-label` does nothing: give it an `href`, or make it a `<button>`, then re-run. One
|
|
115
|
+
that is all a link or button shows names nothing a screen reader can read: give the link or
|
|
116
|
+
button an `aria-label` that says what it does, then re-run, and the icon converts hidden. The
|
|
117
|
+
`<svg class="svg-inline--fa">` Font Awesome's script draws in place of an `<i>` converts as
|
|
118
|
+
`Icon`'s children once its `.icon` is hidden, or write `Icon` with the glyph's `name` in its place,
|
|
119
|
+
which renders the `<i>` the script draws from. Inside a `.control` with `has-icons-left` or
|
|
120
|
+
`has-icons-right`, a hidden `.icon` can go instead, as that `Control`'s `iconLeft` or
|
|
121
|
+
`iconRight` (`iconLeft={{ name: "envelope", size: "small" }}`), which renders it
|
|
122
|
+
after the `Control`'s children. Each TODO says which of these applies, and what the icon converts
|
|
123
|
+
to.
|
|
96
124
|
`Pagination` renders Bulma's own `role="navigation"` and `aria-label="pagination"`, and
|
|
97
125
|
`Pagination.Previous`, `Pagination.Next` and `Pagination.Link` render `tabIndex={0}`, so give each
|
|
98
126
|
element the attribute it's missing.
|
|
@@ -151,6 +179,32 @@ or when what's inside is an expression or text, since `Image` renders an `<img>`
|
|
|
151
179
|
its children come out empty. Keep it as markup, or write the `Image` by hand if the expression
|
|
152
180
|
never is.
|
|
153
181
|
|
|
182
|
+
A `<label>` beside the `<select>` in a `.select` (a visually hidden one, say) is that case too,
|
|
183
|
+
since `SelectBase` renders no label. bestax's convenience `Select` takes it: the label's text as
|
|
184
|
+
`label` and its classes in `labelProps`, and it points the label at the `<select>`'s `id` itself.
|
|
185
|
+
A computed `className` on the label goes in `labelProps` as the same expression, since it may be
|
|
186
|
+
what hides the label, and so does what a spread on it carries. `Select` renders the `.select`
|
|
187
|
+
inside a `Field` and a `Control`, so convert the two by hand and check the layout:
|
|
188
|
+
|
|
189
|
+
```tsx
|
|
190
|
+
<Select
|
|
191
|
+
id="language"
|
|
192
|
+
size="small"
|
|
193
|
+
label="Select language"
|
|
194
|
+
labelProps={{ className: 'is-sr-only' }}
|
|
195
|
+
>
|
|
196
|
+
<option>English</option>
|
|
197
|
+
<option>French</option>
|
|
198
|
+
</Select>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
That holds only where the `.select` isn't inside a `.field` or a `.control` (or a `Field` or
|
|
202
|
+
`Control`). Inside a `Field`, `Select` renders no label of its own and drops `label` and
|
|
203
|
+
`labelProps`, so the select would lose its name; inside a bare `Control`, it puts its label's
|
|
204
|
+
`.field` inside the `.control`. There, keep the label the page's: move the `<label>` out beside
|
|
205
|
+
the `.select`, its `htmlFor` on the `<select>`'s `id`, or give the `<select>` an `aria-label` in
|
|
206
|
+
its place, then re-run, and the `.select` converts to `SelectBase`.
|
|
207
|
+
|
|
154
208
|
A menu item is the same from the `<li>`'s side: `Menu.Item` renders the `<a>` inside it, and a
|
|
155
209
|
`Menu.List` after that, so an item converts only when its `<li>` holds one `<a>` and at most one
|
|
156
210
|
`<ul>` after it, with nothing else beside them. Text or a comment beside the `<a>` keeps it as
|
|
@@ -164,13 +218,14 @@ element converts only holding exactly that (`…` or the character), and cl
|
|
|
164
218
|
|
|
165
219
|
On an `.icon-text`, `IconText` builds its icons from props and wraps each text in a `<span>` of
|
|
166
220
|
its own, so it converts only when its children are `.icon`s, each followed by at most one bare
|
|
167
|
-
`<span>` of static text. Each `.icon` has to convert to `Icon` on its own, so one with
|
|
168
|
-
`aria-label` gets a `defaults:Icon` TODO of its own first:
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
it
|
|
173
|
-
`
|
|
221
|
+
`<span>` of static text. Each `.icon` has to convert to `Icon` on its own, so one with neither
|
|
222
|
+
`aria-hidden` nor `aria-label` gets a `defaults:Icon` TODO of its own first: hide a decorative one,
|
|
223
|
+
or give a meaningful one a name, then re-run. Its `<i>` has to be empty, carry nothing but Font
|
|
224
|
+
Awesome's own `aria-hidden`, which moves up as it does on a `.icon` alone, and name one Font
|
|
225
|
+
Awesome or Material Design Icons glyph, so another attribute on the `<i>`, another icon font, or
|
|
226
|
+
anything between the children keeps it as markup, and the `.icon`s inside convert on their own. The markup renders the same as it is; to use
|
|
227
|
+
`IconText` anyway, write it by hand with `iconProps={{ name: ... }}` (the `bestax-icons` skill
|
|
228
|
+
covers `Icon`'s library and name props).
|
|
174
229
|
|
|
175
230
|
On a `.file`, `File` renders the whole tree from props, so it converts only when its tree is the one
|
|
176
231
|
`File` renders: one bare `.file-label` `<label>` holding a `.file-input` `<input type="file">`, a
|
|
@@ -286,6 +341,25 @@ in a menu item gets this TODO too. For the `<a>`, a condition on `is-active` is
|
|
|
286
341
|
also writes `aria-current="page"` while `on` holds. Pass an `aria-current` of your own if the item
|
|
287
342
|
marks something other than the current page.
|
|
288
343
|
|
|
344
|
+
## An element it converted: `second-component:<Target>`
|
|
345
|
+
|
|
346
|
+
The element carried a second Bulma component class (`<div className="columns box">`), and an
|
|
347
|
+
element converts to one component. It became the one whose component fits its tag best (the
|
|
348
|
+
tag it renders with the element's classes and no `as`, such as the `<figure>` an `.image`
|
|
349
|
+
ratio picks, then one it reaches through `as`), the layout one or a component's part between
|
|
350
|
+
equals, and the other class stayed in `className`, which renders the same. The TODO names the component that class belongs to. A raw component
|
|
351
|
+
class on a bestax component is what the ESLint plugin's `no-bulma-component-class` reports, so
|
|
352
|
+
move it to a component of its own:
|
|
353
|
+
|
|
354
|
+
- **Most classes**: give `<Target>` an element of its own, around the converted one or inside
|
|
355
|
+
it, and drop the class: `<Box><Columns>…</Columns></Box>`. Two elements space differently
|
|
356
|
+
from one (a `.columns` has negative side margins, which a `.box` on the same element shares
|
|
357
|
+
and one around it doesn't), so check the layout.
|
|
358
|
+
- **`second-component:Container`**: where `.container` is only there to center the element, as
|
|
359
|
+
it often is on a sized `.image`, write `mx="auto"` in its place
|
|
360
|
+
(`<Image size="128x128" mx="auto">`), which centers it and does nothing else `.container`
|
|
361
|
+
does. Otherwise wrap the element in a `Container`. Either way, check the layout.
|
|
362
|
+
|
|
289
363
|
## A family it leaves as markup: `family:<class>`
|
|
290
364
|
|
|
291
365
|
The bestax component renders parts of its own, or adds attributes, so a one-element-at-a-time
|
|
@@ -302,13 +376,47 @@ in the browser:
|
|
|
302
376
|
`aria-expanded` and keyboard handling. The codemod turned the `.has-dropdown` item around it
|
|
303
377
|
into a `Navbar.Item` that keeps the class; to get the dropdown behavior, replace that item
|
|
304
378
|
with `Navbar.Dropdown` (`hoverable` for `is-hoverable`) and the link with `Navbar.Link`.
|
|
305
|
-
- **`family:checkbox
|
|
306
|
-
|
|
379
|
+
- **`family:checkbox`**: `Checkbox` renders a `<label class="styled-checkbox checkbox">` around
|
|
380
|
+
its `<input>`, hidden, and draws a box of its own beside it. Write it in place of the element
|
|
381
|
+
that carries `.checkbox`, Bulma's `<label>` or a bare `<input type="checkbox">`:
|
|
382
|
+
- The `<input>`'s attributes go on `Checkbox`, which passes `id`, `name`, `aria-label` and the
|
|
383
|
+
rest to its `<input>`. A `<label>`'s text becomes its children.
|
|
384
|
+
- Drive it with `checked` and `onChange`, and add `indeterminate` for a select-all box that
|
|
385
|
+
shows some of its rows checked.
|
|
386
|
+
- Its `className` goes on its `<label>`, which declares the `--bulma-checkbox-*` variables. For
|
|
387
|
+
the page's colors, set those in a rule for your class beside `.styled-checkbox`, so the rule
|
|
388
|
+
wins whatever order the stylesheets load in, and leave `color` unset.
|
|
389
|
+
- Where the page put `.checkbox` on a bare `<input>`, drop its own rules for that box. bestax
|
|
390
|
+
draws its own, and `.checkbox` is on its `<label>` now, so those rules would land there.
|
|
391
|
+
|
|
392
|
+
```tsx
|
|
393
|
+
<Checkbox
|
|
394
|
+
id="select-all"
|
|
395
|
+
aria-label="Select all guests"
|
|
396
|
+
className="guest-check"
|
|
397
|
+
checked={allChecked}
|
|
398
|
+
indeterminate={someChecked && !allChecked}
|
|
399
|
+
onChange={toggleAll}
|
|
400
|
+
/>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
```css
|
|
404
|
+
.styled-checkbox.guest-check {
|
|
405
|
+
--bulma-checkbox-active-color: #e8505b;
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
- **`family:radio`**, **`family:checkboxes`**, **`family:radios`**: bestax renders its own
|
|
410
|
+
styled radio markup, and its own `.field` and `.control` around a group, not Bulma's.
|
|
307
411
|
- **`family:modal`**: `Modal` writes a `data-testid` of its own and adds dialog attributes and
|
|
308
412
|
focus handling, so the `.modal` root stays markup while its background, content and card parts
|
|
309
|
-
convert on their own. Rebuild the root with `Modal` around them,
|
|
413
|
+
convert on their own. Rebuild the root with `Modal` around them, drive it with its open prop,
|
|
414
|
+
and pass `onClose`, which Escape and `Modal.Close` call. The converted `Modal.Background`
|
|
415
|
+
doesn't call it on its own: give it `onClick={onClose}` for the background to close the modal.
|
|
310
416
|
A `.modal-close` stays too, since `Modal.Close` renders `.delete` unless it's floating: write
|
|
311
|
-
`<Modal.Close variant="floating" />` in its place.
|
|
417
|
+
`<Modal.Close variant="floating" />` in its place. A card head's `.delete` converts to `Delete`,
|
|
418
|
+
which doesn't call `onClose` either, so write `<Modal.Close />` there instead: it renders the
|
|
419
|
+
same `.delete`. When the
|
|
312
420
|
page has to look the same, keep `Modal` rather than `Dialog` or `Toast`: those render
|
|
313
421
|
bestax's own `.dialog` and `.toast` markup, which Bulma's stylesheet doesn't style.
|
|
314
422
|
- **`family:dropdown`**: `Dropdown` renders its own trigger and menu from props.
|
|
@@ -320,9 +428,9 @@ in the browser:
|
|
|
320
428
|
- **`family:message`**: `Message` always wraps its children in `.message-body`.
|
|
321
429
|
- **`family:panel-icon`**: `Panel.Icon` renders through `Icon`, which always writes an
|
|
322
430
|
`aria-label`, so write `<Panel.Icon>` by hand with the `<i>` inside. The rest of a panel converts,
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
431
|
+
a `<label>` or `<div>` `.panel-block` included, as `Panel.Block` with `as` and its contents as
|
|
432
|
+
written. `Panel.CheckboxBlock`, `Panel.InputBlock` and `Panel.ButtonBlock` build the usual
|
|
433
|
+
checkbox, search and button blocks from props, if you would rather write those by hand.
|
|
326
434
|
|
|
327
435
|
## A class Bulma v1 removed: `legacy:<class>`
|
|
328
436
|
|
|
@@ -330,6 +438,43 @@ in the browser:
|
|
|
330
438
|
0.9 to 1 guide shows the translation. Until then the element has no styles at all under
|
|
331
439
|
Bulma v1.
|
|
332
440
|
|
|
441
|
+
`legacy:is-marginless`, `legacy:is-paddingless`: v1 removed both, so they style nothing.
|
|
442
|
+
Wherever the element converts, the codemod writes them as `m="0"` and `p="0"`, which render
|
|
443
|
+
v1's `m-0` and `p-0`, and says nothing. The TODO comes only where the class stays: on an
|
|
444
|
+
element that stays markup (a `<div>` with no component class, or one refused for another
|
|
445
|
+
reason), or beside a class for the same prop (`p-2`, before it or after), which keeps the prop
|
|
446
|
+
since it's what the page renders today. Write `m-0` or `p-0` in its place, or drop it if the
|
|
447
|
+
spacing it once removed no longer matters.
|
|
448
|
+
|
|
449
|
+
## A modifier class that needs a look: `modifier:<root>`
|
|
450
|
+
|
|
451
|
+
`modifier:image`: an `.image` size or ratio (`is-64x64`, `is-square`, `is-4by3`) on an element
|
|
452
|
+
without `.image`. Bulma styles them only on the element that carries `.image`, so this one
|
|
453
|
+
sizes nothing, unless the project's own CSS gives the class a rule. If the element is the
|
|
454
|
+
image's box, add `image`. On a tag `Image` renders (the component map's `.image` row lists
|
|
455
|
+
them), re-run and it can convert; on any other tag it stays markup, and the TODO says so. Where
|
|
456
|
+
the element converted to something else anyway (a `<figure>` to `Figure`), a re-run finds a
|
|
457
|
+
component, so the TODO says to convert it to `Image` by hand. Otherwise drop the class. A computed `className` the codemod can't read whole gets no such TODO, since a class it
|
|
458
|
+
can't see may be the `.image`.
|
|
459
|
+
|
|
460
|
+
`modifier:button` (and `modifier:hero`, `modifier:tag`, `modifier:notification`,
|
|
461
|
+
`modifier:progress`, `modifier:navbar`): a second color on an element that converted
|
|
462
|
+
(`button is-black is-primary`). The component takes one `color`, the first color class on the
|
|
463
|
+
element, and the other stays in `className`, which renders the same. Two colors on one element
|
|
464
|
+
look the way Bulma's stylesheet settles them, not the order they're written in, so one of
|
|
465
|
+
them may be doing nothing. Look at what the page shows, write the color you want as `color`,
|
|
466
|
+
and drop the other class. A color a `clsx` or `classnames` condition adds gets no TODO, since
|
|
467
|
+
that is a state the page asks for.
|
|
468
|
+
|
|
469
|
+
`modifier:title`, `modifier:subtitle`: a heading size on a heading it doesn't name
|
|
470
|
+
(`<h1 className="title is-3">`). bestax picks the heading from `size` (`size="3"` renders an
|
|
471
|
+
`<h3>`), so the size stays in `className` and the element becomes `<Title className="is-3">`,
|
|
472
|
+
the same `<h1>`. To write it as a prop, as the MCP server's `lookup_bulma_classes` says,
|
|
473
|
+
`textSize="3"` in its place keeps the `<h1>` and sizes it the same. It renders Bulma's
|
|
474
|
+
`is-size-3`, which is `!important`, so check a title the page's own CSS sizes. There is no TODO
|
|
475
|
+
when an `is-size-*` beside it writes `textSize` already, or when the element has two size
|
|
476
|
+
classes.
|
|
477
|
+
|
|
333
478
|
## A whole file it left alone
|
|
334
479
|
|
|
335
480
|
These come only when the file has an element the codemod would convert (a computed className
|
|
@@ -359,7 +504,8 @@ Run on an HTML page (`bestax-migrate bulma-classes page.html`, or a folder with
|
|
|
359
504
|
codemod writes a module beside the page and runs everything above on it, so a page gets the same
|
|
360
505
|
TODOs its markup would as JSX. What a component can't carry gets an `html-*` rule. TODOs about the
|
|
361
506
|
whole page sit above the component, the rest above its `return`, and each ends with the page and
|
|
362
|
-
the line it came from (`(index.html:42)`)
|
|
507
|
+
the line it came from (`(index.html:42)`), or every line, for a TODO several elements share
|
|
508
|
+
(`(index.html:42, 57)`). The page itself stays as it was, so the code a TODO
|
|
363
509
|
points at is still there to read. A rule names only a tag, an attribute or a fixed word, never
|
|
364
510
|
anything the page says.
|
|
365
511
|
|
|
@@ -373,6 +519,11 @@ A component renders into the `<body>` of the app's own document, so nothing in t
|
|
|
373
519
|
it into the head; React 18 leaves it in the body, so use `document.title` in an effect there.
|
|
374
520
|
- **`html-head:meta`**: `charset` and `viewport` go once in the app's `index.html`. A page's own
|
|
375
521
|
(a description, Open Graph tags) go where the app sets each page's head.
|
|
522
|
+
- **`html-head:csp`**: a `<meta http-equiv="Content-Security-Policy">`. Its policy was written for
|
|
523
|
+
what the page loads, and copied into `index.html` as it is, it can block what the app loads
|
|
524
|
+
instead: a Vite dev server runs an inline script for React's fast refresh and opens a socket for
|
|
525
|
+
hot reloading, and the build serves the app's own scripts, styles and fonts. Write the app's own
|
|
526
|
+
policy, best sent as a response header, and try it under both the dev server and the build.
|
|
376
527
|
- **`html-head:link`**: icons, preconnects and preloads are app-wide, so keep them in
|
|
377
528
|
`index.html`; a `canonical` is per page.
|
|
378
529
|
- **`html-head:style`**: the `<style>` block was dropped. Move its rules into the app's stylesheet.
|
|
@@ -412,43 +563,59 @@ neither, so load what the app still needs once for the whole app, from its entry
|
|
|
412
563
|
reported in every mode, since the codemod imports only the standard one. bestax's own builds,
|
|
413
564
|
Bulma with its extras, are under `@allxsmith/bestax-bulma/versions/`.
|
|
414
565
|
- **`html-asset:font-awesome`**: Font Awesome, with the major its URL names. bestax's `Icon`
|
|
415
|
-
writes its classes (`fas fa-<name
|
|
566
|
+
writes its classes (`fas fa-<name>`, or the style its `variant` names) and loads no font of its
|
|
567
|
+
own, so keep loading it, from the
|
|
416
568
|
`<link>` in `index.html` or from npm: bestax-bulma's optional peer range for
|
|
417
569
|
`@fortawesome/fontawesome-free` is `^6.7.2 || ^7.0.0`, and an older one fails `npm install`
|
|
418
570
|
with `ERESOLVE`.
|
|
419
571
|
- 6 and 7: keep it as it is, or install it and import its `css/all.min.css` from the entry.
|
|
420
572
|
- 5: the CDN link keeps working, since 5 reads the classes `Icon` writes. From npm, take 6 or 7,
|
|
421
|
-
which still read 5's names.
|
|
422
|
-
|
|
423
|
-
|
|
573
|
+
which still read 5's names, many of them since renamed (`search` is `magnifying-glass`). But
|
|
574
|
+
6 turned the handsets round, so to keep the glyph the page shows, write 5's `phone` and
|
|
575
|
+
`phone-square` as `phone-flip` and `square-phone-flip`, and 5's `phone-alt` and
|
|
576
|
+
`phone-square-alt` as `phone` and `square-phone`.
|
|
577
|
+
- 4: its classes are `fa fa-<name>`. The codemod keeps that `fa` on each icon it converts
|
|
578
|
+
(`variant="fa"`), which 4 styles, but an `Icon` given no `variant` writes `fas fa-<name>`,
|
|
579
|
+
which 4 doesn't, so for the icons written from here on, install 6 or 7 with
|
|
580
|
+
`css/all.min.css`, then either import `css/v4-shims.min.css` beside it so
|
|
424
581
|
the page's 4 names keep working, or move them to the current names (`fa-envelope-o` is
|
|
425
|
-
`envelope` with `variant="regular"`).
|
|
582
|
+
`envelope` with `variant="regular"`). A brand's glyph under `fa` (`fa fa-github`) needs
|
|
583
|
+
`variant="brands"` then: 5 and later draw brands in a style of their own, and without the
|
|
584
|
+
shims show a missing-glyph box for one under `fa`.
|
|
585
|
+
- A URL that doesn't say its version: the TODO points at the `bestax-icons` skill's
|
|
586
|
+
`references/icon-libraries.md`, which lists the older names that draw another glyph in 6
|
|
587
|
+
and 7.
|
|
426
588
|
- A kit (`kit.fontawesome.com`): keep loading it from `index.html`, or install Font Awesome from
|
|
427
589
|
npm instead. A URL with no version: the same, with the v4 shims beside it if the page's names
|
|
428
590
|
are 4's (`fa fa-<name>`).
|
|
429
|
-
- **`html-asset:bulma-extension`**: a `bulma-*` package (or `@creativebulma/bulma-*`).
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
|
437
|
-
|
|
|
438
|
-
| `bulma-
|
|
439
|
-
| `bulma-
|
|
440
|
-
| `bulma-
|
|
441
|
-
| `bulma-
|
|
442
|
-
| `bulma-
|
|
443
|
-
| `bulma-
|
|
444
|
-
| `bulma-
|
|
445
|
-
| `bulma-
|
|
446
|
-
| `bulma-
|
|
447
|
-
| `bulma-
|
|
448
|
-
| `bulma-
|
|
449
|
-
| `bulma-
|
|
450
|
-
| `bulma-
|
|
451
|
-
| `bulma-
|
|
591
|
+
- **`html-asset:bulma-extension`**: a `bulma-*` package (or `@creativebulma/bulma-*`). A file of
|
|
592
|
+
one extension inside the `bulma-extensions` package (`bulma-extensions/bulma-carousel/dist/…`)
|
|
593
|
+
counts as that extension's. An extension's stylesheet and script are one TODO, with both lines.
|
|
594
|
+
Where bestax has a component for what it does, the TODO names it; render that in place of the
|
|
595
|
+
extension's markup and script, whose styles ship in `extras.css` and `bestax.css`, and stop
|
|
596
|
+
loading the extension once nothing the app keeps uses its classes:
|
|
597
|
+
|
|
598
|
+
| Extension | bestax |
|
|
599
|
+
| ------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
600
|
+
| `bulma-carousel` | `Carousel`, with a `CarouselItem` for each slide and `itemsToShow` for several in view |
|
|
601
|
+
| `bulma-slider` | `Slider` |
|
|
602
|
+
| `bulma-switch` | `Switch` |
|
|
603
|
+
| `bulma-checkradio` | `Checkbox` and `Radio`, which draw their own box |
|
|
604
|
+
| `bulma-tooltip`, `@creativebulma/bulma-tooltip` | `Tooltip` |
|
|
605
|
+
| `bulma-badge`, `@creativebulma/bulma-badge` | `Badge` |
|
|
606
|
+
| `bulma-steps` | `Steps` |
|
|
607
|
+
| `bulma-timeline` | `Timeline` |
|
|
608
|
+
| `bulma-tagsinput`, `@creativebulma/bulma-tagsinput` | `Taginput` |
|
|
609
|
+
| `bulma-calendar` | `DateInput`, `TimeInput`, `DateTimeInput` and `DateRangeInput` |
|
|
610
|
+
| `bulma-accordion` | `Collapses`, with a `Collapse` for each item |
|
|
611
|
+
| `bulma-collapsible`, `@creativebulma/bulma-collapsible` | `Collapse` (`Collapses` for an accordion) |
|
|
612
|
+
| `bulma-pageloader` | `Loading`, `isFullPage` for one over the whole page |
|
|
613
|
+
| `bulma-quickview` | `Sidebar` |
|
|
614
|
+
| `bulma-toast` | `Toast`: `toast.show()` from code, with a `ToastContainer` once |
|
|
615
|
+
|
|
616
|
+
bulma-carousel's `is-covered` images are the exception: its stylesheet crops them only inside
|
|
617
|
+
its own slides, which `Carousel` doesn't render, so keeping it wouldn't keep them cropped. The
|
|
618
|
+
TODO says so when the page has them, and `html-extension:is-covered` has the rule to add.
|
|
452
619
|
|
|
453
620
|
`bulma-extensions`, the bundle, holds several of these: replace the ones in the table, and keep
|
|
454
621
|
loading the bundle only for the rest. **bulma-social** has no bestax component: keep loading it,
|
|
@@ -461,6 +628,20 @@ neither, so load what the app still needs once for the whole app, from its entry
|
|
|
461
628
|
</Button>
|
|
462
629
|
```
|
|
463
630
|
|
|
631
|
+
It also ships one stylesheet per brand, `css/single/<brand>/<brand>.min.css`, a few kB each
|
|
632
|
+
against about 100 kB for every brand in `css/all.min.css`. Each holds the brand's button color
|
|
633
|
+
(`is-<brand>`) and its text and background helpers (`has-text-<brand>`,
|
|
634
|
+
`has-background-<brand>`, with `-dark` and `-light`). Every brand has a file from 3.2.0 on
|
|
635
|
+
(`slack`'s came in 2.1.0, `x`'s in 3.1.0 and `twitch`'s in 3.2.0). So with `bulma-social` 3.2.0
|
|
636
|
+
or later installed from npm, import only the brands the app shows, from its entry. The TODO names the files for the brands
|
|
637
|
+
in the page's markup, so an app of several pages imports each brand any of them shows, and one
|
|
638
|
+
a script adds as well:
|
|
639
|
+
|
|
640
|
+
```ts
|
|
641
|
+
import 'bulma-social/css/single/github/github.min.css';
|
|
642
|
+
import 'bulma-social/css/single/twitter/twitter.min.css';
|
|
643
|
+
```
|
|
644
|
+
|
|
464
645
|
Any other extension: keep loading it while the page's markup uses its classes, which go on
|
|
465
646
|
bestax's components through `className`, and under `--css bestax` or `--css bulma` check it
|
|
466
647
|
works with Bulma 1, which an extension can predate.
|
|
@@ -477,9 +658,17 @@ neither, so load what the app still needs once for the whole app, from its entry
|
|
|
477
658
|
- **`html-asset:stylesheet`**: any other stylesheet. The page's own, beside it (in its folder or
|
|
478
659
|
one below), is imported once for the app in the order the page loads it, so its rules still win
|
|
479
660
|
over Bulma's where they did (a module beside the page imports `css/styles.css` as
|
|
480
|
-
`./css/styles.css`), or its rules move into the app's stylesheet.
|
|
481
|
-
|
|
482
|
-
|
|
661
|
+
`./css/styles.css`), or its rules move into the app's stylesheet. A relative URL in it (a
|
|
662
|
+
`url()`, or an `@import` written as a string) resolves against the stylesheet's own folder, not
|
|
663
|
+
the page's, so the TODO names each one it finds: `url('../media/background.webp')` in
|
|
664
|
+
`css/styles.css` points at `media/background.webp` beside the page. Imported where it is, the
|
|
665
|
+
bundler still resolves them. Moved into the app's stylesheet (`src/index.css`), each needs
|
|
666
|
+
rewriting against that file's folder, or copy the files into the app's `public/` folder and
|
|
667
|
+
point at them from the site root (`url('/media/background.webp')`), which the TODO spells out
|
|
668
|
+
for each one inside the page's folder. An `image-set()` that names a file as a bare string
|
|
669
|
+
isn't read, so check those by hand. For a stylesheet that isn't in the page's folder, the TODO
|
|
670
|
+
says only that: the page's `<base href>`, if it has one, may have loaded it from somewhere
|
|
671
|
+
else, so find the one it meant, or drop it.
|
|
483
672
|
- **`html-asset:script`**: any other script. The component runs none: load a library the app still
|
|
484
673
|
needs in `index.html` (or install it), and port what the page's own scripts did into the
|
|
485
674
|
component. A script of the page's own, beside it, is read the way an inline script is, so one
|
|
@@ -525,14 +714,32 @@ read for the burger, a carousel and a theme toggle too, and its TODO names the f
|
|
|
525
714
|
```
|
|
526
715
|
|
|
527
716
|
- **`html-script:modal`** opens or closes a modal. `Modal` shows while `active` is true and calls
|
|
528
|
-
`onClose`
|
|
529
|
-
`
|
|
717
|
+
`onClose` on Escape and from a `Modal.Close` with no `onClick` of its own. `Modal.Background`
|
|
718
|
+
doesn't call it on its own, so give it `onClick={onClose}` for the background to close the
|
|
719
|
+
modal. Keep the open state in `useState` (the `family:modal` TODO covers rebuilding the markup).
|
|
530
720
|
- **`html-script:dismiss`** removes an element when its `.delete` is clicked. `Notification`
|
|
531
721
|
takes `hasDelete` and `onDelete`, `Tag` takes `onDelete` and `Message` takes `onClose`; render
|
|
532
722
|
the element only while it's in state.
|
|
533
723
|
- **`html-script:carousel`** drives a carousel. `Carousel` takes its slides as `CarouselItem`
|
|
534
|
-
children and renders its own arrows and indicators (`autoplay` for a timed one).
|
|
535
|
-
in
|
|
724
|
+
children and renders its own arrows and indicators (`autoplay` for a timed one). For several
|
|
725
|
+
slides in view, set `itemsToShow`, with a variant per viewport (`itemsToShowMobile`,
|
|
726
|
+
`itemsToShowTablet`, …), and `itemsToScroll`: bulma-carousel calls them `slidesToShow` and
|
|
727
|
+
`slidesToScroll`. bulma-carousel's `breakpoints` replace both at and below pixel widths of its
|
|
728
|
+
own (each entry's `changePoint`), and a page that sets none gets its defaults: 1 slide up to
|
|
729
|
+
480px, 2 up to 640px and 3 up to 768px, each scrolling as many, so `slidesToShow` applies only
|
|
730
|
+
from 769px up. Below that the defaults decide whatever `slidesToShow` says: a phone shows 1
|
|
731
|
+
slide, and a page that sets `slidesToShow: 1` shows 2 or 3 between a phone's width and a
|
|
732
|
+
tablet's. A page's own `breakpoints` replace the defaults, and an empty list turns them off.
|
|
733
|
+
`Carousel` has no pixel widths: `itemsToShowMobile` covers every width below 769px, where all
|
|
734
|
+
of those defaults sit, and the wider variants start at Bulma's breakpoints. So set
|
|
735
|
+
`itemsToShow` to the page's `slidesToShow`, and `itemsToShowMobile` to what the page shows on
|
|
736
|
+
a phone (1 under the defaults) where that differs; one `itemsToScroll` covers every width. To
|
|
737
|
+
keep the steps bulma-carousel takes between those widths, compute `itemsToShow` from the
|
|
738
|
+
window's width in your own code. `Carousel` loops unless `repeat={false}`, while
|
|
739
|
+
bulma-carousel stops at the ends unless `loop` (back to the start) or `infinite` (round
|
|
740
|
+
without a break) is set, so a carousel with neither takes `repeat={false}`. Its styles ship in
|
|
741
|
+
bestax's `extras.css` and `bestax.css`, not in Bulma's stylesheet. The element the script
|
|
742
|
+
drives gets `html-extension:carousel`, below, when the codemod can read its selector.
|
|
536
743
|
- **`html-script:theme`** switches Bulma's light and dark schemes. The toggle is `Theme`'s: it
|
|
537
744
|
writes `data-theme` on `<html>` from its `colorMode` (`light`, `dark` or `system`), so keep the
|
|
538
745
|
choice in state, save it in `localStorage`, and pass it. The first paint is `index.html`'s:
|
|
@@ -540,13 +747,50 @@ read for the burger, a carousel and a theme toggle too, and its TODO names the f
|
|
|
540
747
|
from their OS sees the OS's scheme first. A small inline script in the `<head>` of `index.html`
|
|
541
748
|
that reads the saved choice (or the OS's, with none saved) and writes `data-theme` before the
|
|
542
749
|
app loads paints the right one, and the toggle's state starts from what it wrote. The
|
|
543
|
-
bestax-theming skill covers `Theme` and `colorMode
|
|
544
|
-
|
|
750
|
+
bestax-theming skill covers `Theme` and `colorMode`, and its `examples/dark-mode.tsx` has the
|
|
751
|
+
script and the app's side.
|
|
752
|
+
- **`html-script:json-ld`** is structured data for search engines. Data about the whole site, or
|
|
753
|
+
about a single-page app's one page, goes in the app's `index.html` as it is, where a crawler that
|
|
754
|
+
runs no JavaScript still reads it. Data that differs from page to page goes where the app sets
|
|
545
755
|
each page's head, as
|
|
546
756
|
`<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }} />`.
|
|
547
757
|
- **`html-script`**: any other inline script, or a `<script type>` that isn't code (a template,
|
|
548
758
|
JSON data). Port what it does into the component as state, effects and event handlers.
|
|
549
759
|
|
|
760
|
+
### A Bulma extension's own markup: `html-extension:<name>`
|
|
761
|
+
|
|
762
|
+
A component takes the place of an extension's markup, but nothing converts that markup, so these
|
|
763
|
+
point at the elements to rebuild.
|
|
764
|
+
|
|
765
|
+
- **`html-extension:carousel`**: an element bulma-carousel makes a carousel of. When a script of
|
|
766
|
+
the page's, inline or beside it, attaches bulma-carousel with a selector written as a string of
|
|
767
|
+
tags, ids and classes (`bulmaCarousel.attach('#carousel-demo')`), the codemod finds every
|
|
768
|
+
element that selector matches, the way `querySelectorAll` does, and the TODO lists their
|
|
769
|
+
lines. bulma-carousel makes a carousel of each one, so a page that gives one id to two elements
|
|
770
|
+
has two carousels, and the TODO says so. Render a `Carousel` in the place of each, with a
|
|
771
|
+
`CarouselItem` for each slide (bulma-carousel 4 makes a slide of each child), and carry its
|
|
772
|
+
options over as `html-script:carousel` says. On a page that uses bulma-carousel, an element
|
|
773
|
+
with its `carousel` class that no selector reached gets the TODO too. `carousel` is also bestax
|
|
774
|
+
`Carousel`'s own class, so `bestax.css` and `extras.css` style that markup as `Carousel`'s root
|
|
775
|
+
(`position: relative`, `overflow: hidden`, `width: 100%`) until a `Carousel` takes its place. A
|
|
776
|
+
selector the codemod can't read (a variable, or a selector with a combinator or an attribute)
|
|
777
|
+
gets no TODO of its own: find what it selects by hand.
|
|
778
|
+
- **`html-extension:is-covered`**: bulma-carousel's `is-covered` on an `.image`, on a page that
|
|
779
|
+
loads its stylesheet (the bundle's combined `bulma-extensions.min.css` has no rule for it).
|
|
780
|
+
Inside one of the slides its script builds, that stylesheet makes the `<img>` fill the frame
|
|
781
|
+
and crops it to fit (`object-fit: cover`). Nothing in bestax reads the class: `Image` has no
|
|
782
|
+
prop for it, and the rule reaches only bulma-carousel's own slides, not `Carousel`'s. So in the
|
|
783
|
+
app a ratio image stretches its photo instead. Keep the class and give it the rule in the app's
|
|
784
|
+
stylesheet:
|
|
785
|
+
|
|
786
|
+
```css
|
|
787
|
+
.image.is-covered img {
|
|
788
|
+
width: 100%;
|
|
789
|
+
height: 100%;
|
|
790
|
+
object-fit: cover;
|
|
791
|
+
}
|
|
792
|
+
```
|
|
793
|
+
|
|
550
794
|
### `<html>` and `<body>`: `html-document:<name>`
|
|
551
795
|
|
|
552
796
|
The app's document has its own `<html>` and `<body>`, which a component can't reach.
|
|
@@ -558,8 +802,10 @@ The app's document has its own `<html>` and `<body>`, which a component can't re
|
|
|
558
802
|
pads the page for a fixed navbar from it. Put the class on the `<html>` in `index.html`, since
|
|
559
803
|
bestax's `Navbar` adds none there, whatever its `fixed` says.
|
|
560
804
|
- **`html-document:data-theme`**, **`html-document:theme-dark`**, **`html-document:theme-light`**:
|
|
561
|
-
the page's color scheme. Put it on the `<html>` in `index.html`,
|
|
562
|
-
|
|
805
|
+
the page's color scheme. Put it on the `<html>` in `index.html`, where the first paint has it.
|
|
806
|
+
For a scheme the visitor switches, `Theme colorMode` writes the choice only after that paint,
|
|
807
|
+
so write a saved one before it too, as `html-script:theme` says and the bestax-theming skill's
|
|
808
|
+
`examples/dark-mode.tsx` does.
|
|
563
809
|
- **`html-document:lang`**, **`html-document:dir`**: set them on the `<html>` in `index.html`.
|
|
564
810
|
- **`html-document:class`**: the page's own classes on `<html>` or `<body>`. Put them on the
|
|
565
811
|
app's own `<body>` (or `<html>`), or on an element around the page's content if the styles
|
|
@@ -598,9 +844,51 @@ than `this`. A `<body onload>` becomes an effect.
|
|
|
598
844
|
- **`html-url:relative`**: `img/logo.png` resolved against the page's folder, and in the app it
|
|
599
845
|
resolves against the address the component renders at. The file is there beside the page, so
|
|
600
846
|
copy it into the app's `public/` folder and point at it from the site root (`/img/logo.png`), or
|
|
601
|
-
import it.
|
|
602
|
-
|
|
603
|
-
|
|
847
|
+
import it. Each relative URL in a `srcset` is its own entry, quoted as itself
|
|
848
|
+
(`` `hero@2x.png` in `srcset` ``). Several of these share one TODO line, and each is its own
|
|
849
|
+
report entry.
|
|
850
|
+
|
|
851
|
+
A link to another page beside this one should point at the route that page becomes: the
|
|
852
|
+
router's, in an app with one. A multi-page site of static pages, with no router to join, can do
|
|
853
|
+
its routing on the URL's hash in a small module of its own and install no router package, so
|
|
854
|
+
every page still opens from a static host as it is:
|
|
855
|
+
|
|
856
|
+
```ts
|
|
857
|
+
// router.ts: the page the address's hash names (`#/about`).
|
|
858
|
+
import { useEffect, useState } from 'react';
|
|
859
|
+
|
|
860
|
+
export const routes = { home: '#/', about: '#/about' } as const;
|
|
861
|
+
export type Route = keyof typeof routes;
|
|
862
|
+
|
|
863
|
+
function routeOf(hash: string): Route {
|
|
864
|
+
const found = (Object.keys(routes) as Route[]).find(
|
|
865
|
+
route => routes[route] === hash
|
|
866
|
+
);
|
|
867
|
+
return found ?? 'home';
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
export function useRoute(): Route {
|
|
871
|
+
const [route, setRoute] = useState(() => routeOf(window.location.hash));
|
|
872
|
+
useEffect(() => {
|
|
873
|
+
const onHashChange = () => {
|
|
874
|
+
const hash = window.location.hash;
|
|
875
|
+
// Only `#/…` (or no hash) names a page; leave an in-page anchor such
|
|
876
|
+
// as `#features`, or a placeholder `#`, to the browser.
|
|
877
|
+
if (hash !== '' && !hash.startsWith('#/')) return;
|
|
878
|
+
setRoute(routeOf(hash));
|
|
879
|
+
window.scrollTo(0, 0); // a new page starts at the top, as it did
|
|
880
|
+
};
|
|
881
|
+
window.addEventListener('hashchange', onHashChange);
|
|
882
|
+
return () => window.removeEventListener('hashchange', onHashChange);
|
|
883
|
+
}, []);
|
|
884
|
+
return route;
|
|
885
|
+
}
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
The app renders the page the route names, from the modules the pages became
|
|
889
|
+
(`const Page = { home: HomePage, about: AboutPage }[useRoute()]`), with the parts the pages
|
|
890
|
+
share around it, and a link to `about.html` takes `href={routes.about}`.
|
|
891
|
+
|
|
604
892
|
- **`html-url:missing`**: a relative URL whose target isn't beside the page, read the way the
|
|
605
893
|
browser read it, so it was a dead link or a missing file already. Point it somewhere real, or
|
|
606
894
|
drop it.
|
|
@@ -610,6 +898,12 @@ than `this`. A `<body onload>` becomes an effect.
|
|
|
610
898
|
- **`html-attr:name`**: an attribute JSX can't write (`@click`, `:class`, `x-on:click`), or one the
|
|
611
899
|
element already had under another spelling, was left out. A framework's directive is code to port
|
|
612
900
|
into the component.
|
|
901
|
+
- **`html-attr:stray`**: a stray character in a tag, with no letter or digit in it (`\` in
|
|
902
|
+
`<figure class="image" \>`, a typo for `/>`), which the browser read as the name of an empty
|
|
903
|
+
attribute. It was left out, so there is nothing to port; delete it from the page too.
|
|
904
|
+
- **`html-attr:ignored`**: an attribute HTML gives the element no meaning for, so the browser
|
|
905
|
+
ignored it, and React's types reject it there: `type` on a `<textarea>`. It was left out, so the
|
|
906
|
+
module typechecks. Nothing reads it, unless a stylesheet or script of the page's selects on it.
|
|
613
907
|
- **`html-attr:unknown`**: an attribute React has no prop for by that name, written as it was.
|
|
614
908
|
React renders it. Whether a TypeScript build takes it depends on the element (React's types
|
|
615
909
|
list `valign` on a `<td>` and not on a `<th>`), so the TODO doesn't say; what to do depends on
|
|
@@ -632,15 +926,22 @@ than `this`. A `<body onload>` becomes an effect.
|
|
|
632
926
|
|
|
633
927
|
The HTML has an error the browser repaired (`html-parse:duplicate-attribute`,
|
|
634
928
|
`html-parse:end-tag-without-matching-open-element`), reported once for each kind, with how many
|
|
635
|
-
more there are. The module follows the DOM the browser
|
|
636
|
-
markup meant, so check that part of the page. A code too
|
|
637
|
-
`html-parse`.
|
|
929
|
+
more there are, except a duplicate attribute (below). The module follows the DOM the browser
|
|
930
|
+
builds from it, which may not be what the markup meant, so check that part of the page. A code too
|
|
931
|
+
long for a rule id is reported as the bare `html-parse`.
|
|
932
|
+
|
|
933
|
+
A duplicate attribute on an element gets an entry of its own, naming the attribute, the copy the
|
|
934
|
+
element keeps (the first) and the one the browser drops (`placeholder="Email"` kept,
|
|
935
|
+
`placeholder="Your email"` dropped). The module has the kept one, so if the page meant the other,
|
|
936
|
+
change the value there. One the codemod can't name, such as one on an end tag, is counted with the
|
|
937
|
+
rest.
|
|
638
938
|
|
|
639
939
|
### The page itself: `html-file:<case>`
|
|
640
940
|
|
|
641
941
|
- **`html-file:exists`**: the module beside the page is already there, and the codemod never
|
|
642
|
-
writes over a file. That makes a second run change nothing.
|
|
643
|
-
the page
|
|
942
|
+
writes over a file. That makes a second run on the page change nothing. To carry on from the
|
|
943
|
+
module's TODOs, run the codemod on the module itself, which is where each TODO from the page
|
|
944
|
+
says to re-run ("re-run on `index.tsx`"). Move or delete the module to convert the page again.
|
|
644
945
|
- **`html-file:not-included`**: a folder walk found the page, and it has Bulma classes, but a walk
|
|
645
946
|
takes a page only when `--extensions` lists its extension, since most `.html` files in a React
|
|
646
947
|
project aren't pages to convert (Vite's `index.html`, `public/`). `-e` matches an extension
|
|
@@ -655,8 +956,15 @@ A page with no Bulma component class writes nothing and reports nothing.
|
|
|
655
956
|
|
|
656
957
|
- Helper classes on a `<div>` (`<div className="is-flex mt-4">`): bestax has no plain `<div>`
|
|
657
958
|
wrapper, and the classes are valid Bulma, so the element stays.
|
|
959
|
+
- Helper classes on a table's rows and cells (`<th className="has-text-centered">`): the codemod
|
|
960
|
+
converts the `.table` and leaves the `<thead>`, `<tbody>`, `<tfoot>`, `<tr>`, `<th>` and `<td>`
|
|
961
|
+
inside it as they are. To write them by hand, `Table.Thead`, `Table.Tbody`, `Table.Tfoot`,
|
|
962
|
+
`Table.Tr`, `Table.Th` and `Table.Td` render each tag as it is and take the helper props, and
|
|
963
|
+
`Table.Th` and `Table.Td` take `isAligned` for their alignment (`<Table.Td isAligned="right">`).
|
|
658
964
|
- `.help`, `.label`, `.loader` and the other classes in the component map's "left alone" list.
|
|
659
|
-
- A class with no bestax prop on a converted element: it stays in `className`.
|
|
965
|
+
- A class with no bestax prop on a converted element: it stays in `className`. That covers
|
|
966
|
+
v1's `marginless` and `paddingless`, which have the same rules as `m-0` and `p-0` under
|
|
967
|
+
other names, so they stay as written while the element converts on its other classes.
|
|
660
968
|
|
|
661
969
|
## After the codemod
|
|
662
970
|
|