feat: CSS/SCSS/LESS support — stylesheets join the code graph#614
Open
CodeBlackwell wants to merge 4 commits into
Open
feat: CSS/SCSS/LESS support — stylesheets join the code graph#614CodeBlackwell wants to merge 4 commits into
CodeBlackwell wants to merge 4 commits into
Conversation
Extend the merged CSS feature to Svelte SFCs, which upstream added after the CSS branch was written: - Shared _extract_style_blocks helper (refactored out of _parse_vue) now also runs in _parse_svelte, so selectors, custom properties, and OVERRIDES edges inside Svelte <style>/<style lang="scss"> blocks land in the graph with correct line offsets. - Static class attributes in Svelte markup are collected onto the File node as css_classes, so link_css_styles creates STYLES edges with no changes; class:foo directives are ignored as dynamic. - .less added to JS and stylesheet import resolution extensions. - First test coverage for _parse_svelte (script + style + linking).
- parser.py: shared _attr_name_value/_tag_attrs helpers replace four copies of the nested SFC attribute-decoding loop (Vue script, Svelte script, style blocks, template class walker). Vue template classes now use the same css_classes extra key as Svelte and JSX. - incremental.py: link_css_styles/detect_cross_file_conflicts moved into the best-effort resolver layer (_run_css_resolver), matching the rescript/spring/temporal contract: run after commit, swallow failures, and skip on incremental updates when no style-relevant file changed. Selector scan now runs once and is shared by both passes; loop-invariant CSS-module File query hoisted out of the per-node loop; duplicate vue_template_classes STYLES loop deleted. - tools/query.py: five hand-rolled CSS query branches collapsed into one _EDGE_WALK_PATTERNS (kind, directions) table walk. - visualization.py: legend class ternary ladder replaced with a LEGEND_CLASS lookup map alongside EDGE_COLOR/EDGE_CFG. Net -35 lines, no behavior change; full suite 1442 green.
This was referenced Jul 9, 2026
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.
Hi! This PR teaches the graph to understand stylesheets, so reviews can see the relationship between components and the CSS that styles them.
What's new
Parsing
.cssand.scssfiles parse via tree-sitter: selectors, custom properties,@media,@keyframes, mixins, and SCSS variables all become graph nodes.lesssupport via a regex fallback (no tree-sitter grammar exists for LESS)<style>/<style lang="scss">blocks are parsed in place, with correct line offsets back into the SFC@importchains resolve to real files, including SCSS partials (_variables.scss)Cross-language edges
className, Vue/Svelte static template classes, and CSS Modules references (styles.btnPrimary→.btn-primary, camelCase→kebab handled) link components to the selectors that style them!importantwins are tracked per propertyTooling
query_graphpatterns:styles_of,styled_by,overrides_of,overridden_by,conflicts_ofDesign notes
Testing
full_build)main: 1437 passed, 1 skippedHappy to adjust anything — naming, edge semantics, or scope. Thanks for the great project!