Parses your source instead of pattern-matching it
Markup-aware
A prose linter that treats your source as plain text will flag your code samples, your URLs, and your syntax. Vale doesn't read the file—it parses it, the same way your site generator does, and then walks the result. Rules see prose. Everything else is structure.
Scopes referenceOne rule, every syntax
These three files say the same thing in three markup languages. Vale parses each with its own parser and hands the linter the same prose, so a rule written once fires in all three.
The dimmed characters never reach a rule. Neither does --output or the link target—but report format, which a reader actually reads, does.
Vale does not implement any of these syntaxes itself. Markdown goes through goldmark, AsciiDoc
through Asciidoctor, and reStructuredText
through Docutils—the same tools
your site generator is likely using. Whatever they call a heading is what a rule scoped to heading sees.
Rules can aim at structure
Because the document is a tree by the time rules run, a rule can restrict itself to part of it. Pick a selector and watch which blocks it claims.
The default: every block Vale extracts from the file.
7 of 7 blocks
A selector matches when every part of it appears in the block's scope, in any order—so md.list and list.md select the
same thing. Combine parts with & to require
both at once, or lead with ~ to invert the whole
thing.
Inline spans—link, strong, emphasis, code—are scopes of
their own, offered alongside the surrounding text rather than nested inside it. A rule that
asks for link sees only link
text; every other rule pays nothing for the privilege.
Front matter is content too
A title and a description are read more often than the page they sit on—they land in search results, navigation, and social cards. Vale parses front matter in Markdown, AsciiDoc, reStructuredText, MDX, and Org, and gives every field a scope of its own.
Title case, titles only
The field name is part of the scope, so a rule can pick out one key and ignore every other.
No filler in the description
This is the sentence that lands in search results. It is the wrong place for words that carry no information.
Front matter is skipped entirely unless a rule asks for it, so nothing starts firing on your build configuration by accident.
Scope a rule in three lines
Every rule takes a scope. Set it, and the rule stops firing anywhere else.
Headings only
Enforce sentence case where it matters, and leave body text alone.
Everything but tables
Scopes negate. Terse table cells shouldn't trip a rule about full sentences.
What a rule never sees
Exclusions are structural, not a list of patterns you maintain. If the parser calls it code, it is code.
Fenced and indented code
Whole blocks, in every format that has them.
Inline code spans
Backticks, ``literals``, and +passthroughs+ alike.
URLs and link targets
The destination is skipped; the link text is not.
Front matter
YAML and TOML headers, unless you ask for them by key.
HTML attributes
Except the human-readable ones, like alt text.
Directives and macros
Roles, shortcodes, and template tags.
Formats
Each is handed to the parser that owns it, not to a shared approximation of all of them. Follow a tile to the project doing the work.
Source files are handled too—see code-aware linting, which can parse the Markdown inside a comment using everything on this page.