Skip to content

Latest commit

 

History

10 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

datastar.nvim — syntax highlighting for Neovim

datastar.nvim

Syntax highlighting for Datastar attributes in Neovim.

The syntax highlighter supports html, htmldjango, jinja, twig, liquid, and javascript (html tagged templates only). It recognizes the pinned built-in Datastar attribute inventory plus explicitly configured custom plugin names, highlights attribute names and selected tokens in eligible quoted values, and leaves ordinary HTML and template presentation to the host runtime.

See the changelog for release history.

Unofficial project

datastar.nvim is an independent, unofficial community plugin. It is not affiliated with, endorsed by, sponsored by, or maintained by the Datastar project or Star Federation. The Datastar name is used solely to describe compatibility with Datastar attributes and expressions.

AI-assisted development

Large language models (LLMs) were used to help generate portions of this project's code and documentation. All LLM-assisted content was reviewed and approved by the author, who remains responsible for the final work.

Requirements

  • Neovim 0.10 or newer.
  • An externally installed HTML Tree-sitter parser that Neovim can discover.
  • For javascript buffers, an externally installed JavaScript Tree-sitter parser.

The parsers are not bundled. If you use nvim-treesitter, install html (and javascript for JavaScript buffers) using its normal installation flow (for example, :TSInstall html javascript). Parser files on Neovim's runtime path are the usual installation shape, but any parsers Neovim can discover and use satisfy the requirement. The plugin does not fall back to a Vim syntax implementation.

Installation

The plugin initializes itself when its plugin/ file is loaded. For a normal, start-loaded plugin installation, no Lua configuration is needed.

vim-plug

Plug 'MarcusL11/datastar.nvim'

packer.nvim

use "MarcusL11/datastar.nvim"

lazy.nvim

Load it for the supported filetypes:

{
  "MarcusL11/datastar.nvim",
  ft = { "html", "htmldjango", "jinja", "twig", "liquid", "javascript" },
}

Lazy managers may also call setup explicitly. This is safe: setup() is idempotent and replaces the plugin's autocmd group rather than accumulating handlers.

{
  "MarcusL11/datastar.nvim",
  ft = { "html", "htmldjango", "jinja", "twig", "liquid", "javascript" },
  opts = {
    custom_attributes = {
      "my-plugin",
      "custom-action",
    },
  },
}

Custom names are supplied without data- and must be lowercase kebab-case matching ^[a-z][a-z0-9]*(%-[a-z0-9]+)*$ in Lua-pattern notation. Duplicate names and collisions with built-ins are harmlessly deduplicated. The plugin copies the input, so mutating the caller's table later has no effect.

Only custom_attributes is accepted. Options must be a table and custom_attributes must be a dense array of valid strings; malformed input raises an actionable error without changing the active configuration, callbacks, or marks. setup() and setup(nil) preserve and reapply the current configuration. Passing a table replaces the complete explicit configuration from defaults, so setup({}) clears all custom names. Configuration changes immediately refresh loaded supported buffers without adding callbacks.

There is intentionally no generic filetype option. See :help datastar.nvim after generating help tags if your plugin manager does not do so.

Supported syntax

In supported HTML buffers and html tagged templates in JavaScript, the highlighter recognizes these lowercase built-in Datastar attribute names:

animate                 attr                  bind
class                   computed              custom-validity
effect                  ignore                ignore-morph
indicator               init                  json-signals
match-media             nonce                 on
on-intersect            on-interval           on-raf
on-resize               on-signal-patch       on-signal-patch-filter
persist                 preserve-attr         query-string
ref                     replace-url           scroll-into-view
show                    signals               style
text                    view-transition

A recognized built-in or configured custom name starts with data-<name> and may continue with :<key> segments (including well-formed dotted keys) and __<modifier> segments with an optional .argument. A complete recognized name can be highlighted even when the attribute has no value. While a name is being edited, completed name pieces may still be highlighted, but a malformed or incomplete suffix does not activate value tokenization.

Value tokenization is a separate step. It runs only for a complete recognized lowercase name whose value HTML parses as quoted. Unknown or ordinary data-*, ARIA attributes, comments, text, and unquoted values do not activate Datastar value highlighting.

Within an eligible quoted value, the supported highlighting contract is deliberately bounded:

  • $name and $$name signals; called @action forms; function and method calls.
  • Single- and double-quoted strings and backslash escapes.
  • Decimal numbers and the literals true, false, and null.
  • Operators: === !== && || ?? == != >= <= ++ -- += -= *= /= %= + - * / % > < ! = ? :.
  • Object/array punctuation { } [ ] , ;, call parentheses, access dots, and object keys in { key: value } positions.

These are highlighting boundaries, not JavaScript parsing or expression validation. Complete {% ... %} and {{ ... }} template fragments inside a value are host-owned holes in htmldjango, Jinja, Twig, and Liquid: no Datastar mark overlaps them, and surrounding string state resumes after the hole. Whitespace-control forms use the same boundaries. An unclosed {% or {{ stops Datastar tokenization through the end of that attribute value (fail closed).

In javascript buffers, only direct html tagged template literals are parsed as HTML. Ordinary strings, untagged templates, other tags, and comments are ignored. ${...} is JavaScript-owned: a complete Datastar name outside the substitution may still be marked, but an attribute value intersecting any substitution gets no Datastar value marks. Independent attributes after a substitution resume normally. JavaScript highlighting and filetype remain unchanged.

Highlight customization

The plugin defines default links only; it does not set colors. Override any group after your colorscheme, for example:

vim.api.nvim_set_hl(0, "DatastarSignal", { fg = "#7aa2f7", bold = true })
vim.api.nvim_set_hl(0, "DatastarAction", { link = "Special" })

Available groups are DatastarAttributePrefix, DatastarPlugin, DatastarKeySeparator, DatastarKey, DatastarModifierSeparator, DatastarModifier, DatastarModifierArgumentSeparator, DatastarModifierArgument, DatastarSignal, DatastarAction, DatastarFunctionCall, DatastarMethodCall, DatastarString, DatastarEscape, DatastarNumber, DatastarBoolean, DatastarNull, DatastarOperator, DatastarPunctuation, DatastarObjectKey, DatastarAccessor, and DatastarCallPunctuation. Defining the plugin's default links does not replace an override that still exists. Because a colorscheme may clear overrides, apply your overrides after the colorscheme.

Troubleshooting

  • No Datastar highlighting: confirm :echo has('nvim-0.10') is 1, then install and make the HTML parser discoverable by Neovim. A missing parser emits this warning at most once per session: datastar.nvim: the HTML Tree-sitter parser is required for Datastar highlighting; install it with :TSInstall html (or your parser manager) and reload the buffer; host syntax was left unchanged. Query, parse, and unexpected refresh failures also warn at most once per failure category; check :messages and keep host syntax in place.
  • An attribute value is not highlighted: check that the buffer filetype is exactly html, htmldjango, jinja, twig, liquid, or javascript (with a direct html tagged template); the full attribute name and suffixes are complete and lowercase; and the value is quoted. Custom plugin names must also be configured. Other data-* values are intentionally ignored.
  • A .jinja file is not activated on Neovim 0.10: stock Neovim 0.10 does not detect that extension. Set filetype=jinja through your environment; this plugin supports the filetype but does not install filename-detection rules.
  • No highlighting in a JavaScript template: install both javascript and html Tree-sitter parsers (for example, :TSInstall javascript html). A missing JavaScript parser emits its own deduplicated, actionable warning; ${...} inside a Datastar value suppresses that value's Datastar marks.
  • Template colors look different than HTML: the plugin uses HTML Tree-sitter only as a structural parser. Django, Jinja, Twig, and Liquid retain their own Tree-sitter language identities. It never starts or stops a visible host highlighter.
  • :help datastar.nvim is not found: create help tags for the installed plugin's doc directory with :helptags {path-to-datastar.nvim}/doc.

Compatibility and validation

Neovim 0.10+ is the public baseline. CI is configured to build the pinned external HTML and JavaScript parsers and run the suite on Ubuntu with Neovim v0.10.4, v0.11.7, and v0.12.5; its nightly job is non-blocking. A separate macOS job only smoke-tests the Darwin parser-build path, not the plugin suite. No Windows compatibility claim is made.

Run the repository validation contract locally:

./tests/build_parsers.sh
./tests/run.sh --self-test-failure
./tests/run.sh
./tests/run.sh tests/cases/help.lua
./tests/run-version-matrix.sh
git diff --check
git status --short

The dedicated help case generates help tags in a temporary copy and checks that :help datastar.nvim resolves; it does not add doc/tags to the repository. The released-line matrix requires Docker. tests/build_parsers.sh builds local parsers into ignored .deps/; it does not add a parser binary to the repository. See tests/cases/javascript_templates.lua for JavaScript acceptance tests and UPSTREAM.md for pinned source provenance and attribution.

Limitations and non-goals

  • Only html, htmldjango, jinja, twig, liquid, and direct html tagged templates in javascript are supported.
  • Only the listed pinned built-ins and configured lowercase custom plugin names are recognized. Custom metadata, completion, modifier validation, and diagnostics are not provided. Expression highlighting is limited to quoted HTML values.
  • Server-template handling is limited to complete {% ... %} and {{ ... }} holes inside a recognized value. JavaScript ${...} uses the separate fail-closed rule above. Comments, alternate delimiters, and broader template lexical support are not provided.
  • Arrow-function semantics, spread semantics, and interpolation within Datastar expressions are not highlighted.
  • JavaScript support uses bounded parsing of html tagged templates, not host parser injections. There is no Datastar Vim-syntax backend, incremental/decorative rendering backend, LSP, completion, diagnostics, hover, navigation, rename, or signature help.
  • Parser binaries are not bundled, and upstream attribute synchronization is not automatic.

Upstream references

License

MIT

About

Datastar syntax highlighting and language support for Neovim

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages