Scoping
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;heading.md
matches all Markdown headings; andtext.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.
markup
The default behavior for markup files is to apply rules to all non-ignored sections of the file (see Formats for more information). This means that for most rules you don’t need to specify a scope.
For rules that need to target specific sections of the file, you can use the following scopes:
Scope | Description |
---|---|
heading | Matches all <h{1,...}> tags. You can specify an exact level by
appending tags—for example, heading.h1 matches all h1 tags. |
table.header | Matches all <th> tags. |
table.cell | Matches all <td> tags. |
table.caption | Matches all <caption> tags. |
figure.caption | Matches all <figcaption> tags. |
list | Matches all <li> tags. |
paragraph | Matches all paragraphs (segments of text separated by two newlines). |
sentence | Matches all sentences. |
blockquote | Matches all <blockquote> tags. |
alt | Matches all alt attributes. |
summary | Matches all body text (excluding headings, code spans, code blocks, and table cells). This scope is useful for rules that need to match only sentence-level text content (such as readability scores). |
raw | Uses the raw, unprocessed markup source instead of a specific scope. This scope is useful for regex-based rules that need to match against the original source text. |
code
There are two code
scopes: comment.line
and comment.block
.
text
Any format not listed below is considered to be text
and has no special
scoping rules applied.
Multi-scope rules
Rules may define multiple scopes by using a YAML array:
scope:
# h1 OR h2
- heading.h1
- heading.h2
Negation & multi-part selectors
Any scope prefaced with “~” is negated:
scope:
# all scopes != h2
- ~heading.h2
You can chain multiple scopes together using “&”:
scope:
- ~blockquote & ~heading
Formats
Markdown
GitHub-Flavored Markdown support is built in. Vale ignores indented blocks, fenced blocks, and code spans by default.
The supported extensions are .md
, .mdown
, .markdown
, and .markdn
.
If you’re using another flavor of Markdown, see non-standard markup for information on how to make your flavor compatible.
HTML
HTML5 support is built in. Vale ignores script
, style
, pre
, code
,
and tt
tags by default.
The supported extensions are .html
, .htm
, .shtml
, and .xhtml
.
reStructuredText
reStructuredText is supported through the external program
rst2html
. You can get
rst2html
by installing either Sphinx or
docutils.
Vale ignores literal blocks, inline literals, and code-block
s by default. The supported extensions are .rst
and .rest
.
See Non-standard markup for more information on ignoring other types of markup.
AsciiDoc
AsciiDoc is supported through the external program Asciidoctor.
Vale ignores listing blocks and inline literals by default. The supported extensions are .adoc
, .asciidoc
and .asc
.
You can customize how asciidoctor
is called by passing document attributes:
StylesPath = <...>
[asciidoctor]
# attribute = value
#
# where 'YES' enables and 'NO' disables.
# enable
experimental = YES
# assign a specific value
attribute-missing = drop
[*]
BasedOnStyles = Vale
# normal config ...
DITA
dita
command,
you’ll likely experience worse performance with DITA files compared to other formats.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.
Vale ignores <codeblock>
, <tt>
, and <codeph>
elements by default.
XML
XML is supported through the external program xsltproc
.
You also need to provide a version 1.0 XSL Transformation (XSLT) for converting to HTML:
[*.xml]
Transform = docbook-xsl-snapshot/html/docbook.xsl
Org
Org support is built in. Vale ignores code blocks, literal examples, code strings, and verbatim strings by default.
Code
Vale supports linting source code comments in a number of languages (see the table below). You can assign a markup format to the content of the comments using the format association section:
StylesPath = styles
MinAlertLevel = suggestion
[formats]
# Rust + Markdown
rs = md
[*.{rs,md}]
BasedOnStyles = Vale
Once a markup format has been assigned, you can make use of all the supported features of that format (such as ignore patterns and comment-based configuration) in your source code comments.
Language | Extensions | Scopes |
---|---|---|
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 ) |
Java | .java , .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 ) |
Julia | .jl | # (text.comment.line.ext ),
"..." (text.comment.line.ext )
#= (text.comment.block.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 ) |
Perl | .pl , .pm , .pod | # (text.comment.line.ext ) |
PHP | .php | // (text.comment.line.ext ),
# (text.comment.line.ext ),
/*...*/ (text.comment.line.ext ),
/* (text.comment.block.ext ) |
PowerShell | .ps1 | # (text.comment.line.ext ),
<#...#> (text.comment.line.ext ),
<# (text.comment.block.ext ) |
Protobuf | .proto | // (text.comment.line.ext ),
/*...*/ (text.comment.line.ext ),
/* (text.comment.block.ext ) |
Python | .py , .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 ) |
Rust | .rs | // (text.comment.line.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 ) |
TypeScript | .ts , .tsx | // (text.comment.line.ext ),
/*...*/ (text.comment.line.ext ),
/* (text.comment.block.ext ) |
Non-standard markup
Ignore patterns are a low-level concept that have a few important restrictions:
They are only supported in Markdown, reStructuredText, AsciiDoc, and Org Mode.
They are processed before the markup file is converted to HTML, so the patterns should only target non-standard constructs.
See Code for information on using ignore patterns in source code.
When working with non-HTML markup, you’ll probably find that there are certain
non-standard sections of text you’d like to ignore. This is possible using
BlockIgnores
and
TokenIgnores
. Some examples:
To ignore entire blocks of text, you’ll want to define BlockIgnores
.
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 >})
To ignore an inline section of text you’ll want to define TokenIgnores
.
Let’s say we want to ignore math equations of the form $...$
, that look something like:
$\begin{bmatrix} k & k & k \end{bmatrix}^T$
To ignore all instances of math equations, we’d use a pattern along the lines of the following:
TokenIgnores = (\$+[^\n$]+\$+)
To ignore directive blocks use BlockIgnores
. For example, ignoring .. math::
directives:
BlockIgnores = (?s) *(\.\. math::)
To ignore inline roles use TokenIgnores
. For example, ignoring :math:
roles:
TokenIgnores = (:math:`.*`)