html-dom-parser
Advanced tools
+36
-1
@@ -1,5 +0,40 @@ | ||
| # Change Log | ||
| # Changelog | ||
| All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. | ||
| ### [0.2.3](https://github.com/remarkablemark/html-dom-parser/compare/v0.2.2...v0.2.3) (2019-11-04) | ||
| ### Bug Fixes | ||
| * **lib:** improve head and body regex in `domparser.js` ([457bb58](https://github.com/remarkablemark/html-dom-parser/commit/457bb58)), closes [#18](https://github.com/remarkablemark/html-dom-parser/issues/18) | ||
| ### Build System | ||
| * **package:** save commitlint, husky, and lint-staged to devDeps ([3b0ce91](https://github.com/remarkablemark/html-dom-parser/commit/3b0ce91)) | ||
| * **package:** update `eslint` and install `prettier` and plugin ([b7a6b81](https://github.com/remarkablemark/html-dom-parser/commit/b7a6b81)) | ||
| * **package:** update `webpack` and save `webpack-cli` ([908e56d](https://github.com/remarkablemark/html-dom-parser/commit/908e56d)) | ||
| * **package:** update dependencies and devDependencies ([a9016be](https://github.com/remarkablemark/html-dom-parser/commit/a9016be)) | ||
| ### Tests | ||
| * **server:** remove skipped test ([a4c1057](https://github.com/remarkablemark/html-dom-parser/commit/a4c1057)) | ||
| * refactor tests to ES6 ([d5255a5](https://github.com/remarkablemark/html-dom-parser/commit/d5255a5)) | ||
| * **cases:** add empty string test case to `html.js` ([25d7e8a](https://github.com/remarkablemark/html-dom-parser/commit/25d7e8a)) | ||
| * **cases:** add more special test cases to `html.js` ([6fdf2ea](https://github.com/remarkablemark/html-dom-parser/commit/6fdf2ea)) | ||
| * **cases:** refactor test cases and move html data to its own file ([e4fcb09](https://github.com/remarkablemark/html-dom-parser/commit/e4fcb09)) | ||
| * **cases:** remove unnecessary try/catch wrapper to fix lint error ([ca8175e](https://github.com/remarkablemark/html-dom-parser/commit/ca8175e)) | ||
| * **cases:** skip html test cases that PhantomJS does not support ([d095d29](https://github.com/remarkablemark/html-dom-parser/commit/d095d29)) | ||
| * **cases:** update `complex.html` ([1418775](https://github.com/remarkablemark/html-dom-parser/commit/1418775)) | ||
| * **client:** add tests for client parser that will be run by karma ([a0c58aa](https://github.com/remarkablemark/html-dom-parser/commit/a0c58aa)) | ||
| * **helpers:** create `index.js` which exports helpers ([a9255d5](https://github.com/remarkablemark/html-dom-parser/commit/a9255d5)) | ||
| * **helpers:** move helper that tests for errors to separate file ([f2e6312](https://github.com/remarkablemark/html-dom-parser/commit/f2e6312)) | ||
| * **helpers:** refactor and move `runTests` to its own file ([8e30784](https://github.com/remarkablemark/html-dom-parser/commit/8e30784)) | ||
| * **server:** add tests that spy and mock htmlparser2 and domhandler ([61075a1](https://github.com/remarkablemark/html-dom-parser/commit/61075a1)) | ||
| * **server:** move `html-to-dom-server.js` to `server` directory ([3684dac](https://github.com/remarkablemark/html-dom-parser/commit/3684dac)) | ||
| ## [0.2.2](https://github.com/remarkablemark/html-dom-parser/compare/v0.2.1...v0.2.2) (2019-06-07) | ||
@@ -6,0 +41,0 @@ |
+59
-464
@@ -10,3 +10,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
| root["HTMLDOMParser"] = factory(); | ||
| })(this, function() { | ||
| })(window, function() { | ||
| return /******/ (function(modules) { // webpackBootstrap | ||
@@ -47,16 +47,33 @@ /******/ // The module cache | ||
| /******/ | ||
| /******/ // identity function for calling harmony imports with the correct context | ||
| /******/ __webpack_require__.i = function(value) { return value; }; | ||
| /******/ | ||
| /******/ // define getter function for harmony exports | ||
| /******/ __webpack_require__.d = function(exports, name, getter) { | ||
| /******/ if(!__webpack_require__.o(exports, name)) { | ||
| /******/ Object.defineProperty(exports, name, { | ||
| /******/ configurable: false, | ||
| /******/ enumerable: true, | ||
| /******/ get: getter | ||
| /******/ }); | ||
| /******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); | ||
| /******/ } | ||
| /******/ }; | ||
| /******/ | ||
| /******/ // define __esModule on exports | ||
| /******/ __webpack_require__.r = function(exports) { | ||
| /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { | ||
| /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); | ||
| /******/ } | ||
| /******/ Object.defineProperty(exports, '__esModule', { value: true }); | ||
| /******/ }; | ||
| /******/ | ||
| /******/ // create a fake namespace object | ||
| /******/ // mode & 1: value is a module id, require it | ||
| /******/ // mode & 2: merge all properties of value into the ns | ||
| /******/ // mode & 4: return value when already ns object | ||
| /******/ // mode & 8|1: behave like require | ||
| /******/ __webpack_require__.t = function(value, mode) { | ||
| /******/ if(mode & 1) value = __webpack_require__(value); | ||
| /******/ if(mode & 8) return value; | ||
| /******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; | ||
| /******/ var ns = Object.create(null); | ||
| /******/ __webpack_require__.r(ns); | ||
| /******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); | ||
| /******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); | ||
| /******/ return ns; | ||
| /******/ }; | ||
| /******/ | ||
| /******/ // getDefaultExport function for compatibility with non-harmony modules | ||
@@ -77,476 +94,54 @@ /******/ __webpack_require__.n = function(module) { | ||
| /******/ | ||
| /******/ | ||
| /******/ // Load entry module and return exports | ||
| /******/ return __webpack_require__(__webpack_require__.s = 3); | ||
| /******/ return __webpack_require__(__webpack_require__.s = "./lib/html-to-dom-client.js"); | ||
| /******/ }) | ||
| /************************************************************************/ | ||
| /******/ ([ | ||
| /* 0 */ | ||
| /***/ (function(module, exports, __webpack_require__) { | ||
| /******/ ({ | ||
| "use strict"; | ||
| /***/ "./lib/constants.js": | ||
| /*!**************************!*\ | ||
| !*** ./lib/constants.js ***! | ||
| \**************************/ | ||
| /*! no static exports found */ | ||
| /***/ (function(module, exports) { | ||
| eval("/**\n * SVG elements are case-sensitive.\n *\n * @see {@link https://developer.mozilla.org/docs/Web/SVG/Element#SVG_elements_A_to_Z}\n */\nvar CASE_SENSITIVE_TAG_NAMES = [\n 'animateMotion',\n 'animateTransform',\n 'clipPath',\n 'feBlend',\n 'feColorMatrix',\n 'feComponentTransfer',\n 'feComposite',\n 'feConvolveMatrix',\n 'feDiffuseLighting',\n 'feDisplacementMap',\n 'feDropShadow',\n 'feFlood',\n 'feFuncA',\n 'feFuncB',\n 'feFuncG',\n 'feFuncR',\n 'feGaussainBlur',\n 'feImage',\n 'feMerge',\n 'feMergeNode',\n 'feMorphology',\n 'feOffset',\n 'fePointLight',\n 'feSpecularLighting',\n 'feSpotLight',\n 'feTile',\n 'feTurbulence',\n 'foreignObject',\n 'linearGradient',\n 'radialGradient',\n 'textPath'\n];\n\nmodule.exports = {\n CASE_SENSITIVE_TAG_NAMES: CASE_SENSITIVE_TAG_NAMES\n};\n\n\n//# sourceURL=webpack://HTMLDOMParser/./lib/constants.js?"); | ||
| var CASE_SENSITIVE_TAG_NAMES = __webpack_require__(2).CASE_SENSITIVE_TAG_NAMES; | ||
| /***/ }), | ||
| var caseSensitiveTagNamesMap = {}; | ||
| var tagName; | ||
| for (var i = 0, len = CASE_SENSITIVE_TAG_NAMES.length; i < len; i++) { | ||
| tagName = CASE_SENSITIVE_TAG_NAMES[i]; | ||
| caseSensitiveTagNamesMap[tagName.toLowerCase()] = tagName; | ||
| } | ||
| /***/ "./lib/domparser.js": | ||
| /*!**************************!*\ | ||
| !*** ./lib/domparser.js ***! | ||
| \**************************/ | ||
| /*! no static exports found */ | ||
| /***/ (function(module, exports, __webpack_require__) { | ||
| /** | ||
| * Gets case-sensitive tag name. | ||
| * | ||
| * @param {String} tagName - The lowercase tag name. | ||
| * @return {String|undefined} | ||
| */ | ||
| function getCaseSensitiveTagName(tagName) { | ||
| return caseSensitiveTagNamesMap[tagName]; | ||
| } | ||
| eval("var utilities = __webpack_require__(/*! ./utilities */ \"./lib/utilities.js\");\n\n// constants\nvar HTML = 'html';\nvar HEAD = 'head';\nvar BODY = 'body';\nvar FIRST_TAG_REGEX = /<([a-zA-Z]+[0-9]?)/; // e.g., <h1>\nvar HEAD_TAG_REGEX = /<head.*>/i;\nvar BODY_TAG_REGEX = /<body.*>/i;\n// http://www.w3.org/TR/html/syntax.html#void-elements\nvar VOID_ELEMENTS_REGEX = /<(area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)(.*?)\\/?>/gi;\n\n// detect IE browser\nvar isIE9 = utilities.isIE(9);\nvar isIE = isIE9 || utilities.isIE();\n\n/**\n * DOMParser (performance: slow).\n *\n * @see https://developer.mozilla.org/docs/Web/API/DOMParser#Parsing_an_SVG_or_HTML_document\n */\nvar parseFromString;\n\nif (typeof window.DOMParser === 'function') {\n var domParser = new window.DOMParser();\n\n // IE9 does not support 'text/html' MIME type\n // https://msdn.microsoft.com/en-us/library/ff975278(v=vs.85).aspx\n var mimeType = isIE9 ? 'text/xml' : 'text/html';\n\n /**\n * Creates an HTML document using `DOMParser.parseFromString`.\n *\n * @param {string} html - The HTML string.\n * @param {string} [tagName] - The element to render the HTML (with 'body' as fallback).\n * @return {HTMLDocument}\n */\n parseFromString = function domStringParser(html, tagName) {\n if (tagName) {\n html = '<' + tagName + '>' + html + '</' + tagName + '>';\n }\n\n // because IE9 only supports MIME type 'text/xml', void elements need to be self-closed\n if (isIE9) {\n html = html.replace(VOID_ELEMENTS_REGEX, '<$1$2$3/>');\n }\n\n return domParser.parseFromString(html, mimeType);\n };\n}\n\n/**\n * DOMImplementation (performance: fair).\n *\n * @see https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument\n */\nvar parseFromDocument;\n\nif (typeof document.implementation === 'object') {\n // title parameter is required in IE\n // https://msdn.microsoft.com/en-us/library/ff975457(v=vs.85).aspx\n var doc = document.implementation.createHTMLDocument(\n isIE ? 'HTML_DOM_PARSER_TITLE' : undefined\n );\n\n /**\n * Use HTML document created by `document.implementation.createHTMLDocument`.\n *\n * @param {string} html - The HTML string.\n * @param {string} [tagName] - The element to render the HTML (with 'body' as fallback).\n * @return {HTMLDocument}\n */\n parseFromDocument = function createHTMLDocument(html, tagName) {\n if (tagName) {\n doc.documentElement.getElementsByTagName(tagName)[0].innerHTML = html;\n return doc;\n }\n\n try {\n doc.documentElement.innerHTML = html;\n return doc;\n // fallback when certain elements in `documentElement` are read-only (IE9)\n } catch (err) {\n if (parseFromString) {\n return parseFromString(html);\n }\n }\n };\n}\n\n/**\n * Template (performance: fast).\n *\n * @see https://developer.mozilla.org/docs/Web/HTML/Element/template\n */\nvar parseFromTemplate;\nvar template = document.createElement('template');\n\nif (template.content) {\n /**\n * Uses a template element (content fragment) to parse HTML.\n *\n * @param {string} html - The HTML string.\n * @return {NodeList}\n */\n parseFromTemplate = function templateParser(html) {\n template.innerHTML = html;\n return template.content.childNodes;\n };\n}\n\n// fallback document parser\nvar parseWithFallback = parseFromDocument || parseFromString;\n\n/**\n * Parses HTML string to DOM nodes.\n *\n * @param {string} html - The HTML string.\n * @return {NodeList|Array}\n */\nfunction domparser(html) {\n var firstTagName;\n var match = html.match(FIRST_TAG_REGEX);\n\n if (match && match[1]) {\n firstTagName = match[1].toLowerCase();\n }\n\n var doc;\n var element;\n var elements;\n\n switch (firstTagName) {\n case HTML:\n if (parseFromString) {\n doc = parseFromString(html);\n\n // the created document may come with filler head/body elements,\n // so make sure to remove them if they don't actually exist\n if (!HEAD_TAG_REGEX.test(html)) {\n element = doc.getElementsByTagName(HEAD)[0];\n if (element) {\n element.parentNode.removeChild(element);\n }\n }\n\n if (!BODY_TAG_REGEX.test(html)) {\n element = doc.getElementsByTagName(BODY)[0];\n if (element) {\n element.parentNode.removeChild(element);\n }\n }\n\n return doc.getElementsByTagName(HTML);\n }\n break;\n\n case HEAD:\n case BODY:\n if (parseWithFallback) {\n elements = parseWithFallback(html).getElementsByTagName(firstTagName);\n\n // account for possibility of sibling\n if (BODY_TAG_REGEX.test(html) && HEAD_TAG_REGEX.test(html)) {\n return elements[0].parentNode.childNodes;\n }\n\n return elements;\n }\n break;\n\n // low-level tag or text\n default:\n if (parseFromTemplate) {\n return parseFromTemplate(html);\n }\n\n if (parseWithFallback) {\n return parseWithFallback(html, BODY).getElementsByTagName(BODY)[0]\n .childNodes;\n }\n\n break;\n }\n\n return [];\n}\n\nmodule.exports = domparser;\n\n\n//# sourceURL=webpack://HTMLDOMParser/./lib/domparser.js?"); | ||
| /** | ||
| * Formats DOM attributes to a hash map. | ||
| * | ||
| * @param {NamedNodeMap} attributes - The list of attributes. | ||
| * @return {Object} - A map of attribute name to value. | ||
| */ | ||
| function formatAttributes(attributes) { | ||
| var result = {}; | ||
| var attribute; | ||
| // `NamedNodeMap` is array-like | ||
| for (var i = 0, len = attributes.length; i < len; i++) { | ||
| attribute = attributes[i]; | ||
| result[attribute.name] = attribute.value; | ||
| } | ||
| return result; | ||
| } | ||
| /***/ }), | ||
| /** | ||
| * Corrects the tag name if it is case-sensitive (SVG). | ||
| * Otherwise, returns the lowercase tag name (HTML). | ||
| * | ||
| * @param {String} tagName - The lowercase tag name. | ||
| * @return {String} - The formatted tag name. | ||
| */ | ||
| function formatTagName(tagName) { | ||
| tagName = tagName.toLowerCase(); | ||
| var caseSensitiveTagName = getCaseSensitiveTagName(tagName); | ||
| if (caseSensitiveTagName) { | ||
| return caseSensitiveTagName; | ||
| } | ||
| return tagName; | ||
| } | ||
| /** | ||
| * Formats the browser DOM nodes to mimic the output of `htmlparser2.parseDOM()`. | ||
| * | ||
| * @param {NodeList} nodes - The DOM nodes. | ||
| * @param {Object} [parentObj] - The formatted parent node. | ||
| * @param {String} [directive] - The directive. | ||
| * @return {Object[]} - The formatted DOM object. | ||
| */ | ||
| function formatDOM(nodes, parentObj, directive) { | ||
| parentObj = parentObj || null; | ||
| var result = []; | ||
| var node; | ||
| var prevNode; | ||
| var nodeObj; | ||
| // `NodeList` is array-like | ||
| for (var i = 0, len = nodes.length; i < len; i++) { | ||
| node = nodes[i]; | ||
| // reset | ||
| nodeObj = { | ||
| next: null, | ||
| prev: result[i - 1] || null, | ||
| parent: parentObj | ||
| }; | ||
| // set the next node for the previous node (if applicable) | ||
| prevNode = result[i - 1]; | ||
| if (prevNode) { | ||
| prevNode.next = nodeObj; | ||
| } | ||
| // set the node name if it's not "#text" or "#comment" | ||
| // e.g., "div" | ||
| if (node.nodeName[0] !== '#') { | ||
| nodeObj.name = formatTagName(node.nodeName); | ||
| // also, nodes of type "tag" have "attribs" | ||
| nodeObj.attribs = {}; // default | ||
| if (node.attributes && node.attributes.length) { | ||
| nodeObj.attribs = formatAttributes(node.attributes); | ||
| } | ||
| } | ||
| // set the node type | ||
| // e.g., "tag" | ||
| switch (node.nodeType) { | ||
| // 1 = element | ||
| case 1: | ||
| if (nodeObj.name === 'script' || nodeObj.name === 'style') { | ||
| nodeObj.type = nodeObj.name; | ||
| } else { | ||
| nodeObj.type = 'tag'; | ||
| } | ||
| // recursively format the children | ||
| nodeObj.children = formatDOM(node.childNodes, nodeObj); | ||
| break; | ||
| // 2 = attribute | ||
| // 3 = text | ||
| case 3: | ||
| nodeObj.type = 'text'; | ||
| nodeObj.data = node.nodeValue; | ||
| break; | ||
| // 8 = comment | ||
| case 8: | ||
| nodeObj.type = 'comment'; | ||
| nodeObj.data = node.nodeValue; | ||
| break; | ||
| default: | ||
| break; | ||
| } | ||
| result.push(nodeObj); | ||
| } | ||
| if (directive) { | ||
| result.unshift({ | ||
| name: directive.substring(0, directive.indexOf(' ')).toLowerCase(), | ||
| data: directive, | ||
| type: 'directive', | ||
| next: result[0] ? result[0] : null, | ||
| prev: null, | ||
| parent: parentObj | ||
| }); | ||
| if (result[1]) { | ||
| result[1].prev = result[0]; | ||
| } | ||
| } | ||
| return result; | ||
| } | ||
| /** | ||
| * Detects IE with or without version. | ||
| * | ||
| * @param {Number} [version] - The IE version to detect. | ||
| * @return {Boolean} - Whether IE or the version has been detected. | ||
| */ | ||
| function isIE(version) { | ||
| if (version) { | ||
| return document.documentMode === version; | ||
| } | ||
| return /(MSIE |Trident\/|Edge\/)/.test(navigator.userAgent); | ||
| } | ||
| /** | ||
| * Export utilities. | ||
| */ | ||
| module.exports = { | ||
| formatAttributes: formatAttributes, | ||
| formatDOM: formatDOM, | ||
| isIE: isIE | ||
| }; | ||
| /***/ }), | ||
| /* 1 */ | ||
| /***/ "./lib/html-to-dom-client.js": | ||
| /*!***********************************!*\ | ||
| !*** ./lib/html-to-dom-client.js ***! | ||
| \***********************************/ | ||
| /*! no static exports found */ | ||
| /***/ (function(module, exports, __webpack_require__) { | ||
| "use strict"; | ||
| eval("var domparser = __webpack_require__(/*! ./domparser */ \"./lib/domparser.js\");\nvar utilities = __webpack_require__(/*! ./utilities */ \"./lib/utilities.js\");\n\nvar formatDOM = utilities.formatDOM;\nvar isIE9 = utilities.isIE(9);\n\nvar DIRECTIVE_REGEX = /<(![a-zA-Z\\s]+)>/; // e.g., <!doctype html>\n\n/**\n * Parses HTML and reformats DOM nodes output.\n *\n * @param {String} html - The HTML string.\n * @return {Array} - The formatted DOM nodes.\n */\nfunction parseDOM(html) {\n if (typeof html !== 'string') {\n throw new TypeError('First argument must be a string');\n }\n\n if (!html) {\n return [];\n }\n\n // match directive\n var match = html.match(DIRECTIVE_REGEX);\n var directive;\n\n if (match && match[1]) {\n directive = match[1];\n\n // remove directive in IE9 because DOMParser uses\n // MIME type 'text/xml' instead of 'text/html'\n if (isIE9) {\n html = html.replace(match[0], '');\n }\n }\n\n return formatDOM(domparser(html), null, directive);\n}\n\nmodule.exports = parseDOM;\n\n\n//# sourceURL=webpack://HTMLDOMParser/./lib/html-to-dom-client.js?"); | ||
| /** | ||
| * Module dependencies. | ||
| */ | ||
| var utilities = __webpack_require__(0); | ||
| var detectIE = utilities.isIE; | ||
| /** | ||
| * Constants. | ||
| */ | ||
| var HTML_TAG_NAME = 'html'; | ||
| var BODY_TAG_NAME = 'body'; | ||
| var HEAD_TAG_NAME = 'head'; | ||
| var FIRST_TAG_REGEX = /<([a-zA-Z]+[0-9]?)/; // e.g., <h1> | ||
| var HEAD_REGEX = /<\/head>/i; | ||
| var BODY_REGEX = /<\/body>/i; | ||
| // http://www.w3.org/TR/html/syntax.html#void-elements | ||
| var VOID_ELEMENTS_REGEX = /<(area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)(.*?)\/?>/gi; | ||
| // browser support | ||
| var isIE = detectIE(); | ||
| var isIE9 = detectIE(9); | ||
| /** | ||
| * DOMParser (performance: slow). | ||
| * | ||
| * 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(); | ||
| // IE9 does not support 'text/html' MIME type | ||
| // https://msdn.microsoft.com/en-us/library/ff975278(v=vs.85).aspx | ||
| var MIME_TYPE = isIE9 ? 'text/xml' : 'text/html'; | ||
| /** | ||
| * Creates an HTML document using `DOMParser.parseFromString`. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @param {String} [tagName] - The element to render the HTML (with 'body' as fallback). | ||
| * @return {HTMLDocument} | ||
| */ | ||
| parseFromString = function domStringParser(html, tagName) { | ||
| if (tagName) { | ||
| html = ['<', tagName, '>', html, '</', tagName, '>'].join(''); | ||
| } | ||
| // because IE9 only supports MIME type 'text/xml', void elements need to be self-closed | ||
| if (isIE9) { | ||
| html = html.replace(VOID_ELEMENTS_REGEX, '<$1$2$3/>'); | ||
| } | ||
| return domParser.parseFromString(html, MIME_TYPE); | ||
| }; | ||
| } | ||
| /** | ||
| * DOMImplementation (performance: fair). | ||
| * | ||
| * https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument | ||
| */ | ||
| var parseFromDocument; | ||
| if (typeof document.implementation === 'object') { | ||
| // 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); | ||
| /** | ||
| * Use HTML document created by `document.implementation.createHTMLDocument`. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @param {String} [tagName] - The element to render the HTML (with 'body' as fallback). | ||
| * @return {HTMLDocument} | ||
| */ | ||
| parseFromDocument = function createHTMLDocument(html, tagName) { | ||
| if (tagName) { | ||
| doc.documentElement.getElementsByTagName(tagName)[0].innerHTML = html; | ||
| return doc; | ||
| } | ||
| try { | ||
| doc.documentElement.innerHTML = html; | ||
| return doc; | ||
| // fallback when certain elements in `documentElement` are read-only (IE9) | ||
| } catch (err) { | ||
| if (parseFromString) return parseFromString(html); | ||
| } | ||
| }; | ||
| } | ||
| /** | ||
| * Template (performance: fast). | ||
| * | ||
| * https://developer.mozilla.org/docs/Web/HTML/Element/template | ||
| */ | ||
| var parseFromTemplate; | ||
| var template = document.createElement('template'); | ||
| if (template.content) { | ||
| /** | ||
| * Uses a template element (content fragment) to parse HTML. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @return {NodeList} | ||
| */ | ||
| parseFromTemplate = function templateParser(html) { | ||
| template.innerHTML = html; | ||
| return template.content.childNodes; | ||
| }; | ||
| } | ||
| /** Fallback document parser. */ | ||
| var parseWithFallback = parseFromDocument || parseFromString; | ||
| /** | ||
| * Parses HTML string to DOM nodes. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @param {String} [tagName] - The tag name. | ||
| * @return {NodeList|Array} | ||
| */ | ||
| module.exports = function domparser(html) { | ||
| // try to match first tag | ||
| var tagName; | ||
| var match = html.match(FIRST_TAG_REGEX); | ||
| if (match && match[1]) { | ||
| tagName = match[1].toLowerCase(); | ||
| } | ||
| var doc; | ||
| var element; | ||
| var elements; | ||
| switch (tagName) { | ||
| case HTML_TAG_NAME: | ||
| if (parseFromString) { | ||
| doc = parseFromString(html); | ||
| // the created document may come with filler head/body elements, | ||
| // so ake sure to remove them if they don't actually exist | ||
| if (!HEAD_REGEX.test(html)) { | ||
| element = doc.getElementsByTagName(HEAD_TAG_NAME)[0]; | ||
| if (element) element.parentNode.removeChild(element); | ||
| } | ||
| if (!BODY_REGEX.test(html)) { | ||
| element = doc.getElementsByTagName(BODY_TAG_NAME)[0]; | ||
| if (element) element.parentNode.removeChild(element); | ||
| } | ||
| return doc.getElementsByTagName(HTML_TAG_NAME); | ||
| } | ||
| break; | ||
| case HEAD_TAG_NAME: | ||
| if (parseWithFallback) { | ||
| elements = parseWithFallback(html).getElementsByTagName(HEAD_TAG_NAME); | ||
| // account for possibility of sibling | ||
| if (BODY_REGEX.test(html)) { | ||
| return elements[0].parentNode.childNodes; | ||
| } | ||
| return elements; | ||
| } | ||
| break; | ||
| case BODY_TAG_NAME: | ||
| if (parseWithFallback) { | ||
| elements = parseWithFallback(html).getElementsByTagName(BODY_TAG_NAME); | ||
| // account for possibility of sibling (return both body and head) | ||
| if (HEAD_REGEX.test(html)) { | ||
| return elements[0].parentNode.childNodes; | ||
| } | ||
| return elements; | ||
| } | ||
| break; | ||
| // low-level tag or text | ||
| default: | ||
| if (parseFromTemplate) return parseFromTemplate(html); | ||
| if (parseWithFallback) { | ||
| return parseWithFallback(html, BODY_TAG_NAME).getElementsByTagName(BODY_TAG_NAME)[0].childNodes; | ||
| } | ||
| break; | ||
| } | ||
| return []; | ||
| }; | ||
| /***/ }), | ||
| /* 2 */ | ||
| /***/ (function(module, exports, __webpack_require__) { | ||
| "use strict"; | ||
| /** | ||
| * SVG elements, unlike HTML elements, are case-sensitive. | ||
| * | ||
| * @see {@link https://developer.mozilla.org/docs/Web/SVG/Element#SVG_elements_A_to_Z} | ||
| */ | ||
| var CASE_SENSITIVE_TAG_NAMES = [ | ||
| 'animateMotion', | ||
| 'animateTransform', | ||
| 'clipPath', | ||
| 'feBlend', | ||
| 'feColorMatrix', | ||
| 'feComponentTransfer', | ||
| 'feComposite', | ||
| 'feConvolveMatrix', | ||
| 'feDiffuseLighting', | ||
| 'feDisplacementMap', | ||
| 'feDropShadow', | ||
| 'feFlood', | ||
| 'feFuncA', | ||
| 'feFuncB', | ||
| 'feFuncG', | ||
| 'feFuncR', | ||
| 'feGaussainBlur', | ||
| 'feImage', | ||
| 'feMerge', | ||
| 'feMergeNode', | ||
| 'feMorphology', | ||
| 'feOffset', | ||
| 'fePointLight', | ||
| 'feSpecularLighting', | ||
| 'feSpotLight', | ||
| 'feTile', | ||
| 'feTurbulence', | ||
| 'foreignObject', | ||
| 'linearGradient', | ||
| 'radialGradient', | ||
| 'textPath' | ||
| ]; | ||
| module.exports = { | ||
| CASE_SENSITIVE_TAG_NAMES: CASE_SENSITIVE_TAG_NAMES | ||
| }; | ||
| /***/ }), | ||
| /* 3 */ | ||
| /***/ "./lib/utilities.js": | ||
| /*!**************************!*\ | ||
| !*** ./lib/utilities.js ***! | ||
| \**************************/ | ||
| /*! no static exports found */ | ||
| /***/ (function(module, exports, __webpack_require__) { | ||
| "use strict"; | ||
| eval("var CASE_SENSITIVE_TAG_NAMES = __webpack_require__(/*! ./constants */ \"./lib/constants.js\").CASE_SENSITIVE_TAG_NAMES;\n\nvar caseSensitiveTagNamesMap = {};\nvar tagName;\nfor (var i = 0, len = CASE_SENSITIVE_TAG_NAMES.length; i < len; i++) {\n tagName = CASE_SENSITIVE_TAG_NAMES[i];\n caseSensitiveTagNamesMap[tagName.toLowerCase()] = tagName;\n}\n\n/**\n * Gets case-sensitive tag name.\n *\n * @param {String} tagName - The lowercase tag name.\n * @return {String|undefined}\n */\nfunction getCaseSensitiveTagName(tagName) {\n return caseSensitiveTagNamesMap[tagName];\n}\n\n/**\n * Formats DOM attributes to a hash map.\n *\n * @param {NamedNodeMap} attributes - The list of attributes.\n * @return {Object} - A map of attribute name to value.\n */\nfunction formatAttributes(attributes) {\n var result = {};\n var attribute;\n // `NamedNodeMap` is array-like\n for (var i = 0, len = attributes.length; i < len; i++) {\n attribute = attributes[i];\n result[attribute.name] = attribute.value;\n }\n return result;\n}\n\n/**\n * Corrects the tag name if it is case-sensitive (SVG).\n * Otherwise, returns the lowercase tag name (HTML).\n *\n * @param {String} tagName - The lowercase tag name.\n * @return {String} - The formatted tag name.\n */\nfunction formatTagName(tagName) {\n tagName = tagName.toLowerCase();\n var caseSensitiveTagName = getCaseSensitiveTagName(tagName);\n if (caseSensitiveTagName) {\n return caseSensitiveTagName;\n }\n return tagName;\n}\n\n/**\n * Formats the browser DOM nodes to mimic the output of `htmlparser2.parseDOM()`.\n *\n * @param {NodeList} nodes - The DOM nodes.\n * @param {Object} [parentObj] - The formatted parent node.\n * @param {String} [directive] - The directive.\n * @return {Object[]} - The formatted DOM object.\n */\nfunction formatDOM(nodes, parentObj, directive) {\n parentObj = parentObj || null;\n\n var result = [];\n var node;\n var prevNode;\n var nodeObj;\n\n // `NodeList` is array-like\n for (var i = 0, len = nodes.length; i < len; i++) {\n node = nodes[i];\n // reset\n nodeObj = {\n next: null,\n prev: result[i - 1] || null,\n parent: parentObj\n };\n\n // set the next node for the previous node (if applicable)\n prevNode = result[i - 1];\n if (prevNode) {\n prevNode.next = nodeObj;\n }\n\n // set the node name if it's not \"#text\" or \"#comment\"\n // e.g., \"div\"\n if (node.nodeName[0] !== '#') {\n nodeObj.name = formatTagName(node.nodeName);\n // also, nodes of type \"tag\" have \"attribs\"\n nodeObj.attribs = {}; // default\n if (node.attributes && node.attributes.length) {\n nodeObj.attribs = formatAttributes(node.attributes);\n }\n }\n\n // set the node type\n // e.g., \"tag\"\n switch (node.nodeType) {\n // 1 = element\n case 1:\n if (nodeObj.name === 'script' || nodeObj.name === 'style') {\n nodeObj.type = nodeObj.name;\n } else {\n nodeObj.type = 'tag';\n }\n // recursively format the children\n nodeObj.children = formatDOM(node.childNodes, nodeObj);\n break;\n // 2 = attribute\n // 3 = text\n case 3:\n nodeObj.type = 'text';\n nodeObj.data = node.nodeValue;\n break;\n // 8 = comment\n case 8:\n nodeObj.type = 'comment';\n nodeObj.data = node.nodeValue;\n break;\n }\n\n result.push(nodeObj);\n }\n\n if (directive) {\n result.unshift({\n name: directive.substring(0, directive.indexOf(' ')).toLowerCase(),\n data: directive,\n type: 'directive',\n next: result[0] ? result[0] : null,\n prev: null,\n parent: parentObj\n });\n\n if (result[1]) {\n result[1].prev = result[0];\n }\n }\n\n return result;\n}\n\n/**\n * Detects IE with or without version.\n *\n * @param {Number} [version] - The IE version to detect.\n * @return {Boolean} - Whether IE or the version has been detected.\n */\nfunction isIE(version) {\n if (version) {\n return document.documentMode === version;\n }\n return /(MSIE |Trident\\/|Edge\\/)/.test(navigator.userAgent);\n}\n\nmodule.exports = {\n formatAttributes: formatAttributes,\n formatDOM: formatDOM,\n isIE: isIE\n};\n\n\n//# sourceURL=webpack://HTMLDOMParser/./lib/utilities.js?"); | ||
| /***/ }) | ||
| /** | ||
| * Module dependencies. | ||
| */ | ||
| var domparser = __webpack_require__(1); | ||
| var utilities = __webpack_require__(0); | ||
| var formatDOM = utilities.formatDOM; | ||
| var isIE9 = utilities.isIE(9); | ||
| /** | ||
| * Constants. | ||
| */ | ||
| var DIRECTIVE_REGEX = /<(![a-zA-Z\s]+)>/; // e.g., <!doctype html> | ||
| /** | ||
| * Parses HTML and reformats DOM nodes output. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @return {Array} - The formatted DOM nodes. | ||
| */ | ||
| module.exports = function parseDOM(html) { | ||
| if (typeof html !== 'string') { | ||
| throw new TypeError('First argument must be a string.'); | ||
| } | ||
| if (!html) return []; | ||
| // match directive | ||
| var match = html.match(DIRECTIVE_REGEX); | ||
| var directive; | ||
| if (match && match[1]) { | ||
| directive = match[1]; | ||
| // remove directive in IE9 because DOMParser uses | ||
| // MIME type 'text/xml' instead of 'text/html' | ||
| if (isIE9) { | ||
| html = html.replace(match[0], ''); | ||
| } | ||
| } | ||
| return formatDOM(domparser(html), null, directive); | ||
| }; | ||
| /***/ }) | ||
| /******/ ]); | ||
| /******/ }); | ||
| }); |
@@ -1,1 +0,1 @@ | ||
| !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.HTMLDOMParser=t():e.HTMLDOMParser=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var a=n[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,t),a.l=!0,a.exports}var n={};return t.m=e,t.c=n,t.i=function(e){return e},t.d=function(e,n,r){t.o(e,n)||Object.defineProperty(e,n,{configurable:!1,enumerable:!0,get:r})},t.n=function(e){var n=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(n,"a",n),n},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=3)}([function(e,t,n){"use strict";function r(e){return c[e]}function a(e){for(var t,n={},r=0,a=e.length;r<a;r++)t=e[r],n[t.name]=t.value;return n}function o(e){e=e.toLowerCase();var t=r(e);return t||e}function i(e,t,n){t=t||null;for(var r,u,f,s=[],c=0,l=e.length;c<l;c++){switch(r=e[c],f={next:null,prev:s[c-1]||null,parent:t},u=s[c-1],u&&(u.next=f),"#"!==r.nodeName[0]&&(f.name=o(r.nodeName),f.attribs={},r.attributes&&r.attributes.length&&(f.attribs=a(r.attributes))),r.nodeType){case 1:"script"===f.name||"style"===f.name?f.type=f.name:f.type="tag",f.children=i(r.childNodes,f);break;case 3:f.type="text",f.data=r.nodeValue;break;case 8:f.type="comment",f.data=r.nodeValue}s.push(f)}return n&&(s.unshift({name:n.substring(0,n.indexOf(" ")).toLowerCase(),data:n,type:"directive",next:s[0]?s[0]:null,prev:null,parent:t}),s[1]&&(s[1].prev=s[0])),s}function u(e){return e?document.documentMode===e:/(MSIE |Trident\/|Edge\/)/.test(navigator.userAgent)}for(var f,s=n(2).CASE_SENSITIVE_TAG_NAMES,c={},l=0,m=s.length;l<m;l++)f=s[l],c[f.toLowerCase()]=f;e.exports={formatAttributes:a,formatDOM:i,isIE:u}},function(e,t,n){"use strict";var r,a=n(0),o=a.isIE,i=/<([a-zA-Z]+[0-9]?)/,u=/<\/head>/i,f=/<\/body>/i,s=/<(area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)(.*?)\/?>/gi,c=o(),l=o(9);if("function"==typeof window.DOMParser){var m=new window.DOMParser,d=l?"text/xml":"text/html";r=function(e,t){return t&&(e=["<",t,">",e,"</",t,">"].join("")),l&&(e=e.replace(s,"<$1$2$3/>")),m.parseFromString(e,d)}}var p;if("object"==typeof document.implementation){var g=document.implementation.createHTMLDocument(c?"HTML_DOM_PARSER_TITLE":void 0);p=function(e,t){if(t)return g.documentElement.getElementsByTagName(t)[0].innerHTML=e,g;try{return g.documentElement.innerHTML=e,g}catch(t){if(r)return r(e)}}}var h,y=document.createElement("template");y.content&&(h=function(e){return y.innerHTML=e,y.content.childNodes});var b=p||r;e.exports=function(e){var t,n=e.match(i);n&&n[1]&&(t=n[1].toLowerCase());var a,o,s;switch(t){case"html":if(r)return a=r(e),u.test(e)||(o=a.getElementsByTagName("head")[0])&&o.parentNode.removeChild(o),f.test(e)||(o=a.getElementsByTagName("body")[0])&&o.parentNode.removeChild(o),a.getElementsByTagName("html");break;case"head":if(b)return s=b(e).getElementsByTagName("head"),f.test(e)?s[0].parentNode.childNodes:s;break;case"body":if(b)return s=b(e).getElementsByTagName("body"),u.test(e)?s[0].parentNode.childNodes:s;break;default:if(h)return h(e);if(b)return b(e,"body").getElementsByTagName("body")[0].childNodes}return[]}},function(e,t,n){"use strict";var r=["animateMotion","animateTransform","clipPath","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussainBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","foreignObject","linearGradient","radialGradient","textPath"];e.exports={CASE_SENSITIVE_TAG_NAMES:r}},function(e,t,n){"use strict";var r=n(1),a=n(0),o=a.formatDOM,i=a.isIE(9),u=/<(![a-zA-Z\s]+)>/;e.exports=function(e){if("string"!=typeof e)throw new TypeError("First argument must be a string.");if(!e)return[];var t,n=e.match(u);return n&&n[1]&&(t=n[1],i&&(e=e.replace(n[0],""))),o(r(e),null,t)}}])}); | ||
| !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.HTMLDOMParser=t():e.HTMLDOMParser=t()}(window,(function(){return function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}return n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t,n){for(var r,o=n(3).CASE_SENSITIVE_TAG_NAMES,a={},i=0,u=o.length;i<u;i++)r=o[i],a[r.toLowerCase()]=r;function f(e){for(var t,n={},r=0,o=e.length;r<o;r++)n[(t=e[r]).name]=t.value;return n}function c(e){var t=function(e){return a[e]}(e=e.toLowerCase());return t||e}e.exports={formatAttributes:f,formatDOM:function e(t,n,r){n=n||null;for(var o,a,i,u=[],l=0,s=t.length;l<s;l++){switch(o=t[l],i={next:null,prev:u[l-1]||null,parent:n},(a=u[l-1])&&(a.next=i),"#"!==o.nodeName[0]&&(i.name=c(o.nodeName),i.attribs={},o.attributes&&o.attributes.length&&(i.attribs=f(o.attributes))),o.nodeType){case 1:"script"===i.name||"style"===i.name?i.type=i.name:i.type="tag",i.children=e(o.childNodes,i);break;case 3:i.type="text",i.data=o.nodeValue;break;case 8:i.type="comment",i.data=o.nodeValue}u.push(i)}return r&&(u.unshift({name:r.substring(0,r.indexOf(" ")).toLowerCase(),data:r,type:"directive",next:u[0]?u[0]:null,prev:null,parent:n}),u[1]&&(u[1].prev=u[0])),u},isIE:function(e){return e?document.documentMode===e:/(MSIE |Trident\/|Edge\/)/.test(navigator.userAgent)}}},function(e,t,n){var r=n(2),o=n(0),a=o.formatDOM,i=o.isIE(9),u=/<(![a-zA-Z\s]+)>/;e.exports=function(e){if("string"!=typeof e)throw new TypeError("First argument must be a string");if(!e)return[];var t,n=e.match(u);return n&&n[1]&&(t=n[1],i&&(e=e.replace(n[0],""))),a(r(e),null,t)}},function(e,t,n){var r,o,a,i=n(0),u="html",f="head",c="body",l=/<([a-zA-Z]+[0-9]?)/,s=/<head.*>/i,d=/<body.*>/i,m=/<(area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)(.*?)\/?>/gi,p=i.isIE(9),g=p||i.isIE();if("function"==typeof window.DOMParser){var y=new window.DOMParser,b=p?"text/xml":"text/html";r=function(e,t){return t&&(e="<"+t+">"+e+"</"+t+">"),p&&(e=e.replace(m,"<$1$2$3/>")),y.parseFromString(e,b)}}if("object"==typeof document.implementation){var h=document.implementation.createHTMLDocument(g?"HTML_DOM_PARSER_TITLE":void 0);o=function(e,t){if(t)return h.documentElement.getElementsByTagName(t)[0].innerHTML=e,h;try{return h.documentElement.innerHTML=e,h}catch(t){if(r)return r(e)}}}var v=document.createElement("template");v.content&&(a=function(e){return v.innerHTML=e,v.content.childNodes});var M=o||r;e.exports=function(e){var t,n,o,i,m=e.match(l);switch(m&&m[1]&&(t=m[1].toLowerCase()),t){case u:if(r)return n=r(e),s.test(e)||(o=n.getElementsByTagName(f)[0])&&o.parentNode.removeChild(o),d.test(e)||(o=n.getElementsByTagName(c)[0])&&o.parentNode.removeChild(o),n.getElementsByTagName(u);break;case f:case c:if(M)return i=M(e).getElementsByTagName(t),d.test(e)&&s.test(e)?i[0].parentNode.childNodes:i;break;default:if(a)return a(e);if(M)return M(e,c).getElementsByTagName(c)[0].childNodes}return[]}},function(e,t){e.exports={CASE_SENSITIVE_TAG_NAMES:["animateMotion","animateTransform","clipPath","feBlend","feColorMatrix","feComponentTransfer","feComposite","feConvolveMatrix","feDiffuseLighting","feDisplacementMap","feDropShadow","feFlood","feFuncA","feFuncB","feFuncG","feFuncR","feGaussainBlur","feImage","feMerge","feMergeNode","feMorphology","feOffset","fePointLight","feSpecularLighting","feSpotLight","feTile","feTurbulence","foreignObject","linearGradient","radialGradient","textPath"]}}])})); |
+3
-5
@@ -1,9 +0,7 @@ | ||
| 'use strict'; | ||
| /** | ||
| * Use the server/node parser by default. | ||
| * When running on Node.js, use the server parser. | ||
| * When bundling for the browser, use the client parser. | ||
| * | ||
| * But use the client parser when bundling for the browser: | ||
| * https://github.com/substack/node-browserify#browser-field | ||
| * @see {@link https://github.com/substack/node-browserify#browser-field} | ||
| */ | ||
| module.exports = require('./lib/html-to-dom-server'); |
+33
-35
@@ -1,5 +0,3 @@ | ||
| 'use strict'; | ||
| /** | ||
| * SVG elements, unlike HTML elements, are case-sensitive. | ||
| * SVG elements are case-sensitive. | ||
| * | ||
@@ -9,37 +7,37 @@ * @see {@link https://developer.mozilla.org/docs/Web/SVG/Element#SVG_elements_A_to_Z} | ||
| var CASE_SENSITIVE_TAG_NAMES = [ | ||
| 'animateMotion', | ||
| 'animateTransform', | ||
| 'clipPath', | ||
| 'feBlend', | ||
| 'feColorMatrix', | ||
| 'feComponentTransfer', | ||
| 'feComposite', | ||
| 'feConvolveMatrix', | ||
| 'feDiffuseLighting', | ||
| 'feDisplacementMap', | ||
| 'feDropShadow', | ||
| 'feFlood', | ||
| 'feFuncA', | ||
| 'feFuncB', | ||
| 'feFuncG', | ||
| 'feFuncR', | ||
| 'feGaussainBlur', | ||
| 'feImage', | ||
| 'feMerge', | ||
| 'feMergeNode', | ||
| 'feMorphology', | ||
| 'feOffset', | ||
| 'fePointLight', | ||
| 'feSpecularLighting', | ||
| 'feSpotLight', | ||
| 'feTile', | ||
| 'feTurbulence', | ||
| 'foreignObject', | ||
| 'linearGradient', | ||
| 'radialGradient', | ||
| 'textPath' | ||
| 'animateMotion', | ||
| 'animateTransform', | ||
| 'clipPath', | ||
| 'feBlend', | ||
| 'feColorMatrix', | ||
| 'feComponentTransfer', | ||
| 'feComposite', | ||
| 'feConvolveMatrix', | ||
| 'feDiffuseLighting', | ||
| 'feDisplacementMap', | ||
| 'feDropShadow', | ||
| 'feFlood', | ||
| 'feFuncA', | ||
| 'feFuncB', | ||
| 'feFuncG', | ||
| 'feFuncR', | ||
| 'feGaussainBlur', | ||
| 'feImage', | ||
| 'feMerge', | ||
| 'feMergeNode', | ||
| 'feMorphology', | ||
| 'feOffset', | ||
| 'fePointLight', | ||
| 'feSpecularLighting', | ||
| 'feSpotLight', | ||
| 'feTile', | ||
| 'feTurbulence', | ||
| 'foreignObject', | ||
| 'linearGradient', | ||
| 'radialGradient', | ||
| 'textPath' | ||
| ]; | ||
| module.exports = { | ||
| CASE_SENSITIVE_TAG_NAMES: CASE_SENSITIVE_TAG_NAMES | ||
| CASE_SENSITIVE_TAG_NAMES: CASE_SENSITIVE_TAG_NAMES | ||
| }; |
+137
-135
@@ -1,24 +0,16 @@ | ||
| 'use strict'; | ||
| /** | ||
| * Module dependencies. | ||
| */ | ||
| var utilities = require('./utilities'); | ||
| var detectIE = utilities.isIE; | ||
| /** | ||
| * Constants. | ||
| */ | ||
| var HTML_TAG_NAME = 'html'; | ||
| var BODY_TAG_NAME = 'body'; | ||
| var HEAD_TAG_NAME = 'head'; | ||
| // constants | ||
| var HTML = 'html'; | ||
| var HEAD = 'head'; | ||
| var BODY = 'body'; | ||
| var FIRST_TAG_REGEX = /<([a-zA-Z]+[0-9]?)/; // e.g., <h1> | ||
| var HEAD_REGEX = /<\/head>/i; | ||
| var BODY_REGEX = /<\/body>/i; | ||
| var HEAD_TAG_REGEX = /<head.*>/i; | ||
| var BODY_TAG_REGEX = /<body.*>/i; | ||
| // http://www.w3.org/TR/html/syntax.html#void-elements | ||
| var VOID_ELEMENTS_REGEX = /<(area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)(.*?)\/?>/gi; | ||
| // browser support | ||
| var isIE = detectIE(); | ||
| var isIE9 = detectIE(9); | ||
| // detect IE browser | ||
| var isIE9 = utilities.isIE(9); | ||
| var isIE = isIE9 || utilities.isIE(); | ||
@@ -28,28 +20,32 @@ /** | ||
| * | ||
| * https://developer.mozilla.org/docs/Web/API/DOMParser#Parsing_an_SVG_or_HTML_document | ||
| * @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(); | ||
| // IE9 does not support 'text/html' MIME type | ||
| // https://msdn.microsoft.com/en-us/library/ff975278(v=vs.85).aspx | ||
| var MIME_TYPE = isIE9 ? 'text/xml' : 'text/html'; | ||
| var domParser = new window.DOMParser(); | ||
| /** | ||
| * Creates an HTML document using `DOMParser.parseFromString`. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @param {String} [tagName] - The element to render the HTML (with 'body' as fallback). | ||
| * @return {HTMLDocument} | ||
| */ | ||
| parseFromString = function domStringParser(html, tagName) { | ||
| if (tagName) { | ||
| html = ['<', tagName, '>', html, '</', tagName, '>'].join(''); | ||
| } | ||
| // because IE9 only supports MIME type 'text/xml', void elements need to be self-closed | ||
| if (isIE9) { | ||
| html = html.replace(VOID_ELEMENTS_REGEX, '<$1$2$3/>'); | ||
| } | ||
| return domParser.parseFromString(html, MIME_TYPE); | ||
| }; | ||
| // IE9 does not support 'text/html' MIME type | ||
| // https://msdn.microsoft.com/en-us/library/ff975278(v=vs.85).aspx | ||
| var mimeType = isIE9 ? 'text/xml' : 'text/html'; | ||
| /** | ||
| * Creates an HTML document using `DOMParser.parseFromString`. | ||
| * | ||
| * @param {string} html - The HTML string. | ||
| * @param {string} [tagName] - The element to render the HTML (with 'body' as fallback). | ||
| * @return {HTMLDocument} | ||
| */ | ||
| parseFromString = function domStringParser(html, tagName) { | ||
| if (tagName) { | ||
| html = '<' + tagName + '>' + html + '</' + tagName + '>'; | ||
| } | ||
| // because IE9 only supports MIME type 'text/xml', void elements need to be self-closed | ||
| if (isIE9) { | ||
| html = html.replace(VOID_ELEMENTS_REGEX, '<$1$2$3/>'); | ||
| } | ||
| return domParser.parseFromString(html, mimeType); | ||
| }; | ||
| } | ||
@@ -60,31 +56,36 @@ | ||
| * | ||
| * https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument | ||
| * @see https://developer.mozilla.org/docs/Web/API/DOMImplementation/createHTMLDocument | ||
| */ | ||
| var parseFromDocument; | ||
| if (typeof document.implementation === 'object') { | ||
| // 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); | ||
| // 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 | ||
| ); | ||
| /** | ||
| * Use HTML document created by `document.implementation.createHTMLDocument`. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @param {String} [tagName] - The element to render the HTML (with 'body' as fallback). | ||
| * @return {HTMLDocument} | ||
| */ | ||
| parseFromDocument = function createHTMLDocument(html, tagName) { | ||
| if (tagName) { | ||
| doc.documentElement.getElementsByTagName(tagName)[0].innerHTML = html; | ||
| return doc; | ||
| } | ||
| /** | ||
| * Use HTML document created by `document.implementation.createHTMLDocument`. | ||
| * | ||
| * @param {string} html - The HTML string. | ||
| * @param {string} [tagName] - The element to render the HTML (with 'body' as fallback). | ||
| * @return {HTMLDocument} | ||
| */ | ||
| parseFromDocument = function createHTMLDocument(html, tagName) { | ||
| if (tagName) { | ||
| doc.documentElement.getElementsByTagName(tagName)[0].innerHTML = html; | ||
| return doc; | ||
| } | ||
| try { | ||
| doc.documentElement.innerHTML = html; | ||
| return doc; | ||
| // fallback when certain elements in `documentElement` are read-only (IE9) | ||
| } catch (err) { | ||
| if (parseFromString) return parseFromString(html); | ||
| } | ||
| }; | ||
| try { | ||
| doc.documentElement.innerHTML = html; | ||
| return doc; | ||
| // fallback when certain elements in `documentElement` are read-only (IE9) | ||
| } catch (err) { | ||
| if (parseFromString) { | ||
| return parseFromString(html); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
@@ -95,21 +96,21 @@ | ||
| * | ||
| * https://developer.mozilla.org/docs/Web/HTML/Element/template | ||
| * @see https://developer.mozilla.org/docs/Web/HTML/Element/template | ||
| */ | ||
| var parseFromTemplate; | ||
| var template = document.createElement('template'); | ||
| if (template.content) { | ||
| /** | ||
| * Uses a template element (content fragment) to parse HTML. | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @return {NodeList} | ||
| */ | ||
| parseFromTemplate = function templateParser(html) { | ||
| template.innerHTML = html; | ||
| return template.content.childNodes; | ||
| }; | ||
| /** | ||
| * Uses a template element (content fragment) to parse HTML. | ||
| * | ||
| * @param {string} html - The HTML string. | ||
| * @return {NodeList} | ||
| */ | ||
| parseFromTemplate = function templateParser(html) { | ||
| template.innerHTML = html; | ||
| return template.content.childNodes; | ||
| }; | ||
| } | ||
| /** Fallback document parser. */ | ||
| // fallback document parser | ||
| var parseWithFallback = parseFromDocument || parseFromString; | ||
@@ -120,72 +121,73 @@ | ||
| * | ||
| * @param {String} html - The HTML string. | ||
| * @param {String} [tagName] - The tag name. | ||
| * @param {string} html - The HTML string. | ||
| * @return {NodeList|Array} | ||
| */ | ||
| module.exports = function domparser(html) { | ||
| // try to match first tag | ||
| var tagName; | ||
| var match = html.match(FIRST_TAG_REGEX); | ||
| if (match && match[1]) { | ||
| tagName = match[1].toLowerCase(); | ||
| } | ||
| function domparser(html) { | ||
| var firstTagName; | ||
| var match = html.match(FIRST_TAG_REGEX); | ||
| var doc; | ||
| var element; | ||
| var elements; | ||
| if (match && match[1]) { | ||
| firstTagName = match[1].toLowerCase(); | ||
| } | ||
| switch (tagName) { | ||
| case HTML_TAG_NAME: | ||
| if (parseFromString) { | ||
| doc = parseFromString(html); | ||
| var doc; | ||
| var element; | ||
| var elements; | ||
| // the created document may come with filler head/body elements, | ||
| // so ake sure to remove them if they don't actually exist | ||
| if (!HEAD_REGEX.test(html)) { | ||
| element = doc.getElementsByTagName(HEAD_TAG_NAME)[0]; | ||
| if (element) element.parentNode.removeChild(element); | ||
| } | ||
| if (!BODY_REGEX.test(html)) { | ||
| element = doc.getElementsByTagName(BODY_TAG_NAME)[0]; | ||
| if (element) element.parentNode.removeChild(element); | ||
| } | ||
| switch (firstTagName) { | ||
| case HTML: | ||
| if (parseFromString) { | ||
| doc = parseFromString(html); | ||
| return doc.getElementsByTagName(HTML_TAG_NAME); | ||
| } | ||
| break; | ||
| // 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); | ||
| } | ||
| } | ||
| case HEAD_TAG_NAME: | ||
| if (parseWithFallback) { | ||
| elements = parseWithFallback(html).getElementsByTagName(HEAD_TAG_NAME); | ||
| if (!BODY_TAG_REGEX.test(html)) { | ||
| element = doc.getElementsByTagName(BODY)[0]; | ||
| if (element) { | ||
| element.parentNode.removeChild(element); | ||
| } | ||
| } | ||
| // account for possibility of sibling | ||
| if (BODY_REGEX.test(html)) { | ||
| return elements[0].parentNode.childNodes; | ||
| } | ||
| return elements; | ||
| } | ||
| break; | ||
| return doc.getElementsByTagName(HTML); | ||
| } | ||
| break; | ||
| case BODY_TAG_NAME: | ||
| if (parseWithFallback) { | ||
| elements = parseWithFallback(html).getElementsByTagName(BODY_TAG_NAME); | ||
| case HEAD: | ||
| case BODY: | ||
| if (parseWithFallback) { | ||
| elements = parseWithFallback(html).getElementsByTagName(firstTagName); | ||
| // account for possibility of sibling (return both body and head) | ||
| if (HEAD_REGEX.test(html)) { | ||
| return elements[0].parentNode.childNodes; | ||
| } | ||
| return elements; | ||
| } | ||
| break; | ||
| // account for possibility of sibling | ||
| if (BODY_TAG_REGEX.test(html) && HEAD_TAG_REGEX.test(html)) { | ||
| return elements[0].parentNode.childNodes; | ||
| } | ||
| // low-level tag or text | ||
| default: | ||
| if (parseFromTemplate) return parseFromTemplate(html); | ||
| if (parseWithFallback) { | ||
| return parseWithFallback(html, BODY_TAG_NAME).getElementsByTagName(BODY_TAG_NAME)[0].childNodes; | ||
| } | ||
| break; | ||
| } | ||
| return elements; | ||
| } | ||
| break; | ||
| return []; | ||
| }; | ||
| // low-level tag or text | ||
| default: | ||
| if (parseFromTemplate) { | ||
| return parseFromTemplate(html); | ||
| } | ||
| if (parseWithFallback) { | ||
| return parseWithFallback(html, BODY).getElementsByTagName(BODY)[0] | ||
| .childNodes; | ||
| } | ||
| break; | ||
| } | ||
| return []; | ||
| } | ||
| module.exports = domparser; |
@@ -1,14 +0,7 @@ | ||
| 'use strict'; | ||
| /** | ||
| * Module dependencies. | ||
| */ | ||
| var domparser = require('./domparser'); | ||
| var utilities = require('./utilities'); | ||
| var formatDOM = utilities.formatDOM; | ||
| var isIE9 = utilities.isIE(9); | ||
| /** | ||
| * Constants. | ||
| */ | ||
| var DIRECTIVE_REGEX = /<(![a-zA-Z\s]+)>/; // e.g., <!doctype html> | ||
@@ -22,22 +15,28 @@ | ||
| */ | ||
| module.exports = function parseDOM(html) { | ||
| if (typeof html !== 'string') { | ||
| throw new TypeError('First argument must be a string.'); | ||
| } | ||
| if (!html) return []; | ||
| function parseDOM(html) { | ||
| if (typeof html !== 'string') { | ||
| throw new TypeError('First argument must be a string'); | ||
| } | ||
| // match directive | ||
| var match = html.match(DIRECTIVE_REGEX); | ||
| var directive; | ||
| if (match && match[1]) { | ||
| directive = match[1]; | ||
| if (!html) { | ||
| return []; | ||
| } | ||
| // remove directive in IE9 because DOMParser uses | ||
| // MIME type 'text/xml' instead of 'text/html' | ||
| if (isIE9) { | ||
| html = html.replace(match[0], ''); | ||
| } | ||
| // match directive | ||
| var match = html.match(DIRECTIVE_REGEX); | ||
| var directive; | ||
| if (match && match[1]) { | ||
| directive = match[1]; | ||
| // remove directive in IE9 because DOMParser uses | ||
| // MIME type 'text/xml' instead of 'text/html' | ||
| if (isIE9) { | ||
| html = html.replace(match[0], ''); | ||
| } | ||
| } | ||
| return formatDOM(domparser(html), null, directive); | ||
| }; | ||
| return formatDOM(domparser(html), null, directive); | ||
| } | ||
| module.exports = parseDOM; |
@@ -1,6 +0,1 @@ | ||
| 'use strict'; | ||
| /** | ||
| * Module dependencies. | ||
| */ | ||
| var Parser = require('htmlparser2/lib/Parser'); | ||
@@ -19,9 +14,11 @@ var DomHandler = require('domhandler'); | ||
| */ | ||
| module.exports = function parseDOM(html, options) { | ||
| if (typeof html !== 'string') { | ||
| throw new TypeError('First argument must be a string.'); | ||
| } | ||
| var handler = new DomHandler(options); | ||
| new Parser(handler, options).end(html); | ||
| return handler.dom; | ||
| }; | ||
| function parseDOM(html, options) { | ||
| if (typeof html !== 'string') { | ||
| throw new TypeError('First argument must be a string.'); | ||
| } | ||
| var handler = new DomHandler(options); | ||
| new Parser(handler, options).end(html); | ||
| return handler.dom; | ||
| } | ||
| module.exports = parseDOM; |
+92
-99
@@ -1,3 +0,1 @@ | ||
| 'use strict'; | ||
| var CASE_SENSITIVE_TAG_NAMES = require('./constants').CASE_SENSITIVE_TAG_NAMES; | ||
@@ -8,4 +6,4 @@ | ||
| for (var i = 0, len = CASE_SENSITIVE_TAG_NAMES.length; i < len; i++) { | ||
| tagName = CASE_SENSITIVE_TAG_NAMES[i]; | ||
| caseSensitiveTagNamesMap[tagName.toLowerCase()] = tagName; | ||
| tagName = CASE_SENSITIVE_TAG_NAMES[i]; | ||
| caseSensitiveTagNamesMap[tagName.toLowerCase()] = tagName; | ||
| } | ||
@@ -20,3 +18,3 @@ | ||
| function getCaseSensitiveTagName(tagName) { | ||
| return caseSensitiveTagNamesMap[tagName]; | ||
| return caseSensitiveTagNamesMap[tagName]; | ||
| } | ||
@@ -31,10 +29,10 @@ | ||
| function formatAttributes(attributes) { | ||
| var result = {}; | ||
| var attribute; | ||
| // `NamedNodeMap` is array-like | ||
| for (var i = 0, len = attributes.length; i < len; i++) { | ||
| attribute = attributes[i]; | ||
| result[attribute.name] = attribute.value; | ||
| } | ||
| return result; | ||
| var result = {}; | ||
| var attribute; | ||
| // `NamedNodeMap` is array-like | ||
| for (var i = 0, len = attributes.length; i < len; i++) { | ||
| attribute = attributes[i]; | ||
| result[attribute.name] = attribute.value; | ||
| } | ||
| return result; | ||
| } | ||
@@ -50,8 +48,8 @@ | ||
| function formatTagName(tagName) { | ||
| tagName = tagName.toLowerCase(); | ||
| var caseSensitiveTagName = getCaseSensitiveTagName(tagName); | ||
| if (caseSensitiveTagName) { | ||
| return caseSensitiveTagName; | ||
| } | ||
| return tagName; | ||
| tagName = tagName.toLowerCase(); | ||
| var caseSensitiveTagName = getCaseSensitiveTagName(tagName); | ||
| if (caseSensitiveTagName) { | ||
| return caseSensitiveTagName; | ||
| } | ||
| return tagName; | ||
| } | ||
@@ -68,83 +66,81 @@ | ||
| function formatDOM(nodes, parentObj, directive) { | ||
| parentObj = parentObj || null; | ||
| parentObj = parentObj || null; | ||
| var result = []; | ||
| var node; | ||
| var prevNode; | ||
| var nodeObj; | ||
| var result = []; | ||
| var node; | ||
| var prevNode; | ||
| var nodeObj; | ||
| // `NodeList` is array-like | ||
| for (var i = 0, len = nodes.length; i < len; i++) { | ||
| node = nodes[i]; | ||
| // reset | ||
| nodeObj = { | ||
| next: null, | ||
| prev: result[i - 1] || null, | ||
| parent: parentObj | ||
| }; | ||
| // `NodeList` is array-like | ||
| for (var i = 0, len = nodes.length; i < len; i++) { | ||
| node = nodes[i]; | ||
| // reset | ||
| nodeObj = { | ||
| next: null, | ||
| prev: result[i - 1] || null, | ||
| parent: parentObj | ||
| }; | ||
| // set the next node for the previous node (if applicable) | ||
| prevNode = result[i - 1]; | ||
| if (prevNode) { | ||
| prevNode.next = nodeObj; | ||
| } | ||
| // set the next node for the previous node (if applicable) | ||
| prevNode = result[i - 1]; | ||
| if (prevNode) { | ||
| prevNode.next = nodeObj; | ||
| } | ||
| // set the node name if it's not "#text" or "#comment" | ||
| // e.g., "div" | ||
| if (node.nodeName[0] !== '#') { | ||
| nodeObj.name = formatTagName(node.nodeName); | ||
| // also, nodes of type "tag" have "attribs" | ||
| nodeObj.attribs = {}; // default | ||
| if (node.attributes && node.attributes.length) { | ||
| nodeObj.attribs = formatAttributes(node.attributes); | ||
| } | ||
| } | ||
| // set the node name if it's not "#text" or "#comment" | ||
| // e.g., "div" | ||
| if (node.nodeName[0] !== '#') { | ||
| nodeObj.name = formatTagName(node.nodeName); | ||
| // also, nodes of type "tag" have "attribs" | ||
| nodeObj.attribs = {}; // default | ||
| if (node.attributes && node.attributes.length) { | ||
| nodeObj.attribs = formatAttributes(node.attributes); | ||
| } | ||
| } | ||
| // set the node type | ||
| // e.g., "tag" | ||
| switch (node.nodeType) { | ||
| // 1 = element | ||
| case 1: | ||
| if (nodeObj.name === 'script' || nodeObj.name === 'style') { | ||
| nodeObj.type = nodeObj.name; | ||
| } else { | ||
| nodeObj.type = 'tag'; | ||
| } | ||
| // recursively format the children | ||
| nodeObj.children = formatDOM(node.childNodes, nodeObj); | ||
| break; | ||
| // 2 = attribute | ||
| // 3 = text | ||
| case 3: | ||
| nodeObj.type = 'text'; | ||
| nodeObj.data = node.nodeValue; | ||
| break; | ||
| // 8 = comment | ||
| case 8: | ||
| nodeObj.type = 'comment'; | ||
| nodeObj.data = node.nodeValue; | ||
| break; | ||
| default: | ||
| break; | ||
| // set the node type | ||
| // e.g., "tag" | ||
| switch (node.nodeType) { | ||
| // 1 = element | ||
| case 1: | ||
| if (nodeObj.name === 'script' || nodeObj.name === 'style') { | ||
| nodeObj.type = nodeObj.name; | ||
| } else { | ||
| nodeObj.type = 'tag'; | ||
| } | ||
| result.push(nodeObj); | ||
| // recursively format the children | ||
| nodeObj.children = formatDOM(node.childNodes, nodeObj); | ||
| break; | ||
| // 2 = attribute | ||
| // 3 = text | ||
| case 3: | ||
| nodeObj.type = 'text'; | ||
| nodeObj.data = node.nodeValue; | ||
| break; | ||
| // 8 = comment | ||
| case 8: | ||
| nodeObj.type = 'comment'; | ||
| nodeObj.data = node.nodeValue; | ||
| break; | ||
| } | ||
| if (directive) { | ||
| result.unshift({ | ||
| name: directive.substring(0, directive.indexOf(' ')).toLowerCase(), | ||
| data: directive, | ||
| type: 'directive', | ||
| next: result[0] ? result[0] : null, | ||
| prev: null, | ||
| parent: parentObj | ||
| }); | ||
| result.push(nodeObj); | ||
| } | ||
| if (result[1]) { | ||
| result[1].prev = result[0]; | ||
| } | ||
| if (directive) { | ||
| result.unshift({ | ||
| name: directive.substring(0, directive.indexOf(' ')).toLowerCase(), | ||
| data: directive, | ||
| type: 'directive', | ||
| next: result[0] ? result[0] : null, | ||
| prev: null, | ||
| parent: parentObj | ||
| }); | ||
| if (result[1]) { | ||
| result[1].prev = result[0]; | ||
| } | ||
| } | ||
| return result; | ||
| return result; | ||
| } | ||
@@ -159,15 +155,12 @@ | ||
| function isIE(version) { | ||
| if (version) { | ||
| return document.documentMode === version; | ||
| } | ||
| return /(MSIE |Trident\/|Edge\/)/.test(navigator.userAgent); | ||
| if (version) { | ||
| return document.documentMode === version; | ||
| } | ||
| return /(MSIE |Trident\/|Edge\/)/.test(navigator.userAgent); | ||
| } | ||
| /** | ||
| * Export utilities. | ||
| */ | ||
| module.exports = { | ||
| formatAttributes: formatAttributes, | ||
| formatDOM: formatDOM, | ||
| isIE: isIE | ||
| formatAttributes: formatAttributes, | ||
| formatDOM: formatDOM, | ||
| isIE: isIE | ||
| }; |
+55
-24
| { | ||
| "name": "html-dom-parser", | ||
| "version": "0.2.2", | ||
| "description": "An HTML to DOM parser that works on the server and client.", | ||
| "version": "0.2.3", | ||
| "description": "HTML to DOM parser.", | ||
| "author": "Mark <mark@remarkablemark.org>", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "build": "npm run build:min && npm run build:unmin", | ||
| "build:min": "webpack index.js dist/html-dom-parser.min.js -p --output-library HTMLDOMParser --output-library-target umd", | ||
| "build:unmin": "webpack index.js dist/html-dom-parser.js --output-library HTMLDOMParser --output-library-target umd", | ||
| "build": "run-s build:*", | ||
| "build:min": "webpack index.js -o dist/html-dom-parser.min.js --mode production --output-library HTMLDOMParser --output-library-target umd", | ||
| "build:unmin": "webpack index.js -o dist/html-dom-parser.js --mode development --output-library HTMLDOMParser --output-library-target umd", | ||
| "clean": "rm -rf dist", | ||
| "test": "mocha", | ||
| "coveralls": "nyc report --reporter=text-lcov | coveralls", | ||
| "dtslint": "dtslint .", | ||
| "lint": "eslint . --ignore-path .gitignore", | ||
| "dtslint": "dtslint .", | ||
| "cover": "istanbul cover _mocha -- -R spec", | ||
| "coveralls": "cat coverage/lcov.info | coveralls", | ||
| "prepublish": "npm run clean && npm run build", | ||
| "release": "standard-version --no-verify" | ||
| "lint:fix": "npm run lint -- --fix", | ||
| "prepublishOnly": "run-s lint dtslint test clean build", | ||
| "release": "standard-version --no-verify", | ||
| "test": "run-s test:server test:client", | ||
| "test:client": "npm run test:client:watch -- --single-run", | ||
| "test:client:build": "webpack node_modules/htmlparser2/lib/index.js -o dist/htmlparser2.js --mode production --output-library htmlparser2 --output-library-target umd", | ||
| "test:client:setup": "test -f dist/htmlparser2.js || npm run test:client:build", | ||
| "test:client:watch": "npm run test:client:setup && karma start", | ||
| "test:server": "mocha test/server", | ||
| "test:server:coverage": "nyc npm run test:server", | ||
| "test:server:coverage:report": "nyc report --reporter=html" | ||
| }, | ||
@@ -28,24 +35,48 @@ "repository": { | ||
| "keywords": [ | ||
| "html-dom-parser", | ||
| "html", | ||
| "dom", | ||
| "parser", | ||
| "htmlparser2" | ||
| "htmlparser2", | ||
| "pojo" | ||
| ], | ||
| "dependencies": { | ||
| "@types/domhandler": "2.4.1", | ||
| "domhandler": "2.3.0", | ||
| "htmlparser2": "3.9.1" | ||
| "domhandler": "2.4.2", | ||
| "htmlparser2": "3.10.1" | ||
| }, | ||
| "devDependencies": { | ||
| "chai": "^3.5.0", | ||
| "coveralls": "^2.11.14", | ||
| "dtslint": "^0.5.9", | ||
| "eslint": "^3.4.0", | ||
| "html-minifier": "^3.1.0", | ||
| "istanbul": "^0.4.5", | ||
| "jsdomify": "^3.1.0", | ||
| "mocha": "^3.4.2", | ||
| "standard-version": "^5.0.2", | ||
| "webpack": "^2.6.1" | ||
| "@commitlint/cli": "^8.2.0", | ||
| "@commitlint/config-conventional": "^8.2.0", | ||
| "chai": "^4.2.0", | ||
| "coveralls": "^3.0.7", | ||
| "dtslint": "^1.0.2", | ||
| "eslint": "^6.6.0", | ||
| "eslint-plugin-prettier": "^3.1.1", | ||
| "html-minifier": "^4.0.0", | ||
| "husky": "^3.0.9", | ||
| "jsdomify": "^3.1.1", | ||
| "karma": "^4.4.1", | ||
| "karma-chai": "^0.1.0", | ||
| "karma-chrome-launcher": "^3.1.0", | ||
| "karma-commonjs": "^1.0.0", | ||
| "karma-mocha": "^1.3.0", | ||
| "karma-mocha-reporter": "^2.2.5", | ||
| "karma-phantomjs-launcher": "^1.0.4", | ||
| "lint-staged": "^9.4.2", | ||
| "mocha": "^6.2.2", | ||
| "mock-require": "^3.0.3", | ||
| "npm-run-all": "^4.1.5", | ||
| "nyc": "^14.1.1", | ||
| "prettier": "^1.18.2", | ||
| "sinon": "^7.5.0", | ||
| "standard-version": "^6", | ||
| "webpack": "^4.41.2", | ||
| "webpack-cli": "^3.3.10" | ||
| }, | ||
| "files": [ | ||
| "/dist", | ||
| "/index.d.ts", | ||
| "/lib" | ||
| ], | ||
| "browser": { | ||
@@ -52,0 +83,0 @@ "./index.js": "./lib/html-to-dom-client.js" |
+86
-19
@@ -9,4 +9,5 @@ # html-dom-parser | ||
| [](https://david-dm.org/remarkablemark/html-dom-parser) | ||
| [](https://www.npmjs.com/package/html-dom-parser) | ||
| An HTML to DOM parser that works on both the server and the browser: | ||
| HTML to DOM parser that works on both the server (Node.js) and the client (browser): | ||
@@ -17,6 +18,30 @@ ``` | ||
| The parser converts an HTML string to a JavaScript object that describes the DOM tree. | ||
| It converts an HTML string to a JavaScript object that describes the DOM tree. | ||
| [repl.it](https://repl.it/@remarkablemark/html-dom-parser) | [JSFiddle](https://jsfiddle.net/remarkablemark/ff9yg1yz/) | ||
| #### Example: | ||
| ```js | ||
| var parse = require('html-dom-parser'); | ||
| parse('<div>text</div>'); | ||
| ``` | ||
| Output: | ||
| ``` | ||
| [ { type: 'tag', | ||
| name: 'div', | ||
| attribs: {}, | ||
| children: | ||
| [ { data: 'text', | ||
| type: 'text', | ||
| next: null, | ||
| prev: null, | ||
| parent: [Circular] } ], | ||
| next: null, | ||
| prev: null, | ||
| parent: null } ] | ||
| ``` | ||
| [Repl.it](https://repl.it/@remarkablemark/html-dom-parser) | [JSFiddle](https://jsfiddle.net/remarkablemark/ff9yg1yz/) | [Examples](https://github.com/remarkablemark/html-dom-parser/tree/master/examples) | ||
| ## Installation | ||
@@ -36,3 +61,3 @@ | ||
| [unpkg](https://unpkg.com/html-dom-parser/) (CDN): | ||
| [CDN](https://unpkg.com/html-dom-parser/): | ||
@@ -48,26 +73,26 @@ ```html | ||
| Import parser: | ||
| Import the module: | ||
| ```js | ||
| // server | ||
| var parser = require('html-dom-parser'); | ||
| // CommonJS | ||
| var parse = require('html-dom-parser'); | ||
| // client | ||
| var parser = window.HTMLDOMParser; | ||
| // ES Modules | ||
| import parse from 'html-dom-parser'; | ||
| ``` | ||
| Parse input: | ||
| Parse markup: | ||
| ```js | ||
| parser('<p>Hello, world!</p>'); | ||
| parse('<p class="primary" style="color: skyblue;">Hello world</p>'); | ||
| ``` | ||
| Get output: | ||
| Output: | ||
| ```js | ||
| ``` | ||
| [ { type: 'tag', | ||
| name: 'p', | ||
| attribs: {}, | ||
| attribs: { class: 'primary', style: 'color: skyblue;' }, | ||
| children: | ||
| [ { data: 'Hello, world!', | ||
| [ { data: 'Hello world', | ||
| type: 'text', | ||
@@ -82,16 +107,58 @@ next: null, | ||
| On the server-side (Node.js), the parser is a wrapper of `parseDOM` from [htmlparser2](https://github.com/fb55/htmlparser2). | ||
| The _server parser_ is a wrapper of [htmlparser2](https://github.com/fb55/htmlparser2)'s `parseDOM`; the _client parser_ mimics the server parser by using the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) API. | ||
| On the client-side (browser), the parser uses the [DOM](https://developer.mozilla.org/docs/Web/API/Document_Object_Model/Introduction) API to mimic the output schema of the server parser. | ||
| ## Testing | ||
| Run server and client tests: | ||
| ```sh | ||
| $ npm test | ||
| $ npm run lint # npm run lint:fix | ||
| ``` | ||
| Run server tests with coverage: | ||
| ```sh | ||
| $ npm run test:server:coverage | ||
| # generate html report | ||
| $ npm run test:server:coverage:report | ||
| ``` | ||
| Run client tests: | ||
| ```sh | ||
| $ npm run test:client | ||
| ``` | ||
| Lint files: | ||
| ```sh | ||
| $ npm run lint | ||
| # fix lint errors | ||
| $ npm run lint:fix | ||
| ``` | ||
| Test TypeScript declaration file for style and correctness: | ||
| ```sh | ||
| $ npm run dtslint | ||
| ``` | ||
| ## Release | ||
| Only collaborators with credentials can release and publish: | ||
| ```sh | ||
| $ npm run release | ||
| $ git push --follow-tags && npm publish | ||
| ``` | ||
| ## Special Thanks | ||
| - [Contributors](https://github.com/remarkablemark/html-dom-parser/graphs/contributors) | ||
| - [htmlparser2](https://github.com/fb55/htmlparser2) | ||
| ## License | ||
| [MIT](https://github.com/remarkablemark/html-dom-parser/blob/master/LICENSE) |
| { | ||
| "compilerOptions": { | ||
| "module": "commonjs", | ||
| "lib": ["es6", "dom"], | ||
| "noImplicitAny": true, | ||
| "noImplicitThis": true, | ||
| "strictNullChecks": true, | ||
| "strictFunctionTypes": true, | ||
| "baseUrl": ".", | ||
| "noEmit": true, | ||
| "forceConsistentCasingInFileNames": true, | ||
| "paths": { "html-dom-parser": ["."], "html-dom-parser/lib/*": ["./lib/*"] } | ||
| }, | ||
| "files": [ | ||
| "index.d.ts", | ||
| "lib/domparser.d.ts", | ||
| "lib/html-to-dom-client.d.ts", | ||
| "lib/html-to-dom-server.d.ts", | ||
| "lib/utilities.d.ts", | ||
| "test/types/index.test.ts" | ||
| ] | ||
| } |
| { | ||
| "extends": "dtslint/dtslint.json" | ||
| } |
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
48118
9.48%160
72.04%27
170%18
-10%635
-36.5%4
100%4
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated