feat: Reinitialize frontend with SvelteKit and TypeScript

- Delete old Vite+Svelte frontend
- Initialize new SvelteKit project with TypeScript
- Configure Tailwind CSS v4 + DaisyUI
- Implement JWT authentication with auto-refresh
- Create login page with form validation (Zod)
- Add protected route guards
- Update Docker configuration for single-stage build
- Add E2E tests with Playwright (6/11 passing)
- Fix Svelte 5 reactivity with $state() runes

Known issues:
- 5 E2E tests failing (timing/async issues)
- Token refresh implementation needs debugging
- Validation error display timing
This commit is contained in:
2026-02-17 16:19:59 -05:00
parent 54df6018f5
commit de2d83092e
28274 changed files with 3816354 additions and 90 deletions

View File

@@ -0,0 +1,699 @@
import Node from '../node/Node.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import ShadowRoot from '../shadow-root/ShadowRoot.js';
import DOMRect from '../../dom/DOMRect.js';
import DOMTokenList from '../../dom/DOMTokenList.js';
import HTMLCollection from './HTMLCollection.js';
import DOMRectList from '../../dom/DOMRectList.js';
import Attr from '../attr/Attr.js';
import NamedNodeMap from './NamedNodeMap.js';
import Event from '../../event/Event.js';
import NodeTypeEnum from '../node/NodeTypeEnum.js';
import IHTMLElementTagNameMap from '../../config/IHTMLElementTagNameMap.js';
import ISVGElementTagNameMap from '../../config/ISVGElementTagNameMap.js';
import IChildNode from '../child-node/IChildNode.js';
import INonDocumentTypeChildNode from '../child-node/INonDocumentTypeChildNode.js';
import IParentNode from '../parent-node/IParentNode.js';
import NodeList from '../node/NodeList.js';
import CSSStyleDeclaration from '../../css/declaration/CSSStyleDeclaration.js';
import IScrollToOptions from '../../window/IScrollToOptions.js';
type InsertAdjacentPosition = 'beforebegin' | 'afterbegin' | 'beforeend' | 'afterend';
/**
* Element.
*/
export default class Element extends Node implements IChildNode, INonDocumentTypeChildNode, IParentNode {
#private;
static [PropertySymbol.tagName]: string | null;
static [PropertySymbol.localName]: string | null;
static [PropertySymbol.namespaceURI]: string | null;
cloneNode: (deep?: boolean) => Element;
[PropertySymbol.classList]: DOMTokenList | null;
[PropertySymbol.isValue]: string | null;
[PropertySymbol.nodeType]: NodeTypeEnum;
[PropertySymbol.prefix]: string | null;
[PropertySymbol.shadowRoot]: ShadowRoot | null;
[PropertySymbol.scrollHeight]: number;
[PropertySymbol.scrollWidth]: number;
[PropertySymbol.scrollTop]: number;
[PropertySymbol.scrollLeft]: number;
[PropertySymbol.attributes]: NamedNodeMap;
[PropertySymbol.attributesProxy]: NamedNodeMap | null;
[PropertySymbol.children]: HTMLCollection<Element> | null;
[PropertySymbol.computedStyle]: CSSStyleDeclaration | null;
[PropertySymbol.propertyEventListeners]: Map<string, (event: Event) => void>;
[PropertySymbol.tagName]: string | null;
[PropertySymbol.localName]: string | null;
[PropertySymbol.namespaceURI]: string | null;
/**
* Constructor.
*/
constructor();
get onfullscreenerror(): ((event: Event) => void) | null;
set onfullscreenerror(value: ((event: Event) => void) | null);
get onfullscreenchange(): ((event: Event) => void) | null;
set onfullscreenchange(value: ((event: Event) => void) | null);
get onbeforecopy(): ((event: Event) => void) | null;
set onbeforecopy(value: ((event: Event) => void) | null);
get onbeforecut(): ((event: Event) => void) | null;
set onbeforecut(value: ((event: Event) => void) | null);
get onbeforepaste(): ((event: Event) => void) | null;
set onbeforepaste(value: ((event: Event) => void) | null);
get onsearch(): ((event: Event) => void) | null;
set onsearch(value: ((event: Event) => void) | null);
/**
* Returns tag name.
*
* @returns Tag name.
*/
get tagName(): string;
/**
* Returns prefix.
*
* @returns Prefix.
*/
get prefix(): string | null;
/**
* Returns shadow root.
*
* @returns Shadow root.
*/
get shadowRoot(): ShadowRoot | null;
/**
* Returns scroll height.
*
* @returns Scroll height.
*/
get scrollHeight(): number;
/**
* Returns scroll width.
*
* @returns Scroll width.
*/
get scrollWidth(): number;
/**
* Returns scroll top.
*
* @returns Scroll top.
*/
get scrollTop(): number;
/**
* Sets scroll top.
*
* @param value Scroll top.
*/
set scrollTop(value: number);
/**
* Returns scroll left.
*
* @returns Scroll left.
*/
get scrollLeft(): number;
/**
* Sets scroll left.
*
* @param value Scroll left.
*/
set scrollLeft(value: number);
/**
* Returns attributes.
*
* @returns Attributes.
*/
get attributes(): NamedNodeMap;
/**
* Returns namespace URI.
*
* @returns Namespace URI.
*/
get namespaceURI(): string | null;
/**
* Returns element children.
*/
get children(): HTMLCollection<Element>;
/**
* Returns class list.
*
* @returns Class list.
*/
get classList(): DOMTokenList;
/**
* Sets class list.
*
* @param value Class list.
*/
set classList(value: string);
/**
* Returns ID.
*
* @returns ID.
*/
get id(): string;
/**
* Sets ID.
*
* @param id ID.
*/
set id(id: string);
/**
* Returns class name.
*
* @returns Class name.
*/
get className(): string;
/**
* Sets class name.
*
* @param className Class name.
*/
set className(className: string);
/**
* Node name.
*
* @returns Node name.
*/
get nodeName(): string;
/**
* Local name.
*
* @returns Local name.
*/
get localName(): string;
/**
* Returns role.
*
* @returns Role.
*/
get role(): string;
/**
* Sets role.
*
* @param role Role.
*/
set role(role: string);
/**
* Previous element sibling.
*
* @returns Element.
*/
get previousElementSibling(): Element;
/**
* Next element sibling.
*
* @returns Element.
*/
get nextElementSibling(): Element;
/**
* Get text value of children.
*
* @returns Text content.
*/
get textContent(): string;
/**
* Sets text content.
*
* @param textContent Text content.
*/
set textContent(textContent: string);
/**
* Returns inner HTML.
*
* @returns HTML.
*/
get innerHTML(): string;
/**
* Sets inner HTML.
*
* @param html HTML.
*/
set innerHTML(html: string);
/**
* Returns outer HTML.
*
* @returns HTML.
*/
get outerHTML(): string;
/**
* Returns outer HTML.
*
* @param html HTML.
*/
set outerHTML(html: string);
/**
* Last element child.
*
* @returns Element.
*/
get childElementCount(): number;
/**
* First element child.
*
* @returns Element.
*/
get firstElementChild(): Element;
/**
* Last element child.
*
* @returns Element.
*/
get lastElementChild(): Element;
/**
* Returns slot.
*
* @returns Slot.
*/
get slot(): string;
/**
* Returns slot.
*
* @param slot Slot.
*/
set slot(title: string);
/**
* Returns inner HTML and optionally the content of shadow roots.
*
* @deprecated
* @param [options] Options.
* @param [options.includeShadowRoots] Set to "true" to include shadow roots.
* @returns HTML.
*/
getInnerHTML(options?: {
includeShadowRoots?: boolean;
}): string;
/**
* Returns inner HTML and optionally the content of shadow roots.
*
* @param [options] Options.
* @param [options.serializableShadowRoots] A boolean value that specifies whether to include serializable shadow roots. The default value is false.
* @param [options.shadowRoots] An array of ShadowRoot objects to serialize. These are included regardless of whether they are marked as serializable, or if they are open or closed. The default value is an empty array.
* @returns HTML.
*/
getHTML(options?: {
serializableShadowRoots?: boolean;
shadowRoots?: ShadowRoot[];
}): string;
/**
* @override
*/
[PropertySymbol.cloneNode](deep?: boolean): Element;
/**
* Removes the node from its parent.
*/
remove(): void;
/**
* The Node.replaceWith() method replaces this Node in the children list of its parent with a set of Node or DOMString objects.
*
* @param nodes List of Node or DOMString.
*/
replaceWith(...nodes: (Node | string)[]): void;
/**
* Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just before this ChildNode. DOMString objects are inserted as equivalent Text nodes.
*
* @param nodes List of Node or DOMString.
*/
before(...nodes: (string | Node)[]): void;
/**
* Inserts a set of Node or DOMString objects in the children list of this ChildNode's parent, just after this ChildNode. DOMString objects are inserted as equivalent Text nodes.
*
* @param nodes List of Node or DOMString.
*/
after(...nodes: (string | Node)[]): void;
/**
* Inserts a set of Node objects or DOMString objects after the last child of the ParentNode. DOMString objects are inserted as equivalent Text nodes.
*
* @param nodes List of Node or DOMString.
*/
append(...nodes: (string | Node)[]): void;
/**
* Inserts a set of Node objects or DOMString objects before the first child of the ParentNode. DOMString objects are inserted as equivalent Text nodes.
*
* @param nodes List of Node or DOMString.
*/
prepend(...nodes: (string | Node)[]): void;
/**
* Replaces the existing children of a node with a specified new set of children.
*
* @param nodes List of Node or DOMString.
*/
replaceChildren(...nodes: (string | Node)[]): void;
/**
* Inserts a node to the given position.
*
* @param position Position to insert element.
* @param element Node to insert.
* @returns Inserted node or null if couldn't insert.
*/
insertAdjacentElement(position: InsertAdjacentPosition, element: Node): Node | null;
/**
* Inserts an HTML string to the given position.
*
* @param position Position to insert text.
* @param text HTML string to insert.
*/
insertAdjacentHTML(position: InsertAdjacentPosition, text: string): void;
/**
* Inserts text to the given position.
*
* @param position Position to insert text.
* @param text String to insert.
*/
insertAdjacentText(position: InsertAdjacentPosition, text: string): void;
/**
* Sets an attribute.
*
* @param name Name.
* @param value Value.
*/
setAttribute(name: string, value: string): void;
/**
* Sets a namespace attribute.
*
* @param namespaceURI Namespace URI.
* @param name Name.
* @param value Value.
*/
setAttributeNS(namespaceURI: string, name: string, value: string): void;
/**
* Returns attribute names.
*
* @returns Attribute names.
*/
getAttributeNames(): string[];
/**
* Returns attribute value.
*
* @param name Name.
*/
getAttribute(name: string): string | null;
/**
* Toggle an attribute.
* Returns `true` if attribute name is eventually present, and `false` otherwise.
*
* @param name A DOMString specifying the name of the attribute to be toggled.
* @param force A boolean value to determine whether the attribute should be added or removed, no matter whether the attribute is present or not at the moment.
*/
toggleAttribute(name: string, force?: boolean): boolean;
/**
* Returns namespace attribute value.
*
* @param namespace Namespace URI.
* @param localName Local name.
*/
getAttributeNS(namespace: string | null, localName: string): string;
/**
* Returns a boolean value indicating whether the specified element has the attribute or not.
*
* @param name Attribute name.
* @returns True if attribute exists, false otherwise.
*/
hasAttribute(name: string): boolean;
/**
* Returns a boolean value indicating whether the specified element has the namespace attribute or not.
*
* @param namespace Namespace URI.
* @param localName Local name.
* @returns True if attribute exists, false otherwise.
*/
hasAttributeNS(namespace: string | null, localName: string): boolean;
/**
* Returns "true" if the element has attributes.
*
* @returns "true" if the element has attributes.
*/
hasAttributes(): boolean;
/**
* Removes an attribute.
*
* @param name Name.
*/
removeAttribute(name: string): void;
/**
* Removes a namespace attribute.
*
* @param namespace Namespace URI.
* @param localName Local name.
*/
removeAttributeNS(namespace: string | null, localName: string): void;
/**
* Attaches a shadow root.
*
* @param init Shadow root init.
* @param init.mode Shadow root mode.
* @param [init.clonable] Clonable.
* @param [init.delegateFocus] Delegate focus.
* @param [init.serializable] Serializable.
* @param [init.slotAssignment] Slot assignment.
* @returns Shadow root.
*/
attachShadow(init: {
mode: 'open' | 'closed';
clonable?: boolean;
delegateFocus?: boolean;
serializable?: boolean;
slotAssignment?: 'named' | 'manual';
}): ShadowRoot;
/**
* Converts to string.
*
* @returns String.
*/
toString(): string;
/**
* Returns the size of an element and its position relative to the viewport.
*
* @returns DOM rect.
*/
getBoundingClientRect(): DOMRect;
/**
* Returns a collection of DOMRect objects that indicate the bounding rectangles for each CSS border box in a client.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects
* @returns DOM rect list.
*/
getClientRects(): DOMRectList;
/**
* The matches() method checks to see if the Element would be selected by the provided selectorString.
*
* @param selector Selector.
* @returns "true" if matching.
*/
matches(selector: string): boolean;
/**
* Traverses the Element and its parents (heading toward the document root) until it finds a node that matches the provided selector string.
*
* @param selector Selector.
* @returns Closest matching element.
*/
closest(selector: string): Element;
/**
* Connected callback.
*/
connectedCallback?(): void;
/**
* Disconnected callback.
*/
disconnectedCallback?(): void;
/**
* Attribute changed callback.
*
* @param name Name.
* @param oldValue Old value.
* @param newValue New value.
*/
attributeChangedCallback?(name: string, oldValue: string, newValue: string): void;
/**
* Query CSS selector to find matching nodes.
*
* @param selector CSS selector.
* @returns Matching elements.
*/
querySelectorAll<K extends keyof IHTMLElementTagNameMap>(selector: K): NodeList<IHTMLElementTagNameMap[K]>;
/**
* Query CSS selector to find matching elements.
*
* @param selector CSS selector.
* @returns Matching elements.
*/
querySelectorAll<K extends keyof ISVGElementTagNameMap>(selector: K): NodeList<ISVGElementTagNameMap[K]>;
/**
* Query CSS selector to find matching elements.
*
* @param selector CSS selector.
* @returns Matching elements.
*/
querySelectorAll(selector: string): NodeList<Element>;
/**
* Query CSS Selector to find matching node.
*
* @param selector CSS selector.
* @returns Matching element.
*/
querySelector<K extends keyof IHTMLElementTagNameMap>(selector: K): IHTMLElementTagNameMap[K] | null;
/**
* Query CSS Selector to find matching node.
*
* @param selector CSS selector.
* @returns Matching element.
*/
querySelector<K extends keyof ISVGElementTagNameMap>(selector: K): ISVGElementTagNameMap[K] | null;
/**
* Query CSS Selector to find matching node.
*
* @param selector CSS selector.
* @returns Matching element.
*/
querySelector(selector: string): Element | null;
/**
* Returns an elements by class name.
*
* @param className Tag name.
* @returns Matching element.
*/
getElementsByClassName(className: string): HTMLCollection<Element>;
/**
* Returns an elements by tag name.
*
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagName<K extends keyof IHTMLElementTagNameMap>(tagName: K): HTMLCollection<IHTMLElementTagNameMap[K]>;
/**
* Returns an elements by tag name.
*
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagName<K extends keyof ISVGElementTagNameMap>(tagName: K): HTMLCollection<ISVGElementTagNameMap[K]>;
/**
* Returns an elements by tag name.
*
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagName(tagName: string): HTMLCollection<Element>;
/**
* Returns an elements by tag name and namespace.
*
* @param namespaceURI Namespace URI.
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagNameNS<K extends keyof IHTMLElementTagNameMap>(namespaceURI: 'http://www.w3.org/1999/xhtml', tagName: K): HTMLCollection<IHTMLElementTagNameMap[K]>;
/**
* Returns an elements by tag name and namespace.
*
* @param namespaceURI Namespace URI.
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagNameNS<K extends keyof ISVGElementTagNameMap>(namespaceURI: 'http://www.w3.org/2000/svg', tagName: K): HTMLCollection<ISVGElementTagNameMap[K]>;
/**
* Returns an elements by tag name and namespace.
*
* @param namespaceURI Namespace URI.
* @param tagName Tag name.
* @returns Matching element.
*/
getElementsByTagNameNS(namespaceURI: string, tagName: string): HTMLCollection<Element>;
/**
* The setAttributeNode() method adds a new Attr node to the specified element.
*
* @param attribute Attribute.
* @returns Replaced attribute.
*/
setAttributeNode(attribute: Attr): Attr | null;
/**
* The setAttributeNodeNS() method adds a new Attr node to the specified element.
*
* @param attribute Attribute.
* @returns Replaced attribute.
*/
setAttributeNodeNS(attribute: Attr): Attr | null;
/**
* Returns an Attr node.
*
* @param name Name.
* @returns Replaced attribute.
*/
getAttributeNode(name: string): Attr | null;
/**
* Returns a namespaced Attr node.
*
* @param namespace Namespace.
* @param localName Name.
* @returns Replaced attribute.
*/
getAttributeNodeNS(namespace: string | null, localName: string): Attr | null;
/**
* Removes an Attr node.
*
* @param attribute Attribute.
* @returns Removed attribute.
*/
removeAttributeNode(attribute: Attr): Attr | null;
/**
* Scrolls to a particular set of coordinates.
*
* @param x X position or options object.
* @param y Y position.
*/
scroll(x: IScrollToOptions | number, y?: number): void;
/**
* Scrolls to a particular set of coordinates.
*
* @param x X position or options object.
* @param y Y position.
*/
scrollTo(x: IScrollToOptions | number, y?: number): void;
/**
* Scrolls by a relative amount from the current position.
*
* @param x Pixels to scroll by from top or scroll options object.
* @param y Pixels to scroll by from left.
*/
scrollBy(x: IScrollToOptions | number, y?: number): void;
/**
* Scrolls the element's ancestor containers such that the element on which scrollIntoView() is called is visible to the user.
*
* @param [_options] Options.
*/
scrollIntoView(_options?: boolean | {
behavior?: 'smooth' | 'instant' | 'auto';
block?: 'start' | 'center' | 'end' | 'nearest';
inline?: 'start' | 'center' | 'end' | 'nearest';
}): void;
/**
* @override
*/
[PropertySymbol.appendChild](node: Node, disableValidations?: boolean): Node;
/**
* @override
*/
[PropertySymbol.removeChild](node: Node): Node;
/**
* @override
*/
[PropertySymbol.insertBefore](newNode: Node, referenceNode: Node | null, disableValidations?: boolean): Node;
/**
* Triggered when an attribute is set.
*
* @param attribute Attribute.
* @param replacedAttribute Replaced attribute.
*/
[PropertySymbol.onSetAttribute](attribute: Attr, replacedAttribute: Attr | null): void;
/**
* Triggered when an attribute is set.
*
* @param removedAttribute Attribute.
*/
[PropertySymbol.onRemoveAttribute](removedAttribute: Attr): void;
/**
* @override
*/
[PropertySymbol.connectedToDocument](): void;
/**
* @override
*/
[PropertySymbol.disconnectedFromDocument](): void;
}
export {};
//# sourceMappingURL=Element.d.ts.map

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,16 @@
import Event from '../../event/Event.js';
import Element from './Element.js';
/**
* ECMAScript module compiler.
*/
export default class ElementEventAttributeUtility {
/**
* Evaluates code in attribute and returns event listener.
*
* @param element
* @param property Property.
* @returns Result.
*/
static getEventListener(element: Element, property: string): ((event: Event) => void) | null;
}
//# sourceMappingURL=ElementEventAttributeUtility.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ElementEventAttributeUtility.d.ts","sourceRoot":"","sources":["../../../src/nodes/element/ElementEventAttributeUtility.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,sBAAsB,CAAC;AACzC,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAChD;;;;;;OAMG;WACW,gBAAgB,CAC7B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,GACd,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,IAAI;CAoElC"}

View File

@@ -0,0 +1,65 @@
import BrowserErrorCaptureEnum from '../../browser/enums/BrowserErrorCaptureEnum.js';
import WindowBrowserContext from '../../window/WindowBrowserContext.js';
import * as PropertySymbol from '../../PropertySymbol.js';
/**
* ECMAScript module compiler.
*/
export default class ElementEventAttributeUtility {
/**
* Evaluates code in attribute and returns event listener.
*
* @param element
* @param property Property.
* @returns Result.
*/
static getEventListener(element, property) {
const cached = element[PropertySymbol.propertyEventListeners].get(property);
if (cached) {
return cached;
}
const window = element[PropertySymbol.ownerDocument][PropertySymbol.defaultView];
const browserSettings = new WindowBrowserContext(window).getSettings();
if (!browserSettings) {
return null;
}
const code = element.getAttribute(property);
if (!code) {
return null;
}
let newCode = `(function anonymous($happy_dom, event) {\n//# sourceURL=${window.location.href}\n`;
if (browserSettings &&
!browserSettings.disableErrorCapturing &&
browserSettings.errorCapture === BrowserErrorCaptureEnum.tryAndCatch) {
newCode += 'try {\n';
}
newCode += code;
if (browserSettings &&
!browserSettings.disableErrorCapturing &&
browserSettings.errorCapture === BrowserErrorCaptureEnum.tryAndCatch) {
newCode += '\n} catch(e) { $happy_dom.dispatchError(e); }\n';
}
newCode += '})';
let listener = null;
try {
listener = window.eval(newCode).bind(element, {
dispatchError: window[PropertySymbol.dispatchError]
});
}
catch (e) {
const error = new window.SyntaxError(`Failed to read the '${property}' property from '${element.constructor.name}': ${e.message}`);
if (browserSettings.disableErrorCapturing ||
browserSettings.errorCapture !== BrowserErrorCaptureEnum.tryAndCatch) {
throw error;
}
else {
window[PropertySymbol.dispatchError](error);
return null;
}
}
if (listener) {
element[PropertySymbol.propertyEventListeners].set(property, listener);
}
return listener;
}
}
//# sourceMappingURL=ElementEventAttributeUtility.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"ElementEventAttributeUtility.js","sourceRoot":"","sources":["../../../src/nodes/element/ElementEventAttributeUtility.ts"],"names":[],"mappings":"AAAA,OAAO,uBAAuB,MAAM,gDAAgD,CAAC;AACrF,OAAO,oBAAoB,MAAM,sCAAsC,CAAC;AACxE,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAI1D;;GAEG;AACH,MAAM,CAAC,OAAO,OAAO,4BAA4B;IAChD;;;;;;OAMG;IACI,MAAM,CAAC,gBAAgB,CAC7B,OAAgB,EAChB,QAAgB;QAEhB,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC5E,IAAI,MAAM,EAAE,CAAC;YACZ,OAAO,MAAM,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;QACjF,MAAM,eAAe,GAAG,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAEvE,IAAI,CAAC,eAAe,EAAE,CAAC;YACtB,OAAO,IAAI,CAAC;QACb,CAAC;QAED,MAAM,IAAI,GAAG,OAAO,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;QAE5C,IAAI,CAAC,IAAI,EAAE,CAAC;YACX,OAAO,IAAI,CAAC;QACb,CAAC;QAED,IAAI,OAAO,GAAG,2DAA2D,MAAM,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC;QAElG,IACC,eAAe;YACf,CAAC,eAAe,CAAC,qBAAqB;YACtC,eAAe,CAAC,YAAY,KAAK,uBAAuB,CAAC,WAAW,EACnE,CAAC;YACF,OAAO,IAAI,SAAS,CAAC;QACtB,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;QAEhB,IACC,eAAe;YACf,CAAC,eAAe,CAAC,qBAAqB;YACtC,eAAe,CAAC,YAAY,KAAK,uBAAuB,CAAC,WAAW,EACnE,CAAC;YACF,OAAO,IAAI,iDAAiD,CAAC;QAC9D,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;QAEhB,IAAI,QAAQ,GAAoC,IAAI,CAAC;QAErD,IAAI,CAAC;YACJ,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE;gBAC7C,aAAa,EAAE,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC;aACnD,CAAC,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,WAAW,CACnC,uBAAuB,QAAQ,oBAAoB,OAAO,CAAC,WAAW,CAAC,IAAI,MAAM,CAAC,CAAC,OAAO,EAAE,CAC5F,CAAC;YACF,IACC,eAAe,CAAC,qBAAqB;gBACrC,eAAe,CAAC,YAAY,KAAK,uBAAuB,CAAC,WAAW,EACnE,CAAC;gBACF,MAAM,KAAK,CAAC;YACb,CAAC;iBAAM,CAAC;gBACP,MAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,CAAC;gBAC5C,OAAO,IAAI,CAAC;YACb,CAAC;QACF,CAAC;QAED,IAAI,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACxE,CAAC;QAED,OAAO,QAAQ,CAAC;IACjB,CAAC;CACD"}

View File

@@ -0,0 +1,65 @@
import * as PropertySymbol from '../../PropertySymbol.js';
import Element from './Element.js';
/**
* HTMLCollection.
*
* We are extending Array here to improve performance.
* However, we should not expose Array methods to the outside.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
*/
export default class HTMLCollection<T extends Element, NamedItem = T> {
[index: number]: T;
protected [PropertySymbol.query]: () => T[];
/**
* Constructor.
*
* @param illegalConstructorSymbol Illegal constructor symbol.
* @param query Query function.
*/
constructor(illegalConstructorSymbol: symbol, query: () => T[]);
/**
* Returns length.
*
* @returns Length.
*/
get length(): number;
/**
* Returns `Symbol.toStringTag`.
*
* @returns `Symbol.toStringTag`.
*/
get [Symbol.toStringTag](): string;
/**
* Returns `[object HTMLCollection]`.
*
* @returns `[object HTMLCollection]`.
*/
toLocaleString(): string;
/**
* Returns `[object HTMLCollection]`.
*
* @returns `[object HTMLCollection]`.
*/
toString(): string;
/**
* Returns item by index.
*
* @param index Index.
*/
item(index: number): T;
/**
* Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object.
*
* @returns Iterator.
*/
[Symbol.iterator](): IterableIterator<T>;
/**
* Returns named item.
*
* @param name Name.
* @returns Node.
*/
namedItem(name: string): NamedItem | null;
}
//# sourceMappingURL=HTMLCollection.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"HTMLCollection.d.ts","sourceRoot":"","sources":["../../../src/nodes/element/HTMLCollection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAC1D,OAAO,OAAO,MAAM,cAAc,CAAC;AAEnC;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,OAAO,cAAc,CAAC,CAAC,SAAS,OAAO,EAAE,SAAS,GAAG,CAAC;IACnE,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;IACnB,SAAS,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC;IAE5C;;;;;OAKG;gBACS,wBAAwB,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE;IAqI9D;;;;OAIG;IACH,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;;;OAIG;IACH,IAAW,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAExC;IAED;;;;OAIG;IACI,cAAc,IAAI,MAAM;IAI/B;;;;OAIG;IACI,QAAQ,IAAI,MAAM;IAIzB;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC;IAK7B;;;;OAIG;IACI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAC,CAAC;IAK/C;;;;;OAKG;IACI,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;CAUhD"}

View File

@@ -0,0 +1,199 @@
import ClassMethodBinder from '../../utilities/ClassMethodBinder.js';
import * as PropertySymbol from '../../PropertySymbol.js';
/**
* HTMLCollection.
*
* We are extending Array here to improve performance.
* However, we should not expose Array methods to the outside.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
*/
export default class HTMLCollection {
[PropertySymbol.query];
/**
* Constructor.
*
* @param illegalConstructorSymbol Illegal constructor symbol.
* @param query Query function.
*/
constructor(illegalConstructorSymbol, query) {
if (illegalConstructorSymbol !== PropertySymbol.illegalConstructor) {
throw new TypeError('Illegal constructor');
}
this[PropertySymbol.query] = query;
const methodBinder = new ClassMethodBinder(this, this.constructor !== HTMLCollection ? [this.constructor, HTMLCollection] : [HTMLCollection]);
return new Proxy(this, {
get: (target, property) => {
if (property === 'length') {
return query().length;
}
if (property in target || typeof property === 'symbol') {
methodBinder.bind(property);
return target[property];
}
const index = Number(property);
if (!isNaN(index)) {
return query()[index];
}
return target.namedItem(property) || undefined;
},
set(target, property, newValue) {
methodBinder.bind(property);
if (typeof property === 'symbol') {
target[property] = newValue;
return true;
}
const index = Number(property);
if (isNaN(index)) {
target[property] = newValue;
}
return true;
},
deleteProperty(target, property) {
if (typeof property === 'symbol') {
delete target[property];
return true;
}
const index = Number(property);
if (isNaN(index)) {
delete target[property];
}
return true;
},
ownKeys() {
const keys = [];
const items = query();
for (let i = 0; i < items.length; i++) {
const item = items[i];
const name = item.getAttribute('id') || item.getAttribute('name');
keys.push(String(i));
if (name) {
keys.push(name);
}
}
return keys;
},
has(target, property) {
if (property in target) {
return true;
}
const items = query();
const index = Number(property);
if (!isNaN(index) && index >= 0 && index < items.length) {
return true;
}
property = String(property);
for (let i = 0; i < items.length; i++) {
const item = items[i];
const name = item.getAttribute('id') || item.getAttribute('name');
if (name && name === property) {
return true;
}
}
return false;
},
defineProperty(target, property, descriptor) {
methodBinder.preventBinding(property);
if (property in target) {
Object.defineProperty(target, property, descriptor);
return true;
}
return false;
},
getOwnPropertyDescriptor(target, property) {
if (property in target || typeof property === 'symbol') {
return;
}
const items = query();
const index = Number(property);
if (!isNaN(index) && index >= 0 && index < items.length) {
return {
value: items[index],
writable: false,
enumerable: true,
configurable: true
};
}
for (let i = 0; i < items.length; i++) {
const item = items[i];
const name = item.getAttribute('id') || item.getAttribute('name');
if (name && name === property) {
return {
value: item,
writable: false,
enumerable: true,
configurable: true
};
}
}
}
});
}
/**
* Returns length.
*
* @returns Length.
*/
get length() {
return this[PropertySymbol.query]().length;
}
/**
* Returns `Symbol.toStringTag`.
*
* @returns `Symbol.toStringTag`.
*/
get [Symbol.toStringTag]() {
return this.constructor.name;
}
/**
* Returns `[object HTMLCollection]`.
*
* @returns `[object HTMLCollection]`.
*/
toLocaleString() {
return `[object ${this.constructor.name}]`;
}
/**
* Returns `[object HTMLCollection]`.
*
* @returns `[object HTMLCollection]`.
*/
toString() {
return `[object ${this.constructor.name}]`;
}
/**
* Returns item by index.
*
* @param index Index.
*/
item(index) {
const items = this[PropertySymbol.query]();
return index >= 0 && items[index] ? items[index] : null;
}
/**
* Returns an iterator, allowing you to go through all values of the key/value pairs contained in this object.
*
* @returns Iterator.
*/
[Symbol.iterator]() {
const items = this[PropertySymbol.query]();
return items[Symbol.iterator]();
}
/**
* Returns named item.
*
* @param name Name.
* @returns Node.
*/
namedItem(name) {
const items = this[PropertySymbol.query]();
name = String(name);
for (const item of items) {
if (item.getAttribute('id') === name || item.getAttribute('name') === name) {
return item;
}
}
return null;
}
}
//# sourceMappingURL=HTMLCollection.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,113 @@
import * as PropertySymbol from '../../PropertySymbol.js';
import Attr from '../attr/Attr.js';
import Element from './Element.js';
/**
* Named Node Map.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap
*/
export default class NamedNodeMap {
[index: number]: Attr;
[PropertySymbol.itemsByNamespaceURI]: Map<string, Attr>;
[PropertySymbol.itemsByName]: Map<string, Attr[]>;
[PropertySymbol.items]: Map<string, Attr>;
[PropertySymbol.ownerElement]: Element;
/**
* Constructor.
*
* @param ownerElement Owner element.
*/
constructor(ownerElement: Element);
/**
* Returns length.
*
* @returns Length.
*/
get length(): number;
/**
* Returns string.
*
* @returns string.
*/
get [Symbol.toStringTag](): string;
/**
* Returns string.
*
* @returns string.
*/
toString(): string;
/**
* Iterator.
*
* @returns Iterator.
*/
[Symbol.iterator](): IterableIterator<Attr>;
/**
* Returns item by index.
*
* @param index Index.
*/
item(index: number): Attr | null;
/**
* Returns named item.
*
* @param name Name.
* @returns Item.
*/
getNamedItem(name: string): Attr | null;
/**
* Returns item by name and namespace.
*
* @param namespace Namespace.
* @param localName Local name of the attribute.
* @returns Item.
*/
getNamedItemNS(namespace: string, localName: string): Attr | null;
/**
* Sets named item.
*
* @param item Item.
* @returns Replaced item.
*/
setNamedItem(item: Attr): Attr | null;
/**
* Adds a new namespaced item.
*
* @alias setNamedItem()
* @param item Item.
* @returns Replaced item.
*/
setNamedItemNS(item: Attr): Attr | null;
/**
* Removes an item.
*
* @throws DOMException
* @param name Name of item.
* @returns Removed item.
*/
removeNamedItem(name: string): Attr;
/**
* Removes a namespaced item.
*
* @param namespace Namespace.
* @param localName Local name of the item.
* @returns Removed item.
*/
removeNamedItemNS(namespace: string, localName: string): Attr | null;
/**
* Sets named item.
*
* @param item Item.
* @param [ignoreListeners] Ignore listeners.
* @returns Replaced item.
*/
[PropertySymbol.setNamedItem](item: Attr, ignoreListeners?: boolean): Attr;
/**
* Removes named item.
*
* @param item Item.
* @param ignoreListeners
*/
[PropertySymbol.removeNamedItem](item: Attr, ignoreListeners?: boolean): void;
}
//# sourceMappingURL=NamedNodeMap.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NamedNodeMap.d.ts","sourceRoot":"","sources":["../../../src/nodes/element/NamedNodeMap.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,cAAc,MAAM,yBAAyB,CAAC;AAC1D,OAAO,IAAI,MAAM,iBAAiB,CAAC;AAGnC,OAAO,OAAO,MAAM,cAAc,CAAC;AAInC;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,YAAY;IAChC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAGf,CAAC,cAAc,CAAC,mBAAmB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAa;IAGpE,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAa;IAG9D,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAa;IAE9C,CAAC,cAAc,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC;IAEtD;;;;OAIG;gBACS,YAAY,EAAE,OAAO;IAIjC;;;;OAIG;IACH,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;;;OAIG;IACH,IAAW,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,MAAM,CAExC;IAED;;;;OAIG;IACI,QAAQ,IAAI,MAAM;IAIzB;;;;OAIG;IACI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,IAAI,CAAC;IAIlD;;;;OAIG;IACI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAKvC;;;;;OAKG;IACI,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAa9C;;;;;;OAMG;IACI,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAcxE;;;;;OAKG;IACI,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAI5C;;;;;;OAMG;IACI,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI;IAI9C;;;;;;OAMG;IACI,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAe1C;;;;;;OAMG;IACI,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAe3E;;;;;;OAMG;IACI,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,UAAQ,GAAG,IAAI;IAgD/E;;;;;OAKG;IACI,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,eAAe,UAAQ,GAAG,IAAI;CA0BlF"}

View File

@@ -0,0 +1,208 @@
import * as PropertySymbol from '../../PropertySymbol.js';
import DOMException from '../../exception/DOMException.js';
import DOMExceptionNameEnum from '../../exception/DOMExceptionNameEnum.js';
import NamespaceURI from '../../config/NamespaceURI.js';
import StringUtility from '../../utilities/StringUtility.js';
/**
* Named Node Map.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap
*/
export default class NamedNodeMap {
// Items by attribute namespaceURI
[PropertySymbol.itemsByNamespaceURI] = new Map();
// Items by attribute name
[PropertySymbol.itemsByName] = new Map();
// All items
[PropertySymbol.items] = new Map();
/**
* Constructor.
*
* @param ownerElement Owner element.
*/
constructor(ownerElement) {
this[PropertySymbol.ownerElement] = ownerElement;
}
/**
* Returns length.
*
* @returns Length.
*/
get length() {
return this[PropertySymbol.items].size;
}
/**
* Returns string.
*
* @returns string.
*/
get [Symbol.toStringTag]() {
return 'NamedNodeMap';
}
/**
* Returns string.
*
* @returns string.
*/
toString() {
return '[object NamedNodeMap]';
}
/**
* Iterator.
*
* @returns Iterator.
*/
[Symbol.iterator]() {
return this[PropertySymbol.items].values();
}
/**
* Returns item by index.
*
* @param index Index.
*/
item(index) {
const items = Array.from(this[PropertySymbol.items].values());
return index >= 0 && items[index] ? items[index] : null;
}
/**
* Returns named item.
*
* @param name Name.
* @returns Item.
*/
getNamedItem(name) {
name = String(name);
if (this[PropertySymbol.ownerElement][PropertySymbol.namespaceURI] === NamespaceURI.html &&
this[PropertySymbol.ownerElement][PropertySymbol.ownerDocument][PropertySymbol.contentType] === 'text/html') {
return this[PropertySymbol.itemsByName].get(StringUtility.asciiLowerCase(name))?.[0] || null;
}
return this[PropertySymbol.itemsByName].get(name)?.[0] || null;
}
/**
* Returns item by name and namespace.
*
* @param namespace Namespace.
* @param localName Local name of the attribute.
* @returns Item.
*/
getNamedItemNS(namespace, localName) {
const item = this[PropertySymbol.itemsByNamespaceURI].get(`${namespace || ''}:${localName}`);
// It seems like an item cant have a prefix without a namespaceURI
// E.g. element.setAttribute('ns1:key', 'value1');
// expect(element.attributes.getNamedItemNS(null, 'key')).toBeNull();
if (item && (!item[PropertySymbol.prefix] || item[PropertySymbol.namespaceURI])) {
return item;
}
return null;
}
/**
* Sets named item.
*
* @param item Item.
* @returns Replaced item.
*/
setNamedItem(item) {
return this[PropertySymbol.setNamedItem](item);
}
/**
* Adds a new namespaced item.
*
* @alias setNamedItem()
* @param item Item.
* @returns Replaced item.
*/
setNamedItemNS(item) {
return this[PropertySymbol.setNamedItem](item);
}
/**
* Removes an item.
*
* @throws DOMException
* @param name Name of item.
* @returns Removed item.
*/
removeNamedItem(name) {
const item = this.getNamedItem(name);
if (!item) {
throw new DOMException(`Failed to execute 'removeNamedItem' on 'NamedNodeMap': No item with name '${name}' was found.`, DOMExceptionNameEnum.notFoundError);
}
this[PropertySymbol.removeNamedItem](item);
return item;
}
/**
* Removes a namespaced item.
*
* @param namespace Namespace.
* @param localName Local name of the item.
* @returns Removed item.
*/
removeNamedItemNS(namespace, localName) {
const item = this.getNamedItemNS(namespace, localName);
if (!item) {
throw new DOMException(`Failed to execute 'removeNamedItemNS' on 'NamedNodeMap': No item with name '${localName}' in namespace '${namespace}' was found.`, DOMExceptionNameEnum.notFoundError);
}
this[PropertySymbol.removeNamedItem](item);
return item;
}
/**
* Sets named item.
*
* @param item Item.
* @param [ignoreListeners] Ignore listeners.
* @returns Replaced item.
*/
[PropertySymbol.setNamedItem](item, ignoreListeners = false) {
if (item[PropertySymbol.ownerElement] !== null &&
item[PropertySymbol.ownerElement] !== this[PropertySymbol.ownerElement]) {
throw new this[PropertySymbol.ownerElement][PropertySymbol.window].DOMException('The attribute is in use.', DOMExceptionNameEnum.inUseAttributeError);
}
item[PropertySymbol.ownerElement] = this[PropertySymbol.ownerElement];
const replacedItem = this.getNamedItemNS(item[PropertySymbol.namespaceURI], item[PropertySymbol.localName]) ||
null;
const itemsByName = this[PropertySymbol.itemsByName].get(item[PropertySymbol.name]);
if (replacedItem === item) {
return item;
}
this[PropertySymbol.itemsByNamespaceURI].set(`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.localName]}`, item);
this[PropertySymbol.items].set(`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.name]}`, item);
if (!itemsByName?.length) {
this[PropertySymbol.itemsByName].set(item[PropertySymbol.name], [item]);
}
else {
const index = itemsByName.indexOf(replacedItem);
if (index !== -1) {
itemsByName.splice(index, 1);
}
itemsByName.push(item);
}
if (!ignoreListeners) {
this[PropertySymbol.ownerElement][PropertySymbol.onSetAttribute](item, replacedItem);
}
return replacedItem;
}
/**
* Removes named item.
*
* @param item Item.
* @param ignoreListeners
*/
[PropertySymbol.removeNamedItem](item, ignoreListeners = false) {
item[PropertySymbol.ownerElement] = null;
this[PropertySymbol.itemsByNamespaceURI].delete(`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.localName]}`);
this[PropertySymbol.items].delete(`${item[PropertySymbol.namespaceURI] || ''}:${item[PropertySymbol.name]}`);
const itemsByName = this[PropertySymbol.itemsByName].get(item[PropertySymbol.name]);
if (itemsByName?.length) {
const index = itemsByName.indexOf(item);
if (index !== -1) {
itemsByName.splice(index, 1);
}
if (!itemsByName.length) {
this[PropertySymbol.itemsByName].delete(item[PropertySymbol.name]);
}
}
if (!ignoreListeners) {
this[PropertySymbol.ownerElement][PropertySymbol.onRemoveAttribute](item);
}
}
}
//# sourceMappingURL=NamedNodeMap.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,15 @@
import NamedNodeMap from './NamedNodeMap.js';
/**
* Named Node Map.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap
*/
export default class NamedNodeMapProxyFactory {
/**
* Constructor.
*
* @param namedNodeMap
*/
static createProxy(namedNodeMap: NamedNodeMap): NamedNodeMap;
}
//# sourceMappingURL=NamedNodeMapProxyFactory.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NamedNodeMapProxyFactory.d.ts","sourceRoot":"","sources":["../../../src/nodes/element/NamedNodeMapProxyFactory.ts"],"names":[],"mappings":"AAIA,OAAO,YAAY,MAAM,mBAAmB,CAAC;AAE7C;;;;GAIG;AACH,MAAM,CAAC,OAAO,OAAO,wBAAwB;IAC5C;;;;OAIG;WACW,WAAW,CAAC,YAAY,EAAE,YAAY,GAAG,YAAY;CA6GnE"}

View File

@@ -0,0 +1,116 @@
/* eslint-disable filenames/match-exported */
import ClassMethodBinder from '../../utilities/ClassMethodBinder.js';
import * as PropertySymbol from '../../PropertySymbol.js';
import NamedNodeMap from './NamedNodeMap.js';
/**
* Named Node Map.
*
* @see https://developer.mozilla.org/en-US/docs/Web/API/NamedNodeMap
*/
export default class NamedNodeMapProxyFactory {
/**
* Constructor.
*
* @param namedNodeMap
*/
static createProxy(namedNodeMap) {
const methodBinder = new ClassMethodBinder(this, [NamedNodeMap]);
return new Proxy(namedNodeMap, {
get: (target, property) => {
if (property === 'length') {
return namedNodeMap[PropertySymbol.items].size;
}
if (property in target || typeof property === 'symbol') {
methodBinder.bind(property);
return target[property];
}
const index = Number(property);
if (!isNaN(index)) {
return target.item(index);
}
return target.getNamedItem(property) || undefined;
},
set(target, property, newValue) {
methodBinder.bind(property);
if (typeof property === 'symbol') {
target[property] = newValue;
return true;
}
const index = Number(property);
if (isNaN(index)) {
target[property] = newValue;
}
return true;
},
deleteProperty(target, property) {
if (typeof property === 'symbol') {
delete target[property];
return true;
}
const index = Number(property);
if (isNaN(index)) {
delete target[property];
}
return true;
},
ownKeys() {
const keys = Array.from(namedNodeMap[PropertySymbol.items].keys());
for (let i = 0, max = namedNodeMap[PropertySymbol.items].size; i < max; i++) {
keys.push(String(i));
}
return keys;
},
has(target, property) {
if (typeof property === 'symbol') {
return false;
}
if (property in target || namedNodeMap[PropertySymbol.items].has(property)) {
return true;
}
const index = Number(property);
if (!isNaN(index) && index >= 0 && index < namedNodeMap[PropertySymbol.items].size) {
return true;
}
return false;
},
defineProperty(target, property, descriptor) {
methodBinder.preventBinding(property);
if (property in target) {
Object.defineProperty(target, property, descriptor);
return true;
}
return false;
},
getOwnPropertyDescriptor(target, property) {
if (property in target || typeof property === 'symbol') {
return;
}
const index = Number(property);
if (!isNaN(index)) {
if (index >= 0) {
const itemByIndex = target.item(index);
if (itemByIndex) {
return {
value: itemByIndex,
writable: false,
enumerable: true,
configurable: true
};
}
}
return;
}
const items = namedNodeMap[PropertySymbol.items].get(property);
if (items) {
return {
value: items,
writable: false,
enumerable: true,
configurable: true
};
}
}
});
}
}
//# sourceMappingURL=NamedNodeMapProxyFactory.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"NamedNodeMapProxyFactory.js","sourceRoot":"","sources":["../../../src/nodes/element/NamedNodeMapProxyFactory.ts"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,8 @@
type THTMLCollectionListener<T> = (details: {
index?: number;
item?: T;
propertyName?: string;
propertyValue?: any;
}) => void;
export default THTMLCollectionListener;
//# sourceMappingURL=THTMLCollectionListener.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"THTMLCollectionListener.d.ts","sourceRoot":"","sources":["../../../src/nodes/element/THTMLCollectionListener.ts"],"names":[],"mappings":"AAAA,KAAK,uBAAuB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,GAAG,CAAC;CACpB,KAAK,IAAI,CAAC;AACX,eAAe,uBAAuB,CAAC"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=THTMLCollectionListener.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"THTMLCollectionListener.js","sourceRoot":"","sources":["../../../src/nodes/element/THTMLCollectionListener.ts"],"names":[],"mappings":""}

View File

@@ -0,0 +1,4 @@
import Attr from '../attr/Attr.js';
type TNamedNodeMapListener = (attribute: Attr, replacedAttribute?: Attr | null) => void;
export default TNamedNodeMapListener;
//# sourceMappingURL=TNamedNodeMapListener.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"TNamedNodeMapListener.d.ts","sourceRoot":"","sources":["../../../src/nodes/element/TNamedNodeMapListener.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,iBAAiB,CAAC;AAEnC,KAAK,qBAAqB,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,iBAAiB,CAAC,EAAE,IAAI,GAAG,IAAI,KAAK,IAAI,CAAC;AACxF,eAAe,qBAAqB,CAAC"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=TNamedNodeMapListener.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"TNamedNodeMapListener.js","sourceRoot":"","sources":["../../../src/nodes/element/TNamedNodeMapListener.ts"],"names":[],"mappings":""}