Web Validation and Linting

Probar provides Rust-native validation and linting for HTML, CSS, and JavaScript. No external tools like eslint, stylelint, or htmlhint required.

Overview

The validation system is 100% Rust:

ValidatorReplacesChecks
WebValidator::validate_htmlhtmlhintStructure, tags, accessibility
WebValidator::lint_cssstylelintSyntax, selectors, patterns
WebValidator::lint_jseslintLine limit, security issues
WebValidator::validate_allAll aboveComplete validation

HTML Validation

Validate HTML documents for structure and accessibility.

Basic Usage

#![allow(unused)]
fn main() {
use jugar_probar::web::{HtmlBuilder, WebValidator};

let html = HtmlBuilder::new()
    .title("My App")
    .canvas("game", 800, 600)
    .build()?;

let result = WebValidator::validate_html(&html);

if result.is_valid() {
    println!("HTML validation passed!");
} else {
    for error in &result.errors {
        println!("Error: {}", error);
    }
}
}

Checks Performed

CheckError/Warning
Missing DOCTYPEError
Missing <html> tagError
Missing <head> tagError
Missing <body> tagError
Missing or empty <title>Error
Missing charset metaWarning
Missing viewport metaWarning
Missing lang attributeWarning

CSS Linting

Lint CSS stylesheets for syntax and best practices.

Basic Usage

#![allow(unused)]
fn main() {
use jugar_probar::web::{CssBuilder, WebValidator};

let css = CssBuilder::new()
    .reset()
    .build()?;

let result = WebValidator::lint_css(&css);

if result.is_valid() {
    println!("CSS lint passed!");
}

for warning in &result.warnings {
    println!("Warning: {}", warning);
}
}

Checks Performed

CheckError/Warning
Empty selectorError
Empty stylesheetWarning
Use of !importantWarning
Vendor prefixesWarning

JavaScript Linting

Lint JavaScript for security issues and Zero-JS policy compliance.

Basic Usage

#![allow(unused)]
fn main() {
use jugar_probar::web::{JsBuilder, WebValidator};

let js = JsBuilder::new("app.wasm", "canvas")
    .build()?;

let result = WebValidator::lint_js(&js);

if result.is_valid() {
    println!("JS lint passed!");
} else {
    for issue in &result.security_issues {
        println!("{:?}: {}", issue.severity, issue.description);
    }
}
}

Security Checks

PatternSeverityDescription
eval(CriticalCode injection risk
new Function(CriticalDynamic code execution
innerHTMLHighXSS vulnerability
document.writeMediumDeprecated, security risk
setTimeout("..."HighString arg is eval-like
setInterval("..."HighString arg is eval-like

Line Limit

JavaScript is limited to 20 lines (Zero-JS policy):

#![allow(unused)]
fn main() {
let result = WebValidator::lint_js(&js);

if js.line_count > 20 {
    assert!(!result.is_valid());
    assert!(result.errors.iter().any(|e| e.contains("line limit")));
}
}

Accessibility Checking

Check HTML for WCAG accessibility issues.

Basic Usage

#![allow(unused)]
fn main() {
use jugar_probar::web::{HtmlBuilder, WebValidator};

let html = HtmlBuilder::new()
    .title("Game")
    .canvas("game", 800, 600)
    .build()?;

let issues = WebValidator::check_accessibility(&html);

for issue in &issues {
    println!("[{}] {} - {}",
        issue.wcag_ref.as_deref().unwrap_or("N/A"),
        issue.element_id.as_deref().unwrap_or("document"),
        issue.description
    );
}
}

Accessibility Checks

IssueWCAG RefSeverity
Canvas missing roleWCAG 4.1.2Medium
Canvas missing aria-labelWCAG 1.1.1Medium
Button missing aria-labelWCAG 4.1.2Medium
Input missing aria-labelWCAG 1.3.1Medium
Missing lang attributeWCAG 3.1.1High

Combined Validation

Validate all assets at once with validate_all.

Basic Usage

#![allow(unused)]
fn main() {
use jugar_probar::web::{HtmlBuilder, CssBuilder, JsBuilder, WebValidator};

let html = HtmlBuilder::new().title("App").canvas("c", 100, 100).build()?;
let css = CssBuilder::new().reset().build()?;
let js = JsBuilder::new("app.wasm", "c").build()?;

let report = WebValidator::validate_all(&html, &css, &js);

println!("Valid: {}", report.is_valid());
println!("Errors: {}", report.error_count());
println!("Warnings: {}", report.warning_count());
}

ValidationReport Structure

#![allow(unused)]
fn main() {
pub struct ValidationReport {
    pub html: HtmlValidationResult,
    pub css: CssLintResult,
    pub js: JsLintResult,
    pub accessibility: Vec<AccessibilityIssue>,
}

impl ValidationReport {
    pub fn is_valid(&self) -> bool;
    pub fn error_count(&self) -> usize;
    pub fn warning_count(&self) -> usize;
}
}

Severity Levels

Security and accessibility issues have severity levels:

#![allow(unused)]
fn main() {
pub enum Severity {
    Low,      // Minor issues
    Medium,   // Should be fixed
    High,     // Security/a11y risk
    Critical, // Must be fixed
}
}

A bundle is invalid if it has any Critical accessibility issues.

Example

Run the full demo:

cargo run --example web_validation_demo -p jugar-probar

See Also