An opinionated collection of essential HTML validation rules that promote best practices™ for web development. Use this plugin with HTML-validate.
- ✅ Turnkey validation: 7 rules covering SEO, security, accessibility, and best practices
- ✅ TypeScript: full type definitions included
⚠️ Dual module support: works with both ESM (import
) and CJS (require
) (known issue: ESM and CommonJS builds are sometimes not building correctly)- ✅ Tree shakeable: import only what you need
- ✅ Modern tooling: built with tsup, tested with Vitest, good IDE hinting and enforced style checking
- ✅ Comprehensive testing: high test coverage with realistic fixtures
These instructions assume you will use Nice Checkers as part of a web test suite running Node (20+) and HTML-validate. See GitHub Pages Template for an end-to-end example, including GitHub Actions continuous integration, testing and GitHub Pages deployment for all modern best practices.
Nice Checkers is a dev dependency for you because you need it to test your website, not to deploy it.
# Using Yarn
yarn add -D html-validate-nice-checkers
# Using npm
npm install --dev html-validate-nice-checkers
This example assumes you are using the .htmlvalidate.mjs configuration flavor. HTML-validate also supports other configuration flavors.
import { defineConfig } from "html-validate";
+ import { NiceCheckersPlugin } from "@fulldecent/nice-checkers-plugin"
export default defineConfig({
- "extends": ["htmlvalidate:recommended"]
+ "plugins": [NiceCheckersPlugin],
+ "extends": ["htmlvalidate:recommended", "nice-checkers-plugin:recommended"]
});
All rules are enabled by default when you extend from nice-checkers-plugin:recommended
. Find introductions and configuration options for each rule below.
Ensures that each HTML document contains a single canonical link element pointing to the preferred URL for that page. This rule helps with SEO by preventing duplicate content issues and clarifies the primary URL for search engines.
Also this rule enforces that your public URL does not end with a file extension (e.g. .html
) or an index (/index
). Each character in your URL is valuable real estate and you should not expose such implementation details in your URL.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>My first website about horses</title>
+ <link rel="canonical" href="https://example.com/horses" />
</head>
<body>
This page is missing a required canonical link element in the head.
</body>
</html>
{
"rules": {
"nice-checkers/canonical-link": "error"
}
}
This rule has no configurable options.
Validates that all external links are live and accessible. This rule helps maintain website quality by catching broken external links before they go live, improving user experience and SEO.
- <a href="https://wrong-subdomain.example.com">This link is broken</a>
+ <a href="https://example.com/nonexistent-page">This link works</a>
{
"rules": {
"nice-checkers/external-links": [
"error",
{
"proxyUrl": "",
"skipRegexes": ["://example.com", "://localhost"],
"cacheExpiryFoundSeconds": 2592000,
"cacheExpiryNotFoundSeconds": 259200,
"timeoutSeconds": 5,
"cacheDatabasePath": "cache/external-links.db",
"userAgent": "Mozilla/5.0 (compatible; html-validate-nice-checkers)"
}
]
}
}
Option | Type | Default | Description |
---|---|---|---|
proxyUrl |
string |
"" |
Proxy URL to use for HTTP requests |
skipRegexes |
string[] |
[] |
Array of regex patterns for URLs to skip checking |
cacheExpiryFoundSeconds |
number |
2592000 |
Cache duration for successful checks (default: 30 days) |
cacheExpiryNotFoundSeconds |
number |
259200 |
Cache duration for failed checks (default: 3 days) |
timeoutSeconds |
number |
5 |
Request timeout in seconds |
cacheDatabasePath |
string |
"cache/external-links.db" |
Path to the cache database file |
userAgent |
string |
"Mozilla/5.0 (compatible; html-validate-nice-checkers)" |
User agent string for HTTP requests |
Reports insecure HTTP links that are accessible via HTTPS, encouraging the use of secure connections. This rule promotes security best practices by identifying opportunities to upgrade to HTTPS.
- <a href="http://example.com/page">Should use HTTPS</a>
- <img src="http://cdn.example.com/image.webp" alt="Image" />
+ <a href="https://example.com/page">Uses HTTPS</a>
+ <img src="https://cdn.example.com/image.webp" alt="Image" />
{
"rules": {
"nice-checkers/https-links": [
"warn",
{
"cacheExpiryFoundSeconds": 2592000,
"cacheExpiryNotFoundSeconds": 259200,
"timeoutSeconds": 10,
"cacheDatabasePath": "cache/https-availability.db"
}
]
}
}
Option | Type | Default | Description |
---|---|---|---|
cacheExpiryFoundSeconds |
number |
2592000 |
Cache duration for successful HTTPS checks (default: 30 days) |
cacheExpiryNotFoundSeconds |
number |
259200 |
Cache duration for failed HTTPS checks (default: 3 days) |
timeoutSeconds |
number |
10 |
Request timeout in seconds |
cacheDatabasePath |
string |
"cache/https-availability.db" |
Path to the cache database file |
Validates that all internal links point to existing files in your project. This rule prevents broken internal navigation and missing resource references.
- <a href="/nonexistent-page">Broken internal link</a>
- <img src="../images/missing.webp" alt="Missing image" />
+ <a href="/about">Working internal link</a>
+ <img src="../images/logo.webp" alt="Company logo" />
{
"rules": {
"nice-checkers/internal-links": [
"error",
{
"webRoot": "./build",
"alternativeExtensions": [".html", ".php"],
"indexFile": "index.html"
}
]
}
}
Option | Type | Default | Description |
---|---|---|---|
webRoot |
string |
"./build" |
Root directory for resolving absolute links |
alternativeExtensions |
string[] |
[".html"] |
Extensions to check for extensionless links |
indexFile |
string |
"index.html" |
Default file to look for in directory links |
Ensures that package assets loaded from CDNs (like jsDelivr) are using the latest version and have proper SRI attributes. This rule promotes security and ensures you're using up-to-date packages.
- <!-- Outdated package without SRI -->
- <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
+ <!-- Latest package with SRI -->
+ <script
+ src="https://cdn.jsdelivr.net/npm/bootstrap@.../dist/js/bootstrap.min.js"
+ integrity="sha384-..."
+ crossorigin="anonymous"
+ ></script>
{
"rules": {
"nice-checkers/latest-packages": [
"warn",
{
"cacheExpirySeconds": 172800,
"timeoutSeconds": 10,
"cacheDatabasePath": "cache/latest-packages.db",
"skipUrlPatterns": ["googletagmanager.com"]
}
]
}
}
Option | Type | Default | Description |
---|---|---|---|
cacheExpirySeconds |
number |
172800 |
Cache duration for package version checks (default: 2 days) |
timeoutSeconds |
number |
10 |
Request timeout in seconds |
cacheDatabasePath |
string |
"cache/latest-packages.db" |
Path to the cache database file |
skipUrlPatterns |
string[] |
[] |
Array of URL patterns to skip checking |
Enforces that mailto:
links contain specific parameters to improve user experience. This rule ensures email links provide helpful context to users.
- <a href="mailto:[email protected]">Send email</a>
+ <a href="mailto:[email protected]?subject=Website%20Inquiry&body=Hello,%20I%20would%20like%20to...">Send email</a>
{
"rules": {
"nice-checkers/mailto-awesome": [
"error",
{
"requiredParameters": ["subject", "body"]
}
]
}
}
Option | Type | Default | Description |
---|---|---|---|
requiredParameters |
string[] |
[] |
Array of parameters that must be present (e.g., ["subject", "body", "cc"] ) |
If you are still using jQuery after 2022, please try to open your favorite chatbot and ask how to replace it with vanilla JavaScript. Your page will run faster. And it is very possible that your chatbot can do this entire operation in one go without interactive back-and-forth.
- <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
- <script src="../js/jquery.min.js"></script>
{
"rules": {
"nice-checkers/no-jquery": "error"
}
}
This rule has no configurable options.
This package is built with TypeScript and supports both ESM and CommonJS module systems. Thank you for contributing improvements to this project!
# Clone the repository
git clone https://github.com/yourusername/html-validate-nice-checkers.git
cd html-validate-nice-checkers
# Setup Node, for example using nvm
nvm use
# Enable Yarn Berry
corepack enable
# Install dependencies
yarn install
These notes are from the Yarn project.
yarn dlx @yarnpkg/sdks vscode
and YES, use workspace TypeScript version.
yarn build
builds the packageyarn build:watch
builds the package in watch modeyarn test
runs the tests onceyarn test:watch
runs the tests in watch modeyarn test:coverage
runs the tests and generates a coverage reportyarn lint
runs TypeScript type checkingyarn format
formats all source files with Prettier
Publishing to npm registry
@fulldecent will periodically create a GitHub release and this triggers the npm publish workflow.
Periodically, load schemaorg-current-https.jsonld file from https://schema.org/docs/developers.html and save to src/vendor/schemaorg-current-https.jsonld. Ideally, the sponsors of Schema.org: Google, Inc., Yahoo, Inc., Microsoft Corporation and Yandex should maintain a NPM package for this file that we can depend on. This would allow our package manager to handle updates.
This is a Node.js library designed for build-time HTML validation. For browser usage, ensure your bundler supports the module format you're using. Some of our rules use cURL
which will not work in the browser. We would like to switch to fetch()
but are limited by HTML-validate.
Ensure your changes pass yarn format && yarn lint && yarn test
.