<a id="run-documentation-checks"></a>

# Run documentation checks

The Sphinx Stack comes with several tests and checks that you can (and should!) run on
your documentation before committing and pushing changes:

- [Accessibility check](#accessibility-check)
- [Inclusive language check](#inclusive-lang-check)
- [Link check](#link-check)
- [Markdown lint check](#markdown-lint-check)
- [Spelling check](#spelling-check)
- [Style guide linting](#style-guide-linting)
- [Vale exemptions](#vale-exemptions)

<a id="accessibility-check"></a>

## Accessibility check

The Sphinx Stack checks the accessibility of the documentation with [Pa11y](https://pa11y.org/). It’s
configured to check for Level AA conformity to the [Web Content Accessibility Guidelines
(WCAG) 2.2](https://www.w3.org/TR/WCAG22/).

This check is only available locally; it is not part of the [GitHub workflows](https://documentation.ubuntu.com/sphinx-stack/latest/reference/github-workflows/index.html.md#github-workflows) in
the Sphinx Stack.

To run the check, you must have `npm` and `Pa11y` installed. To install `npm`,
refer to the [installation guide](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) for details.
Then:

```bash
npm install pa11y
```

To check the accessibility of the documentation, run the following command in your
`/docs` directory:

```bash
make pa11y
```

### Configure

The `pa11y.json` file in the `_dev` directory provides basic defaults expected to be
used for all teams; refrain from removing any unless absolutely necessary. Additional
settings and options are detailed in the `Pa11y` [README](https://github.com/pa11y/pa11y#command-line-configuration) on GitHub.

<a id="inclusive-lang-check"></a>

## Inclusive language check

The Sphinx Stack checks for inclusive language with a custom set of [Vale](https://vale.sh) rules. To check for inclusive language violations, run:

```bash
make woke
```

### Configure

If you need to exempt single words or sections, follow the process in
[Vale exemptions](#vale-exemptions).

<a id="link-check"></a>

## Link check

The Sphinx Stack checks any links in your documentation with the Sphinx `linkcheck`
builder. To validate the links, run:

```bash
make linkcheck
```

### Configure

If you have links in the documentation that you don’t want to check, add them to the
`linkcheck_ignore` list in the `conf.py` file. See [Sphinx link checker](https://documentation.ubuntu.com/sphinx-stack/latest/reference/conf-py-configuration/index.html.md#conf-py-link-checker) for more information on how to configure the link checker.

<a id="markdown-lint-check"></a>

## Markdown lint check

The Sphinx Stack checks standards and consistency in Markdown files with the Markdown
lint check. To check your Markdown files, run:

```bash
make lint-md
```

### Configure

You can update the linting rules in the `_dev/.pymarkdown.json` file. Refer to [the
pymarkdown rules documentation](https://pymarkdown.readthedocs.io/en/latest/rules/)
for all the available rules.

<a id="spelling-check"></a>

## Spelling check

The Sphinx Stack uses [Vale](https://vale.sh) to check the spelling in your
documentation. It ignores inline code, code blocks, and URLs, but it does check the link
text. To ensure there are no spelling errors in your documentation, run:

```bash
make spelling
```

### Configure

If you need to exempt single words or sections, follow the process in
[Vale exemptions](#vale-exemptions).

<a id="style-guide-linting"></a>

## Style guide linting

The Sphinx Stack runs the [Vale](https://vale.sh) documentation linter configured
with the rules of [style guide](https://github.com/canonical/documentation-style-guide) To check your documentation
with Vale, run:

```bash
make vale
```

Vale can run against individual files, directories, or globs. To check a specific
target, run:

```bash
make vale TARGET=example.file
make vale TARGET=example-directory
```

If you run the linter against a directory, its subdirectories were also linted.

You can use wildcards to lint globs of files. For example, to run against all Markdown
files within a directory, you’d run:

```bash
make vale TARGET=*.md
```

### Configure

If you need to exempt single words or sections, follow the process in
[Vale exemptions](#vale-exemptions).

<a id="vale-exemptions"></a>

<a id="reference-automatic-checks-spelling-vale-ignore"></a>

## Vale exemptions

The [Inclusive language check](#inclusive-lang-check), [Spelling check](#spelling-check), and [Style guide linting](#style-guide-linting)
all use [Vale](https://vale.sh). These checks share a common syntax for exemptions
and pull from the same `.custom_wordlist.txt` file. The style guide repository
[includes a common list of words](https://github.com/canonical/documentation-style-guide/blob/main/styles/config/vocabularies/Canonical/accept.txt)
that will be excluded from the checks.

### A word

To ignore a single instance of a word, wrap it in the `:vale-ignore:` role. Ensure
your `conf.py` file contains the appropriate class association in the `rst_prolog`:

```text
rst_prolog = """
.. role:: vale-ignore
    :class: vale-ignore
"""
```

To ignore a word across your documentation, add it to your project’s
`.custom_wordlist.txt` file.

### A section of text

To disable Vale for a section of text, use the following markup:

### Markdown

```text
<!-- vale off -->

This text will be ignored.

<!-- vale on -->
```

### reST

```text
.. vale off

This text will be ignored.

.. vale on
```

### Directives

To disable Vale linting for Directives as a code block or admonitions, apply the
`vale-ignore` class to the section:

### Markdown

```text
````{class} vale-ignore
```{code-block}

This content will be ignored by Vale.
```
````
```

### reST

```text
.. class:: vale-ignore
    .. code-block::

        This content will be ignored by Vale.
```

The class process isn’t be necessary for Markdown, as Vale has an expanded scope for
ignoring Markdown content by default. Also, the .. class:: directive for reST does not
need to encapsulate content, it applies to the next logical block (which can be another
directive or even a paragraph of content). The class option should only be used when
other options aren’t suitable.
