Skip to content

Releases: NSNet21/css-bridge

v1.3.0 — CSS variable jump

10 May 13:35

Choose a tag to compare

CSS Bridge v1.3.0 — CSS variable jump

F12 and Ctrl+Click now navigate between var(--foo) calls and --foo: definitions, with multi-theme disambiguation, hover preview, and full reverse-lookup.

What's new

CSS variable jump (#2)

  • Forward jumpF12 / Ctrl+Click on var(--primary) lands on its --primary: definition. If multiple themes define the same name (:root light + .theme-dark etc.), the QuickPick disambiguator lists all of them so you can pick the one you want.
  • Reverse navigationF12 on a --primary: definition lists every var(--primary) site across the project.
  • Hover on var(--foo) — shows every definition: selector → value · file:line.
  • Hover on --foo: — summarizes how many places consume it, with the first eight sites listed inline. Shows *no usages found in scope* when the variable is orphaned (handy for dead-code detection).
  • Fallback & nested formsvar(--primary, blue) and var(--a, var(--b)) resolve correctly. The fallback text isn't treated as a separate variable.
  • Multi-theme disambiguation reuses the existing QuickPick UI; selector path and var path live side-by-side without conflict.

Diagnose

CSS Bridge: Diagnose now reports per-file Var defs / Var uses counts plus the cursor-detected variable with its forward/reverse target list — so you can verify scope and lookup without having to F12 manually.

Internals

  • New parseVars(filePath) in src/parsers/cssParser.ts:
    • Definitions via postcss walkDecls(/^--/) so the parent rule's selector (:root / .theme-dark) is captured for theming context.
    • Usages via regex over comment-stripped content; comments are replaced with same-length whitespace so absolute offsets stay accurate.
    • Cached separately from parseSelectors (mtime-keyed, independent map) — keeps the v1.0–v1.2 selector path completely untouched.
  • New CSS-only CssBridgeCssHoverProvider in src/providers/hover.ts — registered on language: 'css' only; the JSX hover provider is unchanged.
  • getCssVarAtCursor in src/providers/definition.ts anchors detection on the -- prefix so cursor anywhere from the leading - through the last name char resolves to the same range.
  • cssWatcher.onDidChange/onDidDelete now also invalidates the var cache.
  • showDisambiguationPick gained a previewMode: 'next' | 'same' option — selectors keep the existing "next-line" preview (so the rule body is shown), variables use "same-line" so the declaration itself is the visible preview.

Backward compatibility

  • Untouched: all v1.0/v1.1/v1.2 features. parseSelectors signature unchanged. getCssTokenAtCursor unchanged. JSX hover provider unchanged.
  • ⚠️ Refactored but invisible: cssParser.ts adds new exports + new cache map. definition.ts provideDefinition adds a new branch — only fires when cursor is on var() or a --def; existing logic for .foo / #bar runs after and is unaffected.
  • 🎯 Intentional behavior change: F12 on var(--foo) previously fell through to VS Code's default; now CSS Bridge intercepts and jumps. F12 on --foo: previously fell through; now finds usages. Hover on var(--foo) adds CSS Bridge's tooltip alongside VS Code's color preview — they coexist without conflict.

Verified

  • 13/13 cases pass on node scripts/smokeVars.js (single :root / multi-theme / fallback / nested / block-comment / local def+use / orphan / whitespace / multi-line / kebab-case / @media wrap)
  • Part A fixture tests N1-N13 ✅ (incl. multi-theme QuickPick + Esc cancel + tooltip rendering + orphan empty-state + cache invalidation on save)
  • Part B regression R1-R9 ✅ (className jump, dynamic className 15 attr-expr, hover multi-match, reverse-nav, atomic rename totalEdits=2, JSX/CSS autocomplete, Code Action Create rule)

Lessons learned

  1. Nested CSS block comments don't work — writing the literal */ sequence inside a /* ... */ description silently breaks postcss parsing. Caught the bug in our own fixture mid-test (defs=0, uses=12 with one false-positive). Same-length whitespace replacement preserves offsets when stripping comments.
  2. showDisambiguationPick previews the line below by design (selectors land on .foo { and the body is the meaningful preview). For variables the location is the declaration line, so the off-by-one preview showed the next line. Added previewMode option to handle both.
  3. globFiles(scope) carries scope-isolation for free — the same function powers selector reverse-nav (verified 32-package monorepo in v1.2). Var jump inherits boundary detection without any new logic.

How to install

  • VSIX: download css-bridge-1.3.0.vsix from this release and install via Extensions → ... → Install from VSIX...
  • Or via Marketplace: nsnet.css-bridge (will publish shortly)

🤖 Generated with Claude Code

v1.2.0 — Dynamic className + clsx/classnames helpers

10 May 10:54

Choose a tag to compare

What's New

#10 Dynamic className expressions — F12 / Hover / Rename / Reverse-nav now work inside className={...}. Recognised shapes: template literals (`btn ${active ? 'is-active' : ''}`), conditionals, && / || / ?? short-circuits, string concatenation, arrays, and objects nested inside.

#4 clsx / classnames / cn / cx / twMerge helpers — string-literal arguments (and object keys like { 'btn-active': flag }) are scanned alongside className="...". Custom helper names extend the list via the new setting.

New setting

  • cssBridge.classNameHelpers — array of function names treated as className helpers. Default: ["clsx", "classnames", "cn", "cx", "twMerge"]. Add your own (e.g. cva, project-specific helpers).

Performance

  • Pre-warm parse on file open so the first F12 inside className={...} doesn't pay the inline parse cost
  • 80 ms parse throttle for fast typing inside expressions
  • CodeAction lightbulb skips the AST fallback to keep typing snappy on big files

Internals

  • New AST-based class index module — single @babel/parser walk per file, mtime + document-version cached, replaces the per-feature regex scanners. Keystroke fast-path on plain className="..." preserved (no parse cost).
  • Diagnose command now reports class-index counts (attr-string / attr-expr / helper) and the source label of the cursor token, so you can verify dynamic detection without speculation. CSS-side diagnose also surfaces Detected selector + JSX usages count.

Trade-off (intentional)

Ctrl+. "Create rule" Quick Fix now fires only on plain className="..." — not on dynamic {...} or clsx(...) arguments. Rationale: dynamic class names are typically intentional logic (e.g. isActive && 'btn-active') rather than typos. Keeps the lightbulb noise-free on big files.

Verified

  • AST walker shape smoke tests 14/14
  • Stress fixture (677 lines, 1141 tokens, 540 className occurrences across 9 dynamic shapes × 60 blocks) — rename roundtrip 309 edits, reverse-nav 308 locations instant
  • Real 32-package monorepo workspace — scope-isolated rename (no leak across sub-projects)
  • All v1.0.x / v1.1.x regression tests pass

Install

Download the .vsix below, then:

code --install-extension css-bridge-1.2.0.vsix

Or grab from the Marketplace.

v1.1.1 — verbose polish + README docs

10 May 00:15

Choose a tag to compare

Polish

  • Toggling cssBridge.verboseLogging on now surfaces the output channel automatically. Previously the channel was silently writing log entries but stayed hidden until you ran CSS Bridge: Show Output Log — confusing if you'd just flipped the setting expecting to see logs.

Docs

  • README updated with the v1.1.0 features (Hover Preview, Workspace CSS Union, Aliased imports), 3 new settings, and a Commands reference table.

Install

Download `css-bridge-1.1.1.vsix` below and install via:
```
code --install-extension css-bridge-1.1.1.vsix
```

🤖 Generated with Claude Code

v1.1.0 — Workspace CSS Union, Aliased imports, Hover, Diagnose

09 May 23:54

Choose a tag to compare

✨ New features

  • Workspace CSS Union — child components now see CSS imported by ancestors. Common case: App.tsx imports globals.css, child component uses className="container" without re-importing. F12 / Hover / Autocomplete / Code Action all work across the project. Toggle via cssBridge.includeWorkspaceCss (default true).
  • Aliased importsimport '@/styles/globals.css' (or any path alias) now resolves through tsconfig.json / jsconfig.json compilerOptions.paths.
  • Hover preview — hover any className / id to see the matching CSS rule body without leaving the editor. Multi-match preview shows every source.
  • Better project detection — recognizes Vite / Next / Remix / Rsbuild / Webpack monorepos where react is hoisted by workspaces. Replaces the v1.0.x package.json-only boundary check.

🛠️ Diagnose tooling

  • CSS Bridge: Show Output Log — open the extension's output channel.
  • CSS Bridge: Diagnose — dump scope detection, resolved imports, alias config, workspace CSS pool, and cursor context to the output channel. Paste it when reporting bugs to short-circuit speculation.
  • Auto-diagnose on editor change — opt-in via cssBridge.autoDiagnoseOnEditorChange. Lightweight per-file context dump (~5ms) on tab switch.
  • Verbose logging — opt-in via cssBridge.verboseLogging. Logs every provider call (Hover, Definition, Completion, Rename, CodeAction) for live debugging.

🐛 Fixes (caught via diagnose during dogfooding)

  • Tsconfig JSONC parser was greedy-matching /* in \"@/*\" through */ in \"src/**/*\", wiping compilerOptions. Replaced with plain JSON.parse first + string-aware fallback.
  • stripComments had the same bug class for JSX — /* in a string literal (e.g. '@styles/*') through */ of a JSX comment blanked the whole className line, breaking F12/Hover/CodeAction. Replaced with a string-aware character scanner.

📦 Install

Download css-bridge-1.1.0.vsix below and install via:
```
code --install-extension css-bridge-1.1.0.vsix
```
or from VS Code: Extensions panel → `…` → Install from VSIX.

🤖 Generated with Claude Code

v1.0.1 — bug fixes

09 May 01:22

Choose a tag to compare

Fixes

  • data-id / aria-id / *-id / *ClassName= no longer falsely matched as id= / className=. Affects Jump, Peek, Autocomplete, and Rename.
  • Reverse navigation (CSS → JSX) and Rename no longer match attribute-shaped text inside JS/JSX comments.
  • CSS-side autocomplete on # now returns id suggestions correctly. Items keep their ./# prefix on accept.

New

  • Ctrl+K Ctrl+P (Peek) now also works from a CSS file — peeks JSX usages of the selector under the cursor.

Perf

  • Cache JSX/TSX import resolution by mtime — no more re-parsing with Babel on every cursor move.

Install

Download css-bridge-1.0.1.vsix below and install via:
```
code --install-extension css-bridge-1.0.1.vsix
```
or from VS Code: Extensions panel → → Install from VSIX.

🤖 Generated with Claude Code

CSS Bridge v1.0.0

08 May 16:45

Choose a tag to compare

Initial release.

Features

  • Jump & Peek — F12 / Ctrl+K Ctrl+P on className/id → CSS rule
  • Reverse Navigation — F12 on CSS selector → JSX/TSX usages
  • Auto-create — Ctrl+. to create missing rule or CSS file + import
  • Autocomplete — className suggestions from imported CSS, and vice versa
  • Project-wide Rename — Alt+R / F2 scoped to nearest package.json

Install

Download \css-bridge-1.0.0.vsix\ and run:
\
code --install-extension css-bridge-1.0.0.vsix
\
Or install directly from VS Code Marketplace.