Language Service: Implement @herb-tools/language-service package#1446
Merged
Language Service: Implement @herb-tools/language-service package#1446
@herb-tools/language-service package#1446Conversation
commit: |
🌿 Interactive Playground and Documentation PreviewA preview deployment has been built for this pull request. Try out the changes live in the interactive playground: 🌱 Grown from commit ✅ Preview deployment has been cleaned up. |
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.
This pull request introduces a new package,
@herb-tools/language-service, which provides an HTML+ERB language service with a compatible API tovscode-html-languageservice.It uses the Herb parser to understand both regular HTML elements and ActionView tag helpers, and presents them through the same
LanguageServiceinterface thatvscode-html-languageserviceconsumers expect — making it a drop-in replacement.What it does
The core idea is that
parseHTMLDocumentuses the Herb parser instead of a plain HTML scanner. This means a template like<%= tag.div data: { controller: "scroll" } %>is understood as a<div>with adata-controller="scroll"attribute completions, diagnostics, and navigation all work as expected, just like they would for regular HTML.For completions inside ERB tag helpers, the language service detects the Ruby hash context and adapts accordingly. Inside a
data: {}hash it suggestsactioninstead ofdata-action, and for space-separated attributes likedata-controller="scroll search"it provides per-token completions rather than replacing the entire value.Each node in the parsed document tracks where its attributes actually appear in the source text via
attributeSourceRanges. This is important because ActionView tag helpers synthesize attribute names (e.g.,controller:in Ruby becomesdata-controllerin HTML), so the language service needs to know where to point diagnostics and highlights in the original ERB source.When no Herb instance is provided the service falls back to the upstream
vscode-html-languageserviceparser, so it works as a regular HTML language service too. All types and functions fromvscode-html-languageserviceare re-exported so consumers only need a single import.Stimulus LSP
This package was built with Stimulus LSP as the first consumer in mind.
Stimulus LSP currently uses
vscode-html-languageservicedirectly, which means it has no understanding of ERB. Controller completions, diagnostics, and go-to-definition only work inside regular HTMLdata-controllerattributes.By switching to
@herb-tools/language-service, Stimulus LSP gains full support for ActionView tag helpers like<%= tag.div data: { controller: "scroll", action: "click->scroll#go" } %>with the same completions, diagnostics, and navigation that already work for plain HTML.Usage