test(ui): den Küchen-Breiten-Guard am Effekt messen statt an der Form - #644
Conversation
Nachlauf zu #643, das dort Gefundene nach dem Merge. Zwei der sieben Befunde waren Fehlalarme - der Guard haette korrekte Arbeit blockiert: - `.recipes-list { max-width: none }` und `width: auto` galten als Kappung. Sie lassen den Scroller ausdruecklich unbeschraenkt. Geprueft wird jetzt der WERT, nicht die Anwesenheit der Eigenschaft. - Eine Kappung in `@layer components { … }` galt als bedingt. Cascade Layers ordnen nur die Kaskade und gelten ueberall; einschraenkend sind @media, @supports, @container und @scope. Der Parser unterscheidet die At-Rules jetzt nach Bedeutung statt nach ihrem '@'. Dazu fuenf echte Luecken, eine davon wieder im Scanner: - Natives Nesting (`.recipes-list { & { max-width: 20rem } }`) wurde still uebersprungen: der flache Scanner nahm die erste schliessende Klammer als Rumpfende. Er balanciert jetzt und liest verschachtelte Regeln mit aufgeloestem Selektor mit. - `--content-max-width-narrow: none`. Die Existenzpruefung nahm jeden Wert; jetzt muss der Token eine Breite SEIN. - `.shopping-page .kitchen-rows` erfuellte die Kind-Zusage, ohne die Rezeptliste zu treffen. Der erfuellende Selektor darf das Element weder ueber einen Vorfahren noch ueber einen Zustand einschraenken. - Kappung und `overflow` in zwei getrennten Regeln. Der Browser sammelt die Deklarationen aller passenden Regeln, bevor er den Wert bestimmt - der Guard tut das jetzt auch, statt jeden Block einzeln zu lesen. - `margin-inline-end: 20rem` am Scroller. Als gestrecktes Flex-Item zieht eine Inline-Marge direkt von der Randbox ab, ganz ohne Breitenangabe. Der margin-Shorthand zaehlt mit. 61 Mutationen belegen den Stand, davon zehn, die gruen bleiben muessen.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: bbebd4f885
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex-Nachlauf zu #644. Vier der acht Befunde sind Folgen der Fixes im vorigen Commit - der wichtigste ein Loch, das beim Beheben eines Fehlalarms entstand: - `max-width: 20rem; width: 100%` kam durch. `width` und `max-width` konkurrieren nicht, sie beschraenken gemeinsam; als eine Liste gelesen gewann das erlaubte `100%` und die Kappung stand ungeprueft daneben. Jetzt wird jede Achsen-Gruppe einzeln ausgewertet. - `FILLS` war eingefuehrt, aber nirgends benutzt: beide Ausrichtungs- Zusicherungen lasen weiter eine hartkodierte Liste ohne `revert`, und `align-self: revert` wurde faelschlich abgelehnt. - `:is(.shopping-page .kitchen-rows)` galt als schlichter Selektor, weil die funktionale Pseudoklasse samt Inhalt entfernt wurde. `:is()` und `:where()` gehoeren zum Subjekt - ihr Inhalt wird jetzt mitgelesen, `:not()` und `:has()` fallen weiter weg. - Die Regel-Zusammenfassung gruppierte nach Selektortext. `.kitchen-rows` und `ul.kitchen-rows` treffen dasselbe Element, standen aber als zwei unvollstaendige Eintraege da. Gruppiert wird jetzt nach den Merkmalen im Subjekt. Dazu vier eigenstaendige Luecken: - `@starting-style` galt als unbedingt. Es liefert Uebergangs-Startwerte, nicht die normale Darstellung; datepicker.css nutzt es bereits. - Eine At-Rule INNERHALB einer Style-Regel trug Deklarationen fuer den Elternselektor, die der Parser verwarf. - Die kanonische Token-Pruefung nahm die erste :root-Deklaration; eine spaetere `--content-max-width-narrow: none` schlaegt sie. - `list.style.marginInlineEnd` blieb ungeprueft - der Inline-Scan kannte Breiten und Ausrichtung, aber keine Margen. 69 Mutationen belegen den Stand, davon elf, die gruen bleiben muessen.
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e3586bd4f4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex-Nachlauf zu #644, dritte Runde. Ein Fehlalarm, fuenf Luecken: - `margin-inline-end: 20rem; margin: 0` wurde als Verstoss gemeldet. Der Shorthand setzt die Langform zurueck, die Marge ist null. Die Margen werden jetzt in Deklarationsreihenfolge aufgeloest statt gesammelt. - `.kitchen-rows:not(.uncapped)` galt als unbedingte Kappung. In targets() muessen :not() und :has() wegfallen - sie sagen dort nur, dass die Klasse nicht das Subjekt ist. Fuer die Frage, ob eine Kappung IMMER gilt, sagen dieselben Pseudoklassen das Gegenteil: sie knuepfen sie an eine Bedingung. Sie bleiben hier jetzt stehen. - `--content-max-width-narrow: 720px bogus` kam durch: die Pruefung war auf ein Praefix statt auf den ganzen Wert verankert. - Ein frueheres `:root { --content-max-width-narrow: none !important }` schlug den gueltigen Wert dahinter. `!important` gilt auch zwischen Regeln, nicht nur innerhalb einer; die kanonischen Rumpfe werden jetzt zusammen ausgewertet. - `list.style.setProperty('margin-inline-end', …)` blieb ungeprueft. - Beim Zusammenfassen ging der Vorfahren-Kontext verloren, wodurch `.context-a .kitchen-rows` und `.context-b .kitchen-rows` in einen Topf fielen - der Guard hielt das Clipping fuer ausgeglichen, das in Kontext A besteht. Kontextfreie Regeln zaehlen weiter ueberall. 75 Mutationen belegen den Stand, davon 15, die gruen bleiben muessen.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1ccdf96aa7
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Codex-Nachlauf zu #644, vierte Runde. Beide Befunde sind Folgen der Fixes im vorigen Commit: - `margin-inline-end: 20rem !important; margin: 0`. Die neue Margen-Kaskade las die Wichtigkeit nicht mit, also loeschte der gewoehnliche Shorthand eine wichtige Langform, die im Browser stehen bleibt. Jede Achse merkt sich jetzt, ob ihr Wert wichtig gesetzt wurde. - `.kitchen-rows:hover { align-self: start }` glich eine Luecke aus, die im Ruhezustand besteht. Neben dem Vorfahren-Kontext gehoert auch der Zustand des Subjekts zum Schluessel; zustandsfreie Regeln zaehlen weiter ueberall, zustandsgebundene nur in ihrem eigenen. 77 Mutationen belegen den Stand, davon 15, die gruen bleiben muessen.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a25928bb57
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| assert.doesNotMatch(src, new RegExp(`\\b${name}\\.style\\.margin(?:Inline|Left|Right)?[A-Za-z]*\\s*=`), | ||
| `${page}.js setzt eine Inline-Marge am Scroller - die zieht als gestrecktes Flex-Item direkt von seiner Breite ab`); |
There was a problem hiding this comment.
Reject bracket-notation inline margins
Fresh evidence after the setProperty fix is that bracket notation still bypasses every inline-margin pattern. On a JavaScript-built scroller, list.style['marginInlineEnd'] = '20rem' shortens the stretched element's wheel-hit area just like the dot-property form, but the audit remains green because this regex requires .style.margin...; include equivalent bracket-property assignments in the scan.
Useful? React with 👍 / 👎.
| const tokenValue = declaredValue(canonicalBodies, '--content-max-width-narrow'); | ||
| assert.ok(tokenValue !== null, | ||
| 'tokens.css muss --content-max-width-narrow unbedingt in :root definieren - ohne die Deklaration löst var(…) auf nichts auf und die Kappung entfällt'); | ||
| assert.match(tokenValue, /^(?:\d+(?:\.\d+)?(?:px|rem|em|ch|ex|vw|vmin|vmax|%)|(?:min|max|clamp|calc)\(.*\))$/, |
There was a problem hiding this comment.
Validate function bodies in the canonical width token
Fresh evidence beyond the previously fixed prefix match is that the anchored regex accepts arbitrary contents inside supported function names. For example, --content-max-width-narrow: calc(1px +) passes this assertion, but substitution produces an invalid max-width, so the browser falls back to an uncapped list while the audit stays green; validate the function grammar rather than only its outer name and parentheses.
Useful? React with 👍 / 👎.
| .replace(/:(?:not|has)\([^)]*\)/g, '') | ||
| .replace(/:(?:is|where)\(([^)]*)\)/g, '$1') | ||
| .trim().split(/[\s>+~]+/).pop() ?? ''; | ||
| return new Set(subject.match(/[.#][\w-]+/g) ?? []); |
There was a problem hiding this comment.
Preserve element types when combining clipping rules
Fresh evidence beyond the ancestor/state fixes is that subjectKeys() still discards the subject's element type. If the base .kitchen-rows rule keeps its cap and overflow: hidden but the alignment fix moves to div.kitchen-rows { align-self: start; }, this combiner applies that fix to the same key and the audit passes; however, the recipe list is an ul.kitchen-rows, so it remains stretched and clips its rows. Keep type selectors in the element identity while still allowing an untyped rule to match every type.
Useful? React with 👍 / 👎.
| const sharedRules = scopedRules(shared) | ||
| .flatMap(({ selectors, body }) => selectors.map((sel) => ({ | ||
| keys: subjectKeys(sel), context: contextOf(sel), state: stateOf(sel), sel, body, | ||
| }))) |
There was a problem hiding this comment.
Preserve conditional contexts when combining clipping rules
Fresh evidence after the at-rule parsing fixes is that this projection drops each rule's conditional flag before declarations are combined. Removing the base align-self and placing .kitchen-rows { align-self: start; } inside @media (max-width: 1px) leaves the audit green because the conditional declaration is merged with the unconditional cap and overflow, although at every normal viewport the list remains stretched and clipped. Conditional rules must not satisfy the unconditional clipping fix.
Useful? React with 👍 / 👎.
| const canonicalBodies = allRules | ||
| .filter(({ file, selectors, conditional }) => file === 'tokens.css' && !conditional | ||
| && selectors.some((sel) => /^:root\b/.test(sel))) | ||
| .map(({ body }) => body).join(';'); |
There was a problem hiding this comment.
Honor selector specificity for canonical token rules
Fresh evidence after the cross-rule !important fix is that concatenating rule bodies still reduces the cascade to source order and discards selector specificity. With an earlier :root:not(.unused) { --content-max-width-narrow: none; } followed by the normal :root declaration, the more-specific earlier rule wins in the browser and leaves the lists uncapped, while declaredValue() selects the later 720px body and the audit passes. Either carry selector specificity into winner selection or accept only the exact canonical :root selector.
Useful? React with 👍 / 👎.
Nachlauf zu #643. Codex hat seine Bewertung des letzten Commits erst nach dem Merge abgegeben - sieben Befunde, alle nachvollzogen, alle umgesetzt.
Zwei davon waren Fehlalarme
Die schwerere Kategorie: der Guard hätte korrekten Code blockiert.
.recipes-list { max-width: none }@layer components { … }Beide hatten dieselbe Ursache: geprüft wurde die Anwesenheit einer Eigenschaft bzw. das
@am Präludium, nicht die Wirkung. Jetzt zählt der Wert, und At-Rules werden nach Bedeutung unterschieden - einschränkend sind@media,@supports,@container,@scope;@layerordnet nur die Kaskade.Fünf echte Lücken
.recipes-list { & { max-width: 20rem } }wurde still übersprungen: der flache Scanner nahm die erste schließende Klammer als Rumpfende. Dieselbe Klasse wie der@import-Fehler aus der letzten Runde - der Guard prüfte weniger, als er behauptet. Er balanciert jetzt und liest verschachtelte Regeln mit aufgelöstem Selektor mit.--content-max-width-narrow: none. Die Existenzprüfung nahm jeden Wert. Der Token muss eine Breite sein, sonst lösen beide Kind-Deklarationen auf nichts auf..shopping-page .kitchen-rows. Erfüllte die Kind-Zusage, ohne die Rezeptliste je zu treffen. Der erfüllende Selektor darf das Element weder über einen Vorfahren noch über einen Zustand einschränken.overflowin getrennten Regeln. Der Browser sammelt die Deklarationen aller passenden Regeln, bevor er den Wert bestimmt. Eine Prüfung pro Block sah in keinem von beiden ein gekapptes, clippendes Element - und genau das war es.margin-inline-end: 20rem. Als gestrecktes Flex-Item zieht eine Inline-Marge direkt von der Randbox ab, ganz ohne Breitenangabe. Dermargin-Shorthand zählt mit.Verifikation
61 Mutationen, jede mit erwartetem Ausgang, 0 Abweichungen. Davon zehn, die grün bleiben müssen - sie belegen, dass der Guard korrekte Arbeit nicht blockiert:
:not(),:has(), Pseudo-Elemente, Kind-Selektoren,width: 100%,align-self: stretch,max-width: none,width: auto,@layer, harmlose Custom Properties.npm testvollständig: 2660 grün, 0 rot. Kein CSS geändert.Bekannte Grenzen
Unverändert die zwei aus #643, beide brauchen Kaskade oder DOM: ein struktureller Selektor auf ein geschütztes Element (
.recipes-list > ul) und eine Ausrichtung, die von einem Vorfahren kommt (align-itemsam Container).