| 
									
										
										
										
											2019-07-19 20:35:53 +02:00
										 |  |  | /*eslint-env es6:false*/ | 
					
						
							|  |  |  | /* This Source Code Form is subject to the terms of the Mozilla Public | 
					
						
							|  |  |  |  * License, v. 2.0. If a copy of the MPL was not distributed with this file, | 
					
						
							|  |  |  |  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * This is a relatively lightweight DOMParser that is safe to use in a web | 
					
						
							|  |  |  |  * worker. This is far from a complete DOM implementation; however, it should | 
					
						
							|  |  |  |  * contain the minimal set of functionality necessary for Readability.js. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Aside from not implementing the full DOM API, there are other quirks to be | 
					
						
							|  |  |  |  * aware of when using the JSDOMParser: | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   1) Properly formed HTML/XML must be used. This means you should be extra | 
					
						
							|  |  |  |  *      careful when using this parser on anything received directly from an | 
					
						
							|  |  |  |  *      XMLHttpRequest. Providing a serialized string from an XMLSerializer, | 
					
						
							|  |  |  |  *      however, should be safe (since the browser's XMLSerializer should | 
					
						
							|  |  |  |  *      generate valid HTML/XML). Therefore, if parsing a document from an XHR, | 
					
						
							|  |  |  |  *      the recommended approach is to do the XHR in the main thread, use | 
					
						
							|  |  |  |  *      XMLSerializer.serializeToString() on the responseXML, and pass the | 
					
						
							|  |  |  |  *      resulting string to the worker. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  *   2) Live NodeLists are not supported. DOM methods and properties such as | 
					
						
							|  |  |  |  *      getElementsByTagName() and childNodes return standard arrays. If you | 
					
						
							|  |  |  |  *      want these lists to be updated when nodes are removed or added to the | 
					
						
							|  |  |  |  *      document, you must take care to manually update them yourself. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | (function (global) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // XML only defines these and the numeric ones:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var entityTable = { | 
					
						
							|  |  |  |     "lt": "<", | 
					
						
							|  |  |  |     "gt": ">", | 
					
						
							|  |  |  |     "amp": "&", | 
					
						
							|  |  |  |     "quot": '"', | 
					
						
							|  |  |  |     "apos": "'", | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var reverseEntityTable = { | 
					
						
							|  |  |  |     "<": "<", | 
					
						
							|  |  |  |     ">": ">", | 
					
						
							|  |  |  |     "&": "&", | 
					
						
							|  |  |  |     '"': """, | 
					
						
							|  |  |  |     "'": "'", | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function encodeTextContentHTML(s) { | 
					
						
							|  |  |  |     return s.replace(/[&<>]/g, function(x) { | 
					
						
							|  |  |  |       return reverseEntityTable[x]; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function encodeHTML(s) { | 
					
						
							|  |  |  |     return s.replace(/[&<>'"]/g, function(x) { | 
					
						
							|  |  |  |       return reverseEntityTable[x]; | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function decodeHTML(str) { | 
					
						
							|  |  |  |     return str.replace(/&(quot|amp|apos|lt|gt);/g, function(match, tag) { | 
					
						
							|  |  |  |       return entityTable[tag]; | 
					
						
							|  |  |  |     }).replace(/&#(?:x([0-9a-z]{1,4})|([0-9]{1,4}));/gi, function(match, hex, numStr) { | 
					
						
							|  |  |  |       var num = parseInt(hex || numStr, hex ? 16 : 10); // read num
 | 
					
						
							|  |  |  |       return String.fromCharCode(num); | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // When a style is set in JS, map it to the corresponding CSS attribute
 | 
					
						
							|  |  |  |   var styleMap = { | 
					
						
							|  |  |  |     "alignmentBaseline": "alignment-baseline", | 
					
						
							|  |  |  |     "background": "background", | 
					
						
							|  |  |  |     "backgroundAttachment": "background-attachment", | 
					
						
							|  |  |  |     "backgroundClip": "background-clip", | 
					
						
							|  |  |  |     "backgroundColor": "background-color", | 
					
						
							|  |  |  |     "backgroundImage": "background-image", | 
					
						
							|  |  |  |     "backgroundOrigin": "background-origin", | 
					
						
							|  |  |  |     "backgroundPosition": "background-position", | 
					
						
							|  |  |  |     "backgroundPositionX": "background-position-x", | 
					
						
							|  |  |  |     "backgroundPositionY": "background-position-y", | 
					
						
							|  |  |  |     "backgroundRepeat": "background-repeat", | 
					
						
							|  |  |  |     "backgroundRepeatX": "background-repeat-x", | 
					
						
							|  |  |  |     "backgroundRepeatY": "background-repeat-y", | 
					
						
							|  |  |  |     "backgroundSize": "background-size", | 
					
						
							|  |  |  |     "baselineShift": "baseline-shift", | 
					
						
							|  |  |  |     "border": "border", | 
					
						
							|  |  |  |     "borderBottom": "border-bottom", | 
					
						
							|  |  |  |     "borderBottomColor": "border-bottom-color", | 
					
						
							|  |  |  |     "borderBottomLeftRadius": "border-bottom-left-radius", | 
					
						
							|  |  |  |     "borderBottomRightRadius": "border-bottom-right-radius", | 
					
						
							|  |  |  |     "borderBottomStyle": "border-bottom-style", | 
					
						
							|  |  |  |     "borderBottomWidth": "border-bottom-width", | 
					
						
							|  |  |  |     "borderCollapse": "border-collapse", | 
					
						
							|  |  |  |     "borderColor": "border-color", | 
					
						
							|  |  |  |     "borderImage": "border-image", | 
					
						
							|  |  |  |     "borderImageOutset": "border-image-outset", | 
					
						
							|  |  |  |     "borderImageRepeat": "border-image-repeat", | 
					
						
							|  |  |  |     "borderImageSlice": "border-image-slice", | 
					
						
							|  |  |  |     "borderImageSource": "border-image-source", | 
					
						
							|  |  |  |     "borderImageWidth": "border-image-width", | 
					
						
							|  |  |  |     "borderLeft": "border-left", | 
					
						
							|  |  |  |     "borderLeftColor": "border-left-color", | 
					
						
							|  |  |  |     "borderLeftStyle": "border-left-style", | 
					
						
							|  |  |  |     "borderLeftWidth": "border-left-width", | 
					
						
							|  |  |  |     "borderRadius": "border-radius", | 
					
						
							|  |  |  |     "borderRight": "border-right", | 
					
						
							|  |  |  |     "borderRightColor": "border-right-color", | 
					
						
							|  |  |  |     "borderRightStyle": "border-right-style", | 
					
						
							|  |  |  |     "borderRightWidth": "border-right-width", | 
					
						
							|  |  |  |     "borderSpacing": "border-spacing", | 
					
						
							|  |  |  |     "borderStyle": "border-style", | 
					
						
							|  |  |  |     "borderTop": "border-top", | 
					
						
							|  |  |  |     "borderTopColor": "border-top-color", | 
					
						
							|  |  |  |     "borderTopLeftRadius": "border-top-left-radius", | 
					
						
							|  |  |  |     "borderTopRightRadius": "border-top-right-radius", | 
					
						
							|  |  |  |     "borderTopStyle": "border-top-style", | 
					
						
							|  |  |  |     "borderTopWidth": "border-top-width", | 
					
						
							|  |  |  |     "borderWidth": "border-width", | 
					
						
							|  |  |  |     "bottom": "bottom", | 
					
						
							|  |  |  |     "boxShadow": "box-shadow", | 
					
						
							|  |  |  |     "boxSizing": "box-sizing", | 
					
						
							|  |  |  |     "captionSide": "caption-side", | 
					
						
							|  |  |  |     "clear": "clear", | 
					
						
							|  |  |  |     "clip": "clip", | 
					
						
							|  |  |  |     "clipPath": "clip-path", | 
					
						
							|  |  |  |     "clipRule": "clip-rule", | 
					
						
							|  |  |  |     "color": "color", | 
					
						
							|  |  |  |     "colorInterpolation": "color-interpolation", | 
					
						
							|  |  |  |     "colorInterpolationFilters": "color-interpolation-filters", | 
					
						
							|  |  |  |     "colorProfile": "color-profile", | 
					
						
							|  |  |  |     "colorRendering": "color-rendering", | 
					
						
							|  |  |  |     "content": "content", | 
					
						
							|  |  |  |     "counterIncrement": "counter-increment", | 
					
						
							|  |  |  |     "counterReset": "counter-reset", | 
					
						
							|  |  |  |     "cursor": "cursor", | 
					
						
							|  |  |  |     "direction": "direction", | 
					
						
							|  |  |  |     "display": "display", | 
					
						
							|  |  |  |     "dominantBaseline": "dominant-baseline", | 
					
						
							|  |  |  |     "emptyCells": "empty-cells", | 
					
						
							|  |  |  |     "enableBackground": "enable-background", | 
					
						
							|  |  |  |     "fill": "fill", | 
					
						
							|  |  |  |     "fillOpacity": "fill-opacity", | 
					
						
							|  |  |  |     "fillRule": "fill-rule", | 
					
						
							|  |  |  |     "filter": "filter", | 
					
						
							|  |  |  |     "cssFloat": "float", | 
					
						
							|  |  |  |     "floodColor": "flood-color", | 
					
						
							|  |  |  |     "floodOpacity": "flood-opacity", | 
					
						
							|  |  |  |     "font": "font", | 
					
						
							|  |  |  |     "fontFamily": "font-family", | 
					
						
							|  |  |  |     "fontSize": "font-size", | 
					
						
							|  |  |  |     "fontStretch": "font-stretch", | 
					
						
							|  |  |  |     "fontStyle": "font-style", | 
					
						
							|  |  |  |     "fontVariant": "font-variant", | 
					
						
							|  |  |  |     "fontWeight": "font-weight", | 
					
						
							|  |  |  |     "glyphOrientationHorizontal": "glyph-orientation-horizontal", | 
					
						
							|  |  |  |     "glyphOrientationVertical": "glyph-orientation-vertical", | 
					
						
							|  |  |  |     "height": "height", | 
					
						
							|  |  |  |     "imageRendering": "image-rendering", | 
					
						
							|  |  |  |     "kerning": "kerning", | 
					
						
							|  |  |  |     "left": "left", | 
					
						
							|  |  |  |     "letterSpacing": "letter-spacing", | 
					
						
							|  |  |  |     "lightingColor": "lighting-color", | 
					
						
							|  |  |  |     "lineHeight": "line-height", | 
					
						
							|  |  |  |     "listStyle": "list-style", | 
					
						
							|  |  |  |     "listStyleImage": "list-style-image", | 
					
						
							|  |  |  |     "listStylePosition": "list-style-position", | 
					
						
							|  |  |  |     "listStyleType": "list-style-type", | 
					
						
							|  |  |  |     "margin": "margin", | 
					
						
							|  |  |  |     "marginBottom": "margin-bottom", | 
					
						
							|  |  |  |     "marginLeft": "margin-left", | 
					
						
							|  |  |  |     "marginRight": "margin-right", | 
					
						
							|  |  |  |     "marginTop": "margin-top", | 
					
						
							|  |  |  |     "marker": "marker", | 
					
						
							|  |  |  |     "markerEnd": "marker-end", | 
					
						
							|  |  |  |     "markerMid": "marker-mid", | 
					
						
							|  |  |  |     "markerStart": "marker-start", | 
					
						
							|  |  |  |     "mask": "mask", | 
					
						
							|  |  |  |     "maxHeight": "max-height", | 
					
						
							|  |  |  |     "maxWidth": "max-width", | 
					
						
							|  |  |  |     "minHeight": "min-height", | 
					
						
							|  |  |  |     "minWidth": "min-width", | 
					
						
							|  |  |  |     "opacity": "opacity", | 
					
						
							|  |  |  |     "orphans": "orphans", | 
					
						
							|  |  |  |     "outline": "outline", | 
					
						
							|  |  |  |     "outlineColor": "outline-color", | 
					
						
							|  |  |  |     "outlineOffset": "outline-offset", | 
					
						
							|  |  |  |     "outlineStyle": "outline-style", | 
					
						
							|  |  |  |     "outlineWidth": "outline-width", | 
					
						
							|  |  |  |     "overflow": "overflow", | 
					
						
							|  |  |  |     "overflowX": "overflow-x", | 
					
						
							|  |  |  |     "overflowY": "overflow-y", | 
					
						
							|  |  |  |     "padding": "padding", | 
					
						
							|  |  |  |     "paddingBottom": "padding-bottom", | 
					
						
							|  |  |  |     "paddingLeft": "padding-left", | 
					
						
							|  |  |  |     "paddingRight": "padding-right", | 
					
						
							|  |  |  |     "paddingTop": "padding-top", | 
					
						
							|  |  |  |     "page": "page", | 
					
						
							|  |  |  |     "pageBreakAfter": "page-break-after", | 
					
						
							|  |  |  |     "pageBreakBefore": "page-break-before", | 
					
						
							|  |  |  |     "pageBreakInside": "page-break-inside", | 
					
						
							|  |  |  |     "pointerEvents": "pointer-events", | 
					
						
							|  |  |  |     "position": "position", | 
					
						
							|  |  |  |     "quotes": "quotes", | 
					
						
							|  |  |  |     "resize": "resize", | 
					
						
							|  |  |  |     "right": "right", | 
					
						
							|  |  |  |     "shapeRendering": "shape-rendering", | 
					
						
							|  |  |  |     "size": "size", | 
					
						
							|  |  |  |     "speak": "speak", | 
					
						
							|  |  |  |     "src": "src", | 
					
						
							|  |  |  |     "stopColor": "stop-color", | 
					
						
							|  |  |  |     "stopOpacity": "stop-opacity", | 
					
						
							|  |  |  |     "stroke": "stroke", | 
					
						
							|  |  |  |     "strokeDasharray": "stroke-dasharray", | 
					
						
							|  |  |  |     "strokeDashoffset": "stroke-dashoffset", | 
					
						
							|  |  |  |     "strokeLinecap": "stroke-linecap", | 
					
						
							|  |  |  |     "strokeLinejoin": "stroke-linejoin", | 
					
						
							|  |  |  |     "strokeMiterlimit": "stroke-miterlimit", | 
					
						
							|  |  |  |     "strokeOpacity": "stroke-opacity", | 
					
						
							|  |  |  |     "strokeWidth": "stroke-width", | 
					
						
							|  |  |  |     "tableLayout": "table-layout", | 
					
						
							|  |  |  |     "textAlign": "text-align", | 
					
						
							|  |  |  |     "textAnchor": "text-anchor", | 
					
						
							|  |  |  |     "textDecoration": "text-decoration", | 
					
						
							|  |  |  |     "textIndent": "text-indent", | 
					
						
							|  |  |  |     "textLineThrough": "text-line-through", | 
					
						
							|  |  |  |     "textLineThroughColor": "text-line-through-color", | 
					
						
							|  |  |  |     "textLineThroughMode": "text-line-through-mode", | 
					
						
							|  |  |  |     "textLineThroughStyle": "text-line-through-style", | 
					
						
							|  |  |  |     "textLineThroughWidth": "text-line-through-width", | 
					
						
							|  |  |  |     "textOverflow": "text-overflow", | 
					
						
							|  |  |  |     "textOverline": "text-overline", | 
					
						
							|  |  |  |     "textOverlineColor": "text-overline-color", | 
					
						
							|  |  |  |     "textOverlineMode": "text-overline-mode", | 
					
						
							|  |  |  |     "textOverlineStyle": "text-overline-style", | 
					
						
							|  |  |  |     "textOverlineWidth": "text-overline-width", | 
					
						
							|  |  |  |     "textRendering": "text-rendering", | 
					
						
							|  |  |  |     "textShadow": "text-shadow", | 
					
						
							|  |  |  |     "textTransform": "text-transform", | 
					
						
							|  |  |  |     "textUnderline": "text-underline", | 
					
						
							|  |  |  |     "textUnderlineColor": "text-underline-color", | 
					
						
							|  |  |  |     "textUnderlineMode": "text-underline-mode", | 
					
						
							|  |  |  |     "textUnderlineStyle": "text-underline-style", | 
					
						
							|  |  |  |     "textUnderlineWidth": "text-underline-width", | 
					
						
							|  |  |  |     "top": "top", | 
					
						
							|  |  |  |     "unicodeBidi": "unicode-bidi", | 
					
						
							|  |  |  |     "unicodeRange": "unicode-range", | 
					
						
							|  |  |  |     "vectorEffect": "vector-effect", | 
					
						
							|  |  |  |     "verticalAlign": "vertical-align", | 
					
						
							|  |  |  |     "visibility": "visibility", | 
					
						
							|  |  |  |     "whiteSpace": "white-space", | 
					
						
							|  |  |  |     "widows": "widows", | 
					
						
							|  |  |  |     "width": "width", | 
					
						
							|  |  |  |     "wordBreak": "word-break", | 
					
						
							|  |  |  |     "wordSpacing": "word-spacing", | 
					
						
							|  |  |  |     "wordWrap": "word-wrap", | 
					
						
							|  |  |  |     "writingMode": "writing-mode", | 
					
						
							|  |  |  |     "zIndex": "z-index", | 
					
						
							|  |  |  |     "zoom": "zoom", | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Elements that can be self-closing
 | 
					
						
							|  |  |  |   var voidElems = { | 
					
						
							|  |  |  |     "area": true, | 
					
						
							|  |  |  |     "base": true, | 
					
						
							|  |  |  |     "br": true, | 
					
						
							|  |  |  |     "col": true, | 
					
						
							|  |  |  |     "command": true, | 
					
						
							|  |  |  |     "embed": true, | 
					
						
							|  |  |  |     "hr": true, | 
					
						
							|  |  |  |     "img": true, | 
					
						
							|  |  |  |     "input": true, | 
					
						
							|  |  |  |     "link": true, | 
					
						
							|  |  |  |     "meta": true, | 
					
						
							|  |  |  |     "param": true, | 
					
						
							|  |  |  |     "source": true, | 
					
						
							|  |  |  |     "wbr": true | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var whitespace = [" ", "\t", "\n", "\r"]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-19 19:35:39 +01:00
										 |  |  |   // See https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType
 | 
					
						
							| 
									
										
										
										
											2019-07-19 20:35:53 +02:00
										 |  |  |   var nodeTypes = { | 
					
						
							|  |  |  |     ELEMENT_NODE: 1, | 
					
						
							|  |  |  |     ATTRIBUTE_NODE: 2, | 
					
						
							|  |  |  |     TEXT_NODE: 3, | 
					
						
							|  |  |  |     CDATA_SECTION_NODE: 4, | 
					
						
							|  |  |  |     ENTITY_REFERENCE_NODE: 5, | 
					
						
							|  |  |  |     ENTITY_NODE: 6, | 
					
						
							|  |  |  |     PROCESSING_INSTRUCTION_NODE: 7, | 
					
						
							|  |  |  |     COMMENT_NODE: 8, | 
					
						
							|  |  |  |     DOCUMENT_NODE: 9, | 
					
						
							|  |  |  |     DOCUMENT_TYPE_NODE: 10, | 
					
						
							|  |  |  |     DOCUMENT_FRAGMENT_NODE: 11, | 
					
						
							|  |  |  |     NOTATION_NODE: 12 | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   function getElementsByTagName(tag) { | 
					
						
							|  |  |  |     tag = tag.toUpperCase(); | 
					
						
							|  |  |  |     var elems = []; | 
					
						
							|  |  |  |     var allTags = (tag === "*"); | 
					
						
							|  |  |  |     function getElems(node) { | 
					
						
							|  |  |  |       var length = node.children.length; | 
					
						
							|  |  |  |       for (var i = 0; i < length; i++) { | 
					
						
							|  |  |  |         var child = node.children[i]; | 
					
						
							|  |  |  |         if (allTags || (child.tagName === tag)) | 
					
						
							|  |  |  |           elems.push(child); | 
					
						
							|  |  |  |         getElems(child); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     getElems(this); | 
					
						
							| 
									
										
										
										
											2020-04-02 22:49:27 +02:00
										 |  |  |     elems._isLiveNodeList = true; | 
					
						
							| 
									
										
										
										
											2019-07-19 20:35:53 +02:00
										 |  |  |     return elems; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Node = function () {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Node.prototype = { | 
					
						
							|  |  |  |     attributes: null, | 
					
						
							|  |  |  |     childNodes: null, | 
					
						
							|  |  |  |     localName: null, | 
					
						
							|  |  |  |     nodeName: null, | 
					
						
							|  |  |  |     parentNode: null, | 
					
						
							|  |  |  |     textContent: null, | 
					
						
							|  |  |  |     nextSibling: null, | 
					
						
							|  |  |  |     previousSibling: null, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get firstChild() { | 
					
						
							|  |  |  |       return this.childNodes[0] || null; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get firstElementChild() { | 
					
						
							|  |  |  |       return this.children[0] || null; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get lastChild() { | 
					
						
							|  |  |  |       return this.childNodes[this.childNodes.length - 1] || null; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get lastElementChild() { | 
					
						
							|  |  |  |       return this.children[this.children.length - 1] || null; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     appendChild: function (child) { | 
					
						
							|  |  |  |       if (child.parentNode) { | 
					
						
							|  |  |  |         child.parentNode.removeChild(child); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var last = this.lastChild; | 
					
						
							|  |  |  |       if (last) | 
					
						
							|  |  |  |         last.nextSibling = child; | 
					
						
							|  |  |  |       child.previousSibling = last; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (child.nodeType === Node.ELEMENT_NODE) { | 
					
						
							|  |  |  |         child.previousElementSibling = this.children[this.children.length - 1] || null; | 
					
						
							|  |  |  |         this.children.push(child); | 
					
						
							|  |  |  |         child.previousElementSibling && (child.previousElementSibling.nextElementSibling = child); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       this.childNodes.push(child); | 
					
						
							|  |  |  |       child.parentNode = this; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     removeChild: function (child) { | 
					
						
							|  |  |  |       var childNodes = this.childNodes; | 
					
						
							|  |  |  |       var childIndex = childNodes.indexOf(child); | 
					
						
							|  |  |  |       if (childIndex === -1) { | 
					
						
							|  |  |  |         throw "removeChild: node not found"; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         child.parentNode = null; | 
					
						
							|  |  |  |         var prev = child.previousSibling; | 
					
						
							|  |  |  |         var next = child.nextSibling; | 
					
						
							|  |  |  |         if (prev) | 
					
						
							|  |  |  |           prev.nextSibling = next; | 
					
						
							|  |  |  |         if (next) | 
					
						
							|  |  |  |           next.previousSibling = prev; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (child.nodeType === Node.ELEMENT_NODE) { | 
					
						
							|  |  |  |           prev = child.previousElementSibling; | 
					
						
							|  |  |  |           next = child.nextElementSibling; | 
					
						
							|  |  |  |           if (prev) | 
					
						
							|  |  |  |             prev.nextElementSibling = next; | 
					
						
							|  |  |  |           if (next) | 
					
						
							|  |  |  |             next.previousElementSibling = prev; | 
					
						
							|  |  |  |           this.children.splice(this.children.indexOf(child), 1); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         child.previousSibling = child.nextSibling = null; | 
					
						
							|  |  |  |         child.previousElementSibling = child.nextElementSibling = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return childNodes.splice(childIndex, 1)[0]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     replaceChild: function (newNode, oldNode) { | 
					
						
							|  |  |  |       var childNodes = this.childNodes; | 
					
						
							|  |  |  |       var childIndex = childNodes.indexOf(oldNode); | 
					
						
							|  |  |  |       if (childIndex === -1) { | 
					
						
							|  |  |  |         throw "replaceChild: node not found"; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         // This will take care of updating the new node if it was somewhere else before:
 | 
					
						
							|  |  |  |         if (newNode.parentNode) | 
					
						
							|  |  |  |           newNode.parentNode.removeChild(newNode); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         childNodes[childIndex] = newNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // update the new node's sibling properties, and its new siblings' sibling properties
 | 
					
						
							|  |  |  |         newNode.nextSibling = oldNode.nextSibling; | 
					
						
							|  |  |  |         newNode.previousSibling = oldNode.previousSibling; | 
					
						
							|  |  |  |         if (newNode.nextSibling) | 
					
						
							|  |  |  |           newNode.nextSibling.previousSibling = newNode; | 
					
						
							|  |  |  |         if (newNode.previousSibling) | 
					
						
							|  |  |  |           newNode.previousSibling.nextSibling = newNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         newNode.parentNode = this; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Now deal with elements before we clear out those values for the old node,
 | 
					
						
							|  |  |  |         // because it can help us take shortcuts here:
 | 
					
						
							|  |  |  |         if (newNode.nodeType === Node.ELEMENT_NODE) { | 
					
						
							|  |  |  |           if (oldNode.nodeType === Node.ELEMENT_NODE) { | 
					
						
							|  |  |  |             // Both were elements, which makes this easier, we just swap things out:
 | 
					
						
							|  |  |  |             newNode.previousElementSibling = oldNode.previousElementSibling; | 
					
						
							|  |  |  |             newNode.nextElementSibling = oldNode.nextElementSibling; | 
					
						
							|  |  |  |             if (newNode.previousElementSibling) | 
					
						
							|  |  |  |               newNode.previousElementSibling.nextElementSibling = newNode; | 
					
						
							|  |  |  |             if (newNode.nextElementSibling) | 
					
						
							|  |  |  |               newNode.nextElementSibling.previousElementSibling = newNode; | 
					
						
							|  |  |  |             this.children[this.children.indexOf(oldNode)] = newNode; | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             // Hard way:
 | 
					
						
							|  |  |  |             newNode.previousElementSibling = (function() { | 
					
						
							|  |  |  |               for (var i = childIndex - 1; i >= 0; i--) { | 
					
						
							|  |  |  |                 if (childNodes[i].nodeType === Node.ELEMENT_NODE) | 
					
						
							|  |  |  |                   return childNodes[i]; | 
					
						
							|  |  |  |               } | 
					
						
							|  |  |  |               return null; | 
					
						
							|  |  |  |             })(); | 
					
						
							|  |  |  |             if (newNode.previousElementSibling) { | 
					
						
							|  |  |  |               newNode.nextElementSibling = newNode.previousElementSibling.nextElementSibling; | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |               newNode.nextElementSibling = (function() { | 
					
						
							|  |  |  |                 for (var i = childIndex + 1; i < childNodes.length; i++) { | 
					
						
							|  |  |  |                   if (childNodes[i].nodeType === Node.ELEMENT_NODE) | 
					
						
							|  |  |  |                     return childNodes[i]; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return null; | 
					
						
							|  |  |  |               })(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (newNode.previousElementSibling) | 
					
						
							|  |  |  |               newNode.previousElementSibling.nextElementSibling = newNode; | 
					
						
							|  |  |  |             if (newNode.nextElementSibling) | 
					
						
							|  |  |  |               newNode.nextElementSibling.previousElementSibling = newNode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (newNode.nextElementSibling) | 
					
						
							|  |  |  |               this.children.splice(this.children.indexOf(newNode.nextElementSibling), 0, newNode); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |               this.children.push(newNode); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } else if (oldNode.nodeType === Node.ELEMENT_NODE) { | 
					
						
							|  |  |  |           // new node is not an element node.
 | 
					
						
							|  |  |  |           // if the old one was, update its element siblings:
 | 
					
						
							|  |  |  |           if (oldNode.previousElementSibling) | 
					
						
							|  |  |  |             oldNode.previousElementSibling.nextElementSibling = oldNode.nextElementSibling; | 
					
						
							|  |  |  |           if (oldNode.nextElementSibling) | 
					
						
							|  |  |  |             oldNode.nextElementSibling.previousElementSibling = oldNode.previousElementSibling; | 
					
						
							|  |  |  |           this.children.splice(this.children.indexOf(oldNode), 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           // If the old node wasn't an element, neither the new nor the old node was an element,
 | 
					
						
							|  |  |  |           // and the children array and its members shouldn't need any updating.
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         oldNode.parentNode = null; | 
					
						
							|  |  |  |         oldNode.previousSibling = null; | 
					
						
							|  |  |  |         oldNode.nextSibling = null; | 
					
						
							|  |  |  |         if (oldNode.nodeType === Node.ELEMENT_NODE) { | 
					
						
							|  |  |  |           oldNode.previousElementSibling = null; | 
					
						
							|  |  |  |           oldNode.nextElementSibling = null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return oldNode; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __JSDOMParser__: true, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   for (var nodeType in nodeTypes) { | 
					
						
							|  |  |  |     Node[nodeType] = Node.prototype[nodeType] = nodeTypes[nodeType]; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Attribute = function (name, value) { | 
					
						
							|  |  |  |     this.name = name; | 
					
						
							|  |  |  |     this._value = value; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Attribute.prototype = { | 
					
						
							|  |  |  |     get value() { | 
					
						
							|  |  |  |       return this._value; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     setValue: function(newValue) { | 
					
						
							|  |  |  |       this._value = newValue; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     getEncodedValue: function() { | 
					
						
							|  |  |  |       return encodeHTML(this._value); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Comment = function () { | 
					
						
							|  |  |  |     this.childNodes = []; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Comment.prototype = { | 
					
						
							|  |  |  |     __proto__: Node.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nodeName: "#comment", | 
					
						
							|  |  |  |     nodeType: Node.COMMENT_NODE | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Text = function () { | 
					
						
							|  |  |  |     this.childNodes = []; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Text.prototype = { | 
					
						
							|  |  |  |     __proto__: Node.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nodeName: "#text", | 
					
						
							|  |  |  |     nodeType: Node.TEXT_NODE, | 
					
						
							|  |  |  |     get textContent() { | 
					
						
							|  |  |  |       if (typeof this._textContent === "undefined") { | 
					
						
							|  |  |  |         this._textContent = decodeHTML(this._innerHTML || ""); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return this._textContent; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     get innerHTML() { | 
					
						
							|  |  |  |       if (typeof this._innerHTML === "undefined") { | 
					
						
							|  |  |  |         this._innerHTML = encodeTextContentHTML(this._textContent || ""); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return this._innerHTML; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set innerHTML(newHTML) { | 
					
						
							|  |  |  |       this._innerHTML = newHTML; | 
					
						
							|  |  |  |       delete this._textContent; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     set textContent(newText) { | 
					
						
							|  |  |  |       this._textContent = newText; | 
					
						
							|  |  |  |       delete this._innerHTML; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Document = function (url) { | 
					
						
							|  |  |  |     this.documentURI = url; | 
					
						
							|  |  |  |     this.styleSheets = []; | 
					
						
							|  |  |  |     this.childNodes = []; | 
					
						
							|  |  |  |     this.children = []; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Document.prototype = { | 
					
						
							|  |  |  |     __proto__: Node.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nodeName: "#document", | 
					
						
							|  |  |  |     nodeType: Node.DOCUMENT_NODE, | 
					
						
							|  |  |  |     title: "", | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getElementsByTagName: getElementsByTagName, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getElementById: function (id) { | 
					
						
							|  |  |  |       function getElem(node) { | 
					
						
							|  |  |  |         var length = node.children.length; | 
					
						
							|  |  |  |         if (node.id === id) | 
					
						
							|  |  |  |           return node; | 
					
						
							|  |  |  |         for (var i = 0; i < length; i++) { | 
					
						
							|  |  |  |           var el = getElem(node.children[i]); | 
					
						
							|  |  |  |           if (el) | 
					
						
							|  |  |  |             return el; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return getElem(this); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     createElement: function (tag) { | 
					
						
							|  |  |  |       var node = new Element(tag); | 
					
						
							|  |  |  |       return node; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     createTextNode: function (text) { | 
					
						
							|  |  |  |       var node = new Text(); | 
					
						
							|  |  |  |       node.textContent = text; | 
					
						
							|  |  |  |       return node; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get baseURI() { | 
					
						
							|  |  |  |       if (!this.hasOwnProperty("_baseURI")) { | 
					
						
							|  |  |  |         this._baseURI = this.documentURI; | 
					
						
							|  |  |  |         var baseElements = this.getElementsByTagName("base"); | 
					
						
							|  |  |  |         var href = baseElements[0] && baseElements[0].getAttribute("href"); | 
					
						
							|  |  |  |         if (href) { | 
					
						
							|  |  |  |           try { | 
					
						
							|  |  |  |             this._baseURI = (new URL(href, this._baseURI)).href; | 
					
						
							|  |  |  |           } catch (ex) {/* Just fall back to documentURI */} | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return this._baseURI; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Element = function (tag) { | 
					
						
							|  |  |  |     // We use this to find the closing tag.
 | 
					
						
							|  |  |  |     this._matchingTag = tag; | 
					
						
							|  |  |  |     // We're explicitly a non-namespace aware parser, we just pretend it's all HTML.
 | 
					
						
							|  |  |  |     var lastColonIndex = tag.lastIndexOf(":"); | 
					
						
							|  |  |  |     if (lastColonIndex != -1) { | 
					
						
							|  |  |  |       tag = tag.substring(lastColonIndex + 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     this.attributes = []; | 
					
						
							|  |  |  |     this.childNodes = []; | 
					
						
							|  |  |  |     this.children = []; | 
					
						
							|  |  |  |     this.nextElementSibling = this.previousElementSibling = null; | 
					
						
							|  |  |  |     this.localName = tag.toLowerCase(); | 
					
						
							|  |  |  |     this.tagName = tag.toUpperCase(); | 
					
						
							|  |  |  |     this.style = new Style(this); | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Element.prototype = { | 
					
						
							|  |  |  |     __proto__: Node.prototype, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     nodeType: Node.ELEMENT_NODE, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getElementsByTagName: getElementsByTagName, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get className() { | 
					
						
							|  |  |  |       return this.getAttribute("class") || ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set className(str) { | 
					
						
							|  |  |  |       this.setAttribute("class", str); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get id() { | 
					
						
							|  |  |  |       return this.getAttribute("id") || ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set id(str) { | 
					
						
							|  |  |  |       this.setAttribute("id", str); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get href() { | 
					
						
							|  |  |  |       return this.getAttribute("href") || ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set href(str) { | 
					
						
							|  |  |  |       this.setAttribute("href", str); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get src() { | 
					
						
							|  |  |  |       return this.getAttribute("src") || ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set src(str) { | 
					
						
							|  |  |  |       this.setAttribute("src", str); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get srcset() { | 
					
						
							|  |  |  |       return this.getAttribute("srcset") || ""; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set srcset(str) { | 
					
						
							|  |  |  |       this.setAttribute("srcset", str); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get nodeName() { | 
					
						
							|  |  |  |       return this.tagName; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get innerHTML() { | 
					
						
							|  |  |  |       function getHTML(node) { | 
					
						
							|  |  |  |         var i = 0; | 
					
						
							|  |  |  |         for (i = 0; i < node.childNodes.length; i++) { | 
					
						
							|  |  |  |           var child = node.childNodes[i]; | 
					
						
							|  |  |  |           if (child.localName) { | 
					
						
							|  |  |  |             arr.push("<" + child.localName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // serialize attribute list
 | 
					
						
							|  |  |  |             for (var j = 0; j < child.attributes.length; j++) { | 
					
						
							|  |  |  |               var attr = child.attributes[j]; | 
					
						
							|  |  |  |               // the attribute value will be HTML escaped.
 | 
					
						
							|  |  |  |               var val = attr.getEncodedValue(); | 
					
						
							|  |  |  |               var quote = (val.indexOf('"') === -1 ? '"' : "'"); | 
					
						
							|  |  |  |               arr.push(" " + attr.name + "=" + quote + val + quote); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (child.localName in voidElems && !child.childNodes.length) { | 
					
						
							|  |  |  |               // if this is a self-closing element, end it here
 | 
					
						
							|  |  |  |               arr.push("/>"); | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |               // otherwise, add its children
 | 
					
						
							|  |  |  |               arr.push(">"); | 
					
						
							|  |  |  |               getHTML(child); | 
					
						
							|  |  |  |               arr.push("</" + child.localName + ">"); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             // This is a text node, so asking for innerHTML won't recurse.
 | 
					
						
							|  |  |  |             arr.push(child.innerHTML); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Using Array.join() avoids the overhead from lazy string concatenation.
 | 
					
						
							|  |  |  |       var arr = []; | 
					
						
							|  |  |  |       getHTML(this); | 
					
						
							|  |  |  |       return arr.join(""); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set innerHTML(html) { | 
					
						
							|  |  |  |       var parser = new JSDOMParser(); | 
					
						
							|  |  |  |       var node = parser.parse(html); | 
					
						
							|  |  |  |       var i; | 
					
						
							|  |  |  |       for (i = this.childNodes.length; --i >= 0;) { | 
					
						
							|  |  |  |         this.childNodes[i].parentNode = null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       this.childNodes = node.childNodes; | 
					
						
							|  |  |  |       this.children = node.children; | 
					
						
							|  |  |  |       for (i = this.childNodes.length; --i >= 0;) { | 
					
						
							|  |  |  |         this.childNodes[i].parentNode = this; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     set textContent(text) { | 
					
						
							|  |  |  |       // clear parentNodes for existing children
 | 
					
						
							|  |  |  |       for (var i = this.childNodes.length; --i >= 0;) { | 
					
						
							|  |  |  |         this.childNodes[i].parentNode = null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var node = new Text(); | 
					
						
							|  |  |  |       this.childNodes = [ node ]; | 
					
						
							|  |  |  |       this.children = []; | 
					
						
							|  |  |  |       node.textContent = text; | 
					
						
							|  |  |  |       node.parentNode = this; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get textContent() { | 
					
						
							|  |  |  |       function getText(node) { | 
					
						
							|  |  |  |         var nodes = node.childNodes; | 
					
						
							|  |  |  |         for (var i = 0; i < nodes.length; i++) { | 
					
						
							|  |  |  |           var child = nodes[i]; | 
					
						
							|  |  |  |           if (child.nodeType === 3) { | 
					
						
							|  |  |  |             text.push(child.textContent); | 
					
						
							|  |  |  |           } else { | 
					
						
							|  |  |  |             getText(child); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Using Array.join() avoids the overhead from lazy string concatenation.
 | 
					
						
							|  |  |  |       // See http://blog.cdleary.com/2012/01/string-representation-in-spidermonkey/#ropes
 | 
					
						
							|  |  |  |       var text = []; | 
					
						
							|  |  |  |       getText(this); | 
					
						
							|  |  |  |       return text.join(""); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     getAttribute: function (name) { | 
					
						
							|  |  |  |       for (var i = this.attributes.length; --i >= 0;) { | 
					
						
							|  |  |  |         var attr = this.attributes[i]; | 
					
						
							|  |  |  |         if (attr.name === name) { | 
					
						
							|  |  |  |           return attr.value; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return undefined; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setAttribute: function (name, value) { | 
					
						
							|  |  |  |       for (var i = this.attributes.length; --i >= 0;) { | 
					
						
							|  |  |  |         var attr = this.attributes[i]; | 
					
						
							|  |  |  |         if (attr.name === name) { | 
					
						
							|  |  |  |           attr.setValue(value); | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       this.attributes.push(new Attribute(name, value)); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     removeAttribute: function (name) { | 
					
						
							|  |  |  |       for (var i = this.attributes.length; --i >= 0;) { | 
					
						
							|  |  |  |         var attr = this.attributes[i]; | 
					
						
							|  |  |  |         if (attr.name === name) { | 
					
						
							|  |  |  |           this.attributes.splice(i, 1); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     hasAttribute: function (name) { | 
					
						
							|  |  |  |       return this.attributes.some(function (attr) { | 
					
						
							|  |  |  |         return attr.name == name; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var Style = function (node) { | 
					
						
							|  |  |  |     this.node = node; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // getStyle() and setStyle() use the style attribute string directly. This
 | 
					
						
							|  |  |  |   // won't be very efficient if there are a lot of style manipulations, but
 | 
					
						
							|  |  |  |   // it's the easiest way to make sure the style attribute string and the JS
 | 
					
						
							|  |  |  |   // style property stay in sync. Readability.js doesn't do many style
 | 
					
						
							|  |  |  |   // manipulations, so this should be okay.
 | 
					
						
							|  |  |  |   Style.prototype = { | 
					
						
							|  |  |  |     getStyle: function (styleName) { | 
					
						
							|  |  |  |       var attr = this.node.getAttribute("style"); | 
					
						
							|  |  |  |       if (!attr) | 
					
						
							|  |  |  |         return undefined; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var styles = attr.split(";"); | 
					
						
							|  |  |  |       for (var i = 0; i < styles.length; i++) { | 
					
						
							|  |  |  |         var style = styles[i].split(":"); | 
					
						
							|  |  |  |         var name = style[0].trim(); | 
					
						
							|  |  |  |         if (name === styleName) | 
					
						
							|  |  |  |           return style[1].trim(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return undefined; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setStyle: function (styleName, styleValue) { | 
					
						
							|  |  |  |       var value = this.node.getAttribute("style") || ""; | 
					
						
							|  |  |  |       var index = 0; | 
					
						
							|  |  |  |       do { | 
					
						
							|  |  |  |         var next = value.indexOf(";", index) + 1; | 
					
						
							|  |  |  |         var length = next - index - 1; | 
					
						
							|  |  |  |         var style = (length > 0 ? value.substr(index, length) : value.substr(index)); | 
					
						
							|  |  |  |         if (style.substr(0, style.indexOf(":")).trim() === styleName) { | 
					
						
							|  |  |  |           value = value.substr(0, index).trim() + (next ? " " + value.substr(next).trim() : ""); | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         index = next; | 
					
						
							|  |  |  |       } while (index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       value += " " + styleName + ": " + styleValue + ";"; | 
					
						
							|  |  |  |       this.node.setAttribute("style", value.trim()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // For each item in styleMap, define a getter and setter on the style
 | 
					
						
							|  |  |  |   // property.
 | 
					
						
							|  |  |  |   for (var jsName in styleMap) { | 
					
						
							|  |  |  |     (function (cssName) { | 
					
						
							|  |  |  |       Style.prototype.__defineGetter__(jsName, function () { | 
					
						
							|  |  |  |         return this.getStyle(cssName); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       Style.prototype.__defineSetter__(jsName, function (value) { | 
					
						
							|  |  |  |         this.setStyle(cssName, value); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     })(styleMap[jsName]); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   var JSDOMParser = function () { | 
					
						
							|  |  |  |     this.currentChar = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // In makeElementNode() we build up many strings one char at a time. Using
 | 
					
						
							|  |  |  |     // += for this results in lots of short-lived intermediate strings. It's
 | 
					
						
							|  |  |  |     // better to build an array of single-char strings and then join() them
 | 
					
						
							|  |  |  |     // together at the end. And reusing a single array (i.e. |this.strBuf|)
 | 
					
						
							|  |  |  |     // over and over for this purpose uses less memory than using a new array
 | 
					
						
							|  |  |  |     // for each string.
 | 
					
						
							|  |  |  |     this.strBuf = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Similarly, we reuse this array to return the two arguments from
 | 
					
						
							|  |  |  |     // makeElementNode(), which saves us from having to allocate a new array
 | 
					
						
							|  |  |  |     // every time.
 | 
					
						
							|  |  |  |     this.retPair = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     this.errorState = ""; | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   JSDOMParser.prototype = { | 
					
						
							|  |  |  |     error: function(m) { | 
					
						
							| 
									
										
										
										
											2022-02-19 19:35:39 +01:00
										 |  |  |       if (typeof dump !== "undefined") { | 
					
						
							|  |  |  |         dump("JSDOMParser error: " + m + "\n"); | 
					
						
							|  |  |  |       } else if (typeof console !== "undefined") { | 
					
						
							|  |  |  |         console.log("JSDOMParser error: " + m + "\n"); | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2019-07-19 20:35:53 +02:00
										 |  |  |       this.errorState += m + "\n"; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Look at the next character without advancing the index. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     peekNext: function () { | 
					
						
							|  |  |  |       return this.html[this.currentChar]; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the next character and advance the index. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     nextChar: function () { | 
					
						
							|  |  |  |       return this.html[this.currentChar++]; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Called after a quote character is read. This finds the next quote | 
					
						
							|  |  |  |      * character and returns the text string in between. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     readString: function (quote) { | 
					
						
							|  |  |  |       var str; | 
					
						
							|  |  |  |       var n = this.html.indexOf(quote, this.currentChar); | 
					
						
							|  |  |  |       if (n === -1) { | 
					
						
							|  |  |  |         this.currentChar = this.html.length; | 
					
						
							|  |  |  |         str = null; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         str = this.html.substring(this.currentChar, n); | 
					
						
							|  |  |  |         this.currentChar = n + 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return str; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Called when parsing a node. This finds the next name/value attribute | 
					
						
							|  |  |  |      * pair and adds the result to the attributes list. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     readAttribute: function (node) { | 
					
						
							|  |  |  |       var name = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var n = this.html.indexOf("=", this.currentChar); | 
					
						
							|  |  |  |       if (n === -1) { | 
					
						
							|  |  |  |         this.currentChar = this.html.length; | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         // Read until a '=' character is hit; this will be the attribute key
 | 
					
						
							|  |  |  |         name = this.html.substring(this.currentChar, n); | 
					
						
							|  |  |  |         this.currentChar = n + 1; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!name) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // After a '=', we should see a '"' for the attribute value
 | 
					
						
							|  |  |  |       var c = this.nextChar(); | 
					
						
							|  |  |  |       if (c !== '"' && c !== "'") { | 
					
						
							|  |  |  |         this.error("Error reading attribute " + name + ", expecting '\"'"); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Read the attribute value (and consume the matching quote)
 | 
					
						
							|  |  |  |       var value = this.readString(c); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       node.attributes.push(new Attribute(name, decodeHTML(value))); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Parses and returns an Element node. This is called after a '<' has been | 
					
						
							|  |  |  |      * read. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @returns an array; the first index of the array is the parsed node; | 
					
						
							|  |  |  |      *          the second index is a boolean indicating whether this is a void | 
					
						
							|  |  |  |      *          Element | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     makeElementNode: function (retPair) { | 
					
						
							|  |  |  |       var c = this.nextChar(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Read the Element tag name
 | 
					
						
							|  |  |  |       var strBuf = this.strBuf; | 
					
						
							|  |  |  |       strBuf.length = 0; | 
					
						
							|  |  |  |       while (whitespace.indexOf(c) == -1 && c !== ">" && c !== "/") { | 
					
						
							|  |  |  |         if (c === undefined) | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  |         strBuf.push(c); | 
					
						
							|  |  |  |         c = this.nextChar(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       var tag = strBuf.join(""); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!tag) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var node = new Element(tag); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Read Element attributes
 | 
					
						
							|  |  |  |       while (c !== "/" && c !== ">") { | 
					
						
							|  |  |  |         if (c === undefined) | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  |         while (whitespace.indexOf(this.html[this.currentChar++]) != -1) { | 
					
						
							|  |  |  |           // Advance cursor to first non-whitespace char.
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         this.currentChar--; | 
					
						
							|  |  |  |         c = this.nextChar(); | 
					
						
							|  |  |  |         if (c !== "/" && c !== ">") { | 
					
						
							|  |  |  |           --this.currentChar; | 
					
						
							|  |  |  |           this.readAttribute(node); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // If this is a self-closing tag, read '/>'
 | 
					
						
							|  |  |  |       var closed = false; | 
					
						
							|  |  |  |       if (c === "/") { | 
					
						
							|  |  |  |         closed = true; | 
					
						
							|  |  |  |         c = this.nextChar(); | 
					
						
							|  |  |  |         if (c !== ">") { | 
					
						
							|  |  |  |           this.error("expected '>' to close " + tag); | 
					
						
							|  |  |  |           return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       retPair[0] = node; | 
					
						
							|  |  |  |       retPair[1] = closed; | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * If the current input matches this string, advance the input index; | 
					
						
							|  |  |  |      * otherwise, do nothing. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @returns whether input matched string | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     match: function (str) { | 
					
						
							|  |  |  |       var strlen = str.length; | 
					
						
							|  |  |  |       if (this.html.substr(this.currentChar, strlen).toLowerCase() === str.toLowerCase()) { | 
					
						
							|  |  |  |         this.currentChar += strlen; | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return false; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Searches the input until a string is found and discards all input up to | 
					
						
							|  |  |  |      * and including the matched string. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     discardTo: function (str) { | 
					
						
							|  |  |  |       var index = this.html.indexOf(str, this.currentChar) + str.length; | 
					
						
							|  |  |  |       if (index === -1) | 
					
						
							|  |  |  |         this.currentChar = this.html.length; | 
					
						
							|  |  |  |       this.currentChar = index; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Reads child nodes for the given node. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     readChildren: function (node) { | 
					
						
							|  |  |  |       var child; | 
					
						
							|  |  |  |       while ((child = this.readNode())) { | 
					
						
							|  |  |  |         // Don't keep Comment nodes
 | 
					
						
							|  |  |  |         if (child.nodeType !== 8) { | 
					
						
							|  |  |  |           node.appendChild(child); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     discardNextComment: function() { | 
					
						
							|  |  |  |       if (this.match("--")) { | 
					
						
							|  |  |  |         this.discardTo("-->"); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         var c = this.nextChar(); | 
					
						
							|  |  |  |         while (c !== ">") { | 
					
						
							|  |  |  |           if (c === undefined) | 
					
						
							|  |  |  |             return null; | 
					
						
							|  |  |  |           if (c === '"' || c === "'") | 
					
						
							|  |  |  |             this.readString(c); | 
					
						
							|  |  |  |           c = this.nextChar(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return new Comment(); | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Reads the next child node from the input. If we're reading a closing | 
					
						
							|  |  |  |      * tag, or if we've reached the end of input, return null. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @returns the node | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     readNode: function () { | 
					
						
							|  |  |  |       var c = this.nextChar(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (c === undefined) | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Read any text as Text node
 | 
					
						
							|  |  |  |       var textNode; | 
					
						
							|  |  |  |       if (c !== "<") { | 
					
						
							|  |  |  |         --this.currentChar; | 
					
						
							|  |  |  |         textNode = new Text(); | 
					
						
							|  |  |  |         var n = this.html.indexOf("<", this.currentChar); | 
					
						
							|  |  |  |         if (n === -1) { | 
					
						
							|  |  |  |           textNode.innerHTML = this.html.substring(this.currentChar, this.html.length); | 
					
						
							|  |  |  |           this.currentChar = this.html.length; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           textNode.innerHTML = this.html.substring(this.currentChar, n); | 
					
						
							|  |  |  |           this.currentChar = n; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return textNode; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (this.match("![CDATA[")) { | 
					
						
							|  |  |  |         var endChar = this.html.indexOf("]]>", this.currentChar); | 
					
						
							|  |  |  |         if (endChar === -1) { | 
					
						
							|  |  |  |           this.error("unclosed CDATA section"); | 
					
						
							|  |  |  |           return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         textNode = new Text(); | 
					
						
							|  |  |  |         textNode.textContent = this.html.substring(this.currentChar, endChar); | 
					
						
							|  |  |  |         this.currentChar = endChar + ("]]>").length; | 
					
						
							|  |  |  |         return textNode; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       c = this.peekNext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Read Comment node. Normally, Comment nodes know their inner
 | 
					
						
							|  |  |  |       // textContent, but we don't really care about Comment nodes (we throw
 | 
					
						
							|  |  |  |       // them away in readChildren()). So just returning an empty Comment node
 | 
					
						
							|  |  |  |       // here is sufficient.
 | 
					
						
							|  |  |  |       if (c === "!" || c === "?") { | 
					
						
							|  |  |  |         // We're still before the ! or ? that is starting this comment:
 | 
					
						
							|  |  |  |         this.currentChar++; | 
					
						
							|  |  |  |         return this.discardNextComment(); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // If we're reading a closing tag, return null. This means we've reached
 | 
					
						
							|  |  |  |       // the end of this set of child nodes.
 | 
					
						
							|  |  |  |       if (c === "/") { | 
					
						
							|  |  |  |         --this.currentChar; | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Otherwise, we're looking at an Element node
 | 
					
						
							|  |  |  |       var result = this.makeElementNode(this.retPair); | 
					
						
							|  |  |  |       if (!result) | 
					
						
							|  |  |  |         return null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       var node = this.retPair[0]; | 
					
						
							|  |  |  |       var closed = this.retPair[1]; | 
					
						
							|  |  |  |       var localName = node.localName; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // If this isn't a void Element, read its child nodes
 | 
					
						
							|  |  |  |       if (!closed) { | 
					
						
							|  |  |  |         this.readChildren(node); | 
					
						
							|  |  |  |         var closingTag = "</" + node._matchingTag + ">"; | 
					
						
							|  |  |  |         if (!this.match(closingTag)) { | 
					
						
							|  |  |  |           this.error("expected '" + closingTag + "' and got " + this.html.substr(this.currentChar, closingTag.length)); | 
					
						
							|  |  |  |           return null; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Only use the first title, because SVG might have other
 | 
					
						
							|  |  |  |       // title elements which we don't care about (medium.com
 | 
					
						
							|  |  |  |       // does this, at least).
 | 
					
						
							|  |  |  |       if (localName === "title" && !this.doc.title) { | 
					
						
							|  |  |  |         this.doc.title = node.textContent.trim(); | 
					
						
							|  |  |  |       } else if (localName === "head") { | 
					
						
							|  |  |  |         this.doc.head = node; | 
					
						
							|  |  |  |       } else if (localName === "body") { | 
					
						
							|  |  |  |         this.doc.body = node; | 
					
						
							|  |  |  |       } else if (localName === "html") { | 
					
						
							|  |  |  |         this.doc.documentElement = node; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return node; | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Parses an HTML string and returns a JS implementation of the Document. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     parse: function (html, url) { | 
					
						
							|  |  |  |       this.html = html; | 
					
						
							|  |  |  |       var doc = this.doc = new Document(url); | 
					
						
							|  |  |  |       this.readChildren(doc); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // If this is an HTML document, remove root-level children except for the
 | 
					
						
							|  |  |  |       // <html> node
 | 
					
						
							|  |  |  |       if (doc.documentElement) { | 
					
						
							|  |  |  |         for (var i = doc.childNodes.length; --i >= 0;) { | 
					
						
							|  |  |  |           var child = doc.childNodes[i]; | 
					
						
							|  |  |  |           if (child !== doc.documentElement) { | 
					
						
							|  |  |  |             doc.removeChild(child); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       return doc; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Attach the standard DOM types to the global scope
 | 
					
						
							|  |  |  |   global.Node = Node; | 
					
						
							|  |  |  |   global.Comment = Comment; | 
					
						
							|  |  |  |   global.Document = Document; | 
					
						
							|  |  |  |   global.Element = Element; | 
					
						
							|  |  |  |   global.Text = Text; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Attach JSDOMParser to the global scope
 | 
					
						
							|  |  |  |   global.JSDOMParser = JSDOMParser; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | })(this); | 
					
						
							| 
									
										
										
										
											2022-02-19 19:35:39 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | if (typeof module === "object") { | 
					
						
							|  |  |  |   module.exports = this.JSDOMParser; | 
					
						
							|  |  |  | } |