Report a colour utility on the application's own theme colour in the design guard

The guard knew M3's roles and Tailwind's palette, so `bg-off-plan`,
`text-sport-run`, `from-brand` or `border-l-zone-4` - colours an
application's own Tailwind theme named before 2.0.0 - were the leftovers
its count never showed, though none has compiled since. After every
other family, a class-list token shaped like a colour utility on a name
that starts with a letter is now reported with the application's own
`var(--...)` as its replacement (`color-mix()` with an opacity), unless
the application's CSS declares the class.

So that none of Tailwind's own utilities on those prefixes reads as a
theme colour, each one Tailwind 4.2 lists is now named by its family:
`border-collapse`, `border-spacing-*`, the block borders `border-bs`/
`border-be`, `bg-blend-*` and the other background positions and
angles, gradient stops, `fill-none`/`stroke-*`, `text-shadow-*`,
`shadow-inner`, `accent-auto`, `inherit`/`initial` as colour keywords,
and the `mauve`, `olive`, `mist` and `taupe` palettes; only
`inset-ring-*` is still not read. BoostVocabularyTest no longer reads
a span holding a single property, prop or role name (`border-color`,
`placeholder-value`, `outline-variant`) as a class list. A fixture
test covers the theme colours and the Tailwind names beside them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Andreas Reinhold / reini
2026-09-17 04:18:10 +02:00
co-authored by Claude Opus 5
parent 394c9326ac
commit 613ac20013
9 changed files with 169 additions and 21 deletions
+46 -3
View File
@@ -1,6 +1,7 @@
<?php
use Illuminate\Support\Facades\File;
use Illuminate\Support\Str;
use NoNameWeb\LivewireMaterial\Support\Stylesheets;
use NoNameWeb\LivewireMaterial\Testing\DesignGuard;
@@ -77,16 +78,58 @@ function boostTextAsCode(string $text): array
return ['view' => implode("\n", $view), 'css' => implode("\n", $css)];
}
/**
* The hyphenated names the texts also write alone in a span for something that is not a class:
* every property the package's stylesheets declare (`border-color`), every component prop
* (`placeholder-value`) and every colour role (`outline-variant`). Each is shaped like a colour
* utility on a name the guard does not know, which is what an application's own theme colour
* (`bg-brand`) looks like.
*
* @return array<string, true>
*/
function boostNamesThatAreNotClasses(): array
{
static $names = null;
if ($names !== null) {
return $names;
}
$names = [];
$root = __DIR__.'/../../resources';
foreach (File::allFiles("{$root}/css") as $file) {
preg_match_all('/(?<![\w-])([a-z][a-z-]*-[a-z-]+)\s*:\s*[^;{}]*[;}]|--md-sys-color-([a-z-]+)/', $file->getContents(), $matches);
foreach ([...$matches[1], ...$matches[2]] as $name) {
$names[$name] = true;
}
}
foreach (File::files("{$root}/views/components") as $file) {
if (preg_match('/@props\(\[(.*?)\]\)/s', $file->getContents(), $props) === 1) {
preg_match_all("/^\s*'(\w+)'/m", $props[1], $keys);
foreach ($keys[1] as $key) {
$names[Str::kebab($key)] = true;
}
}
}
return $names;
}
/**
* Whether an inline span reads as a class list. Not: a CSS declaration (`font: var(…)`), a
* command (`php artisan …`), or a single bare word, which is as often a role, prop or value
* (`outline`, `link`, `hidden`) as a utility.
* command (`php artisan …`), a single bare word, which is as often a role, prop or value
* (`outline`, `link`, `hidden`) as a utility, or a single property, prop or role name
* (`border-color`, `placeholder-value`, `outline-variant`).
*/
function boostSpanIsClassList(string $span): bool
{
$tokens = preg_split('/\s+/', trim($span));
if (count($tokens) === 1 && preg_match('/[-:]/', $tokens[0]) !== 1) {
if (count($tokens) === 1 && (preg_match('/[-:]/', $tokens[0]) !== 1 || isset(boostNamesThatAreNotClasses()[$tokens[0]]))) {
return false;
}