Comprehensive collection of 42 built-in HTML validation rules covering syntax, semantics, accessibility, and best practices, with support for extensible custom rule development.
All HTMLHint rules implement a consistent interface for registration and execution.
/**
* Interface that all HTMLHint rules must implement
*/
interface Rule {
/** Unique identifier for the rule */
id: string;
/** Human-readable description of what the rule validates */
description: string;
/** Optional documentation link for the rule */
link?: string;
/**
* Initialize the rule with parser and reporter instances
* @param parser - HTML parser instance for listening to parsing events
* @param reporter - Reporter instance for recording validation issues
* @param options - Rule-specific configuration options
*/
init(parser: HTMLParser, reporter: Reporter, options: unknown): void;
}Ruleset objects define which rules to apply and their configuration options.
/**
* Configuration object defining which rules to apply and their options
*/
interface Ruleset {
// Core HTML structure rules
'tagname-lowercase'?: boolean;
'tag-pair'?: boolean;
'tag-self-close'?: boolean;
'tag-no-obsolete'?: boolean;
'tagname-specialchars'?: boolean;
// Attribute rules
'attr-lowercase'?: boolean | Array<string | RegExp>;
'attr-no-duplication'?: boolean;
'attr-no-unnecessary-whitespace'?: boolean;
'attr-sorted'?: boolean;
'attr-unsafe-chars'?: boolean;
'attr-value-double-quotes'?: boolean;
'attr-value-not-empty'?: boolean;
'attr-value-single-quotes'?: boolean;
'attr-value-no-duplication'?: boolean;
'attr-whitespace'?: boolean;
// Document structure rules
'doctype-first'?: boolean;
'doctype-html5'?: boolean;
'title-require'?: boolean;
'head-script-disabled'?: boolean;
// Element-specific rules
'alt-require'?: boolean;
'src-not-empty'?: boolean;
'href-abs-or-rel'?: 'abs' | 'rel';
'input-requires-label'?: boolean;
'button-type-require'?: boolean;
'frame-title-require'?: boolean;
'h1-require'?: boolean;
'main-require'?: boolean;
// Content and style rules
'empty-tag-not-self-closed'?: boolean;
'inline-script-disabled'?: boolean;
'inline-style-disabled'?: boolean;
'script-disabled'?: boolean;
'style-disabled'?: boolean;
// Accessibility and semantic rules
'html-lang-require'?: boolean;
'meta-charset-require'?: boolean;
'meta-description-require'?: boolean;
'meta-viewport-require'?: boolean;
// ID and class rules
'id-unique'?: boolean;
'id-class-ad-disabled'?: boolean;
'id-class-value'?: 'underline' | 'dash' | 'hump' | { regId: RegExp; message: string };
// Formatting rules
'space-tab-mixed-disabled'?: boolean | 'space' | 'space1' | 'space2' | 'space3' | 'space4' | 'space5' | 'space6' | 'space7' | 'space8' | 'tab';
'spec-char-escape'?: boolean;
// Custom validation rules
'tags-check'?: { [tagName: string]: Record<string, unknown> };
// Extensible for custom rules
[ruleId: string]: unknown;
}Rules for validating overall document structure and required elements.
doctype-first: Ensures DOCTYPE declaration appears at the beginning of the document.
'doctype-first': truedoctype-html5: Enforces HTML5 DOCTYPE format.
'doctype-html5': truetitle-require: Requires a title element in the document head.
'title-require': truehead-script-disabled: Prevents script elements in the document head.
'head-script-disabled': trueRules for validating HTML tags and their usage.
tagname-lowercase: Enforces lowercase tag names.
'tagname-lowercase': truetag-pair: Ensures all tags are properly paired (opened and closed).
'tag-pair': truetag-self-close: Enforces consistent self-closing tag format.
'tag-self-close': truetag-no-obsolete: Prevents use of obsolete HTML elements.
'tag-no-obsolete': truetagname-specialchars: Prevents special characters in tag names.
'tagname-specialchars': trueempty-tag-not-self-closed: Prevents self-closing syntax on non-void elements.
'empty-tag-not-self-closed': trueRules for validating HTML attributes and their values.
attr-lowercase: Enforces lowercase attribute names, with optional exceptions.
// Simple boolean
'attr-lowercase': true
// With exceptions
'attr-lowercase': ['viewBox', 'preserveAspectRatio']attr-no-duplication: Prevents duplicate attributes on the same element.
'attr-no-duplication': trueattr-value-double-quotes: Enforces double quotes for attribute values.
'attr-value-double-quotes': trueattr-value-single-quotes: Enforces single quotes for attribute values.
'attr-value-single-quotes': trueattr-value-not-empty: Requires non-empty attribute values.
'attr-value-not-empty': trueattr-value-no-duplication: Prevents duplicate attribute values within the same element.
'attr-value-no-duplication': trueattr-sorted: Requires attributes to be sorted alphabetically.
'attr-sorted': trueattr-unsafe-chars: Prevents unsafe characters in attribute values.
'attr-unsafe-chars': trueattr-no-unnecessary-whitespace: Removes unnecessary whitespace in attribute values.
'attr-no-unnecessary-whitespace': trueattr-whitespace: Controls whitespace around attributes.
'attr-whitespace': trueRules for validating content elements and media.
alt-require: Requires alt attributes on img elements.
'alt-require': truesrc-not-empty: Ensures src attributes are not empty.
'src-not-empty': truehref-abs-or-rel: Enforces absolute or relative URL format for href attributes.
'href-abs-or-rel': 'abs' // or 'rel'Rules for improving semantic markup and accessibility.
html-lang-require: Requires lang attribute on html element.
'html-lang-require': trueinput-requires-label: Ensures input elements have associated labels.
'input-requires-label': truebutton-type-require: Requires type attribute on button elements.
'button-type-require': trueframe-title-require: Requires title attribute on frame elements.
'frame-title-require': trueh1-require: Requires at least one h1 element in the document.
'h1-require': truemain-require: Requires a main element in the document.
'main-require': trueRules for document metadata and information.
meta-charset-require: Requires meta charset declaration.
'meta-charset-require': truemeta-description-require: Requires meta description element.
'meta-description-require': truemeta-viewport-require: Requires meta viewport declaration.
'meta-viewport-require': trueRules for validating ID and class attributes.
id-unique: Ensures ID attributes are unique within the document.
'id-unique': trueid-class-ad-disabled: Prevents advertisement-related ID and class names.
'id-class-ad-disabled': trueid-class-value: Enforces naming conventions for ID and class values.
// Predefined patterns
'id-class-value': 'underline' // underscore_case
'id-class-value': 'dash' // kebab-case
'id-class-value': 'hump' // camelCase
// Custom pattern
'id-class-value': {
regId: /^[a-z][a-z0-9-]*$/,
message: 'ID should be lowercase with hyphens'
}Rules for managing scripts and styles.
inline-script-disabled: Prevents inline JavaScript.
'inline-script-disabled': trueinline-style-disabled: Prevents inline CSS styles.
'inline-style-disabled': truescript-disabled: Completely disables script elements.
'script-disabled': truestyle-disabled: Completely disables style elements.
'style-disabled': trueRules for code formatting and whitespace.
space-tab-mixed-disabled: Prevents mixing spaces and tabs for indentation.
'space-tab-mixed-disabled': true // Detect mixed usage
'space-tab-mixed-disabled': 'space' // Enforce spaces only
'space-tab-mixed-disabled': 'space2' // Enforce 2-space indentation
'space-tab-mixed-disabled': 'tab' // Enforce tabs onlyspec-char-escape: Requires proper escaping of special characters.
'spec-char-escape': truetags-check: Enables custom tag-specific validation rules.
'tags-check': {
'img': {
'alt': true, // Require alt attribute
'width': 'number', // Validate width as number
'height': 'number' // Validate height as number
},
'a': {
'href': true // Require href attribute
}
}const strictHTML5 = {
'doctype-html5': true,
'tagname-lowercase': true,
'attr-lowercase': true,
'attr-value-double-quotes': true,
'tag-pair': true,
'spec-char-escape': true,
'id-unique': true,
'src-not-empty': true,
'alt-require': true,
'title-require': true,
'meta-charset-require': true,
'html-lang-require': true
};const accessibilityFocused = {
'alt-require': true,
'html-lang-require': true,
'input-requires-label': true,
'frame-title-require': true,
'h1-require': true,
'main-require': true,
'meta-description-require': true,
'meta-viewport-require': true,
'button-type-require': true
};const lenient = {
'tagname-lowercase': true,
'tag-pair': true,
'id-unique': true,
'attr-no-duplication': true
};Create custom rules by implementing the Rule interface:
const customRule: Rule = {
id: 'custom-rule-name',
description: 'Description of what this rule validates',
link: 'https://example.com/rule-docs',
init(parser, reporter, options) {
// Listen for parsing events
parser.addListener('tagstart', (event) => {
// Validate tag start events
if (/* validation condition */) {
reporter.error(
'Error message',
event.line,
event.col,
this,
event.raw
);
}
});
parser.addListener('text', (event) => {
// Validate text content
});
parser.addListener('tagend', (event) => {
// Validate tag end events
});
}
};
// Register the custom rule
HTMLHint.addRule(customRule);Available parser events:
startendtagstarttagendtextcommentcdataall