Strict HTML validation in Rust: How to detect unclosed tags and unresolved placeholders?

Overview

I'm working on a Rust project that involves validating HTML content—both full documents and fragments. My requirements go beyond lenient parsing:

  • :white_check_mark: Detect and flag unclosed or extra HTML tags
  • :white_check_mark: Identify unresolved template placeholders such as {{field}}, {{ user.name }}, or malformed ones like {{{bad}}}, {{ incomplete
  • :cross_mark: Avoid relying on parsers that silently fix malformed HTML (like html5ever)

Problem

Crates like html5ever and markup5ever_rcdom follow the forgiving HTML5 spec and parse even broken HTML successfully. This makes it impossible to detect structural issues at runtime.

For example, this invalid HTML:

<div class="row template-row">
  <div class="col-auto">
    <a> <!-- ❌ Unclosed <a> tag -->
  </div>
</div>

The above is invalid HTML, yet parsers like html5ever auto-close the <a> tag, and the document is considered "valid" at the parsing level.

This becomes a problem in scenarios like Angular templates, where unclosed tags can cause runtime or build-time errors. Structural correctness matters more than "valid per HTML5 spec."

:white_check_mark: What I'm Looking For

I'm searching for a Rust-based approach that supports the following validation features:

  1. Structural Validation
  • Detect unclosed, mismatched, or stray tags
  • Ex: <div><a></div> or <div><span> should throw an error
  1. Placeholder Detection
  • Find unresolved or malformed template variables like {{field}}, {{, {{{bad}}}
  1. Fail-Fast Parsing
  • Prefer errors over silent recovery
  • Option to opt out of "forgiving mode" if using an HTML5 parser

Questions

  • Is there any existing Rust crate that performs strict HTML validation (not just parsing)?
  • Can we configure html5ever to operate in a strict mode or report unclosed tags?
  • Is writing a custom tag-matching validator (like a stack-based parser) the only way?
  • Would wrapping an external tool like tidy from Rust be the most pragmatic solution?
  • Are there template-aware linting crates for formats like Angular, Handlebars, etc. in Rust?

Just adding some searches I carried out.

  • html5ever won't do strict mode.
    • This also replies your "Can we configure html5ever to operate in a strict mode or report unclosed tags?" The answer is no for first part, and maybe for the latter, but I haven't tested. (check below.)
  • Related post in this forum, also no real answer for your use case.

Even in other languages it seems hard. Although html5ever should report errors, but I'm unsure what it consists of:

exact_errors: bool
Report all parse errors described in the spec, at some performance penalty? Default: false

The only idea I had, which may not be useful, is to run the NU validator.

This is the main page with your code,.

Apparently someone wrote a wrapper in Rust, but it's been unmaintained for quite a long time.