New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

linkedom

Package Overview
Dependencies
Maintainers
1
Versions
214
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

linkedom - npm Package Compare versions

Comparing version 0.1.33 to 0.1.34

10

cjs/attr.js

@@ -5,5 +5,7 @@ 'use strict';

const {ATTRIBUTE_NODE} = require('./constants.js');
const {String, attributeChangedCallback} = require('./utils.js');
const {String} = require('./utils.js');
const {Node} = require('./node.js');
const {attributeChangedCallback} = require('./custom-element-registry.js');
/**

@@ -31,5 +33,5 @@ * @implements globalThis.Attr

this._changed = true;
attributeChangedCallback(
ownerElement, name, _value, this._value = String(value)
);
this._value = String(value);
if (ownerElement)
attributeChangedCallback(ownerElement, name, _value, this._value);
}

@@ -36,0 +38,0 @@

63

cjs/custom-element-registry.js
'use strict';
const getCE = element => element.getAttribute('is') || element.localName;
const {ELEMENT_NODE} = require("../cjs/constants");
const {keys, setPrototypeOf} = Object;
const classes = new WeakMap;
exports.classes = classes;
const {keys, setPrototypeOf} = Object;
const shouldTrigger = element => {
const {_active, _hold} = element.ownerDocument._customElements;
return _active && !_hold;
};
const attributeChangedCallback = (element, name, oldValue, newValue) => {
if (
element._custom &&
element.attributeChangedCallback &&
element.constructor.observedAttributes.includes(name)
) {
element.attributeChangedCallback(name, oldValue, newValue);
}
};
exports.attributeChangedCallback = attributeChangedCallback;
const triggerConnected = element => {
if (element._custom && element.connectedCallback && element.isConnected)
element.connectedCallback();
};
const connectedCallback = element => {
if (shouldTrigger(element)) {
triggerConnected(element);
let {_next, _end} = element;
while (_next !== _end) {
if (_next.nodeType === ELEMENT_NODE)
triggerConnected(_next);
_next = _next._next;
}
}
};
exports.connectedCallback = connectedCallback;
const triggerDisconnected = element => {
if (element._custom && element.disconnectedCallback && !element.isConnected)
element.disconnectedCallback();
};
const disconnectedCallback = element => {
if (shouldTrigger(element)) {
triggerDisconnected(element);
let {_next, _end} = element;
while (_next !== _end) {
if (_next.nodeType === ELEMENT_NODE)
triggerDisconnected(_next);
_next = _next._next;
}
}
};
exports.disconnectedCallback = disconnectedCallback;
/**

@@ -22,2 +74,3 @@ * @implements globalThis.CustomElementRegistry

this._active = false;
this._hold = false;
}

@@ -74,3 +127,3 @@

const {_registry} = this;
const ce = getCE(element);
const ce = element.getAttribute('is') || element.localName;
if (_registry.has(ce)) {

@@ -90,4 +143,4 @@ const {Class, check} = _registry.get(ce);

element._custom = true;
if (element.isConnected && element.connectedCallback)
element.connectedCallback();
if (element.isConnected)
connectedCallback(element);
}

@@ -94,0 +147,0 @@ }

'use strict';
const {DOCUMENT_NODE, DOM} = require('./constants.js');
const {DOCUMENT_NODE, TEXT_NODE, DOM} = require('./constants.js');
const {Mime} = require('./utils.js');
const {Mime, setBoundaries} = require('./utils.js');

@@ -96,3 +96,51 @@ // mixins & interfaces

const {create, defineProperties} = Object;
const {toString} = Element.prototype;
const textOnlyDescriptors = {
_updateTextContent: {
value(content, createNode) {
this.replaceChildren();
const {ownerDocument, _end} = this;
const text = createNode ? ownerDocument.createTextNode(content) : content;
text.parentNode = this;
setBoundaries(this, text, this._end);
}
},
innerHTML : {
get() {
return this.textContent;
},
set(html) {
this.textContent = html;
}
},
textContent: {
get() {
const {firstChild} = this;
return firstChild ? firstChild.textContent : '';
},
set(content) {
this._updateTextContent(content, true);
}
},
// TODO: this is not perfect, although I don't think there are
// real world use cases to make it perfect 🤷‍♂️
// if there are though, this node should accept nodes *but*
// use these as `textContent` only
insertBefore: {
value(node) {
node.remove();
this._updateTextContent(node, node.nodeType !== TEXT_NODE);
node.parentNode = this;
return node;
}
},
toString: {
value() {
const outerHTML = toString.call(this.cloneNode());
return outerHTML.replace(/></, `>${this.textContent}<`);
}
}
};
const defaultViewExports = {

@@ -181,3 +229,3 @@ Event, CustomEvent,

this._mime = Mime[type];
this._customElements = {_active: false};
this._customElements = {_active: false, _hold: false};

@@ -328,2 +376,4 @@ /**

element.setAttribute('is', options.is);
if (this._mime.textOnly.test(localName))
defineProperties(element, textOnlyDescriptors);
}

@@ -330,0 +380,0 @@ else

@@ -5,10 +5,13 @@ 'use strict';

String,
attributeChangedCallback,
getNext,
getPrev,
setAdjacent,
ignoreCase,
localCase,
parseFromString
parseFromString,
setBoundaries
} = require('./utils.js');
const {attributeChangedCallback} = require('./custom-element-registry.js');
const {NodeList} = require('./interfaces.js');

@@ -133,6 +136,14 @@ const {NonDocumentTypeChildNode, ParentNode} = require('./mixins.js');

// awkward ... but necessary to avoid triggering Custom Events
// while created through the parseFromString procedure
set innerHTML(html) {
const {constructor} = this.ownerDocument;
const document = parseFromString(new constructor, ignoreCase(this), html);
this.replaceChildren(...document.documentElement.childNodes);
const {constructor, _customElements} = this.ownerDocument;
const document = new constructor;
document._customElements = _customElements;
_customElements._hold = true;
const {childNodes} = parseFromString(document, ignoreCase(this), html).documentElement;
const fragment = document.createDocumentFragment();
fragment.append(...childNodes);
_customElements._hold = false;
this.replaceChildren(fragment);
}

@@ -228,10 +239,7 @@

const {_prev, _next, name} = attribute;
_prev._next = _next;
_next._prev = _prev;
setAdjacent(_prev, _next);
attribute.ownerElement = attribute._prev = attribute._next = null;
if (name === 'class')
this._classList = null;
attributeChangedCallback(
this, name, attribute._value, null
);
attributeChangedCallback(this, name, attribute._value, null);
return;

@@ -258,10 +266,6 @@ }

attribute.ownerElement = this;
attribute._prev = this;
attribute._next = _next;
this._next = _next._prev = attribute;
setBoundaries(this, attribute, _next);
if (name === 'class')
this.className = attribute._value;
attributeChangedCallback(
this, name, null, attribute._value
);
attributeChangedCallback(this, name, null, attribute._value);
}

@@ -268,0 +272,0 @@ return previously;

@@ -7,2 +7,6 @@ 'use strict';

(m => {
exports.Node = m.Node;
})(require('./node.js'));
(m => {
exports.HTMLElement = m.HTMLElement;

@@ -12,5 +16,5 @@ })(require('./html/html-element.js'));

(m => {
exports.EventTarget = m.EventTarget;
exports.Event = m.Event;
exports.CustomEvent = m.CustomEvent;
exports.Event = m.Event;
exports.EventTarget = m.EventTarget;
})(require('./interfaces.js'));

@@ -11,5 +11,9 @@ 'use strict';

const {disconnectedCallback} = require('./custom-element-registry.js');
const {
findNext,
getEnd
getEnd,
setAdjacent,
setBoundaries
} = require('./utils.js');

@@ -64,14 +68,12 @@

remove(node) {
let {_prev, _next, nodeType} = node;
let _end = node;
if (nodeType === ELEMENT_NODE) {
_end = node._end;
_next = _end._next;
const {_prev} = node;
const {_next} = getEnd(node);
if (_prev || _next || node.parentNode) {
node.parentNode = null;
setAdjacent(_prev, _next);
setBoundaries(null, node, null);
if (node.nodeType === ELEMENT_NODE)
disconnectedCallback(node);
// DO_NOT_REMOVE if (parentNode) invalidate(parentNode);
}
if (_prev) _prev._next = _next;
if (_next) _next._prev = _prev;
node.parentNode = node._prev = _end._next = null;
if (node._custom && node.disconnectedCallback)
node.disconnectedCallback();
// DO_NOT_REMOVE if (parentNode) invalidate(parentNode);
}

@@ -78,0 +80,0 @@ };

@@ -16,2 +16,4 @@ 'use strict';

const {connectedCallback} = require('./custom-element-registry.js');
const {

@@ -21,2 +23,4 @@ String,

getBoundaries,
setAdjacent,
setBoundaries,
getEnd,

@@ -72,2 +76,9 @@ getNext,

get ELEMENT_NODE() { return this.constructor.ELEMENT_NODE; }
get ATTRIBUTE_NODE() { return this.constructor.ATTRIBUTE_NODE; }
get TEXT_NODE() { return this.constructor.TEXT_NODE; }
get COMMENT_NODE() { return this.constructor.COMMENT_NODE; }
get DOCUMENT_NODE() { return this.constructor.DOCUMENT_NODE; }
get DOCUMENT_FRAGMENT_NODE() { return this.constructor.DOCUMENT_FRAGMENT_NODE; }
// <ChildNode>

@@ -147,4 +158,4 @@ before(...nodes) {

_next.parentNode = parentNode;
_next._prev = $next;
$next = ($next._next = _next);
setAdjacent($next, _next);
$next = _next;
};

@@ -157,4 +168,4 @@ const clone = create(OD, this, localName, SVGElement);

case ELEMENT_NODE_END:
parentNode._end._prev = $next;
$next = ($next._next = parentNode._end);
setAdjacent($next, parentNode._end);
$next = parentNode._end;
parentNode = parentNode.parentNode;

@@ -181,4 +192,3 @@ break;

}
clone._end._prev = $next;
$next._next = clone._end;
setAdjacent($next, clone._end);
return clone;

@@ -379,9 +389,5 @@ case TEXT_NODE:

node.remove();
_prev._next = node;
_end._prev = node._end;
node._prev = _prev;
node._end._next = _end;
node.parentNode = this;
if (node._custom && node.connectedCallback)
node.connectedCallback();
setBoundaries(_prev, node, _end);
connectedCallback(node);
break;

@@ -393,18 +399,14 @@ }

if (firstChild) {
_prev._next = firstChild;
firstChild._prev = _prev;
const last = getEnd(lastChild);
_end._prev = last;
last._next = _end;
setAdjacent(_prev, firstChild);
setAdjacent(getEnd(lastChild), _end);
// reset fragment
node._next = node._end;
node._end._prev = node;
setAdjacent(node, node._end);
// set parent node
do {
firstChild.parentNode = this;
if (firstChild._custom && firstChild.connectedCallback)
firstChild.connectedCallback();
if (firstChild.nodeType === ELEMENT_NODE)
connectedCallback(firstChild);
} while (
firstChild !== lastChild &&
(firstChild = firstChild._next)
(firstChild = firstChild.nextSibling)
);

@@ -416,6 +418,4 @@ }

node.remove();
_prev._next = _end._prev = node;
node._prev = _prev;
node._next = _end;
node.parentNode = this;
setBoundaries(_prev, node, _end);
break;

@@ -469,8 +469,4 @@ }

node.remove();
_prev._next = node;
node._prev = _prev;
const _end = getEnd(node);
_next._prev = _end;
_end._next = _next;
node.parentNode = this;
setBoundaries(_prev, node, _next);
return replaced;

@@ -477,0 +473,0 @@ }

'use strict';
const {getEnd} = require('./utils.js');
const {getEnd, setAdjacent} = require('./utils.js');

@@ -11,4 +11,3 @@ // https://dom.spec.whatwg.org/#concept-live-range

const deleteContents = ({_start, _end}, fragment = null) => {
_start._prev._next = _end._next;
_end._next._prev = _start._prev;
setAdjacent(_start._prev, _end._next);
do {

@@ -15,0 +14,0 @@ const end = getEnd(_start);

@@ -16,2 +16,3 @@ 'use strict';

const textOnly = {test: () => false};
const voidElements = {test: () => true};

@@ -22,7 +23,15 @@ const Mime = {

ignoreCase: true,
textOnly: /^(?:plaintext|script|style|textarea|title|xmp)$/i,
voidElements: /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i
},
'image/svg+xml': {
docType: '',
ignoreCase: false,
textOnly,
voidElements
},
'text/xml': {
docType: '<?xml version="1.0" encoding="utf-8"?>',
ignoreCase: false,
textOnly,
voidElements

@@ -33,2 +42,3 @@ },

ignoreCase: false,
textOnly,
voidElements

@@ -39,8 +49,4 @@ },

ignoreCase: false,
textOnly,
voidElements
},
'image/svg+xml': {
docType: '',
ignoreCase: false,
voidElements
}

@@ -50,14 +56,2 @@ };

const attributeChangedCallback = (element, name, oldValue, newValue) => {
if (
element &&
element._custom &&
element.attributeChangedCallback &&
element.constructor.observedAttributes.includes(name)
) {
element.attributeChangedCallback(name, oldValue, newValue);
}
};
exports.attributeChangedCallback = attributeChangedCallback;
const booleanAttribute = {

@@ -124,2 +118,21 @@ get(element, name) {

const setAdjacent = (before, after) => {
if (before)
before._next = after;
if (after)
after._prev = before;
};
exports.setAdjacent = setAdjacent;
const setBoundaries = (before, current, after) => {
if (before)
before._next = current;
current._prev = before;
current = getEnd(current);
current._next = after;
if (after)
after._prev = current;
};
exports.setBoundaries = setBoundaries;
const HTML = 'text/html';

@@ -134,2 +147,4 @@ const VOID_SOURCE = Mime[HTML].voidElements.source.slice(4, -2);

const {SVGElement} = document[DOM];
const {_customElements} = document;
const {_active, _registry} = _customElements;
let node = document.root || document.createElement('root');

@@ -149,2 +164,7 @@ let ownerSVGElement = null;

}
else if (_active && _registry.has(name)) {
const {Class} = _registry.get(name);
node = node.appendChild(new Class);
return;
}
}

@@ -154,3 +174,12 @@ node = node.appendChild(document.createElement(name));

onattribute(name, value) {
node.setAttribute(name, value);
if (isHTML && _active && name === 'is' && _registry.has(value)) {
const {Class} = _registry.get(value);
const custom = new Class;
for (const attribute of node.attributes)
custom.setAttributeNode(attribute);
node.replaceWith(custom);
node = custom;
}
else
node.setAttribute(name, value);
},

@@ -157,0 +186,0 @@ oncomment(data) {

import {escape} from 'html-escaper';
import {ATTRIBUTE_NODE} from './constants.js';
import {String, attributeChangedCallback} from './utils.js';
import {String} from './utils.js';
import {Node} from './node.js';
import {attributeChangedCallback} from './custom-element-registry.js';
/**

@@ -29,5 +31,5 @@ * @implements globalThis.Attr

this._changed = true;
attributeChangedCallback(
ownerElement, name, _value, this._value = String(value)
);
this._value = String(value);
if (ownerElement)
attributeChangedCallback(ownerElement, name, _value, this._value);
}

@@ -34,0 +36,0 @@

@@ -1,7 +0,56 @@

const getCE = element => element.getAttribute('is') || element.localName;
import {ELEMENT_NODE} from "../cjs/constants";
const {keys, setPrototypeOf} = Object;
export const classes = new WeakMap;
const {keys, setPrototypeOf} = Object;
const shouldTrigger = element => {
const {_active, _hold} = element.ownerDocument._customElements;
return _active && !_hold;
};
export const attributeChangedCallback = (element, name, oldValue, newValue) => {
if (
element._custom &&
element.attributeChangedCallback &&
element.constructor.observedAttributes.includes(name)
) {
element.attributeChangedCallback(name, oldValue, newValue);
}
};
const triggerConnected = element => {
if (element._custom && element.connectedCallback && element.isConnected)
element.connectedCallback();
};
export const connectedCallback = element => {
if (shouldTrigger(element)) {
triggerConnected(element);
let {_next, _end} = element;
while (_next !== _end) {
if (_next.nodeType === ELEMENT_NODE)
triggerConnected(_next);
_next = _next._next;
}
}
};
const triggerDisconnected = element => {
if (element._custom && element.disconnectedCallback && !element.isConnected)
element.disconnectedCallback();
};
export const disconnectedCallback = element => {
if (shouldTrigger(element)) {
triggerDisconnected(element);
let {_next, _end} = element;
while (_next !== _end) {
if (_next.nodeType === ELEMENT_NODE)
triggerDisconnected(_next);
_next = _next._next;
}
}
};
/**

@@ -20,2 +69,3 @@ * @implements globalThis.CustomElementRegistry

this._active = false;
this._hold = false;
}

@@ -72,3 +122,3 @@

const {_registry} = this;
const ce = getCE(element);
const ce = element.getAttribute('is') || element.localName;
if (_registry.has(ce)) {

@@ -88,4 +138,4 @@ const {Class, check} = _registry.get(ce);

element._custom = true;
if (element.isConnected && element.connectedCallback)
element.connectedCallback();
if (element.isConnected)
connectedCallback(element);
}

@@ -92,0 +142,0 @@ }

@@ -1,4 +0,4 @@

import {DOCUMENT_NODE, DOM} from './constants.js';
import {DOCUMENT_NODE, TEXT_NODE, DOM} from './constants.js';
import {Mime} from './utils.js';
import {Mime, setBoundaries} from './utils.js';

@@ -95,3 +95,51 @@ // mixins & interfaces

const {create, defineProperties} = Object;
const {toString} = Element.prototype;
const textOnlyDescriptors = {
_updateTextContent: {
value(content, createNode) {
this.replaceChildren();
const {ownerDocument, _end} = this;
const text = createNode ? ownerDocument.createTextNode(content) : content;
text.parentNode = this;
setBoundaries(this, text, this._end);
}
},
innerHTML : {
get() {
return this.textContent;
},
set(html) {
this.textContent = html;
}
},
textContent: {
get() {
const {firstChild} = this;
return firstChild ? firstChild.textContent : '';
},
set(content) {
this._updateTextContent(content, true);
}
},
// TODO: this is not perfect, although I don't think there are
// real world use cases to make it perfect 🤷‍♂️
// if there are though, this node should accept nodes *but*
// use these as `textContent` only
insertBefore: {
value(node) {
node.remove();
this._updateTextContent(node, node.nodeType !== TEXT_NODE);
node.parentNode = this;
return node;
}
},
toString: {
value() {
const outerHTML = toString.call(this.cloneNode());
return outerHTML.replace(/></, `>${this.textContent}<`);
}
}
};
const defaultViewExports = {

@@ -180,3 +228,3 @@ Event, CustomEvent,

this._mime = Mime[type];
this._customElements = {_active: false};
this._customElements = {_active: false, _hold: false};

@@ -327,2 +375,4 @@ /**

element.setAttribute('is', options.is);
if (this._mime.textOnly.test(localName))
defineProperties(element, textOnlyDescriptors);
}

@@ -329,0 +379,0 @@ else

import {ELEMENT_NODE, ELEMENT_NODE_END, ATTRIBUTE_NODE, TEXT_NODE, COMMENT_NODE} from './constants.js';
import {
String,
attributeChangedCallback,
getNext, getPrev,
getNext, getPrev, setAdjacent,
ignoreCase, localCase,
parseFromString
parseFromString,
setBoundaries
} from './utils.js';
import {attributeChangedCallback} from './custom-element-registry.js';
import {NodeList} from './interfaces.js';

@@ -129,6 +131,14 @@ import {NonDocumentTypeChildNode, ParentNode} from './mixins.js';

// awkward ... but necessary to avoid triggering Custom Events
// while created through the parseFromString procedure
set innerHTML(html) {
const {constructor} = this.ownerDocument;
const document = parseFromString(new constructor, ignoreCase(this), html);
this.replaceChildren(...document.documentElement.childNodes);
const {constructor, _customElements} = this.ownerDocument;
const document = new constructor;
document._customElements = _customElements;
_customElements._hold = true;
const {childNodes} = parseFromString(document, ignoreCase(this), html).documentElement;
const fragment = document.createDocumentFragment();
fragment.append(...childNodes);
_customElements._hold = false;
this.replaceChildren(fragment);
}

@@ -224,10 +234,7 @@

const {_prev, _next, name} = attribute;
_prev._next = _next;
_next._prev = _prev;
setAdjacent(_prev, _next);
attribute.ownerElement = attribute._prev = attribute._next = null;
if (name === 'class')
this._classList = null;
attributeChangedCallback(
this, name, attribute._value, null
);
attributeChangedCallback(this, name, attribute._value, null);
return;

@@ -254,10 +261,6 @@ }

attribute.ownerElement = this;
attribute._prev = this;
attribute._next = _next;
this._next = _next._prev = attribute;
setBoundaries(this, attribute, _next);
if (name === 'class')
this.className = attribute._value;
attributeChangedCallback(
this, name, null, attribute._value
);
attributeChangedCallback(this, name, null, attribute._value);
}

@@ -264,0 +267,0 @@ return previously;

export {DOMParser} from './dom-parser.js';
export {Node} from './node.js';
export {HTMLElement} from './html/html-element.js';
export {
CustomEvent,
Event,
EventTarget
} from './interfaces.js';
export {EventTarget, Event, CustomEvent} from './interfaces.js';

@@ -10,5 +10,9 @@ import {

import {disconnectedCallback} from './custom-element-registry.js';
import {
findNext,
getEnd,
setAdjacent,
setBoundaries
// invalidate

@@ -64,14 +68,12 @@ } from './utils.js';

remove(node) {
let {_prev, _next, nodeType} = node;
let _end = node;
if (nodeType === ELEMENT_NODE) {
_end = node._end;
_next = _end._next;
const {_prev} = node;
const {_next} = getEnd(node);
if (_prev || _next || node.parentNode) {
node.parentNode = null;
setAdjacent(_prev, _next);
setBoundaries(null, node, null);
if (node.nodeType === ELEMENT_NODE)
disconnectedCallback(node);
// DO_NOT_REMOVE if (parentNode) invalidate(parentNode);
}
if (_prev) _prev._next = _next;
if (_next) _next._prev = _prev;
node.parentNode = node._prev = _end._next = null;
if (node._custom && node.disconnectedCallback)
node.disconnectedCallback();
// DO_NOT_REMOVE if (parentNode) invalidate(parentNode);
}

@@ -78,0 +80,0 @@ };

@@ -15,2 +15,4 @@ import {

import {connectedCallback} from './custom-element-registry.js';
import {

@@ -20,2 +22,4 @@ String,

getBoundaries,
setAdjacent,
setBoundaries,
getEnd,

@@ -72,2 +76,9 @@ getNext,

get ELEMENT_NODE() { return this.constructor.ELEMENT_NODE; }
get ATTRIBUTE_NODE() { return this.constructor.ATTRIBUTE_NODE; }
get TEXT_NODE() { return this.constructor.TEXT_NODE; }
get COMMENT_NODE() { return this.constructor.COMMENT_NODE; }
get DOCUMENT_NODE() { return this.constructor.DOCUMENT_NODE; }
get DOCUMENT_FRAGMENT_NODE() { return this.constructor.DOCUMENT_FRAGMENT_NODE; }
// <ChildNode>

@@ -147,4 +158,4 @@ before(...nodes) {

_next.parentNode = parentNode;
_next._prev = $next;
$next = ($next._next = _next);
setAdjacent($next, _next);
$next = _next;
};

@@ -157,4 +168,4 @@ const clone = create(OD, this, localName, SVGElement);

case ELEMENT_NODE_END:
parentNode._end._prev = $next;
$next = ($next._next = parentNode._end);
setAdjacent($next, parentNode._end);
$next = parentNode._end;
parentNode = parentNode.parentNode;

@@ -181,4 +192,3 @@ break;

}
clone._end._prev = $next;
$next._next = clone._end;
setAdjacent($next, clone._end);
return clone;

@@ -378,9 +388,5 @@ case TEXT_NODE:

node.remove();
_prev._next = node;
_end._prev = node._end;
node._prev = _prev;
node._end._next = _end;
node.parentNode = this;
if (node._custom && node.connectedCallback)
node.connectedCallback();
setBoundaries(_prev, node, _end);
connectedCallback(node);
break;

@@ -392,18 +398,14 @@ }

if (firstChild) {
_prev._next = firstChild;
firstChild._prev = _prev;
const last = getEnd(lastChild);
_end._prev = last;
last._next = _end;
setAdjacent(_prev, firstChild);
setAdjacent(getEnd(lastChild), _end);
// reset fragment
node._next = node._end;
node._end._prev = node;
setAdjacent(node, node._end);
// set parent node
do {
firstChild.parentNode = this;
if (firstChild._custom && firstChild.connectedCallback)
firstChild.connectedCallback();
if (firstChild.nodeType === ELEMENT_NODE)
connectedCallback(firstChild);
} while (
firstChild !== lastChild &&
(firstChild = firstChild._next)
(firstChild = firstChild.nextSibling)
);

@@ -415,6 +417,4 @@ }

node.remove();
_prev._next = _end._prev = node;
node._prev = _prev;
node._next = _end;
node.parentNode = this;
setBoundaries(_prev, node, _end);
break;

@@ -468,8 +468,4 @@ }

node.remove();
_prev._next = node;
node._prev = _prev;
const _end = getEnd(node);
_next._prev = _end;
_end._next = _next;
node.parentNode = this;
setBoundaries(_prev, node, _next);
return replaced;

@@ -476,0 +472,0 @@ }

@@ -1,2 +0,2 @@

import {getEnd} from './utils.js';
import {getEnd, setAdjacent} from './utils.js';

@@ -10,4 +10,3 @@ // https://dom.spec.whatwg.org/#concept-live-range

const deleteContents = ({_start, _end}, fragment = null) => {
_start._prev._next = _end._next;
_end._next._prev = _start._prev;
setAdjacent(_start._prev, _end._next);
do {

@@ -14,0 +13,0 @@ const end = getEnd(_start);

@@ -15,2 +15,3 @@ import {Parser} from 'htmlparser2';

const textOnly = {test: () => false};
const voidElements = {test: () => true};

@@ -21,7 +22,15 @@ export const Mime = {

ignoreCase: true,
textOnly: /^(?:plaintext|script|style|textarea|title|xmp)$/i,
voidElements: /^(?:area|base|br|col|embed|hr|img|input|keygen|link|menuitem|meta|param|source|track|wbr)$/i
},
'image/svg+xml': {
docType: '',
ignoreCase: false,
textOnly,
voidElements
},
'text/xml': {
docType: '<?xml version="1.0" encoding="utf-8"?>',
ignoreCase: false,
textOnly,
voidElements

@@ -32,2 +41,3 @@ },

ignoreCase: false,
textOnly,
voidElements

@@ -38,22 +48,7 @@ },

ignoreCase: false,
textOnly,
voidElements
},
'image/svg+xml': {
docType: '',
ignoreCase: false,
voidElements
}
};
export const attributeChangedCallback = (element, name, oldValue, newValue) => {
if (
element &&
element._custom &&
element.attributeChangedCallback &&
element.constructor.observedAttributes.includes(name)
) {
element.attributeChangedCallback(name, oldValue, newValue);
}
};
export const booleanAttribute = {

@@ -112,2 +107,19 @@ get(element, name) {

export const setAdjacent = (before, after) => {
if (before)
before._next = after;
if (after)
after._prev = before;
};
export const setBoundaries = (before, current, after) => {
if (before)
before._next = current;
current._prev = before;
current = getEnd(current);
current._next = after;
if (after)
after._prev = current;
};
const HTML = 'text/html';

@@ -122,2 +134,4 @@ const VOID_SOURCE = Mime[HTML].voidElements.source.slice(4, -2);

const {SVGElement} = document[DOM];
const {_customElements} = document;
const {_active, _registry} = _customElements;
let node = document.root || document.createElement('root');

@@ -137,2 +151,7 @@ let ownerSVGElement = null;

}
else if (_active && _registry.has(name)) {
const {Class} = _registry.get(name);
node = node.appendChild(new Class);
return;
}
}

@@ -142,3 +161,12 @@ node = node.appendChild(document.createElement(name));

onattribute(name, value) {
node.setAttribute(name, value);
if (isHTML && _active && name === 'is' && _registry.has(value)) {
const {Class} = _registry.get(value);
const custom = new Class;
for (const attribute of node.attributes)
custom.setAttributeNode(attribute);
node.replaceWith(custom);
node = custom;
}
else
node.setAttribute(name, value);
},

@@ -145,0 +173,0 @@ oncomment(data) {

{
"name": "linkedom",
"version": "0.1.33",
"version": "0.1.34",
"description": "A triple-linked lists based DOM implementation",

@@ -5,0 +5,0 @@ "main": "./cjs/index.js",

@@ -120,7 +120,7 @@ # 🔗 linkedom

All nodes are linked on both side and all elements consist of 2 nodes, also linked in between.
All nodes are linked on both sides, and all elements consist of 2 nodes, also linked in between.
Attributes are always at the beginning of an element, while zero or more can be found before the end node.
Attributes are always at the beginning of an element, while zero or more extra nodes can be found before the end.
A fragment is a special element without boundaries or parent node.
A fragment is a special element without boundaries, or parent node.

@@ -158,3 +158,3 @@ ```

Moving *N* nodes from a container, either *Element* or *Fragment*, requires these steps:
Moving *N* nodes from a container, being it either an *Element* or a *Fragment*, requires the following steps:

@@ -166,6 +166,8 @@ * update the first *left* link of the moved segment

As result, no array operations, no memory operations, everything is kept in sync by updating a few properties, so that removing `3714` sparse `<div>` elements, in a *12M* document, takes as little as *3ms*, while appending a whole fragment takes close to *0ms*.
As result, there are no array operations, and no memory operations, and everything is kept in sync by updating a few properties, so that removing `3714` sparse `<div>` elements in a *12M* document, as example, takes as little as *3ms*, while appending a whole fragment takes close to *0ms*.
This structure also allows developers to avoid issues such as "*Maximum call stack size exceeded*" or "*JavaScript heap out of memory*" crashes, thanks to its reduced usage of memory, zero stacks involved, hence scaling better from small, to very big, documents.
Try `npm run benchmark:html` to see it yourself.
This structure also allows programs to avoid issues such as "*Maximum call stack size exceeded*" <sup><sub>(basicHTML)</sub></sup>, or "*JavaScript heap out of memory*" crashes <sup><sub>(JSDOM)</sub></sup>, thanks to its reduced usage of memory and zero stacks involved, hence scaling better from small to very big documents.
### Are *childNodes* and *children* always computed?

@@ -172,0 +174,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc