Skip to content

Fix CSS plugin incorrectly grouping global rules inside @media blocks - #73

Merged
Dan Marshall (danmarshall) merged 3 commits into
mainfrom
copilot/fix-9b059d06-ec1c-4842-9aa2-7a0563199321
Sep 8, 2025
Merged

Fix CSS plugin incorrectly grouping global rules inside @media blocks#73
Dan Marshall (danmarshall) merged 3 commits into
mainfrom
copilot/fix-9b059d06-ec1c-4842-9aa2-7a0563199321

Conversation

Copilot AI commented Sep 8, 2025

Copy link
Copy Markdown
Contributor

Problem

The CSS plugin had a bug where CSS rules appearing after @media rules were incorrectly parsed as being inside the @media block instead of remaining in global scope. This caused CSS like:

#foo { color: red; }
#baz { color: red; }
@media (max-width: 768px) { body { grid-template-columns: 1fr; } }

To be incorrectly rendered as:

#foo {
  color: red;
}

@media (max-width: 768px) {
#baz {
  color: red;
}

body {
  grid-template-columns: 1fr;
}
}

Instead of the correct:

#foo {
  color: red;
}

#baz {
  color: red;
}

@media (max-width: 768px) {
body {
  grid-template-columns: 1fr;
}
}

Root Cause

The categorizeCss() function used a single currentAtRuleSignature variable to track parsing context. When encountering an @media rule with a block, this variable was set to the @media context but never reset back to global context. This caused all subsequent rules to be incorrectly associated with the @media context regardless of their actual location in the CSS structure.

Solution

  1. Replaced broken context tracking: Removed the problematic currentAtRuleSignature approach and implemented proper AST-based context detection.

  2. Added findAtRuleContext() function: This function walks the CSS AST to determine the correct parent context for each rule by checking if the rule node is actually inside an at-rule's block.

  3. Implemented two-pass processing:

    • First pass: Collect all at-rules and rules with their correct contexts
    • Second pass: Process declarations for each rule
  4. Fixed TypeScript ES5 compatibility: Updated code to work with older TypeScript targets by replacing Object.values(), .includes(), and problematic function declarations.

Impact

  • ✅ CSS rules now correctly appear in their intended contexts (global vs media)
  • ✅ Maintains all existing security checks and validation logic
  • ✅ No breaking changes to the plugin API
  • ✅ Backward compatible with existing CSS processing

The fix ensures that CSS arrays are parsed correctly, with rules appearing in their proper contexts based on the actual CSS structure rather than processing order.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Co-authored-by: danmarshall <11507384+danmarshall@users.noreply.github.com>
Copilot AI changed the title [WIP] The css plugin has a bug: this css "css": [ "body { font-family: sans-serif; margin: 0; padding: 20px; background: #f8fafc; max-width: 1200px; margin: 0 auto; }", "#header, #habits, #table, #monthly, #heatmap { background: white; paddin... Fix CSS plugin incorrectly grouping global rules inside @media blocks Sep 8, 2025
@danmarshall
Dan Marshall (danmarshall) marked this pull request as ready for review September 8, 2025 15:16
@danmarshall
Dan Marshall (danmarshall) merged commit 26e3995 into main Sep 8, 2025
4 checks passed
@danmarshall
Dan Marshall (danmarshall) deleted the copilot/fix-9b059d06-ec1c-4842-9aa2-7a0563199321 branch September 8, 2025 15:16
@danmarshall

Copy link
Copy Markdown
Collaborator

Copilot this was merged, and the branch was deleted. but i found a new bug, which was that the media ordering is not preserved. so some media queries that were supposed to be last in order are now overridden by base rules

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants