HTML Linter Logo

HTML Linter

Beta

A 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

HTML Linter
1<div class="container">
2 <h1>Welcome!</h1>
3 <p>This is a sample<p>
4 <div>Nested content
5 <span>More text</div>
6 </span>
7 <img src="photo.jpg">
8</div>
⚠️Unclosed paragraph tagLine 3
⚠️Mismatched closing tagsLine 5
⚠️Missing closing tag for img elementLine 7

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.

rule-example.json
1 {
2 "name": "img-alt",
3 "rule_type": "AttributePresence",
4 "severity": "Error",
Note

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

semantic-rule.json
1 {
2 "name": "semantic-header",
3 "rule_type": "Semantics",
Note

The 'Semantics' rule type evaluates proper HTML5 semantic element usage to enhance:

  • Accessibility: Screen readers rely on semantic structure
  • SEO: Search engines weigh semantic elements in ranking
  • Code clarity: Self-documenting structure is easier to maintain

Consider these examples:

<!-- Non-semantic approach -->
<div class="header">
  <div class="logo">Site Name</div>
  <div class="nav">...</div>
</div>

<!-- Semantic approach -->
<header>
  <h1>Site Name</h1>
  <nav>...</nav>
</header>
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.

seo-rule.json
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

example.rs
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:

  1. Project-specific rule customization without code changes
  2. Version-controlled linting standards
  3. Shareable configurations across projects

A typical rules.json file might look like:

{
  "rules": [
    {
      "name": "img-alt",
      "rule_type": "AttributePresence",
      "severity": "Error",
      "selector": "img",
      "condition": "alt-missing"
    },
    {
      "name": "semantic-header",
      "rule_type": "Semantics",
      "severity": "Warning",
      "selector": "div.header"
    }
  ]
}
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.

Details

Time
2024
Source
Tech Stack
  • Rust
  • HTML
  • JSON
Package
Documentation
Status
Active