Skip to content

fix(parser): improve support for scss files - #44

Merged
jo16oh merged 6 commits into
mainfrom
add-scss-support
May 5, 2026
Merged

fix(parser): improve support for scss files#44
jo16oh merged 6 commits into
mainfrom
add-scss-support

Conversation

@jo16oh

@jo16oh jo16oh commented May 5, 2026

Copy link
Copy Markdown
Owner

Summary

Parser-level SCSS support so cvk can lint .scss files without dropping definitions or corrupting brace tracking on constructs absent from plain CSS.

  • #{ … } interpolation tracking--color: #{$brand}; no longer truncates at the inner }. Block comments inside #{ … } are skipped wholesale so a } in the comment doesn't pop interp_depth.
  • // line comments in all four scan contexts (main loop, at-rule prelude, @property body, value scan). A ; or } inside // … no longer terminates a value or rule. The main loop also captures cvk-ignore directives written as // cvk-ignore[: rule-name]. The at-rule prelude tracks paren_depth so @import url(//cdn.example.com/x.css); still works.

CSS vs SCSS gating

// would silently truncate valid CSS like --link: https://example.com/path (custom-property values may hold raw URLs), so the parser carries a scss flag derived from the file extension and only honors // when the source is .scss. #{ … } tracking is on for both modes — it's harmless on CSS and keeps the implementation simple.

Test plan

  • cargo test -p css-var-kit (full suite green; SCSS tests use a new test_parse_scss helper)
  • cargo clippy -p css-var-kit --all-targets -- -D warnings
  • CSS-mode regressions pinned: --link: https://… keeps its full value; literal // in a value stays as bytes; // cvk-ignore does not suppress in .css.

jo16oh and others added 6 commits May 5, 2026 09:46
`scan_value_end` previously treated any `}` at paren depth 0 as a value
terminator, so `--color: #{$brand};` was cut to `#{$brand` and the
following `}` of the interpolation was mistaken for the rule's closing
brace, throwing brace tracking off.

Track `#{ … }` as a balanced group alongside parens, and gate the `;`,
comment, and missing-semicolon-recovery branches on `interp_depth <= 0`
so SCSS interpolations parse cleanly inside any value.

Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Verify that the universal at-rule descent (@mixin, @if/@else, @each,
@function) correctly collects definitions and var() references from
SCSS-only at-rule bodies, and that statement-form @return inside a
@function body doesn't pollute the property list.

@each uses #{$name} interpolation and depends on the preceding
scan_value_end interpolation-depth tracking.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`scan_value_end` gated the `/* … */` skip on `interp_depth <= 0`, so a
block comment inside `#{ … }` was advanced byte-by-byte. A `}` inside
the comment then matched the interpolation-close arm, popping
interp_depth one step early — the real interpolation closer was treated
as the rule's `}` and trailing properties were silently dropped.

Add a dedicated `b'/' if peek == b'*' && interp_depth > 0` arm that
consumes the comment wholesale, leaving interp tracking intact.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The parser previously advanced through `//` byte-by-byte, so a `;` or
`}` inside a SCSS line comment terminated the surrounding value or
popped brace_depth, silently dropping later definitions.

Add `Scanner::skip_line_comment` and call it in the four scan
contexts: the main loop, at-rule prelude, `@property` body walker,
and `scan_value_end`. In `scan_value_end` outside parens/interp the
comment terminates the value (mirroring `/* … */`); inside
interpolation it is skipped so a `}` in the comment doesn't pop
interp_depth; inside parens the bytes are kept verbatim so
protocol-relative URLs like `url(//cdn.example.com/x.png)` parse
unchanged. The at-rule prelude tracks paren_depth for the same
reason — `@import url(//cdn.example.com/x.css);` must still work.

cvk-ignore is intentionally not honored on `//` comments; pairing it
with line comments is a separate enhancement.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous commit always treated `//` as a line comment, which silently
truncates valid CSS like `--link: https://example.com/path` because the
custom-property value is allowed to hold raw URLs. Branch the behavior
on file extension instead: the parser now tracks a `scss` flag derived
from the file path and only honors `//` line comments when the source
is `.scss`.

`#{ … }` interpolation tracking and the universal at-rule body descent
are unaffected — neither construct is meaningful in CSS, so applying
them everywhere is harmless and keeps the implementation simple.

Add `test_parse_scss` for SCSS-mode tests, switch the `scss_line_comment_*`
and `scss_protocol_relative_url_*` tests onto it, and pin the CSS-mode
behavior with two regressions: `--link: https://…` keeps its full value
and a literal `//` in a value stays as bytes.

Drop the long-unused `initial_brace_depth` parameter on `parse_impl` —
both call sites passed `0` and dropping it keeps the signature within
clippy's argument-count limit after adding `scss`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The previous SCSS line-comment arm just skipped to EOL. Authors writing
`.scss` had no way to use `//` for `cvk-ignore` directives, even though
that is the natural comment style in SCSS sources.

Add `Scanner::scan_line_comment` that mirrors `scan_comment` (returns
the trimmed body) and upgrade the main loop's SCSS-only `//` arm to
run the same chain-tracking shape the block-comment arm uses: track
`comment_start_line` for blank-line breaks, scan content, update
`last_comment_end_line`, and push to `pending_ignores` when the body
starts with `cvk-ignore`. The other three line-comment sites
(`skip_at_rule_prelude`, `scan_at_property_rule`, `scan_value_end`)
keep using `skip_line_comment` — they sit in positions where the
directive would be meaningless, matching how `/* … */` is treated.

The CSS gate is preserved: in `.css` files the arm never fires and
`// cvk-ignore` produces no suppression — pinned by a regression test.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jo16oh jo16oh changed the title feat(parser): support SCSS syntax in .scss files fix(parser): improve support for scss files May 5, 2026
@jo16oh
jo16oh merged commit 827abb6 into main May 5, 2026
8 checks passed
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.

1 participant