Styles
Vale has a powerful extension system that doesn't require knowledge of any programming language. Instead, it uses collections of individual YAML files (or "rules") to enforce particular writing constructs.
These collections are referred to as styles and are organized in a nested folder structure at a user-specified location (see Configuration). For example,
where base, blog, and docs are your styles that each contain certain rules.
Extension points
Heads up!
Vale uses Go's regexp package to evaluate all patterns in rule definitions. This means that lookarounds and backreferences aren't supported.
This shouldn't be a limitation, though, as Vale offers its own ways to achieve same behavior.
The building blocks of styles are rules (YAML files ending in .yml
), which utilize extension points to perform specific tasks.
The basic structure of a rule consists of a small header (shown below) followed by extension-specific arguments.
The available extension points are discussed below.
existence
Example definition
Key summary
Name | Type | Description |
---|---|---|
append | bool | Adds raw to the end of tokens , assuming both are defined. |
ignorecase | bool | Makes all matches case-insensitive. |
nonword | bool | Removes the default word boundaries (\b ). |
raw | array | A list of tokens to be concatenated into a pattern. |
tokens | array | A list of tokens to be transformed into a non-capturing group. |
The most general extension point is existence
. As its name implies, it looks for the "existence" of particular tokens.
These tokens can be anything from simple phrases (as in the above example) to complex regular expressionsβe.g., the number of spaces between sentences or the position of punctuation after quotes.
You may define the tokens as elements of lists named either tokens
(shown above) or raw
. The former converts its elements into a word-bounded, non-capturing group. For instance,
becomes \b(?:appears to be|arguably)\b
.
raw
, on the other hand, simply concatenates its elementsβso, something like
becomes (?:foo)\sbar(baz)
.
substitution
Example definition
Key summary
Name | Type | Description |
---|---|---|
append | bool | Adds raw to the end of tokens , assuming both are defined. |
ignorecase | bool | Makes all matches case-insensitive. |
nonword | bool | Removes the default word boundaries (\b ). |
swap | map | A sequence of observed: expected pairs. |
substitution
associates a string with a preferred form. If we want to suggest the use of "plenty" instead of "abundance," for example, we'd write:
The keys may be regular expressions, but they can't include nested capture groups:
Like existence
, substitution
accepts the keys ignorecase
and nonword
.
substitution
can have one or two %s
format specifiers in its message. This allows us to do either of the following:
occurrence
Example definition
Key summary
Name | Type | Description |
---|---|---|
max | int | The maximum amount of times token may appear in a given scope. |
min | int | The minimum amount of times token has to appear in a given scope. |
token | string | The token of interest. |
occurrence
enforces the maximum or minimum number of times a particular token can appear in a given scope.
In the example above, we're limiting the number of words per sentence.
This is the only extension point that doesn't accept a format specifier in its message.
repetition
Example definition
Key summary
Name | Type | Description |
---|---|---|
ignorecase | bool | Makes all matches case-insensitive. |
alpha | bool | Limits all matches to alphanumeric tokens. |
tokens | array | A list of tokens to be transformed into a non-capturing group. |
repetition
looks for repeated occurrences of its tokens. If ignorecase
is set to true
, it'll convert all tokens to lower case for comparison purposes.
consistency
Example definition
Key summary
Name | Type | Description |
---|---|---|
nonword | bool | Removes the default word boundaries (\b ). |
ignorecase | bool | Makes all matches case-insensitive. |
either | array | A map of option 1: option 2 pairs of which only one may appear. |
consistency
will ensure that a key and its value (e.g., "advisor" and "adviser") don't both occur in its scope.
conditional
Example definition
Key summary
Name | Type | Description |
---|---|---|
ignorecase | bool | Makes all matches case-insensitive. |
first | string | The antecedent of the statement. |
second | string | The consequent of the statement. |
exceptions | array | An array of strings to be ignored. |
conditional
ensures that the existence of first
implies the existence of second
. For example, consider the following text:
According to Wikipedia, the World Health Organization (WHO) is a specialized agency of the United Nations that is concerned with international public health. We can now use WHO because it has been defined, but we can't use DAFB because people may not know what it represents. We can use DAFB when it's presented as code, though.
Using the above text with our example rule yields the following:
conditional
also takes an optional exceptions
list. Any token listed as an exception won't be flagged.
capitalization
Example definition
Key summary
Name | Type | Description |
---|---|---|
match | string | $title , $sentence , $lower , $upper , or a pattern. |
style | string | AP or Chicago; only applies when match is set to $title . |
exceptions | array | An array of strings to be ignored. |
capitalization
checks that the text in the specified scope matches the case of match
. There are a few pre-defined variables that can be passed as matches:
$title
: "The Quick Brown Fox Jumps Over the Lazy Dog."$sentence
: "The quick brown fox jumps over the lazy dog."$lower
: "the quick brown fox jumps over the lazy dog."$upper
: "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG."
Additionally, when using match: $title
, you can specify a style of either AP or Chicago.
readability
Example definition
Key summary
Name | Type | Description |
---|---|---|
metrics | array | One or more of "Gunning Fog", "Coleman-Liau", "Flesch-Kincaid", "SMOG", and "Automated Readability". |
grade | float | The highest acceptable score. |
readability
calculates a readability score according the specified metrics. The supported tests are Gunning Fog, Coleman-Liau, Flesch-Kincaid, SMOG, and Automated Readability.
If more than one is listed (as seen above), the scores will be averaged. This is also the only extension point that doesn't accept a scope, as readability is always calculated using the entire document (minus headings, code blocks, and lists).
grade
is the highest acceptable score. Using the example above, a warning will be issued if grade
exceeds 8.
spelling
Heads up!
The dic
and aff
keys, while still supported, have been deprecated in favor
of using the dictionaries
key (introduced in v2.8.0
).
Example definition
Key summary
Name | Type | Description |
---|---|---|
custom | bool | Turn off the default filters for acronyms, abbreviations, and numbers. |
filters | array | An array of patterns to ignore during spell checking. |
ignore | string | A relative path (from StylesPath ) to a file consisting of one word per line to ignore. |
dicpath | string | The location to look for .dic and .aff files. |
dictionaries | array | An array of dictionaries to load. |
spelling
implements spell checking based on Hunspell-compatible dictionaries.
Choosing a dictionary
By default, spelling
includes a custom, open-source
dictionary for American English. You
may instead use the dictionaries
key to list multiple custom dictionaries:
The spelling
extension point will look for en_US.{dic,aff}
and
en_medical.{dic,aff}
files in $DICPATH
, which you can set through an
environment variable or the dicpath
key.
Ignoring non-dictionary words
spelling
offers two different ways of ignoring non-dictionary words:
Using ignore files: Ignore files are plain-text files that list words to be ignored during spell check (one case-insensitive entry per line) . For example,
ignore.txtHere, we're instructing
spelling
to ignore both[Dd]estructuring
and[Tt]ranspiler
.You can name these files anything you'd like and reference them relative to the active
StylesPath
:Using filters: You can also customize the spell-checking experience by defining filters, which are Go-compatible regular expressions to applied to individual words:
sequence
(v2.3.0)
Example definition
Key summary
Name | Type | Description |
---|---|---|
tokens | []NLPToken | A list of tokens with associated NLP metadata. |
ignorecase | bool | Makes all matches case-insensitive. |
Unlike the other extension points, sequence
aims to support grammar-focused
rules (rather than "style"). Its built on top of prose
(an open-source natural language processing library) and makes significant use
of part-of-speech tagging.
An individual NLPToken
has the following structure:
The example rule illustrates the basics of the extension point: we're looking
for a particular sequence of tokens (which can either be a regular
expression or a part-of-speech tag). The |
notation means that we'll accept
VB
or VBN
in position 4.
There's also new notation in the message
: %[4]s
is like %s
, but
specifically refers to the 4th token in our sequence.
Built-in style
Heads up!
The built-in Vale.Spelling
rule will respect an ignore file stored at
StylesPath/vocab.txt
. However, the recommended approach is to use a
custom Vocab instead.
Vale comes with a single built-in style named Vale
that implements three rules,
as described in the table below.
Rule | Scope | Level | Description |
---|---|---|---|
Vale.Spelling | text | error | Spell checks text while respecting the active project's vocabulary. |
Vale.Terms | text | error | Enforces the current project's Preferred vocabulary terms. |
Vale.Avoid | text | error | Enforces the current project's Do not use vocabulary terms. |
Third-party styles
Vale has a growing selection of pre-made styles available for download from its style library, and community-maintained styles you can find by sreaching for the "vale-linter-style" tag on GitHub.