An open API service indexing awesome lists of open source software.

https://github.com/fulldecent/html-validate-nice-checkers

HTML-validate plugin and rules you should always use
https://github.com/fulldecent/html-validate-nice-checkers

Last synced: 2 months ago
JSON representation

HTML-validate plugin and rules you should always use

Awesome Lists containing this project

README

          

# :cherry_blossom: Nice Checkers

[![CI](https://github.com/fulldecent/html-validate-nice-checkers/actions/workflows/ci.yml/badge.svg)](https://github.com/fulldecent/html-validate-nice-checkers/actions/workflows/ci.yml)

An opinionated collection of essential HTML validation rules that promote best practices™ for web development. Use this plugin with [HTML-validate](https://html-validate.org/).

## Features

- :white_check_mark: **Turnkey validation**: 11 rules covering SEO, security, accessibility, and best practices
- :white_check_mark: **TypeScript**: full type definitions included
- :warning: **Dual module support**: works with both ESM (`import`) and CJS (`require`) (known issue: ESM and CommonJS builds are [sometimes not building correctly](https://github.com/fulldecent/html-validate-nice-checkers/issues/6))
- :white_check_mark: **Tree shakeable**: import only what you need
- :white_check_mark: **Modern tooling**: [built with tsup](https://github.com/fulldecent/html-validate-nice-checkers/blob/main/tsup.config.ts), [tested with Vitest](https://github.com/fulldecent/html-validate-nice-checkers/blob/main/vitest.config.ts), [good IDE hinting](https://github.com/fulldecent/html-validate-nice-checkers/blob/main/tsconfig.json) and [enforced style checking](https://github.com/fulldecent/html-validate-nice-checkers/blob/main/.prettierrc)
- :white_check_mark: **Comprehensive testing**: high test coverage with realistic fixtures

## Installation

These instructions assume you will use Nice Checkers as part of a web test suite running Node (20+) and [HTML-validate](https://html-validate.org/). See [GitHub Pages Template](https://github.com/fulldecent/github-pages-template) for an end-to-end example, including GitHub Actions continuous integration, testing and GitHub Pages deployment for all modern best practices.

### Add package dev dependency

_Nice Checkers is a **dev** dependency for you because you need it to test your website, not to deploy it._

```sh
# Using Yarn
yarn add -D html-validate-nice-checkers

# Using npm
npm install --dev html-validate-nice-checkers
```

### Update your HTML-validate configuration

This example assumes you are using the .htmlvalidate.mjs configuration flavor. HTML-validate also [supports other configuration flavors](https://html-validate.org/usage/index.html#configuration).

```diff
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"]
});
```

## Rules

All rules are enabled by default when you extend from `nice-checkers-plugin:recommended`. Find introductions and configuration options for each rule below.

### `nice-checkers/alternate-language-url`

Ensures that all alternate language links (``) use fully qualified URLs with protocol (https://). This follows Google's best practices for international and multilingual websites.

According to [Google's documentation on localized versions](https://developers.google.com/search/docs/specialty/international/localized-versions), alternate language links must use fully qualified URLs:

> "The value of the hreflang attribute identifies the language (in ISO 639-1 format) and optionally a region (in ISO 3166-1 Alpha 2 format) of an alternate URL. **The href attribute contains the full URL of the alternate version.**"

Using relative or protocol-relative URLs can cause search engines to misinterpret or ignore your international content signals.

```diff
-
-
-
+
+
+
```

#### Configuration

```json
{
"rules": {
"nice-checkers/alternate-language-url": "error"
}
}
```

#### Configuration options

This rule has no configurable options.

### `nice-checkers/canonical-link`

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.

```diff




My first website about horses
+


This page is missing a required canonical link element in the head.


```

### Configuration

```json
{
"rules": {
"nice-checkers/canonical-link": "error"
}
}
```

### Configuration options

This rule has no configurable options.

### `nice-checkers/external-links`

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.

**Note:** This rule automatically skips validation of:

- `` - Canonical URLs point to the site itself and may not be published yet during development/preview
- `` - Alternate language URLs also point to the site itself and may not exist during development

This allows you to validate your HTML before publishing, even when the canonical and alternate URLs reference the final production URLs.

```diff
- This link is broken
+ This link works
```

### Configuration

```json
{
"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)"
}
]
}
}
```

### Configuration options

| 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 |
| `manuallyReviewedPath` | `string` | `""` | Path to CSV file with manually reviewed URLs (see below) |
| `manuallyReviewedExpirySeconds` | `number` | `31536000` | Expiry time for manually reviewed URLs (default: 365 days) |

#### Manually reviewed URLs

Some websites resist automated checking (anti-scraping, rate limiting, etc.). You can maintain a CSV file of manually reviewed URLs that should be treated as valid:

**CSV format:**

```csv
url,last_approved_timestamp
https://anti-scraping-site.example.com/page,1764877136
https://example.com/manually-verified,1764877136
```

- The first line must be the header: `url,last_approved_timestamp`
- `url`: The exact URL to approve (must match exactly, including protocol and path)
- `last_approved_timestamp`: Unix timestamp (seconds since epoch) when you last verified the URL

URLs in this file are approved if:

1. The URL matches exactly
2. Current time < (last_approved_timestamp + manuallyReviewedExpirySeconds)

This allows time-limited manual approvals that automatically expire, ensuring you periodically re-verify that URLs still exist.

### `nice-checkers/https-links`

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.

```diff
- Should use HTTPS
- Image
+ Uses HTTPS
+ Image
```

### Configuration

```json
{
"rules": {
"nice-checkers/https-links": [
"warn",
{
"cacheExpiryFoundSeconds": 2592000,
"cacheExpiryNotFoundSeconds": 259200,
"timeoutSeconds": 10,
"cacheDatabasePath": "cache/https-availability.db"
}
]
}
}
```

### Configuration options

| 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 |

### `nice-checkers/internal-links`

Validates that all internal links point to existing files in your project. This rule prevents broken internal navigation and missing resource references.

**Case-sensitive checking:** This rule performs case-sensitive file matching even on case-insensitive file systems (like macOS default). A link to `/abc.webp` will fail if the actual file is `/AbC.webp`, ensuring your code works correctly on Linux servers where case matters.

```diff
- Broken internal link
- Missing image
- Wrong case (actual file: logo.png)
+ Working internal link
+ Company logo
+ Correct case
```

### Configuration

```json
{
"rules": {
"nice-checkers/internal-links": [
"error",
{
"webRoot": "./build",
"alternativeExtensions": [".html", ".php"],
"indexFile": "index.html"
}
]
}
}
```

### Configuration options

| 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 |

### `nice-checkers/latest-packages`

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.

```diff
-
-
+
+
```

### Configuration

```json
{
"rules": {
"nice-checkers/latest-packages": [
"warn",
{
"cacheExpirySeconds": 172800,
"timeoutSeconds": 10,
"cacheDatabasePath": "cache/latest-packages.db",
"skipUrlPatterns": ["googletagmanager.com"]
}
]
}
}
```

### Configuration options

| 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 |

### `nice-checkers/match-regex`

Requires page source to match all `mustMatch` regexes and none of the `mustNotMatch` regexes. This rule is off by default because it requires user-provided patterns.

Use this to enforce that specific content or HTML elements are present on every page, or to forbid certain words or patterns. All patterns are evaluated with the `s` (dotAll) flag enabled, so they can match across multiple lines.

When configuring via JSON, patterns must be given as strings. When configuring via JavaScript or TypeScript, each entry may be either a string or a `RegExp` instance. For `RegExp` inputs, all existing user flags are preserved and `s` is added if not already present.

For example, you might require a specific footer script on every page:

```json
{
"rules": {
"nice-checkers/match-regex": [
"error",
{
"mustMatch": [
"\\s*