You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
173 lines
5.8 KiB
173 lines
5.8 KiB
"use strict"; |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
exports.serializeOuter = exports.serialize = void 0; |
|
const html_js_1 = require("../common/html.js"); |
|
const escape_js_1 = require("entities/lib/escape.js"); |
|
const default_js_1 = require("../tree-adapters/default.js"); |
|
// Sets |
|
const VOID_ELEMENTS = new Set([ |
|
html_js_1.TAG_NAMES.AREA, |
|
html_js_1.TAG_NAMES.BASE, |
|
html_js_1.TAG_NAMES.BASEFONT, |
|
html_js_1.TAG_NAMES.BGSOUND, |
|
html_js_1.TAG_NAMES.BR, |
|
html_js_1.TAG_NAMES.COL, |
|
html_js_1.TAG_NAMES.EMBED, |
|
html_js_1.TAG_NAMES.FRAME, |
|
html_js_1.TAG_NAMES.HR, |
|
html_js_1.TAG_NAMES.IMG, |
|
html_js_1.TAG_NAMES.INPUT, |
|
html_js_1.TAG_NAMES.KEYGEN, |
|
html_js_1.TAG_NAMES.LINK, |
|
html_js_1.TAG_NAMES.META, |
|
html_js_1.TAG_NAMES.PARAM, |
|
html_js_1.TAG_NAMES.SOURCE, |
|
html_js_1.TAG_NAMES.TRACK, |
|
html_js_1.TAG_NAMES.WBR, |
|
]); |
|
function isVoidElement(node, options) { |
|
return (options.treeAdapter.isElementNode(node) && |
|
options.treeAdapter.getNamespaceURI(node) === html_js_1.NS.HTML && |
|
VOID_ELEMENTS.has(options.treeAdapter.getTagName(node))); |
|
} |
|
const defaultOpts = { treeAdapter: default_js_1.defaultTreeAdapter, scriptingEnabled: true }; |
|
/** |
|
* Serializes an AST node to an HTML string. |
|
* |
|
* @example |
|
* |
|
* ```js |
|
* const parse5 = require('parse5'); |
|
* |
|
* const document = parse5.parse('<!DOCTYPE html><html><head></head><body>Hi there!</body></html>'); |
|
* |
|
* // Serializes a document. |
|
* const html = parse5.serialize(document); |
|
* |
|
* // Serializes the <html> element content. |
|
* const str = parse5.serialize(document.childNodes[1]); |
|
* |
|
* console.log(str); //> '<head></head><body>Hi there!</body>' |
|
* ``` |
|
* |
|
* @param node Node to serialize. |
|
* @param options Serialization options. |
|
*/ |
|
function serialize(node, options) { |
|
const opts = Object.assign(Object.assign({}, defaultOpts), options); |
|
if (isVoidElement(node, opts)) { |
|
return ''; |
|
} |
|
return serializeChildNodes(node, opts); |
|
} |
|
exports.serialize = serialize; |
|
/** |
|
* Serializes an AST element node to an HTML string, including the element node. |
|
* |
|
* @example |
|
* |
|
* ```js |
|
* const parse5 = require('parse5'); |
|
* |
|
* const document = parse5.parseFragment('<div>Hello, <b>world</b>!</div>'); |
|
* |
|
* // Serializes the <div> element. |
|
* const html = parse5.serializeOuter(document.childNodes[0]); |
|
* |
|
* console.log(str); //> '<div>Hello, <b>world</b>!</div>' |
|
* ``` |
|
* |
|
* @param node Node to serialize. |
|
* @param options Serialization options. |
|
*/ |
|
function serializeOuter(node, options) { |
|
const opts = Object.assign(Object.assign({}, defaultOpts), options); |
|
return serializeNode(node, opts); |
|
} |
|
exports.serializeOuter = serializeOuter; |
|
function serializeChildNodes(parentNode, options) { |
|
let html = ''; |
|
// Get container of the child nodes |
|
const container = options.treeAdapter.isElementNode(parentNode) && |
|
options.treeAdapter.getTagName(parentNode) === html_js_1.TAG_NAMES.TEMPLATE && |
|
options.treeAdapter.getNamespaceURI(parentNode) === html_js_1.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)}</${tn}>`}`; |
|
} |
|
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 html_js_1.NS.XML: { |
|
html += `xml:${attr.name}`; |
|
break; |
|
} |
|
case html_js_1.NS.XMLNS: { |
|
if (attr.name !== 'xmlns') { |
|
html += 'xmlns:'; |
|
} |
|
html += attr.name; |
|
break; |
|
} |
|
case html_js_1.NS.XLINK: { |
|
html += `xlink:${attr.name}`; |
|
break; |
|
} |
|
default: { |
|
html += `${attr.prefix}:${attr.name}`; |
|
} |
|
} |
|
html += `="${(0, escape_js_1.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) === html_js_1.NS.HTML && |
|
(0, html_js_1.hasUnescapedText)(parentTn, options.scriptingEnabled) |
|
? content |
|
: (0, escape_js_1.escapeText)(content); |
|
} |
|
function serializeCommentNode(node, { treeAdapter }) { |
|
return `<!--${treeAdapter.getCommentNodeContent(node)}-->`; |
|
} |
|
function serializeDocumentTypeNode(node, { treeAdapter }) { |
|
return `<!DOCTYPE ${treeAdapter.getDocumentTypeNodeName(node)}>`; |
|
} |
|
//# sourceMappingURL=index.js.map
|