NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #4372 most downloaded on crates.io
Streaming HTML rewriter/parser with CSS selector-based API
Last release 2 months ago
29 Jul 2026
Ships fairly regularly
a new release about every 6 weeks
Nearly every release is documented
notes for 27 of 27 stable releases
Nothing withdrawn
no release was ever pulled
7 years old
27 releases · first in 2019
Improved performance of selector matching on deeply nested elements and on stray end tags.
[HREF] silently matched[HREF=x] was rejected as a namespaced selector.:nth-of-type() counting custom elements spelled with different ASCII case as…break out of the comment and inject HTML (security fix).
MemorySettings::with_graceful_bail_out_on_memory_limit_exceeded(): when set, theMemoryLimitExceededError, so callers can continue the response bySettings::with_graceful_bail_out_on_content_handler_error(): symmetric to theRewritingError::ContentHandlerError. When set, theSettings::append_bail_out_handler() and the matching bail_out! macro,BailOut rewritable unit, and BailOutHandler / BailOutHandlerSend type aliases.RewritingError and a BailOut through which they can append final bytes to the sinkBailOut::append(content, content_type). Intended for handlers that buffer stateRewritingError #[non_exhaustive] so future error variants can be added withoutmatch on it, but must include a_ => arm.Settings, MemorySettings and RewriteStrSettings to use a consuming-builder::new() plus chained with_* settersappend_* methods for the content-handler vectors. This makes future field additions// before
Settings {
element_content_handlers: vec![element!("div", |el| { /* ... */ Ok(()) })],
strict: false,
..Settings::new()
}
// after
Settings::new()
.with_strict(false)
.append_element_content_handler(element!("div", |el| { /* ... */ Ok(()) }))integration_test to _integration_test. The leadingcargo-semver-checks and similar tools that the feature is notComment::set_text now also rejects --!>, a leading >, and a leading ->, which--> wasOne column per quarter.
Added OutputSink::set_encoding #315
OutputSink::set_encodingrewrite_str to ignore non-UTF-8 encoding declarations (it takes a UTF-8 string)selectors dependencyAdded support for nested :not() with simple selectors. #304
Replaced several panicking assertions with gracefully reported errors, especially in the C API.
Performance improvements. Updated dependencies.
Improve type generation in js-api.
Added source code locations to the C and JS APIs.
Source code locations for tags and other tokens.
Upgraded selectors and cssparser .
selectors and cssparser.Added element.onEndTag to JS bindings.
element.onEndTag to JS bindings.Updated cssparser and selectors dependencies
cargo-c for building the C API/> syntax will be removed when content is added to an HTML elementOnly allow changing the charset once with the tag, in accordance with the HTML spec.
<meta> tag, in accordance with the HTML spec.<svg> and <math>.Added the ability for the rewriter to be `Send`. The send module contains the utilities for that.
Send.
The send module contains the utilities for that.Remove unmaintained safemem dependency.
safemem dependency.Expose is_self_closing and can_have_content in C api.
is_self_closing and can_have_content in C api.ElementContentHandlers and DocumentContentHandlers fields public.Ensure that TagScanner::is_in_end_tag resets when changing parsers.
TagScanner::is_in_end_tag resets when changing parsers.Added ability to get the tag and attribute names with the original casing.
The C API's new lol_html_element_add_end_tag_handler() function now sets the last error retrievable by lol_html_take_last_error() if it is called on a
lol_html_element_add_end_tag_handler() function now sets the last error retrievable by lol_html_take_last_error() if it is called on an element that can have no end tag.Yes, you got that right: this is the first 1.x release! From now on you should expect this project to adhere to the semantic versioning spec (we have
Yes, you got that right: this is the first 1.x release! From now on you should expect this project to adhere to the semantic versioning spec (we have been somewhat relaxed about that in the past).
Element::end_tag_handlers() which allows better control over the end tag handlers.Element::on_end_tag() and Element::add_on_end_tag() in favor of the newly added
Element::end_tag_handlers().Modified method Element::on_end_tag() to support multiple handlers. This is a breaking change since the old semantics of the method was to overwrite a…
TextChunk::as_mut_str() and TextChunk::set_str() for in-place modifications to the text in a
TextChunk. (#175)Element::on_end_tag() to support multiple handlers. This is a breaking change since the old
semantics of the method was to overwrite any previously set handler. (#177)Support dynamic charset change on meta tags in HtmlRewriter.
Element::can_have_content(). (#163)Add Element::start_tag() and Element::is_self_closing().
Doctype::remove. (#129)Element::start_tag() and Element::is_self_closing(). (#148)StartTag and EndTag. (#148)Eq for all types that implement PartialEq. (#146)Add Element::on_end_tag (#97, #107, #124)
Element::on_end_tag (#97, #107, #124)lol_html_str_t, not lol_html_str_t*. This was necessary to fix a memory leak in lol_html_str_free. (#115)Add unofficial Go bindings to the README
self in HtmlRewriter::end (#68)HTMLRewriter::new infallible (#70)element! in a separate expression from rewrite_str (#69)Added: DocumentContentHandlers::end.
DocumentContentHandlers::end.- Initial release
Your coding agent can read these notes before it upgrades. Set up the MCP server →