feat(language-server): understand the api binding attribute
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
cd0dffa87d
commit
29febb2e0c
4 files changed
+187
-3
No files matched your search
@@ -5,6 +5,7 @@
|
||||
// cleanly, so import it explicitly.
|
||||
import {
|
||||
getLanguageService,
|
||||
newHTMLDataProvider,
|
||||
TextDocument as HtmlTextDocument,
|
||||
} from "vscode-html-languageservice/lib/esm/htmlLanguageService.js";
|
||||
import { isInsideHtml, virtualHtmlDocument } from "./html-regions.ts";
|
||||
@@ -19,7 +20,21 @@ export interface HtmlCompletionItem {
|
||||
insertText?: string;
|
||||
}
|
||||
|
||||
const service = getLanguageService();
|
||||
/**
|
||||
* `api="<name>"` / `api="<name>()"` / `api="<name>({ field: value })"` is a
|
||||
* WRNexus data-api binding, not arbitrary markup — declaring it here keeps
|
||||
* the HTML service from treating it as an unrecognized attribute on any
|
||||
* element, without inventing an attribute-value grammar the library would
|
||||
* try to spell-check as prose.
|
||||
*/
|
||||
const wrnexusDataProvider = newHTMLDataProvider("wrnexus", {
|
||||
version: 1,
|
||||
globalAttributes: [
|
||||
{ name: "api", description: "Binds this element to a declared `apis { }` entry." },
|
||||
],
|
||||
});
|
||||
|
||||
const service = getLanguageService({ customDataProviders: [wrnexusDataProvider] });
|
||||
|
||||
/** The virtual document as the HTML service's own document type. */
|
||||
function htmlDocument(document: TextDocument) {
|
||||
@@ -41,8 +56,24 @@ function markdown(value: unknown): string | undefined {
|
||||
* Every item carries the `1` sortText prefix so the server can rank WRNexus
|
||||
* entries above these without filtering either list.
|
||||
*/
|
||||
/**
|
||||
* True when `offset` sits inside the quotes of an `api="…"` attribute value.
|
||||
*
|
||||
* The value is a call expression (`name`, `name()`, `name({ field: value })`),
|
||||
* not prose, so completion there is routed to `apiCallCompletions` instead of
|
||||
* the HTML service's own (text-oriented) attribute-value completion.
|
||||
*/
|
||||
export function isApiAttributeValuePosition(document: TextDocument, position: Position): boolean {
|
||||
const offset = offsetAt(document.text, position);
|
||||
if (!isInsideHtml(document, offset)) return false;
|
||||
|
||||
const before = document.text.slice(0, offset);
|
||||
return /\bapi\s*=\s*(["'])(?:(?!\1)[^\n])*$/.test(before);
|
||||
}
|
||||
|
||||
export function htmlCompletions(document: TextDocument, position: Position): HtmlCompletionItem[] {
|
||||
if (!isInsideHtml(document, offsetAt(document.text, position))) return [];
|
||||
if (isApiAttributeValuePosition(document, position)) return [];
|
||||
|
||||
const virtual = htmlDocument(document);
|
||||
const parsed = service.parseHTMLDocument(virtual);
|
||||
|
||||
Reference in new issue
Block a user