Repository navigation
feat(lint): flag CSS rules that select on the inline style attribute - #6261
miguel-heygen wants to merge 2 commits into
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
💡 Tip: Enable Automations to automatically generate PRs for you. |
Edit accuracy: accurate 271 (base branch 271), smooth 142 of thoseThe gate passes. Quarantined, measured but not gated (0) Unstable (2)
|
There was a problem hiding this comment.
Verdict: APPROVE · 0 blocker · 0 important · 1 nit · head b986bf81
- nit
packages/lint/src/rules/core.ts:764— a selector that tripsruntime_hidden_style_opacity(e.g.[style*="visibility: hidden"] { opacity: 0 }) now produces two errors for the same rule. Both give the same fix, so this is only noise. Skip the new finding when the hidden-style one fires if you want a single error.
Scope
Read the full diff. selectsOnInlineStyle walks every attribute node, including those nested in :not()/:is(), and compares names case-insensitively. It runs over resolvedRuleSelectors, which covers inline and linked stylesheets. The runtime's own [style*=…] rules (timedClipHide.ts, pending #5974) are injected by JS and never linted. No skill, template, or doc in the repo still recommends a [style…] guard. The compiler's static guard only warns on errors, so the new rule blocks a render only under --strict. CI passed at this head.
What this fixes
A CSS rule that selects on the inline
styleattribute ([style],[style*=…],[style^=…]and the other attribute forms) makes every inline style write expensive. GSAP writes inline styles on every animated element every frame, so a composition with such a rule plays slowly in the preview:[style*="visibility: hidden"] *). With a few hundred animated elements, that is most of the page on every frame.style.The runtime's own two rules of this kind are removed in #5974. Authored rules of the same shape bring the cost back, and the lint today recommends one: the fix hint for
runtime_hidden_style_opacitysuggests[data-composition-src][style*="visibility: hidden"]guards.Changes
inline_style_attribute_selector(error): flags any selector that reads thestyleattribute, including inside:not()/:is()and in any letter case. It reuses the CSS-selector pass andpostcss-selector-parserthe lint already has, and checks inline<style>blocks and the linked stylesheets the lint already reads. Each selector is reported once. Lint errors block a render only under--strict, as for the other rules.runtime_hidden_style_opacity: no longer recommends a[style…]guard. It now says the runtime already hides a hidden clip and its contents, and to animate on the timeline or toggle a class or data attribute instead. The rule's detection is unchanged: it is about the video replacement frame, and a host-scoped guard does not affect that. The new rule flags such guards for their playback cost.docs/reference/lint-rules.mdx: the new rule, and the corrected fix.Tests
packages/lint/src/rules/core.test.ts:[style],*=,^=,$=,~=,|=, uppercase with theiflag, and inside:not().[data-state],[data-style],[styles],[data-hf-style].runtime_hidden_style_opacityfix hint contains no[style.On
mainthe new tests fail (10 of them). Each was checked by breaking the rule:[style*=…]turns the other forms red.:not()case red.The whole lint suite passes three runs in a row. The lint package typecheck,
bun run lint,oxfmtand thefallowaudit on the changed files are clean.