4823 lines
294 KiB
JavaScript
4823 lines
294 KiB
JavaScript
|
|
/*!
|
|||
|
|
Stencil Mock Doc v2.22.3 | MIT Licensed | https://stenciljs.com
|
|||
|
|
*/
|
|||
|
|
const CONTENT_REF_ID = 'r';
|
|||
|
|
const ORG_LOCATION_ID = 'o';
|
|||
|
|
const SLOT_NODE_ID = 's';
|
|||
|
|
const TEXT_NODE_ID = 't';
|
|||
|
|
const XLINK_NS = 'http://www.w3.org/1999/xlink';
|
|||
|
|
|
|||
|
|
const attrHandler = {
|
|||
|
|
get(obj, prop) {
|
|||
|
|
if (prop in obj) {
|
|||
|
|
return obj[prop];
|
|||
|
|
}
|
|||
|
|
if (typeof prop !== 'symbol' && !isNaN(prop)) {
|
|||
|
|
return obj.__items[prop];
|
|||
|
|
}
|
|||
|
|
return undefined;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
const createAttributeProxy = (caseInsensitive) => new Proxy(new MockAttributeMap(caseInsensitive), attrHandler);
|
|||
|
|
class MockAttributeMap {
|
|||
|
|
constructor(caseInsensitive = false) {
|
|||
|
|
this.caseInsensitive = caseInsensitive;
|
|||
|
|
this.__items = [];
|
|||
|
|
}
|
|||
|
|
get length() {
|
|||
|
|
return this.__items.length;
|
|||
|
|
}
|
|||
|
|
item(index) {
|
|||
|
|
return this.__items[index] || null;
|
|||
|
|
}
|
|||
|
|
setNamedItem(attr) {
|
|||
|
|
attr.namespaceURI = null;
|
|||
|
|
this.setNamedItemNS(attr);
|
|||
|
|
}
|
|||
|
|
setNamedItemNS(attr) {
|
|||
|
|
if (attr != null && attr.value != null) {
|
|||
|
|
attr.value = String(attr.value);
|
|||
|
|
}
|
|||
|
|
const existingAttr = this.__items.find((a) => a.name === attr.name && a.namespaceURI === attr.namespaceURI);
|
|||
|
|
if (existingAttr != null) {
|
|||
|
|
existingAttr.value = attr.value;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.__items.push(attr);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
getNamedItem(attrName) {
|
|||
|
|
if (this.caseInsensitive) {
|
|||
|
|
attrName = attrName.toLowerCase();
|
|||
|
|
}
|
|||
|
|
return this.getNamedItemNS(null, attrName);
|
|||
|
|
}
|
|||
|
|
getNamedItemNS(namespaceURI, attrName) {
|
|||
|
|
namespaceURI = getNamespaceURI(namespaceURI);
|
|||
|
|
return (this.__items.find((attr) => attr.name === attrName && getNamespaceURI(attr.namespaceURI) === namespaceURI) || null);
|
|||
|
|
}
|
|||
|
|
removeNamedItem(attr) {
|
|||
|
|
this.removeNamedItemNS(attr);
|
|||
|
|
}
|
|||
|
|
removeNamedItemNS(attr) {
|
|||
|
|
for (let i = 0, ii = this.__items.length; i < ii; i++) {
|
|||
|
|
if (this.__items[i].name === attr.name && this.__items[i].namespaceURI === attr.namespaceURI) {
|
|||
|
|
this.__items.splice(i, 1);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
[Symbol.iterator]() {
|
|||
|
|
let i = 0;
|
|||
|
|
return {
|
|||
|
|
next: () => ({
|
|||
|
|
done: i === this.length,
|
|||
|
|
value: this.item(i++),
|
|||
|
|
}),
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
get [Symbol.toStringTag]() {
|
|||
|
|
return 'MockAttributeMap';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getNamespaceURI(namespaceURI) {
|
|||
|
|
return namespaceURI === XLINK_NS ? null : namespaceURI;
|
|||
|
|
}
|
|||
|
|
function cloneAttributes(srcAttrs, sortByName = false) {
|
|||
|
|
const dstAttrs = new MockAttributeMap(srcAttrs.caseInsensitive);
|
|||
|
|
if (srcAttrs != null) {
|
|||
|
|
const attrLen = srcAttrs.length;
|
|||
|
|
if (sortByName && attrLen > 1) {
|
|||
|
|
const sortedAttrs = [];
|
|||
|
|
for (let i = 0; i < attrLen; i++) {
|
|||
|
|
const srcAttr = srcAttrs.item(i);
|
|||
|
|
const dstAttr = new MockAttr(srcAttr.name, srcAttr.value, srcAttr.namespaceURI);
|
|||
|
|
sortedAttrs.push(dstAttr);
|
|||
|
|
}
|
|||
|
|
sortedAttrs.sort(sortAttributes).forEach((attr) => {
|
|||
|
|
dstAttrs.setNamedItemNS(attr);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
for (let i = 0; i < attrLen; i++) {
|
|||
|
|
const srcAttr = srcAttrs.item(i);
|
|||
|
|
const dstAttr = new MockAttr(srcAttr.name, srcAttr.value, srcAttr.namespaceURI);
|
|||
|
|
dstAttrs.setNamedItemNS(dstAttr);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return dstAttrs;
|
|||
|
|
}
|
|||
|
|
function sortAttributes(a, b) {
|
|||
|
|
if (a.name < b.name)
|
|||
|
|
return -1;
|
|||
|
|
if (a.name > b.name)
|
|||
|
|
return 1;
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
class MockAttr {
|
|||
|
|
constructor(attrName, attrValue, namespaceURI = null) {
|
|||
|
|
this._name = attrName;
|
|||
|
|
this._value = String(attrValue);
|
|||
|
|
this._namespaceURI = namespaceURI;
|
|||
|
|
}
|
|||
|
|
get name() {
|
|||
|
|
return this._name;
|
|||
|
|
}
|
|||
|
|
set name(value) {
|
|||
|
|
this._name = value;
|
|||
|
|
}
|
|||
|
|
get value() {
|
|||
|
|
return this._value;
|
|||
|
|
}
|
|||
|
|
set value(value) {
|
|||
|
|
this._value = String(value);
|
|||
|
|
}
|
|||
|
|
get nodeName() {
|
|||
|
|
return this._name;
|
|||
|
|
}
|
|||
|
|
set nodeName(value) {
|
|||
|
|
this._name = value;
|
|||
|
|
}
|
|||
|
|
get nodeValue() {
|
|||
|
|
return this._value;
|
|||
|
|
}
|
|||
|
|
set nodeValue(value) {
|
|||
|
|
this._value = String(value);
|
|||
|
|
}
|
|||
|
|
get namespaceURI() {
|
|||
|
|
return this._namespaceURI;
|
|||
|
|
}
|
|||
|
|
set namespaceURI(namespaceURI) {
|
|||
|
|
this._namespaceURI = namespaceURI;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockClassList {
|
|||
|
|
constructor(elm) {
|
|||
|
|
this.elm = elm;
|
|||
|
|
}
|
|||
|
|
add(...classNames) {
|
|||
|
|
const clsNames = getItems(this.elm);
|
|||
|
|
let updated = false;
|
|||
|
|
classNames.forEach((className) => {
|
|||
|
|
className = String(className);
|
|||
|
|
validateClass(className);
|
|||
|
|
if (clsNames.includes(className) === false) {
|
|||
|
|
clsNames.push(className);
|
|||
|
|
updated = true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (updated) {
|
|||
|
|
this.elm.setAttributeNS(null, 'class', clsNames.join(' '));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
remove(...classNames) {
|
|||
|
|
const clsNames = getItems(this.elm);
|
|||
|
|
let updated = false;
|
|||
|
|
classNames.forEach((className) => {
|
|||
|
|
className = String(className);
|
|||
|
|
validateClass(className);
|
|||
|
|
const index = clsNames.indexOf(className);
|
|||
|
|
if (index > -1) {
|
|||
|
|
clsNames.splice(index, 1);
|
|||
|
|
updated = true;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
if (updated) {
|
|||
|
|
this.elm.setAttributeNS(null, 'class', clsNames.filter((c) => c.length > 0).join(' '));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
contains(className) {
|
|||
|
|
className = String(className);
|
|||
|
|
return getItems(this.elm).includes(className);
|
|||
|
|
}
|
|||
|
|
toggle(className) {
|
|||
|
|
className = String(className);
|
|||
|
|
if (this.contains(className) === true) {
|
|||
|
|
this.remove(className);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.add(className);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get length() {
|
|||
|
|
return getItems(this.elm).length;
|
|||
|
|
}
|
|||
|
|
item(index) {
|
|||
|
|
return getItems(this.elm)[index];
|
|||
|
|
}
|
|||
|
|
toString() {
|
|||
|
|
return getItems(this.elm).join(' ');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function validateClass(className) {
|
|||
|
|
if (className === '') {
|
|||
|
|
throw new Error('The token provided must not be empty.');
|
|||
|
|
}
|
|||
|
|
if (/\s/.test(className)) {
|
|||
|
|
throw new Error(`The token provided ('${className}') contains HTML space characters, which are not valid in tokens.`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getItems(elm) {
|
|||
|
|
const className = elm.getAttribute('class');
|
|||
|
|
if (typeof className === 'string' && className.length > 0) {
|
|||
|
|
return className
|
|||
|
|
.trim()
|
|||
|
|
.split(' ')
|
|||
|
|
.filter((c) => c.length > 0);
|
|||
|
|
}
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockCSSStyleDeclaration {
|
|||
|
|
constructor() {
|
|||
|
|
this._styles = new Map();
|
|||
|
|
}
|
|||
|
|
setProperty(prop, value) {
|
|||
|
|
prop = jsCaseToCssCase(prop);
|
|||
|
|
if (value == null || value === '') {
|
|||
|
|
this._styles.delete(prop);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this._styles.set(prop, String(value));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
getPropertyValue(prop) {
|
|||
|
|
prop = jsCaseToCssCase(prop);
|
|||
|
|
return String(this._styles.get(prop) || '');
|
|||
|
|
}
|
|||
|
|
removeProperty(prop) {
|
|||
|
|
prop = jsCaseToCssCase(prop);
|
|||
|
|
this._styles.delete(prop);
|
|||
|
|
}
|
|||
|
|
get length() {
|
|||
|
|
return this._styles.size;
|
|||
|
|
}
|
|||
|
|
get cssText() {
|
|||
|
|
const cssText = [];
|
|||
|
|
this._styles.forEach((value, prop) => {
|
|||
|
|
cssText.push(`${prop}: ${value};`);
|
|||
|
|
});
|
|||
|
|
return cssText.join(' ').trim();
|
|||
|
|
}
|
|||
|
|
set cssText(cssText) {
|
|||
|
|
if (cssText == null || cssText === '') {
|
|||
|
|
this._styles.clear();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
cssText.split(';').forEach((rule) => {
|
|||
|
|
rule = rule.trim();
|
|||
|
|
if (rule.length > 0) {
|
|||
|
|
const splt = rule.split(':');
|
|||
|
|
if (splt.length > 1) {
|
|||
|
|
const prop = splt[0].trim();
|
|||
|
|
const value = splt.slice(1).join(':').trim();
|
|||
|
|
if (prop !== '' && value !== '') {
|
|||
|
|
this._styles.set(jsCaseToCssCase(prop), value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function createCSSStyleDeclaration() {
|
|||
|
|
return new Proxy(new MockCSSStyleDeclaration(), cssProxyHandler);
|
|||
|
|
}
|
|||
|
|
const cssProxyHandler = {
|
|||
|
|
get(cssStyle, prop) {
|
|||
|
|
if (prop in cssStyle) {
|
|||
|
|
return cssStyle[prop];
|
|||
|
|
}
|
|||
|
|
prop = cssCaseToJsCase(prop);
|
|||
|
|
return cssStyle.getPropertyValue(prop);
|
|||
|
|
},
|
|||
|
|
set(cssStyle, prop, value) {
|
|||
|
|
if (prop in cssStyle) {
|
|||
|
|
cssStyle[prop] = value;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
cssStyle.setProperty(prop, value);
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
function cssCaseToJsCase(str) {
|
|||
|
|
// font-size to fontSize
|
|||
|
|
if (str.length > 1 && str.includes('-') === true) {
|
|||
|
|
str = str
|
|||
|
|
.toLowerCase()
|
|||
|
|
.split('-')
|
|||
|
|
.map((segment) => segment.charAt(0).toUpperCase() + segment.slice(1))
|
|||
|
|
.join('');
|
|||
|
|
str = str.slice(0, 1).toLowerCase() + str.slice(1);
|
|||
|
|
}
|
|||
|
|
return str;
|
|||
|
|
}
|
|||
|
|
function jsCaseToCssCase(str) {
|
|||
|
|
// fontSize to font-size
|
|||
|
|
if (str.length > 1 && str.includes('-') === false && /[A-Z]/.test(str) === true) {
|
|||
|
|
str = str
|
|||
|
|
.replace(/([A-Z])/g, (g) => ' ' + g[0])
|
|||
|
|
.trim()
|
|||
|
|
.replace(/ /g, '-')
|
|||
|
|
.toLowerCase();
|
|||
|
|
}
|
|||
|
|
return str;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockCustomElementRegistry {
|
|||
|
|
constructor(win) {
|
|||
|
|
this.win = win;
|
|||
|
|
}
|
|||
|
|
define(tagName, cstr, options) {
|
|||
|
|
if (tagName.toLowerCase() !== tagName) {
|
|||
|
|
throw new Error(`Failed to execute 'define' on 'CustomElementRegistry': "${tagName}" is not a valid custom element name`);
|
|||
|
|
}
|
|||
|
|
if (this.__registry == null) {
|
|||
|
|
this.__registry = new Map();
|
|||
|
|
}
|
|||
|
|
this.__registry.set(tagName, { cstr, options });
|
|||
|
|
if (this.__whenDefined != null) {
|
|||
|
|
const whenDefinedResolveFns = this.__whenDefined.get(tagName);
|
|||
|
|
if (whenDefinedResolveFns != null) {
|
|||
|
|
whenDefinedResolveFns.forEach((whenDefinedResolveFn) => {
|
|||
|
|
whenDefinedResolveFn();
|
|||
|
|
});
|
|||
|
|
whenDefinedResolveFns.length = 0;
|
|||
|
|
this.__whenDefined.delete(tagName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const doc = this.win.document;
|
|||
|
|
if (doc != null) {
|
|||
|
|
const hosts = doc.querySelectorAll(tagName);
|
|||
|
|
hosts.forEach((host) => {
|
|||
|
|
if (upgradedElements.has(host) === false) {
|
|||
|
|
tempDisableCallbacks.add(doc);
|
|||
|
|
const upgradedCmp = createCustomElement(this, doc, tagName);
|
|||
|
|
for (let i = 0; i < host.childNodes.length; i++) {
|
|||
|
|
const childNode = host.childNodes[i];
|
|||
|
|
childNode.remove();
|
|||
|
|
upgradedCmp.appendChild(childNode);
|
|||
|
|
}
|
|||
|
|
tempDisableCallbacks.delete(doc);
|
|||
|
|
if (proxyElements.has(host)) {
|
|||
|
|
proxyElements.set(host, upgradedCmp);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
fireConnectedCallback(host);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get(tagName) {
|
|||
|
|
if (this.__registry != null) {
|
|||
|
|
const def = this.__registry.get(tagName.toLowerCase());
|
|||
|
|
if (def != null) {
|
|||
|
|
return def.cstr;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return undefined;
|
|||
|
|
}
|
|||
|
|
upgrade(_rootNode) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
clear() {
|
|||
|
|
if (this.__registry != null) {
|
|||
|
|
this.__registry.clear();
|
|||
|
|
}
|
|||
|
|
if (this.__whenDefined != null) {
|
|||
|
|
this.__whenDefined.clear();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
whenDefined(tagName) {
|
|||
|
|
tagName = tagName.toLowerCase();
|
|||
|
|
if (this.__registry != null && this.__registry.has(tagName) === true) {
|
|||
|
|
return Promise.resolve(this.__registry.get(tagName).cstr);
|
|||
|
|
}
|
|||
|
|
return new Promise((resolve) => {
|
|||
|
|
if (this.__whenDefined == null) {
|
|||
|
|
this.__whenDefined = new Map();
|
|||
|
|
}
|
|||
|
|
let whenDefinedResolveFns = this.__whenDefined.get(tagName);
|
|||
|
|
if (whenDefinedResolveFns == null) {
|
|||
|
|
whenDefinedResolveFns = [];
|
|||
|
|
this.__whenDefined.set(tagName, whenDefinedResolveFns);
|
|||
|
|
}
|
|||
|
|
whenDefinedResolveFns.push(resolve);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function createCustomElement(customElements, ownerDocument, tagName) {
|
|||
|
|
const Cstr = customElements.get(tagName);
|
|||
|
|
if (Cstr != null) {
|
|||
|
|
const cmp = new Cstr(ownerDocument);
|
|||
|
|
cmp.nodeName = tagName.toUpperCase();
|
|||
|
|
upgradedElements.add(cmp);
|
|||
|
|
return cmp;
|
|||
|
|
}
|
|||
|
|
const host = new Proxy({}, {
|
|||
|
|
get(obj, prop) {
|
|||
|
|
const elm = proxyElements.get(host);
|
|||
|
|
if (elm != null) {
|
|||
|
|
return elm[prop];
|
|||
|
|
}
|
|||
|
|
return obj[prop];
|
|||
|
|
},
|
|||
|
|
set(obj, prop, val) {
|
|||
|
|
const elm = proxyElements.get(host);
|
|||
|
|
if (elm != null) {
|
|||
|
|
elm[prop] = val;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
obj[prop] = val;
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
},
|
|||
|
|
has(obj, prop) {
|
|||
|
|
const elm = proxyElements.get(host);
|
|||
|
|
if (prop in elm) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
if (prop in obj) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
const elm = new MockHTMLElement(ownerDocument, tagName);
|
|||
|
|
proxyElements.set(host, elm);
|
|||
|
|
return host;
|
|||
|
|
}
|
|||
|
|
const proxyElements = new WeakMap();
|
|||
|
|
const upgradedElements = new WeakSet();
|
|||
|
|
function connectNode(ownerDocument, node) {
|
|||
|
|
node.ownerDocument = ownerDocument;
|
|||
|
|
if (node.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */) {
|
|||
|
|
if (ownerDocument != null && node.nodeName.includes('-')) {
|
|||
|
|
const win = ownerDocument.defaultView;
|
|||
|
|
if (win != null && typeof node.connectedCallback === 'function' && node.isConnected) {
|
|||
|
|
fireConnectedCallback(node);
|
|||
|
|
}
|
|||
|
|
const shadowRoot = node.shadowRoot;
|
|||
|
|
if (shadowRoot != null) {
|
|||
|
|
shadowRoot.childNodes.forEach((childNode) => {
|
|||
|
|
connectNode(ownerDocument, childNode);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
node.childNodes.forEach((childNode) => {
|
|||
|
|
connectNode(ownerDocument, childNode);
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
node.childNodes.forEach((childNode) => {
|
|||
|
|
childNode.ownerDocument = ownerDocument;
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function fireConnectedCallback(node) {
|
|||
|
|
if (typeof node.connectedCallback === 'function') {
|
|||
|
|
if (tempDisableCallbacks.has(node.ownerDocument) === false) {
|
|||
|
|
try {
|
|||
|
|
node.connectedCallback();
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function disconnectNode(node) {
|
|||
|
|
if (node.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */) {
|
|||
|
|
if (node.nodeName.includes('-') === true && typeof node.disconnectedCallback === 'function') {
|
|||
|
|
if (tempDisableCallbacks.has(node.ownerDocument) === false) {
|
|||
|
|
try {
|
|||
|
|
node.disconnectedCallback();
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
node.childNodes.forEach(disconnectNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function attributeChanged(node, attrName, oldValue, newValue) {
|
|||
|
|
attrName = attrName.toLowerCase();
|
|||
|
|
const observedAttributes = node.constructor.observedAttributes;
|
|||
|
|
if (Array.isArray(observedAttributes) === true &&
|
|||
|
|
observedAttributes.some((obs) => obs.toLowerCase() === attrName) === true) {
|
|||
|
|
try {
|
|||
|
|
node.attributeChangedCallback(attrName, oldValue, newValue);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function checkAttributeChanged(node) {
|
|||
|
|
return node.nodeName.includes('-') === true && typeof node.attributeChangedCallback === 'function';
|
|||
|
|
}
|
|||
|
|
const tempDisableCallbacks = new Set();
|
|||
|
|
|
|||
|
|
function dataset(elm) {
|
|||
|
|
const ds = {};
|
|||
|
|
const attributes = elm.attributes;
|
|||
|
|
const attrLen = attributes.length;
|
|||
|
|
for (let i = 0; i < attrLen; i++) {
|
|||
|
|
const attr = attributes.item(i);
|
|||
|
|
const nodeName = attr.nodeName;
|
|||
|
|
if (nodeName.startsWith('data-')) {
|
|||
|
|
ds[dashToPascalCase(nodeName)] = attr.nodeValue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return new Proxy(ds, {
|
|||
|
|
get(_obj, camelCaseProp) {
|
|||
|
|
return ds[camelCaseProp];
|
|||
|
|
},
|
|||
|
|
set(_obj, camelCaseProp, value) {
|
|||
|
|
const dataAttr = toDataAttribute(camelCaseProp);
|
|||
|
|
elm.setAttribute(dataAttr, value);
|
|||
|
|
return true;
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function toDataAttribute(str) {
|
|||
|
|
return ('data-' +
|
|||
|
|
String(str)
|
|||
|
|
.replace(/([A-Z0-9])/g, (g) => ' ' + g[0])
|
|||
|
|
.trim()
|
|||
|
|
.replace(/ /g, '-')
|
|||
|
|
.toLowerCase());
|
|||
|
|
}
|
|||
|
|
function dashToPascalCase(str) {
|
|||
|
|
str = String(str).slice(5);
|
|||
|
|
return str
|
|||
|
|
.split('-')
|
|||
|
|
.map((segment, index) => {
|
|||
|
|
if (index === 0) {
|
|||
|
|
return segment.charAt(0).toLowerCase() + segment.slice(1);
|
|||
|
|
}
|
|||
|
|
return segment.charAt(0).toUpperCase() + segment.slice(1);
|
|||
|
|
})
|
|||
|
|
.join('');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockEvent {
|
|||
|
|
constructor(type, eventInitDict) {
|
|||
|
|
this.bubbles = false;
|
|||
|
|
this.cancelBubble = false;
|
|||
|
|
this.cancelable = false;
|
|||
|
|
this.composed = false;
|
|||
|
|
this.currentTarget = null;
|
|||
|
|
this.defaultPrevented = false;
|
|||
|
|
this.srcElement = null;
|
|||
|
|
this.target = null;
|
|||
|
|
if (typeof type !== 'string') {
|
|||
|
|
throw new Error(`Event type required`);
|
|||
|
|
}
|
|||
|
|
this.type = type;
|
|||
|
|
this.timeStamp = Date.now();
|
|||
|
|
if (eventInitDict != null) {
|
|||
|
|
Object.assign(this, eventInitDict);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
preventDefault() {
|
|||
|
|
this.defaultPrevented = true;
|
|||
|
|
}
|
|||
|
|
stopPropagation() {
|
|||
|
|
this.cancelBubble = true;
|
|||
|
|
}
|
|||
|
|
stopImmediatePropagation() {
|
|||
|
|
this.cancelBubble = true;
|
|||
|
|
}
|
|||
|
|
composedPath() {
|
|||
|
|
const composedPath = [];
|
|||
|
|
let currentElement = this.target;
|
|||
|
|
while (currentElement) {
|
|||
|
|
composedPath.push(currentElement);
|
|||
|
|
if (!currentElement.parentElement && currentElement.nodeName === "#document" /* NODE_NAMES.DOCUMENT_NODE */) {
|
|||
|
|
// the current element doesn't have a parent, but we've detected it's our root document node. push the window
|
|||
|
|
// object associated with the document onto the path
|
|||
|
|
composedPath.push(currentElement.defaultView);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
currentElement = currentElement.parentElement;
|
|||
|
|
}
|
|||
|
|
return composedPath;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockCustomEvent extends MockEvent {
|
|||
|
|
constructor(type, customEventInitDic) {
|
|||
|
|
super(type);
|
|||
|
|
this.detail = null;
|
|||
|
|
if (customEventInitDic != null) {
|
|||
|
|
Object.assign(this, customEventInitDic);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockKeyboardEvent extends MockEvent {
|
|||
|
|
constructor(type, keyboardEventInitDic) {
|
|||
|
|
super(type);
|
|||
|
|
this.code = '';
|
|||
|
|
this.key = '';
|
|||
|
|
this.altKey = false;
|
|||
|
|
this.ctrlKey = false;
|
|||
|
|
this.metaKey = false;
|
|||
|
|
this.shiftKey = false;
|
|||
|
|
this.location = 0;
|
|||
|
|
this.repeat = false;
|
|||
|
|
if (keyboardEventInitDic != null) {
|
|||
|
|
Object.assign(this, keyboardEventInitDic);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockMouseEvent extends MockEvent {
|
|||
|
|
constructor(type, mouseEventInitDic) {
|
|||
|
|
super(type);
|
|||
|
|
this.screenX = 0;
|
|||
|
|
this.screenY = 0;
|
|||
|
|
this.clientX = 0;
|
|||
|
|
this.clientY = 0;
|
|||
|
|
this.ctrlKey = false;
|
|||
|
|
this.shiftKey = false;
|
|||
|
|
this.altKey = false;
|
|||
|
|
this.metaKey = false;
|
|||
|
|
this.button = 0;
|
|||
|
|
this.buttons = 0;
|
|||
|
|
this.relatedTarget = null;
|
|||
|
|
if (mouseEventInitDic != null) {
|
|||
|
|
Object.assign(this, mouseEventInitDic);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockUIEvent extends MockEvent {
|
|||
|
|
constructor(type, uiEventInitDic) {
|
|||
|
|
super(type);
|
|||
|
|
this.detail = null;
|
|||
|
|
this.view = null;
|
|||
|
|
if (uiEventInitDic != null) {
|
|||
|
|
Object.assign(this, uiEventInitDic);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockFocusEvent extends MockUIEvent {
|
|||
|
|
constructor(type, focusEventInitDic) {
|
|||
|
|
super(type);
|
|||
|
|
this.relatedTarget = null;
|
|||
|
|
if (focusEventInitDic != null) {
|
|||
|
|
Object.assign(this, focusEventInitDic);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockEventListener {
|
|||
|
|
constructor(type, handler) {
|
|||
|
|
this.type = type;
|
|||
|
|
this.handler = handler;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function addEventListener(elm, type, handler) {
|
|||
|
|
const target = elm;
|
|||
|
|
if (target.__listeners == null) {
|
|||
|
|
target.__listeners = [];
|
|||
|
|
}
|
|||
|
|
target.__listeners.push(new MockEventListener(type, handler));
|
|||
|
|
}
|
|||
|
|
function removeEventListener(elm, type, handler) {
|
|||
|
|
const target = elm;
|
|||
|
|
if (target != null && Array.isArray(target.__listeners) === true) {
|
|||
|
|
const elmListener = target.__listeners.find((e) => e.type === type && e.handler === handler);
|
|||
|
|
if (elmListener != null) {
|
|||
|
|
const index = target.__listeners.indexOf(elmListener);
|
|||
|
|
target.__listeners.splice(index, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function resetEventListeners(target) {
|
|||
|
|
if (target != null && target.__listeners != null) {
|
|||
|
|
target.__listeners = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function triggerEventListener(elm, ev) {
|
|||
|
|
if (elm == null || ev.cancelBubble === true) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const target = elm;
|
|||
|
|
ev.currentTarget = elm;
|
|||
|
|
if (Array.isArray(target.__listeners) === true) {
|
|||
|
|
const listeners = target.__listeners.filter((e) => e.type === ev.type);
|
|||
|
|
listeners.forEach((listener) => {
|
|||
|
|
try {
|
|||
|
|
listener.handler.call(target, ev);
|
|||
|
|
}
|
|||
|
|
catch (err) {
|
|||
|
|
console.error(err);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
if (ev.bubbles === false) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
if (elm.nodeName === "#document" /* NODE_NAMES.DOCUMENT_NODE */) {
|
|||
|
|
triggerEventListener(elm.defaultView, ev);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
triggerEventListener(elm.parentElement, ev);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function dispatchEvent(currentTarget, ev) {
|
|||
|
|
ev.target = currentTarget;
|
|||
|
|
triggerEventListener(currentTarget, ev);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Parse5 7.1.2
|
|||
|
|
const e=function(e){const t=new Set([65534,65535,131070,131071,196606,196607,262142,262143,327678,327679,393214,393215,458750,458751,524286,524287,589822,589823,655358,655359,720894,720895,786430,786431,851966,851967,917502,917503,983038,983039,1048574,1048575,1114110,1114111]),s="<22>";var a;!function(e){e[e.EOF=-1]="EOF",e[e.NULL=0]="NULL",e[e.TABULATION=9]="TABULATION",e[e.CARRIAGE_RETURN=13]="CARRIAGE_RETURN",e[e.LINE_FEED=10]="LINE_FEED",e[e.FORM_FEED=12]="FORM_FEED",e[e.SPACE=32]="SPACE",e[e.EXCLAMATION_MARK=33]="EXCLAMATION_MARK",e[e.QUOTATION_MARK=34]="QUOTATION_MARK",e[e.NUMBER_SIGN=35]="NUMBER_SIGN",e[e.AMPERSAND=38]="AMPERSAND",e[e.APOSTROPHE=39]="APOSTROPHE",e[e.HYPHEN_MINUS=45]="HYPHEN_MINUS",e[e.SOLIDUS=47]="SOLIDUS",e[e.DIGIT_0=48]="DIGIT_0",e[e.DIGIT_9=57]="DIGIT_9",e[e.SEMICOLON=59]="SEMICOLON",e[e.LESS_THAN_SIGN=60]="LESS_THAN_SIGN",e[e.EQUALS_SIGN=61]="EQUALS_SIGN",e[e.GREATER_THAN_SIGN=62]="GREATER_THAN_SIGN",e[e.QUESTION_MARK=63]="QUESTION_MARK",e[e.LATIN_CAPITAL_A=65]="LATIN_CAPITAL_A",e[e.LATIN_CAPITAL_F=70]="LATIN_CAPITAL_F",e[e.LATIN_CAPITAL_X=88]="LATIN_CAPITAL_X",e[e.LATIN_CAPITAL_Z=90]="LATIN_CAPITAL_Z",e[e.RIGHT_SQUARE_BRACKET=93]="RIGHT_SQUARE_BRACKET",e[e.GRAVE_ACCENT=96]="GRAVE_ACCENT",e[e.LATIN_SMALL_A=97]="LATIN_SMALL_A",e[e.LATIN_SMALL_F=102]="LATIN_SMALL_F",e[e.LATIN_SMALL_X=120]="LATIN_SMALL_X",e[e.LATIN_SMALL_Z=122]="LATIN_SMALL_Z",e[e.REPLACEMENT_CHARACTER=65533]="REPLACEMENT_CHARACTER";}(a=a||(a={}));const r="[CDATA[",n="doctype",i="script";function o(e){return e>=55296&&e<=57343}function c(e){return 32!==e&&10!==e&&13!==e&&9!==e&&12!==e&&e>=1&&e<=31||e>=127&&e<=159}function E(e){return e>=64976&&e<=65007||t.has(e)}var T,h;!function(e){e.controlCharacterInInputStream="control-character-in-input-stream",e.noncharacterInInputStream="noncharacter-in-input-stream",e.surrogateInInputStream="surrogate-in-input-stream",e.nonVoidHtmlElementStartTagWithTrailingSolidus="non-void-html-element-start-tag-with-trailing-solidus",e.endTagWithAttributes="end-tag-with-attributes",e.endTagWithTrailingSolidus="end-tag-with-trailing-solidus",e.unexpectedSolidusInTag="unexpected-solidus-in-tag",e.unexpectedNullCharacter="unexpected-null-character",e.unexpectedQuestionMarkInsteadOfTagName="unexpected-question-mark-instead-of-tag-name",e.invalidFirstCharacterOfTagName="invalid-first-character-of-tag-name",e.unexpectedEqualsSignBeforeAttributeName="unexpected-equals-sign-before-attribute-name",e.missingEndTagName="missing-end-tag-name",e.unexpectedCharacterInAttributeName="unexpected-character-in-attribute-name",e.unknownNamedCharacterReference="unknown-named-character-reference",e.missingSemicolonAfterCharacterReference="missing-semicolon-after-character-reference",e.unexpectedCharacterAfterDoctypeSystemIdentifier="unexpected-character-after-doctype-system-identifier",e.unexpectedCharacterInUnquotedAttributeValue="unexpected-character-in-unquoted-attribute-value",e.eofBeforeTagName="eof-before-tag-name",e.eofInTag="eof-in-tag",e.missingAttributeValue="missing-attribute-value",e.missingWhitespaceBetweenAttributes="missing-whitespace-between-attributes",e.missingWhitespaceAfterDoctypePublicKeyword="missing-whitespace-after-doctype-public-keyword",e.missingWhitespaceBetweenDoctypePublicAndSystemIdentifiers="missing-whitespace-between-doctype-public-and-system-identifiers",e.missingWhitespaceAfterDoctypeSystemKeyword="missing-whitespace-after-doctype-system-keyword",e.missingQuoteBeforeDoctypePublicIdentifier="missing-quote-before-doctype-public-identifier",e.missingQuoteBeforeDoctypeSystemIdentifier="missing-quote-before-doctype-system-identifier",e.missingDoctypePublicIdentifier="missing-doctype-public-identifier",e.missingDoctypeSystemIdentifier="missing-doctype-system-identifier",e.abruptDoctypePublicIdentifier="abrupt-doctype-public-identifier",e.abruptDoctypeSystemIdentifier="abrupt-doctype-system-identifier",e.cdataInHtmlContent="cdata-in-html-content",e.incorrectlyOpenedComment="incorrectly-opened-comment",e.eofInScriptHtmlCommentLikeText="eof-in-script-html-comment-like-text",e.eofInDoctype="eof-in-d
|
|||
|
|
|
|||
|
|
const docParser = new WeakMap();
|
|||
|
|
function parseDocumentUtil(ownerDocument, html) {
|
|||
|
|
const doc = parse(html.trim(), getParser(ownerDocument));
|
|||
|
|
doc.documentElement = doc.firstElementChild;
|
|||
|
|
doc.head = doc.documentElement.firstElementChild;
|
|||
|
|
doc.body = doc.head.nextElementSibling;
|
|||
|
|
return doc;
|
|||
|
|
}
|
|||
|
|
function parseFragmentUtil(ownerDocument, html) {
|
|||
|
|
if (typeof html === 'string') {
|
|||
|
|
html = html.trim();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
html = '';
|
|||
|
|
}
|
|||
|
|
const frag = parseFragment(html, getParser(ownerDocument));
|
|||
|
|
return frag;
|
|||
|
|
}
|
|||
|
|
function getParser(ownerDocument) {
|
|||
|
|
let parseOptions = docParser.get(ownerDocument);
|
|||
|
|
if (parseOptions != null) {
|
|||
|
|
return parseOptions;
|
|||
|
|
}
|
|||
|
|
const treeAdapter = {
|
|||
|
|
createDocument() {
|
|||
|
|
const doc = ownerDocument.createElement("#document" /* NODE_NAMES.DOCUMENT_NODE */);
|
|||
|
|
doc['x-mode'] = 'no-quirks';
|
|||
|
|
return doc;
|
|||
|
|
},
|
|||
|
|
setNodeSourceCodeLocation(node, location) {
|
|||
|
|
node.sourceCodeLocation = location;
|
|||
|
|
},
|
|||
|
|
getNodeSourceCodeLocation(node) {
|
|||
|
|
return node.sourceCodeLocation;
|
|||
|
|
},
|
|||
|
|
createDocumentFragment() {
|
|||
|
|
return ownerDocument.createDocumentFragment();
|
|||
|
|
},
|
|||
|
|
createElement(tagName, namespaceURI, attrs) {
|
|||
|
|
const elm = ownerDocument.createElementNS(namespaceURI, tagName);
|
|||
|
|
for (let i = 0; i < attrs.length; i++) {
|
|||
|
|
const attr = attrs[i];
|
|||
|
|
if (attr.namespace == null || attr.namespace === 'http://www.w3.org/1999/xhtml') {
|
|||
|
|
elm.setAttribute(attr.name, attr.value);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
elm.setAttributeNS(attr.namespace, attr.name, attr.value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return elm;
|
|||
|
|
},
|
|||
|
|
createCommentNode(data) {
|
|||
|
|
return ownerDocument.createComment(data);
|
|||
|
|
},
|
|||
|
|
appendChild(parentNode, newNode) {
|
|||
|
|
parentNode.appendChild(newNode);
|
|||
|
|
},
|
|||
|
|
insertBefore(parentNode, newNode, referenceNode) {
|
|||
|
|
parentNode.insertBefore(newNode, referenceNode);
|
|||
|
|
},
|
|||
|
|
setTemplateContent(templateElement, contentElement) {
|
|||
|
|
templateElement.content = contentElement;
|
|||
|
|
},
|
|||
|
|
getTemplateContent(templateElement) {
|
|||
|
|
return templateElement.content;
|
|||
|
|
},
|
|||
|
|
setDocumentType(doc, name, publicId, systemId) {
|
|||
|
|
let doctypeNode = doc.childNodes.find((n) => n.nodeType === 10 /* NODE_TYPES.DOCUMENT_TYPE_NODE */);
|
|||
|
|
if (doctypeNode == null) {
|
|||
|
|
doctypeNode = ownerDocument.createDocumentTypeNode();
|
|||
|
|
doc.insertBefore(doctypeNode, doc.firstChild);
|
|||
|
|
}
|
|||
|
|
doctypeNode.nodeValue = '!DOCTYPE';
|
|||
|
|
doctypeNode['x-name'] = name;
|
|||
|
|
doctypeNode['x-publicId'] = publicId;
|
|||
|
|
doctypeNode['x-systemId'] = systemId;
|
|||
|
|
},
|
|||
|
|
setDocumentMode(doc, mode) {
|
|||
|
|
doc['x-mode'] = mode;
|
|||
|
|
},
|
|||
|
|
getDocumentMode(doc) {
|
|||
|
|
return doc['x-mode'];
|
|||
|
|
},
|
|||
|
|
detachNode(node) {
|
|||
|
|
node.remove();
|
|||
|
|
},
|
|||
|
|
insertText(parentNode, text) {
|
|||
|
|
const lastChild = parentNode.lastChild;
|
|||
|
|
if (lastChild != null && lastChild.nodeType === 3 /* NODE_TYPES.TEXT_NODE */) {
|
|||
|
|
lastChild.nodeValue += text;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
parentNode.appendChild(ownerDocument.createTextNode(text));
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
insertTextBefore(parentNode, text, referenceNode) {
|
|||
|
|
const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
|
|||
|
|
if (prevNode != null && prevNode.nodeType === 3 /* NODE_TYPES.TEXT_NODE */) {
|
|||
|
|
prevNode.nodeValue += text;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
parentNode.insertBefore(ownerDocument.createTextNode(text), referenceNode);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
adoptAttributes(recipient, attrs) {
|
|||
|
|
for (let i = 0; i < attrs.length; i++) {
|
|||
|
|
const attr = attrs[i];
|
|||
|
|
if (recipient.hasAttributeNS(attr.namespace, attr.name) === false) {
|
|||
|
|
recipient.setAttributeNS(attr.namespace, attr.name, attr.value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
getFirstChild(node) {
|
|||
|
|
return node.childNodes[0];
|
|||
|
|
},
|
|||
|
|
getChildNodes(node) {
|
|||
|
|
return node.childNodes;
|
|||
|
|
},
|
|||
|
|
getParentNode(node) {
|
|||
|
|
return node.parentNode;
|
|||
|
|
},
|
|||
|
|
getAttrList(element) {
|
|||
|
|
const attrs = element.attributes.__items.map((attr) => {
|
|||
|
|
return {
|
|||
|
|
name: attr.name,
|
|||
|
|
value: attr.value,
|
|||
|
|
namespace: attr.namespaceURI,
|
|||
|
|
prefix: null,
|
|||
|
|
};
|
|||
|
|
});
|
|||
|
|
return attrs;
|
|||
|
|
},
|
|||
|
|
getTagName(element) {
|
|||
|
|
if (element.namespaceURI === 'http://www.w3.org/1999/xhtml') {
|
|||
|
|
return element.nodeName.toLowerCase();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return element.nodeName;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
getNamespaceURI(element) {
|
|||
|
|
// mock-doc widens the type of an element's namespace uri to 'string | null'
|
|||
|
|
// we use a type assertion here to adhere to parse5's type definitions
|
|||
|
|
return element.namespaceURI;
|
|||
|
|
},
|
|||
|
|
getTextNodeContent(textNode) {
|
|||
|
|
return textNode.nodeValue;
|
|||
|
|
},
|
|||
|
|
getCommentNodeContent(commentNode) {
|
|||
|
|
return commentNode.nodeValue;
|
|||
|
|
},
|
|||
|
|
getDocumentTypeNodeName(doctypeNode) {
|
|||
|
|
return doctypeNode['x-name'];
|
|||
|
|
},
|
|||
|
|
getDocumentTypeNodePublicId(doctypeNode) {
|
|||
|
|
return doctypeNode['x-publicId'];
|
|||
|
|
},
|
|||
|
|
getDocumentTypeNodeSystemId(doctypeNode) {
|
|||
|
|
return doctypeNode['x-systemId'];
|
|||
|
|
},
|
|||
|
|
// @ts-ignore - a `MockNode` will never be assignable to a `TreeAdapterTypeMap['text']`. As a result, we cannot
|
|||
|
|
// complete this function signature
|
|||
|
|
isTextNode(node) {
|
|||
|
|
return node.nodeType === 3 /* NODE_TYPES.TEXT_NODE */;
|
|||
|
|
},
|
|||
|
|
// @ts-ignore - a `MockNode` will never be assignable to a `TreeAdapterTypeMap['comment']`. As a result, we cannot
|
|||
|
|
// complete this function signature (which requires its return type to be a type predicate)
|
|||
|
|
isCommentNode(node) {
|
|||
|
|
return node.nodeType === 8 /* NODE_TYPES.COMMENT_NODE */;
|
|||
|
|
},
|
|||
|
|
// @ts-ignore - a `MockNode` will never be assignable to a `TreeAdapterTypeMap['document']`. As a result, we cannot
|
|||
|
|
// complete this function signature (which requires its return type to be a type predicate)
|
|||
|
|
isDocumentTypeNode(node) {
|
|||
|
|
return node.nodeType === 10 /* NODE_TYPES.DOCUMENT_TYPE_NODE */;
|
|||
|
|
},
|
|||
|
|
// @ts-ignore - a `MockNode` will never be assignable to a `TreeAdapterTypeMap['element']`. As a result, we cannot
|
|||
|
|
// complete this function signature (which requires its return type to be a type predicate)
|
|||
|
|
isElementNode(node) {
|
|||
|
|
return node.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
parseOptions = {
|
|||
|
|
treeAdapter: treeAdapter,
|
|||
|
|
};
|
|||
|
|
docParser.set(ownerDocument, parseOptions);
|
|||
|
|
return parseOptions;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Sizzle 2.3.9
|
|||
|
|
const Sizzle = (function() {
|
|||
|
|
const window = {
|
|||
|
|
document: {
|
|||
|
|
createElement() {
|
|||
|
|
return {};
|
|||
|
|
},
|
|||
|
|
nodeType: 9,
|
|||
|
|
documentElement: {
|
|||
|
|
nodeType: 1,
|
|||
|
|
nodeName: 'HTML'
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
const module = { exports: {} };
|
|||
|
|
|
|||
|
|
/*! Sizzle v2.3.9 | (c) JS Foundation and other contributors | js.foundation */
|
|||
|
|
!function(e){var t,n,r,i,o,u,l,a,s,c,f,d,p,h,g,m,y,v,w,b="sizzle"+1*new Date,N=e.document,C=0,x=0,S=ae(),E=ae(),A=ae(),D=ae(),T=function(e,t){return e===t&&(f=!0),0},L={}.hasOwnProperty,q=[],I=q.pop,B=q.push,R=q.push,k=q.slice,$=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return -1},H="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",P="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",z="\\["+M+"*("+P+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+P+"))|)"+M+"*\\]",F=":("+P+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+z+")*)|.*)\\)|)",O=new RegExp(M+"+","g"),j=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),G=new RegExp("^"+M+"*,"+M+"*"),U=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),V=new RegExp(M+"|>"),X=new RegExp(F),J=new RegExp("^"+P+"$"),K={ID:new RegExp("^#("+P+")"),CLASS:new RegExp("^\\.("+P+")"),TAG:new RegExp("^("+P+"|[*])"),ATTR:new RegExp("^"+z),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+H+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Q=/HTML$/i,W=/^(?:input|select|textarea|button)$/i,Y=/^h\d$/i,Z=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){d();},ue=ve(function(e){return !0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{R.apply(q=k.call(N.childNodes),N.childNodes),q[N.childNodes.length].nodeType;}catch(e){R={apply:q.length?function(e,t){B.apply(e,k.call(t));}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1;}};}function le(e,t,r,i){var o,l,s,c,f,h,y,v=t&&t.ownerDocument,N=t?t.nodeType:9;if(r=r||[],"string"!=typeof e||!e||1!==N&&9!==N&&11!==N)return r;if(!i&&(d(t),t=t||p,g)){if(11!==N&&(f=_.exec(e)))if(o=f[1]){if(9===N){if(!(s=t.getElementById(o)))return r;if(s.id===o)return r.push(s),r}else if(v&&(s=v.getElementById(o))&&w(t,s)&&s.id===o)return r.push(s),r}else {if(f[2])return R.apply(r,t.getElementsByTagName(e)),r;if((o=f[3])&&n.getElementsByClassName&&t.getElementsByClassName)return R.apply(r,t.getElementsByClassName(o)),r}if(n.qsa&&!D[e+" "]&&(!m||!m.test(e))&&(1!==N||"object"!==t.nodeName.toLowerCase())){if(y=e,v=t,1===N&&(V.test(e)||U.test(e))){(v=ee.test(e)&&ge(t.parentNode)||t)===t&&n.scope||((c=t.getAttribute("id"))?c=c.replace(re,ie):t.setAttribute("id",c=b)),l=(h=u(e)).length;while(l--)h[l]=(c?"#"+c:":scope")+" "+ye(h[l]);y=h.join(",");}try{if(n.cssSupportsSelector&&!CSS.supports("selector(:is("+y+"))"))throw new Error;return R.apply(r,v.querySelectorAll(y)),r}catch(t){D(e,!0);}finally{c===b&&t.removeAttribute("id");}}}return a(e.replace(j,"$1"),t,r,i)}function ae(){var e=[];function t(n,i){return e.push(n+" ")>r.cacheLength&&delete t[e.shift()],t[n+" "]=i}return t}function se(e){return e[b]=!0,e}function ce(e){var t=p.createElement("fieldset");try{return !!e(t)}catch(e){return !1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null;}}function fe(e,t){var n=e.split("|"),i=n.length;while(i--)r.attrHandle[n[i]]=t;}function de(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return -1;return e?1:-1}function pe(e){return function(t){return "form"in t?t.parentNode&&!1===t.disabled?"label"in t?"label"in t.parentNode?t.parentNode.disabled===e:t.disabled===e:t.isDisabled===e||t.is
|
|||
|
|
//# sourceMappingURL=sizzle.min.map
|
|||
|
|
|
|||
|
|
return module.exports;
|
|||
|
|
})();
|
|||
|
|
|
|||
|
|
function matches(selector, elm) {
|
|||
|
|
const r = Sizzle.matches(selector, [elm]);
|
|||
|
|
return r.length > 0;
|
|||
|
|
}
|
|||
|
|
function selectOne(selector, elm) {
|
|||
|
|
const r = Sizzle(selector, elm);
|
|||
|
|
return r[0] || null;
|
|||
|
|
}
|
|||
|
|
function selectAll(selector, elm) {
|
|||
|
|
return Sizzle(selector, elm);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function serializeNodeToHtml(elm, opts = {}) {
|
|||
|
|
const output = {
|
|||
|
|
currentLineWidth: 0,
|
|||
|
|
indent: 0,
|
|||
|
|
isWithinBody: false,
|
|||
|
|
text: [],
|
|||
|
|
};
|
|||
|
|
if (opts.prettyHtml) {
|
|||
|
|
if (typeof opts.indentSpaces !== 'number') {
|
|||
|
|
opts.indentSpaces = 2;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.newLines !== 'boolean') {
|
|||
|
|
opts.newLines = true;
|
|||
|
|
}
|
|||
|
|
opts.approximateLineWidth = -1;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
opts.prettyHtml = false;
|
|||
|
|
if (typeof opts.newLines !== 'boolean') {
|
|||
|
|
opts.newLines = false;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.indentSpaces !== 'number') {
|
|||
|
|
opts.indentSpaces = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (typeof opts.approximateLineWidth !== 'number') {
|
|||
|
|
opts.approximateLineWidth = -1;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.removeEmptyAttributes !== 'boolean') {
|
|||
|
|
opts.removeEmptyAttributes = true;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.removeAttributeQuotes !== 'boolean') {
|
|||
|
|
opts.removeAttributeQuotes = false;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.removeBooleanAttributeQuotes !== 'boolean') {
|
|||
|
|
opts.removeBooleanAttributeQuotes = false;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.removeHtmlComments !== 'boolean') {
|
|||
|
|
opts.removeHtmlComments = false;
|
|||
|
|
}
|
|||
|
|
if (typeof opts.serializeShadowRoot !== 'boolean') {
|
|||
|
|
opts.serializeShadowRoot = false;
|
|||
|
|
}
|
|||
|
|
if (opts.outerHtml) {
|
|||
|
|
serializeToHtml(elm, opts, output, false);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
for (let i = 0, ii = elm.childNodes.length; i < ii; i++) {
|
|||
|
|
serializeToHtml(elm.childNodes[i], opts, output, false);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (output.text[0] === '\n') {
|
|||
|
|
output.text.shift();
|
|||
|
|
}
|
|||
|
|
if (output.text[output.text.length - 1] === '\n') {
|
|||
|
|
output.text.pop();
|
|||
|
|
}
|
|||
|
|
return output.text.join('');
|
|||
|
|
}
|
|||
|
|
function serializeToHtml(node, opts, output, isShadowRoot) {
|
|||
|
|
if (node.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */ || isShadowRoot) {
|
|||
|
|
const tagName = isShadowRoot ? 'mock:shadow-root' : getTagName(node);
|
|||
|
|
if (tagName === 'body') {
|
|||
|
|
output.isWithinBody = true;
|
|||
|
|
}
|
|||
|
|
const ignoreTag = opts.excludeTags != null && opts.excludeTags.includes(tagName);
|
|||
|
|
if (ignoreTag === false) {
|
|||
|
|
const isWithinWhitespaceSensitiveNode = opts.newLines || opts.indentSpaces > 0 ? isWithinWhitespaceSensitive(node) : false;
|
|||
|
|
if (opts.newLines && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
if (opts.indentSpaces > 0 && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
for (let i = 0; i < output.indent; i++) {
|
|||
|
|
output.text.push(' ');
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += output.indent;
|
|||
|
|
}
|
|||
|
|
output.text.push('<' + tagName);
|
|||
|
|
output.currentLineWidth += tagName.length + 1;
|
|||
|
|
const attrsLength = node.attributes.length;
|
|||
|
|
const attributes = opts.prettyHtml && attrsLength > 1
|
|||
|
|
? cloneAttributes(node.attributes, true)
|
|||
|
|
: node.attributes;
|
|||
|
|
for (let i = 0; i < attrsLength; i++) {
|
|||
|
|
const attr = attributes.item(i);
|
|||
|
|
const attrName = attr.name;
|
|||
|
|
if (attrName === 'style') {
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
let attrValue = attr.value;
|
|||
|
|
if (opts.removeEmptyAttributes && attrValue === '' && REMOVE_EMPTY_ATTR.has(attrName)) {
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
const attrNamespaceURI = attr.namespaceURI;
|
|||
|
|
if (attrNamespaceURI == null) {
|
|||
|
|
output.currentLineWidth += attrName.length + 1;
|
|||
|
|
if (opts.approximateLineWidth > 0 && output.currentLineWidth > opts.approximateLineWidth) {
|
|||
|
|
output.text.push('\n' + attrName);
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push(' ' + attrName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (attrNamespaceURI === 'http://www.w3.org/XML/1998/namespace') {
|
|||
|
|
output.text.push(' xml:' + attrName);
|
|||
|
|
output.currentLineWidth += attrName.length + 5;
|
|||
|
|
}
|
|||
|
|
else if (attrNamespaceURI === 'http://www.w3.org/2000/xmlns/') {
|
|||
|
|
if (attrName !== 'xmlns') {
|
|||
|
|
output.text.push(' xmlns:' + attrName);
|
|||
|
|
output.currentLineWidth += attrName.length + 7;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push(' ' + attrName);
|
|||
|
|
output.currentLineWidth += attrName.length + 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (attrNamespaceURI === XLINK_NS) {
|
|||
|
|
output.text.push(' xlink:' + attrName);
|
|||
|
|
output.currentLineWidth += attrName.length + 7;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push(' ' + attrNamespaceURI + ':' + attrName);
|
|||
|
|
output.currentLineWidth += attrNamespaceURI.length + attrName.length + 2;
|
|||
|
|
}
|
|||
|
|
if (opts.prettyHtml && attrName === 'class') {
|
|||
|
|
attrValue = attr.value = attrValue
|
|||
|
|
.split(' ')
|
|||
|
|
.filter((t) => t !== '')
|
|||
|
|
.sort()
|
|||
|
|
.join(' ')
|
|||
|
|
.trim();
|
|||
|
|
}
|
|||
|
|
if (attrValue === '') {
|
|||
|
|
if (opts.removeBooleanAttributeQuotes && BOOLEAN_ATTR.has(attrName)) {
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
if (opts.removeEmptyAttributes && attrName.startsWith('data-')) {
|
|||
|
|
continue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (opts.removeAttributeQuotes && CAN_REMOVE_ATTR_QUOTES.test(attrValue)) {
|
|||
|
|
output.text.push('=' + escapeString(attrValue, true));
|
|||
|
|
output.currentLineWidth += attrValue.length + 1;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push('="' + escapeString(attrValue, true) + '"');
|
|||
|
|
output.currentLineWidth += attrValue.length + 3;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (node.hasAttribute('style')) {
|
|||
|
|
const cssText = node.style.cssText;
|
|||
|
|
if (opts.approximateLineWidth > 0 &&
|
|||
|
|
output.currentLineWidth + cssText.length + 10 > opts.approximateLineWidth) {
|
|||
|
|
output.text.push(`\nstyle="${cssText}">`);
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push(` style="${cssText}">`);
|
|||
|
|
output.currentLineWidth += cssText.length + 10;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push('>');
|
|||
|
|
output.currentLineWidth += 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (EMPTY_ELEMENTS.has(tagName) === false) {
|
|||
|
|
if (opts.serializeShadowRoot && node.shadowRoot != null) {
|
|||
|
|
output.indent = output.indent + opts.indentSpaces;
|
|||
|
|
serializeToHtml(node.shadowRoot, opts, output, true);
|
|||
|
|
output.indent = output.indent - opts.indentSpaces;
|
|||
|
|
if (opts.newLines &&
|
|||
|
|
(node.childNodes.length === 0 ||
|
|||
|
|
(node.childNodes.length === 1 &&
|
|||
|
|
node.childNodes[0].nodeType === 3 /* NODE_TYPES.TEXT_NODE */ &&
|
|||
|
|
node.childNodes[0].nodeValue.trim() === ''))) {
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
for (let i = 0; i < output.indent; i++) {
|
|||
|
|
output.text.push(' ');
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += output.indent;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (opts.excludeTagContent == null || opts.excludeTagContent.includes(tagName) === false) {
|
|||
|
|
const childNodes = tagName === 'template' ? node.content.childNodes : node.childNodes;
|
|||
|
|
const childNodeLength = childNodes.length;
|
|||
|
|
if (childNodeLength > 0) {
|
|||
|
|
if (childNodeLength === 1 &&
|
|||
|
|
childNodes[0].nodeType === 3 /* NODE_TYPES.TEXT_NODE */ &&
|
|||
|
|
(typeof childNodes[0].nodeValue !== 'string' || childNodes[0].nodeValue.trim() === '')) ;
|
|||
|
|
else {
|
|||
|
|
const isWithinWhitespaceSensitiveNode = opts.newLines || opts.indentSpaces > 0 ? isWithinWhitespaceSensitive(node) : false;
|
|||
|
|
if (!isWithinWhitespaceSensitiveNode && opts.indentSpaces > 0 && ignoreTag === false) {
|
|||
|
|
output.indent = output.indent + opts.indentSpaces;
|
|||
|
|
}
|
|||
|
|
for (let i = 0; i < childNodeLength; i++) {
|
|||
|
|
serializeToHtml(childNodes[i], opts, output, false);
|
|||
|
|
}
|
|||
|
|
if (ignoreTag === false) {
|
|||
|
|
if (opts.newLines && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
if (opts.indentSpaces > 0 && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
output.indent = output.indent - opts.indentSpaces;
|
|||
|
|
for (let i = 0; i < output.indent; i++) {
|
|||
|
|
output.text.push(' ');
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += output.indent;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (ignoreTag === false) {
|
|||
|
|
output.text.push('</' + tagName + '>');
|
|||
|
|
output.currentLineWidth += tagName.length + 3;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (opts.approximateLineWidth > 0 && STRUCTURE_ELEMENTS.has(tagName)) {
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
if (tagName === 'body') {
|
|||
|
|
output.isWithinBody = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (node.nodeType === 3 /* NODE_TYPES.TEXT_NODE */) {
|
|||
|
|
let textContent = node.nodeValue;
|
|||
|
|
if (typeof textContent === 'string') {
|
|||
|
|
const trimmedTextContent = textContent.trim();
|
|||
|
|
if (trimmedTextContent === '') {
|
|||
|
|
// this text node is whitespace only
|
|||
|
|
if (isWithinWhitespaceSensitive(node)) {
|
|||
|
|
// whitespace matters within this element
|
|||
|
|
// just add the exact text we were given
|
|||
|
|
output.text.push(textContent);
|
|||
|
|
output.currentLineWidth += textContent.length;
|
|||
|
|
}
|
|||
|
|
else if (opts.approximateLineWidth > 0 && !output.isWithinBody) ;
|
|||
|
|
else if (!opts.prettyHtml) {
|
|||
|
|
// this text node is only whitespace, and it's not
|
|||
|
|
// within a whitespace sensitive element like <pre> or <code>
|
|||
|
|
// so replace the entire white space with a single new line
|
|||
|
|
output.currentLineWidth += 1;
|
|||
|
|
if (opts.approximateLineWidth > 0 && output.currentLineWidth > opts.approximateLineWidth) {
|
|||
|
|
// good enough for a new line
|
|||
|
|
// for perf these are all just estimates
|
|||
|
|
// we don't care to ensure exact line lengths
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
// let's keep it all on the same line yet
|
|||
|
|
output.text.push(' ');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
// this text node has text content
|
|||
|
|
const isWithinWhitespaceSensitiveNode = opts.newLines || opts.indentSpaces > 0 || opts.prettyHtml ? isWithinWhitespaceSensitive(node) : false;
|
|||
|
|
if (opts.newLines && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
if (opts.indentSpaces > 0 && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
for (let i = 0; i < output.indent; i++) {
|
|||
|
|
output.text.push(' ');
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += output.indent;
|
|||
|
|
}
|
|||
|
|
let textContentLength = textContent.length;
|
|||
|
|
if (textContentLength > 0) {
|
|||
|
|
// this text node has text content
|
|||
|
|
const parentTagName = node.parentNode != null && node.parentNode.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */
|
|||
|
|
? node.parentNode.nodeName
|
|||
|
|
: null;
|
|||
|
|
if (NON_ESCAPABLE_CONTENT.has(parentTagName)) {
|
|||
|
|
// this text node cannot have its content escaped since it's going
|
|||
|
|
// into an element like <style> or <script>
|
|||
|
|
if (isWithinWhitespaceSensitive(node)) {
|
|||
|
|
output.text.push(textContent);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
output.text.push(trimmedTextContent);
|
|||
|
|
textContentLength = trimmedTextContent.length;
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += textContentLength;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
// this text node is going into a normal element and html can be escaped
|
|||
|
|
if (opts.prettyHtml && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
// pretty print the text node
|
|||
|
|
output.text.push(escapeString(textContent.replace(/\s\s+/g, ' ').trim(), false));
|
|||
|
|
output.currentLineWidth += textContentLength;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
// not pretty printing the text node
|
|||
|
|
if (isWithinWhitespaceSensitive(node)) {
|
|||
|
|
output.currentLineWidth += textContentLength;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
// this element is not a whitespace sensitive one, like <pre> or <code> so
|
|||
|
|
// any whitespace at the start and end can be cleaned up to just be one space
|
|||
|
|
if (/\s/.test(textContent.charAt(0))) {
|
|||
|
|
textContent = ' ' + textContent.trimLeft();
|
|||
|
|
}
|
|||
|
|
textContentLength = textContent.length;
|
|||
|
|
if (textContentLength > 1) {
|
|||
|
|
if (/\s/.test(textContent.charAt(textContentLength - 1))) {
|
|||
|
|
if (opts.approximateLineWidth > 0 &&
|
|||
|
|
output.currentLineWidth + textContentLength > opts.approximateLineWidth) {
|
|||
|
|
textContent = textContent.trimRight() + '\n';
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
textContent = textContent.trimRight() + ' ';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += textContentLength;
|
|||
|
|
}
|
|||
|
|
output.text.push(escapeString(textContent, false));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (node.nodeType === 8 /* NODE_TYPES.COMMENT_NODE */) {
|
|||
|
|
const nodeValue = node.nodeValue;
|
|||
|
|
if (opts.removeHtmlComments) {
|
|||
|
|
const isHydrateAnnotation = nodeValue.startsWith(CONTENT_REF_ID + '.') ||
|
|||
|
|
nodeValue.startsWith(ORG_LOCATION_ID + '.') ||
|
|||
|
|
nodeValue.startsWith(SLOT_NODE_ID + '.') ||
|
|||
|
|
nodeValue.startsWith(TEXT_NODE_ID + '.');
|
|||
|
|
if (!isHydrateAnnotation) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const isWithinWhitespaceSensitiveNode = opts.newLines || opts.indentSpaces > 0 ? isWithinWhitespaceSensitive(node) : false;
|
|||
|
|
if (opts.newLines && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
output.text.push('\n');
|
|||
|
|
output.currentLineWidth = 0;
|
|||
|
|
}
|
|||
|
|
if (opts.indentSpaces > 0 && !isWithinWhitespaceSensitiveNode) {
|
|||
|
|
for (let i = 0; i < output.indent; i++) {
|
|||
|
|
output.text.push(' ');
|
|||
|
|
}
|
|||
|
|
output.currentLineWidth += output.indent;
|
|||
|
|
}
|
|||
|
|
output.text.push('<!--' + nodeValue + '-->');
|
|||
|
|
output.currentLineWidth += nodeValue.length + 7;
|
|||
|
|
}
|
|||
|
|
else if (node.nodeType === 10 /* NODE_TYPES.DOCUMENT_TYPE_NODE */) {
|
|||
|
|
output.text.push('<!doctype html>');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const AMP_REGEX = /&/g;
|
|||
|
|
const NBSP_REGEX = /\u00a0/g;
|
|||
|
|
const DOUBLE_QUOTE_REGEX = /"/g;
|
|||
|
|
const LT_REGEX = /</g;
|
|||
|
|
const GT_REGEX = />/g;
|
|||
|
|
const CAN_REMOVE_ATTR_QUOTES = /^[^ \t\n\f\r"'`=<>\/\\-]+$/;
|
|||
|
|
function getTagName(element) {
|
|||
|
|
if (element.namespaceURI === 'http://www.w3.org/1999/xhtml') {
|
|||
|
|
return element.nodeName.toLowerCase();
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return element.nodeName;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function escapeString(str, attrMode) {
|
|||
|
|
str = str.replace(AMP_REGEX, '&').replace(NBSP_REGEX, ' ');
|
|||
|
|
if (attrMode) {
|
|||
|
|
return str.replace(DOUBLE_QUOTE_REGEX, '"');
|
|||
|
|
}
|
|||
|
|
return str.replace(LT_REGEX, '<').replace(GT_REGEX, '>');
|
|||
|
|
}
|
|||
|
|
function isWithinWhitespaceSensitive(node) {
|
|||
|
|
while (node != null) {
|
|||
|
|
if (WHITESPACE_SENSITIVE.has(node.nodeName)) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
node = node.parentNode;
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
/*@__PURE__*/ const NON_ESCAPABLE_CONTENT = new Set([
|
|||
|
|
'STYLE',
|
|||
|
|
'SCRIPT',
|
|||
|
|
'IFRAME',
|
|||
|
|
'NOSCRIPT',
|
|||
|
|
'XMP',
|
|||
|
|
'NOEMBED',
|
|||
|
|
'NOFRAMES',
|
|||
|
|
'PLAINTEXT',
|
|||
|
|
]);
|
|||
|
|
/*@__PURE__*/ const WHITESPACE_SENSITIVE = new Set([
|
|||
|
|
'CODE',
|
|||
|
|
'OUTPUT',
|
|||
|
|
'PLAINTEXT',
|
|||
|
|
'PRE',
|
|||
|
|
'SCRIPT',
|
|||
|
|
'TEMPLATE',
|
|||
|
|
'TEXTAREA',
|
|||
|
|
]);
|
|||
|
|
/*@__PURE__*/ const EMPTY_ELEMENTS = new Set([
|
|||
|
|
'area',
|
|||
|
|
'base',
|
|||
|
|
'basefont',
|
|||
|
|
'bgsound',
|
|||
|
|
'br',
|
|||
|
|
'col',
|
|||
|
|
'embed',
|
|||
|
|
'frame',
|
|||
|
|
'hr',
|
|||
|
|
'img',
|
|||
|
|
'input',
|
|||
|
|
'keygen',
|
|||
|
|
'link',
|
|||
|
|
'meta',
|
|||
|
|
'param',
|
|||
|
|
'source',
|
|||
|
|
'trace',
|
|||
|
|
'wbr',
|
|||
|
|
]);
|
|||
|
|
/*@__PURE__*/ const REMOVE_EMPTY_ATTR = new Set(['class', 'dir', 'id', 'lang', 'name', 'title']);
|
|||
|
|
/*@__PURE__*/ const BOOLEAN_ATTR = new Set([
|
|||
|
|
'allowfullscreen',
|
|||
|
|
'async',
|
|||
|
|
'autofocus',
|
|||
|
|
'autoplay',
|
|||
|
|
'checked',
|
|||
|
|
'compact',
|
|||
|
|
'controls',
|
|||
|
|
'declare',
|
|||
|
|
'default',
|
|||
|
|
'defaultchecked',
|
|||
|
|
'defaultmuted',
|
|||
|
|
'defaultselected',
|
|||
|
|
'defer',
|
|||
|
|
'disabled',
|
|||
|
|
'enabled',
|
|||
|
|
'formnovalidate',
|
|||
|
|
'hidden',
|
|||
|
|
'indeterminate',
|
|||
|
|
'inert',
|
|||
|
|
'ismap',
|
|||
|
|
'itemscope',
|
|||
|
|
'loop',
|
|||
|
|
'multiple',
|
|||
|
|
'muted',
|
|||
|
|
'nohref',
|
|||
|
|
'nomodule',
|
|||
|
|
'noresize',
|
|||
|
|
'noshade',
|
|||
|
|
'novalidate',
|
|||
|
|
'nowrap',
|
|||
|
|
'open',
|
|||
|
|
'pauseonexit',
|
|||
|
|
'readonly',
|
|||
|
|
'required',
|
|||
|
|
'reversed',
|
|||
|
|
'scoped',
|
|||
|
|
'seamless',
|
|||
|
|
'selected',
|
|||
|
|
'sortable',
|
|||
|
|
'truespeed',
|
|||
|
|
'typemustmatch',
|
|||
|
|
'visible',
|
|||
|
|
]);
|
|||
|
|
/*@__PURE__*/ const STRUCTURE_ELEMENTS = new Set([
|
|||
|
|
'html',
|
|||
|
|
'body',
|
|||
|
|
'head',
|
|||
|
|
'iframe',
|
|||
|
|
'meta',
|
|||
|
|
'link',
|
|||
|
|
'base',
|
|||
|
|
'title',
|
|||
|
|
'script',
|
|||
|
|
'style',
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
class MockNode {
|
|||
|
|
constructor(ownerDocument, nodeType, nodeName, nodeValue) {
|
|||
|
|
this.ownerDocument = ownerDocument;
|
|||
|
|
this.nodeType = nodeType;
|
|||
|
|
this.nodeName = nodeName;
|
|||
|
|
this._nodeValue = nodeValue;
|
|||
|
|
this.parentNode = null;
|
|||
|
|
this.childNodes = [];
|
|||
|
|
}
|
|||
|
|
appendChild(newNode) {
|
|||
|
|
if (newNode.nodeType === 11 /* NODE_TYPES.DOCUMENT_FRAGMENT_NODE */) {
|
|||
|
|
const nodes = newNode.childNodes.slice();
|
|||
|
|
for (const child of nodes) {
|
|||
|
|
this.appendChild(child);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
newNode.remove();
|
|||
|
|
newNode.parentNode = this;
|
|||
|
|
this.childNodes.push(newNode);
|
|||
|
|
connectNode(this.ownerDocument, newNode);
|
|||
|
|
}
|
|||
|
|
return newNode;
|
|||
|
|
}
|
|||
|
|
append(...items) {
|
|||
|
|
items.forEach((item) => {
|
|||
|
|
const isNode = typeof item === 'object' && item !== null && 'nodeType' in item;
|
|||
|
|
this.appendChild(isNode ? item : this.ownerDocument.createTextNode(String(item)));
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
prepend(...items) {
|
|||
|
|
const firstChild = this.firstChild;
|
|||
|
|
items.forEach((item) => {
|
|||
|
|
const isNode = typeof item === 'object' && item !== null && 'nodeType' in item;
|
|||
|
|
if (firstChild) {
|
|||
|
|
this.insertBefore(isNode ? item : this.ownerDocument.createTextNode(String(item)), firstChild);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
cloneNode(deep) {
|
|||
|
|
throw new Error(`invalid node type to clone: ${this.nodeType}, deep: ${deep}`);
|
|||
|
|
}
|
|||
|
|
compareDocumentPosition(_other) {
|
|||
|
|
// unimplemented
|
|||
|
|
// https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition
|
|||
|
|
return -1;
|
|||
|
|
}
|
|||
|
|
get firstChild() {
|
|||
|
|
return this.childNodes[0] || null;
|
|||
|
|
}
|
|||
|
|
insertBefore(newNode, referenceNode) {
|
|||
|
|
if (newNode.nodeType === 11 /* NODE_TYPES.DOCUMENT_FRAGMENT_NODE */) {
|
|||
|
|
for (let i = 0, ii = newNode.childNodes.length; i < ii; i++) {
|
|||
|
|
insertBefore(this, newNode.childNodes[i], referenceNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
insertBefore(this, newNode, referenceNode);
|
|||
|
|
}
|
|||
|
|
return newNode;
|
|||
|
|
}
|
|||
|
|
get isConnected() {
|
|||
|
|
let node = this;
|
|||
|
|
while (node != null) {
|
|||
|
|
if (node.nodeType === 9 /* NODE_TYPES.DOCUMENT_NODE */) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
node = node.parentNode;
|
|||
|
|
if (node != null && node.nodeType === 11 /* NODE_TYPES.DOCUMENT_FRAGMENT_NODE */) {
|
|||
|
|
node = node.host;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
isSameNode(node) {
|
|||
|
|
return this === node;
|
|||
|
|
}
|
|||
|
|
get lastChild() {
|
|||
|
|
return this.childNodes[this.childNodes.length - 1] || null;
|
|||
|
|
}
|
|||
|
|
get nextSibling() {
|
|||
|
|
if (this.parentNode != null) {
|
|||
|
|
const index = this.parentNode.childNodes.indexOf(this) + 1;
|
|||
|
|
return this.parentNode.childNodes[index] || null;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
get nodeValue() {
|
|||
|
|
var _a;
|
|||
|
|
return (_a = this._nodeValue) !== null && _a !== void 0 ? _a : '';
|
|||
|
|
}
|
|||
|
|
set nodeValue(value) {
|
|||
|
|
this._nodeValue = value;
|
|||
|
|
}
|
|||
|
|
get parentElement() {
|
|||
|
|
return this.parentNode || null;
|
|||
|
|
}
|
|||
|
|
set parentElement(value) {
|
|||
|
|
this.parentNode = value;
|
|||
|
|
}
|
|||
|
|
get previousSibling() {
|
|||
|
|
if (this.parentNode != null) {
|
|||
|
|
const index = this.parentNode.childNodes.indexOf(this) - 1;
|
|||
|
|
return this.parentNode.childNodes[index] || null;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
contains(otherNode) {
|
|||
|
|
if (otherNode === this) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
const childNodes = Array.from(this.childNodes);
|
|||
|
|
if (childNodes.includes(otherNode)) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
return childNodes.some((node) => this.contains.bind(node)(otherNode));
|
|||
|
|
}
|
|||
|
|
removeChild(childNode) {
|
|||
|
|
const index = this.childNodes.indexOf(childNode);
|
|||
|
|
if (index > -1) {
|
|||
|
|
this.childNodes.splice(index, 1);
|
|||
|
|
if (this.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */) {
|
|||
|
|
const wasConnected = this.isConnected;
|
|||
|
|
childNode.parentNode = null;
|
|||
|
|
if (wasConnected === true) {
|
|||
|
|
disconnectNode(childNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
childNode.parentNode = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error(`node not found within childNodes during removeChild`);
|
|||
|
|
}
|
|||
|
|
return childNode;
|
|||
|
|
}
|
|||
|
|
remove() {
|
|||
|
|
if (this.parentNode != null) {
|
|||
|
|
this.parentNode.removeChild(this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
replaceChild(newChild, oldChild) {
|
|||
|
|
if (oldChild.parentNode === this) {
|
|||
|
|
this.insertBefore(newChild, oldChild);
|
|||
|
|
oldChild.remove();
|
|||
|
|
return newChild;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
get textContent() {
|
|||
|
|
var _a;
|
|||
|
|
return (_a = this._nodeValue) !== null && _a !== void 0 ? _a : '';
|
|||
|
|
}
|
|||
|
|
set textContent(value) {
|
|||
|
|
this._nodeValue = String(value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
MockNode.ELEMENT_NODE = 1;
|
|||
|
|
MockNode.TEXT_NODE = 3;
|
|||
|
|
MockNode.PROCESSING_INSTRUCTION_NODE = 7;
|
|||
|
|
MockNode.COMMENT_NODE = 8;
|
|||
|
|
MockNode.DOCUMENT_NODE = 9;
|
|||
|
|
MockNode.DOCUMENT_TYPE_NODE = 10;
|
|||
|
|
MockNode.DOCUMENT_FRAGMENT_NODE = 11;
|
|||
|
|
class MockNodeList {
|
|||
|
|
constructor(ownerDocument, childNodes, length) {
|
|||
|
|
this.ownerDocument = ownerDocument;
|
|||
|
|
this.childNodes = childNodes;
|
|||
|
|
this.length = length;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockElement extends MockNode {
|
|||
|
|
constructor(ownerDocument, nodeName) {
|
|||
|
|
super(ownerDocument, 1 /* NODE_TYPES.ELEMENT_NODE */, typeof nodeName === 'string' ? nodeName : null, null);
|
|||
|
|
this.namespaceURI = null;
|
|||
|
|
this.__shadowRoot = null;
|
|||
|
|
this.__attributeMap = null;
|
|||
|
|
}
|
|||
|
|
addEventListener(type, handler) {
|
|||
|
|
addEventListener(this, type, handler);
|
|||
|
|
}
|
|||
|
|
attachShadow(_opts) {
|
|||
|
|
const shadowRoot = this.ownerDocument.createDocumentFragment();
|
|||
|
|
this.shadowRoot = shadowRoot;
|
|||
|
|
return shadowRoot;
|
|||
|
|
}
|
|||
|
|
blur() {
|
|||
|
|
dispatchEvent(this, new MockFocusEvent('blur', { relatedTarget: null, bubbles: true, cancelable: true, composed: true }));
|
|||
|
|
}
|
|||
|
|
get shadowRoot() {
|
|||
|
|
return this.__shadowRoot || null;
|
|||
|
|
}
|
|||
|
|
set shadowRoot(shadowRoot) {
|
|||
|
|
if (shadowRoot != null) {
|
|||
|
|
shadowRoot.host = this;
|
|||
|
|
this.__shadowRoot = shadowRoot;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
delete this.__shadowRoot;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get attributes() {
|
|||
|
|
if (this.__attributeMap == null) {
|
|||
|
|
const attrMap = createAttributeProxy(false);
|
|||
|
|
this.__attributeMap = attrMap;
|
|||
|
|
return attrMap;
|
|||
|
|
}
|
|||
|
|
return this.__attributeMap;
|
|||
|
|
}
|
|||
|
|
set attributes(attrs) {
|
|||
|
|
this.__attributeMap = attrs;
|
|||
|
|
}
|
|||
|
|
get children() {
|
|||
|
|
return this.childNodes.filter((n) => n.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */);
|
|||
|
|
}
|
|||
|
|
get childElementCount() {
|
|||
|
|
return this.childNodes.filter((n) => n.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */).length;
|
|||
|
|
}
|
|||
|
|
get className() {
|
|||
|
|
return this.getAttributeNS(null, 'class') || '';
|
|||
|
|
}
|
|||
|
|
set className(value) {
|
|||
|
|
this.setAttributeNS(null, 'class', value);
|
|||
|
|
}
|
|||
|
|
get classList() {
|
|||
|
|
return new MockClassList(this);
|
|||
|
|
}
|
|||
|
|
click() {
|
|||
|
|
dispatchEvent(this, new MockEvent('click', { bubbles: true, cancelable: true, composed: true }));
|
|||
|
|
}
|
|||
|
|
cloneNode(_deep) {
|
|||
|
|
// implemented on MockElement.prototype from within element.ts
|
|||
|
|
// @ts-ignore - implemented on MockElement.prototype from within element.ts
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
closest(selector) {
|
|||
|
|
let elm = this;
|
|||
|
|
while (elm != null) {
|
|||
|
|
if (elm.matches(selector)) {
|
|||
|
|
return elm;
|
|||
|
|
}
|
|||
|
|
elm = elm.parentNode;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
get dataset() {
|
|||
|
|
return dataset(this);
|
|||
|
|
}
|
|||
|
|
get dir() {
|
|||
|
|
return this.getAttributeNS(null, 'dir') || '';
|
|||
|
|
}
|
|||
|
|
set dir(value) {
|
|||
|
|
this.setAttributeNS(null, 'dir', value);
|
|||
|
|
}
|
|||
|
|
dispatchEvent(ev) {
|
|||
|
|
return dispatchEvent(this, ev);
|
|||
|
|
}
|
|||
|
|
get firstElementChild() {
|
|||
|
|
return this.children[0] || null;
|
|||
|
|
}
|
|||
|
|
focus(_options) {
|
|||
|
|
dispatchEvent(this, new MockFocusEvent('focus', { relatedTarget: null, bubbles: true, cancelable: true, composed: true }));
|
|||
|
|
}
|
|||
|
|
getAttribute(attrName) {
|
|||
|
|
if (attrName === 'style') {
|
|||
|
|
if (this.__style != null && this.__style.length > 0) {
|
|||
|
|
return this.style.cssText;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
const attr = this.attributes.getNamedItem(attrName);
|
|||
|
|
if (attr != null) {
|
|||
|
|
return attr.value;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
getAttributeNS(namespaceURI, attrName) {
|
|||
|
|
const attr = this.attributes.getNamedItemNS(namespaceURI, attrName);
|
|||
|
|
if (attr != null) {
|
|||
|
|
return attr.value;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
getBoundingClientRect() {
|
|||
|
|
return { bottom: 0, height: 0, left: 0, right: 0, top: 0, width: 0, x: 0, y: 0 };
|
|||
|
|
}
|
|||
|
|
getRootNode(opts) {
|
|||
|
|
const isComposed = opts != null && opts.composed === true;
|
|||
|
|
let node = this;
|
|||
|
|
while (node.parentNode != null) {
|
|||
|
|
node = node.parentNode;
|
|||
|
|
if (isComposed === true && node.parentNode == null && node.host != null) {
|
|||
|
|
node = node.host;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return node;
|
|||
|
|
}
|
|||
|
|
get draggable() {
|
|||
|
|
return this.getAttributeNS(null, 'draggable') === 'true';
|
|||
|
|
}
|
|||
|
|
set draggable(value) {
|
|||
|
|
this.setAttributeNS(null, 'draggable', value);
|
|||
|
|
}
|
|||
|
|
hasChildNodes() {
|
|||
|
|
return this.childNodes.length > 0;
|
|||
|
|
}
|
|||
|
|
get id() {
|
|||
|
|
return this.getAttributeNS(null, 'id') || '';
|
|||
|
|
}
|
|||
|
|
set id(value) {
|
|||
|
|
this.setAttributeNS(null, 'id', value);
|
|||
|
|
}
|
|||
|
|
get innerHTML() {
|
|||
|
|
if (this.childNodes.length === 0) {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
return serializeNodeToHtml(this, {
|
|||
|
|
newLines: false,
|
|||
|
|
indentSpaces: 0,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
set innerHTML(html) {
|
|||
|
|
var _a;
|
|||
|
|
if (NON_ESCAPABLE_CONTENT.has((_a = this.nodeName) !== null && _a !== void 0 ? _a : '') === true) {
|
|||
|
|
setTextContent(this, html);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
for (let i = this.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
this.removeChild(this.childNodes[i]);
|
|||
|
|
}
|
|||
|
|
if (typeof html === 'string') {
|
|||
|
|
const frag = parseFragmentUtil(this.ownerDocument, html);
|
|||
|
|
while (frag.childNodes.length > 0) {
|
|||
|
|
this.appendChild(frag.childNodes[0]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get innerText() {
|
|||
|
|
const text = [];
|
|||
|
|
getTextContent(this.childNodes, text);
|
|||
|
|
return text.join('');
|
|||
|
|
}
|
|||
|
|
set innerText(value) {
|
|||
|
|
setTextContent(this, value);
|
|||
|
|
}
|
|||
|
|
insertAdjacentElement(position, elm) {
|
|||
|
|
if (position === 'beforebegin') {
|
|||
|
|
insertBefore(this.parentNode, elm, this);
|
|||
|
|
}
|
|||
|
|
else if (position === 'afterbegin') {
|
|||
|
|
this.prepend(elm);
|
|||
|
|
}
|
|||
|
|
else if (position === 'beforeend') {
|
|||
|
|
this.appendChild(elm);
|
|||
|
|
}
|
|||
|
|
else if (position === 'afterend') {
|
|||
|
|
insertBefore(this.parentNode, elm, this.nextSibling);
|
|||
|
|
}
|
|||
|
|
return elm;
|
|||
|
|
}
|
|||
|
|
insertAdjacentHTML(position, html) {
|
|||
|
|
const frag = parseFragmentUtil(this.ownerDocument, html);
|
|||
|
|
if (position === 'beforebegin') {
|
|||
|
|
while (frag.childNodes.length > 0) {
|
|||
|
|
insertBefore(this.parentNode, frag.childNodes[0], this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (position === 'afterbegin') {
|
|||
|
|
while (frag.childNodes.length > 0) {
|
|||
|
|
this.prepend(frag.childNodes[frag.childNodes.length - 1]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (position === 'beforeend') {
|
|||
|
|
while (frag.childNodes.length > 0) {
|
|||
|
|
this.appendChild(frag.childNodes[0]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (position === 'afterend') {
|
|||
|
|
while (frag.childNodes.length > 0) {
|
|||
|
|
insertBefore(this.parentNode, frag.childNodes[frag.childNodes.length - 1], this.nextSibling);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
insertAdjacentText(position, text) {
|
|||
|
|
const elm = this.ownerDocument.createTextNode(text);
|
|||
|
|
if (position === 'beforebegin') {
|
|||
|
|
insertBefore(this.parentNode, elm, this);
|
|||
|
|
}
|
|||
|
|
else if (position === 'afterbegin') {
|
|||
|
|
this.prepend(elm);
|
|||
|
|
}
|
|||
|
|
else if (position === 'beforeend') {
|
|||
|
|
this.appendChild(elm);
|
|||
|
|
}
|
|||
|
|
else if (position === 'afterend') {
|
|||
|
|
insertBefore(this.parentNode, elm, this.nextSibling);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
hasAttribute(attrName) {
|
|||
|
|
if (attrName === 'style') {
|
|||
|
|
return this.__style != null && this.__style.length > 0;
|
|||
|
|
}
|
|||
|
|
return this.getAttribute(attrName) !== null;
|
|||
|
|
}
|
|||
|
|
hasAttributeNS(namespaceURI, name) {
|
|||
|
|
return this.getAttributeNS(namespaceURI, name) !== null;
|
|||
|
|
}
|
|||
|
|
get hidden() {
|
|||
|
|
return this.hasAttributeNS(null, 'hidden');
|
|||
|
|
}
|
|||
|
|
set hidden(isHidden) {
|
|||
|
|
if (isHidden === true) {
|
|||
|
|
this.setAttributeNS(null, 'hidden', '');
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.removeAttributeNS(null, 'hidden');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get lang() {
|
|||
|
|
return this.getAttributeNS(null, 'lang') || '';
|
|||
|
|
}
|
|||
|
|
set lang(value) {
|
|||
|
|
this.setAttributeNS(null, 'lang', value);
|
|||
|
|
}
|
|||
|
|
get lastElementChild() {
|
|||
|
|
const children = this.children;
|
|||
|
|
return children[children.length - 1] || null;
|
|||
|
|
}
|
|||
|
|
matches(selector) {
|
|||
|
|
return matches(selector, this);
|
|||
|
|
}
|
|||
|
|
get nextElementSibling() {
|
|||
|
|
const parentElement = this.parentElement;
|
|||
|
|
if (parentElement != null &&
|
|||
|
|
(parentElement.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */ ||
|
|||
|
|
parentElement.nodeType === 11 /* NODE_TYPES.DOCUMENT_FRAGMENT_NODE */ ||
|
|||
|
|
parentElement.nodeType === 9 /* NODE_TYPES.DOCUMENT_NODE */)) {
|
|||
|
|
const children = parentElement.children;
|
|||
|
|
const index = children.indexOf(this) + 1;
|
|||
|
|
return parentElement.children[index] || null;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
get outerHTML() {
|
|||
|
|
return serializeNodeToHtml(this, {
|
|||
|
|
newLines: false,
|
|||
|
|
outerHtml: true,
|
|||
|
|
indentSpaces: 0,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
get previousElementSibling() {
|
|||
|
|
const parentElement = this.parentElement;
|
|||
|
|
if (parentElement != null &&
|
|||
|
|
(parentElement.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */ ||
|
|||
|
|
parentElement.nodeType === 11 /* NODE_TYPES.DOCUMENT_FRAGMENT_NODE */ ||
|
|||
|
|
parentElement.nodeType === 9 /* NODE_TYPES.DOCUMENT_NODE */)) {
|
|||
|
|
const children = parentElement.children;
|
|||
|
|
const index = children.indexOf(this) - 1;
|
|||
|
|
return parentElement.children[index] || null;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
getElementsByClassName(classNames) {
|
|||
|
|
const classes = classNames
|
|||
|
|
.trim()
|
|||
|
|
.split(' ')
|
|||
|
|
.filter((c) => c.length > 0);
|
|||
|
|
const results = [];
|
|||
|
|
getElementsByClassName(this, classes, results);
|
|||
|
|
return results;
|
|||
|
|
}
|
|||
|
|
getElementsByTagName(tagName) {
|
|||
|
|
const results = [];
|
|||
|
|
getElementsByTagName(this, tagName.toLowerCase(), results);
|
|||
|
|
return results;
|
|||
|
|
}
|
|||
|
|
querySelector(selector) {
|
|||
|
|
return selectOne(selector, this);
|
|||
|
|
}
|
|||
|
|
querySelectorAll(selector) {
|
|||
|
|
return selectAll(selector, this);
|
|||
|
|
}
|
|||
|
|
removeAttribute(attrName) {
|
|||
|
|
if (attrName === 'style') {
|
|||
|
|
delete this.__style;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
const attr = this.attributes.getNamedItem(attrName);
|
|||
|
|
if (attr != null) {
|
|||
|
|
this.attributes.removeNamedItemNS(attr);
|
|||
|
|
if (checkAttributeChanged(this) === true) {
|
|||
|
|
attributeChanged(this, attrName, attr.value, null);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
removeAttributeNS(namespaceURI, attrName) {
|
|||
|
|
const attr = this.attributes.getNamedItemNS(namespaceURI, attrName);
|
|||
|
|
if (attr != null) {
|
|||
|
|
this.attributes.removeNamedItemNS(attr);
|
|||
|
|
if (checkAttributeChanged(this) === true) {
|
|||
|
|
attributeChanged(this, attrName, attr.value, null);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
removeEventListener(type, handler) {
|
|||
|
|
removeEventListener(this, type, handler);
|
|||
|
|
}
|
|||
|
|
setAttribute(attrName, value) {
|
|||
|
|
if (attrName === 'style') {
|
|||
|
|
this.style = value;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
const attributes = this.attributes;
|
|||
|
|
let attr = attributes.getNamedItem(attrName);
|
|||
|
|
const checkAttrChanged = checkAttributeChanged(this);
|
|||
|
|
if (attr != null) {
|
|||
|
|
if (checkAttrChanged === true) {
|
|||
|
|
const oldValue = attr.value;
|
|||
|
|
attr.value = value;
|
|||
|
|
if (oldValue !== attr.value) {
|
|||
|
|
attributeChanged(this, attr.name, oldValue, attr.value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
attr.value = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
if (attributes.caseInsensitive) {
|
|||
|
|
attrName = attrName.toLowerCase();
|
|||
|
|
}
|
|||
|
|
attr = new MockAttr(attrName, value);
|
|||
|
|
attributes.__items.push(attr);
|
|||
|
|
if (checkAttrChanged === true) {
|
|||
|
|
attributeChanged(this, attrName, null, attr.value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
setAttributeNS(namespaceURI, attrName, value) {
|
|||
|
|
const attributes = this.attributes;
|
|||
|
|
let attr = attributes.getNamedItemNS(namespaceURI, attrName);
|
|||
|
|
const checkAttrChanged = checkAttributeChanged(this);
|
|||
|
|
if (attr != null) {
|
|||
|
|
if (checkAttrChanged === true) {
|
|||
|
|
const oldValue = attr.value;
|
|||
|
|
attr.value = value;
|
|||
|
|
if (oldValue !== attr.value) {
|
|||
|
|
attributeChanged(this, attr.name, oldValue, attr.value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
attr.value = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
attr = new MockAttr(attrName, value, namespaceURI);
|
|||
|
|
attributes.__items.push(attr);
|
|||
|
|
if (checkAttrChanged === true) {
|
|||
|
|
attributeChanged(this, attrName, null, attr.value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get style() {
|
|||
|
|
if (this.__style == null) {
|
|||
|
|
this.__style = createCSSStyleDeclaration();
|
|||
|
|
}
|
|||
|
|
return this.__style;
|
|||
|
|
}
|
|||
|
|
set style(val) {
|
|||
|
|
if (typeof val === 'string') {
|
|||
|
|
if (this.__style == null) {
|
|||
|
|
this.__style = createCSSStyleDeclaration();
|
|||
|
|
}
|
|||
|
|
this.__style.cssText = val;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.__style = val;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get tabIndex() {
|
|||
|
|
return parseInt(this.getAttributeNS(null, 'tabindex') || '-1', 10);
|
|||
|
|
}
|
|||
|
|
set tabIndex(value) {
|
|||
|
|
this.setAttributeNS(null, 'tabindex', value);
|
|||
|
|
}
|
|||
|
|
get tagName() {
|
|||
|
|
var _a;
|
|||
|
|
return (_a = this.nodeName) !== null && _a !== void 0 ? _a : '';
|
|||
|
|
}
|
|||
|
|
set tagName(value) {
|
|||
|
|
this.nodeName = value;
|
|||
|
|
}
|
|||
|
|
get textContent() {
|
|||
|
|
const text = [];
|
|||
|
|
getTextContent(this.childNodes, text);
|
|||
|
|
return text.join('');
|
|||
|
|
}
|
|||
|
|
set textContent(value) {
|
|||
|
|
setTextContent(this, value);
|
|||
|
|
}
|
|||
|
|
get title() {
|
|||
|
|
return this.getAttributeNS(null, 'title') || '';
|
|||
|
|
}
|
|||
|
|
set title(value) {
|
|||
|
|
this.setAttributeNS(null, 'title', value);
|
|||
|
|
}
|
|||
|
|
animate() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onanimationstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onanimationend() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onanimationiteration() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onabort() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onauxclick() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onbeforecopy() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onbeforecut() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onbeforepaste() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onblur() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncancel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncanplay() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncanplaythrough() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onclick() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onclose() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncontextmenu() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncopy() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncuechange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncut() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondblclick() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondrag() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragend() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragenter() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragleave() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragover() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondrop() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondurationchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onemptied() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onended() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onerror() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfocus() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfocusin() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfocusout() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onformdata() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfullscreenchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfullscreenerror() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ongotpointercapture() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oninput() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oninvalid() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onkeydown() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onkeypress() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onkeyup() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onload() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onloadeddata() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onloadedmetadata() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onloadstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onlostpointercapture() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmousedown() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseenter() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseleave() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmousemove() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseout() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseover() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseup() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmousewheel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpaste() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpause() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onplay() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onplaying() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointercancel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerdown() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerenter() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerleave() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointermove() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerout() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerover() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerup() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onprogress() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onratechange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onreset() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onresize() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onscroll() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onsearch() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onseeked() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onseeking() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onselect() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onselectstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onstalled() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onsubmit() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onsuspend() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ontimeupdate() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ontoggle() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onvolumechange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwaiting() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwebkitfullscreenchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwebkitfullscreenerror() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwheel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
requestFullscreen() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
scrollBy() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
scrollTo() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
scrollIntoView() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
toString(opts) {
|
|||
|
|
return serializeNodeToHtml(this, opts);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getElementsByClassName(elm, classNames, foundElms) {
|
|||
|
|
const children = elm.children;
|
|||
|
|
for (let i = 0, ii = children.length; i < ii; i++) {
|
|||
|
|
const childElm = children[i];
|
|||
|
|
for (let j = 0, jj = classNames.length; j < jj; j++) {
|
|||
|
|
if (childElm.classList.contains(classNames[j])) {
|
|||
|
|
foundElms.push(childElm);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
getElementsByClassName(childElm, classNames, foundElms);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getElementsByTagName(elm, tagName, foundElms) {
|
|||
|
|
var _a;
|
|||
|
|
const children = elm.children;
|
|||
|
|
for (let i = 0, ii = children.length; i < ii; i++) {
|
|||
|
|
const childElm = children[i];
|
|||
|
|
if (tagName === '*' || ((_a = childElm.nodeName) !== null && _a !== void 0 ? _a : '').toLowerCase() === tagName) {
|
|||
|
|
foundElms.push(childElm);
|
|||
|
|
}
|
|||
|
|
getElementsByTagName(childElm, tagName, foundElms);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function resetElement(elm) {
|
|||
|
|
resetEventListeners(elm);
|
|||
|
|
delete elm.__attributeMap;
|
|||
|
|
delete elm.__shadowRoot;
|
|||
|
|
delete elm.__style;
|
|||
|
|
}
|
|||
|
|
function insertBefore(parentNode, newNode, referenceNode) {
|
|||
|
|
if (newNode !== referenceNode) {
|
|||
|
|
newNode.remove();
|
|||
|
|
newNode.parentNode = parentNode;
|
|||
|
|
newNode.ownerDocument = parentNode.ownerDocument;
|
|||
|
|
if (referenceNode != null) {
|
|||
|
|
const index = parentNode.childNodes.indexOf(referenceNode);
|
|||
|
|
if (index > -1) {
|
|||
|
|
parentNode.childNodes.splice(index, 0, newNode);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
throw new Error(`referenceNode not found in parentNode.childNodes`);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
parentNode.childNodes.push(newNode);
|
|||
|
|
}
|
|||
|
|
connectNode(parentNode.ownerDocument, newNode);
|
|||
|
|
}
|
|||
|
|
return newNode;
|
|||
|
|
}
|
|||
|
|
class MockHTMLElement extends MockElement {
|
|||
|
|
constructor(ownerDocument, nodeName) {
|
|||
|
|
super(ownerDocument, typeof nodeName === 'string' ? nodeName.toUpperCase() : null);
|
|||
|
|
this.namespaceURI = 'http://www.w3.org/1999/xhtml';
|
|||
|
|
}
|
|||
|
|
get tagName() {
|
|||
|
|
var _a;
|
|||
|
|
return (_a = this.nodeName) !== null && _a !== void 0 ? _a : '';
|
|||
|
|
}
|
|||
|
|
set tagName(value) {
|
|||
|
|
this.nodeName = value;
|
|||
|
|
}
|
|||
|
|
get attributes() {
|
|||
|
|
if (this.__attributeMap == null) {
|
|||
|
|
const attrMap = createAttributeProxy(true);
|
|||
|
|
this.__attributeMap = attrMap;
|
|||
|
|
return attrMap;
|
|||
|
|
}
|
|||
|
|
return this.__attributeMap;
|
|||
|
|
}
|
|||
|
|
set attributes(attrs) {
|
|||
|
|
this.__attributeMap = attrs;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockTextNode extends MockNode {
|
|||
|
|
constructor(ownerDocument, text) {
|
|||
|
|
super(ownerDocument, 3 /* NODE_TYPES.TEXT_NODE */, "#text" /* NODE_NAMES.TEXT_NODE */, text);
|
|||
|
|
}
|
|||
|
|
cloneNode(_deep) {
|
|||
|
|
return new MockTextNode(null, this.nodeValue);
|
|||
|
|
}
|
|||
|
|
get textContent() {
|
|||
|
|
return this.nodeValue;
|
|||
|
|
}
|
|||
|
|
set textContent(text) {
|
|||
|
|
this.nodeValue = text;
|
|||
|
|
}
|
|||
|
|
get data() {
|
|||
|
|
return this.nodeValue;
|
|||
|
|
}
|
|||
|
|
set data(text) {
|
|||
|
|
this.nodeValue = text;
|
|||
|
|
}
|
|||
|
|
get wholeText() {
|
|||
|
|
if (this.parentNode != null) {
|
|||
|
|
const text = [];
|
|||
|
|
for (let i = 0, ii = this.parentNode.childNodes.length; i < ii; i++) {
|
|||
|
|
const childNode = this.parentNode.childNodes[i];
|
|||
|
|
if (childNode.nodeType === 3 /* NODE_TYPES.TEXT_NODE */) {
|
|||
|
|
text.push(childNode.nodeValue);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return text.join('');
|
|||
|
|
}
|
|||
|
|
return this.nodeValue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getTextContent(childNodes, text) {
|
|||
|
|
for (let i = 0, ii = childNodes.length; i < ii; i++) {
|
|||
|
|
const childNode = childNodes[i];
|
|||
|
|
if (childNode.nodeType === 3 /* NODE_TYPES.TEXT_NODE */) {
|
|||
|
|
text.push(childNode.nodeValue);
|
|||
|
|
}
|
|||
|
|
else if (childNode.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */) {
|
|||
|
|
getTextContent(childNode.childNodes, text);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function setTextContent(elm, text) {
|
|||
|
|
for (let i = elm.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
elm.removeChild(elm.childNodes[i]);
|
|||
|
|
}
|
|||
|
|
const textNode = new MockTextNode(elm.ownerDocument, text);
|
|||
|
|
elm.appendChild(textNode);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockComment extends MockNode {
|
|||
|
|
constructor(ownerDocument, data) {
|
|||
|
|
super(ownerDocument, 8 /* NODE_TYPES.COMMENT_NODE */, "#comment" /* NODE_NAMES.COMMENT_NODE */, data);
|
|||
|
|
}
|
|||
|
|
cloneNode(_deep) {
|
|||
|
|
return new MockComment(null, this.nodeValue);
|
|||
|
|
}
|
|||
|
|
get textContent() {
|
|||
|
|
return this.nodeValue;
|
|||
|
|
}
|
|||
|
|
set textContent(text) {
|
|||
|
|
this.nodeValue = text;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockDocumentFragment extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, null);
|
|||
|
|
this.nodeName = "#document-fragment" /* NODE_NAMES.DOCUMENT_FRAGMENT_NODE */;
|
|||
|
|
this.nodeType = 11 /* NODE_TYPES.DOCUMENT_FRAGMENT_NODE */;
|
|||
|
|
}
|
|||
|
|
getElementById(id) {
|
|||
|
|
return getElementById(this, id);
|
|||
|
|
}
|
|||
|
|
cloneNode(deep) {
|
|||
|
|
const cloned = new MockDocumentFragment(null);
|
|||
|
|
if (deep) {
|
|||
|
|
for (let i = 0, ii = this.childNodes.length; i < ii; i++) {
|
|||
|
|
const childNode = this.childNodes[i];
|
|||
|
|
if (childNode.nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */ ||
|
|||
|
|
childNode.nodeType === 3 /* NODE_TYPES.TEXT_NODE */ ||
|
|||
|
|
childNode.nodeType === 8 /* NODE_TYPES.COMMENT_NODE */) {
|
|||
|
|
const clonedChildNode = this.childNodes[i].cloneNode(true);
|
|||
|
|
cloned.appendChild(clonedChildNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return cloned;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockDocumentTypeNode extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, '!DOCTYPE');
|
|||
|
|
this.nodeType = 10 /* NODE_TYPES.DOCUMENT_TYPE_NODE */;
|
|||
|
|
this.setAttribute('html', '');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockCSSRule {
|
|||
|
|
constructor(parentStyleSheet) {
|
|||
|
|
this.parentStyleSheet = parentStyleSheet;
|
|||
|
|
this.cssText = '';
|
|||
|
|
this.type = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockCSSStyleSheet {
|
|||
|
|
constructor(ownerNode) {
|
|||
|
|
this.type = 'text/css';
|
|||
|
|
this.parentStyleSheet = null;
|
|||
|
|
this.cssRules = [];
|
|||
|
|
this.ownerNode = ownerNode;
|
|||
|
|
}
|
|||
|
|
get rules() {
|
|||
|
|
return this.cssRules;
|
|||
|
|
}
|
|||
|
|
set rules(rules) {
|
|||
|
|
this.cssRules = rules;
|
|||
|
|
}
|
|||
|
|
deleteRule(index) {
|
|||
|
|
if (index >= 0 && index < this.cssRules.length) {
|
|||
|
|
this.cssRules.splice(index, 1);
|
|||
|
|
updateStyleTextNode(this.ownerNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
insertRule(rule, index = 0) {
|
|||
|
|
if (typeof index !== 'number') {
|
|||
|
|
index = 0;
|
|||
|
|
}
|
|||
|
|
if (index < 0) {
|
|||
|
|
index = 0;
|
|||
|
|
}
|
|||
|
|
if (index > this.cssRules.length) {
|
|||
|
|
index = this.cssRules.length;
|
|||
|
|
}
|
|||
|
|
const cssRule = new MockCSSRule(this);
|
|||
|
|
cssRule.cssText = rule;
|
|||
|
|
this.cssRules.splice(index, 0, cssRule);
|
|||
|
|
updateStyleTextNode(this.ownerNode);
|
|||
|
|
return index;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function getStyleElementText(styleElm) {
|
|||
|
|
const output = [];
|
|||
|
|
for (let i = 0; i < styleElm.childNodes.length; i++) {
|
|||
|
|
output.push(styleElm.childNodes[i].nodeValue);
|
|||
|
|
}
|
|||
|
|
return output.join('');
|
|||
|
|
}
|
|||
|
|
function setStyleElementText(styleElm, text) {
|
|||
|
|
// keeping the innerHTML and the sheet.cssRules connected
|
|||
|
|
// is not technically correct, but since we're doing
|
|||
|
|
// SSR we'll need to turn any assigned cssRules into
|
|||
|
|
// real text, not just properties that aren't rendered
|
|||
|
|
const sheet = styleElm.sheet;
|
|||
|
|
sheet.cssRules.length = 0;
|
|||
|
|
sheet.insertRule(text);
|
|||
|
|
updateStyleTextNode(styleElm);
|
|||
|
|
}
|
|||
|
|
function updateStyleTextNode(styleElm) {
|
|||
|
|
const childNodeLen = styleElm.childNodes.length;
|
|||
|
|
if (childNodeLen > 1) {
|
|||
|
|
for (let i = childNodeLen - 1; i >= 1; i--) {
|
|||
|
|
styleElm.removeChild(styleElm.childNodes[i]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (childNodeLen < 1) {
|
|||
|
|
styleElm.appendChild(styleElm.ownerDocument.createTextNode(''));
|
|||
|
|
}
|
|||
|
|
const textNode = styleElm.childNodes[0];
|
|||
|
|
textNode.nodeValue = styleElm.sheet.cssRules.map((r) => r.cssText).join('\n');
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function createElement(ownerDocument, tagName) {
|
|||
|
|
if (typeof tagName !== 'string' || tagName === '' || !/^[a-z0-9-_:]+$/i.test(tagName)) {
|
|||
|
|
throw new Error(`The tag name provided (${tagName}) is not a valid name.`);
|
|||
|
|
}
|
|||
|
|
tagName = tagName.toLowerCase();
|
|||
|
|
switch (tagName) {
|
|||
|
|
case 'a':
|
|||
|
|
return new MockAnchorElement(ownerDocument);
|
|||
|
|
case 'base':
|
|||
|
|
return new MockBaseElement(ownerDocument);
|
|||
|
|
case 'button':
|
|||
|
|
return new MockButtonElement(ownerDocument);
|
|||
|
|
case 'canvas':
|
|||
|
|
return new MockCanvasElement(ownerDocument);
|
|||
|
|
case 'form':
|
|||
|
|
return new MockFormElement(ownerDocument);
|
|||
|
|
case 'img':
|
|||
|
|
return new MockImageElement(ownerDocument);
|
|||
|
|
case 'input':
|
|||
|
|
return new MockInputElement(ownerDocument);
|
|||
|
|
case 'link':
|
|||
|
|
return new MockLinkElement(ownerDocument);
|
|||
|
|
case 'meta':
|
|||
|
|
return new MockMetaElement(ownerDocument);
|
|||
|
|
case 'script':
|
|||
|
|
return new MockScriptElement(ownerDocument);
|
|||
|
|
case 'style':
|
|||
|
|
return new MockStyleElement(ownerDocument);
|
|||
|
|
case 'template':
|
|||
|
|
return new MockTemplateElement(ownerDocument);
|
|||
|
|
case 'title':
|
|||
|
|
return new MockTitleElement(ownerDocument);
|
|||
|
|
}
|
|||
|
|
if (ownerDocument != null && tagName.includes('-')) {
|
|||
|
|
const win = ownerDocument.defaultView;
|
|||
|
|
if (win != null && win.customElements != null) {
|
|||
|
|
return createCustomElement(win.customElements, ownerDocument, tagName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return new MockHTMLElement(ownerDocument, tagName);
|
|||
|
|
}
|
|||
|
|
function createElementNS(ownerDocument, namespaceURI, tagName) {
|
|||
|
|
if (namespaceURI === 'http://www.w3.org/1999/xhtml') {
|
|||
|
|
return createElement(ownerDocument, tagName);
|
|||
|
|
}
|
|||
|
|
else if (namespaceURI === 'http://www.w3.org/2000/svg') {
|
|||
|
|
switch (tagName.toLowerCase()) {
|
|||
|
|
case 'text':
|
|||
|
|
case 'tspan':
|
|||
|
|
case 'tref':
|
|||
|
|
case 'altglyph':
|
|||
|
|
case 'textpath':
|
|||
|
|
return new MockSVGTextContentElement(ownerDocument, tagName);
|
|||
|
|
case 'circle':
|
|||
|
|
case 'ellipse':
|
|||
|
|
case 'image':
|
|||
|
|
case 'line':
|
|||
|
|
case 'path':
|
|||
|
|
case 'polygon':
|
|||
|
|
case 'polyline':
|
|||
|
|
case 'rect':
|
|||
|
|
case 'use':
|
|||
|
|
return new MockSVGGraphicsElement(ownerDocument, tagName);
|
|||
|
|
case 'svg':
|
|||
|
|
return new MockSVGSVGElement(ownerDocument, tagName);
|
|||
|
|
default:
|
|||
|
|
return new MockSVGElement(ownerDocument, tagName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
return new MockElement(ownerDocument, tagName);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockAnchorElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'a');
|
|||
|
|
}
|
|||
|
|
get href() {
|
|||
|
|
return fullUrl(this, 'href');
|
|||
|
|
}
|
|||
|
|
set href(value) {
|
|||
|
|
this.setAttribute('href', value);
|
|||
|
|
}
|
|||
|
|
get pathname() {
|
|||
|
|
return new URL(this.href).pathname;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockButtonElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'button');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockButtonElement.prototype, {
|
|||
|
|
type: String,
|
|||
|
|
}, {
|
|||
|
|
type: 'submit',
|
|||
|
|
});
|
|||
|
|
class MockImageElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'img');
|
|||
|
|
}
|
|||
|
|
get draggable() {
|
|||
|
|
return this.getAttributeNS(null, 'draggable') !== 'false';
|
|||
|
|
}
|
|||
|
|
set draggable(value) {
|
|||
|
|
this.setAttributeNS(null, 'draggable', value);
|
|||
|
|
}
|
|||
|
|
get src() {
|
|||
|
|
return fullUrl(this, 'src');
|
|||
|
|
}
|
|||
|
|
set src(value) {
|
|||
|
|
this.setAttribute('src', value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockImageElement.prototype, {
|
|||
|
|
height: Number,
|
|||
|
|
width: Number,
|
|||
|
|
});
|
|||
|
|
class MockInputElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'input');
|
|||
|
|
}
|
|||
|
|
get list() {
|
|||
|
|
const listId = this.getAttribute('list');
|
|||
|
|
if (listId) {
|
|||
|
|
return this.ownerDocument.getElementById(listId);
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockInputElement.prototype, {
|
|||
|
|
accept: String,
|
|||
|
|
autocomplete: String,
|
|||
|
|
autofocus: Boolean,
|
|||
|
|
capture: String,
|
|||
|
|
checked: Boolean,
|
|||
|
|
disabled: Boolean,
|
|||
|
|
form: String,
|
|||
|
|
formaction: String,
|
|||
|
|
formenctype: String,
|
|||
|
|
formmethod: String,
|
|||
|
|
formnovalidate: String,
|
|||
|
|
formtarget: String,
|
|||
|
|
height: Number,
|
|||
|
|
inputmode: String,
|
|||
|
|
max: String,
|
|||
|
|
maxLength: Number,
|
|||
|
|
min: String,
|
|||
|
|
minLength: Number,
|
|||
|
|
multiple: Boolean,
|
|||
|
|
name: String,
|
|||
|
|
pattern: String,
|
|||
|
|
placeholder: String,
|
|||
|
|
required: Boolean,
|
|||
|
|
readOnly: Boolean,
|
|||
|
|
size: Number,
|
|||
|
|
spellCheck: Boolean,
|
|||
|
|
src: String,
|
|||
|
|
step: String,
|
|||
|
|
type: String,
|
|||
|
|
value: String,
|
|||
|
|
width: Number,
|
|||
|
|
}, {
|
|||
|
|
type: 'text',
|
|||
|
|
});
|
|||
|
|
class MockFormElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'form');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockFormElement.prototype, {
|
|||
|
|
name: String,
|
|||
|
|
});
|
|||
|
|
class MockLinkElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'link');
|
|||
|
|
}
|
|||
|
|
get href() {
|
|||
|
|
return fullUrl(this, 'href');
|
|||
|
|
}
|
|||
|
|
set href(value) {
|
|||
|
|
this.setAttribute('href', value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockLinkElement.prototype, {
|
|||
|
|
crossorigin: String,
|
|||
|
|
media: String,
|
|||
|
|
rel: String,
|
|||
|
|
type: String,
|
|||
|
|
});
|
|||
|
|
class MockMetaElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'meta');
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockMetaElement.prototype, {
|
|||
|
|
charset: String,
|
|||
|
|
content: String,
|
|||
|
|
name: String,
|
|||
|
|
});
|
|||
|
|
class MockScriptElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'script');
|
|||
|
|
}
|
|||
|
|
get src() {
|
|||
|
|
return fullUrl(this, 'src');
|
|||
|
|
}
|
|||
|
|
set src(value) {
|
|||
|
|
this.setAttribute('src', value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
patchPropAttributes(MockScriptElement.prototype, {
|
|||
|
|
type: String,
|
|||
|
|
});
|
|||
|
|
class MockDOMMatrix {
|
|||
|
|
constructor() {
|
|||
|
|
this.a = 1;
|
|||
|
|
this.b = 0;
|
|||
|
|
this.c = 0;
|
|||
|
|
this.d = 1;
|
|||
|
|
this.e = 0;
|
|||
|
|
this.f = 0;
|
|||
|
|
this.m11 = 1;
|
|||
|
|
this.m12 = 0;
|
|||
|
|
this.m13 = 0;
|
|||
|
|
this.m14 = 0;
|
|||
|
|
this.m21 = 0;
|
|||
|
|
this.m22 = 1;
|
|||
|
|
this.m23 = 0;
|
|||
|
|
this.m24 = 0;
|
|||
|
|
this.m31 = 0;
|
|||
|
|
this.m32 = 0;
|
|||
|
|
this.m33 = 1;
|
|||
|
|
this.m34 = 0;
|
|||
|
|
this.m41 = 0;
|
|||
|
|
this.m42 = 0;
|
|||
|
|
this.m43 = 0;
|
|||
|
|
this.m44 = 1;
|
|||
|
|
this.is2D = true;
|
|||
|
|
this.isIdentity = true;
|
|||
|
|
}
|
|||
|
|
static fromMatrix() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
inverse() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
flipX() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
flipY() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
multiply() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
rotate() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
rotateAxisAngle() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
rotateFromVector() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
scale() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
scaleNonUniform() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
skewX() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
skewY() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
toJSON() { }
|
|||
|
|
toString() { }
|
|||
|
|
transformPoint() {
|
|||
|
|
return new MockDOMPoint();
|
|||
|
|
}
|
|||
|
|
translate() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockDOMPoint {
|
|||
|
|
constructor() {
|
|||
|
|
this.w = 1;
|
|||
|
|
this.x = 0;
|
|||
|
|
this.y = 0;
|
|||
|
|
this.z = 0;
|
|||
|
|
}
|
|||
|
|
toJSON() { }
|
|||
|
|
matrixTransform() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockSVGRect {
|
|||
|
|
constructor() {
|
|||
|
|
this.height = 10;
|
|||
|
|
this.width = 10;
|
|||
|
|
this.x = 0;
|
|||
|
|
this.y = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockStyleElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'style');
|
|||
|
|
this.sheet = new MockCSSStyleSheet(this);
|
|||
|
|
}
|
|||
|
|
get innerHTML() {
|
|||
|
|
return getStyleElementText(this);
|
|||
|
|
}
|
|||
|
|
set innerHTML(value) {
|
|||
|
|
setStyleElementText(this, value);
|
|||
|
|
}
|
|||
|
|
get innerText() {
|
|||
|
|
return getStyleElementText(this);
|
|||
|
|
}
|
|||
|
|
set innerText(value) {
|
|||
|
|
setStyleElementText(this, value);
|
|||
|
|
}
|
|||
|
|
get textContent() {
|
|||
|
|
return getStyleElementText(this);
|
|||
|
|
}
|
|||
|
|
set textContent(value) {
|
|||
|
|
setStyleElementText(this, value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockSVGElement extends MockElement {
|
|||
|
|
// SVGElement properties and methods
|
|||
|
|
get ownerSVGElement() {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
get viewportElement() {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
onunload() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
// SVGGeometryElement properties and methods
|
|||
|
|
get pathLength() {
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
isPointInFill(_pt) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
isPointInStroke(_pt) {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
getTotalLength() {
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockSVGGraphicsElement extends MockSVGElement {
|
|||
|
|
getBBox(_options) {
|
|||
|
|
return new MockSVGRect();
|
|||
|
|
}
|
|||
|
|
getCTM() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
getScreenCTM() {
|
|||
|
|
return new MockDOMMatrix();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockSVGSVGElement extends MockSVGGraphicsElement {
|
|||
|
|
createSVGPoint() {
|
|||
|
|
return new MockDOMPoint();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockSVGTextContentElement extends MockSVGGraphicsElement {
|
|||
|
|
getComputedTextLength() {
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockBaseElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'base');
|
|||
|
|
}
|
|||
|
|
get href() {
|
|||
|
|
return fullUrl(this, 'href');
|
|||
|
|
}
|
|||
|
|
set href(value) {
|
|||
|
|
this.setAttribute('href', value);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockTemplateElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'template');
|
|||
|
|
this.content = new MockDocumentFragment(ownerDocument);
|
|||
|
|
}
|
|||
|
|
get innerHTML() {
|
|||
|
|
return this.content.innerHTML;
|
|||
|
|
}
|
|||
|
|
set innerHTML(html) {
|
|||
|
|
this.content.innerHTML = html;
|
|||
|
|
}
|
|||
|
|
cloneNode(deep) {
|
|||
|
|
const cloned = new MockTemplateElement(null);
|
|||
|
|
cloned.attributes = cloneAttributes(this.attributes);
|
|||
|
|
const styleCssText = this.getAttribute('style');
|
|||
|
|
if (styleCssText != null && styleCssText.length > 0) {
|
|||
|
|
cloned.setAttribute('style', styleCssText);
|
|||
|
|
}
|
|||
|
|
cloned.content = this.content.cloneNode(deep);
|
|||
|
|
if (deep) {
|
|||
|
|
for (let i = 0, ii = this.childNodes.length; i < ii; i++) {
|
|||
|
|
const clonedChildNode = this.childNodes[i].cloneNode(true);
|
|||
|
|
cloned.appendChild(clonedChildNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return cloned;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockTitleElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'title');
|
|||
|
|
}
|
|||
|
|
get text() {
|
|||
|
|
return this.textContent;
|
|||
|
|
}
|
|||
|
|
set text(value) {
|
|||
|
|
this.textContent = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockCanvasElement extends MockHTMLElement {
|
|||
|
|
constructor(ownerDocument) {
|
|||
|
|
super(ownerDocument, 'canvas');
|
|||
|
|
}
|
|||
|
|
getContext() {
|
|||
|
|
return {
|
|||
|
|
fillRect() {
|
|||
|
|
return;
|
|||
|
|
},
|
|||
|
|
clearRect() { },
|
|||
|
|
getImageData: function (_, __, w, h) {
|
|||
|
|
return {
|
|||
|
|
data: new Array(w * h * 4),
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
putImageData() { },
|
|||
|
|
createImageData: function () {
|
|||
|
|
return [];
|
|||
|
|
},
|
|||
|
|
setTransform() { },
|
|||
|
|
drawImage() { },
|
|||
|
|
save() { },
|
|||
|
|
fillText() { },
|
|||
|
|
restore() { },
|
|||
|
|
beginPath() { },
|
|||
|
|
moveTo() { },
|
|||
|
|
lineTo() { },
|
|||
|
|
closePath() { },
|
|||
|
|
stroke() { },
|
|||
|
|
translate() { },
|
|||
|
|
scale() { },
|
|||
|
|
rotate() { },
|
|||
|
|
arc() { },
|
|||
|
|
fill() { },
|
|||
|
|
measureText() {
|
|||
|
|
return { width: 0 };
|
|||
|
|
},
|
|||
|
|
transform() { },
|
|||
|
|
rect() { },
|
|||
|
|
clip() { },
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function fullUrl(elm, attrName) {
|
|||
|
|
const val = elm.getAttribute(attrName) || '';
|
|||
|
|
if (elm.ownerDocument != null) {
|
|||
|
|
const win = elm.ownerDocument.defaultView;
|
|||
|
|
if (win != null) {
|
|||
|
|
const loc = win.location;
|
|||
|
|
if (loc != null) {
|
|||
|
|
try {
|
|||
|
|
const url = new URL(val, loc.href);
|
|||
|
|
return url.href;
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return val.replace(/\'|\"/g, '').trim();
|
|||
|
|
}
|
|||
|
|
function patchPropAttributes(prototype, attrs, defaults = {}) {
|
|||
|
|
Object.keys(attrs).forEach((propName) => {
|
|||
|
|
const attr = attrs[propName];
|
|||
|
|
const defaultValue = defaults[propName];
|
|||
|
|
if (attr === Boolean) {
|
|||
|
|
Object.defineProperty(prototype, propName, {
|
|||
|
|
get() {
|
|||
|
|
return this.hasAttribute(propName);
|
|||
|
|
},
|
|||
|
|
set(value) {
|
|||
|
|
if (value) {
|
|||
|
|
this.setAttribute(propName, '');
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.removeAttribute(propName);
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else if (attr === Number) {
|
|||
|
|
Object.defineProperty(prototype, propName, {
|
|||
|
|
get() {
|
|||
|
|
const value = this.getAttribute(propName);
|
|||
|
|
return value ? parseInt(value, 10) : defaultValue === undefined ? 0 : defaultValue;
|
|||
|
|
},
|
|||
|
|
set(value) {
|
|||
|
|
this.setAttribute(propName, value);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
Object.defineProperty(prototype, propName, {
|
|||
|
|
get() {
|
|||
|
|
return this.hasAttribute(propName) ? this.getAttribute(propName) : defaultValue || '';
|
|||
|
|
},
|
|||
|
|
set(value) {
|
|||
|
|
this.setAttribute(propName, value);
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
MockElement.prototype.cloneNode = function (deep) {
|
|||
|
|
// because we're creating elements, which extending specific HTML base classes there
|
|||
|
|
// is a MockElement circular reference that bundling has trouble dealing with so
|
|||
|
|
// the fix is to add cloneNode() to MockElement's prototype after the HTML classes
|
|||
|
|
const cloned = createElement(this.ownerDocument, this.nodeName);
|
|||
|
|
cloned.attributes = cloneAttributes(this.attributes);
|
|||
|
|
const styleCssText = this.getAttribute('style');
|
|||
|
|
if (styleCssText != null && styleCssText.length > 0) {
|
|||
|
|
cloned.setAttribute('style', styleCssText);
|
|||
|
|
}
|
|||
|
|
if (deep) {
|
|||
|
|
for (let i = 0, ii = this.childNodes.length; i < ii; i++) {
|
|||
|
|
const clonedChildNode = this.childNodes[i].cloneNode(true);
|
|||
|
|
cloned.appendChild(clonedChildNode);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return cloned;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
let sharedDocument;
|
|||
|
|
function parseHtmlToDocument(html, ownerDocument = null) {
|
|||
|
|
if (ownerDocument == null) {
|
|||
|
|
if (sharedDocument == null) {
|
|||
|
|
sharedDocument = new MockDocument();
|
|||
|
|
}
|
|||
|
|
ownerDocument = sharedDocument;
|
|||
|
|
}
|
|||
|
|
return parseDocumentUtil(ownerDocument, html);
|
|||
|
|
}
|
|||
|
|
function parseHtmlToFragment(html, ownerDocument = null) {
|
|||
|
|
if (ownerDocument == null) {
|
|||
|
|
if (sharedDocument == null) {
|
|||
|
|
sharedDocument = new MockDocument();
|
|||
|
|
}
|
|||
|
|
ownerDocument = sharedDocument;
|
|||
|
|
}
|
|||
|
|
return parseFragmentUtil(ownerDocument, html);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const consoleNoop = () => {
|
|||
|
|
/**/
|
|||
|
|
};
|
|||
|
|
function createConsole() {
|
|||
|
|
return {
|
|||
|
|
debug: consoleNoop,
|
|||
|
|
error: consoleNoop,
|
|||
|
|
info: consoleNoop,
|
|||
|
|
log: consoleNoop,
|
|||
|
|
warn: consoleNoop,
|
|||
|
|
dir: consoleNoop,
|
|||
|
|
dirxml: consoleNoop,
|
|||
|
|
table: consoleNoop,
|
|||
|
|
trace: consoleNoop,
|
|||
|
|
group: consoleNoop,
|
|||
|
|
groupCollapsed: consoleNoop,
|
|||
|
|
groupEnd: consoleNoop,
|
|||
|
|
clear: consoleNoop,
|
|||
|
|
count: consoleNoop,
|
|||
|
|
countReset: consoleNoop,
|
|||
|
|
assert: consoleNoop,
|
|||
|
|
profile: consoleNoop,
|
|||
|
|
profileEnd: consoleNoop,
|
|||
|
|
time: consoleNoop,
|
|||
|
|
timeLog: consoleNoop,
|
|||
|
|
timeEnd: consoleNoop,
|
|||
|
|
timeStamp: consoleNoop,
|
|||
|
|
context: consoleNoop,
|
|||
|
|
memory: consoleNoop,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockHeaders {
|
|||
|
|
constructor(init) {
|
|||
|
|
this._values = [];
|
|||
|
|
if (typeof init === 'object') {
|
|||
|
|
if (typeof init[Symbol.iterator] === 'function') {
|
|||
|
|
const kvs = [];
|
|||
|
|
for (const kv of init) {
|
|||
|
|
if (typeof kv[Symbol.iterator] === 'function') {
|
|||
|
|
kvs.push([...kv]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for (const kv of kvs) {
|
|||
|
|
this.append(kv[0], kv[1]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
for (const key in init) {
|
|||
|
|
this.append(key, init[key]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
append(key, value) {
|
|||
|
|
this._values.push([key, value + '']);
|
|||
|
|
}
|
|||
|
|
delete(key) {
|
|||
|
|
key = key.toLowerCase();
|
|||
|
|
for (let i = this._values.length - 1; i >= 0; i--) {
|
|||
|
|
if (this._values[i][0].toLowerCase() === key) {
|
|||
|
|
this._values.splice(i, 1);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
entries() {
|
|||
|
|
const entries = [];
|
|||
|
|
for (const kv of this.keys()) {
|
|||
|
|
entries.push([kv, this.get(kv)]);
|
|||
|
|
}
|
|||
|
|
let index = -1;
|
|||
|
|
return {
|
|||
|
|
next() {
|
|||
|
|
index++;
|
|||
|
|
return {
|
|||
|
|
value: entries[index],
|
|||
|
|
done: !entries[index],
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
[Symbol.iterator]() {
|
|||
|
|
return this;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
forEach(cb) {
|
|||
|
|
for (const kv of this.entries()) {
|
|||
|
|
cb(kv[1], kv[0]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get(key) {
|
|||
|
|
const rtn = [];
|
|||
|
|
key = key.toLowerCase();
|
|||
|
|
for (const kv of this._values) {
|
|||
|
|
if (kv[0].toLowerCase() === key) {
|
|||
|
|
rtn.push(kv[1]);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return rtn.length > 0 ? rtn.join(', ') : null;
|
|||
|
|
}
|
|||
|
|
has(key) {
|
|||
|
|
key = key.toLowerCase();
|
|||
|
|
for (const kv of this._values) {
|
|||
|
|
if (kv[0].toLowerCase() === key) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
keys() {
|
|||
|
|
const keys = [];
|
|||
|
|
for (const kv of this._values) {
|
|||
|
|
const key = kv[0].toLowerCase();
|
|||
|
|
if (!keys.includes(key)) {
|
|||
|
|
keys.push(key);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
let index = -1;
|
|||
|
|
return {
|
|||
|
|
next() {
|
|||
|
|
index++;
|
|||
|
|
return {
|
|||
|
|
value: keys[index],
|
|||
|
|
done: !keys[index],
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
[Symbol.iterator]() {
|
|||
|
|
return this;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
set(key, value) {
|
|||
|
|
for (const kv of this._values) {
|
|||
|
|
if (kv[0].toLowerCase() === key.toLowerCase()) {
|
|||
|
|
kv[1] = value + '';
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
this.append(key, value);
|
|||
|
|
}
|
|||
|
|
values() {
|
|||
|
|
const values = this._values;
|
|||
|
|
let index = -1;
|
|||
|
|
return {
|
|||
|
|
next() {
|
|||
|
|
index++;
|
|||
|
|
const done = !values[index];
|
|||
|
|
return {
|
|||
|
|
value: done ? undefined : values[index][1],
|
|||
|
|
done,
|
|||
|
|
};
|
|||
|
|
},
|
|||
|
|
[Symbol.iterator]() {
|
|||
|
|
return this;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
[Symbol.iterator]() {
|
|||
|
|
return this.entries();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockDOMParser {
|
|||
|
|
parseFromString(htmlToParse, mimeType) {
|
|||
|
|
if (mimeType !== 'text/html') {
|
|||
|
|
console.error('XML parsing not implemented yet, continuing as html');
|
|||
|
|
}
|
|||
|
|
return parseHtmlToDocument(htmlToParse);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockRequest {
|
|||
|
|
constructor(input, init = {}) {
|
|||
|
|
this._method = 'GET';
|
|||
|
|
this._url = '/';
|
|||
|
|
this.bodyUsed = false;
|
|||
|
|
this.cache = 'default';
|
|||
|
|
this.credentials = 'same-origin';
|
|||
|
|
this.integrity = '';
|
|||
|
|
this.keepalive = false;
|
|||
|
|
this.mode = 'cors';
|
|||
|
|
this.redirect = 'follow';
|
|||
|
|
this.referrer = 'about:client';
|
|||
|
|
this.referrerPolicy = '';
|
|||
|
|
if (typeof input === 'string') {
|
|||
|
|
this.url = input;
|
|||
|
|
}
|
|||
|
|
else if (input) {
|
|||
|
|
Object.assign(this, input);
|
|||
|
|
this.headers = new MockHeaders(input.headers);
|
|||
|
|
}
|
|||
|
|
Object.assign(this, init);
|
|||
|
|
if (init.headers) {
|
|||
|
|
this.headers = new MockHeaders(init.headers);
|
|||
|
|
}
|
|||
|
|
if (!this.headers) {
|
|||
|
|
this.headers = new MockHeaders();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get url() {
|
|||
|
|
if (typeof this._url === 'string') {
|
|||
|
|
return new URL(this._url, location.href).href;
|
|||
|
|
}
|
|||
|
|
return new URL('/', location.href).href;
|
|||
|
|
}
|
|||
|
|
set url(value) {
|
|||
|
|
this._url = value;
|
|||
|
|
}
|
|||
|
|
get method() {
|
|||
|
|
if (typeof this._method === 'string') {
|
|||
|
|
return this._method.toUpperCase();
|
|||
|
|
}
|
|||
|
|
return 'GET';
|
|||
|
|
}
|
|||
|
|
set method(value) {
|
|||
|
|
this._method = value;
|
|||
|
|
}
|
|||
|
|
clone() {
|
|||
|
|
const clone = { ...this };
|
|||
|
|
clone.headers = new MockHeaders(this.headers);
|
|||
|
|
return new MockRequest(clone);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
class MockResponse {
|
|||
|
|
constructor(body, init = {}) {
|
|||
|
|
this.ok = true;
|
|||
|
|
this.status = 200;
|
|||
|
|
this.statusText = '';
|
|||
|
|
this.type = 'default';
|
|||
|
|
this.url = '';
|
|||
|
|
this._body = body;
|
|||
|
|
if (init) {
|
|||
|
|
Object.assign(this, init);
|
|||
|
|
}
|
|||
|
|
this.headers = new MockHeaders(init.headers);
|
|||
|
|
}
|
|||
|
|
async json() {
|
|||
|
|
return JSON.parse(this._body);
|
|||
|
|
}
|
|||
|
|
async text() {
|
|||
|
|
return this._body;
|
|||
|
|
}
|
|||
|
|
clone() {
|
|||
|
|
const initClone = { ...this };
|
|||
|
|
initClone.headers = new MockHeaders(this.headers);
|
|||
|
|
return new MockResponse(this._body, initClone);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function setupGlobal(gbl) {
|
|||
|
|
if (gbl.window == null) {
|
|||
|
|
const win = (gbl.window = new MockWindow());
|
|||
|
|
WINDOW_FUNCTIONS.forEach((fnName) => {
|
|||
|
|
if (!(fnName in gbl)) {
|
|||
|
|
gbl[fnName] = win[fnName].bind(win);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
WINDOW_PROPS.forEach((propName) => {
|
|||
|
|
if (!(propName in gbl)) {
|
|||
|
|
Object.defineProperty(gbl, propName, {
|
|||
|
|
get() {
|
|||
|
|
return win[propName];
|
|||
|
|
},
|
|||
|
|
set(val) {
|
|||
|
|
win[propName] = val;
|
|||
|
|
},
|
|||
|
|
configurable: true,
|
|||
|
|
enumerable: true,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
GLOBAL_CONSTRUCTORS.forEach(([cstrName]) => {
|
|||
|
|
gbl[cstrName] = win[cstrName];
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
return gbl.window;
|
|||
|
|
}
|
|||
|
|
function teardownGlobal(gbl) {
|
|||
|
|
const win = gbl.window;
|
|||
|
|
if (win && typeof win.close === 'function') {
|
|||
|
|
win.close();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function patchWindow(winToBePatched) {
|
|||
|
|
const mockWin = new MockWindow(false);
|
|||
|
|
WINDOW_FUNCTIONS.forEach((fnName) => {
|
|||
|
|
if (typeof winToBePatched[fnName] !== 'function') {
|
|||
|
|
winToBePatched[fnName] = mockWin[fnName].bind(mockWin);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
WINDOW_PROPS.forEach((propName) => {
|
|||
|
|
if (winToBePatched === undefined) {
|
|||
|
|
Object.defineProperty(winToBePatched, propName, {
|
|||
|
|
get() {
|
|||
|
|
return mockWin[propName];
|
|||
|
|
},
|
|||
|
|
set(val) {
|
|||
|
|
mockWin[propName] = val;
|
|||
|
|
},
|
|||
|
|
configurable: true,
|
|||
|
|
enumerable: true,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
function addGlobalsToWindowPrototype(mockWinPrototype) {
|
|||
|
|
GLOBAL_CONSTRUCTORS.forEach(([cstrName, Cstr]) => {
|
|||
|
|
Object.defineProperty(mockWinPrototype, cstrName, {
|
|||
|
|
get() {
|
|||
|
|
return this['__' + cstrName] || Cstr;
|
|||
|
|
},
|
|||
|
|
set(cstr) {
|
|||
|
|
this['__' + cstrName] = cstr;
|
|||
|
|
},
|
|||
|
|
configurable: true,
|
|||
|
|
enumerable: true,
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
const WINDOW_FUNCTIONS = [
|
|||
|
|
'addEventListener',
|
|||
|
|
'alert',
|
|||
|
|
'blur',
|
|||
|
|
'cancelAnimationFrame',
|
|||
|
|
'cancelIdleCallback',
|
|||
|
|
'clearInterval',
|
|||
|
|
'clearTimeout',
|
|||
|
|
'close',
|
|||
|
|
'confirm',
|
|||
|
|
'dispatchEvent',
|
|||
|
|
'focus',
|
|||
|
|
'getComputedStyle',
|
|||
|
|
'matchMedia',
|
|||
|
|
'open',
|
|||
|
|
'prompt',
|
|||
|
|
'removeEventListener',
|
|||
|
|
'requestAnimationFrame',
|
|||
|
|
'requestIdleCallback',
|
|||
|
|
'URL',
|
|||
|
|
];
|
|||
|
|
const WINDOW_PROPS = [
|
|||
|
|
'customElements',
|
|||
|
|
'devicePixelRatio',
|
|||
|
|
'document',
|
|||
|
|
'history',
|
|||
|
|
'innerHeight',
|
|||
|
|
'innerWidth',
|
|||
|
|
'localStorage',
|
|||
|
|
'location',
|
|||
|
|
'navigator',
|
|||
|
|
'pageXOffset',
|
|||
|
|
'pageYOffset',
|
|||
|
|
'performance',
|
|||
|
|
'screenLeft',
|
|||
|
|
'screenTop',
|
|||
|
|
'screenX',
|
|||
|
|
'screenY',
|
|||
|
|
'scrollX',
|
|||
|
|
'scrollY',
|
|||
|
|
'sessionStorage',
|
|||
|
|
'CSS',
|
|||
|
|
'CustomEvent',
|
|||
|
|
'Event',
|
|||
|
|
'Element',
|
|||
|
|
'HTMLElement',
|
|||
|
|
'Node',
|
|||
|
|
'NodeList',
|
|||
|
|
'FocusEvent',
|
|||
|
|
'KeyboardEvent',
|
|||
|
|
'MouseEvent',
|
|||
|
|
];
|
|||
|
|
const GLOBAL_CONSTRUCTORS = [
|
|||
|
|
['CustomEvent', MockCustomEvent],
|
|||
|
|
['Event', MockEvent],
|
|||
|
|
['Headers', MockHeaders],
|
|||
|
|
['FocusEvent', MockFocusEvent],
|
|||
|
|
['KeyboardEvent', MockKeyboardEvent],
|
|||
|
|
['MouseEvent', MockMouseEvent],
|
|||
|
|
['Request', MockRequest],
|
|||
|
|
['Response', MockResponse],
|
|||
|
|
['DOMParser', MockDOMParser],
|
|||
|
|
['HTMLAnchorElement', MockAnchorElement],
|
|||
|
|
['HTMLBaseElement', MockBaseElement],
|
|||
|
|
['HTMLButtonElement', MockButtonElement],
|
|||
|
|
['HTMLCanvasElement', MockCanvasElement],
|
|||
|
|
['HTMLFormElement', MockFormElement],
|
|||
|
|
['HTMLImageElement', MockImageElement],
|
|||
|
|
['HTMLInputElement', MockInputElement],
|
|||
|
|
['HTMLLinkElement', MockLinkElement],
|
|||
|
|
['HTMLMetaElement', MockMetaElement],
|
|||
|
|
['HTMLScriptElement', MockScriptElement],
|
|||
|
|
['HTMLStyleElement', MockStyleElement],
|
|||
|
|
['HTMLTemplateElement', MockTemplateElement],
|
|||
|
|
['HTMLTitleElement', MockTitleElement],
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
class MockHistory {
|
|||
|
|
constructor() {
|
|||
|
|
this.items = [];
|
|||
|
|
}
|
|||
|
|
get length() {
|
|||
|
|
return this.items.length;
|
|||
|
|
}
|
|||
|
|
back() {
|
|||
|
|
this.go(-1);
|
|||
|
|
}
|
|||
|
|
forward() {
|
|||
|
|
this.go(1);
|
|||
|
|
}
|
|||
|
|
go(_value) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
pushState(_state, _title, _url) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
replaceState(_state, _title, _url) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockIntersectionObserver {
|
|||
|
|
constructor() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
disconnect() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
observe() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
takeRecords() {
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
unobserve() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockLocation {
|
|||
|
|
constructor() {
|
|||
|
|
this.ancestorOrigins = null;
|
|||
|
|
this.protocol = '';
|
|||
|
|
this.host = '';
|
|||
|
|
this.hostname = '';
|
|||
|
|
this.port = '';
|
|||
|
|
this.pathname = '';
|
|||
|
|
this.search = '';
|
|||
|
|
this.hash = '';
|
|||
|
|
this.username = '';
|
|||
|
|
this.password = '';
|
|||
|
|
this.origin = '';
|
|||
|
|
this._href = '';
|
|||
|
|
}
|
|||
|
|
get href() {
|
|||
|
|
return this._href;
|
|||
|
|
}
|
|||
|
|
set href(value) {
|
|||
|
|
const url = new URL(value, 'http://mockdoc.stenciljs.com');
|
|||
|
|
this._href = url.href;
|
|||
|
|
this.protocol = url.protocol;
|
|||
|
|
this.host = url.host;
|
|||
|
|
this.hostname = url.hostname;
|
|||
|
|
this.port = url.port;
|
|||
|
|
this.pathname = url.pathname;
|
|||
|
|
this.search = url.search;
|
|||
|
|
this.hash = url.hash;
|
|||
|
|
this.username = url.username;
|
|||
|
|
this.password = url.password;
|
|||
|
|
this.origin = url.origin;
|
|||
|
|
}
|
|||
|
|
assign(_url) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
reload(_forcedReload) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
replace(_url) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
toString() {
|
|||
|
|
return this.href;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockNavigator {
|
|||
|
|
constructor() {
|
|||
|
|
this.appCodeName = 'MockNavigator';
|
|||
|
|
this.appName = 'MockNavigator';
|
|||
|
|
this.appVersion = 'MockNavigator';
|
|||
|
|
this.platform = 'MockNavigator';
|
|||
|
|
this.userAgent = 'MockNavigator';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* https://developer.mozilla.org/en-US/docs/Web/API/Performance
|
|||
|
|
*/
|
|||
|
|
class MockPerformance {
|
|||
|
|
constructor() {
|
|||
|
|
this.timeOrigin = Date.now();
|
|||
|
|
this.eventCounts = new Map();
|
|||
|
|
}
|
|||
|
|
addEventListener() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
clearMarks() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
clearMeasures() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
clearResourceTimings() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
dispatchEvent() {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
getEntries() {
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
getEntriesByName() {
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
getEntriesByType() {
|
|||
|
|
return [];
|
|||
|
|
}
|
|||
|
|
// Stencil's implementation of `mark` is non-compliant with the `Performance` interface. Because Stencil will
|
|||
|
|
// instantiate an instance of this class and may attempt to assign it to a variable of type `Performance`, the return
|
|||
|
|
// type must match the `Performance` interface (rather than typing this function as returning `void` and ignoring the
|
|||
|
|
// associated errors returned by the type checker)
|
|||
|
|
// @ts-ignore
|
|||
|
|
mark() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
// Stencil's implementation of `measure` is non-compliant with the `Performance` interface. Because Stencil will
|
|||
|
|
// instantiate an instance of this class and may attempt to assign it to a variable of type `Performance`, the return
|
|||
|
|
// type must match the `Performance` interface (rather than typing this function as returning `void` and ignoring the
|
|||
|
|
// associated errors returned by the type checker)
|
|||
|
|
// @ts-ignore
|
|||
|
|
measure() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
get navigation() {
|
|||
|
|
return {};
|
|||
|
|
}
|
|||
|
|
now() {
|
|||
|
|
return Date.now() - this.timeOrigin;
|
|||
|
|
}
|
|||
|
|
get onresourcetimingbufferfull() {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
removeEventListener() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
setResourceTimingBufferSize() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
get timing() {
|
|||
|
|
return {};
|
|||
|
|
}
|
|||
|
|
toJSON() {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function resetPerformance(perf) {
|
|||
|
|
if (perf != null) {
|
|||
|
|
try {
|
|||
|
|
perf.timeOrigin = Date.now();
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockStorage {
|
|||
|
|
constructor() {
|
|||
|
|
this.items = new Map();
|
|||
|
|
}
|
|||
|
|
key(_value) {
|
|||
|
|
//
|
|||
|
|
}
|
|||
|
|
getItem(key) {
|
|||
|
|
key = String(key);
|
|||
|
|
if (this.items.has(key)) {
|
|||
|
|
return this.items.get(key);
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
setItem(key, value) {
|
|||
|
|
if (value == null) {
|
|||
|
|
value = 'null';
|
|||
|
|
}
|
|||
|
|
this.items.set(String(key), String(value));
|
|||
|
|
}
|
|||
|
|
removeItem(key) {
|
|||
|
|
this.items.delete(String(key));
|
|||
|
|
}
|
|||
|
|
clear() {
|
|||
|
|
this.items.clear();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const nativeClearInterval = clearInterval;
|
|||
|
|
const nativeClearTimeout = clearTimeout;
|
|||
|
|
const nativeSetInterval = setInterval;
|
|||
|
|
const nativeSetTimeout = setTimeout;
|
|||
|
|
const nativeURL = URL;
|
|||
|
|
class MockWindow {
|
|||
|
|
constructor(html = null) {
|
|||
|
|
if (html !== false) {
|
|||
|
|
this.document = new MockDocument(html, this);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.document = null;
|
|||
|
|
}
|
|||
|
|
this.performance = new MockPerformance();
|
|||
|
|
this.customElements = new MockCustomElementRegistry(this);
|
|||
|
|
this.console = createConsole();
|
|||
|
|
resetWindowDefaults(this);
|
|||
|
|
resetWindowDimensions(this);
|
|||
|
|
}
|
|||
|
|
addEventListener(type, handler) {
|
|||
|
|
addEventListener(this, type, handler);
|
|||
|
|
}
|
|||
|
|
alert(msg) {
|
|||
|
|
if (this.console) {
|
|||
|
|
this.console.debug(msg);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
console.debug(msg);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
blur() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
cancelAnimationFrame(id) {
|
|||
|
|
this.__clearTimeout(id);
|
|||
|
|
}
|
|||
|
|
cancelIdleCallback(id) {
|
|||
|
|
this.__clearTimeout(id);
|
|||
|
|
}
|
|||
|
|
get CharacterData() {
|
|||
|
|
if (this.__charDataCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__charDataCstr = class extends MockNode {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument, 0, 'test', '');
|
|||
|
|
throw new Error('Illegal constructor: cannot construct CharacterData');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__charDataCstr;
|
|||
|
|
}
|
|||
|
|
set CharacterData(charDataCstr) {
|
|||
|
|
this.__charDataCstr = charDataCstr;
|
|||
|
|
}
|
|||
|
|
clearInterval(id) {
|
|||
|
|
this.__clearInterval(id);
|
|||
|
|
}
|
|||
|
|
clearTimeout(id) {
|
|||
|
|
this.__clearTimeout(id);
|
|||
|
|
}
|
|||
|
|
close() {
|
|||
|
|
resetWindow(this);
|
|||
|
|
}
|
|||
|
|
confirm() {
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
get CSS() {
|
|||
|
|
return {
|
|||
|
|
supports: () => true,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
get Document() {
|
|||
|
|
if (this.__docCstr == null) {
|
|||
|
|
const win = this;
|
|||
|
|
this.__docCstr = class extends MockDocument {
|
|||
|
|
constructor() {
|
|||
|
|
super(false, win);
|
|||
|
|
throw new Error('Illegal constructor: cannot construct Document');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__docCstr;
|
|||
|
|
}
|
|||
|
|
set Document(docCstr) {
|
|||
|
|
this.__docCstr = docCstr;
|
|||
|
|
}
|
|||
|
|
get DocumentFragment() {
|
|||
|
|
if (this.__docFragCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__docFragCstr = class extends MockDocumentFragment {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument);
|
|||
|
|
throw new Error('Illegal constructor: cannot construct DocumentFragment');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__docFragCstr;
|
|||
|
|
}
|
|||
|
|
set DocumentFragment(docFragCstr) {
|
|||
|
|
this.__docFragCstr = docFragCstr;
|
|||
|
|
}
|
|||
|
|
get DocumentType() {
|
|||
|
|
if (this.__docTypeCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__docTypeCstr = class extends MockNode {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument, 0, 'test', '');
|
|||
|
|
throw new Error('Illegal constructor: cannot construct DocumentType');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__docTypeCstr;
|
|||
|
|
}
|
|||
|
|
set DocumentType(docTypeCstr) {
|
|||
|
|
this.__docTypeCstr = docTypeCstr;
|
|||
|
|
}
|
|||
|
|
get DOMTokenList() {
|
|||
|
|
if (this.__domTokenListCstr == null) {
|
|||
|
|
this.__domTokenListCstr = class MockDOMTokenList {
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__domTokenListCstr;
|
|||
|
|
}
|
|||
|
|
set DOMTokenList(domTokenListCstr) {
|
|||
|
|
this.__domTokenListCstr = domTokenListCstr;
|
|||
|
|
}
|
|||
|
|
dispatchEvent(ev) {
|
|||
|
|
return dispatchEvent(this, ev);
|
|||
|
|
}
|
|||
|
|
get Element() {
|
|||
|
|
if (this.__elementCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__elementCstr = class extends MockElement {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument, '');
|
|||
|
|
throw new Error('Illegal constructor: cannot construct Element');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__elementCstr;
|
|||
|
|
}
|
|||
|
|
fetch(input, init) {
|
|||
|
|
if (typeof fetch === 'function') {
|
|||
|
|
return fetch(input, init);
|
|||
|
|
}
|
|||
|
|
throw new Error(`fetch() not implemented`);
|
|||
|
|
}
|
|||
|
|
focus() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
getComputedStyle(_) {
|
|||
|
|
return {
|
|||
|
|
cssText: '',
|
|||
|
|
length: 0,
|
|||
|
|
parentRule: null,
|
|||
|
|
getPropertyPriority() {
|
|||
|
|
return null;
|
|||
|
|
},
|
|||
|
|
getPropertyValue() {
|
|||
|
|
return '';
|
|||
|
|
},
|
|||
|
|
item() {
|
|||
|
|
return null;
|
|||
|
|
},
|
|||
|
|
removeProperty() {
|
|||
|
|
return null;
|
|||
|
|
},
|
|||
|
|
setProperty() {
|
|||
|
|
return null;
|
|||
|
|
},
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
get globalThis() {
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
get history() {
|
|||
|
|
if (this.__history == null) {
|
|||
|
|
this.__history = new MockHistory();
|
|||
|
|
}
|
|||
|
|
return this.__history;
|
|||
|
|
}
|
|||
|
|
set history(hsty) {
|
|||
|
|
this.__history = hsty;
|
|||
|
|
}
|
|||
|
|
get JSON() {
|
|||
|
|
return JSON;
|
|||
|
|
}
|
|||
|
|
get HTMLElement() {
|
|||
|
|
if (this.__htmlElementCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__htmlElementCstr = class extends MockHTMLElement {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument, '');
|
|||
|
|
const observedAttributes = this.constructor.observedAttributes;
|
|||
|
|
if (Array.isArray(observedAttributes) && typeof this.attributeChangedCallback === 'function') {
|
|||
|
|
observedAttributes.forEach((attrName) => {
|
|||
|
|
const attrValue = this.getAttribute(attrName);
|
|||
|
|
if (attrValue != null) {
|
|||
|
|
this.attributeChangedCallback(attrName, null, attrValue);
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__htmlElementCstr;
|
|||
|
|
}
|
|||
|
|
set HTMLElement(htmlElementCstr) {
|
|||
|
|
this.__htmlElementCstr = htmlElementCstr;
|
|||
|
|
}
|
|||
|
|
get IntersectionObserver() {
|
|||
|
|
return MockIntersectionObserver;
|
|||
|
|
}
|
|||
|
|
get localStorage() {
|
|||
|
|
if (this.__localStorage == null) {
|
|||
|
|
this.__localStorage = new MockStorage();
|
|||
|
|
}
|
|||
|
|
return this.__localStorage;
|
|||
|
|
}
|
|||
|
|
set localStorage(locStorage) {
|
|||
|
|
this.__localStorage = locStorage;
|
|||
|
|
}
|
|||
|
|
get location() {
|
|||
|
|
if (this.__location == null) {
|
|||
|
|
this.__location = new MockLocation();
|
|||
|
|
}
|
|||
|
|
return this.__location;
|
|||
|
|
}
|
|||
|
|
set location(val) {
|
|||
|
|
if (typeof val === 'string') {
|
|||
|
|
if (this.__location == null) {
|
|||
|
|
this.__location = new MockLocation();
|
|||
|
|
}
|
|||
|
|
this.__location.href = val;
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
this.__location = val;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
matchMedia() {
|
|||
|
|
return {
|
|||
|
|
matches: false,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
get Node() {
|
|||
|
|
if (this.__nodeCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__nodeCstr = class extends MockNode {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument, 0, 'test', '');
|
|||
|
|
throw new Error('Illegal constructor: cannot construct Node');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__nodeCstr;
|
|||
|
|
}
|
|||
|
|
get NodeList() {
|
|||
|
|
if (this.__nodeListCstr == null) {
|
|||
|
|
const ownerDocument = this.document;
|
|||
|
|
this.__nodeListCstr = class extends MockNodeList {
|
|||
|
|
constructor() {
|
|||
|
|
super(ownerDocument, [], 0);
|
|||
|
|
throw new Error('Illegal constructor: cannot construct NodeList');
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
return this.__nodeListCstr;
|
|||
|
|
}
|
|||
|
|
get navigator() {
|
|||
|
|
if (this.__navigator == null) {
|
|||
|
|
this.__navigator = new MockNavigator();
|
|||
|
|
}
|
|||
|
|
return this.__navigator;
|
|||
|
|
}
|
|||
|
|
set navigator(nav) {
|
|||
|
|
this.__navigator = nav;
|
|||
|
|
}
|
|||
|
|
get parent() {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
prompt() {
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
open() {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
get origin() {
|
|||
|
|
return this.location.origin;
|
|||
|
|
}
|
|||
|
|
removeEventListener(type, handler) {
|
|||
|
|
removeEventListener(this, type, handler);
|
|||
|
|
}
|
|||
|
|
requestAnimationFrame(callback) {
|
|||
|
|
return this.setTimeout(() => {
|
|||
|
|
callback(Date.now());
|
|||
|
|
}, 0);
|
|||
|
|
}
|
|||
|
|
requestIdleCallback(callback) {
|
|||
|
|
return this.setTimeout(() => {
|
|||
|
|
callback({
|
|||
|
|
didTimeout: false,
|
|||
|
|
timeRemaining: () => 0,
|
|||
|
|
});
|
|||
|
|
}, 0);
|
|||
|
|
}
|
|||
|
|
scroll(_x, _y) {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
scrollBy(_x, _y) {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
scrollTo(_x, _y) {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
get self() {
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
get sessionStorage() {
|
|||
|
|
if (this.__sessionStorage == null) {
|
|||
|
|
this.__sessionStorage = new MockStorage();
|
|||
|
|
}
|
|||
|
|
return this.__sessionStorage;
|
|||
|
|
}
|
|||
|
|
set sessionStorage(locStorage) {
|
|||
|
|
this.__sessionStorage = locStorage;
|
|||
|
|
}
|
|||
|
|
setInterval(callback, ms, ...args) {
|
|||
|
|
if (this.__timeouts == null) {
|
|||
|
|
this.__timeouts = new Set();
|
|||
|
|
}
|
|||
|
|
ms = Math.min(ms, this.__maxTimeout);
|
|||
|
|
if (this.__allowInterval) {
|
|||
|
|
const intervalId = this.__setInterval(() => {
|
|||
|
|
if (this.__timeouts) {
|
|||
|
|
this.__timeouts.delete(intervalId);
|
|||
|
|
try {
|
|||
|
|
callback(...args);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
if (this.console) {
|
|||
|
|
this.console.error(e);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, ms);
|
|||
|
|
if (this.__timeouts) {
|
|||
|
|
this.__timeouts.add(intervalId);
|
|||
|
|
}
|
|||
|
|
return intervalId;
|
|||
|
|
}
|
|||
|
|
const timeoutId = this.__setTimeout(() => {
|
|||
|
|
if (this.__timeouts) {
|
|||
|
|
this.__timeouts.delete(timeoutId);
|
|||
|
|
try {
|
|||
|
|
callback(...args);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
if (this.console) {
|
|||
|
|
this.console.error(e);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, ms);
|
|||
|
|
if (this.__timeouts) {
|
|||
|
|
this.__timeouts.add(timeoutId);
|
|||
|
|
}
|
|||
|
|
return timeoutId;
|
|||
|
|
}
|
|||
|
|
setTimeout(callback, ms, ...args) {
|
|||
|
|
if (this.__timeouts == null) {
|
|||
|
|
this.__timeouts = new Set();
|
|||
|
|
}
|
|||
|
|
ms = Math.min(ms, this.__maxTimeout);
|
|||
|
|
const timeoutId = this.__setTimeout(() => {
|
|||
|
|
if (this.__timeouts) {
|
|||
|
|
this.__timeouts.delete(timeoutId);
|
|||
|
|
try {
|
|||
|
|
callback(...args);
|
|||
|
|
}
|
|||
|
|
catch (e) {
|
|||
|
|
if (this.console) {
|
|||
|
|
this.console.error(e);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
console.error(e);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}, ms);
|
|||
|
|
if (this.__timeouts) {
|
|||
|
|
this.__timeouts.add(timeoutId);
|
|||
|
|
}
|
|||
|
|
return timeoutId;
|
|||
|
|
}
|
|||
|
|
get top() {
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
get window() {
|
|||
|
|
return this;
|
|||
|
|
}
|
|||
|
|
onanimationstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onanimationend() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onanimationiteration() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onabort() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onauxclick() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onbeforecopy() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onbeforecut() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onbeforepaste() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onblur() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncancel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncanplay() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncanplaythrough() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onclick() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onclose() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncontextmenu() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncopy() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncuechange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oncut() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondblclick() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondrag() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragend() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragenter() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragleave() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragover() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondragstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondrop() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ondurationchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onemptied() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onended() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onerror() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfocus() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfocusin() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfocusout() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onformdata() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfullscreenchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onfullscreenerror() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ongotpointercapture() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oninput() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
oninvalid() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onkeydown() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onkeypress() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onkeyup() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onload() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onloadeddata() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onloadedmetadata() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onloadstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onlostpointercapture() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmousedown() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseenter() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseleave() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmousemove() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseout() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseover() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmouseup() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onmousewheel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpaste() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpause() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onplay() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onplaying() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointercancel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerdown() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerenter() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerleave() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointermove() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerout() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerover() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onpointerup() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onprogress() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onratechange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onreset() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onresize() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onscroll() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onsearch() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onseeked() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onseeking() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onselect() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onselectstart() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onstalled() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onsubmit() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onsuspend() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ontimeupdate() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
ontoggle() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onvolumechange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwaiting() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwebkitfullscreenchange() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwebkitfullscreenerror() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
onwheel() {
|
|||
|
|
/**/
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
addGlobalsToWindowPrototype(MockWindow.prototype);
|
|||
|
|
function resetWindowDefaults(win) {
|
|||
|
|
win.__clearInterval = nativeClearInterval;
|
|||
|
|
win.__clearTimeout = nativeClearTimeout;
|
|||
|
|
win.__setInterval = nativeSetInterval;
|
|||
|
|
win.__setTimeout = nativeSetTimeout;
|
|||
|
|
win.__maxTimeout = 30000;
|
|||
|
|
win.__allowInterval = true;
|
|||
|
|
win.URL = nativeURL;
|
|||
|
|
}
|
|||
|
|
function cloneWindow(srcWin, opts = {}) {
|
|||
|
|
if (srcWin == null) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
const clonedWin = new MockWindow(false);
|
|||
|
|
if (!opts.customElementProxy) {
|
|||
|
|
// TODO(STENCIL-345) - Evaluate reconciling MockWindow, Window differences
|
|||
|
|
// @ts-ignore
|
|||
|
|
srcWin.customElements = null;
|
|||
|
|
}
|
|||
|
|
if (srcWin.document != null) {
|
|||
|
|
const clonedDoc = new MockDocument(false, clonedWin);
|
|||
|
|
clonedWin.document = clonedDoc;
|
|||
|
|
clonedDoc.documentElement = srcWin.document.documentElement.cloneNode(true);
|
|||
|
|
}
|
|||
|
|
else {
|
|||
|
|
clonedWin.document = new MockDocument(null, clonedWin);
|
|||
|
|
}
|
|||
|
|
return clonedWin;
|
|||
|
|
}
|
|||
|
|
function cloneDocument(srcDoc) {
|
|||
|
|
if (srcDoc == null) {
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
const dstWin = cloneWindow(srcDoc.defaultView);
|
|||
|
|
return dstWin.document;
|
|||
|
|
}
|
|||
|
|
// TODO(STENCIL-345) - Evaluate reconciling MockWindow, Window differences
|
|||
|
|
/**
|
|||
|
|
* Constrain setTimeout() to 1ms, but still async. Also
|
|||
|
|
* only allow setInterval() to fire once, also constrained to 1ms.
|
|||
|
|
* @param win the mock window instance to update
|
|||
|
|
*/
|
|||
|
|
function constrainTimeouts(win) {
|
|||
|
|
win.__allowInterval = false;
|
|||
|
|
win.__maxTimeout = 0;
|
|||
|
|
}
|
|||
|
|
function resetWindow(win) {
|
|||
|
|
if (win != null) {
|
|||
|
|
if (win.__timeouts) {
|
|||
|
|
win.__timeouts.forEach((timeoutId) => {
|
|||
|
|
nativeClearInterval(timeoutId);
|
|||
|
|
nativeClearTimeout(timeoutId);
|
|||
|
|
});
|
|||
|
|
win.__timeouts.clear();
|
|||
|
|
}
|
|||
|
|
if (win.customElements && win.customElements.clear) {
|
|||
|
|
win.customElements.clear();
|
|||
|
|
}
|
|||
|
|
resetDocument(win.document);
|
|||
|
|
resetPerformance(win.performance);
|
|||
|
|
for (const key in win) {
|
|||
|
|
if (win.hasOwnProperty(key) && key !== 'document' && key !== 'performance' && key !== 'customElements') {
|
|||
|
|
delete win[key];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
resetWindowDefaults(win);
|
|||
|
|
resetWindowDimensions(win);
|
|||
|
|
resetEventListeners(win);
|
|||
|
|
if (win.document != null) {
|
|||
|
|
try {
|
|||
|
|
win.document.defaultView = win;
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
}
|
|||
|
|
// ensure we don't hold onto nodeFetch values
|
|||
|
|
win.fetch = null;
|
|||
|
|
win.Headers = null;
|
|||
|
|
win.Request = null;
|
|||
|
|
win.Response = null;
|
|||
|
|
win.FetchError = null;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function resetWindowDimensions(win) {
|
|||
|
|
try {
|
|||
|
|
win.devicePixelRatio = 1;
|
|||
|
|
win.innerHeight = 768;
|
|||
|
|
win.innerWidth = 1366;
|
|||
|
|
win.pageXOffset = 0;
|
|||
|
|
win.pageYOffset = 0;
|
|||
|
|
win.screenLeft = 0;
|
|||
|
|
win.screenTop = 0;
|
|||
|
|
win.screenX = 0;
|
|||
|
|
win.screenY = 0;
|
|||
|
|
win.scrollX = 0;
|
|||
|
|
win.scrollY = 0;
|
|||
|
|
win.screen = {
|
|||
|
|
availHeight: win.innerHeight,
|
|||
|
|
availLeft: 0,
|
|||
|
|
availTop: 0,
|
|||
|
|
availWidth: win.innerWidth,
|
|||
|
|
colorDepth: 24,
|
|||
|
|
height: win.innerHeight,
|
|||
|
|
keepAwake: false,
|
|||
|
|
orientation: {
|
|||
|
|
angle: 0,
|
|||
|
|
type: 'portrait-primary',
|
|||
|
|
},
|
|||
|
|
pixelDepth: 24,
|
|||
|
|
width: win.innerWidth,
|
|||
|
|
};
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
class MockDocument extends MockHTMLElement {
|
|||
|
|
constructor(html = null, win = null) {
|
|||
|
|
super(null, null);
|
|||
|
|
this.nodeName = "#document" /* NODE_NAMES.DOCUMENT_NODE */;
|
|||
|
|
this.nodeType = 9 /* NODE_TYPES.DOCUMENT_NODE */;
|
|||
|
|
this.defaultView = win;
|
|||
|
|
this.cookie = '';
|
|||
|
|
this.referrer = '';
|
|||
|
|
this.appendChild(this.createDocumentTypeNode());
|
|||
|
|
if (typeof html === 'string') {
|
|||
|
|
const parsedDoc = parseDocumentUtil(this, html);
|
|||
|
|
const documentElement = parsedDoc.children.find((elm) => elm.nodeName === 'HTML');
|
|||
|
|
if (documentElement != null) {
|
|||
|
|
this.appendChild(documentElement);
|
|||
|
|
setOwnerDocument(documentElement, this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
else if (html !== false) {
|
|||
|
|
const documentElement = new MockHTMLElement(this, 'html');
|
|||
|
|
this.appendChild(documentElement);
|
|||
|
|
documentElement.appendChild(new MockHTMLElement(this, 'head'));
|
|||
|
|
documentElement.appendChild(new MockHTMLElement(this, 'body'));
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get dir() {
|
|||
|
|
return this.documentElement.dir;
|
|||
|
|
}
|
|||
|
|
set dir(value) {
|
|||
|
|
this.documentElement.dir = value;
|
|||
|
|
}
|
|||
|
|
get location() {
|
|||
|
|
if (this.defaultView != null) {
|
|||
|
|
return this.defaultView.location;
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
set location(val) {
|
|||
|
|
if (this.defaultView != null) {
|
|||
|
|
this.defaultView.location = val;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get baseURI() {
|
|||
|
|
const baseNode = this.head.childNodes.find((node) => node.nodeName === 'BASE');
|
|||
|
|
if (baseNode) {
|
|||
|
|
return baseNode.href;
|
|||
|
|
}
|
|||
|
|
return this.URL;
|
|||
|
|
}
|
|||
|
|
get URL() {
|
|||
|
|
return this.location.href;
|
|||
|
|
}
|
|||
|
|
get styleSheets() {
|
|||
|
|
return this.querySelectorAll('style');
|
|||
|
|
}
|
|||
|
|
get scripts() {
|
|||
|
|
return this.querySelectorAll('script');
|
|||
|
|
}
|
|||
|
|
get forms() {
|
|||
|
|
return this.querySelectorAll('form');
|
|||
|
|
}
|
|||
|
|
get images() {
|
|||
|
|
return this.querySelectorAll('img');
|
|||
|
|
}
|
|||
|
|
get scrollingElement() {
|
|||
|
|
return this.documentElement;
|
|||
|
|
}
|
|||
|
|
get documentElement() {
|
|||
|
|
for (let i = this.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
if (this.childNodes[i].nodeName === 'HTML') {
|
|||
|
|
return this.childNodes[i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const documentElement = new MockHTMLElement(this, 'html');
|
|||
|
|
this.appendChild(documentElement);
|
|||
|
|
return documentElement;
|
|||
|
|
}
|
|||
|
|
set documentElement(documentElement) {
|
|||
|
|
for (let i = this.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
if (this.childNodes[i].nodeType !== 10 /* NODE_TYPES.DOCUMENT_TYPE_NODE */) {
|
|||
|
|
this.childNodes[i].remove();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (documentElement != null) {
|
|||
|
|
this.appendChild(documentElement);
|
|||
|
|
setOwnerDocument(documentElement, this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get head() {
|
|||
|
|
const documentElement = this.documentElement;
|
|||
|
|
for (let i = 0; i < documentElement.childNodes.length; i++) {
|
|||
|
|
if (documentElement.childNodes[i].nodeName === 'HEAD') {
|
|||
|
|
return documentElement.childNodes[i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const head = new MockHTMLElement(this, 'head');
|
|||
|
|
documentElement.insertBefore(head, documentElement.firstChild);
|
|||
|
|
return head;
|
|||
|
|
}
|
|||
|
|
set head(head) {
|
|||
|
|
const documentElement = this.documentElement;
|
|||
|
|
for (let i = documentElement.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
if (documentElement.childNodes[i].nodeName === 'HEAD') {
|
|||
|
|
documentElement.childNodes[i].remove();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (head != null) {
|
|||
|
|
documentElement.insertBefore(head, documentElement.firstChild);
|
|||
|
|
setOwnerDocument(head, this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
get body() {
|
|||
|
|
const documentElement = this.documentElement;
|
|||
|
|
for (let i = documentElement.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
if (documentElement.childNodes[i].nodeName === 'BODY') {
|
|||
|
|
return documentElement.childNodes[i];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const body = new MockHTMLElement(this, 'body');
|
|||
|
|
documentElement.appendChild(body);
|
|||
|
|
return body;
|
|||
|
|
}
|
|||
|
|
set body(body) {
|
|||
|
|
const documentElement = this.documentElement;
|
|||
|
|
for (let i = documentElement.childNodes.length - 1; i >= 0; i--) {
|
|||
|
|
if (documentElement.childNodes[i].nodeName === 'BODY') {
|
|||
|
|
documentElement.childNodes[i].remove();
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (body != null) {
|
|||
|
|
documentElement.appendChild(body);
|
|||
|
|
setOwnerDocument(body, this);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
appendChild(newNode) {
|
|||
|
|
newNode.remove();
|
|||
|
|
newNode.parentNode = this;
|
|||
|
|
this.childNodes.push(newNode);
|
|||
|
|
return newNode;
|
|||
|
|
}
|
|||
|
|
createComment(data) {
|
|||
|
|
return new MockComment(this, data);
|
|||
|
|
}
|
|||
|
|
createAttribute(attrName) {
|
|||
|
|
return new MockAttr(attrName.toLowerCase(), '');
|
|||
|
|
}
|
|||
|
|
createAttributeNS(namespaceURI, attrName) {
|
|||
|
|
return new MockAttr(attrName, '', namespaceURI);
|
|||
|
|
}
|
|||
|
|
createElement(tagName) {
|
|||
|
|
if (tagName === "#document" /* NODE_NAMES.DOCUMENT_NODE */) {
|
|||
|
|
const doc = new MockDocument(false);
|
|||
|
|
doc.nodeName = tagName;
|
|||
|
|
doc.parentNode = null;
|
|||
|
|
return doc;
|
|||
|
|
}
|
|||
|
|
return createElement(this, tagName);
|
|||
|
|
}
|
|||
|
|
createElementNS(namespaceURI, tagName) {
|
|||
|
|
const elmNs = createElementNS(this, namespaceURI, tagName);
|
|||
|
|
elmNs.namespaceURI = namespaceURI;
|
|||
|
|
return elmNs;
|
|||
|
|
}
|
|||
|
|
createTextNode(text) {
|
|||
|
|
return new MockTextNode(this, text);
|
|||
|
|
}
|
|||
|
|
createDocumentFragment() {
|
|||
|
|
return new MockDocumentFragment(this);
|
|||
|
|
}
|
|||
|
|
createDocumentTypeNode() {
|
|||
|
|
return new MockDocumentTypeNode(this);
|
|||
|
|
}
|
|||
|
|
getElementById(id) {
|
|||
|
|
return getElementById(this, id);
|
|||
|
|
}
|
|||
|
|
getElementsByName(elmName) {
|
|||
|
|
return getElementsByName(this, elmName.toLowerCase());
|
|||
|
|
}
|
|||
|
|
get title() {
|
|||
|
|
const title = this.head.childNodes.find((elm) => elm.nodeName === 'TITLE');
|
|||
|
|
if (title != null && typeof title.textContent === 'string') {
|
|||
|
|
return title.textContent.trim();
|
|||
|
|
}
|
|||
|
|
return '';
|
|||
|
|
}
|
|||
|
|
set title(value) {
|
|||
|
|
const head = this.head;
|
|||
|
|
let title = head.childNodes.find((elm) => elm.nodeName === 'TITLE');
|
|||
|
|
if (title == null) {
|
|||
|
|
title = this.createElement('title');
|
|||
|
|
head.appendChild(title);
|
|||
|
|
}
|
|||
|
|
title.textContent = value;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
function createDocument(html = null) {
|
|||
|
|
return new MockWindow(html).document;
|
|||
|
|
}
|
|||
|
|
function createFragment(html) {
|
|||
|
|
return parseHtmlToFragment(html, null);
|
|||
|
|
}
|
|||
|
|
function resetDocument(doc) {
|
|||
|
|
if (doc != null) {
|
|||
|
|
resetEventListeners(doc);
|
|||
|
|
const documentElement = doc.documentElement;
|
|||
|
|
if (documentElement != null) {
|
|||
|
|
resetElement(documentElement);
|
|||
|
|
for (let i = 0, ii = documentElement.childNodes.length; i < ii; i++) {
|
|||
|
|
const childNode = documentElement.childNodes[i];
|
|||
|
|
resetElement(childNode);
|
|||
|
|
childNode.childNodes.length = 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
for (const key in doc) {
|
|||
|
|
if (doc.hasOwnProperty(key) && !DOC_KEY_KEEPERS.has(key)) {
|
|||
|
|
delete doc[key];
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
try {
|
|||
|
|
doc.nodeName = "#document" /* NODE_NAMES.DOCUMENT_NODE */;
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
try {
|
|||
|
|
doc.nodeType = 9 /* NODE_TYPES.DOCUMENT_NODE */;
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
try {
|
|||
|
|
doc.cookie = '';
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
try {
|
|||
|
|
doc.referrer = '';
|
|||
|
|
}
|
|||
|
|
catch (e) { }
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
const DOC_KEY_KEEPERS = new Set([
|
|||
|
|
'nodeName',
|
|||
|
|
'nodeType',
|
|||
|
|
'nodeValue',
|
|||
|
|
'ownerDocument',
|
|||
|
|
'parentNode',
|
|||
|
|
'childNodes',
|
|||
|
|
'_shadowRoot',
|
|||
|
|
]);
|
|||
|
|
function getElementById(elm, id) {
|
|||
|
|
const children = elm.children;
|
|||
|
|
for (let i = 0, ii = children.length; i < ii; i++) {
|
|||
|
|
const childElm = children[i];
|
|||
|
|
if (childElm.id === id) {
|
|||
|
|
return childElm;
|
|||
|
|
}
|
|||
|
|
const childElmFound = getElementById(childElm, id);
|
|||
|
|
if (childElmFound != null) {
|
|||
|
|
return childElmFound;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return null;
|
|||
|
|
}
|
|||
|
|
function getElementsByName(elm, elmName, foundElms = []) {
|
|||
|
|
const children = elm.children;
|
|||
|
|
for (let i = 0, ii = children.length; i < ii; i++) {
|
|||
|
|
const childElm = children[i];
|
|||
|
|
if (childElm.name && childElm.name.toLowerCase() === elmName) {
|
|||
|
|
foundElms.push(childElm);
|
|||
|
|
}
|
|||
|
|
getElementsByName(childElm, elmName, foundElms);
|
|||
|
|
}
|
|||
|
|
return foundElms;
|
|||
|
|
}
|
|||
|
|
function setOwnerDocument(elm, ownerDocument) {
|
|||
|
|
for (let i = 0, ii = elm.childNodes.length; i < ii; i++) {
|
|||
|
|
elm.childNodes[i].ownerDocument = ownerDocument;
|
|||
|
|
if (elm.childNodes[i].nodeType === 1 /* NODE_TYPES.ELEMENT_NODE */) {
|
|||
|
|
setOwnerDocument(elm.childNodes[i], ownerDocument);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
export { MockAttr, MockAttributeMap, MockComment, MockCustomEvent, MockDocument, MockElement, MockHTMLElement, MockHeaders, MockKeyboardEvent, MockMouseEvent, MockNode, MockRequest, MockResponse, MockTextNode, MockWindow, cloneAttributes, cloneDocument, cloneWindow, constrainTimeouts, createDocument, createFragment, parseHtmlToDocument, parseHtmlToFragment, patchWindow, resetDocument, serializeNodeToHtml, setupGlobal, teardownGlobal };
|