A Language Server Protocol (LSP) implementation for Thymeleaf templates, written in Rust. It brings completion, documentation, diagnostics, and fragment navigation for the Thymeleaf Standard Dialect to any LSP-capable editor.
Status: early but usable. The features below work today; the dialect catalog and expression analysis will keep growing. Feedback and contributions welcome.
| Feature | What you get |
|---|---|
| Completion | The full Standard Dialect attribute surface in tags — the structural processors first, then the generic th:<html-attr> ones — filtered as you type, plus expression syntaxes inside th:* values. Triggers on :. |
| Hover | Documentation for Thymeleaf attributes and expression syntaxes. |
| Diagnostics | Warnings for misspelled th:* attributes (with the intended name); errors for unbalanced expression brackets. |
| Goto-definition / References | Jump between th:fragment definitions and th:insert/th:replace/th:include usages, across the whole workspace. |
| Rename | Rename a fragment everywhere it is defined and referenced. |
| Code actions | Quick-fix a misspelled th:* attribute (nearest-match suggestion) or remove it. |
| Document / workspace symbols | Outline of fragments and id elements; workspace-wide fragment search. |
| Document highlight | Highlight every occurrence of the fragment/attribute under the cursor. |
| Semantic tokens | Highlight th:* names and expression markers. |
| Folding & document links | Element/comment folding; clickable @{...} and href/src URLs. |
From source (requires a Rust toolchain)
cargo install --path .
# or, from a clone:
git clone https://github.com/dozken/thymeleaf_ls
cd thymeleaf_ls
make install # cargo install --path .This installs a thymeleaf_ls binary into ~/.cargo/bin (make sure it is on your PATH).
Download an archive for your platform from the Releases page, extract the thymeleaf_ls binary, and put it somewhere on your PATH.
The server communicates over stdio and targets HTML documents (filetype/languageId = html). Point your editor's LSP client at the thymeleaf_ls binary for HTML files.
vim.lsp.config.thymeleaf_ls = {
cmd = { "thymeleaf_ls" },
filetypes = { "html" },
root_markers = { "pom.xml", "build.gradle", "build.gradle.kts", ".git" },
}
vim.lsp.enable("thymeleaf_ls")Neovim with nvim-lspconfig (older setups)
local configs = require("lspconfig.configs")
local lspconfig = require("lspconfig")
if not configs.thymeleaf_ls then
configs.thymeleaf_ls = {
default_config = {
cmd = { "thymeleaf_ls" },
filetypes = { "html" },
root_dir = lspconfig.util.root_pattern("pom.xml", "build.gradle", ".git"),
settings = {},
},
}
end
lspconfig.thymeleaf_ls.setup({})Add to ~/.config/helix/languages.toml:
[language-server.thymeleaf_ls]
command = "thymeleaf_ls"
[[language]]
name = "html"
language-servers = ["thymeleaf_ls"](with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'((html-mode web-mode) . ("thymeleaf_ls"))))In LSP.sublime-settings:
{
"clients": {
"thymeleaf_ls": {
"enabled": true,
"command": ["thymeleaf_ls"],
"selector": "text.html"
}
}
}There is no dedicated extension yet. Any generic LSP-client extension that lets you register a stdio server command for HTML files (pointing at thymeleaf_ls) will work.
The server takes a single optional CLI flag:
--level <LEVEL>— log level (TRACE,DEBUG,INFO,WARN,ERROR; defaultINFO). Logs are written to stderr as JSON; stdout is reserved for the LSP protocol.
thymeleaf_ls --level DEBUGmake build # cargo build
make test # cargo test
make lint # cargo clippy --all-targets -- -D warnings
make fmt # cargo fmt --all
make check # fmt-check + lint + test (what CI runs)A single test: cargo test <name>.
The server is a tower-lsp backend; each capability lives in its own module under src/:
main.rs— LSP glue, capabilities, request handlers, incremental syncdocument.rs/vault.rs— tree-sitter-parsed documents and the workspace storethymeleaf.rs— the Standard Dialect attribute + expression catalogfragmentref.rs— shared fragment-attribute parsingcompletion.rs,hover.rs,diagnostics.rs,navigation.rs,rename.rs,code_actions.rs,symbols.rs,highlight.rs,folding.rs,links.rs,semantic_tokens.rs— features
See CLAUDE.md for a deeper architecture tour and CONTRIBUTING.md to get started.
index.html is a sample template to try the server against. The make nvim / make debug / make tmux targets wire up a live debug loop with lsp-debug-tools.nvim; make link symlinks the debug build onto your PATH.
Licensed under either of
- MIT License (LICENSE-MIT)
- Apache License, Version 2.0 (LICENSE-APACHE)
at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project, as defined in the Apache-2.0 license, shall be dual-licensed as above, without any additional terms or conditions.