Preserve block-less at-rules when keep_at_rules is enabled - #768
Merged
Stranger6667 merged 3 commits intoAug 8, 2026
Merged
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #768 +/- ##
==========================================
+ Coverage 92.02% 92.05% +0.02%
==========================================
Files 17 17
Lines 2584 2593 +9
==========================================
+ Hits 2378 2387 +9
Misses 206 206 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
AtRuleFilteringParser writes `@` + the rule name in parse_prelude and
appends the prelude and body in parse_block, but never implements
rule_without_block, so an at-rule terminated by a semicolon instead of
a block (e.g. `@import`) left a bare `@import` fused to the following
rule: `@import@media (max-width: 600px) { ... }`. Browsers treat that
as one invalid rule and discard the entire stylesheet, so enabling
keep_at_rules could remove every kept at-rule's effect whenever an
`@import` preceded them.
Implement rule_without_block to emit the prelude and a terminating
semicolon, matching how parse_block emits blocked at-rules.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jmortlock
force-pushed
the
fix-keep-at-rules-without-block
branch
from
August 8, 2026 08:04
b44dbe2 to
08b9e0b
Compare
Pre-existing CI failures unrelated to this change: clippy 1.97's new question_mark and useless_borrows_in_formatting lints fire on element.rs sibling traversal, attr_value.rs and the profiler's panic message under -D warnings, and the pre-commit prettier hook (v4.0.0-alpha.8) reformats bindings/javascript/wasm/index.html. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
jmortlock
force-pushed
the
fix-keep-at-rules-without-block
branch
from
August 8, 2026 08:09
08b9e0b to
5a6e381
Compare
Stranger6667
approved these changes
Aug 8, 2026
Owner
|
Awesome! Thank you :) Could you please add the same changelog entry to all the bindings? as it is a user-visible change for non-rust users |
The fix is user-visible in every language binding, so the Python, Ruby, Java, C, PHP and JavaScript changelogs each get the same entry under Unreleased, using each binding's own option spelling (keep_at_rules / keepAtRules). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Author
|
Done — added the same entry under |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With
keep_at_rules: true, an at-rule terminated by a semicolon instead of a block —@importbeing the common case — loses its prelude and terminator.AtRuleFilteringParserwrites@+ the rule name inparse_preludeand appends the prelude/body inparse_block, but never implementsrule_without_block(whose default rejects the rule), so the already-written bare@importfuses with the following rule:Browsers treat the fused text as one invalid rule and discard it — in Chromium the resulting
<style>sheet parses tocssRules.length === 0— so a single@importsilently disables every at-rule the option was meant to keep. We hit this inlining MJML email output, where the responsive@mediablock stopped applying on mobile clients.Fix
Implement
rule_without_blockto emit the prelude and a terminating semicolon, mirroring howparse_blockemits blocked at-rules:Includes a regression test (fails on master with the fused output above) and a changelog entry. Full suite passes locally apart from the four tests that need the
127.0.0.1:1234stylesheet server.🤖 Generated with Claude Code