@bettercms-ai/convert 0.8.0 → 0.10.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/CHANGELOG.md CHANGED
@@ -1,5 +1,56 @@
1
1
  # @bettercms-ai/convert
2
2
 
3
+ ## 0.10.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ac3a9ff: Declare the shapes the derive lane mints for every visible body tag: a heading whose styled run is
8
+ part of its value (`richtext inline`, bound whole rather than wrapped around its text node), a
9
+ standalone `span`/`time`/`small`/`label`/`option` leaf, a `<pre>` code block (the `<pre>` is the
10
+ field, not the `<code>` inside it), and a group row whose optional leaf is empty (covered by its
11
+ own route's templated declaration instead of reported `NO_ORIGINAL`). A heading split by a `<br />`
12
+ is found again: its value carries no space, because no text node holds one.
13
+
14
+ An inline heading the lane cannot own whole — its element holds a component, a `<slot>` or an
15
+ expression, which no stored string can re-emit — is refused by name (`SUBTREE_NOT_HTML`) instead of
16
+ being bound over the top of it.
17
+
18
+ New `--xray <dist-dir>` mode: how much of each built page's visible copy no binding owns, and the
19
+ biggest buckets of it, so the loop is build -> measure -> fix -> build with no deploy in it.
20
+
21
+ ## 0.9.0
22
+
23
+ ### Minor Changes
24
+
25
+ - 94a00c3: `--forms`: point an imported site's own `<form>` at the CMS form behind it.
26
+
27
+ After an import the release hook derives a draft form row per `<form>` in the built site, so the
28
+ Forms tab fills up while the repository's markup still posts wherever it always did — to nothing,
29
+ or to somebody else's endpoint. Nothing joined the two halves, because the id that does is the
30
+ platform's and lives in the brief.
31
+
32
+ `npx @bettercms-ai/convert --forms --brief brief.json --root . --receipt receipt.json` reads the
33
+ brief's new `forms` array and writes, in one `magic-string` pass: `action`, `method`,
34
+ `data-bcms-form`, `data-bcms-form-success`, a `data-bcms-form-field` per field (on the control's
35
+ wrapper where it has one), the CMS key as each control's `name`, the `<p class="bcms-form-msg">`
36
+ the runtime writes into, and the submit script — the same bytes the hosted renderer ships, held
37
+ byte-for-byte by a test, because the `cf-turnstile-response` hoist in the middle of it is what
38
+ keeps enabling Turnstile from 403ing every submission.
39
+
40
+ The match is strict: a `<form>` is the CMS form's only when the names its controls post cover
41
+ every field key, and exactly one `<form>` answers. Everything else is receipted by name —
42
+ `FORM_NOT_IN_SOURCE`, `FORM_AMBIGUOUS`, `FIELD_UNMATCHED`, `ACTION_IS_EXPRESSION`,
43
+ `DIALECT_UNSUPPORTED`, `PARSE_ERROR` — because a form wired to the wrong id sends a customer's
44
+ leads into another form's inbox, silently, forever. A form already carrying `data-bcms-form` is
45
+ `alreadyWired`, so a second run writes nothing.
46
+
47
+ The receipt rides on `ConversionReceipt.forms` and claims no brief path, so
48
+ `submit_conversion_receipt` takes it unchanged. A form the brief lists as a DRAFT is wired AND
49
+ noted: it rejects every submission with a 403 until somebody publishes it in the Forms tab.
50
+
51
+ Also: `--version` now reports the package's real version. The constant had been stale at `0.4.0`
52
+ for four releases.
53
+
3
54
  ## 0.8.0
4
55
 
5
56
  ### Minor Changes
package/README.md CHANGED
@@ -38,6 +38,27 @@ Exit codes: `0` done — the pending list is printed, not hidden; `1` something
38
38
  | `--strict` | exit 2 when any path is pending. |
39
39
  | `--overwrite-helper` | replace a `bcms-content` helper whose bytes this tool did not write — including one of ours that has since been edited. |
40
40
  | `--verbose` | stack traces, and every file considered. |
41
+ | `--xray <dist-dir>` | a mode of its own: measure a LOCAL build instead of converting one. |
42
+
43
+ ### `--xray` — what is not editable
44
+
45
+ A receipt says what the codemod bound. It cannot say what it was never asked to bind, so a site can
46
+ report full coverage while a quarter of its visible text is unreachable from the editor. `--xray`
47
+ walks a build and counts that, per page, with no deploy in the loop:
48
+
49
+ ```bash
50
+ npm run build && npx @bettercms-ai/convert --xray dist
51
+ ```
52
+
53
+ ```
54
+ docs/index.html visible=3512 unaddressable=701 (20.0%)
55
+ 379ch 4n code @ main e.g. "const site = { direction: 'rtl', language: 'ar'," | "npm install"
56
+ 188ch 12n span @ main>ul e.g. "Performance" | "100"
57
+ ```
58
+
59
+ Glyphs, ordinals, the platform badge and skip links are excluded from BOTH halves of the ratio —
60
+ counting them would put a floor under every route that no amount of binding could lift. `--strict`
61
+ exits 2 while any page is above 2 %. It takes no `--brief`: it measures, it does not convert.
41
62
 
42
63
  ## What it actually does
43
64
 
@@ -152,6 +173,8 @@ rendering that binding — `<img>`, `<source>`, `<video poster>`, or `<Image>`/`
152
173
  different paths share a sentence and position cannot separate them (both are skipped; the rest of
153
174
  the file still converts), `SUBSTRING_ONLY`, `IN_SCRIPT_OR_COMMENT`, `KIND_MISMATCH`,
154
175
  `REPEATER_AMBIGUOUS` (one array declaration, two loops over it — the row has two homes),
176
+ `SUBTREE_NOT_HTML` (an INLINE richtext heading whose element holds a component, a `<slot>` or an
177
+ expression: its whole subtree is the value and no stored string can re-emit that),
155
178
  `IMAGE_ASSET_UNRESOLVED`, `PARSE_ERROR`. `NOT_IN_SOURCE` is reserved for what it says: a path
156
179
  `locate` found in a file is `IN_EXPRESSION` when it sits in the module region or an expression
157
180
  node, and where `NOT_IN_SOURCE` is still the answer the row names the file it was found in. And
@@ -520,6 +543,48 @@ the now-unused `bcms`/snapshot imports P2 added, and a page whose registered cal
520
543
  `<Sections>` keeps the imports of the components it used to call. They are harmless at build time
521
544
  and removing them would mean editing statements no section asked about.
522
545
 
546
+ ## Forms
547
+
548
+ The third mode, and the shortest. The release-time derive lane reads every `<form>` in the built
549
+ site and creates a DRAFT form per distinct shape, so the Forms tab fills on import while the
550
+ repository's own markup goes on posting wherever it always did. `--forms` joins the two halves.
551
+
552
+ ```bash
553
+ # after the import; the brief carries the project's forms
554
+ npx @bettercms-ai/convert --forms --brief brief.json --root . --receipt forms-receipt.json
555
+ git diff
556
+ ```
557
+
558
+ ```
559
+ modify src/pages/contact.astro
560
+
561
+ 1 forms wired (0 already wired, 0 pending)
562
+ todo publish form Contact in the Forms tab — a draft form rejects every submission with 403.
563
+ ```
564
+
565
+ It writes six things onto a matched `<form>` and nothing else: `action="<submitUrl>"`,
566
+ `method="post"`, `data-bcms-form="<id>"` (plus `data-bcms-form-success` when the CMS form has a
567
+ success message), `data-bcms-form-field="<key>"` on each matched control, a
568
+ `<p class="bcms-form-msg" hidden>` before `</form>` when there is none, and the submit script once
569
+ per file — the same bytes the hosted renderer ships, pinned by a test. No helper, no snapshot, no
570
+ import: a form posts to an absolute URL at runtime, so there is nothing to read at build time.
571
+
572
+ The match is the FIELD KEYS: a `<form>` is a CMS form's only when the names its controls post are a
573
+ superset of that form's field keys and exactly one `<form>` answers. Everything else is pending with
574
+ a reason — `FORM_NOT_IN_SOURCE`, `FORM_AMBIGUOUS`, `FIELD_UNMATCHED`, `ACTION_IS_EXPRESSION`,
575
+ `DIALECT_UNSUPPORTED`, `PARSE_ERROR` — because a form wired to the wrong id sends the customer's
576
+ leads into another form's inbox, silently, forever. A `<form>` that already carries
577
+ `data-bcms-form` is `alreadyWired` and is left alone, so a second run is a no-op.
578
+
579
+ `--receipt <file>` writes this run's own receipt (`forms-receipt.json` — a separate file from the
580
+ P2 run's, since the two runs describe different work), and `--strict` exits 2 on any pending form.
581
+ `--forms` and `--componentize` are separate runs; doing both in one command is refused.
582
+
583
+ **Publish the drafts afterwards.** The lane creates forms as drafts and the public submit route
584
+ 403s a draft, so a wired draft form is an inviting form on a live site that rejects every
585
+ submission. The receipt carries one `notes` line per draft naming the form to publish in the Forms
586
+ tab; that is the step no codemod can do for you.
587
+
523
588
  ## Not here yet
524
589
 
525
590
  GROWABLE lists. An array of primitives or tuples is bound (above) but renders the number of rows