import { TAG_NAMES as $, NS, hasUnescapedText } from '../common/html.js'; import { escapeText, escapeAttribute } from 'entities/lib/escape.js'; import { defaultTreeAdapter } from '../tree-adapters/default.js'; // Sets const VOID_ELEMENTS = new Set([ $.AREA, $.BASE, $.BASEFONT, $.BGSOUND, $.BR, $.COL, $.EMBED, $.FRAME, $.HR, $.IMG, $.INPUT, $.KEYGEN, $.LINK, $.META, $.PARAM, $.SOURCE, $.TRACK, $.WBR, ]); function isVoidElement(node, options) { return (options.treeAdapter.isElementNode(node) && options.treeAdapter.getNamespaceURI(node) === NS.HTML && VOID_ELEMENTS.has(options.treeAdapter.getTagName(node))); } const defaultOpts = { treeAdapter: defaultTreeAdapter, scriptingEnabled: true }; /** * Serializes an AST node to an HTML string. * * @example * * ```js * const parse5 = require('parse5'); * * const document = parse5.parse('Hi there!'); * * // Serializes a document. * const html = parse5.serialize(document); * * // Serializes the element content. * const str = parse5.serialize(document.childNodes[1]); * * console.log(str); //> 'Hi there!' * ``` * * @param node Node to serialize. * @param options Serialization options. */ export function serialize(node, options) { const opts = { ...defaultOpts, ...options }; if (isVoidElement(node, opts)) { return ''; } return serializeChildNodes(node, opts); } /** * Serializes an AST element node to an HTML string, including the element node. * * @example * * ```js * const parse5 = require('parse5'); * * const document = parse5.parseFragment('
Hello, world!
'); * * // Serializes the
element. * const html = parse5.serializeOuter(document.childNodes[0]); * * console.log(str); //> '
Hello, world!
' * ``` * * @param node Node to serialize. * @param options Serialization options. */ export function serializeOuter(node, options) { const opts = { ...defaultOpts, ...options }; return serializeNode(node, opts); } function serializeChildNodes(parentNode, options) { let html = ''; // Get container of the child nodes const container = options.treeAdapter.isElementNode(parentNode) && options.treeAdapter.getTagName(parentNode) === $.TEMPLATE && options.treeAdapter.getNamespaceURI(parentNode) === NS.HTML ? options.treeAdapter.getTemplateContent(parentNode) : parentNode; const childNodes = options.treeAdapter.getChildNodes(container); if (childNodes) { for (const currentNode of childNodes) { html += serializeNode(currentNode, options); } } return html; } function serializeNode(node, options) { if (options.treeAdapter.isElementNode(node)) { return serializeElement(node, options); } if (options.treeAdapter.isTextNode(node)) { return serializeTextNode(node, options); } if (options.treeAdapter.isCommentNode(node)) { return serializeCommentNode(node, options); } if (options.treeAdapter.isDocumentTypeNode(node)) { return serializeDocumentTypeNode(node, options); } // Return an empty string for unknown nodes return ''; } function serializeElement(node, options) { const tn = options.treeAdapter.getTagName(node); return `<${tn}${serializeAttributes(node, options)}>${isVoidElement(node, options) ? '' : `${serializeChildNodes(node, options)}`}`; } function serializeAttributes(node, { treeAdapter }) { let html = ''; for (const attr of treeAdapter.getAttrList(node)) { html += ' '; if (!attr.namespace) { html += attr.name; } else switch (attr.namespace) { case NS.XML: { html += `xml:${attr.name}`; break; } case NS.XMLNS: { if (attr.name !== 'xmlns') { html += 'xmlns:'; } html += attr.name; break; } case NS.XLINK: { html += `xlink:${attr.name}`; break; } default: { html += `${attr.prefix}:${attr.name}`; } } html += `="${escapeAttribute(attr.value)}"`; } return html; } function serializeTextNode(node, options) { const { treeAdapter } = options; const content = treeAdapter.getTextNodeContent(node); const parent = treeAdapter.getParentNode(node); const parentTn = parent && treeAdapter.isElementNode(parent) && treeAdapter.getTagName(parent); return parentTn && treeAdapter.getNamespaceURI(parent) === NS.HTML && hasUnescapedText(parentTn, options.scriptingEnabled) ? content : escapeText(content); } function serializeCommentNode(node, { treeAdapter }) { return ``; } function serializeDocumentTypeNode(node, { treeAdapter }) { return ``; } //# sourceMappingURL=index.js.map