NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #4593 most downloaded on npm
A 1.75kB library for enhancing `html`. `ultrahtml` has zero dependencies and is compatible with any JavaScript runtime.
Last release 2 months ago
09 Jul 2026
Ships unpredictably
gaps range from 8 days to 1.3 years
Nearly every release is documented
notes for 30 of 31 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
36 releases · first in 2022
One column per quarter.
4694b57: Updates the build target from Node 16 to Node 22. Published code now uses modern syntax like optional chaining (?.) directly instead of downl
?.) directly instead of downleveled equivalents, resulting in slightly smaller output. Node 22 or later is now the supported runtime baseline.124e573: Adds a new transformSync function, a synchronous alternative to the transform function. This can be used when there are no async transformer
124e573: Adds a new transformSync function, a synchronous alternative to the transform function. This can be used when there are no async transformer functions.
import { transformSync, html } from "ultrahtml";
import swap from "ultrahtml/transformers/swap";
const output = transformSync(`<h1>Hello world!</h1>`, [
swap({
h1: "h2",
}),
]);
console.log(output); // <h2>Hello world!</h2>
f0a1da3: Adds a new unblockElements option to the sanitize transformer. This option makes it easier to remove all or most HTML from a string without dropping child content.
f0a1da3: Fixes sanitization of nested elements.
For example, the following code:
const output = await transform("<h1>Hello <strong>world!</strong></h1>", [
sanitize({ blockElements: ["h1", "strong"] }),
]);
produced the following output before this fix:
Hello <strong>world!</strong>
and now correctly produces:
Hello world!
e8aee16: Improve parser performance for attributes
8388fe7: Updates internal dependency on esbuild
ebc97e0: upgrades dts-bundle-generator to 9.2.1, fixing an issue with .d.ts generation which led methods prefixed with two underscores to be incorrect
dts-bundle-generator to 9.2.1, fixing an issue with .d.ts
generation which led methods prefixed with two underscores to be
incorrectly made private in the generated declaration file.244be0a: Update parsel-js to latest
parsel-js to latesta989b5a: Bundle type definitions in .d.ts files
.d.ts files7c93190: Add support for static media queries to ultrahtml/transformers/inline.
7c93190: Add support for static media queries to ultrahtml/transformers/inline.
You may now pass an env value to the transformer, for example:
import { transform } from "ultrahtml";
import inline from "ultrahtml/transformers/inline";
const output = await transform(input, [
// Acts as if the screen is 960px wide and 1280px tall
inline({ env: { width: 960, height: 1280 } }),
]);
8bbaeef: Allow elements inside of to be self-closing for compactness
<svg> to be self-closing for compactnesssanitize transformer behavior when only using allowElements### Minor Changes - 0556b19: Add renderSync export ### Patch Changes - 3362aa2: Add main entrypoint
renderSync exportmain entrypoint7792f5d: Add useObjectSyntax option to inline transformer. Note that this option is currently not compatible with transform
useObjectSyntax option to inline transformer. Note that this option is currently not compatible with transformd910619: Remove resolveAsset option from inline transformer, making it synchronous again.
resolveAsset option from inline transformer, making it synchronous again.c5799aa: Update attribute handling to account for attributes with newlines
d7cb17d: Fix another edge case with text inside script/styles
c7a1ef6: Fix edge case with parsing
<script> parsingb136e51: Fix unhandled edge case with sanitize transformer
sanitize transformer95c0f73: ultrahtml is a complete markup toolkit with a tiny footprint. Parse, transform, and render HTML on the server, in the browser, with or withou
95c0f73: ultrahtml is a complete markup toolkit with a tiny footprint. Parse, transform, and render HTML on the server, in the browser, with or without a build step.
The signature of transform has been updated. Rather than applying sanitization and component swapping by default, these have been split out to individual ultrahtml/transformers that can be applied modularly.
In ultrahtml@0.x, transform accepted an options object with sanitize and components. Other transformations would need to be applied outside of this flow.
import { transform } from "ultrahtml";
await transform(markup, {
components: { h1: "h2" },
sanitize: { allowElements: ["h1", "h2", "h3"] },
});
In ultrahtml@1.x, transform accepts an array of transformers to apply. The sanitize and components options can be handled with the built-in transformers named sanitize and swap.
import { transform } from "ultrahtml";
import swap from "ultrahtml/transformers/swap";
import sanitize from "ultrahtml/transformers/sanitize";
await transform(markup, [
swap({ h1: "h2" }),
sanitize({ allowElements: ["h1", "h2", "h3"] }),
]);
ultrahtml now comes with h and Fragment functions for JSX, as well as a jsx-runtime export.
Transformers are AST transformations that can be applied to any ultrahtml Node. Usually these are applied to entire documents.
New inline transformer inlines CSS from <style> blocks directly to matching elements.
New scope transformer scopes CSS from <style> blocks to the elements in a given document or component.
resolveAsset option to the inline transformerd29a0e2: Add resolveAsset option to the inline transformer
resolveAsset option to the inline transformer4699020: Update JSX runtime child handling
### Patch Changes - 401b13a: Fix JSX runtime types
da119c1: Fix transformer definitions
95c0f73: ultrahtml is a complete markup toolkit with a tiny footprint. Parse, transform, and render HTML on the server, in the browser, with or withou
95c0f73: ultrahtml is a complete markup toolkit with a tiny footprint. Parse, transform, and render HTML on the server, in the browser, with or without a build step.
The signature of transform has been updated. Rather than applying sanitization and component swapping by default, these have been split out to individual ultrahtml/transformers that can be applied modularly.
In ultrahtml@0.x, transform accepted an options object with sanitize and components. Other transformations would need to be applied outside of this flow.
import { transform } from "ultrahtml";
await transform(markup, {
components: { h1: "h2" },
sanitize: { allowElements: ["h1", "h2", "h3"] },
});
In ultrahtml@1.x, transform accepts an array of transformers to apply. The sanitize and components options can be handled with the built-in transformers named sanitize and swap.
import { transform } from "ultrahtml";
import swap from "ultrahtml/transformers/swap";
import sanitize from "ultrahtml/transformers/sanitize";
await transform(markup, [
swap({ h1: "h2" }),
sanitize({ allowElements: ["h1", "h2", "h3"] }),
]);
ultrahtml now comes with h and Fragment functions for JSX, as well as a jsx-runtime export.
Transformers are AST transformations that can be applied to any ultrahtml Node. Usually these are applied to entire documents.
New inline transformer inlines CSS from <style> blocks directly to matching elements.
New scope transformer scopes CSS from <style> blocks to the elements in a given document or component.
83c2e35: Improve declarations for node types
3b8fb6e: Remove bundledDependencies field
74010dd: Bundle parsel-js to avoid ESM/CJS issues
### Patch Changes - a105c5e: Fix CJS compat issue
2de70f3: Add ultrahtml/selector module which exports querySelector, querySelectorAll, and matches functions.
2de70f3: Add ultrahtml/selector module which exports querySelector, querySelectorAll, and matches functions.
To use querySelectorAll, pass the root Node as the first argument and any valid CSS selector as the second argument. Note that if a CSS selector you need is not yet implemented, you are invited to open an issue.
import { parse } from "ultrahtml";
import { querySelectorAll, matches } from "ultrahtml/selector";
const doc = parse(`
<html>
<head>
<title>Demo</title>
/head>
<body>
<h1>Hello world!</h1>
</body>
</html>
`);
const h1 = querySelector(doc, "h1");
const match = matches(h1, "h1");
### Patch Changes - 037711f: Update types
### Minor Changes - 97b297f: Add walkSync export
walkSync export123f7ea: Fix custom elements transform.
### Patch Changes - 758bbba: Improve documentation
### Patch Changes - 2f92e93: Export node types
517e24d: Fix edge cases with text node detection, refactor for compactness
23771a3: Fix walk function definition
walk function definition4d082b3: Ensure types are included
e0e8a2b: Add __unsafeHTML export
__unsafeHTML exportf6e3a71: Support async components
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →