Full-featured CLI for batch HTML validation with file globbing, configuration management, multiple output formats, and comprehensive CI/CD integration support.
HTMLHint provides a powerful command-line interface accessible via the
htmlhint# Basic usage
htmlhint [files/directories/patterns/urls] [options]
# Examples
htmlhint # Validate current directory
htmlhint index.html # Validate single file
htmlhint src/**/*.html # Validate with glob patterns
htmlhint https://example.com/ # Validate remote URL
htmlhint --init # Create configuration file
htmlhint --list # List all available rulesUsage: htmlhint <file|folder|pattern|stdin|url ...> [options]
Options:
-V, --version output the version number
-l, --list show all of the rules available
--init create a new .htmlhintrc config file with default rules
-c, --config <file> custom configuration file
-r, --rules <ruleid, ruleid=value ...> set all of the rules available
-R, --rulesdir <file|folder> load custom rules from file or folder
-f, --format <formatter> output messages as custom format
-i, --ignore <pattern, pattern ...> add pattern to exclude matches
--nocolor disable color
--warn Warn only, exit with 0
-h, --help display help for commandHTMLHint's CLI supports multiple output formatters through an extensible formatter system.
/**
* Core HTMLHint functionality interface
*/
interface HTMLHintCore {
rules: { [id: string]: Rule };
readonly defaultRuleset: Ruleset;
verify(html: string, ruleset?: Ruleset): Hint[];
addRule(rule: Rule): void;
format(arrMessages: Hint[], options?: FormatOptions): string[];
}
/**
* Interface that all HTMLHint rules must implement
*/
interface Rule {
id: string;
description: string;
link?: string;
init(parser: HTMLParser, reporter: Reporter, options: unknown): void;
}
/**
* Configuration object defining which rules to apply and their options
*/
interface Ruleset {
[ruleId: string]: unknown;
}
/**
* Represents a validation issue found during HTML analysis
*/
interface Hint {
type: ReportType;
message: string;
raw: string;
evidence: string;
line: number;
col: number;
rule: {
id: string;
description: string;
link: string;
};
}
/**
* Formatting options for message display
*/
interface FormatOptions {
colors?: boolean;
indent?: number;
}
/**
* Severity levels for validation issues
*/
enum ReportType {
error = "error",
warning = "warning",
info = "info"
}
/**
* Node.js EventEmitter interface
*/
interface EventEmitter {
emit(event: string | symbol, ...args: any[]): boolean;
on(event: string | symbol, listener: (...args: any[]) => void): this;
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
}
/**
* Formatter interface for generating different output formats
*/
interface Formatter extends EventEmitter {
/**
* Get list of supported formatter names
* @returns Array of supported formatter identifiers
*/
getSupported(): string[];
/**
* Initialize formatter with HTMLHint instance and options
* @param htmlhint - HTMLHint core instance
* @param options - Formatter configuration options
*/
init(htmlhint: HTMLHintCore, options: { nocolor?: boolean }): void;
/**
* Set the active output format
* @param format - Formatter name to use for output
*/
setFormat(format: string): void;
// Event emitters
emit(event: 'start'): boolean;
emit(event: 'file', arg: FormatterFileEvent): boolean;
emit(event: 'config', arg: FormatterConfigEvent): boolean;
emit(event: 'end', arg: FormatterEndEvent): boolean;
// Event listeners
on(event: 'start', listener: () => void): this;
on(event: 'file', listener: (event: FormatterFileEvent) => void): this;
on(event: 'config', listener: (event: FormatterConfigEvent) => void): this;
on(event: 'end', listener: (event: FormatterEndEvent) => void): this;
}
/**
* Event data for file processing completion
*/
interface FormatterFileEvent {
file: string;
messages: Hint[];
time: number;
}
/**
* Event data for configuration loading
*/
interface FormatterConfigEvent {
ruleset: Ruleset;
configPath?: string;
}
/**
* Event data for processing completion
*/
interface FormatterEndEvent {
arrAllMessages: Array<{
file: string;
messages: Hint[];
time: number;
}>;
allFileCount: number;
allHintFileCount: number;
allHintCount: number;
time: number;
}
/**
* Formatter callback function type for custom formatter implementations
*/
type FormatterCallback = (
formatter: Formatter,
htmlhint: HTMLHintCore,
options: { nocolor?: boolean }
) => void;HTMLHint supports 9 different output formatters for various use cases.
/**
* Supported output format identifiers
*/
type SupportedFormats =
| 'default' // Colored terminal output with context
| 'json' // JSON format for programmatic processing
| 'checkstyle' // Checkstyle XML format
| 'junit' // JUnit XML format for test integration
| 'sarif' // SARIF format for security analysis
| 'html' // HTML report format
| 'markdown' // Markdown format for documentation
| 'compact' // Compact single-line format
| 'unix' // Unix-style format for shell processing# Validate single file
htmlhint index.html
# Validate multiple files
htmlhint file1.html file2.html file3.html
# Validate directory (automatically finds *.html and *.htm files)
htmlhint src/
# Validate with glob patterns
htmlhint "src/**/*.html"
htmlhint "pages/*.{html,htm}"# Create default configuration file
htmlhint --init
# Use custom configuration file
htmlhint --config custom.htmlhintrc index.html
# Specify rules via command line
htmlhint --rules "tag-pair,id-unique,attr-value-double-quotes" index.html
# Complex rule configuration
htmlhint --rules "tag-pair:true,id-class-value:underline,attr-lowercase:true" src/# JSON output for programmatic processing
htmlhint --format json src/ > results.json
# JUnit XML for CI/CD integration
htmlhint --format junit src/ > test-results.xml
# SARIF format for security analysis
htmlhint --format sarif src/ > security-results.sarif
# HTML report
htmlhint --format html src/ > report.html
# Compact format for parsing
htmlhint --format compact src/
# Unix format for shell scripting
htmlhint --format unix src/ | grep "error"# Ignore specific patterns
htmlhint --ignore "**/node_modules/**,**/dist/**" src/
# Complex ignore patterns
htmlhint --ignore "temp/**,build/**,*.min.html" .
# Multiple patterns
htmlhint --ignore "vendor/**" --ignore "legacy/**" src/HTMLHint provides a utility function for parsing glob patterns and extracting path components.
/**
* Parse glob pattern and extract components for file processing
* @param target - Glob pattern or file path to parse
* @returns Object with parsed components
*/
function parseGlob(target: string): {
/** Base directory path */
base: string;
/** Glob pattern component */
glob: string;
/** Information about the pattern */
is: {
glob: boolean;
};
/** Path information */
path: {
basename: string;
};
};# Validate remote URL
htmlhint https://example.com/
# Validate multiple URLs
htmlhint https://example.com/ https://test.com/page.html
# URL with specific format
htmlhint --format json https://example.com/ > url-results.json# Process HTML from stdin
echo "<div><p>Hello</div>" | htmlhint stdin
# Process piped content
curl -s https://example.com/ | htmlhint stdin
# With custom rules
echo "<DIV>content</DIV>" | htmlhint --rules "tagname-lowercase" stdin# Load custom rules from directory
htmlhint --rulesdir ./custom-rules/ src/
# Load custom rules from single file
htmlhint --rulesdir ./my-custom-rule.js src/
# Custom rules with specific configuration
htmlhint --rulesdir ./rules/ --config ./config.json src/# Exit with 0 for warnings (useful in CI)
htmlhint --warn src/
# Generate JUnit report for build systems
htmlhint --format junit src/ > htmlhint-results.xml
# Generate SARIF for security scanning
htmlhint --format sarif src/ > htmlhint.sarif
# Colorless output for log files
htmlhint --nocolor --format compact src/ >> build.logHTMLHint automatically searches for
.htmlhintrc{
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": true,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"attr-no-duplication": true,
"title-require": true,
"alt-require": true,
"id-class-value": "dash"
}# Generate default configuration file
htmlhint --init
# This creates .htmlhintrc with default rules:
# {
# "tagname-lowercase": true,
# "attr-lowercase": true,
# "attr-value-double-quotes": true,
# "doctype-first": true,
# "tag-pair": true,
# "spec-char-escape": true,
# "id-unique": true,
# "src-not-empty": true,
# "attr-no-duplication": true,
# "title-require": true
# }{
"// Strict HTML5 configuration": "",
"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,
"html-lang-require": true,
"meta-charset-require": true
}{
"// Accessibility-focused configuration": "",
"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
}/path/to/file.html
line 5, col 10: Tag must be paired, missing: [ </div> ], start tag: < div > (tag-pair)
line 8, col 15: Attribute value must be in double quotes. (attr-value-double-quotes)
2 problems in 1 file[
{
"file": "/path/to/file.html",
"messages": [
{
"type": "error",
"message": "Tag must be paired, missing: [ </div> ]",
"raw": "<div>",
"evidence": "<div><p>Content</p>",
"line": 5,
"col": 10,
"rule": {
"id": "tag-pair",
"description": "Tag must be paired."
}
}
]
}
]<?xml version="1.0" encoding="utf-8"?>
<testsuite name="HTMLHint Tests" tests="1" failures="1" errors="0" time="0.005">
<testcase name="/path/to/file.html" time="0.003">
<failure message="line 5, col 10: Tag must be paired (tag-pair)">
<![CDATA[line 5, col 10: Tag must be paired, missing: [ </div> ], start tag: < div > (tag-pair)]]>
</failure>
</testcase>
</testsuite>{
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "HTMLHint",
"version": "1.6.3"
}
},
"results": [
{
"level": "error",
"message": {
"text": "Tag must be paired, missing: [ </div> ]"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "/path/to/file.html"
},
"region": {
"startLine": 5,
"startColumn": 10
}
}
}
]
}
]
}
]
}// custom-rule.js
module.exports = function(HTMLHint) {
HTMLHint.addRule({
id: 'custom-rule',
description: 'Custom validation rule',
init: function(parser, reporter, options) {
// Rule implementation
}
});
};# Load custom rule
htmlhint --rulesdir ./custom-rule.js src/#!/bin/bash
# validate-all.sh
# Process multiple directories with different configurations
htmlhint --config strict.htmlhintrc src/critical/ --format json > critical-results.json
htmlhint --config lenient.htmlhintrc src/legacy/ --format json > legacy-results.json
htmlhint --config accessibility.htmlhintrc src/public/ --format json > a11y-results.json
# Combine results
jq -s 'add' *-results.json > combined-results.json# Package.json scripts
{
"scripts": {
"lint:html": "htmlhint src/**/*.html",
"lint:html:ci": "htmlhint --format junit src/**/*.html > htmlhint-results.xml",
"lint:html:fix": "htmlhint --warn src/**/*.html"
}
}--warn--warnThe CLI handles various error conditions gracefully: