netscape-bookmark-parser
Version:
A TypeScript/JavaScript library for parsing browser bookmark files (HTML format) and manipulating them as structured data. Compatible with both Deno and Node.js runtimes.
1,069 lines (1,068 loc) • 49.5 kB
JavaScript
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
};
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
if (kind === "m") throw new TypeError("Private method is not writable");
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
};
var _DOMTokenList_instances, _a, _DOMTokenList_DOM_TOKEN_LIST_MIN_SET_SIZE, _DOMTokenList__value, _DOMTokenList_value_get, _DOMTokenList_value_set, _DOMTokenList_set, _DOMTokenList_onChange, _DOMTokenList_invalidToken, _DOMTokenList_setIndices, _DOMTokenList_arrayAdd, _DOMTokenList_setAdd, _DOMTokenList_arrayRemove, _DOMTokenList_setRemove, _DOMTokenList_updateClassString, _UninitializedDOMTokenList_instances, _UninitializedDOMTokenList_getInitialized, _b, _Attr_namedNodeMap, _Attr_name, _Attr_value, _Attr_ownerElement, _c, _NamedNodeMap_indexedAttrAccess, _NamedNodeMap_onAttrNodeChange, _NamedNodeMap_attrNodeCache, _NamedNodeMap_map, _NamedNodeMap_length, _NamedNodeMap_capacity, _NamedNodeMap_ownerElement, _Element_instances, _Element_namedNodeMap, _Element_datasetProxy, _Element_currentId, _Element_currentClassName, _Element_hasIdAttribute, _Element_hasClassNameAttribute, _Element_classListInstance, _Element_classList_get;
import { CTOR_KEY } from "../constructor-lock.js";
import { fragmentNodesFromString } from "../deserialize.js";
import { Node, nodesAndTextNodes, NodeType } from "./node.js";
import { NodeList, nodeListMutatorSym } from "./node-list.js";
import { getDatasetHtmlAttrName, getDatasetJavascriptName, getElementsByClassName, getOuterOrInnerHtml, insertBeforeAfter, lowerCaseCharRe, upperCaseCharRe, } from "./utils.js";
import UtilTypes from "./utils-types.js";
import { getLowerCase, getUpperCase } from "./string-cache.js";
export class DOMTokenList {
constructor(onChange, key) {
_DOMTokenList_instances.add(this);
_DOMTokenList__value.set(this, "");
_DOMTokenList_set.set(this, []);
_DOMTokenList_onChange.set(this, void 0);
if (key !== CTOR_KEY) {
throw new TypeError("Illegal constructor");
}
__classPrivateFieldSet(this, _DOMTokenList_onChange, onChange, "f");
}
set value(input) {
__classPrivateFieldSet(this, _DOMTokenList_instances, input, "a", _DOMTokenList_value_set);
__classPrivateFieldSet(this, _DOMTokenList_set, input
.trim()
.split(/[\t\n\f\r\s]+/g)
.filter(Boolean), "f");
if (__classPrivateFieldGet(this, _DOMTokenList_set, "f").length > __classPrivateFieldGet(_a, _a, "f", _DOMTokenList_DOM_TOKEN_LIST_MIN_SET_SIZE)) {
__classPrivateFieldSet(this, _DOMTokenList_set, new Set(__classPrivateFieldGet(this, _DOMTokenList_set, "f")), "f");
}
else {
const deduplicatedSet = [];
for (const element of __classPrivateFieldGet(this, _DOMTokenList_set, "f")) {
if (!deduplicatedSet.includes(element)) {
deduplicatedSet.push(element);
}
}
__classPrivateFieldSet(this, _DOMTokenList_set, deduplicatedSet, "f");
}
__classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setIndices).call(this);
}
get value() {
return __classPrivateFieldGet(this, _DOMTokenList__value, "f");
}
get length() {
if (__classPrivateFieldGet(this, _DOMTokenList_set, "f").constructor === Array) {
return __classPrivateFieldGet(this, _DOMTokenList_set, "f").length;
}
else {
return __classPrivateFieldGet(this, _DOMTokenList_set, "f").size;
}
}
*entries() {
const array = Array.from(__classPrivateFieldGet(this, _DOMTokenList_set, "f"));
for (let i = 0; i < array.length; i++) {
yield [i, array[i]];
}
}
*values() {
yield* __classPrivateFieldGet(this, _DOMTokenList_set, "f").values();
}
*keys() {
const length = this.length;
for (let i = 0; i < length; i++) {
yield i;
}
}
*[(_DOMTokenList__value = new WeakMap(), _DOMTokenList_set = new WeakMap(), _DOMTokenList_onChange = new WeakMap(), _DOMTokenList_instances = new WeakSet(), _DOMTokenList_value_get = function _DOMTokenList_value_get() {
return __classPrivateFieldGet(this, _DOMTokenList__value, "f");
}, _DOMTokenList_value_set = function _DOMTokenList_value_set(value) {
__classPrivateFieldSet(this, _DOMTokenList__value, value, "f");
__classPrivateFieldGet(this, _DOMTokenList_onChange, "f").call(this, value);
}, _DOMTokenList_invalidToken = function _DOMTokenList_invalidToken(token) {
return token === "" || /[\t\n\f\r ]/.test(token);
}, _DOMTokenList_setIndices = function _DOMTokenList_setIndices() {
const classes = Array.from(__classPrivateFieldGet(this, _DOMTokenList_set, "f"));
for (let i = 0; i < classes.length; i++) {
this[i] = classes[i];
}
}, Symbol.iterator)]() {
yield* __classPrivateFieldGet(this, _DOMTokenList_set, "f").values();
}
item(index) {
index = Number(index);
if (Number.isNaN(index) || index === Infinity)
index = 0;
return this[Math.trunc(index) % 2 ** 32] ?? null;
}
contains(element) {
if (__classPrivateFieldGet(this, _DOMTokenList_set, "f").constructor === Array) {
return __classPrivateFieldGet(this, _DOMTokenList_set, "f").includes(element);
}
else {
return __classPrivateFieldGet(this, _DOMTokenList_set, "f").has(element);
}
}
add(...elements) {
const method = (__classPrivateFieldGet(this, _DOMTokenList_set, "f").constructor === Array ? __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_arrayAdd) : __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setAdd)).bind(this);
for (const element of elements) {
if (__classPrivateFieldGet(_a, _a, "m", _DOMTokenList_invalidToken).call(_a, element)) {
throw new DOMException("Failed to execute 'add' on 'DOMTokenList': The token provided must not be empty.");
}
method(element);
}
__classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_updateClassString).call(this);
}
remove(...elements) {
const method = (__classPrivateFieldGet(this, _DOMTokenList_set, "f").constructor === Array ? __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_arrayRemove) : __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setRemove))
.bind(this);
const size = this.length;
for (const element of elements) {
if (__classPrivateFieldGet(_a, _a, "m", _DOMTokenList_invalidToken).call(_a, element)) {
throw new DOMException("Failed to execute 'remove' on 'DOMTokenList': The token provided must not be empty.");
}
method(element);
}
const newSize = this.length;
if (size !== newSize) {
for (let i = newSize; i < size; i++) {
delete this[i];
}
__classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setIndices).call(this);
}
__classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_updateClassString).call(this);
}
replace(oldToken, newToken) {
const isArrayBacked = __classPrivateFieldGet(this, _DOMTokenList_set, "f").constructor === Array;
const removeMethod = (isArrayBacked ? __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_arrayRemove) : __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setRemove))
.bind(this);
const addMethod = (isArrayBacked ? __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_arrayAdd) : __classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setAdd)).bind(this);
if ([oldToken, newToken].some((v) => __classPrivateFieldGet(_a, _a, "m", _DOMTokenList_invalidToken).call(_a, v))) {
throw new DOMException("Failed to execute 'replace' on 'DOMTokenList': The token provided must not be empty.");
}
if (!this.contains(oldToken)) {
return false;
}
if (this.contains(newToken)) {
this.remove(oldToken);
}
else {
removeMethod(oldToken);
addMethod(newToken);
__classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_setIndices).call(this);
__classPrivateFieldGet(this, _DOMTokenList_instances, "m", _DOMTokenList_updateClassString).call(this);
}
return true;
}
supports() {
throw new Error("Not implemented");
}
toggle(element, force) {
if (force !== undefined) {
const operation = force ? "add" : "remove";
this[operation](element);
return false;
}
else {
const contains = this.contains(element);
const operation = contains ? "remove" : "add";
this[operation](element);
return !contains;
}
}
forEach(callback) {
for (const [i, value] of this.entries()) {
callback(value, i, this);
}
}
}
_a = DOMTokenList, _DOMTokenList_arrayAdd = function _DOMTokenList_arrayAdd(element) {
const array = __classPrivateFieldGet(this, _DOMTokenList_set, "f");
if (!array.includes(element)) {
this[array.length] = element;
array.push(element);
}
}, _DOMTokenList_setAdd = function _DOMTokenList_setAdd(element) {
const set = __classPrivateFieldGet(this, _DOMTokenList_set, "f");
const { size } = set;
set.add(element);
if (size < set.size) {
this[size] = element;
}
}, _DOMTokenList_arrayRemove = function _DOMTokenList_arrayRemove(element) {
const array = __classPrivateFieldGet(this, _DOMTokenList_set, "f");
const index = array.indexOf(element);
if (index >= 0) {
array.splice(index, 1);
}
}, _DOMTokenList_setRemove = function _DOMTokenList_setRemove(element) {
__classPrivateFieldGet(this, _DOMTokenList_set, "f").delete(element);
}, _DOMTokenList_updateClassString = function _DOMTokenList_updateClassString() {
__classPrivateFieldSet(this, _DOMTokenList_instances, Array.from(__classPrivateFieldGet(this, _DOMTokenList_set, "f")).join(" "), "a", _DOMTokenList_value_set);
if (__classPrivateFieldGet(this, _DOMTokenList_set, "f").constructor === Array &&
__classPrivateFieldGet(this, _DOMTokenList_set, "f").length > __classPrivateFieldGet(_a, _a, "f", _DOMTokenList_DOM_TOKEN_LIST_MIN_SET_SIZE)) {
__classPrivateFieldSet(this, _DOMTokenList_set, new Set(__classPrivateFieldGet(this, _DOMTokenList_set, "f")), "f");
}
};
// Minimum number of classnames/tokens in order to switch from
// an array-backed to a set-backed list
_DOMTokenList_DOM_TOKEN_LIST_MIN_SET_SIZE = { value: 32 };
const initializeClassListSym = Symbol("initializeClassListSym");
const domTokenListCurrentElementSym = Symbol("domTokenListCurrentElementSym");
/**
* The purpose of this uninitialized DOMTokenList is to consume less memory
* than the actual DOMTokenList class. By measurements of Deno v2.1.0 (V8 13.0.245.12-rusty)
* this class consumes 48 bytes while the smallest DOMTokenList consumes 488
* bytes
*/
class UninitializedDOMTokenList {
constructor(currentElement) {
_UninitializedDOMTokenList_instances.add(this);
// This will always be populated with the current element
// being queried
Object.defineProperty(this, _b, {
enumerable: true,
configurable: true,
writable: true,
value: void 0
});
this[domTokenListCurrentElementSym] = currentElement;
}
set value(input) {
this[domTokenListCurrentElementSym][initializeClassListSym]();
this[domTokenListCurrentElementSym].classList.value = String(input);
}
get value() {
return __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.value ?? "";
}
get length() {
return __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.length ?? 0;
}
*entries() {
const initialized = __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this);
if (initialized) {
yield* initialized.entries();
}
}
*values() {
const initialized = __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this);
if (initialized) {
yield* initialized.values();
}
}
*keys() {
const initialized = __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this);
if (initialized) {
yield* initialized.keys();
}
}
*[(_UninitializedDOMTokenList_instances = new WeakSet(), _b = domTokenListCurrentElementSym, _UninitializedDOMTokenList_getInitialized = function _UninitializedDOMTokenList_getInitialized() {
const currentClassList = this[domTokenListCurrentElementSym].classList;
if (currentClassList === this) {
return null;
}
return currentClassList;
}, Symbol.iterator)]() {
yield* this.values();
}
item(index) {
return __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.item(index) ?? null;
}
contains(element) {
return __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.contains(element) ?? false;
}
add(...elements) {
this[domTokenListCurrentElementSym][initializeClassListSym]();
this[domTokenListCurrentElementSym].classList.add(...elements);
}
remove(...elements) {
__classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.remove(...elements);
}
replace(oldToken, newToken) {
return __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.replace(oldToken, newToken) ?? false;
}
supports() {
throw new Error("Not implemented");
}
toggle(element, force) {
if (force === false) {
return __classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.toggle(element, force) ?? false;
}
this[domTokenListCurrentElementSym][initializeClassListSym]();
this[domTokenListCurrentElementSym].classList.add(element);
return true;
}
forEach(callback) {
__classPrivateFieldGet(this, _UninitializedDOMTokenList_instances, "m", _UninitializedDOMTokenList_getInitialized).call(this)?.forEach(callback);
}
}
const setNamedNodeMapOwnerElementSym = Symbol("setNamedNodeMapOwnerElementSym");
const setAttrValueSym = Symbol("setAttrValueSym");
export class Attr extends Node {
constructor(map, name, value, key) {
if (key !== CTOR_KEY) {
throw new TypeError("Illegal constructor");
}
super(name, NodeType.ATTRIBUTE_NODE, null, CTOR_KEY);
_Attr_namedNodeMap.set(this, null);
_Attr_name.set(this, "");
_Attr_value.set(this, "");
_Attr_ownerElement.set(this, null);
__classPrivateFieldSet(this, _Attr_name, name, "f");
__classPrivateFieldSet(this, _Attr_value, value, "f");
__classPrivateFieldSet(this, _Attr_namedNodeMap, map, "f");
}
[(_Attr_namedNodeMap = new WeakMap(), _Attr_name = new WeakMap(), _Attr_value = new WeakMap(), _Attr_ownerElement = new WeakMap(), setNamedNodeMapOwnerElementSym)](ownerElement) {
__classPrivateFieldSet(this, _Attr_ownerElement, ownerElement, "f");
__classPrivateFieldSet(this, _Attr_namedNodeMap, ownerElement?.attributes ?? null, "f");
if (ownerElement) {
this._setOwnerDocument(ownerElement.ownerDocument);
}
}
[setAttrValueSym](value) {
__classPrivateFieldSet(this, _Attr_value, value, "f");
}
_shallowClone() {
const newAttr = new Attr(null, __classPrivateFieldGet(this, _Attr_name, "f"), __classPrivateFieldGet(this, _Attr_value, "f"), CTOR_KEY);
newAttr._setOwnerDocument(this.ownerDocument);
return newAttr;
}
cloneNode() {
return super.cloneNode();
}
appendChild() {
throw new DOMException("Cannot add children to an Attribute");
}
replaceChild() {
throw new DOMException("Cannot add children to an Attribute");
}
insertBefore() {
throw new DOMException("Cannot add children to an Attribute");
}
removeChild() {
throw new DOMException("The node to be removed is not a child of this node");
}
get name() {
return __classPrivateFieldGet(this, _Attr_name, "f");
}
get localName() {
// TODO: When we make namespaces a thing this needs
// to be updated
return __classPrivateFieldGet(this, _Attr_name, "f");
}
get value() {
return __classPrivateFieldGet(this, _Attr_value, "f");
}
set value(value) {
__classPrivateFieldSet(this, _Attr_value, String(value), "f");
if (__classPrivateFieldGet(this, _Attr_namedNodeMap, "f")) {
__classPrivateFieldGet(this, _Attr_namedNodeMap, "f")[setNamedNodeMapValueSym](__classPrivateFieldGet(this, _Attr_name, "f"), __classPrivateFieldGet(this, _Attr_value, "f"), true);
}
}
get ownerElement() {
return __classPrivateFieldGet(this, _Attr_ownerElement, "f") ?? null;
}
get specified() {
return true;
}
// TODO
get prefix() {
return null;
}
}
const setNamedNodeMapValueSym = Symbol("setNamedNodeMapValueSym");
const getNamedNodeMapValueSym = Symbol("getNamedNodeMapValueSym");
const getNamedNodeMapAttrNamesSym = Symbol("getNamedNodeMapAttrNamesSym");
const getNamedNodeMapAttrNodeSym = Symbol("getNamedNodeMapAttrNodeSym");
const removeNamedNodeMapAttrSym = Symbol("removeNamedNodeMapAttrSym");
export class NamedNodeMap {
constructor(ownerElement, onAttrNodeChange, key) {
_NamedNodeMap_onAttrNodeChange.set(this, void 0);
_NamedNodeMap_attrNodeCache.set(this, {});
_NamedNodeMap_map.set(this, {});
_NamedNodeMap_length.set(this, 0);
_NamedNodeMap_capacity.set(this, 0);
_NamedNodeMap_ownerElement.set(this, null);
if (key !== CTOR_KEY) {
throw new TypeError("Illegal constructor.");
}
__classPrivateFieldSet(this, _NamedNodeMap_ownerElement, ownerElement, "f");
__classPrivateFieldSet(this, _NamedNodeMap_onAttrNodeChange, onAttrNodeChange, "f");
// Retain ordering of any preceding id or class attributes
for (const attr of ownerElement.getAttributeNames()) {
this[setNamedNodeMapValueSym](attr, ownerElement.getAttribute(attr));
}
}
[(_NamedNodeMap_onAttrNodeChange = new WeakMap(), _NamedNodeMap_attrNodeCache = new WeakMap(), _NamedNodeMap_map = new WeakMap(), _NamedNodeMap_length = new WeakMap(), _NamedNodeMap_capacity = new WeakMap(), _NamedNodeMap_ownerElement = new WeakMap(), getNamedNodeMapAttrNodeSym)](attribute) {
const safeAttrName = "a" + attribute;
let attrNode = __classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName];
if (!attrNode) {
attrNode = __classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName] = new Attr(this, attribute, __classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName], CTOR_KEY);
attrNode[setNamedNodeMapOwnerElementSym](__classPrivateFieldGet(this, _NamedNodeMap_ownerElement, "f"));
}
return attrNode;
}
[getNamedNodeMapAttrNamesSym]() {
const names = [];
for (const [name, value] of Object.entries(__classPrivateFieldGet(this, _NamedNodeMap_map, "f"))) {
if (value !== undefined) {
names.push(name.slice(1)); // Remove "a" for safeAttrName
}
}
return names;
}
[getNamedNodeMapValueSym](attribute) {
const safeAttrName = "a" + attribute;
return __classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName];
}
[setNamedNodeMapValueSym](attribute, value, bubble = false) {
var _d;
const safeAttrName = "a" + attribute;
if (__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] === undefined) {
__classPrivateFieldSet(this, _NamedNodeMap_length, (_d = __classPrivateFieldGet(this, _NamedNodeMap_length, "f"), _d++, _d), "f");
if (__classPrivateFieldGet(this, _NamedNodeMap_length, "f") > __classPrivateFieldGet(this, _NamedNodeMap_capacity, "f")) {
__classPrivateFieldSet(this, _NamedNodeMap_capacity, __classPrivateFieldGet(this, _NamedNodeMap_length, "f"), "f");
const index = __classPrivateFieldGet(this, _NamedNodeMap_capacity, "f") - 1;
Object.defineProperty(this, String(__classPrivateFieldGet(this, _NamedNodeMap_capacity, "f") - 1), {
get: __classPrivateFieldGet(_c, _c, "f", _NamedNodeMap_indexedAttrAccess).bind(this, __classPrivateFieldGet(this, _NamedNodeMap_map, "f"), index),
});
}
}
else if (__classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName]) {
__classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName][setAttrValueSym](value);
}
__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] = value;
if (bubble) {
__classPrivateFieldGet(this, _NamedNodeMap_onAttrNodeChange, "f").call(this, attribute, value);
}
}
/**
* Called when an attribute is removed from
* an element
*/
[removeNamedNodeMapAttrSym](attribute) {
var _d;
const safeAttrName = "a" + attribute;
if (__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] !== undefined) {
__classPrivateFieldSet(this, _NamedNodeMap_length, (_d = __classPrivateFieldGet(this, _NamedNodeMap_length, "f"), _d--, _d), "f");
__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] = undefined;
__classPrivateFieldGet(this, _NamedNodeMap_onAttrNodeChange, "f").call(this, attribute, null);
const attrNode = __classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName];
if (attrNode) {
attrNode[setNamedNodeMapOwnerElementSym](null);
__classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName] = undefined;
}
}
}
*[Symbol.iterator]() {
for (let i = 0; i < this.length; i++) {
yield this[i];
}
}
get length() {
return __classPrivateFieldGet(this, _NamedNodeMap_length, "f");
}
// FIXME: This method should accept anything and basically
// coerce any non numbers (and Infinity/-Infinity) into 0
item(index) {
if (index >= __classPrivateFieldGet(this, _NamedNodeMap_length, "f")) {
return null;
}
return this[index];
}
getNamedItem(attribute) {
const safeAttrName = "a" + attribute;
if (__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] !== undefined) {
return this[getNamedNodeMapAttrNodeSym](attribute);
}
return null;
}
setNamedItem(attrNode) {
if (attrNode.ownerElement) {
throw new DOMException("Attribute already in use");
}
const safeAttrName = "a" + attrNode.name;
const previousAttr = __classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName];
if (previousAttr) {
previousAttr[setNamedNodeMapOwnerElementSym](null);
__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] = undefined;
}
attrNode[setNamedNodeMapOwnerElementSym](__classPrivateFieldGet(this, _NamedNodeMap_ownerElement, "f"));
__classPrivateFieldGet(this, _NamedNodeMap_attrNodeCache, "f")[safeAttrName] = attrNode;
this[setNamedNodeMapValueSym](attrNode.name, attrNode.value, true);
}
removeNamedItem(attribute) {
const safeAttrName = "a" + attribute;
if (__classPrivateFieldGet(this, _NamedNodeMap_map, "f")[safeAttrName] !== undefined) {
const attrNode = this[getNamedNodeMapAttrNodeSym](attribute);
this[removeNamedNodeMapAttrSym](attribute);
return attrNode;
}
throw new DOMException("Node was not found");
}
}
_c = NamedNodeMap;
_NamedNodeMap_indexedAttrAccess = { value: function (map, index) {
if (index + 1 > this.length) {
return undefined;
}
const attribute = Object
.keys(map)
.filter((attribute) => map[attribute] !== undefined)[index]
?.slice(1); // Remove "a" for safeAttrName
return this[getNamedNodeMapAttrNodeSym](attribute);
} };
const XML_NAMESTART_CHAR_RE_SRC = ":A-Za-z_" +
String.raw `\u{C0}-\u{D6}\u{D8}-\u{F6}\u{F8}-\u{2FF}\u{370}-\u{37D}` +
String
.raw `\u{37F}-\u{1FFF}\u{200C}-\u{200D}\u{2070}-\u{218F}\u{2C00}-\u{2FEF}` +
String
.raw `\u{3001}-\u{D7FF}\u{F900}-\u{FDCF}\u{FDF0}-\u{FFFD}\u{10000}-\u{EFFFF}`;
const XML_NAME_CHAR_RE_SRC = XML_NAMESTART_CHAR_RE_SRC +
String.raw `\u{B7}\u{0300}-\u{036F}\u{203F}-\u{2040}0-9.-`;
const xmlNamestartCharRe = new RegExp(`[${XML_NAMESTART_CHAR_RE_SRC}]`, "u");
const xmlNameCharRe = new RegExp(`[${XML_NAME_CHAR_RE_SRC}]`, "u");
export class Element extends Node {
get attributes() {
if (!__classPrivateFieldGet(this, _Element_namedNodeMap, "f")) {
__classPrivateFieldSet(this, _Element_namedNodeMap, new NamedNodeMap(this, (attribute, value) => {
const isRemoved = value === null;
if (value === null) {
value = "";
}
switch (attribute) {
case "class": {
if (isRemoved) {
__classPrivateFieldSet(this, _Element_hasClassNameAttribute, -1, "f");
}
else if (__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f") === -1) {
__classPrivateFieldSet(this, _Element_hasClassNameAttribute, __classPrivateFieldGet(this, _Element_hasIdAttribute, "f") + 1, "f");
}
// This must happen after the attribute is marked removed
__classPrivateFieldSet(this, _Element_currentClassName, value, "f");
__classPrivateFieldGet(this, _Element_instances, "a", _Element_classList_get).value = value;
break;
}
case "id": {
if (isRemoved) {
__classPrivateFieldSet(this, _Element_hasIdAttribute, -1, "f");
}
else if (__classPrivateFieldGet(this, _Element_hasIdAttribute, "f") === -1) {
__classPrivateFieldSet(this, _Element_hasIdAttribute, __classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f") + 1, "f");
}
__classPrivateFieldSet(this, _Element_currentId, value, "f");
break;
}
}
}, CTOR_KEY), "f");
}
return __classPrivateFieldGet(this, _Element_namedNodeMap, "f");
}
[(_Element_namedNodeMap = new WeakMap(), _Element_datasetProxy = new WeakMap(), _Element_currentId = new WeakMap(), _Element_currentClassName = new WeakMap(), _Element_hasIdAttribute = new WeakMap(), _Element_hasClassNameAttribute = new WeakMap(), _Element_classListInstance = new WeakMap(), _Element_instances = new WeakSet(), _Element_classList_get = function _Element_classList_get() {
return __classPrivateFieldGet(this, _Element_classListInstance, "f");
}, initializeClassListSym)]() {
if (__classPrivateFieldGet(this, _Element_classListInstance, "f").constructor === DOMTokenList) {
return;
}
__classPrivateFieldSet(this, _Element_classListInstance, new DOMTokenList((className) => {
if (__classPrivateFieldGet(this, _Element_currentClassName, "f") !== className) {
__classPrivateFieldSet(this, _Element_currentClassName, className, "f");
if (__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f") === -1) {
__classPrivateFieldSet(this, _Element_hasClassNameAttribute, __classPrivateFieldGet(this, _Element_hasIdAttribute, "f") + 1, "f");
}
if (__classPrivateFieldGet(this, _Element_namedNodeMap, "f") &&
(this.hasAttribute("class") || className !== "")) {
this.attributes[setNamedNodeMapValueSym]("class", className);
}
}
}, CTOR_KEY), "f");
}
constructor(tagName, parentNode, attributes, key) {
super(tagName, NodeType.ELEMENT_NODE, parentNode, key);
_Element_instances.add(this);
_Element_namedNodeMap.set(this, null);
_Element_datasetProxy.set(this, null);
_Element_currentId.set(this, "");
_Element_currentClassName.set(this, "");
_Element_hasIdAttribute.set(this, -1);
_Element_hasClassNameAttribute.set(this, -1);
// Only initialize a classList when we need one
_Element_classListInstance.set(this, new UninitializedDOMTokenList(this));
for (const attr of attributes) {
this.setAttribute(attr[0], attr[1]);
}
this.nodeName = getUpperCase(tagName);
}
get tagName() {
return this.nodeName;
}
get localName() {
return getLowerCase(this.tagName);
}
_shallowClone() {
// FIXME: This attribute copying needs to also be fixed in other
// elements that override _shallowClone like <template>
const attributes = [];
for (const attribute of this.getAttributeNames()) {
attributes.push([attribute, this.getAttribute(attribute)]);
}
return new Element(this.nodeName, null, attributes, CTOR_KEY);
}
get childElementCount() {
return this._getChildNodesMutator().elementsView().length;
}
get className() {
return __classPrivateFieldGet(this, _Element_currentClassName, "f");
}
set className(className) {
__classPrivateFieldGet(this, _Element_instances, "a", _Element_classList_get).value = className;
}
get classList() {
return __classPrivateFieldGet(this, _Element_instances, "a", _Element_classList_get);
}
get outerHTML() {
return getOuterOrInnerHtml(this, true);
}
set outerHTML(html) {
if (this.parentNode) {
const { parentElement, parentNode } = this;
let contextLocalName = parentElement?.localName;
switch (parentNode.nodeType) {
case NodeType.DOCUMENT_NODE: {
throw new DOMException("Modifications are not allowed for this document");
}
// setting outerHTML, step 4. Document Fragment
// ref: https://w3c.github.io/DOM-Parsing/#dom-element-outerhtml
case NodeType.DOCUMENT_FRAGMENT_NODE: {
contextLocalName = "body";
// fall-through
}
default: {
const { childNodes: newChildNodes } = fragmentNodesFromString(html, contextLocalName).childNodes[0];
const mutator = parentNode._getChildNodesMutator();
const insertionIndex = mutator.indexOf(this);
for (let i = newChildNodes.length - 1; i >= 0; i--) {
const child = newChildNodes[i];
mutator.splice(insertionIndex, 0, child);
child._setParent(parentNode);
child._setOwnerDocument(parentNode.ownerDocument);
}
this.remove();
}
}
}
}
get innerHTML() {
return getOuterOrInnerHtml(this, false);
}
set innerHTML(html) {
// Remove all children
for (const child of this.childNodes) {
child._setParent(null);
}
const mutator = this._getChildNodesMutator();
mutator.splice(0, this.childNodes.length);
// Parse HTML into new children
if (html.length) {
const parsed = fragmentNodesFromString(html, this.localName);
for (const child of parsed.childNodes[0].childNodes) {
mutator.push(child);
}
for (const child of this.childNodes) {
child._setParent(this);
child._setOwnerDocument(this.ownerDocument);
}
}
}
get innerText() {
return this.textContent;
}
set innerText(text) {
this.textContent = text;
}
get children() {
return this._getChildNodesMutator().elementsView();
}
get id() {
return __classPrivateFieldGet(this, _Element_currentId, "f") || "";
}
set id(id) {
this.setAttribute("id", id);
}
get dataset() {
if (__classPrivateFieldGet(this, _Element_datasetProxy, "f")) {
return __classPrivateFieldGet(this, _Element_datasetProxy, "f");
}
__classPrivateFieldSet(this, _Element_datasetProxy, new Proxy({}, {
get: (_target, property, _receiver) => {
if (typeof property === "string") {
const attributeName = getDatasetHtmlAttrName(property);
return this.getAttribute(attributeName) ?? undefined;
}
return undefined;
},
set: (_target, property, value, _receiver) => {
if (typeof property === "string") {
let attributeName = "data-";
let prevChar = "";
for (const char of property) {
// Step 1. https://html.spec.whatwg.org/multipage/dom.html#dom-domstringmap-setitem
if (prevChar === "-" && lowerCaseCharRe.test(char)) {
throw new DOMException("An invalid or illegal string was specified");
}
// Step 4. https://html.spec.whatwg.org/multipage/dom.html#dom-domstringmap-setitem
if (!xmlNameCharRe.test(char)) {
throw new DOMException("String contains an invalid character");
}
// Step 2. https://html.spec.whatwg.org/multipage/dom.html#dom-domstringmap-setitem
if (upperCaseCharRe.test(char)) {
attributeName += "-";
}
attributeName += char.toLowerCase();
prevChar = char;
}
this.setAttribute(attributeName, String(value));
}
return true;
},
deleteProperty: (_target, property) => {
if (typeof property === "string") {
const attributeName = getDatasetHtmlAttrName(property);
this.removeAttribute(attributeName);
}
return true;
},
ownKeys: (_target) => {
return this
.getAttributeNames()
.flatMap((attributeName) => {
if (attributeName.startsWith?.("data-")) {
return [getDatasetJavascriptName(attributeName)];
}
else {
return [];
}
});
},
getOwnPropertyDescriptor: (_target, property) => {
if (typeof property === "string") {
const attributeName = getDatasetHtmlAttrName(property);
if (this.hasAttribute(attributeName)) {
return {
writable: true,
enumerable: true,
configurable: true,
};
}
}
return undefined;
},
has: (_target, property) => {
if (typeof property === "string") {
const attributeName = getDatasetHtmlAttrName(property);
return this.hasAttribute(attributeName);
}
return false;
},
}), "f");
return __classPrivateFieldGet(this, _Element_datasetProxy, "f");
}
getAttributeNames() {
if (!__classPrivateFieldGet(this, _Element_namedNodeMap, "f")) {
const attributes = [];
// We preserve the order of the "id" and "class" attributes when
// returning the list of names with an uninitialized NamedNodeMap
const startWithClassAttr = Number(__classPrivateFieldGet(this, _Element_hasIdAttribute, "f") > __classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f"));
for (let i = 0; i < 2; i++) {
const attributeIdx = (i + startWithClassAttr) % 2;
switch (attributeIdx) {
// "id" attribute
case 0: {
~__classPrivateFieldGet(this, _Element_hasIdAttribute, "f") && attributes.push("id");
break;
}
// "class" attribute
case 1: {
~__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f") && attributes.push("class");
break;
}
}
}
return attributes;
}
return this.attributes[getNamedNodeMapAttrNamesSym]();
}
getAttribute(rawName) {
const name = getLowerCase(String(rawName));
switch (name) {
case "id": {
if (~__classPrivateFieldGet(this, _Element_hasIdAttribute, "f")) {
return __classPrivateFieldGet(this, _Element_currentId, "f");
}
else {
return null;
}
}
case "class": {
if (~__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f")) {
return __classPrivateFieldGet(this, _Element_currentClassName, "f");
}
else {
return null;
}
}
}
if (!__classPrivateFieldGet(this, _Element_namedNodeMap, "f")) {
return null;
}
return this.attributes[getNamedNodeMapValueSym](name) ?? null;
}
setAttribute(rawName, value) {
const name = getLowerCase(String(rawName));
const strValue = String(value);
let isNormalAttribute = false;
switch (name) {
case "id": {
__classPrivateFieldSet(this, _Element_currentId, strValue, "f");
if (__classPrivateFieldGet(this, _Element_hasIdAttribute, "f") === -1) {
__classPrivateFieldSet(this, _Element_hasIdAttribute, __classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f") + 1, "f");
}
break;
}
case "class": {
__classPrivateFieldGet(this, _Element_instances, "a", _Element_classList_get).value = strValue;
if (__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f") === -1) {
__classPrivateFieldSet(this, _Element_hasClassNameAttribute, __classPrivateFieldGet(this, _Element_hasIdAttribute, "f") + 1, "f");
}
break;
}
default: {
isNormalAttribute = true;
}
}
if (__classPrivateFieldGet(this, _Element_namedNodeMap, "f") || isNormalAttribute) {
this.attributes[setNamedNodeMapValueSym](name, strValue);
}
}
removeAttribute(rawName) {
const name = getLowerCase(String(rawName));
switch (name) {
case "id": {
__classPrivateFieldSet(this, _Element_currentId, "", "f");
__classPrivateFieldSet(this, _Element_hasIdAttribute, -1, "f");
break;
}
case "class": {
__classPrivateFieldGet(this, _Element_instances, "a", _Element_classList_get).value = "";
__classPrivateFieldSet(this, _Element_hasClassNameAttribute, -1, "f");
break;
}
}
if (!__classPrivateFieldGet(this, _Element_namedNodeMap, "f")) {
return;
}
this.attributes[removeNamedNodeMapAttrSym](name);
}
toggleAttribute(rawName, force) {
const name = getLowerCase(String(rawName));
if (this.hasAttribute(name)) {
if ((force === undefined) || (force === false)) {
this.removeAttribute(name);
return false;
}
return true;
}
if ((force === undefined) || (force === true)) {
this.setAttribute(name, "");
return true;
}
return false;
}
hasAttribute(rawName) {
const name = getLowerCase(String(rawName));
switch (name) {
case "id": {
return Boolean(~__classPrivateFieldGet(this, _Element_hasIdAttribute, "f"));
}
case "class": {
return Boolean(~__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f"));
}
}
if (!__classPrivateFieldGet(this, _Element_namedNodeMap, "f")) {
return false;
}
return this.attributes[getNamedNodeMapValueSym](name) !== undefined;
}
hasAttributeNS(_namespace, rawName) {
const name = getLowerCase(String(rawName));
switch (name) {
case "id": {
return Boolean(~__classPrivateFieldGet(this, _Element_hasIdAttribute, "f"));
}
case "class": {
return Boolean(~__classPrivateFieldGet(this, _Element_hasClassNameAttribute, "f"));
}
}
if (!__classPrivateFieldGet(this, _Element_namedNodeMap, "f")) {
return false;
}
// TODO: Use namespace
return this.attributes[getNamedNodeMapValueSym](name) !== undefined;
}
replaceWith(...nodes) {
this._replaceWith(...nodes);
}
remove() {
this._remove();
}
append(...nodes) {
const mutator = this._getChildNodesMutator();
mutator.push(...nodesAndTextNodes(nodes, this));
}
prepend(...nodes) {
const mutator = this._getChildNodesMutator();
mutator.splice(0, 0, ...nodesAndTextNodes(nodes, this));
}
before(...nodes) {
if (this.parentNode) {
insertBeforeAfter(this, nodes, true);
}
}
after(...nodes) {
if (this.parentNode) {
insertBeforeAfter(this, nodes, false);
}
}
get firstElementChild() {
const elements = this._getChildNodesMutator().elementsView();
return elements[0] ?? null;
}
get lastElementChild() {
const elements = this._getChildNodesMutator().elementsView();
return elements[elements.length - 1] ?? null;
}
get nextElementSibling() {
const parent = this.parentNode;
if (!parent) {
return null;
}
const mutator = parent._getChildNodesMutator();
const index = mutator.indexOfElementsView(this);
const elements = mutator.elementsView();
return elements[index + 1] ?? null;
}
get previousElementSibling() {
const parent = this.parentNode;
if (!parent) {
return null;
}
const mutator = parent._getChildNodesMutator();
const index = mutator.indexOfElementsView(this);
const elements = mutator.elementsView();
return elements[index - 1] ?? null;
}
querySelector(selectors) {
if (!this.ownerDocument) {
throw new Error("Element must have an owner document");
}
return this.ownerDocument._nwapi.first(selectors, this);
}
querySelectorAll(selectors) {
if (!this.ownerDocument) {
throw new Error("Element must have an owner document");
}
const nodeList = new NodeList();
const mutator = nodeList[nodeListMutatorSym]();
for (const match of this.ownerDocument._nwapi.select(selectors, this)) {
mutator.push(match);
}
return nodeList;
}
matches(selectorString) {
return this.ownerDocument._nwapi.match(selectorString, this);
}
closest(selectorString) {
const { match } = this.ownerDocument._nwapi; // See note below
// deno-lint-ignore no-this-alias
let el = this;
do {
// Note: Not using `el.matches(selectorString)` because on a browser if you override
// `matches`, you *don't* see it being used by `closest`.
if (match(selectorString, el)) {
return el;
}
el = el.parentElement;
} while (el !== null);
return null;
}
// TODO: DRY!!!
getElementById(id) {
if (!this._hasInitializedChildNodes()) {
return null;
}
for (const child of this.childNodes) {
if (child.nodeType === NodeType.ELEMENT_NODE) {
if (child.id === id) {
return child;
}
const search = child.getElementById(id);
if (search) {
return search;
}
}
}
return null;
}
getElementsByTagName(tagName) {
if (!this._hasInitializedChildNodes()) {
return [];
}
const fixCaseTagName = getUpperCase(tagName);
if (fixCaseTagName === "*") {
return this._getElementsByTagNameWildcard([]);
}
else {
return this._getElementsByTagName(fixCaseTagName, []);
}
}
_getElementsByTagNameWildcard(search) {
if (!this._hasInitializedChildNodes()) {
return search;
}
for (const child of this.childNodes) {
if (child.nodeType === NodeType.ELEMENT_NODE) {
search.push(child);
child._getElementsByTagNameWildcard(search);
}
}
return search;
}
_getElementsByTagName(tagName, search) {
if (!this._hasInitializedChildNodes()) {
return search;
}
for (const child of this.childNodes) {
if (child.nodeType === NodeType.ELEMENT_NODE) {
if (child.tagName === tagName) {
search.push(child);
}
child._getElementsByTagName(tagName, search);
}
}
return search;
}
getElementsByClassName(className) {
if (!this._hasInitializedChildNodes()) {
return [];
}
return getElementsByClassName(this, className.trim().split(/\s+/), []);
}
getElementsByTagNameNS(_namespace, localName) {
if (!this._hasInitializedChildNodes()) {
return [];
}
// TODO: Use namespace
return this.getElementsByTagName(localName);
}
}
UtilTypes.Element = Element;