From c047fefd8b5bcc08f460d3cd7022a04d0cede047 Mon Sep 17 00:00:00 2001 From: Andreas Reinhold / reini Date: Tue, 15 Sep 2026 08:28:35 +0200 Subject: [PATCH] Remove the design guard's maryUI and daisyUI checks Plan step 41 review (the user, 2026-09-15): SealShare and ReStride have both left maryUI and daisyUI, and no application of 2.0.0 carries either, so the tag check, the daisyUI class and colour lists and the Tailwind look-alike exclusions they needed go, with their fixture lines and the mentions in the header, README and development skill. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9 --- README.md | 2 +- .../livewire-material-development/SKILL.md | 2 +- src/Testing/DesignGuard.php | 52 +++---------------- tests/Feature/DesignGuardTest.php | 20 +++---- .../design-guard/views/page.blade.php | 9 ++-- 5 files changed, 22 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index d3f8cc40..d075c4f6 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ it('uses only what compiles', function () { }); ``` -The guard fails on maryUI tags, daisyUI classes, colours the theme does not declare, unknown Material Symbol names and Blade directives written inside component tags. It also fails on every Tailwind utility or variant still sitting in a view, PHP or JS file — a breakpoint prefix, a radius, shadow, type size/weight/leading/tracking, easing or duration, a flex/grid/spacing/sizing/display utility, a text-layout utility, an M3 role utility (`text-on-surface-variant`, `bg-primary`), a pseudo-class variant, or an arbitrary `[…]` value — none of which compile any more, since the application carries no Tailwind: every line names its 2.0.0 replacement, a layout component and prop (`flex gap-4` → ``), an `md-*` class (`truncate` → `md-truncate`), or a token for the application's own CSS (`rounded-lg` → `var(--md-sys-shape-corner-lg)`). A class the application's own stylesheets declare is exempt, and so is every `md-*` class. +The guard fails on Tailwind palette colours, unknown Material Symbol names and Blade directives written inside component tags. It also fails on every Tailwind utility or variant still sitting in a view, PHP or JS file — a breakpoint prefix, a radius, shadow, type size/weight/leading/tracking, easing or duration, a flex/grid/spacing/sizing/display utility, a text-layout utility, an M3 role utility (`text-on-surface-variant`, `bg-primary`), a pseudo-class variant, or an arbitrary `[…]` value — none of which compile any more, since the application carries no Tailwind: every line names its 2.0.0 replacement, a layout component and prop (`flex gap-4` → ``), an `md-*` class (`truncate` → `md-truncate`), or a token for the application's own CSS (`rounded-lg` → `var(--md-sys-shape-corner-lg)`). A class the application's own stylesheets declare is exempt, and so is every `md-*` class. `missingStylesheets($cssEntry)` checks the CSS entry's `@import` graph (followed through every package file's own imports) against the package tags a view actually renders — unprefixed, under the configured prefix, or `` — and `->links()`; each missing one names the exact `@import` line to add, and a tag the application shadows with its own component of the same name is reported instead. It also turns on a check of the application's own CSS (the entry and what it imports outside the package, plus any `.css` file among the scanned paths), which reports a literal colour, radius, shadow, font size, weight, line height, letter spacing, easing, duration or off-scale media query with its token or breakpoint — a value inside `var(--md-sys-…)` or `calc()` is always fine, and the generated `material-scheme.css` is skipped. diff --git a/resources/boost/skills/livewire-material-development/SKILL.md b/resources/boost/skills/livewire-material-development/SKILL.md index fc6b0cda..4e885227 100644 --- a/resources/boost/skills/livewire-material-development/SKILL.md +++ b/resources/boost/skills/livewire-material-development/SKILL.md @@ -1119,7 +1119,7 @@ it('uses only what compiles', function () { }); ``` -It fails on maryUI tags, daisyUI classes, colours the theme does not declare, unknown symbol names and Blade directives written inside a component tag (where they do not compile), with `path:line` for each. +It fails on Tailwind palette colours, unknown symbol names and Blade directives written inside a component tag (where they do not compile), with `path:line` for each. It also fails on every Tailwind utility or variant, which compile to nothing in a Tailwind-free application, each with its 2.0.0 replacement — a layout component and prop, an `md-*` class, or a token for the application's own CSS. A class the application's own stylesheets declare is exempt, and so is every `md-*` class: diff --git a/src/Testing/DesignGuard.php b/src/Testing/DesignGuard.php index d26cc0ba..fb8d2179 100644 --- a/src/Testing/DesignGuard.php +++ b/src/Testing/DesignGuard.php @@ -33,10 +33,10 @@ use Symfony\Component\Finder\Finder; * height, letter spacing, easing or duration, and a media query at a width other than * 600/840/1200/1600px — each with its token or breakpoint. A value inside * `var(--md-sys-…)` or `calc()` is never flagged, whatever it contains. - * (iv) maryUI tags, daisyUI classes, colours the theme does not declare, icon names that are - * not Material Symbols, and Blade directives written inside a component tag (where they - * do not compile) — plus whatever an application bans on top with `forbidColours()`, - * `forbidAbsolutes()`, `forbidOpacityInk()` and `forbid()`. These, and the breakpoint, + * (iv) Tailwind palette colours, icon names that are not Material Symbols, and Blade + * directives written inside a component tag (where they do not compile) — plus whatever + * an application bans on top with `forbidColours()`, `forbidAbsolutes()`, + * `forbidOpacityInk()` and `forbid()`. These, and the breakpoint, * scale and colour-value checks, read a line at a time, so a class assembled at runtime * (`'text-'.$tone`) or hidden in a comment stays invisible — the same reason to write * class names out whole. `forbidAbsolutes()` and `forbidOpacityInk()` matter mainly to an @@ -66,17 +66,6 @@ class DesignGuard protected const string PALETTE = '(?:red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose|slate|gray|zinc|neutral|stone)-(?:50|[1-9]00|950)'; - protected const string DAISY_COLOURS = '(?:base-(?:100|200|300|content)|(?:primary|secondary|accent|neutral|info|success|warning|error)-content|accent|neutral)'; - - /** - * daisyUI's component classes. Tailwind utilities that share a name — `collapse`, `table`, - * `select-none`, `tab-4` — and the package's own `link` are not on it. - */ - protected const string DAISY_CLASSES = '/^(?:btn|badge|card|alert|modal|drawer|dropdown|menu|navbar|footer|hero|stats?|tabs?|tooltip|toast|toggle|checkbox|radio|range|rating|input|select|textarea|file-input|fieldset|label|join|kbd|loading|progress|radial-progress|skeleton|steps?|timeline|swap|indicator|avatar|divider|dock|fab|status|validator|breadcrumbs|carousel|chat|countdown|diff|stack|theme-controller)(?:-[a-z0-9-]+)?$' - .'|^(?:table-(?:zebra|xs|sm|md|lg|xl|pin-rows|pin-cols)|collapse-(?:arrow|plus|title|content|open|close)|list-row|link-(?:primary|secondary|accent|neutral|info|success|warning|error))$/'; - - protected const string TAILWIND_LOOKALIKES = '/^(?:select-(?:none|text|all|auto)|tab-\d+)$/'; - /** A colour written as a value: an arbitrary hex, function or mix instead of a role. */ protected const string ARBITRARY_COLOUR = '/(?withoutBladeComments($contents); foreach ($this->literalClasses($contents) as [$line, $class]) { - $bare = $this->withoutVariantPrefix($class); - - if (preg_match(self::DAISY_CLASSES, $bare) === 1 && preg_match(self::TAILWIND_LOOKALIKES, $bare) !== 1) { - $violations[] = "{$where}:{$line} daisyUI class `{$bare}`"; - } - if (($hint = $this->tailwindFamilyHint($class)) !== null) { $violations[] = "{$where}:{$line} {$hint}"; } @@ -366,12 +349,6 @@ class DesignGuard foreach (explode("\n", $contents) as $index => $text) { $line = $index + 1; - if ($isBlade && preg_match_all('/colourPattern(), $text, $matches)) { foreach ($matches[0] as $class) { $violations[] = "{$where}:{$line} colour the theme does not declare `{$class}`"; @@ -413,7 +390,7 @@ class DesignGuard protected function colourPattern(): string { - $names = [self::PALETTE, self::DAISY_COLOURS]; + $names = [self::PALETTE]; foreach ($this->forbiddenColours as $role) { $role = preg_quote($role, '/'); @@ -548,17 +525,6 @@ class DesignGuard return $found; } - /** - * `$token` with a variant prefix — a breakpoint, a stacked pseudo-class chain — and a leading - * `!` dropped, so the daisyUI check can still recognise a variant-prefixed daisy class for - * what it is underneath. `tailwindFamilyHint()` reports the prefix itself (see the variant - * family below), so it works from the token `literalClasses()` returns, unstripped. - */ - protected function withoutVariantPrefix(string $token): string - { - return ltrim((string) preg_replace('/^.*:/', '', $token), '!'); - } - /** * A Tailwind-shaped class token's 2.0.0 replacement, or null when the token is not this * guard's to report: it is not Tailwind-shaped at all (an application's own class, an ARIA or @@ -859,8 +825,7 @@ class DesignGuard * Every class written out literally: in `class="…"`, and in the string keys and values of * `:class`/`x-bind:class`, `@class([...])`, `->class([...])` and `Arr::toCssClasses([...])`. * Echoes inside a list are skipped. A token is returned exactly as written, variant prefix - * (`sm:`, `hover:`) and all — `withoutVariantPrefix()` strips one for the daisyUI check, which - * needs to see through it; `tailwindFamilyHint()` needs to see it. + * (`sm:`, `hover:`) and all, since `tailwindFamilyHint()` reports the prefix itself. * * @return list */ @@ -967,8 +932,7 @@ class DesignGuard * application component of the same name (Blade tries the application's own * `resources/views/components/.blade.php` — and a class-based one — before this * package's registered anonymous path, whatever the configured prefix; a namespaced or - * prefixed tag always reaches the package). `` is not a component tag, and - * `` is the maryUI check's concern. + * prefixed tag always reaches the package). `` is not a component tag. * * @return list */ @@ -981,7 +945,7 @@ class DesignGuard $found = []; foreach ($tags[1] as [$tag, $offset]) { - if (str_starts_with($tag, 'x-slot') || str_starts_with($tag, 'x-mary-')) { + if (str_starts_with($tag, 'x-slot')) { continue; } diff --git a/tests/Feature/DesignGuardTest.php b/tests/Feature/DesignGuardTest.php index c2d6a11f..f4d91aa0 100644 --- a/tests/Feature/DesignGuardTest.php +++ b/tests/Feature/DesignGuardTest.php @@ -23,16 +23,12 @@ it('finds what compiles to nothing', function () { expect(fixtureRelative($violations))->toBe([ 'app/Status.php:14 colour the theme does not declare `text-red-500`', - 'views/page.blade.php:3 daisyUI class `card`', - "views/page.blade.php:3 Tailwind spacing utility `p-4` compiles to nothing — use a layout component's `gap`/`padding` prop (``, ``), or `var(--md-sys-measurement-space*)` in your own CSS", - 'views/page.blade.php:6 daisyUI class `btn-primary`', - 'views/page.blade.php:9 Tailwind sizing utility `size-4` compiles to nothing — M3 keeps no size scale; write the literal length in your own CSS, or use ``/`` where it fits', - 'views/page.blade.php:4 unknown Material Symbol `o-home`', - 'views/page.blade.php:5 unknown Material Symbol `not_a_symbol`', - 'views/page.blade.php:9 Blade directive `@class` inside a component tag, where it does not compile', - 'views/page.blade.php:2 maryUI component ``, ``), or `var(--md-sys-measurement-space*)` in your own CSS", + 'views/page.blade.php:8 Tailwind sizing utility `size-4` compiles to nothing — M3 keeps no size scale; write the literal length in your own CSS, or use ``/`` where it fits', + 'views/page.blade.php:3 unknown Material Symbol `o-home`', + 'views/page.blade.php:4 unknown Material Symbol `not_a_symbol`', + 'views/page.blade.php:8 Blade directive `@class` inside a component tag, where it does not compile', + 'views/page.blade.php:5 colour the theme does not declare `text-red-600`', ]); }); @@ -299,7 +295,7 @@ it('bans the roles an application leaves out', function () { ->forbidColours(['tertiary']) ->violations()); - expect($violations)->toContain('views/page.blade.php:7 colour the theme does not declare `text-tertiary`'); + expect($violations)->toContain('views/page.blade.php:6 colour the theme does not declare `text-tertiary`'); }); it('bans any further pattern', function () { @@ -307,7 +303,7 @@ it('bans any further pattern', function () { ->forbid('/\bfocus-ring\b/', 'a retired utility') ->violations()); - expect($violations)->toContain('views/page.blade.php:7 a retired utility'); + expect($violations)->toContain('views/page.blade.php:6 a retired utility'); }); it('names the missing package stylesheet and the exact @import line to add', function () { diff --git a/tests/Fixtures/design-guard/views/page.blade.php b/tests/Fixtures/design-guard/views/page.blade.php index 967aea1c..1a0b5dcd 100644 --- a/tests/Fixtures/design-guard/views/page.blade.php +++ b/tests/Fixtures/design-guard/views/page.blade.php @@ -1,10 +1,9 @@ -{{-- and btn-primary in a comment are not violations --}} - -
+{{-- text-red-600 and in a comment are not violations --}} +
- $active, 'select-none'])>text-red-600 - + text-red-600 +

Tailwind's and ours