Renders domhandler DOM nodes to HTML/XML strings with configurable serialization options
npx @tessl/cli install tessl/npm-dom-serializer@1.4.0dom-serializer renders domhandler DOM nodes to HTML/XML strings with configurable serialization behavior. It serves as the equivalent of the outerHTML property for parsed DOM structures, offering comprehensive support for both HTML and XML modes with proper entity encoding, foreign element handling, and various formatting options.
npm install dom-serializerimport render, { DomSerializerOptions } from "dom-serializer";For named imports:
import { render, DomSerializerOptions } from "dom-serializer";For foreign name mappings:
import { elementNames, attributeNames } from "dom-serializer/lib/foreignNames";CommonJS:
const render = require("dom-serializer").default;
// OR for named import
const { render } = require("dom-serializer");import render from "dom-serializer";
import { parseDocument } from "htmlparser2";
// Parse HTML and serialize back to string
const document = parseDocument("<div>Hello <b>world</b>!</div>");
const html = render(document);
console.log(html); // "<div>Hello <b>world</b>!</div>"
// With options for XML mode
const xmlOptions = { xmlMode: true, selfClosingTags: true };
const xml = render(document, xmlOptions);
console.log(xml); // "<div>Hello <b>world</b>!</div>"
// With specific encoding options
const encodedOptions = { encodeEntities: true };
const encoded = render(document, encodedOptions);Renders DOM nodes or arrays of DOM nodes to HTML/XML strings with comprehensive configuration options.
/**
* Renders a DOM node or an array of DOM nodes to a string.
* Can be thought of as the equivalent of the `outerHTML` of the passed node(s).
* @param node Node to be rendered
* @param options Changes serialization behavior
* @returns String representation of the DOM structure
*/
export function render(
node: AnyNode | ArrayLike<AnyNode>,
options?: DomSerializerOptions
): string;
// Also available as default export
export default render;Mixed-case SVG and MathML element and attribute name mappings for proper case correction in foreign mode.
/**
* Map of lowercase element names to their proper mixed-case versions
* Used when xmlMode is "foreign" to correct SVG/MathML element names
*/
export const elementNames: Map<string, string>;
/**
* Map of lowercase attribute names to their proper mixed-case versions
* Used when xmlMode is "foreign" to correct SVG/MathML attribute names
*/
export const attributeNames: Map<string, string>;Configuration interface for controlling DOM serialization behavior across HTML and XML modes.
interface DomSerializerOptions {
/**
* Print an empty attribute's value.
* @default xmlMode
* @example With emptyAttrs: false: `<input checked>`
* @example With emptyAttrs: true: `<input checked="">`
*/
emptyAttrs?: boolean;
/**
* Print self-closing tags for tags without contents.
* @default xmlMode
* @example With selfClosingTags: false: `<foo></foo>`
* @example With selfClosingTags: true: `<foo />`
*/
selfClosingTags?: boolean;
/**
* Treat the input as an XML document; enables the `emptyAttrs` and `selfClosingTags` options.
* If the value is `"foreign"`, it will try to correct mixed-case attribute names.
* @default false
*/
xmlMode?: boolean | "foreign";
/**
* Encode characters that are either reserved in HTML or XML.
* If `xmlMode` is `true` or the value not `'utf8'`, characters outside of the utf8 range will be encoded as well.
* @default `decodeEntities`
*/
encodeEntities?: boolean | "utf8";
/**
* Option inherited from parsing; will be used as the default value for `encodeEntities`.
* @default true
*/
decodeEntities?: boolean;
}// External types from domhandler (used in render function signature)
import type {
AnyNode,
Element,
Text,
Comment,
ProcessingInstruction,
CDATA,
Document
} from "domhandler";
// Union type representing any DOM node type
type AnyNode = Element | Text | Comment | ProcessingInstruction | CDATA | Document;
// ArrayLike interface for node collections
interface ArrayLike<T> {
readonly length: number;
readonly [n: number]: T;
}import render from "dom-serializer";
import { parseDocument } from "htmlparser2";
const html = '<div class="container"><p>Hello world</p><br></div>';
const document = parseDocument(html);
// Default HTML mode
const serialized = render(document);
console.log(serialized); // '<div class="container"><p>Hello world</p><br></div>'
// With specific HTML options
const htmlOptions = {
emptyAttrs: false,
selfClosingTags: false
};
const htmlOutput = render(document, htmlOptions);import render from "dom-serializer";
import { parseDocument } from "htmlparser2";
const xml = '<root><item attr="value" /><empty></empty></root>';
const document = parseDocument(xml, { xmlMode: true });
// XML mode with self-closing tags
const xmlOptions = {
xmlMode: true,
selfClosingTags: true,
emptyAttrs: true
};
const serialized = render(document, xmlOptions);
console.log(serialized); // '<root><item attr="value"/><empty/></root>'import render from "dom-serializer";
import { elementNames, attributeNames } from "dom-serializer/lib/foreignNames";
import { parseDocument } from "htmlparser2";
const svgHtml = '<div><svg viewbox="0 0 100 100"><radialgradient /></svg></div>';
const document = parseDocument(svgHtml);
// Foreign mode corrects mixed-case element and attribute names
const foreignOptions = { xmlMode: "foreign" };
const corrected = render(document, foreignOptions);
console.log(corrected); // '<div><svg viewBox="0 0 100 100"><radialGradient /></svg></div>'
// Access the mapping tables directly
console.log(elementNames.get('radialgradient')); // 'radialGradient'
console.log(attributeNames.get('viewbox')); // 'viewBox'import render from "dom-serializer";
import { parseDocument } from "htmlparser2";
const htmlWithEntities = '<div title="A "quoted" value">Content & more</div>';
const document = parseDocument(htmlWithEntities);
// UTF-8 encoding (minimal encoding)
const utf8Options = { encodeEntities: "utf8" };
const utf8Output = render(document, utf8Options);
// Full XML encoding
const xmlOptions = { encodeEntities: true };
const xmlOutput = render(document, xmlOptions);
// No encoding
const noEncoding = { encodeEntities: false };
const rawOutput = render(document, noEncoding);