Skip to content

Editor support

@staticbolt/lsp is the language server for staticbolt projects, built on Volar. It serves HTML and Markdown, and it takes everything it knows from the project's own plugins. There is no second list of tags to keep in sync, so a plugin you add today shows up in completion today.

Terminal window
npm install -D @staticbolt/lsp

What it serves

  • Completion and hover for the tags and attributes the project's plugins declare, with path completion that knows the project's aliases.
  • Links resolved the way the build resolves them, so Ctrl-click lands where the build would.
  • The problems plugins find, reported at the element, attribute, or range they belong to.
  • The code that plugins embed in HTML (<script type="application/x-typescript"> bodies, the layout plugin's {{ placeholders }}), served through TypeScript: completion, hover, diagnostics, semantic tokens, definitions, references, rename, folding, signature help, inlay hints, and code actions.

Running the server

Editors find the server through the @staticbolt/lsp package installed in the project, so installing it is usually the whole setup.

Terminal window
node node_modules/@staticbolt/lsp/lib/index.mjs --stdio

TypeScript

The server runs TypeScript's API in process, so it needs a TypeScript that ships one, which means 6.x. The native 7 builds do not.

It looks for one in this order:

  1. initializationOptions.typescript.tsdk, the directory holding typescript.js (node_modules/typescript/lib for example). The VS Code extension passes VS Code's own TypeScript here unless typescript.tsdk is set in the workspace.
  2. A --tsdk=<directory> argument.
  3. The nearest node_modules/typescript/lib above the working directory that has an API.

If none of the three turns up a TypeScript with an API, the embedded-language features go quiet: completion and hover for tags still work, but everything routed through TypeScript does not.

Teaching it about a plugin

A plugin takes part through three optional hooks. Each is given the document already parsed, as a DocumentInfo: the text, every element with its attributes and ranges, select(...tags), textOf(range), and resolve(source) through the project's aliases.

lspHtmlData()

The tags and attributes the plugin adds, in the VS Code custom data format. This is what becomes completion and hover in the editor.

lspValidate(document, report)

The problems the plugin finds, reported at an element, an attribute, or a range. These are the same problems the build would report, surfaced before the build runs.

lspEmbeddedLanguages()

The code the plugin embeds in HTML:

  • filter selects the files that carry it.
  • findRegions(document) says where it sits in the document.
  • prelude is optional and declares what the embedded code can see.
  • isColouredByEditor is set when the editor's own grammar already colours the regions, so the server does not fight it.

Regions are claimed in config order. A plugin that understands a script better than the core HTML plugin (which sits last in the config) simply claims it first.