create-bestax 4.2.17 → 4.2.19
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 -5
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/constants.d.ts +2 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +10 -2
- package/dist/display.d.ts +9 -0
- package/dist/display.d.ts.map +1 -1
- package/dist/display.js +19 -1
- package/dist/file-system.d.ts +21 -4
- package/dist/file-system.d.ts.map +1 -1
- package/dist/file-system.js +52 -6
- 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 +16 -1
- package/dist/project-creator.d.ts.map +1 -1
- package/dist/project-creator.js +39 -7
- package/dist/prompts.d.ts +1 -0
- package/dist/prompts.d.ts.map +1 -1
- package/dist/prompts.js +3 -2
- package/dist/validators.d.ts +8 -0
- package/dist/validators.d.ts.map +1 -1
- package/dist/validators.js +18 -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 +45 -16
- package/templates/skills/bestax-form/references/api.md +13 -8
- package/templates/skills/bestax-form/references/patterns.md +75 -3
- package/templates/skills/bestax-layout-scaffold/SKILL.md +34 -6
- 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 +34 -5
- package/templates/skills/bestax-migrate/references/bloomer/component-map.md +1 -1
- package/templates/skills/bestax-migrate/references/bloomer/prop-map.md +12 -9
- package/templates/skills/bestax-migrate/references/bulma-classes/component-map.md +153 -105
- package/templates/skills/bestax-migrate/references/bulma-classes/prop-map.md +48 -17
- package/templates/skills/bestax-migrate/references/bulma-classes/unmappables.md +501 -16
- package/templates/skills/bestax-migrate/references/css-migration.md +12 -1
- package/templates/skills/bestax-migrate/references/rbx/prop-map.md +23 -17
- 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 +5 -5
- package/templates/skills/bestax-optimize/references/modular-build.md +57 -15
- package/templates/skills/bestax-theming/SKILL.md +19 -8
- package/templates/skills/bestax-theming/examples/dark-mode.tsx +99 -17
- package/templates/skills/bestax-theming/examples/theme-config.tsx +13 -8
- package/templates/skills/bestax-theming/references/css-variables.md +231 -18
- package/templates/skills/bestax-theming/references/themeable-components.md +4 -0
- package/templates/vite/package.json +1 -1
- package/templates/vite/src/main.jsx +1 -1
- package/templates/vite-ts/package.json +1 -1
- package/templates/vite-ts/src/main.tsx +1 -1
|
@@ -36,9 +36,10 @@ color. Rename or drop the attribute, then re-run.
|
|
|
36
36
|
|
|
37
37
|
It also covers an attribute the component's props type rejects. `Delete` takes no `type`
|
|
38
38
|
(`type="button"` is the one value that converts, because `Delete` renders it anyway), and
|
|
39
|
-
`Progress` types `value` and `max` as numbers, so `value="half"` stays.
|
|
40
|
-
`
|
|
41
|
-
|
|
39
|
+
`Progress` types `value` and `max` as numbers, so `value="half"` stays. `InputBase` and
|
|
40
|
+
`TextAreaBase` type `maxLength` and `minLength` as numbers, and `TextAreaBase` `rows` and `cols`
|
|
41
|
+
too. Every component types `tabIndex` as a number, so `tabIndex="0"` converts as `tabIndex={0}`.
|
|
42
|
+
A number converts only when it is spelled the way it renders (`value="40"`, not `value="040"`).
|
|
42
43
|
|
|
43
44
|
`attr:dangerouslySetInnerHTML` is the same kind of refusal: the element sets its own content,
|
|
44
45
|
and some bestax components render content of their own beside `children`, which React
|
|
@@ -67,6 +68,17 @@ empty one, keeps the item as markup too, and so does an empty `className` on the
|
|
|
67
68
|
nothing is left to render its `class=""`. Move the attribute to where `Menu.Item` puts it if
|
|
68
69
|
that's what you want, then re-run.
|
|
69
70
|
|
|
71
|
+
`attr:role` on a `.menu-list` is a `role` other than `list`. `Menu.List` writes `role="list"` on
|
|
72
|
+
its `<ul>` whatever it's given, for Safari, which stops treating a list as one once its markers are
|
|
73
|
+
hidden, so that role would be lost. Keep the list as markup. One with no `role`, or `role="list"`,
|
|
74
|
+
converts, since that's the role a `<ul>` already has.
|
|
75
|
+
|
|
76
|
+
`attr:aria-current` is the `<a>`'s `is-active` with no `aria-current` beside it. `Menu.Item`'s
|
|
77
|
+
`active` writes `aria-current="page"` on the `<a>` unless it has one of its own, so the item would
|
|
78
|
+
gain it. If the item marks the page you're on, which is what `is-active` usually means in a menu,
|
|
79
|
+
add `aria-current="page"` to the `<a>` and re-run, and the item converts with it. If it marks
|
|
80
|
+
something else, keep the markup, or convert it by hand and pass the `aria-current` you want.
|
|
81
|
+
|
|
70
82
|
### `defaults:<Target>`
|
|
71
83
|
|
|
72
84
|
The component renders attributes of its own when the element doesn't set them. `Delete`
|
|
@@ -80,7 +92,29 @@ give the `<nav>` both, with your own label if you like. `Breadcrumb` renders
|
|
|
80
92
|
makes one named by `aria-label` or `aria-labelledby` an image, with `role="img"`. Give a decorative
|
|
81
93
|
`.icon` `aria-hidden="true"`, and a meaningful one an `aria-label` that says what it means and
|
|
82
94
|
`role="img"`. One whose name is an expression may render with no name, so it needs a `role` of its
|
|
83
|
-
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 in a link or
|
|
108
|
+
button that its `aria-label` or its text names is decoration there, so give it
|
|
109
|
+
`aria-hidden="true"`. One that is all a link or button shows names nothing a screen reader can
|
|
110
|
+
read: give the link or button an `aria-label` that says what it does, then hide the icon. The
|
|
111
|
+
`<svg class="svg-inline--fa">` Font Awesome's script draws in place of an `<i>` converts as
|
|
112
|
+
`Icon`'s children once its `.icon` is hidden, or write `Icon` with the glyph's `name` in its place,
|
|
113
|
+
which renders the `<i>` the script draws from. Inside a `.control` with `has-icons-left` or
|
|
114
|
+
`has-icons-right`, a hidden `.icon` can go instead, as that `Control`'s `iconLeft` or
|
|
115
|
+
`iconRight` (`iconLeft={{ library: "fa", name: "envelope", size: "small" }}`), which renders it
|
|
116
|
+
after the `Control`'s children. Each TODO says which of these applies, and what the icon converts
|
|
117
|
+
to.
|
|
84
118
|
`Pagination` renders Bulma's own `role="navigation"` and `aria-label="pagination"`, and
|
|
85
119
|
`Pagination.Previous`, `Pagination.Next` and `Pagination.Link` render `tabIndex={0}`, so give each
|
|
86
120
|
element the attribute it's missing.
|
|
@@ -139,6 +173,32 @@ or when what's inside is an expression or text, since `Image` renders an `<img>`
|
|
|
139
173
|
its children come out empty. Keep it as markup, or write the `Image` by hand if the expression
|
|
140
174
|
never is.
|
|
141
175
|
|
|
176
|
+
A `<label>` beside the `<select>` in a `.select` (a visually hidden one, say) is that case too,
|
|
177
|
+
since `SelectBase` renders no label. bestax's convenience `Select` takes it: the label's text as
|
|
178
|
+
`label` and its classes in `labelProps`, and it points the label at the `<select>`'s `id` itself.
|
|
179
|
+
A computed `className` on the label goes in `labelProps` as the same expression, since it may be
|
|
180
|
+
what hides the label, and so does what a spread on it carries. `Select` renders the `.select`
|
|
181
|
+
inside a `Field` and a `Control`, so convert the two by hand and check the layout:
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
<Select
|
|
185
|
+
id="language"
|
|
186
|
+
size="small"
|
|
187
|
+
label="Select language"
|
|
188
|
+
labelProps={{ className: 'is-sr-only' }}
|
|
189
|
+
>
|
|
190
|
+
<option>English</option>
|
|
191
|
+
<option>French</option>
|
|
192
|
+
</Select>
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
That holds only where the `.select` isn't inside a `.field` or a `.control` (or a `Field` or
|
|
196
|
+
`Control`). Inside a `Field`, `Select` renders no label of its own and drops `label` and
|
|
197
|
+
`labelProps`, so the select would lose its name; inside a bare `Control`, it puts its label's
|
|
198
|
+
`.field` inside the `.control`. There, keep the label the page's: move the `<label>` out beside
|
|
199
|
+
the `.select`, its `htmlFor` on the `<select>`'s `id`, or give the `<select>` an `aria-label` in
|
|
200
|
+
its place, then re-run, and the `.select` converts to `SelectBase`.
|
|
201
|
+
|
|
142
202
|
A menu item is the same from the `<li>`'s side: `Menu.Item` renders the `<a>` inside it, and a
|
|
143
203
|
`Menu.List` after that, so an item converts only when its `<li>` holds one `<a>` and at most one
|
|
144
204
|
`<ul>` after it, with nothing else beside them. Text or a comment beside the `<a>` keeps it as
|
|
@@ -152,13 +212,14 @@ element converts only holding exactly that (`…` or the character), and cl
|
|
|
152
212
|
|
|
153
213
|
On an `.icon-text`, `IconText` builds its icons from props and wraps each text in a `<span>` of
|
|
154
214
|
its own, so it converts only when its children are `.icon`s, each followed by at most one bare
|
|
155
|
-
`<span>` of static text. Each `.icon` has to convert to `Icon` on its own, so one with
|
|
156
|
-
`aria-label` gets a `defaults:Icon` TODO of its own first:
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
it
|
|
161
|
-
`
|
|
215
|
+
`<span>` of static text. Each `.icon` has to convert to `Icon` on its own, so one with neither
|
|
216
|
+
`aria-hidden` nor `aria-label` gets a `defaults:Icon` TODO of its own first: hide a decorative one,
|
|
217
|
+
or give a meaningful one a name, then re-run. Its `<i>` has to be empty, carry nothing but Font
|
|
218
|
+
Awesome's own `aria-hidden`, which moves up as it does on a `.icon` alone, and name one Font
|
|
219
|
+
Awesome or Material Design Icons glyph, so another attribute on the `<i>`, another icon font, or
|
|
220
|
+
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
|
|
221
|
+
`IconText` anyway, write it by hand with `iconProps={{ name: ... }}` (the `bestax-icons` skill
|
|
222
|
+
covers `Icon`'s library and name props).
|
|
162
223
|
|
|
163
224
|
On a `.file`, `File` renders the whole tree from props, so it converts only when its tree is the one
|
|
164
225
|
`File` renders: one bare `.file-label` `<label>` holding a `.file-input` `<input type="file">`, a
|
|
@@ -270,7 +331,28 @@ The classes in a computed `className` still count for every other rule: a `clsx(
|
|
|
270
331
|
`<span>` gets `tag:Box`, and a `clsx('dropdown', …)` gets `family:dropdown`. A computed
|
|
271
332
|
`className` on the `<select>` inside a `.select`, the `<ul>` inside a `.breadcrumb` or the `<a>`
|
|
272
333
|
in a menu item gets this TODO too. For the `<a>`, a condition on `is-active` is `Menu.Item`'s
|
|
273
|
-
`active`: `<a className={on ? 'is-active' : undefined}>` becomes `<Menu.Item active={on}
|
|
334
|
+
`active`: `<a className={on ? 'is-active' : undefined}>` becomes `<Menu.Item active={on}>`, which
|
|
335
|
+
also writes `aria-current="page"` while `on` holds. Pass an `aria-current` of your own if the item
|
|
336
|
+
marks something other than the current page.
|
|
337
|
+
|
|
338
|
+
## An element it converted: `second-component:<Target>`
|
|
339
|
+
|
|
340
|
+
The element carried a second Bulma component class (`<div className="columns box">`), and an
|
|
341
|
+
element converts to one component. It became the one whose component fits its tag best (the
|
|
342
|
+
tag it renders with the element's classes and no `as`, such as the `<figure>` an `.image`
|
|
343
|
+
ratio picks, then one it reaches through `as`), the layout one or a component's part between
|
|
344
|
+
equals, and the other class stayed in `className`, which renders the same. The TODO names the component that class belongs to. A raw component
|
|
345
|
+
class on a bestax component is what the ESLint plugin's `no-bulma-component-class` reports, so
|
|
346
|
+
move it to a component of its own:
|
|
347
|
+
|
|
348
|
+
- **Most classes**: give `<Target>` an element of its own, around the converted one or inside
|
|
349
|
+
it, and drop the class: `<Box><Columns>…</Columns></Box>`. Two elements space differently
|
|
350
|
+
from one (a `.columns` has negative side margins, which a `.box` on the same element shares
|
|
351
|
+
and one around it doesn't), so check the layout.
|
|
352
|
+
- **`second-component:Container`**: where `.container` is only there to center the element, as
|
|
353
|
+
it often is on a sized `.image`, write `mx="auto"` in its place
|
|
354
|
+
(`<Image size="128x128" mx="auto">`), which centers it and does nothing else `.container`
|
|
355
|
+
does. Otherwise wrap the element in a `Container`. Either way, check the layout.
|
|
274
356
|
|
|
275
357
|
## A family it leaves as markup: `family:<class>`
|
|
276
358
|
|
|
@@ -306,9 +388,9 @@ in the browser:
|
|
|
306
388
|
- **`family:message`**: `Message` always wraps its children in `.message-body`.
|
|
307
389
|
- **`family:panel-icon`**: `Panel.Icon` renders through `Icon`, which always writes an
|
|
308
390
|
`aria-label`, so write `<Panel.Icon>` by hand with the `<i>` inside. The rest of a panel converts,
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
391
|
+
a `<label>` or `<div>` `.panel-block` included, as `Panel.Block` with `as` and its contents as
|
|
392
|
+
written. `Panel.CheckboxBlock`, `Panel.InputBlock` and `Panel.ButtonBlock` build the usual
|
|
393
|
+
checkbox, search and button blocks from props, if you would rather write those by hand.
|
|
312
394
|
|
|
313
395
|
## A class Bulma v1 removed: `legacy:<class>`
|
|
314
396
|
|
|
@@ -316,6 +398,24 @@ in the browser:
|
|
|
316
398
|
0.9 to 1 guide shows the translation. Until then the element has no styles at all under
|
|
317
399
|
Bulma v1.
|
|
318
400
|
|
|
401
|
+
`legacy:is-marginless`, `legacy:is-paddingless`: v1 removed both, so they style nothing.
|
|
402
|
+
Wherever the element converts, the codemod writes them as `m="0"` and `p="0"`, which render
|
|
403
|
+
v1's `m-0` and `p-0`, and says nothing. The TODO comes only where the class stays: on an
|
|
404
|
+
element that stays markup (a `<div>` with no component class, or one refused for another
|
|
405
|
+
reason), or beside a class for the same prop (`p-2`, before it or after), which keeps the prop
|
|
406
|
+
since it's what the page renders today. Write `m-0` or `p-0` in its place, or drop it if the
|
|
407
|
+
spacing it once removed no longer matters.
|
|
408
|
+
|
|
409
|
+
## A class that styles nothing where it is: `modifier:<root>`
|
|
410
|
+
|
|
411
|
+
`modifier:image`: an `.image` size or ratio (`is-64x64`, `is-square`, `is-4by3`) on an element
|
|
412
|
+
without `.image`. Bulma styles them only on the element that carries `.image`, so this one
|
|
413
|
+
sizes nothing, unless the project's own CSS gives the class a rule. If the element is the
|
|
414
|
+
image's box, add `image`. On a tag `Image` renders (the component map's `.image` row lists
|
|
415
|
+
them), re-run and it can convert; on any other tag it stays markup, and the TODO says so.
|
|
416
|
+
Otherwise drop the class. A computed `className` the codemod can't read whole gets no such TODO, since a class it
|
|
417
|
+
can't see may be the `.image`.
|
|
418
|
+
|
|
319
419
|
## A whole file it left alone
|
|
320
420
|
|
|
321
421
|
These come only when the file has an element the codemod would convert (a computed className
|
|
@@ -338,12 +438,397 @@ alone: every other TODO names a React component to use.
|
|
|
338
438
|
another runtime (Preact, Solid), or a package that sets one in its tsconfig or depends on one
|
|
339
439
|
instead of React. bestax-bulma components are React components.
|
|
340
440
|
|
|
441
|
+
## A page converted from HTML: `html-*`
|
|
442
|
+
|
|
443
|
+
Run on an HTML page (`bestax-migrate bulma-classes page.html`, or a folder with `-e html`, or
|
|
444
|
+
`-e html,htm` to take `.htm` pages too), the
|
|
445
|
+
codemod writes a module beside the page and runs everything above on it, so a page gets the same
|
|
446
|
+
TODOs its markup would as JSX. What a component can't carry gets an `html-*` rule. TODOs about the
|
|
447
|
+
whole page sit above the component, the rest above its `return`, and each ends with the page and
|
|
448
|
+
the line it came from (`(index.html:42)`), or every line, for a TODO several elements share
|
|
449
|
+
(`(index.html:42, 57)`). The page itself stays as it was, so the code a TODO
|
|
450
|
+
points at is still there to read. A rule names only a tag, an attribute or a fixed word, never
|
|
451
|
+
anything the page says.
|
|
452
|
+
|
|
453
|
+
### The page's head: `html-head:<tag>`
|
|
454
|
+
|
|
455
|
+
A component renders into the `<body>` of the app's own document, so nothing in the page's
|
|
456
|
+
`<head>` comes with it.
|
|
457
|
+
|
|
458
|
+
- **`html-head:title`**: set the title where the app sets each page's title (its router's or
|
|
459
|
+
framework's head API). Under React 19 the component can render `<title>` itself and React moves
|
|
460
|
+
it into the head; React 18 leaves it in the body, so use `document.title` in an effect there.
|
|
461
|
+
- **`html-head:meta`**: `charset` and `viewport` go once in the app's `index.html`. A page's own
|
|
462
|
+
(a description, Open Graph tags) go where the app sets each page's head.
|
|
463
|
+
- **`html-head:csp`**: a `<meta http-equiv="Content-Security-Policy">`. Its policy was written for
|
|
464
|
+
what the page loads, and copied into `index.html` as it is, it can block what the app loads
|
|
465
|
+
instead: a Vite dev server runs an inline script for React's fast refresh and opens a socket for
|
|
466
|
+
hot reloading, and the build serves the app's own scripts, styles and fonts. Write the app's own
|
|
467
|
+
policy, best sent as a response header, and try it under both the dev server and the build.
|
|
468
|
+
- **`html-head:link`**: icons, preconnects and preloads are app-wide, so keep them in
|
|
469
|
+
`index.html`; a `canonical` is per page.
|
|
470
|
+
- **`html-head:style`**: the `<style>` block was dropped. Move its rules into the app's stylesheet.
|
|
471
|
+
- **`html-head:base`**: `<base href>` changed how the page's relative URLs resolved, and the app
|
|
472
|
+
has one document for every route. Make those URLs absolute instead (see `html-url:relative`).
|
|
473
|
+
- **`html-head`**: anything else in the head (a `<noscript>`, a `<template>`). Move it into
|
|
474
|
+
`index.html` if the app needs it.
|
|
475
|
+
|
|
476
|
+
### Stylesheets and scripts it loads: `html-asset:<kind>`
|
|
477
|
+
|
|
478
|
+
Each `<link rel="stylesheet">` and `<script src>`, by what its URL says it is. A component loads
|
|
479
|
+
neither, so load what the app still needs once for the whole app, from its entry module or
|
|
480
|
+
`index.html`. The TODO quotes the URL.
|
|
481
|
+
|
|
482
|
+
- **`html-asset:bulma`**: Bulma's own stylesheet, with the version its URL names
|
|
483
|
+
(`bulma@0.9.4`, or none for a copy of the page's own).
|
|
484
|
+
- Under the default `--css keep` it is only reported: keep loading Bulma
|
|
485
|
+
(`import 'bulma/css/bulma.min.css'` in the entry, with that version of `bulma` installed, or the
|
|
486
|
+
CDN `<link>` in `index.html`).
|
|
487
|
+
- Under `--css bestax` the module imports `@allxsmith/bestax-bulma/bestax.css` in the link's
|
|
488
|
+
place, and under `--css bulma` it imports `bulma/css/bulma.min.css` and
|
|
489
|
+
`@allxsmith/bestax-bulma/extras.css`, the way the same import in a JSX file is retargeted, so the
|
|
490
|
+
package.json step sees the module's `bulma` import too. One import from each page module is
|
|
491
|
+
fine, since the bundler loads it once. What is left gets the TODO: a page made for Bulma 0.9, or
|
|
492
|
+
one whose URL doesn't say, moves to Bulma 1 (the docs' Bulma 0.9 to 1 guide), and under
|
|
493
|
+
`--css bestax` a page with a primary color class (`is-primary`, `has-text-primary`) changes
|
|
494
|
+
color, since `bestax.css` builds Bulma with bestax's own primary. To keep it, set the
|
|
495
|
+
`--bulma-primary-*` variables as [css-migration.md](../css-migration.md) says, or use
|
|
496
|
+
`--css bulma`. A Bulma 1 page with no primary class gets the import and no TODO. A TypeScript
|
|
497
|
+
build resolves the import through the bundler's CSS types (Vite's `vite/client`), as it does
|
|
498
|
+
every stylesheet import.
|
|
499
|
+
- No import is written in a Next.js app, whose Pages Router takes a global stylesheet only in
|
|
500
|
+
`pages/_app`, nor for a link with a media query (`media="print"`), since an import applies to
|
|
501
|
+
every medium. The TODO says where it goes instead: the root layout or `pages/_app`, or a
|
|
502
|
+
`<link>` with the same `media` in `index.html`.
|
|
503
|
+
- One of Bulma's other builds (`bulma-no-dark-mode`, `bulma-prefixed`, 0.9's `bulma-rtl`) is
|
|
504
|
+
reported in every mode, since the codemod imports only the standard one. bestax's own builds,
|
|
505
|
+
Bulma with its extras, are under `@allxsmith/bestax-bulma/versions/`.
|
|
506
|
+
- **`html-asset:font-awesome`**: Font Awesome, with the major its URL names. bestax's `Icon`
|
|
507
|
+
writes its classes (`fas fa-<name>`, or the style its `variant` names) and loads no font of its
|
|
508
|
+
own, so keep loading it, from the
|
|
509
|
+
`<link>` in `index.html` or from npm: bestax-bulma's optional peer range for
|
|
510
|
+
`@fortawesome/fontawesome-free` is `^6.7.2 || ^7.0.0`, and an older one fails `npm install`
|
|
511
|
+
with `ERESOLVE`.
|
|
512
|
+
- 6 and 7: keep it as it is, or install it and import its `css/all.min.css` from the entry.
|
|
513
|
+
- 5: the CDN link keeps working, since 5 reads the classes `Icon` writes. From npm, take 6 or 7,
|
|
514
|
+
which still read 5's names.
|
|
515
|
+
- 4: its classes are `fa fa-<name>`. The codemod keeps that `fa` on each icon it converts
|
|
516
|
+
(`variant="fa"`), which 4 styles, but an `Icon` given no `variant` writes `fas fa-<name>`,
|
|
517
|
+
which 4 doesn't, so for the icons written from here on, install 6 or 7 with
|
|
518
|
+
`css/all.min.css`, then either import `css/v4-shims.min.css` beside it so
|
|
519
|
+
the page's 4 names keep working, or move them to the current names (`fa-envelope-o` is
|
|
520
|
+
`envelope` with `variant="regular"`).
|
|
521
|
+
- A kit (`kit.fontawesome.com`): keep loading it from `index.html`, or install Font Awesome from
|
|
522
|
+
npm instead. A URL with no version: the same, with the v4 shims beside it if the page's names
|
|
523
|
+
are 4's (`fa fa-<name>`).
|
|
524
|
+
- **`html-asset:bulma-extension`**: a `bulma-*` package (or `@creativebulma/bulma-*`). An
|
|
525
|
+
extension's stylesheet and script are one TODO, with both lines. Where bestax has a component
|
|
526
|
+
for what it does, the TODO names it; render that in place of the extension's markup and script,
|
|
527
|
+
whose styles ship in `extras.css` and `bestax.css`, and stop loading the extension once nothing
|
|
528
|
+
the app keeps uses its classes:
|
|
529
|
+
|
|
530
|
+
| Extension | bestax |
|
|
531
|
+
| ------------------------------------------------------- | -------------------------------------------------------------------------------------- |
|
|
532
|
+
| `bulma-carousel` | `Carousel`, with a `CarouselItem` for each slide and `itemsToShow` for several in view |
|
|
533
|
+
| `bulma-slider` | `Slider` |
|
|
534
|
+
| `bulma-switch` | `Switch` |
|
|
535
|
+
| `bulma-checkradio` | `Checkbox` and `Radio`, which draw their own box |
|
|
536
|
+
| `bulma-tooltip`, `@creativebulma/bulma-tooltip` | `Tooltip` |
|
|
537
|
+
| `bulma-badge`, `@creativebulma/bulma-badge` | `Badge` |
|
|
538
|
+
| `bulma-steps` | `Steps` |
|
|
539
|
+
| `bulma-timeline` | `Timeline` |
|
|
540
|
+
| `bulma-tagsinput`, `@creativebulma/bulma-tagsinput` | `Taginput` |
|
|
541
|
+
| `bulma-calendar` | `DateInput`, `TimeInput`, `DateTimeInput` and `DateRangeInput` |
|
|
542
|
+
| `bulma-accordion` | `Collapses`, with a `Collapse` for each item |
|
|
543
|
+
| `bulma-collapsible`, `@creativebulma/bulma-collapsible` | `Collapse` (`Collapses` for an accordion) |
|
|
544
|
+
| `bulma-pageloader` | `Loading`, `isFullPage` for one over the whole page |
|
|
545
|
+
| `bulma-quickview` | `Sidebar` |
|
|
546
|
+
| `bulma-toast` | `Toast`: `toast.show()` from code, with a `ToastContainer` once |
|
|
547
|
+
|
|
548
|
+
`bulma-extensions`, the bundle, holds several of these: replace the ones in the table, and keep
|
|
549
|
+
loading the bundle only for the rest. **bulma-social** has no bestax component: keep loading it,
|
|
550
|
+
since its classes (`is-twitter`, `is-github`) style Bulma's `.button`, which `Button` renders,
|
|
551
|
+
so they go on `Button` through `className`:
|
|
552
|
+
|
|
553
|
+
```tsx
|
|
554
|
+
<Button as="a" className="is-github" href="https://github.com/example">
|
|
555
|
+
<Icon name="github" variant="brands" />
|
|
556
|
+
</Button>
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Any other extension: keep loading it while the page's markup uses its classes, which go on
|
|
560
|
+
bestax's components through `className`, and under `--css bestax` or `--css bulma` check it
|
|
561
|
+
works with Bulma 1, which an extension can predate.
|
|
562
|
+
|
|
563
|
+
- **`html-asset:jquery`**: jQuery itself (a plugin such as jQuery UI is `html-asset:script`).
|
|
564
|
+
React renders the page now, so what the page's scripts did with jQuery (toggling classes,
|
|
565
|
+
handlers, showing and hiding) becomes state and event props; load jQuery only if a library the
|
|
566
|
+
app keeps still needs it.
|
|
567
|
+
- **`html-asset:webfont`**: a web font's stylesheet (Google Fonts, Bunny Fonts, Adobe Fonts).
|
|
568
|
+
Keep the `<link>` in `index.html` with its preconnects, or self-host the font and import it from
|
|
569
|
+
the entry. Google's Material Icons and Material Symbols are icon fonts, which `Icon` writes with
|
|
570
|
+
`library="material-icons"` or `library="material-symbols"`; keep the link, or install the
|
|
571
|
+
`material-icons` or `material-symbols` package.
|
|
572
|
+
- **`html-asset:stylesheet`**: any other stylesheet. The page's own, beside it (in its folder or
|
|
573
|
+
one below), is imported once for the app in the order the page loads it, so its rules still win
|
|
574
|
+
over Bulma's where they did (a module beside the page imports `css/styles.css` as
|
|
575
|
+
`./css/styles.css`), or its rules move into the app's stylesheet. For one that isn't in the
|
|
576
|
+
page's folder, the TODO says only that: the page's `<base href>`, if it has one, may have loaded
|
|
577
|
+
it from somewhere else, so find the one it meant, or drop it.
|
|
578
|
+
- **`html-asset:script`**: any other script. The component runs none: load a library the app still
|
|
579
|
+
needs in `index.html` (or install it), and port what the page's own scripts did into the
|
|
580
|
+
component. A script of the page's own, beside it, is read the way an inline script is, so one
|
|
581
|
+
that toggles the burger, drives a carousel or switches the theme gets that `html-script:<pattern>`
|
|
582
|
+
TODO instead, quoting the file. One a `../` reaches outside the page's folder isn't read. A
|
|
583
|
+
`<script src>` of a type a browser loads nothing for (`text/template`, `application/json`) isn't
|
|
584
|
+
code: it gets the `html-script` TODO for data (`html-script:json-ld` for JSON-LD), naming its
|
|
585
|
+
file.
|
|
586
|
+
|
|
587
|
+
### Inline scripts: `html-script:<pattern>`
|
|
588
|
+
|
|
589
|
+
Every inline `<script>` is dropped, and its TODO gives the lines in the page where its code still
|
|
590
|
+
is. One that does something bestax has a component for gets that pattern's rule, and a script
|
|
591
|
+
can get more than one. A script of the page's own, beside it (`<script src="js/scripts.js">`), is
|
|
592
|
+
read for the burger, a carousel and a theme toggle too, and its TODO names the file:
|
|
593
|
+
|
|
594
|
+
- **`html-script:burger`** toggles the navbar burger (`.navbar-burger`, or the `.burger` class
|
|
595
|
+
Bulma 0.x's docs put beside it). Keep the open state in `useState` and pass it to
|
|
596
|
+
`Navbar.Burger` and `Navbar.Menu` (the `family:navbar-burger` TODO on the burger says why the
|
|
597
|
+
markup stays):
|
|
598
|
+
|
|
599
|
+
```tsx
|
|
600
|
+
function SiteNavbar() {
|
|
601
|
+
const [open, setOpen] = useState(false);
|
|
602
|
+
return (
|
|
603
|
+
<Navbar role="navigation" aria-label="main navigation">
|
|
604
|
+
<Navbar.Brand>
|
|
605
|
+
<Navbar.Item href="/">Home</Navbar.Item>
|
|
606
|
+
<Navbar.Burger
|
|
607
|
+
active={open}
|
|
608
|
+
onClick={() => setOpen(!open)}
|
|
609
|
+
aria-label="menu"
|
|
610
|
+
/>
|
|
611
|
+
</Navbar.Brand>
|
|
612
|
+
<Navbar.Menu active={open}>
|
|
613
|
+
<Navbar.Start>
|
|
614
|
+
<Navbar.Item href="/docs">Docs</Navbar.Item>
|
|
615
|
+
</Navbar.Start>
|
|
616
|
+
</Navbar.Menu>
|
|
617
|
+
</Navbar>
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
- **`html-script:modal`** opens or closes a modal. `Modal` shows while `active` is true and calls
|
|
623
|
+
`onClose` from its background, its close button and Escape, so keep the open state in
|
|
624
|
+
`useState` (the `family:modal` TODO covers rebuilding the markup).
|
|
625
|
+
- **`html-script:dismiss`** removes an element when its `.delete` is clicked. `Notification`
|
|
626
|
+
takes `hasDelete` and `onDelete`, `Tag` takes `onDelete` and `Message` takes `onClose`; render
|
|
627
|
+
the element only while it's in state.
|
|
628
|
+
- **`html-script:carousel`** drives a carousel. `Carousel` takes its slides as `CarouselItem`
|
|
629
|
+
children and renders its own arrows and indicators (`autoplay` for a timed one). For several
|
|
630
|
+
slides in view, set `itemsToShow`, with a variant per viewport (`itemsToShowMobile`,
|
|
631
|
+
`itemsToShowTablet`, …), and `itemsToScroll`: bulma-carousel calls them `slidesToShow` and
|
|
632
|
+
`slidesToScroll`. bulma-carousel's `breakpoints` replace both at and below pixel widths of its
|
|
633
|
+
own (each entry's `changePoint`), and a page that sets none gets its defaults: 1 slide up to
|
|
634
|
+
480px, 2 up to 640px and 3 up to 768px, each scrolling as many, so `slidesToShow` applies only
|
|
635
|
+
from 769px up. Below that the defaults decide whatever `slidesToShow` says: a phone shows 1
|
|
636
|
+
slide, and a page that sets `slidesToShow: 1` shows 2 or 3 between a phone's width and a
|
|
637
|
+
tablet's. A page's own `breakpoints` replace the defaults, and an empty list turns them off.
|
|
638
|
+
`Carousel` has no pixel widths: `itemsToShowMobile` covers every width below 769px, where all
|
|
639
|
+
of those defaults sit, and the wider variants start at Bulma's breakpoints. So set
|
|
640
|
+
`itemsToShow` to the page's `slidesToShow`, and `itemsToShowMobile` to what the page shows on
|
|
641
|
+
a phone (1 under the defaults) where that differs; one `itemsToScroll` covers every width. To
|
|
642
|
+
keep the steps bulma-carousel takes between those widths, compute `itemsToShow` from the
|
|
643
|
+
window's width in your own code. `Carousel` loops unless `repeat={false}`, while
|
|
644
|
+
bulma-carousel stops at the ends unless `loop` (back to the start) or `infinite` (round
|
|
645
|
+
without a break) is set, so a carousel with neither takes `repeat={false}`. Its styles ship in
|
|
646
|
+
bestax's `extras.css` and `bestax.css`, not in Bulma's stylesheet.
|
|
647
|
+
- **`html-script:theme`** switches Bulma's light and dark schemes. The toggle is `Theme`'s: it
|
|
648
|
+
writes `data-theme` on `<html>` from its `colorMode` (`light`, `dark` or `system`), so keep the
|
|
649
|
+
choice in state, save it in `localStorage`, and pass it. The first paint is `index.html`'s:
|
|
650
|
+
`Theme` writes from an effect, after the first paint, so a visitor whose saved choice differs
|
|
651
|
+
from their OS sees the OS's scheme first. A small inline script in the `<head>` of `index.html`
|
|
652
|
+
that reads the saved choice (or the OS's, with none saved) and writes `data-theme` before the
|
|
653
|
+
app loads paints the right one, and the toggle's state starts from what it wrote. The
|
|
654
|
+
bestax-theming skill covers `Theme` and `colorMode`, and its `examples/dark-mode.tsx` has the
|
|
655
|
+
script and the app's side.
|
|
656
|
+
- **`html-script:json-ld`** is structured data for search engines. Data about the whole site, or
|
|
657
|
+
about a single-page app's one page, goes in the app's `index.html` as it is, where a crawler that
|
|
658
|
+
runs no JavaScript still reads it. Data that differs from page to page goes where the app sets
|
|
659
|
+
each page's head, as
|
|
660
|
+
`<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }} />`.
|
|
661
|
+
- **`html-script`**: any other inline script, or a `<script type>` that isn't code (a template,
|
|
662
|
+
JSON data). Port what it does into the component as state, effects and event handlers.
|
|
663
|
+
|
|
664
|
+
### `<html>` and `<body>`: `html-document:<name>`
|
|
665
|
+
|
|
666
|
+
The app's document has its own `<html>` and `<body>`, which a component can't reach.
|
|
667
|
+
|
|
668
|
+
- **`html-document:has-navbar-fixed-top`**, and the same for `has-navbar-fixed-bottom`,
|
|
669
|
+
`has-navbar-fixed-top-desktop`, `has-navbar-fixed-top-touch`, `has-navbar-fixed-bottom-desktop`,
|
|
670
|
+
`has-navbar-fixed-bottom-touch`, `has-spaced-navbar-fixed-top` and
|
|
671
|
+
`has-spaced-navbar-fixed-bottom` (`html-document:has-navbar-fixed-bottom` and so on): Bulma
|
|
672
|
+
pads the page for a fixed navbar from it. Put the class on the `<html>` in `index.html`, since
|
|
673
|
+
bestax's `Navbar` adds none there, whatever its `fixed` says.
|
|
674
|
+
- **`html-document:data-theme`**, **`html-document:theme-dark`**, **`html-document:theme-light`**:
|
|
675
|
+
the page's color scheme. Put it on the `<html>` in `index.html`, where the first paint has it.
|
|
676
|
+
For a scheme the visitor switches, `Theme colorMode` writes the choice only after that paint,
|
|
677
|
+
so write a saved one before it too, as `html-script:theme` says and the bestax-theming skill's
|
|
678
|
+
`examples/dark-mode.tsx` does.
|
|
679
|
+
- **`html-document:lang`**, **`html-document:dir`**: set them on the `<html>` in `index.html`.
|
|
680
|
+
- **`html-document:class`**: the page's own classes on `<html>` or `<body>`. Put them on the
|
|
681
|
+
app's own `<body>` (or `<html>`), or on an element around the page's content if the styles
|
|
682
|
+
allow it.
|
|
683
|
+
- **`html-document:id`**, **`html-document:style`**, **`html-document`**: any other attribute
|
|
684
|
+
there, which moves the same way.
|
|
685
|
+
|
|
686
|
+
### Event handlers: `html-event:<attribute>`
|
|
687
|
+
|
|
688
|
+
An `onclick="…"` and its kind, on any element or on `<body>` (`onload`). React takes a function,
|
|
689
|
+
not code in a string, so the attribute was dropped; the TODO quotes the code and names the prop
|
|
690
|
+
that takes it (`onClick`). Port the code into a handler, reading the element from the event rather
|
|
691
|
+
than `this`. A `<body onload>` becomes an effect.
|
|
692
|
+
|
|
693
|
+
### Elements: `html-element:<kind>`
|
|
694
|
+
|
|
695
|
+
- **`html-element:custom`**: a custom element (`<my-widget>`) renders as written, but the script
|
|
696
|
+
that defines it isn't loaded by the module: import its definition in the app. A TypeScript
|
|
697
|
+
build also needs the tag declared in `JSX.IntrinsicElements`.
|
|
698
|
+
- **`html-element:obsolete`**: `<center>`, `<font>`, `<marquee>` and their kind still render, but
|
|
699
|
+
React's types list few of them. Replace each with current markup (`has-text-centered` for
|
|
700
|
+
`<center>`, a class for `<font>`).
|
|
701
|
+
- **`html-element:unknown`**: a tag that isn't HTML renders as an unknown inline element, and
|
|
702
|
+
TypeScript rejects it. Replace it with the element it stands for.
|
|
703
|
+
- **`html-element:template`**: `<template>` holds markup for a script to clone. Render that
|
|
704
|
+
markup from the component where the script used it.
|
|
705
|
+
- **`html-element:name`**: a tag JSX can't write (`<o:p>`, from Word), so its children were
|
|
706
|
+
written in its place. Put back the element it stood for, if it mattered.
|
|
707
|
+
- **`html-element:conditional-comment`**: an Internet Explorer conditional comment was dropped;
|
|
708
|
+
no browser React supports reads one.
|
|
709
|
+
|
|
710
|
+
### URLs: `html-url:<kind>`
|
|
711
|
+
|
|
712
|
+
- **`html-url:javascript`**: a `javascript:` URL won't run (React 19 replaces it with one that
|
|
713
|
+
throws, and React 18 warns). Move the code into an `onClick` handler.
|
|
714
|
+
- **`html-url:relative`**: `img/logo.png` resolved against the page's folder, and in the app it
|
|
715
|
+
resolves against the address the component renders at. The file is there beside the page, so
|
|
716
|
+
copy it into the app's `public/` folder and point at it from the site root (`/img/logo.png`), or
|
|
717
|
+
import it. Each relative URL in a `srcset` is its own entry, quoted as itself
|
|
718
|
+
(`` `hero@2x.png` in `srcset` ``). Several of these share one TODO line, and each is its own
|
|
719
|
+
report entry.
|
|
720
|
+
|
|
721
|
+
A link to another page beside this one should point at the route that page becomes: the
|
|
722
|
+
router's, in an app with one. A site of static pages, with no router to join, can route on the
|
|
723
|
+
URL's hash in a small module of its own and install no router package, so every page still
|
|
724
|
+
opens from a static host as it is:
|
|
725
|
+
|
|
726
|
+
```ts
|
|
727
|
+
// router.ts: the page the address's hash names (`#/about`).
|
|
728
|
+
import { useEffect, useState } from 'react';
|
|
729
|
+
|
|
730
|
+
export const routes = { home: '#/', about: '#/about' } as const;
|
|
731
|
+
export type Route = keyof typeof routes;
|
|
732
|
+
|
|
733
|
+
function routeOf(hash: string): Route {
|
|
734
|
+
const found = (Object.keys(routes) as Route[]).find(
|
|
735
|
+
route => routes[route] === hash
|
|
736
|
+
);
|
|
737
|
+
return found ?? 'home';
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
export function useRoute(): Route {
|
|
741
|
+
const [route, setRoute] = useState(() => routeOf(window.location.hash));
|
|
742
|
+
useEffect(() => {
|
|
743
|
+
const onHashChange = () => {
|
|
744
|
+
const hash = window.location.hash;
|
|
745
|
+
// Only `#/…` (or no hash) names a page; leave an in-page anchor such
|
|
746
|
+
// as `#features`, or a placeholder `#`, to the browser.
|
|
747
|
+
if (hash !== '' && !hash.startsWith('#/')) return;
|
|
748
|
+
setRoute(routeOf(hash));
|
|
749
|
+
window.scrollTo(0, 0); // a new page starts at the top, as it did
|
|
750
|
+
};
|
|
751
|
+
window.addEventListener('hashchange', onHashChange);
|
|
752
|
+
return () => window.removeEventListener('hashchange', onHashChange);
|
|
753
|
+
}, []);
|
|
754
|
+
return route;
|
|
755
|
+
}
|
|
756
|
+
```
|
|
757
|
+
|
|
758
|
+
The app renders the page the route names, from the modules the pages became
|
|
759
|
+
(`const Page = { home: HomePage, about: AboutPage }[useRoute()]`), with the parts the pages
|
|
760
|
+
share around it, and a link to `about.html` takes `href={routes.about}`.
|
|
761
|
+
|
|
762
|
+
- **`html-url:missing`**: a relative URL whose target isn't beside the page, read the way the
|
|
763
|
+
browser read it, so it was a dead link or a missing file already. Point it somewhere real, or
|
|
764
|
+
drop it.
|
|
765
|
+
|
|
766
|
+
### Attributes: `html-attr:<kind>`
|
|
767
|
+
|
|
768
|
+
- **`html-attr:name`**: an attribute JSX can't write (`@click`, `:class`, `x-on:click`), or one the
|
|
769
|
+
element already had under another spelling, was left out. A framework's directive is code to port
|
|
770
|
+
into the component.
|
|
771
|
+
- **`html-attr:stray`**: a stray character in a tag, with no letter or digit in it (`\` in
|
|
772
|
+
`<figure class="image" \>`, a typo for `/>`), which the browser read as the name of an empty
|
|
773
|
+
attribute. It was left out, so there is nothing to port; delete it from the page too.
|
|
774
|
+
- **`html-attr:ignored`**: an attribute HTML gives the element no meaning for, so the browser
|
|
775
|
+
ignored it, and React's types reject it there: `type` on a `<textarea>`. It was left out, so the
|
|
776
|
+
module typechecks. Nothing reads it, unless a stylesheet or script of the page's selects on it.
|
|
777
|
+
- **`html-attr:unknown`**: an attribute React has no prop for by that name, written as it was.
|
|
778
|
+
React renders it. Whether a TypeScript build takes it depends on the element (React's types
|
|
779
|
+
list `valign` on a `<td>` and not on a `<th>`), so the TODO doesn't say; what to do depends on
|
|
780
|
+
the attribute, and the TODO says which:
|
|
781
|
+
- React's own prop in the wrong case (`defaultvalue`, `defaultchecked`), which the page never
|
|
782
|
+
read since it isn't HTML: rename it to the prop (`defaultValue`), or drop it if it isn't
|
|
783
|
+
meant.
|
|
784
|
+
- An obsolete presentational attribute (`valign`, `bgcolor`, `nowrap`), which CSS replaced:
|
|
785
|
+
write it as CSS or a class.
|
|
786
|
+
- Anything else: drop it if nothing reads it, make it a `data-` attribute if a script of the
|
|
787
|
+
page's reads it, and if React's types don't list it on that element, declare it for a
|
|
788
|
+
TypeScript build.
|
|
789
|
+
- **`html-attr:style`**: a `style` declaration a browser can't read (`*zoom: 1`) was left out, as a
|
|
790
|
+
browser leaves it out. Delete it, or rewrite it if it meant something.
|
|
791
|
+
- **`html-attr:important`**: React sets a style without a priority, so the declaration is written
|
|
792
|
+
without its `!important`. If a stylesheet rule beats it now, move it into a class in the app's
|
|
793
|
+
stylesheet.
|
|
794
|
+
|
|
795
|
+
### Parse errors: `html-parse:<code>`
|
|
796
|
+
|
|
797
|
+
The HTML has an error the browser repaired (`html-parse:duplicate-attribute`,
|
|
798
|
+
`html-parse:end-tag-without-matching-open-element`), reported once for each kind, with how many
|
|
799
|
+
more there are, except a duplicate attribute (below). The module follows the DOM the browser
|
|
800
|
+
builds from it, which may not be what the markup meant, so check that part of the page. A code too
|
|
801
|
+
long for a rule id is reported as the bare `html-parse`.
|
|
802
|
+
|
|
803
|
+
A duplicate attribute on an element gets an entry of its own, naming the attribute, the copy the
|
|
804
|
+
element keeps (the first) and the one the browser drops (`placeholder="Email"` kept,
|
|
805
|
+
`placeholder="Your email"` dropped). The module has the kept one, so if the page meant the other,
|
|
806
|
+
change the value there. One the codemod can't name, such as one on an end tag, is counted with the
|
|
807
|
+
rest.
|
|
808
|
+
|
|
809
|
+
### The page itself: `html-file:<case>`
|
|
810
|
+
|
|
811
|
+
- **`html-file:exists`**: the module beside the page is already there, and the codemod never
|
|
812
|
+
writes over a file. That makes a second run change nothing. Move or delete the module to convert
|
|
813
|
+
the page again.
|
|
814
|
+
- **`html-file:not-included`**: a folder walk found the page, and it has Bulma classes, but a walk
|
|
815
|
+
takes a page only when `--extensions` lists its extension, since most `.html` files in a React
|
|
816
|
+
project aren't pages to convert (Vite's `index.html`, `public/`). `-e` matches an extension
|
|
817
|
+
exactly, as it does for every file, so `-e html` takes no `.htm` page; the TODO names the one
|
|
818
|
+
the page needs. Name the page, or add its extension to `--extensions` (`-e html,htm` for both).
|
|
819
|
+
- **`html-file:template-syntax`**: the page is a server template (`{{`, `{%`, `<?php`, `<%`), which
|
|
820
|
+
isn't HTML a browser reads as written. Convert the HTML it renders, or the template by hand.
|
|
821
|
+
|
|
822
|
+
A page with no Bulma component class writes nothing and reports nothing.
|
|
823
|
+
|
|
341
824
|
## Things that get no TODO
|
|
342
825
|
|
|
343
826
|
- Helper classes on a `<div>` (`<div className="is-flex mt-4">`): bestax has no plain `<div>`
|
|
344
827
|
wrapper, and the classes are valid Bulma, so the element stays.
|
|
345
828
|
- `.help`, `.label`, `.loader` and the other classes in the component map's "left alone" list.
|
|
346
|
-
- A class with no bestax prop on a converted element: it stays in `className`.
|
|
829
|
+
- A class with no bestax prop on a converted element: it stays in `className`. That covers
|
|
830
|
+
v1's `marginless` and `paddingless`, which have the same rules as `m-0` and `p-0` under
|
|
831
|
+
other names, so they stay as written while the element converts on its other classes.
|
|
347
832
|
|
|
348
833
|
## After the codemod
|
|
349
834
|
|
|
@@ -26,7 +26,18 @@ choice below applies.
|
|
|
26
26
|
**Visual note**: `bestax.css` ships with `$primary` set to bestax blue (`#1e6b99`),
|
|
27
27
|
not Bulma's stock turquoise — `is-primary` surfaces (hero, navbar, buttons) change
|
|
28
28
|
color. Keep the stock Bulma look with `--css bulma`, or set your own brand color via
|
|
29
|
-
`--bulma-primary-*` CSS variables / a Sass build.
|
|
29
|
+
`--bulma-primary-*` CSS variables / a Sass build. With the variables, set
|
|
30
|
+
`--bulma-primary-invert-l` and `--bulma-primary-on-scheme-l` along with `--bulma-primary-h`,
|
|
31
|
+
`--bulma-primary-s` and `--bulma-primary-l`. The first is the lightness of the label on a
|
|
32
|
+
primary surface and the second of primary text on the page, and bestax's build fixes both for
|
|
33
|
+
its dark blue, so a light primary set through the trio alone keeps white labels and pale text.
|
|
34
|
+
To get stock Bulma's turquoise back on top of `bestax.css`, copy those five from Bulma's own
|
|
35
|
+
`bulma/css/bulma.css`. The on-scheme lightness differs between its light and dark schemes, so
|
|
36
|
+
set each scheme's value where the app shows both; the `bestax-theming` skill's
|
|
37
|
+
`references/css-variables.md` ("The lightnesses Bulma's build picks for contrast") shows how,
|
|
38
|
+
and what reads each one. Text the page colors with `has-text-primary` converts to
|
|
39
|
+
`textColor="primary"`, which reads the trio's own lightness, under 2:1 on white for turquoise
|
|
40
|
+
(in stock Bulma too); add `colorShade="on-scheme"` to take the shade made for text.
|
|
30
41
|
|
|
31
42
|
- **SCSS files**: Bulma 0.9's `@import 'bulma/bulma.sass'` (plus preceding
|
|
32
43
|
`$var: value !default;` overrides) became Bulma v1 module syntax, with simple literal
|