Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Panache
A language server, formatter, and linter for Pandoc, Quarto, and R Markdown.
Work in Progress
This project is in early development. Expect bugs, missing features, and breaking changes.
Installation
From crates.io
If you have Rust installed, the easiest way is likely to install from crates.io:
Pre-built Binaries
Alternatively, you can install pre-built binary packages from the releases
page for Linux, macOS, and Windows.
For Linux, packages are available for generic distributions (tarballs) as well
as Debian/Ubuntu (.deb) and Fedora/RHEL/openSUSE (.rpm).
Usage
Formatting
# Format a file in place
# Check if a file is formatted
# Format from stdin
|
# Format all .qmd and .md files in directory, recursively
Linting
# Lint a file
# Lint entire working directory
Pre-commit Hooks
panache integrates with pre-commit to automatically format and lint your files before committing.
Installation:
First, install pre-commit if you haven't already:
# or
Then add Panache to your .pre-commit-config.yaml:
repos:
- repo: https://github.com/jolars/panache
rev: v2.6.3 # Use the latest version
hooks:
- id: panache-format # Format files
- id: panache-lint # Lint and auto-fix issues
Install the hooks:
Now Panache will automatically run on your staged .qmd, .md, and .Rmd
files before each commit.
See examples/pre-commit-config.yaml for more configuration options.
Language Server
Panache includes a built-in LSP implementation for editor integration.
To start the LSP server, run:
But typically you will configure your editor to start the LSP server
automatically when editing supported file types (.qmd, .md, .Rmd).
Editor Configuration:
The LSP communicates over stdin/stdout and provides document formatting
capabilities. For Quarto projects, the LSP also reads _quarto.yml,
per-directory _metadata.yml, and metadata-files includes to supply
project-level metadata to bibliography-aware features. For bookdown,
_bookdown.yml, _output.yml, and index.Rmd frontmatter are also considered.
Native LSP configuration (0.11+)
-- .config/nvim/lsp/panache.lua
return
-- Enable it
vim..
Nvim-lspconfig
-- Add to your LSP config
local lspconfig = require
local configs = require
-- Define panache LSP
if not configs.
-- Enable it
lspconfig..
Format on save:
vim..
Install a generic LSP client extension like vscode-languageserver-node, then configure in settings.json:
Or use the Custom LSP extension.
Add to ~/.config/helix/languages.toml:
[[]]
= "markdown"
= ["panache-lsp"]
= true
[]
= "panache"
= ["lsp"]
Features
The list of LSP features supported by Panache is still evolving, but currently includes:
- Document formatting (full document and range)
- Live diagnostics with quick fixes
- Code actions for refactoring
- Convert between loose/compact lists
- Convert between inline/reference footnotes
- Document symbols/outline
- Folding ranges
- Go to definition for references and footnotes
Configuration
Panache looks for a configuration in:
.panache.tomlorpanache.tomlin current directory or parent directories$XDG_CONFIG_HOME/panache/config.toml(usually~/.config/panache/config.toml)
Example
# Markdown flavor and line width
= "quarto"
= 80
= "auto"
# Formatting style
[]
= "reflow"
# External code formatters (opt-in)
[]
= ["isort", "black"] # Sequential formatting
= "air" # Built-in preset
= "prettier" # Reusable definitions
= "prettier"
= "yamlfmt" # Formats both code blocks AND frontmatter
# Customize formatters
[]
= ["--print-width=100"]
# External code linters
[]
= "jarl" # Enable R linting
See .panache.toml.example for a complete configuration reference.
External Code Formatters
Panache supports external formatters for code blocks—opt-in and easy to enable:
[]
= "air"
= "ruff"
= "prettier"
= "prettier" # Reuse same formatter
Key features:
- Opt-in by design - No surprises, explicit configuration
- Built-in presets - Quick setup with sensible defaults
- Preset inheritance - Override only specific fields, inherit the rest
- Incremental arg modification - Add args with
append_args/prepend_args - Sequential formatting - Run multiple formatters in order:
python = ["isort", "black"] - Reusable definitions - Define once, use for multiple languages
- Parallel execution - Formatters run concurrently across languages
- Graceful fallback - Missing tools preserve original code (no errors)
- Custom config - Full control with
cmd,args,stdinfields
Custom formatter definitions:
[]
= ["isort", "black"]
= "prettier"
# Partial override - inherits cmd/stdin from built-in "air" preset
[]
= ["format", "--custom-flag", "{}"] # Only override args
# Incremental modification - add args without full override
[]
= ["--line-length", "100"] # Adds to preset args
# Full custom formatter
[]
= "prettier"
= ["--print-width=100"]
= true
Preset inheritance:
When a [formatters.NAME] section matches a built-in preset name (like air,
black, ruff), unspecified fields are inherited from the preset:
[]
= "air"
[]
= ["format", "--preset=tidyverse"] # cmd and stdin inherited from built-in
Incremental argument modification:
Use append_args and prepend_args to add arguments without completely
overriding the base args (from preset or explicit args field):
[]
= "air"
[]
# Base args from preset: ["format", "{}"]
= ["-i", "2"]
# Final args: ["format", "{}", "-i", "2"]
Both modifiers work together and with explicit args:
[]
= "shfmt"
= ["-filename", "$FILENAME"]
= ["--verbose"]
= ["-i", "2"]
# Final: ["--verbose", "-filename", "$FILENAME", "-i", "2"]
Additional details:
- Formatters respect their own config files (
.prettierrc,pyproject.toml, etc.) - Support both stdin/stdout and file-based formatters
- 30 second timeout per formatter
External Code Linters
panache supports external linters for code blocks—opt-in via configuration:
# Enable R linting
[]
= "jarl" # R linter with JSON output
Key features:
- Opt-in by design - Only runs if configured
- Stateful code analysis - Concatenates all code blocks of same language to handle cross-block dependencies
- LSP integration - Diagnostics appear inline in your editor
- CLI support -
panache lintshows external linter issues - Line-accurate diagnostics - Reports exact line/column locations
How it works:
- Collects all code blocks of each configured language
- Concatenates blocks with blank-line preservation (keeps original line numbers)
- Runs external linter on concatenated code
- Maps diagnostics back to original document positions
Supported linters:
- jarl - R linter with structured JSON output
Note: Auto-fixes from external linters are currently disabled due to byte offset mapping complexity. Diagnostics work perfectly.
Motivation
I wanted a formatter that understands Quarto and Pandoc syntax. I have tried to use Prettier as well as mdformat, but both fail to handle some of the particular syntax used in Quarto documents, such as fenced divs and some of the table syntax.
Design Goals
- Full LSP implementation for editor integration
- Linting as part of LSP but also available as a standalone CLI command
- Support Quarto, Pandoc, and Markdown syntax
- Fast lossless parsing and formatting (no CST changes if already formatted)
- Be configurable, but have sane defaults (that most people can agree on)
- Format math
- Hook into external formatters for code blocks (e.g.
airfor R,rufffor Python)