v0.0.41 — Global Styles that were saved but never applied

Two defects in the Global Styles abilities, both of which reported success while doing nothing you asked for — or undoing it. A one-time repair runs on upgrade; read Upgrading below before you update.

Styles were saved, reported as active, and ignored by WordPress

Every write to the database record — blocks/create-global-style and blocks/update-global-style with source: "db" — saved settings and styles and nothing else. WordPress uses that record only when it also carries "isGlobalStylesUserThemeJSON": true; WP_Theme_JSON_Resolver::get_user_data() discards the whole thing otherwise and falls back to the theme's theme.json. It logs nothing.

So a palette, a font, a layout width would be written, read back correctly, reported as origin: "db" and effective: true — and the site went on rendering theme defaults. Measured on a test site: with the key absent, wp_get_global_stylesheet() contained no --wp--preset--color--accent-1. Adding the key alone, changing no style, produced it.

Adding the key by hand did not work either. It was rejected as an unknown top-level key, because the database record was being validated against the list of keys a theme.json file may carry. Both keys are now stamped on the server for every write, and the database source is validated against the shape WordPress actually reads from it.

A font stack with double quotes wiped the whole record

"fontFamily": "\"EB Garamond\", Georgia, serif" is an ordinary value. Saving it destroyed everything else in the record — colours, spacing and layout saved minutes earlier — and still returned success with a non-zero byte count.

The encoded JSON reached wp_update_post() unslashed, and WordPress runs wp_unslash() over every field it is given, so each \" inside the JSON lost its backslash and the stored content stopped being JSON. It then decoded to null, which the read path reported as an empty record — so the next merge-write started from empty and saved only the section it was handed.

Content is now slashed on the way in, exactly as WordPress's own Global Styles REST controller does. Every write is also read back and decoded before it is called a success; one that does not survive is rolled back to the previous content and returned as a failure. A merge into a record that does not decode is refused outright — that conversion is what turned one bad write into total loss. Block style variations were written through the same path and share the fix.

Reads now say when WordPress is ignoring a record

read-global-style reported origin: "db" and list-global-styles reported effective: true for records WordPress was not using at all. A record that is missing the key or does not decode now reads origin: "db:ignored" with a warning naming the reason, every list row carries applied_by_wordpress, and the theme.json copy the site is really serving is the one marked effective.

Section writes stop discarding what you sent

A section: "typography" write carrying styles.elements saved the typography and dropped every heading, link and button style in the same call. A section: "blockStyles" write carrying only styles.elements saved nothing at all. Both reported success.

Element styles now have a section of their own — section: "elements" — anything a section write does not save comes back in warnings as ignored: styles.elements, and a section write that would save nothing is refused with a message naming what was ignored and where it belongs.

get-style-guide says where each preset came from

It listed theme and user presets for the same slug side by side with nothing to tell them apart, so an overridden colour read as a duplicate — and for fonts, font sizes, duotones and gradients it read the theme's presets only, so user presets were missing entirely. Each preset now carries an origin of theme or custom, a slug appears once (the value the site renders), and a user preset that replaced a theme one says so.

Upgrading

If this site's Global Styles were ever set through the abilities rather than the Site Editor, this update changes what your site renders. Those records were being stored without the key WordPress requires, so the styles never took effect. A one-time routine on upgrade adds it, which means colours, fonts, spacing and layout widths saved months ago will start rendering the moment you update.

Nothing in those records is changed beyond the two keys. Records whose content is not valid JSON are left untouched for hand-recovery rather than rewritten, and block style variations are skipped, since they must not carry the key. The repair is also available on demand: update-global-style with repair: true.

No ability's input changed, and nothing else needs doing.

Full changelog: https://acrossai.co/changelog/acrossai-abilities-manager/
Compare: v0.0.40…v0.0.41


Keep reading