Getting started

HTML-validate is an offline HTML5 validator.

Installation

Install using npm:

npm install --save-dev html-validate

Create a configuration file:

.htmlvalidate.json
{
  "extends": ["html-validate:recommended"]
}

Run with:

npm exec html-validate yourfile.html
Tip

If you use Prettier code formatter add the htm-validate:prettier preset as well to avoid style related rules clashing with Prettier.

Learn more about configuration presets.

Configuration

Configuration can be added to:

ESM configuration files are not currently supported.

For json the JSON schema https://html-validate.org/schemas/config.json can optionally be used:

{
  "$schema": "https://html-validate.org/schemas/config.json",
  "extends": ["html-validate:recommended"],
}

For js and cjs the defineConfig(..) helper can optionally be used to assist the IDE with type-checking and documentation:

import { defineConfig } from "html-validate";

module.exports = defineConfig({
  extends: ["html-validate:recommended"],
});

Configuration files will be searched from the target file and up until either no more parent folders exist or "root": true is found.

extends

Configuration can be extended from bundled preset or shareable configurations.

.htmlvalidate.json
{
  "plugins": ["my-plugin"],
  "extends": [
    /* bundled preset */
    "html-validate:recommended",

    /* npm package */
    "my-npm-package",

    /* preset "recommended" from "my-plugin" */
    "my-plugin:recommended",

    /* local file */
    "./file",
  ],
}

A list of bundled presets is available at the preset list. By default html-validate:recommended is used.

When using NPM packages or files each must be resolvable with require(..) and export a valid configuration object. Plugins may create configuration presets by exposing one or more preset in the plugin declaration.

rules

.htmlvalidate.json
{
  "rules": {
    "some-rules": "severity",
    "other-rule": ["severity", { "option": true }]
  }
}

Severity can be one of:

Some options takes optional parameters when using the form ["severity", OPTIONS].

See Available rules for a list of all built-in rules and options.

elements

For proper validation some metadata for each element is required, detailing in which context it can be used, allowed/disallowed attributes, etc. If elements is not specified it defaults to ["html5"] which is a bundled collection for all HTML5 elements.

.htmlvalidate.json
{
  "elements": [
    "html5",
    "my-npm-package",
    "./file.json",
    {
      /* inline metadata */
    },
  ],
}

Each entry will try to load metadata from (search in following order):

  1. Named bundled metadata.
  2. NPM package with the same name.
  3. A local file, json or js, resolvable by require(..). Path is relative to the configuration file.
Note

Loading native ESM is not supported yet (see issue #125) and must be transpiled to commonjs before usage.

An object can also be passed with inline metadata but it is highly recommended to write it to a separate file.

See elements metadata for details about writing your own metadata.

plugins

List of extra plugins to load. Plugins can contain additional rules, predefined configurations and transformers.

Can be either a NPM package or relative path to a local file, i.e. when writing custom rules inside the repository. Must be resolvable by require(..).

See writing plugins for details about creating your own plugins.

.htmlvalidate.json
{
  "plugins": ["my-awesome-plugin", "./local-plugin"]
}
Note

Loading native ESM is not supported yet (see issue #125) and must be transpiled to commonjs before usage.

Since version 7.17.0, if you are using javascript configuration or API you can also import or define plugins inline:

const { defineConfig } = require("html-validate");

module.exports = defineConfig({
  plugins: [
    {
      name: "my-awesome-plugin",
      /* ... */
    },
  ],
});

transform

Transform input files to extract HTML chunks, e.g. extract templates from javascript sources. See transformers for details.

.htmlvalidate.json
{
  "transform": {
    "^.*\\.vue$": "html-validate-vue"
  }
}

This will transform *.vue with the html-validate-vue NPM package. Use a relative path to use a local script (use <rootDir> to refer to the path to package.json, e.g. <rootDir>/my-transformer.js).

root

By default, configuration is search in the file structure until the root directory (typically /) is found:

By setting the root property to true the search is stopped. This can be used to prevent searching from outside the project directory or to use a specific configuration for a specific directory without loading project configuration.

For instance, if /home/project/.htmlvalidate.json contains:

.htmlvalidate.json
{
  "root": true
}

Only the following files would be searched:

This also affects CLI --config and the API, e.g. when using --config with a configuration using "root": true will prevent any additional files to be loaded.

Inline configuration

Configuration can be changed inline using directive of the form:

<!-- [html-validate-ACTION OPTIONS -- COMMENT] -->

ACTION is an action such as enable, disable etc and OPTIONS is arguments to the action. Comment is optional but encouraged.

Multiple rules can be enabled/disabled at once by using a comma-separated list:

<!-- [html-validate-disable-next void-style, deprecated -- disable both rules] -->

Comments can be entered using both -- and : as delimiter:

<!-- [html-validate-disable-next deprecated -- justification for disabling] -->
<blink>Blinking text</blink>
<!-- [html-validate-disable-next deprecated: justification for disabling] -->
<blink>Blinking text</blink>

enable

<!-- [html-validate-enable element-permitted-content] -->

Enables a rule. If the severity is set to off it will be raised to error, i.e a previously disabled warning will remain a warning after enabling it again.

disable

<!-- [html-validate-disable deprecated] -->

Disable a rule for the rest of the file or until re-enabled using enable directive.

disable-block

<!-- [html-validate-disable-block attribute-allowed-values] -->

Disables a rule for a block of elements. All siblings and descendants following the directive will not trigger any errors.

<div>
  <button type="foo">Invalid button</button>
  <!-- [html-validate-disable-block attribute-allowed-values -- will be disabled until the parent div is closed] -->
  <button type="bar">Invalid but ignored</button>
  <button type="baz">Still ignored</button>
</div>
<button type="spam">Another invalid</button>
error: Attribute "type" has invalid value "foo" (attribute-allowed-values) at inline:2:17:
  1 | <div>
> 2 |   <button type="foo">Invalid button</button>
    |                 ^^^
  3 |   <!-- [html-validate-disable-block attribute-allowed-values -- will be disabled until the parent div is closed] -->
  4 |   <button type="bar">Invalid but ignored</button>
  5 |   <button type="baz">Still ignored</button>


error: Attribute "type" has invalid value "spam" (attribute-allowed-values) at inline:7:15:
  5 |   <button type="baz">Still ignored</button>
  6 | </div>
> 7 | <button type="spam">Another invalid</button>
    |               ^^^^


2 errors found.

disable-next

<!-- [html-validate-disable-next deprecated] -->

Disables the rule for the next element.

<!-- [html-validate-disable-next deprecated -- the next occurrence will not trigger an error] -->
<blink>This will not trigger an error</blink>
<blink>But this line will</blink>
error: <blink> is deprecated (deprecated) at inline:3:2:
  1 | <!-- [html-validate-disable-next deprecated -- the next occurrence will not trigger an error] -->
  2 | <blink>This will not trigger an error</blink>
> 3 | <blink>But this line will</blink>
    |  ^^^^^


1 error found.

Ignoring files

.htmlvalidateignore file

The .htmlvalidateignore file works similar to .gitignore, i.e. the file should contain a list of file patterns to ignore.

Similar to .gitignore if a line starts with / it matches from the current directory only, e.g /foo.html matches only foo.html in the current directory but not src/foo.html.