File: /var/www/zaklada/html/node_modules/jsdom/lib/jsdom/browser/htmltodom.js
var parse5 = require('parse5');
var htmlparser2 = require('htmlparser2');
var attributes = require('../living/attributes');
var createDocumentTypeInternal = require('../living/document-type').create;
const locationInfo = require("../living/helpers/internal-constants").locationInfo;
function HtmlToDom(core, parser, parsingMode) {
if (!parser) {
if (parsingMode === "xml") {
parser = htmlparser2;
} else {
parser = parse5;
}
}
if (parser.DefaultHandler || (parser.Parser && parser.TreeAdapters)) {
// Forgiving HTML parser
if (parser.DefaultHandler){
// fb55/htmlparser2
parser.ParseHtml = function(rawHtml) {
var handler = new parser.DefaultHandler();
// Check if document is XML
var isXML = parsingMode === "xml";
var parserInstance = new parser.Parser(handler, {
xmlMode: isXML,
lowerCaseTags: !isXML,
lowerCaseAttributeNames: !isXML,
decodeEntities: true
});
parserInstance.includeLocation = false;
parserInstance.parseComplete(rawHtml);
return handler.dom;
};
} else if (parser.Parser && parser.TreeAdapters) {
parser.ParseHtml = function (rawHtml) {
if (parsingMode === 'xml') {
throw new Error('Can\'t parse XML with parse5, please use htmlparser2 instead.');
}
var instance = new parser.Parser(parser.TreeAdapters.htmlparser2, { locationInfo: true });
var dom = instance.parse(rawHtml);
return dom.children;
};
}
this.appendHtmlToElement = function(html, element) {
if (typeof html !== 'string') {
html +='';
}
var parsed = parser.ParseHtml(html);
for (var i = 0; i < parsed.length; i++) {
setChild(core, element, parsed[i]);
}
return element;
};
this.appendHtmlToDocument = this.appendHtmlToElement;
if (parser.Parser && parser.TreeAdapters) {
this.appendHtmlToElement = function (html, element) {
if (typeof html !== 'string') {
html += '';
}
var instance = new parser.Parser(parser.TreeAdapters.htmlparser2);
var parentElement = parser.TreeAdapters.htmlparser2.createElement(element.tagName.toLowerCase(), element.namespaceURI, []);
var dom = instance.parseFragment(html, parentElement);
var parsed = dom.children;
for (var i = 0; i < parsed.length; i++) {
setChild(core, element, parsed[i]);
}
return element;
};
}
} else if (parser.moduleName == 'HTML5') { /* HTML5 parser */
this.appendHtmlToElement = function(html, element) {
if (typeof html !== 'string') {
html += '';
}
if (html.length > 0) {
if (element.nodeType == 9) {
new parser.Parser({document: element}).parse(html);
}
else {
var p = new parser.Parser({document: element.ownerDocument});
p.parse_fragment(html, element);
}
}
};
} else {
this.appendHtmlToElement = function () {
console.log('');
console.log('###########################################################');
console.log('# WARNING: No compatible HTML parser was given.');
console.log('# Element.innerHTML setter support has been disabled');
console.log('# Element.innerHTML getter support will still function');
console.log('###########################################################');
console.log('');
};
}
};
// utility function for forgiving parser
function setChild(core, parent, node) {
var c, newNode, currentDocument = parent._ownerDocument || parent;
switch (node.type)
{
case 'tag':
case 'script':
case 'style':
newNode = currentDocument._createElementWithCorrectElementInterface(node.name, node.namespace);
newNode._namespaceURI = node.namespace || "http://www.w3.org/1999/xhtml";
break;
case 'root':
// If we are in <template> then implicitly create #document-fragment for its content
if(parent.tagName === 'TEMPLATE' && parent._namespaceURI === 'http://www.w3.org/1999/xhtml') {
newNode = currentDocument.createDocumentFragment();
// Mark fragment as parser-created template content, so it will be accepted by appendChild()
newNode._templateContent = true;
}
break;
case 'text':
// HTML entities should already be decoded by the parser, so no need to decode them
newNode = currentDocument.createTextNode(node.data);
break;
case 'comment':
newNode = currentDocument.createComment(node.data);
break;
case 'directive':
if (node.name[0] === '?' && node.name.toLowerCase() !== '?xml') {
var data = node.data.slice(node.name.length + 1, -1);
newNode = currentDocument.createProcessingInstruction(node.name.substring(1), data);
} else if (node.name.toLowerCase() === '!doctype') {
if (node['x-name'] !== undefined) { // parse5 supports doctypes directly
newNode = createDocumentTypeInternal(core, currentDocument,
node['x-name'] || '',
node['x-publicId'] || '',
node['x-systemId'] || '');
} else {
newNode = parseDocType(core, currentDocument, '<' + node.data + '>');
}
}
break;
default:
return null;
break;
}
if (!newNode)
return null;
newNode[locationInfo] = node.__location;
newNode._localName = node.name;
if (node.attribs) {
for (var localName in node.attribs) {
var value = node.attribs[localName];
var prefix = node['x-attribsPrefix'] && node['x-attribsPrefix'][localName];
var name = prefix ? (prefix + ':' + localName) : localName;
var namespace = node['x-attribsNamespace'] && node['x-attribsNamespace'][localName] || null;
attributes.setAttributeValue(newNode, localName, value, name, prefix, namespace);
}
}
if (node.children) {
for (c = 0; c < node.children.length; c++) {
setChild(core, newNode, node.children[c]);
}
}
return parent.appendChild(newNode);
}
var HTML5_DOCTYPE = /<!doctype html>/i;
var PUBLIC_DOCTYPE = /<!doctype\s+([^\s]+)\s+public\s+"([^"]+)"\s+"([^"]+)"/i;
var SYSTEM_DOCTYPE = /<!doctype\s+([^\s]+)\s+system\s+"([^"]+)"/i;
function parseDocType(core, doc, html) {
if (HTML5_DOCTYPE.test(html)) {
return createDocumentTypeInternal(core, doc, "html", "", "");
}
var publicPieces = PUBLIC_DOCTYPE.exec(html);
if (publicPieces) {
return createDocumentTypeInternal(core, doc, publicPieces[1], publicPieces[2], publicPieces[3]);
}
var systemPieces = SYSTEM_DOCTYPE.exec(html);
if (systemPieces) {
return createDocumentTypeInternal(core, doc, systemPieces[1], systemPieces[2], "");
}
// Shouldn't get here (the parser shouldn't let us know about invalid doctypes), but our logic likely isn't
// real-world perfect, so let's fallback.
return createDocumentTypeInternal(core, doc, "html", "", "");
}
exports.HtmlToDom = HtmlToDom;