Keep missingStylesheets() to imports, and never crash on a foreign one
Plan step 41 review: an application's CSS entry may import what a Vite build resolves but Stylesheets::bundle() refuses (tailwindcss mid- migration, a font URL, a layer() import); resolvedFiles() threw on each, failing the application's whole design test. It now follows relative imports only and skips the rest. Each missing stylesheet, shadowed tag and ->links() is reported once, at its first use, instead of at every occurrence; a CSS entry that does not exist says so; the @import line goes through vendor/ when Composer symlinks the package. missingStylesheets() also switched on the literal-value check for the entry's whole import graph, vendor stylesheets included, with no way to check imports alone. Check (iii) now reads the .css files scan() is given, like every other check; the entry's imports still feed the class exemptions, now escaped selectors (.hover\:underline) included. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qwx5USif3wFFmxtHg5U1g9
This commit is contained in:
co-authored by
Claude Opus 5
parent
9595722f35
commit
c0c71ef16c
@@ -405,6 +405,25 @@ it('needs nothing more once the entry imports all.css', function () {
|
||||
expect($violations)->toBe([]);
|
||||
});
|
||||
|
||||
it('follows an entry that imports what only a Vite build resolves, reports each missing stylesheet once, and leaves the entry\'s literals to scan()', function () {
|
||||
$entry = realpath(GUARD_FIXTURES.'/stylesheets/foreign-imports.css');
|
||||
$mt2 = "stylesheets/views-foreign/page.blade.php:1 Tailwind spacing utility `mt-2` compiles to nothing — space between siblings is a layout component's `gap=\"space100\"` (8px); any other margin is `var(--md-sys-measurement-space100)` in your own CSS";
|
||||
$button = "stylesheets/views-foreign/page.blade.php:2 `<x-button>` needs `components/button.css`, missing from stylesheets/foreign-imports.css — add `@import '../../../../resources/css/components/button.css';`";
|
||||
|
||||
expect(fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/stylesheets/views-foreign'))->missingStylesheets($entry)->violations()))
|
||||
->toBe([$mt2, $button])
|
||||
->and(fixtureRelative(DesignGuard::scan([realpath(GUARD_FIXTURES.'/stylesheets/views-foreign'), $entry])->missingStylesheets($entry)->violations()))
|
||||
->toBe([$mt2, $button, 'stylesheets/foreign-imports.css:7 literal colour `#ff0000` — use `var(--md-sys-color-*)`']);
|
||||
});
|
||||
|
||||
it('says so when the CSS entry does not exist', function () {
|
||||
$violations = DesignGuard::scan(realpath(GUARD_FIXTURES.'/stylesheets/views/plain.blade.php'))
|
||||
->missingStylesheets('/nowhere/app.css')
|
||||
->violations();
|
||||
|
||||
expect($violations)->toBe(['/nowhere/app.css:1 the CSS entry `missingStylesheets()` names does not exist']);
|
||||
});
|
||||
|
||||
it('requires foundation.css whatever the views hold', function () {
|
||||
$violations = fixtureRelative(DesignGuard::scan(realpath(GUARD_FIXTURES.'/stylesheets/views/plain.blade.php'))
|
||||
->missingStylesheets(realpath(GUARD_FIXTURES.'/stylesheets/missing-foundation.css'))
|
||||
|
||||
@@ -93,6 +93,27 @@ it('resolves the files an entry imports, transitively, without bundling any cont
|
||||
);
|
||||
});
|
||||
|
||||
it('resolves past what an application entry imports and bundle() refuses, without throwing', function () {
|
||||
$dir = sys_get_temp_dir().'/livewire-material-resolved-'.Str::random(8);
|
||||
File::makeDirectory($dir);
|
||||
File::put($dir.'/theme.css', '.theme {}');
|
||||
File::put($dir.'/app.css', implode("\n", [
|
||||
"@import 'tailwindcss';",
|
||||
"@import url('https://fonts.googleapis.com/css2?family=Roboto');",
|
||||
"@import './theme.css' layer(app);",
|
||||
"@import './missing.css';",
|
||||
"@import '".stylesheetsBundlePath('components/icon.css')."';",
|
||||
]));
|
||||
|
||||
try {
|
||||
$files = Stylesheets::resolvedFiles([$dir.'/app.css']);
|
||||
} finally {
|
||||
File::deleteDirectory($dir);
|
||||
}
|
||||
|
||||
expect($files)->toBe([realpath(sys_get_temp_dir()).'/'.basename($dir).'/app.css', realpath(sys_get_temp_dir()).'/'.basename($dir).'/theme.css']);
|
||||
});
|
||||
|
||||
it('keeps a file two others import once, at its first position', function () {
|
||||
$dir = sys_get_temp_dir().'/livewire-material-bundle-'.Str::random(8);
|
||||
File::makeDirectory($dir);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
.gap-4 { gap: var(--md-sys-measurement-space200); }
|
||||
.hover\:underline:hover { text-decoration: underline; }
|
||||
@@ -0,0 +1,7 @@
|
||||
@import 'tailwindcss';
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto');
|
||||
@import './app-theme.css' layer(app);
|
||||
@import '../../../../resources/css/foundation.css';
|
||||
@import './does-not-exist.css';
|
||||
|
||||
.entry-literal { color: #ff0000; }
|
||||
@@ -0,0 +1,4 @@
|
||||
<div class="gap-4 hover:underline mt-2">
|
||||
<x-button label="Save" />
|
||||
<x-button label="Again" />
|
||||
</div>
|
||||
@@ -0,0 +1 @@
|
||||
<x-button label="Elsewhere" />
|
||||
Reference in New Issue
Block a user