Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@tko/utils.jsx

Package Overview
Dependencies
Maintainers
1
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tko/utils.jsx - npm Package Compare versions

Comparing version
4.0.1
to
4.1.0
+5
README.md
# @tko/utils.jsx
JSX/TSX rendering for TKO (createElement, JsxObserver)
Part of [TKO](https://tko.io) — modern Knockout.js. [Docs](https://tko.io) · [Source](https://github.com/knockout/tko/tree/main/packages/utils.jsx)
+28
-8

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

// @tko/utils.jsx 🥊 4.0.1 CommonJS
// @tko/utils.jsx 🥊 4.1.0 CommonJS
"use strict";

@@ -48,22 +48,42 @@ var __defProp = Object.defineProperty;

var DELAY_MS = 25;
var MAX_CLEAN_AT_ONCE = 1e3;
var cleanNodeQueue = new Array();
var cleanNodeTimeoutID = null;
(0, import_utils.defineOption)("jsxCleanBatchSize", { default: 1e3 });
function queueCleanNode(node) {
cleanNodeQueue.push(node);
triggerCleanTimeout();
if (import_utils.options.jsxCleanBatchSize === 0) {
flushAll();
} else {
scheduleBatch();
}
}
function triggerCleanTimeout() {
function scheduleBatch() {
if (!cleanNodeTimeoutID && cleanNodeQueue.length) {
cleanNodeTimeoutID = setTimeout(flushCleanQueue, DELAY_MS);
cleanNodeTimeoutID = setTimeout(flushBatch, DELAY_MS);
}
}
function flushCleanQueue() {
function flushBatch() {
cleanNodeTimeoutID = null;
const nodes = cleanNodeQueue.splice(0, MAX_CLEAN_AT_ONCE);
const batchSize = Math.trunc(import_utils.options.jsxCleanBatchSize);
if (!Number.isFinite(batchSize) || batchSize <= 0) {
flushAll();
return;
}
const nodes = cleanNodeQueue.splice(0, batchSize);
for (const node of nodes) {
(0, import_utils.cleanNode)(node);
}
triggerCleanTimeout();
scheduleBatch();
}
function flushAll() {
if (cleanNodeTimeoutID !== null) {
clearTimeout(cleanNodeTimeoutID);
cleanNodeTimeoutID = null;
}
while (cleanNodeQueue.length) {
for (const node of cleanNodeQueue.splice(0)) {
(0, import_utils.cleanNode)(node);
}
}
}

@@ -70,0 +90,0 @@ // src/JsxObserver.ts

{
"version": 3,
"sources": ["../index.ts", "../src/jsx.ts", "../src/JsxObserver.ts", "../src/jsxClean.ts"],
"sourcesContent": ["export * from './src'\n", "import { isObservable, unwrap } from '@tko/observable'\n\nimport { ORIGINAL_JSX_SYM } from './JsxObserver'\n\n/**\n *\n * @param {any} possibleJsx Test whether this value is JSX.\n *\n * True for\n * { elementName }\n * [{elementName}]\n * observable({elementName} | [])\n *\n * Any observable will return truthy if its value is an array that doesn't\n * contain HTML elements. Template nodes should not be observable unless they\n * are JSX.\n *\n * There's a bit of guesswork here that we could nail down with more test cases.\n */\nexport function maybeJsx(possibleJsx) {\n if (isObservable(possibleJsx)) {\n return true\n }\n const value = unwrap(possibleJsx)\n if (!value) {\n return false\n }\n if (value.elementName) {\n return true\n }\n if (!Array.isArray(value) || !value.length) {\n return false\n }\n if (value[0] instanceof window.Node) {\n return false\n }\n return true\n}\n\nexport function getOriginalJsxForNode(node) {\n return node[ORIGINAL_JSX_SYM]\n}\n\n/**\n * Convert JSX into an object that can be consumed by TKO.\n * Mimics React.createElement\n * @param {string} e tagName of the element\n * @param {object|null} a attributes of the element\n * @param {...string|object} c children of the element\n */\nexport function createElement(elementName, attributes, ...children) {\n return elementName === Fragment\n ? children\n : { elementName: elementName, attributes: attributes || {}, children: [...children] }\n}\n\nexport const Fragment = Symbol('JSX Fragment')\n", "import { LifeCycle } from '@tko/lifecycle'\n\nimport { safeStringify, isThenable } from '@tko/utils'\n\nimport { applyBindings, contextFor } from '@tko/bind'\n\nimport { isObservable, unwrap, observable } from '@tko/observable'\n\nimport type { Observable } from '@tko/observable'\n\nimport { isComputed } from '@tko/computed'\n\nimport { NativeProvider, NATIVE_BINDINGS } from '@tko/provider.native'\n\nimport { queueCleanNode } from './jsxClean'\n\nexport const ORIGINAL_JSX_SYM = Symbol('Knockout - Original JSX')\n\nconst NAMESPACES = {\n svg: 'http://www.w3.org/2000/svg',\n html: 'http://www.w3.org/1999/xhtml',\n xml: 'http://www.w3.org/XML/1998/namespace',\n xlink: 'http://www.w3.org/1999/xlink',\n xmlns: 'http://www.w3.org/2000/xmlns/'\n}\n\nfunction isIterable(v) {\n return v && typeof v[Symbol.iterator] === 'function'\n}\n\n/**\n * JSX object from a pre-processor.\n * @typedef {Object} JSX\n * @property {string} elementName becomes the `tagName`\n * @property {Array.<JSX>} children\n * @property {object} attributes\n */\n\ninterface JSX {\n elementName: string\n children: Array<JSX>\n attributes: any\n}\n\ninterface Changes {\n index: number\n status: string\n value: any\n}\n\n/**\n * Observe a variety of possible cases from JSX, modifying the\n * `parentNode` at `insertBefore` with the result.\n */\nexport class JsxObserver extends LifeCycle {\n adoptedInsertBefore: boolean\n noInitialBinding: boolean\n insertBefore: Node | null\n parentNode: Node\n parentNodeTarget: Node | null\n subscriptionsForNode: any\n nodeArrayOrObservableAtIndex: any\n xmlns: any\n\n /**\n * @param {any} jsxOrObservable take a long list of permutations\n */\n constructor(\n jsxOrObservable: any,\n parentNode: Node,\n insertBefore: Node | null = null,\n xmlns?: any,\n noInitialBinding?: boolean | null\n ) {\n super()\n\n const parentNodeIsComment = parentNode.nodeType === Node.COMMENT_NODE\n\n const parentNodeTarget = this.getParentTarget(parentNode)\n\n if (isObservable(jsxOrObservable)) {\n jsxOrObservable.extend({ trackArrayChanges: true })\n this.subscribe(jsxOrObservable, this.observableArrayChange, 'arrayChange')\n\n if (!insertBefore) {\n const insertAt = parentNodeIsComment ? parentNode.nextSibling : null\n insertBefore = this.createComment('O')\n parentNodeTarget?.insertBefore(insertBefore, insertAt)\n } else {\n this.adoptedInsertBefore = true\n }\n }\n\n if (parentNodeIsComment && !insertBefore) {\n // Typcially: insertBefore becomes <!-- /ko -->\n insertBefore = parentNode.nextSibling\n // Mark this so we don't remove the next node - since we didn't create it.\n this.adoptedInsertBefore = true\n }\n\n this.anchorTo(insertBefore || parentNode)\n\n Object.assign(this, {\n insertBefore,\n noInitialBinding,\n parentNode,\n parentNodeTarget,\n xmlns,\n nodeArrayOrObservableAtIndex: [],\n subscriptionsForNode: new Map()\n })\n\n const jsx = unwrap(jsxOrObservable)\n const computed = isComputed(jsxOrObservable)\n\n if (computed || (jsx !== null && jsx !== undefined)) {\n this.observableArrayChange(this.createInitialAdditions(jsx))\n }\n this.noInitialBinding = false\n }\n\n getParentTarget(parentNode: Node): Node | null {\n if ('content' in parentNode) {\n return (parentNode as HTMLTemplateElement).content\n }\n if (parentNode.nodeType === Node.COMMENT_NODE) {\n return (parentNode as Comment).parentNode\n }\n return parentNode\n }\n\n remove() {\n this.dispose()\n }\n override dispose() {\n super.dispose()\n const ib = this.insertBefore\n const insertBeforeIsChild = ib && this.parentNodeTarget === ib.parentNode\n if (insertBeforeIsChild && !this.adoptedInsertBefore) {\n this.parentNodeTarget?.removeChild(ib)\n }\n this.removeAllPriorNodes()\n Object.assign(this, {\n parentNode: null,\n parentNodeTarget: null,\n insertBefore: null,\n nodeArrayOrObservableAtIndex: []\n })\n for (const subscriptions of this.subscriptionsForNode.values()) {\n subscriptions.forEach(s => s.dispose())\n }\n this.subscriptionsForNode.clear()\n }\n\n createInitialAdditions(possibleIterable): Changes[] {\n const status = 'added'\n if (typeof possibleIterable === 'object' && possibleIterable !== null && Symbol.iterator in possibleIterable) {\n possibleIterable = [...possibleIterable]\n }\n\n return Array.isArray(possibleIterable)\n ? possibleIterable.map((value, index) => ({ index, status, value }))\n : [{ status, index: 0, value: possibleIterable }]\n }\n\n /**\n * Note: array change notification indexes are:\n * - to the original array indexes for deletes\n * - to the new array indexes for adds\n * - sorted by index in ascending order\n */\n observableArrayChange(changes: Changes[]) {\n const adds: [number, any][] = []\n const dels: [number, any][] = []\n\n for (const index in changes) {\n const change = changes[index]\n if (change.status === 'added') {\n adds.push([change.index, change.value])\n } else {\n dels.unshift([change.index, change.value])\n }\n }\n\n dels.forEach(change => this.delChange(...change))\n adds.forEach(change => this.addChange(...change))\n }\n\n /**\n * Add a change at the given index.\n *\n * @param {int} index\n * @param {string|object|Array|Observable.string|Observable.Array|Observable.object} jsx\n */\n addChange(\n index: number,\n jsx: string | object | Array<any> | Observable<string> | Observable<any[]> | Observable<object>\n ) {\n this.nodeArrayOrObservableAtIndex.splice(index, 0, this.injectNode(jsx, this.lastNodeFor(index)!))\n }\n\n injectNode(jsx, nextNode: Node) {\n let nodeArrayOrObservable\n\n if (isObservable(jsx)) {\n const { parentNode, xmlns } = this\n const observer = new JsxObserver(jsx, parentNode, nextNode, xmlns, this.noInitialBinding)\n nodeArrayOrObservable = [observer]\n } else if (typeof jsx !== 'string' && isIterable(jsx)) {\n nodeArrayOrObservable = new Array()\n for (const child of jsx) {\n nodeArrayOrObservable.unshift(this.injectNode(child, nextNode))\n }\n } else {\n const $context = contextFor(this.parentNode as HTMLElement)\n const isInsideTemplate = 'content' in this.parentNode\n const shouldApplyBindings = $context && !isInsideTemplate && !this.noInitialBinding\n\n if (Array.isArray(jsx)) {\n nodeArrayOrObservable = jsx.map(j => this.anyToNode(j))\n } else {\n nodeArrayOrObservable = [this.anyToNode(jsx)]\n }\n\n for (const node of nodeArrayOrObservable) {\n this.parentNodeTarget?.insertBefore(node, nextNode)\n if (shouldApplyBindings && this.canApplyBindings(node)) {\n applyBindings($context, node)\n }\n }\n }\n\n return nodeArrayOrObservable\n }\n\n /**\n * True when Node is a type suitable for applyBindings i.e. a HTMLElement\n * or a Comment.\n * @param {Node} node\n */\n canApplyBindings(node: Node): boolean {\n return node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.COMMENT_NODE\n }\n\n delChange(index: number, _: any) {\n this.removeNodeArrayOrObservable(this.nodeArrayOrObservableAtIndex[index])\n this.nodeArrayOrObservableAtIndex.splice(index, 1)\n }\n\n getSubscriptionsForNode(node: Node) {\n if (!this.subscriptionsForNode.has(node)) {\n const subscriptions = new Array()\n this.subscriptionsForNode.set(node, subscriptions)\n return subscriptions\n }\n return this.subscriptionsForNode.get(node)\n }\n\n isJsx(jsx): jsx is JSX {\n return typeof jsx.elementName === 'string' && 'children' in jsx && 'attributes' in jsx\n }\n\n /**\n * @param {any} value acceptable to turn into a Node\n *\n * The one thing `any` cannot be here is an Array or Observable; both those\n * cases are handled with new JsxObservers.\n */\n anyToNode(any) {\n if (isThenable(any)) {\n return this.futureJsxNode(any)\n }\n\n switch (typeof any) {\n case 'object':\n if (any instanceof Error) {\n return this.createComment(any.toString())\n }\n if (any === null) {\n return this.createComment(String(any))\n }\n if (any instanceof Node) {\n return this.cloneJSXorMoveNode(any)\n }\n if (Symbol.iterator in any) {\n return any\n }\n break\n case 'function':\n return this.anyToNode(any())\n case 'undefined':\n case 'symbol':\n return this.createComment(String(any))\n case 'string':\n return this.createTextNode(any)\n case 'boolean':\n case 'number':\n case 'bigint':\n default:\n return this.createTextNode(String(any))\n }\n\n return this.isJsx(any) ? this.jsxToNode(any) : this.createComment(safeStringify(any))\n }\n\n createComment(string) {\n const node = document.createComment(string)\n node[NATIVE_BINDINGS] = true\n return node\n }\n\n createTextNode(string) {\n const node = document.createTextNode(string)\n node[NATIVE_BINDINGS] = true\n return node\n }\n\n /**\n * Clone a node; if that node was originally from JSX, we clone from there\n * so we preserve binding handlers.\n *\n * @param {HTMLElement} node\n */\n cloneJSXorMoveNode(node: Node) {\n return ORIGINAL_JSX_SYM in node ? this.jsxToNode(node[ORIGINAL_JSX_SYM] as JSX) : node\n }\n\n /**\n * @param {JSX} jsx to convert to a node.\n */\n jsxToNode(jsx: JSX) {\n const xmlns = jsx.attributes.xmlns || NAMESPACES[jsx.elementName] || this.xmlns\n const node = document.createElementNS(xmlns || NAMESPACES.html, jsx.elementName)\n\n /** Slots need to be able to replicate with the attributes, which\n * are not preserved when cloning from template nodes. */\n node[ORIGINAL_JSX_SYM] = jsx\n\n if (isObservable(jsx.attributes)) {\n const subscriptions = this.getSubscriptionsForNode(node)\n subscriptions.push(\n jsx.attributes.subscribe(attrs => {\n this.updateAttributes(node, unwrap(attrs))\n })\n )\n }\n this.updateAttributes(node, unwrap(jsx.attributes))\n\n this.addDisposable(new JsxObserver(jsx.children, node, null, xmlns, this.noInitialBinding))\n\n return node\n }\n\n futureJsxNode(promise) {\n const obs = observable()\n promise.then(obs).catch(e => obs(e instanceof Error ? e : Error(e)))\n const jo = new JsxObserver(obs, this.parentNode, null, this.xmlns, this.noInitialBinding)\n this.addDisposable(jo)\n return jo.insertBefore\n }\n\n updateAttributes(node, attributes) {\n const subscriptions = this.getSubscriptionsForNode(node)\n const toRemove = new Set([...node.attributes].map(n => n.name))\n\n for (const [name, value] of Object.entries(attributes || {})) {\n toRemove.delete(name)\n if (isObservable(value)) {\n subscriptions.push(value.subscribe(attr => this.setNodeAttribute(node, name, value)))\n }\n this.setNodeAttribute(node, name, value)\n }\n\n for (const name of toRemove) {\n this.setNodeAttribute(node, name, undefined)\n }\n }\n\n /**\n * See https://stackoverflow.com/a/52572048\n * @param {string} attr element attribute\n * @return {string} namespace argument for setAtttributeNS\n */\n getNamespaceOfAttribute(attr: string): string | null {\n const [prefix, ...unqualifiedName] = attr.split(':')\n if (prefix === 'xmlns' || (unqualifiedName.length && NAMESPACES[prefix])) {\n return NAMESPACES[prefix]\n }\n return null\n }\n\n /**\n *\n * @param {HTMLElement} node\n * @param {string} name\n * @param {any} valueOrObservable\n */\n setNodeAttribute(node: HTMLElement, name: string, valueOrObservable: any) {\n const value = unwrap(valueOrObservable)\n NativeProvider.addValueToNode(node, name, valueOrObservable)\n if (value === undefined) {\n node.removeAttributeNS(null, name)\n } else if (isThenable(valueOrObservable)) {\n Promise.resolve(valueOrObservable).then(v => this.setNodeAttribute(node, name, v))\n } else {\n const ns = this.getNamespaceOfAttribute(name)\n node.setAttributeNS(ns, name, String(value))\n }\n }\n\n /**\n * @param {int} index\n * @return {Comment} that immediately precedes this.\n */\n lastNodeFor(index: number): Comment | null {\n const nodesAtIndex = this.nodeArrayOrObservableAtIndex[index] || []\n const [lastNodeOfPrior] = nodesAtIndex.slice(-1)\n const insertBefore =\n lastNodeOfPrior instanceof JsxObserver ? lastNodeOfPrior.insertBefore : lastNodeOfPrior || this.insertBefore\n if (insertBefore) {\n return insertBefore.parentNode ? insertBefore : null\n }\n return null\n }\n\n removeAllPriorNodes() {\n const { nodeArrayOrObservableAtIndex } = this\n while (nodeArrayOrObservableAtIndex.length) {\n this.removeNodeArrayOrObservable(nodeArrayOrObservableAtIndex.pop())\n }\n }\n\n removeNodeArrayOrObservable(nodeArrayOrObservable) {\n for (const nodeOrObservable of nodeArrayOrObservable) {\n if (nodeOrObservable instanceof JsxObserver) {\n nodeOrObservable.dispose()\n continue\n }\n const node = nodeOrObservable\n delete node[ORIGINAL_JSX_SYM]\n this.detachAndDispose(node)\n const subscriptions = this.subscriptionsForNode.get(node)\n if (subscriptions) {\n subscriptions.forEach(s => s.dispose())\n this.subscriptionsForNode.delete(node)\n }\n }\n }\n\n /**\n * Detach the given node, and dispose of its children.\n *\n * The cleaning can trigger a lot of garbage collection, so we defer that.\n */\n detachAndDispose(node) {\n if (isIterable(node)) {\n for (const child of node) {\n this.detachAndDispose(child)\n }\n } else {\n node.remove()\n }\n queueCleanNode(node)\n }\n}\n\nexport default JsxObserver\n", "import { cleanNode } from '@tko/utils'\n\nconst DELAY_MS = 25\nconst MAX_CLEAN_AT_ONCE = 1000\nconst cleanNodeQueue = new Array()\nlet cleanNodeTimeoutID: ReturnType<typeof setTimeout> | null = null\n\nexport function queueCleanNode(node) {\n cleanNodeQueue.push(node)\n triggerCleanTimeout()\n}\n\nfunction triggerCleanTimeout() {\n if (!cleanNodeTimeoutID && cleanNodeQueue.length) {\n cleanNodeTimeoutID = setTimeout(flushCleanQueue, DELAY_MS)\n }\n}\n\nfunction flushCleanQueue() {\n cleanNodeTimeoutID = null\n const nodes = cleanNodeQueue.splice(0, MAX_CLEAN_AT_ONCE)\n for (const node of nodes) {\n cleanNode(node)\n }\n triggerCleanTimeout()\n}\n"],
"mappings": "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",
"sourcesContent": ["export * from './src'\n", "import { isObservable, unwrap } from '@tko/observable'\n\nimport { ORIGINAL_JSX_SYM } from './JsxObserver'\n\n/**\n *\n * @param {any} possibleJsx Test whether this value is JSX.\n *\n * True for\n * { elementName }\n * [{elementName}]\n * observable({elementName} | [])\n *\n * Any observable will return truthy if its value is an array that doesn't\n * contain HTML elements. Template nodes should not be observable unless they\n * are JSX.\n *\n * There's a bit of guesswork here that we could nail down with more test cases.\n */\nexport function maybeJsx(possibleJsx) {\n if (isObservable(possibleJsx)) {\n return true\n }\n const value = unwrap(possibleJsx)\n if (!value) {\n return false\n }\n if (value.elementName) {\n return true\n }\n if (!Array.isArray(value) || !value.length) {\n return false\n }\n if (value[0] instanceof window.Node) {\n return false\n }\n return true\n}\n\nexport function getOriginalJsxForNode(node) {\n return node[ORIGINAL_JSX_SYM]\n}\n\n/**\n * Convert JSX into an object that can be consumed by TKO.\n * Mimics React.createElement\n * @param {string} e tagName of the element\n * @param {object|null} a attributes of the element\n * @param {...string|object} c children of the element\n */\nexport function createElement(elementName, attributes, ...children) {\n return elementName === Fragment\n ? children\n : { elementName: elementName, attributes: attributes || {}, children: [...children] }\n}\n\nexport const Fragment = Symbol('JSX Fragment')\n", "import { LifeCycle } from '@tko/lifecycle'\n\nimport { safeStringify, isThenable } from '@tko/utils'\n\nimport { applyBindings, contextFor } from '@tko/bind'\n\nimport { isObservable, unwrap, observable } from '@tko/observable'\n\nimport type { Observable } from '@tko/observable'\n\nimport { isComputed } from '@tko/computed'\n\nimport { NativeProvider, NATIVE_BINDINGS } from '@tko/provider.native'\n\nimport { queueCleanNode } from './jsxClean'\n\nexport const ORIGINAL_JSX_SYM = Symbol('Knockout - Original JSX')\n\nconst NAMESPACES = {\n svg: 'http://www.w3.org/2000/svg',\n html: 'http://www.w3.org/1999/xhtml',\n xml: 'http://www.w3.org/XML/1998/namespace',\n xlink: 'http://www.w3.org/1999/xlink',\n xmlns: 'http://www.w3.org/2000/xmlns/'\n}\n\nfunction isIterable(v) {\n return v && typeof v[Symbol.iterator] === 'function'\n}\n\n/**\n * JSX object from a pre-processor.\n * @typedef {Object} JSX\n * @property {string} elementName becomes the `tagName`\n * @property {Array.<JSX>} children\n * @property {object} attributes\n */\n\ninterface JSX {\n elementName: string\n children: Array<JSX>\n attributes: any\n}\n\ninterface Changes {\n index: number\n status: string\n value: any\n}\n\n/**\n * Observe a variety of possible cases from JSX, modifying the\n * `parentNode` at `insertBefore` with the result.\n */\nexport class JsxObserver extends LifeCycle {\n adoptedInsertBefore: boolean\n noInitialBinding: boolean\n insertBefore: Node | null\n parentNode: Node\n parentNodeTarget: Node | null\n subscriptionsForNode: any\n nodeArrayOrObservableAtIndex: any\n xmlns: any\n\n /**\n * @param {any} jsxOrObservable take a long list of permutations\n */\n constructor(\n jsxOrObservable: any,\n parentNode: Node,\n insertBefore: Node | null = null,\n xmlns?: any,\n noInitialBinding?: boolean | null\n ) {\n super()\n\n const parentNodeIsComment = parentNode.nodeType === Node.COMMENT_NODE\n\n const parentNodeTarget = this.getParentTarget(parentNode)\n\n if (isObservable(jsxOrObservable)) {\n jsxOrObservable.extend({ trackArrayChanges: true })\n this.subscribe(jsxOrObservable, this.observableArrayChange, 'arrayChange')\n\n if (!insertBefore) {\n const insertAt = parentNodeIsComment ? parentNode.nextSibling : null\n insertBefore = this.createComment('O')\n parentNodeTarget?.insertBefore(insertBefore, insertAt)\n } else {\n this.adoptedInsertBefore = true\n }\n }\n\n if (parentNodeIsComment && !insertBefore) {\n // Typcially: insertBefore becomes <!-- /ko -->\n insertBefore = parentNode.nextSibling\n // Mark this so we don't remove the next node - since we didn't create it.\n this.adoptedInsertBefore = true\n }\n\n this.anchorTo(insertBefore || parentNode)\n\n Object.assign(this, {\n insertBefore,\n noInitialBinding,\n parentNode,\n parentNodeTarget,\n xmlns,\n nodeArrayOrObservableAtIndex: [],\n subscriptionsForNode: new Map()\n })\n\n const jsx = unwrap(jsxOrObservable)\n const computed = isComputed(jsxOrObservable)\n\n if (computed || (jsx !== null && jsx !== undefined)) {\n this.observableArrayChange(this.createInitialAdditions(jsx))\n }\n this.noInitialBinding = false\n }\n\n getParentTarget(parentNode: Node): Node | null {\n if ('content' in parentNode) {\n return (parentNode as HTMLTemplateElement).content\n }\n if (parentNode.nodeType === Node.COMMENT_NODE) {\n return (parentNode as Comment).parentNode\n }\n return parentNode\n }\n\n remove() {\n this.dispose()\n }\n override dispose() {\n super.dispose()\n const ib = this.insertBefore\n const insertBeforeIsChild = ib && this.parentNodeTarget === ib.parentNode\n if (insertBeforeIsChild && !this.adoptedInsertBefore) {\n this.parentNodeTarget?.removeChild(ib)\n }\n this.removeAllPriorNodes()\n Object.assign(this, {\n parentNode: null,\n parentNodeTarget: null,\n insertBefore: null,\n nodeArrayOrObservableAtIndex: []\n })\n for (const subscriptions of this.subscriptionsForNode.values()) {\n subscriptions.forEach(s => s.dispose())\n }\n this.subscriptionsForNode.clear()\n }\n\n createInitialAdditions(possibleIterable): Changes[] {\n const status = 'added'\n if (typeof possibleIterable === 'object' && possibleIterable !== null && Symbol.iterator in possibleIterable) {\n possibleIterable = [...possibleIterable]\n }\n\n return Array.isArray(possibleIterable)\n ? possibleIterable.map((value, index) => ({ index, status, value }))\n : [{ status, index: 0, value: possibleIterable }]\n }\n\n /**\n * Note: array change notification indexes are:\n * - to the original array indexes for deletes\n * - to the new array indexes for adds\n * - sorted by index in ascending order\n */\n observableArrayChange(changes: Changes[]) {\n const adds: [number, any][] = []\n const dels: [number, any][] = []\n\n for (const index in changes) {\n const change = changes[index]\n if (change.status === 'added') {\n adds.push([change.index, change.value])\n } else {\n dels.unshift([change.index, change.value])\n }\n }\n\n dels.forEach(change => this.delChange(...change))\n adds.forEach(change => this.addChange(...change))\n }\n\n /**\n * Add a change at the given index.\n *\n * @param {int} index\n * @param {string|object|Array|Observable.string|Observable.Array|Observable.object} jsx\n */\n addChange(\n index: number,\n jsx: string | object | Array<any> | Observable<string> | Observable<any[]> | Observable<object>\n ) {\n this.nodeArrayOrObservableAtIndex.splice(index, 0, this.injectNode(jsx, this.lastNodeFor(index)!))\n }\n\n injectNode(jsx, nextNode: Node) {\n let nodeArrayOrObservable\n\n if (isObservable(jsx)) {\n const { parentNode, xmlns } = this\n const observer = new JsxObserver(jsx, parentNode, nextNode, xmlns, this.noInitialBinding)\n nodeArrayOrObservable = [observer]\n } else if (typeof jsx !== 'string' && isIterable(jsx)) {\n nodeArrayOrObservable = new Array()\n for (const child of jsx) {\n nodeArrayOrObservable.unshift(this.injectNode(child, nextNode))\n }\n } else {\n const $context = contextFor(this.parentNode as HTMLElement)\n const isInsideTemplate = 'content' in this.parentNode\n const shouldApplyBindings = $context && !isInsideTemplate && !this.noInitialBinding\n\n if (Array.isArray(jsx)) {\n nodeArrayOrObservable = jsx.map(j => this.anyToNode(j))\n } else {\n nodeArrayOrObservable = [this.anyToNode(jsx)]\n }\n\n for (const node of nodeArrayOrObservable) {\n this.parentNodeTarget?.insertBefore(node, nextNode)\n if (shouldApplyBindings && this.canApplyBindings(node)) {\n applyBindings($context, node)\n }\n }\n }\n\n return nodeArrayOrObservable\n }\n\n /**\n * True when Node is a type suitable for applyBindings i.e. a HTMLElement\n * or a Comment.\n * @param {Node} node\n */\n canApplyBindings(node: Node): boolean {\n return node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.COMMENT_NODE\n }\n\n delChange(index: number, _: any) {\n this.removeNodeArrayOrObservable(this.nodeArrayOrObservableAtIndex[index])\n this.nodeArrayOrObservableAtIndex.splice(index, 1)\n }\n\n getSubscriptionsForNode(node: Node) {\n if (!this.subscriptionsForNode.has(node)) {\n const subscriptions = new Array()\n this.subscriptionsForNode.set(node, subscriptions)\n return subscriptions\n }\n return this.subscriptionsForNode.get(node)\n }\n\n isJsx(jsx): jsx is JSX {\n return typeof jsx.elementName === 'string' && 'children' in jsx && 'attributes' in jsx\n }\n\n /**\n * @param {any} value acceptable to turn into a Node\n *\n * The one thing `any` cannot be here is an Array or Observable; both those\n * cases are handled with new JsxObservers.\n */\n anyToNode(any) {\n if (isThenable(any)) {\n return this.futureJsxNode(any)\n }\n\n switch (typeof any) {\n case 'object':\n if (any instanceof Error) {\n return this.createComment(any.toString())\n }\n if (any === null) {\n return this.createComment(String(any))\n }\n if (any instanceof Node) {\n return this.cloneJSXorMoveNode(any)\n }\n if (Symbol.iterator in any) {\n return any\n }\n break\n case 'function':\n return this.anyToNode(any())\n case 'undefined':\n case 'symbol':\n return this.createComment(String(any))\n case 'string':\n return this.createTextNode(any)\n case 'boolean':\n case 'number':\n case 'bigint':\n default:\n return this.createTextNode(String(any))\n }\n\n return this.isJsx(any) ? this.jsxToNode(any) : this.createComment(safeStringify(any))\n }\n\n createComment(string) {\n const node = document.createComment(string)\n node[NATIVE_BINDINGS] = true\n return node\n }\n\n createTextNode(string) {\n const node = document.createTextNode(string)\n node[NATIVE_BINDINGS] = true\n return node\n }\n\n /**\n * Clone a node; if that node was originally from JSX, we clone from there\n * so we preserve binding handlers.\n *\n * @param {HTMLElement} node\n */\n cloneJSXorMoveNode(node: Node) {\n return ORIGINAL_JSX_SYM in node ? this.jsxToNode(node[ORIGINAL_JSX_SYM] as JSX) : node\n }\n\n /**\n * @param {JSX} jsx to convert to a node.\n */\n jsxToNode(jsx: JSX) {\n const xmlns = jsx.attributes.xmlns || NAMESPACES[jsx.elementName] || this.xmlns\n const node = document.createElementNS(xmlns || NAMESPACES.html, jsx.elementName)\n\n /** Slots need to be able to replicate with the attributes, which\n * are not preserved when cloning from template nodes. */\n node[ORIGINAL_JSX_SYM] = jsx\n\n if (isObservable(jsx.attributes)) {\n const subscriptions = this.getSubscriptionsForNode(node)\n subscriptions.push(\n jsx.attributes.subscribe(attrs => {\n this.updateAttributes(node, unwrap(attrs))\n })\n )\n }\n this.updateAttributes(node, unwrap(jsx.attributes))\n\n this.addDisposable(new JsxObserver(jsx.children, node, null, xmlns, this.noInitialBinding))\n\n return node\n }\n\n futureJsxNode(promise) {\n const obs = observable()\n promise.then(obs).catch(e => obs(e instanceof Error ? e : Error(e)))\n const jo = new JsxObserver(obs, this.parentNode, null, this.xmlns, this.noInitialBinding)\n this.addDisposable(jo)\n return jo.insertBefore\n }\n\n updateAttributes(node, attributes) {\n const subscriptions = this.getSubscriptionsForNode(node)\n const toRemove = new Set([...node.attributes].map(n => n.name))\n\n for (const [name, value] of Object.entries(attributes || {})) {\n toRemove.delete(name)\n if (isObservable(value)) {\n subscriptions.push(value.subscribe(attr => this.setNodeAttribute(node, name, value)))\n }\n this.setNodeAttribute(node, name, value)\n }\n\n for (const name of toRemove) {\n this.setNodeAttribute(node, name, undefined)\n }\n }\n\n /**\n * See https://stackoverflow.com/a/52572048\n * @param {string} attr element attribute\n * @return {string} namespace argument for setAtttributeNS\n */\n getNamespaceOfAttribute(attr: string): string | null {\n const [prefix, ...unqualifiedName] = attr.split(':')\n if (prefix === 'xmlns' || (unqualifiedName.length && NAMESPACES[prefix])) {\n return NAMESPACES[prefix]\n }\n return null\n }\n\n /**\n *\n * @param {HTMLElement} node\n * @param {string} name\n * @param {any} valueOrObservable\n */\n setNodeAttribute(node: HTMLElement, name: string, valueOrObservable: any) {\n const value = unwrap(valueOrObservable)\n NativeProvider.addValueToNode(node, name, valueOrObservable)\n if (value === undefined) {\n node.removeAttributeNS(null, name)\n } else if (isThenable(valueOrObservable)) {\n Promise.resolve(valueOrObservable).then(v => this.setNodeAttribute(node, name, v))\n } else {\n const ns = this.getNamespaceOfAttribute(name)\n node.setAttributeNS(ns, name, String(value))\n }\n }\n\n /**\n * @param {int} index\n * @return {Comment} that immediately precedes this.\n */\n lastNodeFor(index: number): Comment | null {\n const nodesAtIndex = this.nodeArrayOrObservableAtIndex[index] || []\n const [lastNodeOfPrior] = nodesAtIndex.slice(-1)\n const insertBefore =\n lastNodeOfPrior instanceof JsxObserver ? lastNodeOfPrior.insertBefore : lastNodeOfPrior || this.insertBefore\n if (insertBefore) {\n return insertBefore.parentNode ? insertBefore : null\n }\n return null\n }\n\n removeAllPriorNodes() {\n const { nodeArrayOrObservableAtIndex } = this\n while (nodeArrayOrObservableAtIndex.length) {\n this.removeNodeArrayOrObservable(nodeArrayOrObservableAtIndex.pop())\n }\n }\n\n removeNodeArrayOrObservable(nodeArrayOrObservable) {\n for (const nodeOrObservable of nodeArrayOrObservable) {\n if (nodeOrObservable instanceof JsxObserver) {\n nodeOrObservable.dispose()\n continue\n }\n const node = nodeOrObservable\n delete node[ORIGINAL_JSX_SYM]\n this.detachAndDispose(node)\n const subscriptions = this.subscriptionsForNode.get(node)\n if (subscriptions) {\n subscriptions.forEach(s => s.dispose())\n this.subscriptionsForNode.delete(node)\n }\n }\n }\n\n /**\n * Detach the given node, and dispose of its children.\n *\n * The cleaning can trigger a lot of garbage collection, so we defer that.\n */\n detachAndDispose(node) {\n if (isIterable(node)) {\n for (const child of node) {\n this.detachAndDispose(child)\n }\n } else {\n node.remove()\n }\n queueCleanNode(node)\n }\n}\n\nexport default JsxObserver\n", "import { cleanNode, defineOption, options } from '@tko/utils'\n\nconst DELAY_MS = 25\nconst cleanNodeQueue = new Array()\nlet cleanNodeTimeoutID: ReturnType<typeof setTimeout> | null = null\n\n// Extend the Options type so ko.options.jsxCleanBatchSize is strongly typed.\ndeclare module '@tko/utils' {\n interface Options {\n jsxCleanBatchSize: number\n }\n}\n\n// `0` runs cleanup synchronously on detach. Test environments that tear\n// down DOM globals between files use that to avoid a pending 25ms timer\n// firing against a dead global.\ndefineOption('jsxCleanBatchSize', { default: 1000 })\n\nexport function queueCleanNode(node) {\n cleanNodeQueue.push(node)\n if (options.jsxCleanBatchSize === 0) {\n flushAll()\n } else {\n scheduleBatch()\n }\n}\n\nfunction scheduleBatch() {\n if (!cleanNodeTimeoutID && cleanNodeQueue.length) {\n cleanNodeTimeoutID = setTimeout(flushBatch, DELAY_MS)\n }\n}\n\nfunction flushBatch() {\n cleanNodeTimeoutID = null\n // If the option was flipped to a non-positive / non-finite value while the\n // timer was pending, fall through to synchronous drain \u2014 otherwise\n // splice(0, <=0|NaN) removes nothing and scheduleBatch re-arms forever.\n const batchSize = Math.trunc(options.jsxCleanBatchSize)\n if (!Number.isFinite(batchSize) || batchSize <= 0) {\n flushAll()\n return\n }\n const nodes = cleanNodeQueue.splice(0, batchSize)\n for (const node of nodes) {\n cleanNode(node)\n }\n scheduleBatch()\n}\n\nfunction flushAll() {\n if (cleanNodeTimeoutID !== null) {\n clearTimeout(cleanNodeTimeoutID)\n cleanNodeTimeoutID = null\n }\n // Outer `while` is for re-enqueues triggered by cleanNode side effects.\n while (cleanNodeQueue.length) {\n for (const node of cleanNodeQueue.splice(0)) {\n cleanNode(node)\n }\n }\n}\n"],
"mappings": "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",
"names": ["import_observable", "import_utils"]
}

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

// @tko/utils.jsx 🥊 4.0.1 ESM
// @tko/utils.jsx 🥊 4.1.0 ESM
"use strict";
export { getOriginalJsxForNode, maybeJsx, createElement, Fragment } from "./jsx.js";
export { default as JsxObserver } from "./JsxObserver.js";

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

// @tko/utils.jsx 🥊 4.0.1 MJS
// @tko/utils.jsx 🥊 4.1.0 MJS
"use strict";
export { getOriginalJsxForNode, maybeJsx, createElement, Fragment } from "./jsx.js";
export { default as JsxObserver } from "./JsxObserver.js";

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

// @tko/utils.jsx 🥊 4.0.1 ESM
// @tko/utils.jsx 🥊 4.1.0 ESM
"use strict";

@@ -3,0 +3,0 @@ import { isObservable, unwrap } from "@tko/observable";

@@ -1,24 +0,44 @@

// @tko/utils.jsx 🥊 4.0.1 ESM
// @tko/utils.jsx 🥊 4.1.0 ESM
"use strict";
import { cleanNode } from "@tko/utils";
import { cleanNode, defineOption, options } from "@tko/utils";
const DELAY_MS = 25;
const MAX_CLEAN_AT_ONCE = 1e3;
const cleanNodeQueue = new Array();
let cleanNodeTimeoutID = null;
defineOption("jsxCleanBatchSize", { default: 1e3 });
export function queueCleanNode(node) {
cleanNodeQueue.push(node);
triggerCleanTimeout();
if (options.jsxCleanBatchSize === 0) {
flushAll();
} else {
scheduleBatch();
}
}
function triggerCleanTimeout() {
function scheduleBatch() {
if (!cleanNodeTimeoutID && cleanNodeQueue.length) {
cleanNodeTimeoutID = setTimeout(flushCleanQueue, DELAY_MS);
cleanNodeTimeoutID = setTimeout(flushBatch, DELAY_MS);
}
}
function flushCleanQueue() {
function flushBatch() {
cleanNodeTimeoutID = null;
const nodes = cleanNodeQueue.splice(0, MAX_CLEAN_AT_ONCE);
const batchSize = Math.trunc(options.jsxCleanBatchSize);
if (!Number.isFinite(batchSize) || batchSize <= 0) {
flushAll();
return;
}
const nodes = cleanNodeQueue.splice(0, batchSize);
for (const node of nodes) {
cleanNode(node);
}
triggerCleanTimeout();
scheduleBatch();
}
function flushAll() {
if (cleanNodeTimeoutID !== null) {
clearTimeout(cleanNodeTimeoutID);
cleanNodeTimeoutID = null;
}
while (cleanNodeQueue.length) {
for (const node of cleanNodeQueue.splice(0)) {
cleanNode(node);
}
}
}
{
"version": 3,
"sources": ["../src/jsxClean.ts"],
"sourcesContent": ["import { cleanNode } from '@tko/utils'\n\nconst DELAY_MS = 25\nconst MAX_CLEAN_AT_ONCE = 1000\nconst cleanNodeQueue = new Array()\nlet cleanNodeTimeoutID: ReturnType<typeof setTimeout> | null = null\n\nexport function queueCleanNode(node) {\n cleanNodeQueue.push(node)\n triggerCleanTimeout()\n}\n\nfunction triggerCleanTimeout() {\n if (!cleanNodeTimeoutID && cleanNodeQueue.length) {\n cleanNodeTimeoutID = setTimeout(flushCleanQueue, DELAY_MS)\n }\n}\n\nfunction flushCleanQueue() {\n cleanNodeTimeoutID = null\n const nodes = cleanNodeQueue.splice(0, MAX_CLEAN_AT_ONCE)\n for (const node of nodes) {\n cleanNode(node)\n }\n triggerCleanTimeout()\n}\n"],
"mappings": ";;AAAA,SAAS,iBAAiB;AAE1B,MAAM,WAAW;AACjB,MAAM,oBAAoB;AAC1B,MAAM,iBAAiB,IAAI,MAAM;AACjC,IAAI,qBAA2D;AAExD,gBAAS,eAAe,MAAM;AACnC,iBAAe,KAAK,IAAI;AACxB,sBAAoB;AACtB;AAEA,SAAS,sBAAsB;AAC7B,MAAI,CAAC,sBAAsB,eAAe,QAAQ;AAChD,yBAAqB,WAAW,iBAAiB,QAAQ;AAAA,EAC3D;AACF;AAEA,SAAS,kBAAkB;AACzB,uBAAqB;AACrB,QAAM,QAAQ,eAAe,OAAO,GAAG,iBAAiB;AACxD,aAAW,QAAQ,OAAO;AACxB,cAAU,IAAI;AAAA,EAChB;AACA,sBAAoB;AACtB;",
"sourcesContent": ["import { cleanNode, defineOption, options } from '@tko/utils'\n\nconst DELAY_MS = 25\nconst cleanNodeQueue = new Array()\nlet cleanNodeTimeoutID: ReturnType<typeof setTimeout> | null = null\n\n// Extend the Options type so ko.options.jsxCleanBatchSize is strongly typed.\ndeclare module '@tko/utils' {\n interface Options {\n jsxCleanBatchSize: number\n }\n}\n\n// `0` runs cleanup synchronously on detach. Test environments that tear\n// down DOM globals between files use that to avoid a pending 25ms timer\n// firing against a dead global.\ndefineOption('jsxCleanBatchSize', { default: 1000 })\n\nexport function queueCleanNode(node) {\n cleanNodeQueue.push(node)\n if (options.jsxCleanBatchSize === 0) {\n flushAll()\n } else {\n scheduleBatch()\n }\n}\n\nfunction scheduleBatch() {\n if (!cleanNodeTimeoutID && cleanNodeQueue.length) {\n cleanNodeTimeoutID = setTimeout(flushBatch, DELAY_MS)\n }\n}\n\nfunction flushBatch() {\n cleanNodeTimeoutID = null\n // If the option was flipped to a non-positive / non-finite value while the\n // timer was pending, fall through to synchronous drain \u2014 otherwise\n // splice(0, <=0|NaN) removes nothing and scheduleBatch re-arms forever.\n const batchSize = Math.trunc(options.jsxCleanBatchSize)\n if (!Number.isFinite(batchSize) || batchSize <= 0) {\n flushAll()\n return\n }\n const nodes = cleanNodeQueue.splice(0, batchSize)\n for (const node of nodes) {\n cleanNode(node)\n }\n scheduleBatch()\n}\n\nfunction flushAll() {\n if (cleanNodeTimeoutID !== null) {\n clearTimeout(cleanNodeTimeoutID)\n cleanNodeTimeoutID = null\n }\n // Outer `while` is for re-enqueues triggered by cleanNode side effects.\n while (cleanNodeQueue.length) {\n for (const node of cleanNodeQueue.splice(0)) {\n cleanNode(node)\n }\n }\n}\n"],
"mappings": ";;AAAA,SAAS,WAAW,cAAc,eAAe;AAEjD,MAAM,WAAW;AACjB,MAAM,iBAAiB,IAAI,MAAM;AACjC,IAAI,qBAA2D;AAY/D,aAAa,qBAAqB,EAAE,SAAS,IAAK,CAAC;AAE5C,gBAAS,eAAe,MAAM;AACnC,iBAAe,KAAK,IAAI;AACxB,MAAI,QAAQ,sBAAsB,GAAG;AACnC,aAAS;AAAA,EACX,OAAO;AACL,kBAAc;AAAA,EAChB;AACF;AAEA,SAAS,gBAAgB;AACvB,MAAI,CAAC,sBAAsB,eAAe,QAAQ;AAChD,yBAAqB,WAAW,YAAY,QAAQ;AAAA,EACtD;AACF;AAEA,SAAS,aAAa;AACpB,uBAAqB;AAIrB,QAAM,YAAY,KAAK,MAAM,QAAQ,iBAAiB;AACtD,MAAI,CAAC,OAAO,SAAS,SAAS,KAAK,aAAa,GAAG;AACjD,aAAS;AACT;AAAA,EACF;AACA,QAAM,QAAQ,eAAe,OAAO,GAAG,SAAS;AAChD,aAAW,QAAQ,OAAO;AACxB,cAAU,IAAI;AAAA,EAChB;AACA,gBAAc;AAChB;AAEA,SAAS,WAAW;AAClB,MAAI,uBAAuB,MAAM;AAC/B,iBAAa,kBAAkB;AAC/B,yBAAqB;AAAA,EACvB;AAEA,SAAO,eAAe,QAAQ;AAC5B,eAAW,QAAQ,eAAe,OAAO,CAAC,GAAG;AAC3C,gBAAU,IAAI;AAAA,IAChB;AAAA,EACF;AACF;",
"names": []
}

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

// @tko/utils.jsx 🥊 4.0.1 ESM
// @tko/utils.jsx 🥊 4.1.0 ESM
"use strict";

@@ -3,0 +3,0 @@ import { LifeCycle } from "@tko/lifecycle";

{
"version": "4.0.1",
"version": "4.1.0",
"name": "@tko/utils.jsx",

@@ -16,3 +16,5 @@ "description": "TKO JSX Rendering",

"tko",
"ko"
"jsx",
"tsx",
"reactive-rendering"
],

@@ -22,9 +24,8 @@ "author": "The Knockout Team",

"dependencies": {
"@tko/bind": "^4.0.1",
"@tko/computed": "^4.0.1",
"@tko/lifecycle": "^4.0.1",
"@tko/observable": "^4.0.1",
"@tko/provider.native": "^4.0.1",
"@tko/utils": "^4.0.1",
"tslib": "^2.2.0"
"@tko/bind": "^4.1.0",
"@tko/computed": "^4.1.0",
"@tko/lifecycle": "^4.1.0",
"@tko/observable": "^4.1.0",
"@tko/provider.native": "^4.1.0",
"@tko/utils": "^4.1.0"
},

@@ -31,0 +32,0 @@ "homepage": "https://tko.io",