mirror of
https://github.com/x1xhlol/system-prompts-and-models-of-ai-tools.git
synced 2026-02-07 23:40:55 +00:00
feat: Finalize VitePress site structure and styling
This commit is contained in:
451
node_modules/preact/src/diff/children.js
generated
vendored
Normal file
451
node_modules/preact/src/diff/children.js
generated
vendored
Normal file
@@ -0,0 +1,451 @@
|
||||
import { diff, unmount, applyRef } from './index';
|
||||
import { createVNode, Fragment } from '../create-element';
|
||||
import {
|
||||
EMPTY_OBJ,
|
||||
EMPTY_ARR,
|
||||
INSERT_VNODE,
|
||||
MATCHED,
|
||||
UNDEFINED,
|
||||
NULL
|
||||
} from '../constants';
|
||||
import { isArray } from '../util';
|
||||
import { getDomSibling } from '../component';
|
||||
|
||||
/**
|
||||
* @typedef {import('../internal').ComponentChildren} ComponentChildren
|
||||
* @typedef {import('../internal').Component} Component
|
||||
* @typedef {import('../internal').PreactElement} PreactElement
|
||||
* @typedef {import('../internal').VNode} VNode
|
||||
*/
|
||||
|
||||
/**
|
||||
* Diff the children of a virtual node
|
||||
* @param {PreactElement} parentDom The DOM element whose children are being
|
||||
* diffed
|
||||
* @param {ComponentChildren[]} renderResult
|
||||
* @param {VNode} newParentVNode The new virtual node whose children should be
|
||||
* diff'ed against oldParentVNode
|
||||
* @param {VNode} oldParentVNode The old virtual node whose children should be
|
||||
* diff'ed against newParentVNode
|
||||
* @param {object} globalContext The current context object - modified by
|
||||
* getChildContext
|
||||
* @param {string} namespace Current namespace of the DOM node (HTML, SVG, or MathML)
|
||||
* @param {Array<PreactElement>} excessDomChildren
|
||||
* @param {Array<Component>} commitQueue List of components which have callbacks
|
||||
* to invoke in commitRoot
|
||||
* @param {PreactElement} oldDom The current attached DOM element any new dom
|
||||
* elements should be placed around. Likely `null` on first render (except when
|
||||
* hydrating). Can be a sibling DOM element when diffing Fragments that have
|
||||
* siblings. In most cases, it starts out as `oldChildren[0]._dom`.
|
||||
* @param {boolean} isHydrating Whether or not we are in hydration
|
||||
* @param {any[]} refQueue an array of elements needed to invoke refs
|
||||
*/
|
||||
export function diffChildren(
|
||||
parentDom,
|
||||
renderResult,
|
||||
newParentVNode,
|
||||
oldParentVNode,
|
||||
globalContext,
|
||||
namespace,
|
||||
excessDomChildren,
|
||||
commitQueue,
|
||||
oldDom,
|
||||
isHydrating,
|
||||
refQueue
|
||||
) {
|
||||
let i,
|
||||
/** @type {VNode} */
|
||||
oldVNode,
|
||||
/** @type {VNode} */
|
||||
childVNode,
|
||||
/** @type {PreactElement} */
|
||||
newDom,
|
||||
/** @type {PreactElement} */
|
||||
firstChildDom;
|
||||
|
||||
// This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR
|
||||
// as EMPTY_OBJ._children should be `undefined`.
|
||||
/** @type {VNode[]} */
|
||||
let oldChildren = (oldParentVNode && oldParentVNode._children) || EMPTY_ARR;
|
||||
|
||||
let newChildrenLength = renderResult.length;
|
||||
|
||||
oldDom = constructNewChildrenArray(
|
||||
newParentVNode,
|
||||
renderResult,
|
||||
oldChildren,
|
||||
oldDom,
|
||||
newChildrenLength
|
||||
);
|
||||
|
||||
for (i = 0; i < newChildrenLength; i++) {
|
||||
childVNode = newParentVNode._children[i];
|
||||
if (childVNode == NULL) continue;
|
||||
|
||||
// At this point, constructNewChildrenArray has assigned _index to be the
|
||||
// matchingIndex for this VNode's oldVNode (or -1 if there is no oldVNode).
|
||||
if (childVNode._index == -1) {
|
||||
oldVNode = EMPTY_OBJ;
|
||||
} else {
|
||||
oldVNode = oldChildren[childVNode._index] || EMPTY_OBJ;
|
||||
}
|
||||
|
||||
// Update childVNode._index to its final index
|
||||
childVNode._index = i;
|
||||
|
||||
// Morph the old element into the new one, but don't append it to the dom yet
|
||||
let result = diff(
|
||||
parentDom,
|
||||
childVNode,
|
||||
oldVNode,
|
||||
globalContext,
|
||||
namespace,
|
||||
excessDomChildren,
|
||||
commitQueue,
|
||||
oldDom,
|
||||
isHydrating,
|
||||
refQueue
|
||||
);
|
||||
|
||||
// Adjust DOM nodes
|
||||
newDom = childVNode._dom;
|
||||
if (childVNode.ref && oldVNode.ref != childVNode.ref) {
|
||||
if (oldVNode.ref) {
|
||||
applyRef(oldVNode.ref, NULL, childVNode);
|
||||
}
|
||||
refQueue.push(
|
||||
childVNode.ref,
|
||||
childVNode._component || newDom,
|
||||
childVNode
|
||||
);
|
||||
}
|
||||
|
||||
if (firstChildDom == NULL && newDom != NULL) {
|
||||
firstChildDom = newDom;
|
||||
}
|
||||
|
||||
let shouldPlace = !!(childVNode._flags & INSERT_VNODE);
|
||||
if (shouldPlace || oldVNode._children === childVNode._children) {
|
||||
oldDom = insert(childVNode, oldDom, parentDom, shouldPlace);
|
||||
} else if (typeof childVNode.type == 'function' && result !== UNDEFINED) {
|
||||
oldDom = result;
|
||||
} else if (newDom) {
|
||||
oldDom = newDom.nextSibling;
|
||||
}
|
||||
|
||||
// Unset diffing flags
|
||||
childVNode._flags &= ~(INSERT_VNODE | MATCHED);
|
||||
}
|
||||
|
||||
newParentVNode._dom = firstChildDom;
|
||||
|
||||
return oldDom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VNode} newParentVNode
|
||||
* @param {ComponentChildren[]} renderResult
|
||||
* @param {VNode[]} oldChildren
|
||||
*/
|
||||
function constructNewChildrenArray(
|
||||
newParentVNode,
|
||||
renderResult,
|
||||
oldChildren,
|
||||
oldDom,
|
||||
newChildrenLength
|
||||
) {
|
||||
/** @type {number} */
|
||||
let i;
|
||||
/** @type {VNode} */
|
||||
let childVNode;
|
||||
/** @type {VNode} */
|
||||
let oldVNode;
|
||||
|
||||
let oldChildrenLength = oldChildren.length,
|
||||
remainingOldChildren = oldChildrenLength;
|
||||
|
||||
let skew = 0;
|
||||
|
||||
newParentVNode._children = new Array(newChildrenLength);
|
||||
for (i = 0; i < newChildrenLength; i++) {
|
||||
// @ts-expect-error We are reusing the childVNode variable to hold both the
|
||||
// pre and post normalized childVNode
|
||||
childVNode = renderResult[i];
|
||||
|
||||
if (
|
||||
childVNode == NULL ||
|
||||
typeof childVNode == 'boolean' ||
|
||||
typeof childVNode == 'function'
|
||||
) {
|
||||
newParentVNode._children[i] = NULL;
|
||||
continue;
|
||||
}
|
||||
// If this newVNode is being reused (e.g. <div>{reuse}{reuse}</div>) in the same diff,
|
||||
// or we are rendering a component (e.g. setState) copy the oldVNodes so it can have
|
||||
// it's own DOM & etc. pointers
|
||||
else if (
|
||||
typeof childVNode == 'string' ||
|
||||
typeof childVNode == 'number' ||
|
||||
// eslint-disable-next-line valid-typeof
|
||||
typeof childVNode == 'bigint' ||
|
||||
childVNode.constructor == String
|
||||
) {
|
||||
childVNode = newParentVNode._children[i] = createVNode(
|
||||
NULL,
|
||||
childVNode,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
} else if (isArray(childVNode)) {
|
||||
childVNode = newParentVNode._children[i] = createVNode(
|
||||
Fragment,
|
||||
{ children: childVNode },
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
} else if (childVNode.constructor == UNDEFINED && childVNode._depth > 0) {
|
||||
// VNode is already in use, clone it. This can happen in the following
|
||||
// scenario:
|
||||
// const reuse = <div />
|
||||
// <div>{reuse}<span />{reuse}</div>
|
||||
childVNode = newParentVNode._children[i] = createVNode(
|
||||
childVNode.type,
|
||||
childVNode.props,
|
||||
childVNode.key,
|
||||
childVNode.ref ? childVNode.ref : NULL,
|
||||
childVNode._original
|
||||
);
|
||||
} else {
|
||||
childVNode = newParentVNode._children[i] = childVNode;
|
||||
}
|
||||
|
||||
const skewedIndex = i + skew;
|
||||
childVNode._parent = newParentVNode;
|
||||
childVNode._depth = newParentVNode._depth + 1;
|
||||
|
||||
// Temporarily store the matchingIndex on the _index property so we can pull
|
||||
// out the oldVNode in diffChildren. We'll override this to the VNode's
|
||||
// final index after using this property to get the oldVNode
|
||||
const matchingIndex = (childVNode._index = findMatchingIndex(
|
||||
childVNode,
|
||||
oldChildren,
|
||||
skewedIndex,
|
||||
remainingOldChildren
|
||||
));
|
||||
|
||||
oldVNode = NULL;
|
||||
if (matchingIndex != -1) {
|
||||
oldVNode = oldChildren[matchingIndex];
|
||||
remainingOldChildren--;
|
||||
if (oldVNode) {
|
||||
oldVNode._flags |= MATCHED;
|
||||
}
|
||||
}
|
||||
|
||||
// Here, we define isMounting for the purposes of the skew diffing
|
||||
// algorithm. Nodes that are unsuspending are considered mounting and we detect
|
||||
// this by checking if oldVNode._original == null
|
||||
const isMounting = oldVNode == NULL || oldVNode._original == NULL;
|
||||
|
||||
if (isMounting) {
|
||||
if (matchingIndex == -1) {
|
||||
// When the array of children is growing we need to decrease the skew
|
||||
// as we are adding a new element to the array.
|
||||
// Example:
|
||||
// [1, 2, 3] --> [0, 1, 2, 3]
|
||||
// oldChildren newChildren
|
||||
//
|
||||
// The new element is at index 0, so our skew is 0,
|
||||
// we need to decrease the skew as we are adding a new element.
|
||||
// The decrease will cause us to compare the element at position 1
|
||||
// with value 1 with the element at position 0 with value 0.
|
||||
//
|
||||
// A linear concept is applied when the array is shrinking,
|
||||
// if the length is unchanged we can assume that no skew
|
||||
// changes are needed.
|
||||
if (newChildrenLength > oldChildrenLength) {
|
||||
skew--;
|
||||
} else if (newChildrenLength < oldChildrenLength) {
|
||||
skew++;
|
||||
}
|
||||
}
|
||||
|
||||
// If we are mounting a DOM VNode, mark it for insertion
|
||||
if (typeof childVNode.type != 'function') {
|
||||
childVNode._flags |= INSERT_VNODE;
|
||||
}
|
||||
} else if (matchingIndex != skewedIndex) {
|
||||
// When we move elements around i.e. [0, 1, 2] --> [1, 0, 2]
|
||||
// --> we diff 1, we find it at position 1 while our skewed index is 0 and our skew is 0
|
||||
// we set the skew to 1 as we found an offset.
|
||||
// --> we diff 0, we find it at position 0 while our skewed index is at 2 and our skew is 1
|
||||
// this makes us increase the skew again.
|
||||
// --> we diff 2, we find it at position 2 while our skewed index is at 4 and our skew is 2
|
||||
//
|
||||
// this becomes an optimization question where currently we see a 1 element offset as an insertion
|
||||
// or deletion i.e. we optimize for [0, 1, 2] --> [9, 0, 1, 2]
|
||||
// while a more than 1 offset we see as a swap.
|
||||
// We could probably build heuristics for having an optimized course of action here as well, but
|
||||
// might go at the cost of some bytes.
|
||||
//
|
||||
// If we wanted to optimize for i.e. only swaps we'd just do the last two code-branches and have
|
||||
// only the first item be a re-scouting and all the others fall in their skewed counter-part.
|
||||
// We could also further optimize for swaps
|
||||
if (matchingIndex == skewedIndex - 1) {
|
||||
skew--;
|
||||
} else if (matchingIndex == skewedIndex + 1) {
|
||||
skew++;
|
||||
} else {
|
||||
if (matchingIndex > skewedIndex) {
|
||||
skew--;
|
||||
} else {
|
||||
skew++;
|
||||
}
|
||||
|
||||
// Move this VNode's DOM if the original index (matchingIndex) doesn't
|
||||
// match the new skew index (i + new skew)
|
||||
// In the former two branches we know that it matches after skewing
|
||||
childVNode._flags |= INSERT_VNODE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove remaining oldChildren if there are any. Loop forwards so that as we
|
||||
// unmount DOM from the beginning of the oldChildren, we can adjust oldDom to
|
||||
// point to the next child, which needs to be the first DOM node that won't be
|
||||
// unmounted.
|
||||
if (remainingOldChildren) {
|
||||
for (i = 0; i < oldChildrenLength; i++) {
|
||||
oldVNode = oldChildren[i];
|
||||
if (oldVNode != NULL && (oldVNode._flags & MATCHED) == 0) {
|
||||
if (oldVNode._dom == oldDom) {
|
||||
oldDom = getDomSibling(oldVNode);
|
||||
}
|
||||
|
||||
unmount(oldVNode, oldVNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return oldDom;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VNode} parentVNode
|
||||
* @param {PreactElement} oldDom
|
||||
* @param {PreactElement} parentDom
|
||||
* @param {boolean} shouldPlace
|
||||
* @returns {PreactElement}
|
||||
*/
|
||||
function insert(parentVNode, oldDom, parentDom, shouldPlace) {
|
||||
// Note: VNodes in nested suspended trees may be missing _children.
|
||||
|
||||
if (typeof parentVNode.type == 'function') {
|
||||
let children = parentVNode._children;
|
||||
for (let i = 0; children && i < children.length; i++) {
|
||||
if (children[i]) {
|
||||
// If we enter this code path on sCU bailout, where we copy
|
||||
// oldVNode._children to newVNode._children, we need to update the old
|
||||
// children's _parent pointer to point to the newVNode (parentVNode
|
||||
// here).
|
||||
children[i]._parent = parentVNode;
|
||||
oldDom = insert(children[i], oldDom, parentDom, shouldPlace);
|
||||
}
|
||||
}
|
||||
|
||||
return oldDom;
|
||||
} else if (parentVNode._dom != oldDom) {
|
||||
if (shouldPlace) {
|
||||
if (oldDom && parentVNode.type && !oldDom.parentNode) {
|
||||
oldDom = getDomSibling(parentVNode);
|
||||
}
|
||||
parentDom.insertBefore(parentVNode._dom, oldDom || NULL);
|
||||
}
|
||||
oldDom = parentVNode._dom;
|
||||
}
|
||||
|
||||
do {
|
||||
oldDom = oldDom && oldDom.nextSibling;
|
||||
} while (oldDom != NULL && oldDom.nodeType == 8);
|
||||
|
||||
return oldDom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flatten and loop through the children of a virtual node
|
||||
* @param {ComponentChildren} children The unflattened children of a virtual
|
||||
* node
|
||||
* @returns {VNode[]}
|
||||
*/
|
||||
export function toChildArray(children, out) {
|
||||
out = out || [];
|
||||
if (children == NULL || typeof children == 'boolean') {
|
||||
} else if (isArray(children)) {
|
||||
children.some(child => {
|
||||
toChildArray(child, out);
|
||||
});
|
||||
} else {
|
||||
out.push(children);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {VNode} childVNode
|
||||
* @param {VNode[]} oldChildren
|
||||
* @param {number} skewedIndex
|
||||
* @param {number} remainingOldChildren
|
||||
* @returns {number}
|
||||
*/
|
||||
function findMatchingIndex(
|
||||
childVNode,
|
||||
oldChildren,
|
||||
skewedIndex,
|
||||
remainingOldChildren
|
||||
) {
|
||||
const key = childVNode.key;
|
||||
const type = childVNode.type;
|
||||
let oldVNode = oldChildren[skewedIndex];
|
||||
const matched = oldVNode != NULL && (oldVNode._flags & MATCHED) == 0;
|
||||
|
||||
// We only need to perform a search if there are more children
|
||||
// (remainingOldChildren) to search. However, if the oldVNode we just looked
|
||||
// at skewedIndex was not already used in this diff, then there must be at
|
||||
// least 1 other (so greater than 1) remainingOldChildren to attempt to match
|
||||
// against. So the following condition checks that ensuring
|
||||
// remainingOldChildren > 1 if the oldVNode is not already used/matched. Else
|
||||
// if the oldVNode was null or matched, then there could needs to be at least
|
||||
// 1 (aka `remainingOldChildren > 0`) children to find and compare against.
|
||||
//
|
||||
// If there is an unkeyed functional VNode, that isn't a built-in like our Fragment,
|
||||
// we should not search as we risk re-using state of an unrelated VNode. (reverted for now)
|
||||
let shouldSearch =
|
||||
// (typeof type != 'function' || type === Fragment || key) &&
|
||||
remainingOldChildren > (matched ? 1 : 0);
|
||||
|
||||
if (
|
||||
(oldVNode === NULL && childVNode.key == null) ||
|
||||
(matched && key == oldVNode.key && type == oldVNode.type)
|
||||
) {
|
||||
return skewedIndex;
|
||||
} else if (shouldSearch) {
|
||||
let x = skewedIndex - 1;
|
||||
let y = skewedIndex + 1;
|
||||
while (x >= 0 || y < oldChildren.length) {
|
||||
const childIndex = x >= 0 ? x-- : y++;
|
||||
oldVNode = oldChildren[childIndex];
|
||||
if (
|
||||
oldVNode != NULL &&
|
||||
(oldVNode._flags & MATCHED) == 0 &&
|
||||
key == oldVNode.key &&
|
||||
type == oldVNode.type
|
||||
) {
|
||||
return childIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
Reference in New Issue
Block a user