
HTML Linter
BetaA powerful static analysis tool for HTML that helps catch common mistakes and enforce best practices
html-linter is a Rust library for validating HTML content through customizable rules. It helps developers maintain consistent HTML structure, enforce best practices, and catch common errors early in development.
The linter is highly configurable through both programmatic APIs and JSON configuration, making it adaptable to different project requirements and coding standards.
Demo
1<div class="container">2 <h1>Welcome!</h1>3 <p>This is a sample<p>4 <div>Nested content5 <span>More text</div>6 </span>7 <img src="photo.jpg">8</div>
Key Features
- Rule-based HTML linting with customizable severity levels
- Multiple rule types for comprehensive validation
- Semantic HTML and SEO validation
- JSON-based configuration support
- Detailed error reporting with line/column information
Rule-Based Validation
Define custom rules for HTML validation with different severity levels (Error, Warning, Info). Rules can check for element presence, attribute requirements, content patterns, and more.
1 | { |
2 | "name": "img-alt", |
3 | "rule_type": "AttributePresence", |
4 | "severity": "Error", |
5 | "selector": "img", |
Note The selector uses CSS-like syntax to target all img elements in the document. This approach makes the rule definition intuitive for web developers already familiar with CSS selectors. You can create more specific selectors like 'article img' or 'img.hero' to target only certain images. | |
6 | "condition": "alt-missing", |
7 | "message": "Images must have alt attributes" |
Note The condition 'alt-missing' checks specifically for the absence of the alt attribute, while the message provides clear guidance on what needs to be fixed. This combination helps developers understand both the issue and how to resolve it, improving the overall accessibility of their HTML content. | |
8 | } |
Semantic Validation
Enforce semantic HTML usage and proper document structure. The linter can identify cases where semantic elements should be used instead of generic divs.
1 | { |
2 | "name": "semantic-header", |
3 | "rule_type": "Semantics", |
Note The 'Semantics' rule type evaluates proper HTML5 semantic element usage to enhance:
Consider these examples:
| |
4 | "severity": "Warning", |
Note Using 'Warning' severity creates a balance between enforcing best practices and maintaining flexibility. Unlike errors, warnings won't break builds or deployments but still highlight opportunities for improvement. This is ideal for semantic issues which may require contextual judgment rather than strict enforcement. | |
5 | "selector": "div.header", |
6 | "condition": "semantic-structure", |
7 | "message": "Use <header> instead of div.header" |
8 | } |
SEO Optimization
Validate meta tags, Open Graph tags, and other SEO-related elements to ensure proper page optimization.
1 | { |
2 | "name": "meta-description", |
3 | "rule_type": "ElementContent", |
4 | "severity": "Error", |
5 | "selector": "head", |
6 | "condition": "meta-tags", |
7 | "message": "Meta description must be 50-160 characters", |
8 | "options": { |
9 | "required_meta_tags": [{ |
10 | "name": "description", |
11 | "pattern": { |
12 | "type": "MinLength", |
13 | "value": 50 |
14 | } |
15 | }] |
Note The options object provides powerful configuration capabilities beyond simple attribute checking. Here, it creates a complex validation rule that can evaluate specific content patterns within meta tags. This extensibility allows for highly customized rules tailored to project-specific requirements and SEO standards. | |
16 | } |
17 | } |
Rust Implementation
Built in Rust for optimal performance and memory safety. The library uses efficient parsing and validation algorithms to process HTML quickly, even for large documents.
Integration Example
1 | use html_linter::{HtmlLinter, Rule}; |
2 | |
3 | let linter = HtmlLinter::from_json_file( |
4 | "rules.json", |
5 | None |
Note The HTML Linter supports JSON configuration to decouple rules from code. This enables:
A typical rules.json file might look like:
| |
6 | )?; |
7 | |
Note The actual linting operation is a single function call that processes the entire HTML document against all defined rules. Despite its simple interface, the linter performs complex parsing and analysis under the hood, leveraging Rust's performance advantages to handle even large documents efficiently. The operation returns a Result type, properly handling potential errors. | |
8 | let results = linter.lint(html_content)?; |
9 | for result in results { |
Note The linter returns structured results that include both the severity level and the detailed message. This makes it easy to filter issues by importance or to format them appropriately for different output contexts - such as CI/CD pipelines, development environments, or reporting tools. The example shows simple console output, but the structured data enables integration with any reporting system. | |
10 | println!("{}: {}", result.severity, result.message); |
11 | } |
Testing
Comprehensive test suite ensures reliability across different HTML structures and rule configurations. Integration tests validate real-world use cases and edge cases.
Critical for accessibility: Setting severity to 'Error' makes this rule a hard requirement that will fail builds when violated.
Missing alt attributes create barriers for users with screen readers and violate WCAG guidelines. Here's how screen readers interpret images:
<!-- Image without alt --> <img src="logo.png"> <!-- Screen reader announces: "image" or filename --> <!-- Image with alt --> <img src="logo.png" alt="Company Logo"> <!-- Screen reader announces: "Company Logo, image" -->