Learn about how Vale handles different file types, allowing it to selectively target or exclude certain sections of text.

Types, formats, and scopes

Vale is “syntax aware,” which means that it’s capable of both applying rules to and ignoring certain sections of text. This functionality is implemented through a scoping system. A scope is specified through a selector such as paragraph.rst, which indicates that the rule applies to all paragraphs in reStructuredText files.

Here are a few examples:

  • comment matches all source code comments;
  • comment.line matches all source code line comments;
  • matches all Markdown headings; and
  • text.html matches all HTML scopes.

Vale classifies files into one of three types—markup, code, or text—that determine what scopes are available.

Within each type, there can be multiple supported formats—such as Markdown and AsciiDoc under markup. Since each format has access to the same scopes, rules are compatible across all formats within a particular type.


headingMatches all <h{1,...}> tags. You can specify an exact level by appending a tags—for example, heading.h1 matches all h1 tags.
table.headerMatches all <th> tags.
table.cellMatches all <td> tags.
table.captionMatches all <caption> tags.
figure.captionMatches all <figcaption> tags.
listMatches all <li> tags.
paragraphMatches all paragraphs (segments of text separated by two newlines).
sentenceMatches all sentences.
linkMatches all <a> tags.
altMatches all alt attributes.
blockquoteMatches all <blockquote> tags.
summaryMatches all body text (excluding headings, code spans, code blocks, and table cells).
codeMatches all <code> tags.
strongMatches all <strong> and <b> tags.
emphasisMatches all <em> and <i> tags
rawUses the raw, unprocessed markup source instead of a specific scope.


There are two code scopes: comment.line and comment.block.


Any format not listed below is considered to be text and has no special scoping rules applied.



GitHub-Flavored Markdown support is built in. By default, indented blocks, fenced blocks, and code spans are ignored.

If you’re using another flavor of Markdown, see non-standard markup for information on how to make your flavor compatible.


HTML5 support is built in. By default, script, style, pre, code, and tt tags are ignored.


reStructuredText is supported through the external program rst2html. You can get rst2html by installing either Sphinx or docutils.

By default, literal blocks, inline literals, and code-blocks are ignored.


AsciiDoc is supported through the external program Asciidoctor. By default, listing blocks and inline literals are ignored.

You can customize how asciidoctor is called by passing document attributes:

StylesPath = <...>

# attribute = value
# where 'YES' enables and 'NO' disables.

# enable
experimental = YES

# assign a specific value
attribute-missing = drop

BasedOnStyles = Vale

# normal config ...


DITA is supported through the DITA Open Toolkit. You’ll need to follow the installation instructions, including the optional step of adding the absolute path for the bin directory to the PATH system variable.

By default, <codeblock>, <tt>, and <codeph> elements are ignored.


XML is supported through the external program xsltproc.

You also need to provide a version 1.0 XSL Transformation (XSLT) for converting to HTML:

Transform = docbook-xsl-snapshot/html/docbook.xsl


C.c, .h// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
C#.cs, .csx// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
C++.cpp, .cc, .cxx, .hpp// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
CSS.css/*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
Go.go// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
Haskell.hs-- (text.comment.line.ext), {- (text.comment.block.ext), .bsh// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
JavaScript.js// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
LESS.less// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
Lua.lua-- (text.comment.line.ext), --[[ (text.comment.block.ext), .pm, .pod# (text.comment.line.ext)
PHP.php// (text.comment.line.ext), # (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext), .py3, .pyw, .pyi, rpy# (text.comment.line.ext), """ (text.comment.block.ext)
R.r, .R# (text.comment.line.ext)
Ruby.rb# (text.comment.line.ext), ^=begin (text.comment.block.ext)
Sass.sass// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)
Scala.scala, .sbt// (text.comment.line.ext)
Swift.swift// (text.comment.line.ext), /*...*/ (text.comment.line.ext), /* (text.comment.block.ext)

Non-standard markup

When working with non-HTML markup, you’ll probably find that there are certain non-standard sections of text you’d like to ignore.

To ignore entire blocks of text—for example, Hugo’s shortcodes—you’ll want to define BlockIgnores. For example, consider the following shortcode-like file snippet:

{< file "hello.go" go >}
package main

func main() {
    fmt.Printf("hello, world\n")
{</ file >}

To ignore all instances of file, we’d use a pattern along the lines of the following:

BlockIgnores = (?s) *({< file [^>]* >}.*?{</ ?file >})

The basic idea is to capture the entire snippet in the first grouping. See regex101 for a more thorough explanation.

You can also define more than one by using a list (the \ allows for line breaks):

BlockIgnores = (?s) *({< output >}.*?{< ?/ ?output >}), \
(?s) *({< highlight .* >}.*?{< ?/ ?highlight >})

To ignore an inline section of text, you’ll want to define TokenIgnores. For example, let’s say we want to ignore math equations of the form $...$:

$\begin{bmatrix} k & k & k \end{bmatrix}^T$

Similar to BlockIgnores, we just need to define a pattern:

TokenIgnores = (\$+[^\n$]+\$+)