mosaic-headless 1.17.2 → 1.18.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.ja.md +17 -10
- package/README.ko.md +17 -10
- package/README.md +16 -9
- package/README.zh-TW.md +15 -9
- package/SKILL.md +96 -40
- package/assets/templates/platforms/claude-ai.json +1 -1
- package/assets/templates/platforms/claude-code.json +1 -1
- package/assets/templates/platforms/codex-cli.json +1 -1
- package/assets/templates/platforms/copilot.json +1 -1
- package/assets/templates/platforms/gemini-cli.json +1 -1
- package/bin/check-release.mjs +1 -1
- package/data/accordion-verification.csv +1 -1
- package/data/browser-verification.csv +906 -906
- package/data/conversion-verification.csv +1 -1
- package/data/db-columns.csv +40 -36
- package/data/design-audit-acknowledged.csv +1 -0
- package/data/design-audit.csv +1 -1
- package/data/intro-verification.csv +7 -7
- package/data/loop-verification.csv +5 -5
- package/data/node-properties.csv +4 -3
- package/data/node-property-verification.csv +81 -80
- package/data/node-type-notes.csv +1 -1
- package/data/node-types.csv +9 -9
- package/data/node-verification.csv +100 -100
- package/data/rest-routes.csv +1 -1
- package/data/style-properties.csv +1 -1
- package/data/style-state-verification.csv +48 -48
- package/data/style-states.csv +32 -32
- package/data/style-verification.csv +1 -1
- package/data/theme-zip-verification.csv +10 -10
- package/data/variants.csv +153 -0
- package/evals/accordion-is-not-broken/graders/criteria.md +1 -1
- package/evals/grid-child-placement/graders/criteria.md +3 -3
- package/package.json +1 -1
- package/references/data-model.md +7 -6
- package/references/design-system.md +28 -16
- package/references/interactions.md +1 -1
- package/references/responsive.md +6 -6
- package/references/styling.md +23 -14
- package/references/upgrading.md +182 -0
- package/references/vs-elementor-gutenberg.md +1 -1
- package/references/write-protocol.md +1 -1
- package/sites/_moksa.py +67 -62
- package/sites/moksa.json +219 -219
- package/tools/bootstrap_probe_theme.php +1 -1
- package/tools/build_page.py +17 -11
- package/tools/build_site.py +1 -1
- package/tools/capture_live.py +42 -6
- package/tools/data_upgrade.py +74 -0
- package/tools/extract_node_types.py +1 -1
- package/tools/from_elementor.py +3 -3
- package/tools/mo.py +10 -9
- package/tools/probe.py +1 -1
- package/tools/sweep_components.py +1 -1
- package/tools/sweep_interactions.py +3 -3
- package/tools/sweep_node_properties.py +1 -1
- package/tools/sweep_node_types.py +20 -0
- package/tools/sweep_style_properties.py +6 -7
- package/tools/sweep_style_states.py +2 -2
- package/tools/theme_export.php +2 -2
- package/tools/theme_zip_compare.php +2 -2
- package/tools/verify_browser.py +6 -5
- package/tools/verify_rwd.py +17 -15
- package/data/element-classes.csv +0 -152
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# Upgrading the plugin: what 1.0.7 → 1.0.8 did to the data, measured
|
|
2
|
+
|
|
3
|
+
A Mosaic plugin update is two events, not one. The files change when WordPress
|
|
4
|
+
installs the package; the DATA changes only when Mosaic's own upgrade flow has
|
|
5
|
+
walked its milestones, and until it has, the site is in a state nothing in this
|
|
6
|
+
skill can talk to: the editor namespace (`/wp-json/mosaic/v<version>`) is not
|
|
7
|
+
registered at all. Only `mosaic/<dataVersion>/<version>/upgrade` answers.
|
|
8
|
+
|
|
9
|
+
Everything below was done to the test site this skill was built on - a real
|
|
10
|
+
1.0.7 theme with the worked example (1,286 nodes), the WooCommerce account page,
|
|
11
|
+
the nineteen Elementor conversions and every probe master on it - and then
|
|
12
|
+
every sweep was re-run against the result.
|
|
13
|
+
|
|
14
|
+
## Driving the upgrade from outside wp-admin
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
python tools/data_upgrade.py mk.json --status
|
|
18
|
+
editor running : - (data upgrade pending)
|
|
19
|
+
upgrade namespace : mosaic/1.0.8/1.0.8
|
|
20
|
+
|
|
21
|
+
python tools/data_upgrade.py mk.json
|
|
22
|
+
processing 4426b1d4, 6 milestones
|
|
23
|
+
clone ok (1 call, 4.0s)
|
|
24
|
+
backup ok (5 calls, 20.8s)
|
|
25
|
+
1.0.8 ok (8 calls, 35.2s)
|
|
26
|
+
restore ok (1 call, 1.5s)
|
|
27
|
+
set-data-version ok (1 call, 1.3s)
|
|
28
|
+
replace-plugin ok (1 call, 1.8s)
|
|
29
|
+
done - https://<site> now serves v1.0.8; mk.json version set to 1.0.8
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Three things about that route worth knowing before you call it:
|
|
33
|
+
|
|
34
|
+
- **It is the same milestone protocol as the theme ZIP flow** (`theme_zip.py`):
|
|
35
|
+
POST once to Start, then POST `{processingID, milestoneID}` until `isCompleted`.
|
|
36
|
+
`data_upgrade.py` reuses `Flow` from `theme_zip.py` for exactly that reason.
|
|
37
|
+
- **It refuses to start without `siteID`** (`Missing siteID`), even on a single
|
|
38
|
+
site. `1` is the blog ID there; the tool sends it.
|
|
39
|
+
- **The upgrade namespace stays registered after the upgrade.** Its presence means
|
|
40
|
+
nothing. The signal that Mosaic is running again is the versioned
|
|
41
|
+
`mosaic/v<version>/pluggable/endpoint` namespace in the REST index - the editor
|
|
42
|
+
namespace itself is a regex (`mosaic/v(?P<mosaicVersion>...)`) and cannot be
|
|
43
|
+
read for a version.
|
|
44
|
+
- **`wp plugin install <zip> --force` may not replace the plugin.** WordPress
|
|
45
|
+
installed the 1.0.8 package beside 1.0.7 as `mosaic-next`, inactive, because the
|
|
46
|
+
slug it derived did not match. Deactivate, move the folders, activate: the
|
|
47
|
+
files were then 1.0.8 and the data still 1.0.7, which is the state the tool
|
|
48
|
+
above expects.
|
|
49
|
+
|
|
50
|
+
The plugin clones every table before touching it, works on the clones, and swaps
|
|
51
|
+
at the end (`MilestoneRestore`), so a tick that dies mid-way leaves the live
|
|
52
|
+
tables alone. Back up anyway: `wp db export --tables=<the 23 mosaic tables>`.
|
|
53
|
+
|
|
54
|
+
## What the migration rewrote
|
|
55
|
+
|
|
56
|
+
Read off `MosaicUpgradeRunLayer/Upgrades/Upgrade-1.0.8.php` and confirmed on the
|
|
57
|
+
rows afterwards.
|
|
58
|
+
|
|
59
|
+
**Four tables renamed** (the clones are renamed, last batch of the file):
|
|
60
|
+
|
|
61
|
+
| 1.0.7 | 1.0.8 |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `mosaic_element_classes` | `mosaic_variants` |
|
|
64
|
+
| `mosaic_sub_classes` | `mosaic_variant_sub_classes` |
|
|
65
|
+
| `mosaic_utility_classes` | `mosaic_universal_classes` |
|
|
66
|
+
| `mosaic_utility_sub_classes` | `mosaic_universal_sub_classes` |
|
|
67
|
+
|
|
68
|
+
Still 23 tables (22 in the schema plus `mosaic_locks`); 210 columns rather than
|
|
69
|
+
206, because four tables gained an `emittedName` column - a write-only projection
|
|
70
|
+
of the class or custom-property name each row emits, with a per-theme UNIQUE
|
|
71
|
+
index. Two classes in one theme can no longer emit the same spelling. The column
|
|
72
|
+
is declared `CHARACTER SET ascii COLLATE ascii_bin` so the index fits a 4K
|
|
73
|
+
InnoDB page; the source comments explain why at length.
|
|
74
|
+
|
|
75
|
+
**The stored discriminators inside `data`** - the keys the identifier renames had
|
|
76
|
+
deliberately skipped so they could move once, with a migration:
|
|
77
|
+
|
|
78
|
+
| where | 1.0.7 | 1.0.8 |
|
|
79
|
+
|---|---|---|
|
|
80
|
+
| node `style` key | `elementClass` | `variant` |
|
|
81
|
+
| node `style` key | `utilityClasses` | `universalClasses` |
|
|
82
|
+
| node `style` key | `defaultClass` | `defaultStyleSelector` |
|
|
83
|
+
| `defaultStyleSelector.type` | `elementClass` / `subClass` / `utilityClass` / `utilitySubClass` / `custom` | `variant` / `variantSubClass` / `universalClass` / `universalSubClass` / `local` |
|
|
84
|
+
| interaction trigger / target `type` | the same four | the same four |
|
|
85
|
+
| `parentType` column on the two sub-class tables | `elementClass`, `subClass`, `utilityClass`, `utilitySubClass` | `variant`, `variantSubClass`, `universalClass`, `universalSubClass` |
|
|
86
|
+
| style-state property, nodes AND every class row | `customStyles` | `customDeclarations` |
|
|
87
|
+
| REST resource in checkout / commit envelopes | `elementClass`, `subClass`, `utilityClass`, `utilitySubClass`, `elementClassMeta` | `variant`, `variantSubClass`, `universalClass`, `universalSubClass`, `variantDefinition` |
|
|
88
|
+
| REST route | `/elementClassMeta` | `/variantCatalog` |
|
|
89
|
+
|
|
90
|
+
`ValidatorTargetDetails` accepts only the new spellings and DROPS what it does
|
|
91
|
+
not recognise, which is why the interaction rows are walked too: a class-level
|
|
92
|
+
interaction with a stale discriminator would quietly lose its trigger.
|
|
93
|
+
|
|
94
|
+
**Class names became a naming system** (`ClassNameHelper.php`; the source calls
|
|
95
|
+
it WYSIWYG class names). Every class, sub class and variant sub class had its
|
|
96
|
+
freeform name folded into a canonical segment: transliterate, lowercase, replace
|
|
97
|
+
anything outside `[a-z0-9_-]` with `-`, collapse runs, cap at 60 characters, fold
|
|
98
|
+
the size scale (`s`→`sm`, `m`→`md`, `l`→`lg`, `xxs`→`2xs` … `xxxxl`→`4xl`),
|
|
99
|
+
dedupe published siblings with `-2`, `-3`. A root segment may not start with a
|
|
100
|
+
digit or with the reserved `m-`. A name that sanitizes to nothing becomes
|
|
101
|
+
`class`. The hidden `cssClass` override is cleared, but an emittable value is
|
|
102
|
+
kept as `data.legacyClassName` so the class still emits it as an extra selector.
|
|
103
|
+
|
|
104
|
+
**The catalog grew by one.** Badge, which used to be a sub-class tree under the
|
|
105
|
+
Button variant, is its own variant (`1d964ef1-…`, `m-badge`); the legacy tree is
|
|
106
|
+
left in place because existing pages point at it. 152 entries in
|
|
107
|
+
`data/variants.csv`, 151 before.
|
|
108
|
+
|
|
109
|
+
## What changed in the delivered page
|
|
110
|
+
|
|
111
|
+
This is the part no row tells you about, and the part that broke something.
|
|
112
|
+
|
|
113
|
+
```
|
|
114
|
+
1.0.7 <div id="x" class="M_EL4 M_EL_Div"> .M_EL4{...}
|
|
115
|
+
<div class="M_EL7 M_EL_Text M_EL_WYSIWYG">
|
|
116
|
+
h2,.M_EL_Text__Heading2{...}
|
|
117
|
+
<div class="M_EL_AccordionItem M_EL_AccordionItem--opened">
|
|
118
|
+
|
|
119
|
+
1.0.8 <div id="x" class="m-div _e"> ._e{...}
|
|
120
|
+
<div class="m-text m-wysiwyg _h">
|
|
121
|
+
h2,.m-heading-2{...}
|
|
122
|
+
<div class="m-accordion-item m-accordion-item--opened">
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
- The per-element class is `_` + a base-38 token (`ElementTokenHelper`:
|
|
126
|
+
alphabet `a-z0-9-_`, so `_a` … `_9`, `_-`, `__`, then `_ba`). Single-case on
|
|
127
|
+
purpose: a shortcode that echoes before the doctype drops the page into quirks
|
|
128
|
+
mode, where class matching is case-insensitive, and `a`/`A` would share one
|
|
129
|
+
local style block. It comes LAST in the class list now; it came first.
|
|
130
|
+
- The type class is `m-<type>` (`m-div`, `m-section`, `m-menu-link`, `m-code`),
|
|
131
|
+
and a variant that renders its name adds it (`m-heading-2`). 113 of the 152
|
|
132
|
+
catalog entries render one; the rest (Body, HTML, the Gutenberg mirrors, the
|
|
133
|
+
accordion content inner) are matched by selector only. `renders_class` in
|
|
134
|
+
`data/variants.csv`.
|
|
135
|
+
- State classes moved with the type classes: `m-accordion-item--opened`,
|
|
136
|
+
`m-dropdown--opened`, `m-navbar--opened`, `m-menu-link--current`,
|
|
137
|
+
`m-dropdown-toggle--current`, `m-tab--active`, `m-slider-arrow--hidden`.
|
|
138
|
+
`data/style-states.csv` carries the new selector templates.
|
|
139
|
+
- The `<mosaic-*>` custom elements, the `mosaicInteractions` payload, the
|
|
140
|
+
`wp-theme-mosaic-1-1-<themeID>` body class and `body{opacity:0}` are unchanged.
|
|
141
|
+
|
|
142
|
+
The worked example's loop window opens by toggling the accordion and styling
|
|
143
|
+
`#mk-plate-item.M_EL_AccordionItem--opened{position:fixed;inset:0;…}`. After the
|
|
144
|
+
upgrade the migration had rewritten every row it owns, the page served with HTTP
|
|
145
|
+
200 at the same size, the tap did toggle `aria-expanded` - and the panel did not
|
|
146
|
+
enlarge, because the class the selector named no longer exists. Nothing in the
|
|
147
|
+
plugin reports that; `verify_loop.py` OPENS (186x161 → 1920x900) is what saw it.
|
|
148
|
+
The selector now reads `m-accordion-item--opened`, and the lesson is in
|
|
149
|
+
`SKILL.md`: any CSS that names an emitted class is coupled to the plugin version.
|
|
150
|
+
|
|
151
|
+
## What did not change
|
|
152
|
+
|
|
153
|
+
Re-extracted from the 1.0.8 source and diffed against 1.0.7: 122 node types, the
|
|
154
|
+
same 122 placement rules, 10 default structures, 74 dynamic variables, 12
|
|
155
|
+
interaction triggers, 22 animatable properties, 207 pluggable IDs, 53 style
|
|
156
|
+
states (12 templates re-spelt for the new class names), 98 style properties with
|
|
157
|
+
one renamed. Node properties went from 181 to 182: `button` gained `inactive`
|
|
158
|
+
(integer, `ValidatorInteger|ValidatorIntegerAsString`) and its emitted attribute
|
|
159
|
+
list gained `type`. The REST surface is 114 routes either way, one swapped.
|
|
160
|
+
The seven failure modes measured before are all still there, and the eighth is
|
|
161
|
+
this file.
|
|
162
|
+
|
|
163
|
+
## Re-verifying after an upgrade
|
|
164
|
+
|
|
165
|
+
The order that worked, and why each step is there:
|
|
166
|
+
|
|
167
|
+
1. `data_upgrade.py --status` until the editor namespace is back; set `version`
|
|
168
|
+
in every config (the tool does it for the one it was given).
|
|
169
|
+
2. Re-extract from the new source tree and diff `data/*.csv` - the source says
|
|
170
|
+
what was renamed before any sweep has to discover it.
|
|
171
|
+
3. `capture_live.py` for the routes, the catalog and the columns.
|
|
172
|
+
4. Rebuild the worked example (`build_site.py`) - the first real write through
|
|
173
|
+
the renamed vocabulary, and the page has to come out byte-for-byte the same
|
|
174
|
+
apart from the tokens. It did (235,105 bytes, 1,286 nodes).
|
|
175
|
+
5. `verify_loop.py`, `probe_accordion.py`, `sweep_node_types.py`,
|
|
176
|
+
`sweep_style_states.py`, then the rwd and browser passes. The loop check is
|
|
177
|
+
first because it is the one that failed.
|
|
178
|
+
6. The ZIP round trip last - and prune the theme first. 223 accumulated masters
|
|
179
|
+
(98,261 nodes, 25 of them bound) made the 1.0.8 import time out at nginx's
|
|
180
|
+
five-minute upstream limit during `createTemplates`; at 25 masters and 8,608
|
|
181
|
+
nodes it finished in under two minutes and `theme_zip_compare.php` passed
|
|
182
|
+
22 of 22, the four renamed tables included.
|
|
@@ -53,7 +53,7 @@ page" usually means editing a template, and the blast radius is every post that
|
|
|
53
53
|
template is assigned to. Check `mosaic_template_assigns` before you edit.
|
|
54
54
|
|
|
55
55
|
**"Style the element."** Elementor puts controls on the widget. Mosaic puts styling
|
|
56
|
-
in a **class system** (
|
|
56
|
+
in a **class system** (152 built-in variants - element classes) layered over a **token system**
|
|
57
57
|
(collections → modes/skins → variables). Writing styles onto individual nodes works
|
|
58
58
|
and is almost always wrong; it opts that node out of both layers.
|
|
59
59
|
|
|
@@ -27,7 +27,7 @@ Both `checkout` and `check` take one required string parameter, `syncCheckEnvelo
|
|
|
27
27
|
pairs:
|
|
28
28
|
|
|
29
29
|
```json
|
|
30
|
-
{"node": [["<nodeID>", "<revision>"], ...], "
|
|
30
|
+
{"node": [["<nodeID>", "<revision>"], ...], "variant": [[...]]}
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
The `revision` is the value from the row's `revision` column when you read it. The
|