From 336d50c8f2fabe1ccc5b57e45e281bc8ece0db6a Mon Sep 17 00:00:00 2001 From: Joel Drapper Date: Thu, 4 Apr 2024 02:40:28 +0100 Subject: [PATCH] Simplify interfaces --- dist/morphlex.d.ts | 6 ++-- dist/morphlex.js | 82 ++++++++++++++++++++---------------------- src/morphlex.ts | 88 ++++++++++++++++++++++------------------------ 3 files changed, 84 insertions(+), 92 deletions(-) diff --git a/dist/morphlex.d.ts b/dist/morphlex.d.ts index 7b1fa9c..4ac1b25 100644 --- a/dist/morphlex.d.ts +++ b/dist/morphlex.d.ts @@ -12,6 +12,8 @@ interface Options { beforePropertyUpdated?: (node: Node, propertyName: PropertyKey, newValue: unknown) => boolean; afterPropertyUpdated?: (node: Node, propertyName: PropertyKey, previousValue: unknown) => void; } -export declare function morph(node: ChildNode, reference: ChildNode | string, options?: Options): void; -export declare function morphInner(node: Element, reference: Element | string, options?: Options): void; +export declare function morph(node: ChildNode, reference: ChildNode, options?: Options): void; +export declare function morphInner(node: Element, reference: Element, options?: Options): void; +export declare function morphFromString(node: ChildNode, reference: string, options?: Options): void; +export declare function morphInnerFromString(node: Element, reference: string, options?: Options): void; export {}; diff --git a/dist/morphlex.js b/dist/morphlex.js index a27aa7f..0b3d98f 100644 --- a/dist/morphlex.js +++ b/dist/morphlex.js @@ -1,43 +1,26 @@ export function morph(node, reference, options = {}) { - if (typeof reference === "string") { - const parsedReferenceNode = parseNodeFromString(reference); - if (parsedReferenceNode) { - reference = parsedReferenceNode; - } else { - throw new Error("[Morphlex] The string did not contain any nodes."); - } - } - if (isElement(node)) { - const originalAriaBusy = node.ariaBusy; - node.ariaBusy = "true"; - new Morph(options).morph([node, reference]); - node.ariaBusy = originalAriaBusy; - } else { - new Morph(options).morph([node, reference]); - } + new Morph(options).morph([node, reference]); } export function morphInner(node, reference, options = {}) { - if (typeof reference === "string") { - const parsedReferenceNode = parseNodeFromString(reference); - if (parsedReferenceNode && isElement(parsedReferenceNode)) { - reference = parsedReferenceNode; - } else { - throw new Error("[Morphlex] The string did not contain any nodes."); - } - } - if (isElement(node)) { - const originalAriaBusy = node.ariaBusy; - node.ariaBusy = "true"; - new Morph(options).morphInner([node, reference]); - node.ariaBusy = originalAriaBusy; - } else { - new Morph(options).morphInner([node, reference]); - } + new Morph(options).morphInner([node, reference]); +} +export function morphFromString(node, reference, options = {}) { + morph(node, parseChildNodeFromString(reference), options); } -function parseNodeFromString(string) { +export function morphInnerFromString(node, reference, options = {}) { + morphInner(node, parseElementFromString(reference), options); +} +function parseElementFromString(string) { + const node = parseChildNodeFromString(string); + if (isElement(node)) return node; + else throw new Error("[Morphlex] The string was not a valid HTML element."); +} +function parseChildNodeFromString(string) { const parser = new DOMParser(); const doc = parser.parseFromString(string, "text/html"); - return doc.body.firstChild; + const firstChild = doc.body.firstChild; + if (doc.childNodes.length === 1) return firstChild; + else throw new Error("[Morphlex] The string was not a valid HTML node."); } class Morph { #idMap; @@ -72,16 +55,28 @@ class Morph { Object.freeze(this); } morph(pair) { - if (isParentNodePair(pair)) this.#buildMaps(pair); - this.#morphNode(pair); + this.#withAriaBusy(pair[0], () => { + if (isParentNodePair(pair)) this.#buildMaps(pair); + this.#morphNode(pair); + }); } morphInner(pair) { - if (isMatchingElementPair(pair)) { - this.#buildMaps(pair); - this.#morphMatchingElementContent(pair); - } else { - throw new Error("[Morphlex] You can only do an inner morph with matching elements."); - } + this.#withAriaBusy(pair[0], () => { + if (isMatchingElementPair(pair)) { + this.#buildMaps(pair); + this.#morphMatchingElementContent(pair); + } else { + throw new Error("[Morphlex] You can only do an inner morph with matching elements."); + } + }); + } + #withAriaBusy(node, block) { + if (isElement(node)) { + const originalAriaBusy = node.ariaBusy; + node.ariaBusy = "true"; + block(); + node.ariaBusy = originalAriaBusy; + } else block(); } #buildMaps([node, reference]) { this.#mapIdSets(node); @@ -349,8 +344,7 @@ function isMatchingElementPair(pair) { return isElement(a) && isElement(b) && a.localName === b.localName; } function isParentNodePair(pair) { - const [a, b] = pair; - return isParentNode(a) && isParentNode(b); + return isParentNode(pair[0]) && isParentNode(pair[1]); } function isElement(node) { return node.nodeType === 1; diff --git a/src/morphlex.ts b/src/morphlex.ts index c112f51..636a0c7 100644 --- a/src/morphlex.ts +++ b/src/morphlex.ts @@ -49,52 +49,36 @@ interface Options { afterPropertyUpdated?: (node: Node, propertyName: PropertyKey, previousValue: unknown) => void; } -export function morph(node: ChildNode, reference: ChildNode | string, options: Options = {}): void { - if (typeof reference === "string") { - const parsedReferenceNode = parseNodeFromString(reference); +export function morph(node: ChildNode, reference: ChildNode, options: Options = {}): void { + new Morph(options).morph([node, reference]); +} - if (parsedReferenceNode) { - reference = parsedReferenceNode; - } else { - throw new Error("[Morphlex] The string did not contain any nodes."); - } - } +export function morphInner(node: Element, reference: Element, options: Options = {}): void { + new Morph(options).morphInner([node, reference]); +} - if (isElement(node)) { - const originalAriaBusy = node.ariaBusy; - node.ariaBusy = "true"; - new Morph(options).morph([node, reference]); - node.ariaBusy = originalAriaBusy; - } else { - new Morph(options).morph([node, reference]); - } +export function morphFromString(node: ChildNode, reference: string, options: Options = {}): void { + morph(node, parseChildNodeFromString(reference), options); } -export function morphInner(node: Element, reference: Element | string, options: Options = {}): void { - if (typeof reference === "string") { - const parsedReferenceNode = parseNodeFromString(reference); +export function morphInnerFromString(node: Element, reference: string, options: Options = {}): void { + morphInner(node, parseElementFromString(reference), options); +} - if (parsedReferenceNode && isElement(parsedReferenceNode)) { - reference = parsedReferenceNode; - } else { - throw new Error("[Morphlex] The string did not contain any nodes."); - } - } +function parseElementFromString(string: string): Element { + const node = parseChildNodeFromString(string); - if (isElement(node)) { - const originalAriaBusy = node.ariaBusy; - node.ariaBusy = "true"; - new Morph(options).morphInner([node, reference]); - node.ariaBusy = originalAriaBusy; - } else { - new Morph(options).morphInner([node, reference]); - } + if (isElement(node)) return node; + else throw new Error("[Morphlex] The string was not a valid HTML element."); } -function parseNodeFromString(string: string): ChildNode | null { +function parseChildNodeFromString(string: string): ChildNode { const parser = new DOMParser(); const doc = parser.parseFromString(string, "text/html"); - return doc.body.firstChild; + const firstChild = doc.body.firstChild; + + if (doc.childNodes.length === 1) return firstChild as ChildNode; + else throw new Error("[Morphlex] The string was not a valid HTML node."); } class Morph { @@ -135,17 +119,30 @@ class Morph { } morph(pair: NodeReferencePair): void { - if (isParentNodePair(pair)) this.#buildMaps(pair); - this.#morphNode(pair); + this.#withAriaBusy(pair[0], () => { + if (isParentNodePair(pair)) this.#buildMaps(pair); + this.#morphNode(pair); + }); } morphInner(pair: NodeReferencePair): void { - if (isMatchingElementPair(pair)) { - this.#buildMaps(pair); - this.#morphMatchingElementContent(pair); - } else { - throw new Error("[Morphlex] You can only do an inner morph with matching elements."); - } + this.#withAriaBusy(pair[0], () => { + if (isMatchingElementPair(pair)) { + this.#buildMaps(pair); + this.#morphMatchingElementContent(pair); + } else { + throw new Error("[Morphlex] You can only do an inner morph with matching elements."); + } + }); + } + + #withAriaBusy(node: Node, block: () => void): void { + if (isElement(node)) { + const originalAriaBusy = node.ariaBusy; + node.ariaBusy = "true"; + block(); + node.ariaBusy = originalAriaBusy; + } else block(); } #buildMaps([node, reference]: NodeReferencePair): void { @@ -479,8 +476,7 @@ function isMatchingElementPair(pair: NodeReferencePair): pair is MatchingE } function isParentNodePair(pair: NodeReferencePair): pair is NodeReferencePair { - const [a, b] = pair; - return isParentNode(a) && isParentNode(b); + return isParentNode(pair[0]) && isParentNode(pair[1]); } function isElement(node: Node): node is Element;