feat: peek into <style> blocks in HTML/Vue files (#151)#163
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds support for resolving CSS selectors defined in embedded <style> blocks within the same HTML/Vue document, enabling Peek/Go to Definition to jump directly to in-file styles (addressing #151 / “Same File CSS”).
Changes:
- Added embedded
<style>block extraction forhtml/vuedocuments usingvscode-html-languageservicescanning and creation of masked “virtual” CSS documents aligned to host offsets. - Extended
findSymbols/findDefinitionto accept an optional in-memory embedded stylesheet map merged with the existing persistent stylesheet cache. - Added/updated tests and fixtures to validate same-file class/id resolution and to ensure non-HTML/Vue documents don’t produce embedded stylesheets.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
server/src/core/embeddedStyles.ts |
New helper to scan HTML/Vue docs for <style> blocks and produce aligned virtual TextDocuments for symbol extraction. |
server/src/core/findDefinition.ts |
Adds optional embedded stylesheet map support and merges it with the persistent stylesheet cache for symbol/definition lookup. |
server/src/server.ts |
Integrates embedded <style> lookup into the LSP onDefinition path for HTML/Vue documents. |
tests/src/findDefinition.test.ts |
Adds coverage for same-file embedded <style> class/id definitions and non-html/vue behavior. |
tests/fixture/example.html |
Extends fixture with an embedded <style> block and matching usages. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds support for resolving CSS class and ID selectors that are defined in an embedded `<style>` block within the same HTML or Vue file as the source. The HTML language service scanner is used to extract `<style>` regions (respecting `lang="scss|less|sass"` so we pick the right CSS parser), and the embedded contents are wrapped in a virtual TextDocument whose text outside the style region is masked with whitespace. That preserves line and column offsets so peek/goto jumps to the correct line in the host file without any coordinate translation. Only runs for `html` and `vue` languageIds, so non-HTML peek paths are unaffected. Closes #151 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b30df3f to
e65c0ab
Compare
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.
Summary
Closes #151
Adds same-file CSS support: when peeking from a
class="...",id="...", or HTML tag in an HTML or Vue document, the extension now also resolves selectors defined in any<style>block within the same file.server/src/core/embeddedStyles.tsusesvscode-html-languageservice's scanner (already a dep) to locate<style>regions and reads anylang="scss|sass|less"attribute to pick the right CSS parser.TextDocumentreuses the host document's URI and masks everything outside the<style>region with whitespace (preserving newlines), so symbol positions line up exactly with the host file — peek/goto jumps to the correct line without any coordinate translation.findSymbols/findDefinitionaccept an optional in-memoryembeddedStylesheetMapthat's merged with the persistentStylesheetMap. The persistent cache wins on key collision; embedded entries use fragment-suffixed keys so collisions don't happen in practice.htmlandvuedocuments — JS/TS/etc. peek paths are unchanged.Test plan
yarn buildpasses with zero TS errorsyarn lintpassesyarn test— 27 tests pass, including three new cases:<style>block is found in the same HTML file<style>block is found in the same HTML filetests/fixture/example.htmlupdated with a<style>block containing.embedded-classand#embedded-idplus matching usages in the body🤖 Generated with Claude Code