mdita-lsp
An LSP server for MDITA (Markdown DITA) documents.
Provides comprehensive language support for .md and .mditamap files with 29 diagnostic codes, MDITA extended profile support (domain specializations, task sections, conditional processing), keyref resolution, incremental text sync, and full IDE integration.
Install
From GitHub Releases
Download the binary for your platform from Releases and place it on your PATH.
From source
go install github.com/aireilly/mdita-lsp/cmd/mdita-lsp@latest
Or clone and build:
git clone https://github.com/aireilly/mdita-lsp.git
cd mdita-lsp
make install # installs to ~/.local/bin
Ensure the install location is on your PATH:
# For go install:
echo 'export PATH=$PATH:~/go/bin' >> ~/.bashrc
# For make install:
echo 'export PATH=$PATH:~/.local/bin' >> ~/.bashrc
source ~/.bashrc
Editor setup
VS Code
Use any generic LSP client extension with:
{
"lsp.server.command": "mdita-lsp",
"lsp.server.filetypes": ["markdown"]
}
Neovim (nvim-lspconfig)
vim.api.nvim_create_autocmd("FileType", {
pattern = { "markdown" },
callback = function()
vim.lsp.start({
name = "mdita-lsp",
cmd = { "mdita-lsp" },
root_dir = vim.fs.dirname(vim.fs.find({ ".mdita-lsp.yaml", ".git" }, { upward = true })[1]),
})
end,
})
Helix
Add to ~/.config/helix/languages.toml:
[[language]]
name = "markdown"
language-servers = ["mdita-lsp"]
[language-server.mdita-lsp]
command = "mdita-lsp"
Configuration
Create .mdita-lsp.yaml in your project root or ~/.config/mdita-lsp/config.yaml for user-wide settings.
core:
markdown:
file_extensions: [md, markdown, mditamap]
mdita:
enable: true
map_extensions: [mditamap]
completion:
wiki_style: title-slug
code_actions:
toc:
enable: true
include_levels: [2, 3, 4]
create_missing_file:
enable: true
build:
dita_ot:
enable: true
dita_path: "" # Path to dita binary (empty = search $PATH)
output_dir: "out" # Output directory relative to workspace root
diagnostics:
mdita_compliance: true
ditamap_validation: true
keyref_resolution: true
link_validation: true
nbsp_detection: true
Features
| Feature |
Description |
| Diagnostics |
29 codes: MDITA compliance, link validation, heading hierarchy, footnotes, keyrefs, ditamap validation, domain elements, task sections, conditional attributes, relationship tables |
| Completion |
Inline links (](), YAML keys, heading anchors (#), keyrefs ([), task section headings, attribute classes ({.), attribute open ({ after inline elements/headings), conditional attributes |
| Go to Definition |
Markdown links and keyref shortcut references |
| Hover |
Document titles, heading text, keyref targets, YAML front matter keys, domain elements, task sections, conditional attributes |
| Find References |
All references to a heading across the workspace |
| Rename |
Heading rename |
| Code Actions |
Generate ToC, create missing files, add YAML front matter, add to mditamap, add related links, add task sections, quick-fix NBSP/footnotes/heading hierarchy, build XHTML/DITA with DITA OT |
| Code Lens |
Reference counts on headings |
| Document Links |
Clickable links for external URLs |
| Document Symbols |
Hierarchical heading outline tree |
| Workspace Symbols |
Search headings across all documents |
| Folding Ranges |
Fold headings, YAML front matter, and ToC markers |
| Selection Ranges |
Progressive selection expansion by line/element/section |
| Linked Editing |
Linked editing of heading text |
| Formatting |
Trim trailing whitespace, normalize headings, align tables, ensure trailing newline (full + range) |
| Inlay Hints |
Show resolved markdown link targets, keyref targets, and DITA domain element mappings inline |
| Document Highlight |
Highlight all same-document references to heading under cursor |
| Semantic Tokens |
Semantic token encoding (full + range) with attribute decorator highlighting |
| File Rename |
Auto-update markdown links and map references on file rename |
| File Create |
Auto-populate new .md files with MDITA YAML front matter |
| Execute Command |
Create files, add documents to map, build XHTML/DITA via DITA OT |
| Pull Diagnostics |
On-demand diagnostics via textDocument/diagnostic (LSP 3.17) |
| Text Sync |
Incremental (mode 2) with 200ms diagnostic debouncing |
| File Operations |
Auto-index created/deleted files, cross-document diagnostic refresh |
Diagnostic codes
| Code |
Name |
Severity |
| 1 |
Ambiguous link |
Warning |
| 2 |
Broken link |
Error |
| 3 |
Non-breaking whitespace |
Warning |
| 4 |
Missing YAML front matter |
Warning |
| 5 |
Missing short description |
Warning |
| 6 |
Invalid heading hierarchy |
Warning |
| 7 |
Unrecognized schema |
Warning |
| 8 |
Task missing procedure |
Warning |
| 9 |
Concept has procedure |
Info |
| 10 |
Reference missing table |
Info |
| 11 |
Map has body content |
Info |
| 12 |
Extended feature in core profile |
Warning |
| 13 |
Footnote ref without def |
Warning |
| 14 |
Footnote def without ref |
Info |
| 15 |
Unknown admonition type |
Warning |
| 16 |
Unresolved keyref |
Warning |
| 17 |
Broken map reference |
Error |
| 18 |
Circular map reference |
Error |
| 19 |
Inconsistent map heading hierarchy |
Info |
| 20 |
Unknown outputclass |
Warning |
| 21 |
Domain class wrong parent |
Warning |
| 22 |
Extended profile required |
Warning |
| 23 |
Unknown conditional attribute |
Warning |
| 24 |
Task section out of order |
Warning |
| 25 |
Duplicate task section |
Error |
| 26 |
Related links non-link content |
Warning |
| 27 |
Menucascade missing separator |
Warning |
| 28 |
Step element outside task |
Warning |
| 29 |
Reltable inconsistent columns |
Warning |
MDITA extended profile
mdita-lsp supports the MDITA extended profile with inline attribute syntax for DITA domain specializations:
# Install the software {.task}
## Prerequisites
{platform="linux"}
1. Click **File > Open**{.menucascade} to open the dialog.
2. Edit `config.yaml`{.filepath} to set options.
3. Run the `installer`{.cmdname} command.
## Related information
- [User Guide](user-guide.md)
Supported domain elements
| Domain |
Elements |
| UI (ui-d) |
{.uicontrol}, {.wintitle}, {.menucascade}, {.shortcut} on bold |
| Software (sw-d) |
{.filepath}, {.cmdname}, {.userinput}, {.systemoutput}, {.varname}, {.msgph} on `code` |
| Programming (pr-d) |
{.codeph}, {.option}, {.parmname}, {.apiname}, {.kwd} on `code` |
| Topic |
{.cite} on italic, {.draft-comment} on paragraph |
Conditional processing
Block-level attributes for DITA profiling:
{platform="linux" audience="admin"}
Supported attributes: audience, platform, product, otherprops, deliveryTarget, props, rev.
.mditamap files define document structure using nested markdown lists:
# Product Documentation
- [Getting Started](getting-started.md)
- [Installation](install.md)
- [Configuration](config.md)
- [User Guide](user-guide.md)
Keys are derived from filenames (e.g., install.md → key install). Use [install] in topic files to create keyref shortcut references.
Relationship tables
Tables in .mditamap files are parsed as DITA relationship tables:
| [Overview](overview.md) | [Install](install.md) |
|-------------------------|----------------------|
| [Config](config.md) | [Troubleshoot](ts.md) |
Map references
Links to .ditamap or .mditamap files are treated as map references (mapref).
Development
make build # Build binary
make test # Run 210+ tests with race detection
make lint # Run golangci-lint
make publish # Cross-compile for 5 platforms (~3.5 MB each)
make clean # Remove build artifacts
License
See LICENSE.