Migrate from legacy section-based tokens to flat override map - #95
Conversation
… legacy token system
Frontend panel was fully non-interactive: AppOverlay bound `inert={!isOpen}`,
but `inert` is a boolean attribute so `inert="false"` (rendered when open) kept
the panel disabled. Bind `inert={!isOpen || undefined}` so the attribute is
absent when open — clicks, keyboard, and all inputs work again.
Modular scale (Mobile -> Desktop): ratio presets hid the custom inputs and forced
mobile and desktop to share one ratio. Redesign ClampField's ratio block into two
always-visible per-breakpoint rows (Mobile/Desktop), each with its own preset
selector and editable number input, writing the independent --sf-*-ratio-min and
--sf-*-ratio-max tokens. Wire TypographyPanel and SpacingPanel to per-side handlers.
Remove the dead legacy section-based token system (slashed_tokens) so the flat
override map is the single source of truth:
- css-generator now emits only the validated flat overrides
- rest-controller drops /tokens, /tokens/validate|reset|export|import handlers
- token-store drops the section read/write API and legacy option constants
- inventory reads admin-chrome colors from the flat overrides (-source-light/-dark)
- token-page stops hydrating settings/tabs/defaults
- delete class-tab-registry.php and class-token-sanitizer.php
Also fix a temporal-dead-zone error in SliderRow (state declared after the
derived that read it). Rebuild the committed admin-app bundle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A96n1MkdCboCtqEuYQhAdP
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (7)
💤 Files with no reviewable changes (3)
✅ Files skipped from review due to trivial changes (1)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughRemoves legacy section-based token storage, REST endpoints ( ChangesPHP: Flat override model and legacy removal
Svelte admin app: ratio UI and minor fixes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Resolves PSR2.Classes.ClassDeclaration.CloseBraceAfterBody — the class closing brace must follow the last method body with no intervening blank line. Left over from removing the legacy section/export/import handlers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01A96n1MkdCboCtqEuYQhAdP
PR Summary by QodoMigrate token customization to flat override map and remove legacy section APIs
AI Description
Diagram
High-Level Assessment
Files changed (13)
|
Code Review by Qodo
1.
|
| // (Design Settings → POST /tokens/overrides). Appended last so a value | ||
| // set there wins over a legacy section override of the same property. | ||
| $declarations = array_merge( $declarations, self::generate_flat_override_declarations() ); | ||
| $declarations = self::generate_flat_override_declarations(); |
There was a problem hiding this comment.
2. Legacy slashed_tokens dropped 🐞 Bug ≡ Correctness
Slashed_CSS_Generator::get_override_css() now only emits declarations from the flat slashed_overrides map, and Slashed_Token_Store no longer exposes any read/migration path for the legacy slashed_tokens section map. Any existing installs that still have overrides stored only in slashed_tokens will stop applying those overrides after upgrade.
Agent Prompt
### Issue description
The PR removes all legacy section-based token handling (`slashed_tokens`) and emits CSS only from `slashed_overrides`. If an upgraded site still has customizations stored in the legacy option, they will no longer affect emitted override CSS.
### Issue Context
Post-PR, there is no `Slashed_Token_Store::get_settings()` (or similar) and `Slashed_CSS_Generator` no longer merges legacy section declarations.
### Fix Focus Areas
- SLASHED-for-WP/includes/class-token-store.php[22-70]
- SLASHED-for-WP/includes/class-css-generator.php[30-100]
### What to change
Implement a one-time migration path that preserves existing user customizations:
- On plugin load or on first `get_overrides()` call, if `slashed_overrides` is empty, check for legacy option(s) (e.g., `slashed_tokens` and any older names).
- If legacy data exists, convert it into the flat override map keys (`--sf-*`) and store it in `slashed_overrides`.
- Optionally delete the legacy option after successful migration.
- Ensure the conversion uses the same validation rules as the REST override sanitizer (`Slashed_CSS_Generator::validate_override_value`) so only safe values are migrated.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| @@ -1,146 +0,0 @@ | |||
| <?php | |||
There was a problem hiding this comment.
1. Standalone bootstrap fatal requires 🐞 Bug ☼ Reliability
The standalone Bricks/Gutenberg bootstrap code still require_onces includes/class-token-sanitizer.php and includes/class-tab-registry.php, but this PR deletes those files. In standalone mode (when Slashed_Token_Store isn't already loaded), those require_once calls will fatal-error on missing files and prevent the integration plugin from loading.
Agent Prompt
### Issue description
This PR deletes `includes/class-token-sanitizer.php` and `includes/class-tab-registry.php`, but the standalone integration entrypoints still attempt to load these files via `require_once` when running without the unified plugin. `require_once` on a missing file causes a fatal error, breaking standalone activation/runtime.
### Issue Context
In standalone mode, `integrations/bricks/slashed-bricks.php` and `integrations/gutenberg/slashed-gutenberg.php` execute their "load shared infrastructure" block (guarded by `! class_exists('Slashed_Token_Store')`). That block still includes the deleted legacy files.
### Fix Focus Areas
- SLASHED-for-WP/integrations/bricks/slashed-bricks.php[40-52]
- SLASHED-for-WP/integrations/gutenberg/slashed-gutenberg.php[54-65]
### What to change
- Remove the `require_once $slashed_shared . 'class-token-sanitizer.php';` line.
- Remove the `require_once $slashed_shared . 'class-tab-registry.php';` line.
- Double-check no other standalone bootstrap code paths reference the removed classes/files.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
SLASHED-for-WP/includes/class-css-generator.php (2)
30-43: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick winKeep
has_overrides()aligned with the emitter.Line 37 treats any non-empty value as an override, but
generate_flat_override_declarations()later drops values that failvalidate_override_value(). A stored invalid value can makehas_overrides()return true whileget_override_css()emits nothing.Proposed fix
foreach ( Slashed_Token_Store::get_overrides() as $name => $value ) { if ( ! is_string( $name ) || ! preg_match( '/^--sf-[a-z0-9-]+$/', $name ) ) { continue; } - if ( '' !== (string) $value && null !== $value ) { + if ( false !== self::validate_override_value( $value ) ) { return true; } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@SLASHED-for-WP/includes/class-css-generator.php` around lines 30 - 43, Keep has_overrides() consistent with generate_flat_override_declarations() by using the same value validation before returning true. Update the override check in Slashed_CSS_Generator::has_overrides() so it only counts entries that would actually be emitted by get_override_css(), either by reusing validate_override_value() or matching its exact acceptance rules, and keep the existing key filtering aligned with the emitter.
150-174: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winAccept the token syntaxes the flat UI now saves.
The shared flat validator rejects current admin-app values such as
cubic-bezier(...),linear(...), and scroll timeline ranges likeentry 0%;sanitize_overrides()then silently drops those overrides before storage. Add explicit timing-function and timeline-range branches before falling through to font-family parsing.Proposed fix
public static function validate_override_value( $value ) { $candidate = self::valid_color( $value ); if ( false !== $candidate ) { return $candidate; } $candidate = self::valid_dimension( $value ); if ( false !== $candidate ) { return $candidate; } + $candidate = self::valid_timing_function( $value ); + if ( false !== $candidate ) { + return $candidate; + } + $candidate = self::valid_timeline_range( $value ); + if ( false !== $candidate ) { + return $candidate; + } return self::valid_font_family( $value ); } + + private static function valid_timing_function( $value ) { + $v = trim( (string) $value ); + if ( ! self::is_css_safe( $v ) ) { + return false; + } + if ( preg_match( '/^(linear|ease|ease-in|ease-out|ease-in-out|step-start|step-end)$/i', $v ) ) { + return $v; + } + if ( preg_match( '/^(cubic-bezier|linear|steps)\s*\(/i', $v ) + && preg_match( '#^[a-z0-9\s.,%()+-]+$#i', $v ) ) { + return $v; + } + return false; + } + + private static function valid_timeline_range( $value ) { + $v = trim( (string) $value ); + if ( ! self::is_css_safe( $v ) ) { + return false; + } + if ( preg_match( '/^(normal|entry|exit|cover|contain)(\s+-?(\d+\.?\d*|\.\d+)(%|px|rem|em|vh|vw)?)?$/i', $v ) ) { + return $v; + } + return false; + }Also applies to: 232-237
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@SLASHED-for-WP/includes/class-css-generator.php` around lines 150 - 174, `validate_override_value()` is missing support for the token syntaxes the flat UI now emits, so `sanitize_overrides()` drops valid override values before they are stored. Update `Slashed_CSS_Generator::validate_override_value` to try explicit timing-function and scroll timeline-range validation branches before falling back to `valid_font_family()`, alongside the existing `valid_color()` and `valid_dimension()` checks, so values like `cubic-bezier(...)`, `linear(...)`, and `entry 0%` are accepted.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@SLASHED-for-WP/admin-app/src/components/inputs/ClampField.svelte`:
- Around line 151-172: The ratio controls in ClampField.svelte are currently
unlabeled for assistive tech because the side text is only rendered as a span;
add accessible names to both the select and number input, either by wiring them
to real labels or by adding clear aria-labels. Update the controls in the row
render block that uses row.side, ratioPresets, and row.onChange so each input
has a unique, descriptive label tied to its purpose.
---
Outside diff comments:
In `@SLASHED-for-WP/includes/class-css-generator.php`:
- Around line 30-43: Keep has_overrides() consistent with
generate_flat_override_declarations() by using the same value validation before
returning true. Update the override check in
Slashed_CSS_Generator::has_overrides() so it only counts entries that would
actually be emitted by get_override_css(), either by reusing
validate_override_value() or matching its exact acceptance rules, and keep the
existing key filtering aligned with the emitter.
- Around line 150-174: `validate_override_value()` is missing support for the
token syntaxes the flat UI now emits, so `sanitize_overrides()` drops valid
override values before they are stored. Update
`Slashed_CSS_Generator::validate_override_value` to try explicit timing-function
and scroll timeline-range validation branches before falling back to
`valid_font_family()`, alongside the existing `valid_color()` and
`valid_dimension()` checks, so values like `cubic-bezier(...)`, `linear(...)`,
and `entry 0%` are accepted.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6a25253b-fa72-42fd-a9ad-78f5a99a8f6c
📒 Files selected for processing (15)
SLASHED-for-WP/admin-app/src/AppOverlay.svelteSLASHED-for-WP/admin-app/src/components/inputs/ClampField.svelteSLASHED-for-WP/admin-app/src/components/inputs/SliderRow.svelteSLASHED-for-WP/admin-app/src/components/panels/SpacingPanel.svelteSLASHED-for-WP/admin-app/src/components/panels/TypographyPanel.svelteSLASHED-for-WP/assets/admin-app/app.cssSLASHED-for-WP/assets/admin-app/app.jsSLASHED-for-WP/includes/class-css-generator.phpSLASHED-for-WP/includes/class-inventory.phpSLASHED-for-WP/includes/class-rest-controller.phpSLASHED-for-WP/includes/class-tab-registry.phpSLASHED-for-WP/includes/class-token-page.phpSLASHED-for-WP/includes/class-token-sanitizer.phpSLASHED-for-WP/includes/class-token-store.phpSLASHED-for-WP/slashed.php
💤 Files with no reviewable changes (6)
- SLASHED-for-WP/includes/class-token-sanitizer.php
- SLASHED-for-WP/includes/class-tab-registry.php
- SLASHED-for-WP/slashed.php
- SLASHED-for-WP/admin-app/src/components/panels/TypographyPanel.svelte
- SLASHED-for-WP/admin-app/src/components/panels/SpacingPanel.svelte
- SLASHED-for-WP/includes/class-token-page.php
- Remove require_once of deleted class-token-sanitizer.php and class-tab-registry.php from standalone Bricks/Gutenberg bootstraps to avoid a fatal error on standalone activation. - Accept easing (cubic-bezier()/linear()/steps()) and scroll-timeline range (entry 0%, cover 30%) values in validate_override_value() so motion-panel overrides are no longer silently dropped on save/emit. - Align has_overrides() with the emitter by reusing validate_override_value(). - Add aria-labels to the modular-scale ratio select and number input in ClampField.svelte; rebuild admin SPA assets. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Snqr6gnsRqsXFgxB9zo991
Summary
This PR completes the migration from the legacy section-based token storage system (
slashed_tokensoption with per-section maps) to the new flat override map system (slashed_overridesoption with CSS custom property names as keys).Key changes:
Slashed_CSS_Generator— the class now only reads from the flat override map viagenerate_flat_override_declarations()Slashed_Token_Sanitizerclass (legacy section sanitization no longer needed)Slashed_Tab_Registryclass (legacy tab/section registry no longer needed)POST /tokens,POST /tokens/validate,POST /tokens/reset,GET /tokens/export,POST /tokens/import) — only the flat override endpoints remainSlashed_Token_Storeto remove legacy settings methods; keep only the flat override map and plugin settingsThe configurator SPA now exclusively uses the flat override map (
POST /tokens/overrides) for all design token customization. Framework defaults remain untouched when no override is set.Type
Checklist
npm testpassesnpm run lintpassesnpm run verifypassesCHANGELOG.mdupdated under## [Unreleased]Notes
This is a breaking change for any external code that directly accessed
Slashed_Token_Store::get_settings()or the legacy REST endpoints. All token customization now flows through the flat override map, which is simpler and more maintainable.The migration is transparent to end users — the configurator UI continues to work identically, just backed by the new storage format.
https://claude.ai/code/session_01A96n1MkdCboCtqEuYQhAdP
Summary by CodeRabbit
New Features
Bug Fixes