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 <x-mary-*> 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) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
Andreas Reinhold / reini
2026-09-15 08:28:35 +02:00
co-authored by Claude Opus 5
parent 6147221b89
commit c047fefd8b
5 changed files with 22 additions and 63 deletions
+8 -44
View File
@@ -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 = '/(?<![\w-])'.self::UTILITY.'-\[(?:#|rgb|hsl|oklch|color-mix)[^\]\s"\']*\]?/';
@@ -337,12 +326,6 @@ class DesignGuard
$contents = $this->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('/<x-mary-[\w.:-]+/', $text, $matches)) {
foreach ($matches[0] as $tag) {
$violations[] = "{$where}:{$line} maryUI component `{$tag}`";
}
}
if (preg_match_all($this->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<array{0: int, 1: string}>
*/
@@ -967,8 +932,7 @@ class DesignGuard
* application component of the same name (Blade tries the application's own
* `resources/views/components/<name>.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). `<x-slot:…>` is not a component tag, and
* `<x-mary-…>` is the maryUI check's concern.
* prefixed tag always reaches the package). `<x-slot:…>` is not a component tag.
*
* @return list<array{0: int, 1: string, 2: string}>
*/
@@ -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;
}