Skip to content

Commit

Permalink
feat(lib): throw error if browser does not support parsing methods
Browse files Browse the repository at this point in the history
  • Loading branch information
remarkablemark committed Nov 6, 2019
1 parent 3f3e514 commit de327af
Showing 1 changed file with 43 additions and 48 deletions.
91 changes: 43 additions & 48 deletions lib/domparser.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,24 @@ var VOID_ELEMENTS_REGEX = /<(area|base|br|col|embed|hr|img|input|keygen|link|men
var isIE9 = utilities.isIE(9);
var isIE = isIE9 || utilities.isIE();

// falls back to `parseFromString` if `createHTMLDocument` cannot be used
var parseFromDocument = function() {
throw new Error(
'This browser does not support `document.implementation.createHTMLDocument`'
);
};

var parseFromString = function() {
throw new Error(
'This browser does not support `DOMParser.prototype.parseFromString`'
);
};

/**
* DOMParser (performance: slow).
*
* @see https://developer.mozilla.org/docs/Web/API/DOMParser#Parsing_an_SVG_or_HTML_document
*/
var parseFromString;

if (typeof window.DOMParser === 'function') {
var domParser = new window.DOMParser();

Expand All @@ -35,7 +46,7 @@ if (typeof window.DOMParser === 'function') {
* @param {string} [tagName] - The element to render the HTML (with 'body' as fallback).
* @return {HTMLDocument}
*/
parseFromString = function domStringParser(html, tagName) {
parseFromString = function(html, tagName) {
if (tagName) {
html = '<' + tagName + '>' + html + '</' + tagName + '>';
}
Expand All @@ -47,20 +58,20 @@ if (typeof window.DOMParser === 'function') {

return domParser.parseFromString(html, mimeType);
};

parseFromDocument = parseFromString;
}

/**
* DOMImplementation (performance: fair).
*
* @see https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument
*/
var parseFromDocument;

if (typeof document.implementation === 'object') {
if (document.implementation) {
// title parameter is required in IE
// https://msdn.microsoft.com/en-us/library/ff975457(v=vs.85).aspx
var doc = document.implementation.createHTMLDocument(
isIE ? 'HTML_DOM_PARSER_TITLE' : undefined
isIE ? 'html-dom-parser' : undefined
);

/**
Expand All @@ -70,7 +81,7 @@ if (typeof document.implementation === 'object') {
* @param {string} [tagName] - The element to render the HTML (with 'body' as fallback).
* @return {HTMLDocument}
*/
parseFromDocument = function createHTMLDocument(html, tagName) {
parseFromDocument = function(html, tagName) {
if (tagName) {
doc.documentElement.getElementsByTagName(tagName)[0].innerHTML = html;
return doc;
Expand All @@ -93,8 +104,8 @@ if (typeof document.implementation === 'object') {
*
* @see https://developer.mozilla.org/docs/Web/HTML/Element/template
*/
var parseFromTemplate;
var template = document.createElement('template');
var parseFromTemplate;

if (template.content) {
/**
Expand All @@ -103,15 +114,12 @@ if (template.content) {
* @param {string} html - The HTML string.
* @return {NodeList}
*/
parseFromTemplate = function templateParser(html) {
parseFromTemplate = function(html) {
template.innerHTML = html;
return template.content.childNodes;
};
}

// fallback document parser
var parseWithFallback = parseFromDocument || parseFromString;

/**
* Parses HTML string to DOM nodes.
*
Expand All @@ -132,58 +140,45 @@ function domparser(html) {

switch (firstTagName) {
case HTML:
if (parseFromString) {
doc = parseFromString(html);

// the created document may come with filler head/body elements,
// so make sure to remove them if they don't actually exist
if (!HEAD_TAG_REGEX.test(html)) {
element = doc.getElementsByTagName(HEAD)[0];
if (element) {
element.parentNode.removeChild(element);
}
doc = parseFromString(html);

// the created document may come with filler head/body elements,
// so make sure to remove them if they don't actually exist
if (!HEAD_TAG_REGEX.test(html)) {
element = doc.getElementsByTagName(HEAD)[0];
if (element) {
element.parentNode.removeChild(element);
}
}

if (!BODY_TAG_REGEX.test(html)) {
element = doc.getElementsByTagName(BODY)[0];
if (element) {
element.parentNode.removeChild(element);
}
if (!BODY_TAG_REGEX.test(html)) {
element = doc.getElementsByTagName(BODY)[0];
if (element) {
element.parentNode.removeChild(element);
}

return doc.getElementsByTagName(HTML);
}
break;

return doc.getElementsByTagName(HTML);

case HEAD:
case BODY:
if (parseWithFallback) {
elements = parseWithFallback(html).getElementsByTagName(firstTagName);
elements = parseFromDocument(html).getElementsByTagName(firstTagName);

// account for possibility of sibling
if (BODY_TAG_REGEX.test(html) && HEAD_TAG_REGEX.test(html)) {
return elements[0].parentNode.childNodes;
}

return elements;
// if there's a sibling element, then return both elements
if (BODY_TAG_REGEX.test(html) && HEAD_TAG_REGEX.test(html)) {
return elements[0].parentNode.childNodes;
}
break;
return elements;

// low-level tag or text
default:
if (parseFromTemplate) {
return parseFromTemplate(html);
}

if (parseWithFallback) {
return parseWithFallback(html, BODY).getElementsByTagName(BODY)[0]
.childNodes;
}

break;
return parseFromDocument(html, BODY).getElementsByTagName(BODY)[0]
.childNodes;
}

return [];
}

module.exports = domparser;

0 comments on commit de327af

Please sign in to comment.