2024-01-20 13:38:20 +08:00
|
|
|
import { isArray, toDisplayString } from '@vue/shared'
|
2023-12-06 14:59:11 +08:00
|
|
|
import type { Block, ParentBlock } from './render'
|
|
|
|
|
2024-02-07 01:37:07 +08:00
|
|
|
export * from './dom/prop'
|
|
|
|
export * from './dom/event'
|
2024-01-20 23:48:10 +08:00
|
|
|
export * from './dom/templateRef'
|
2024-01-20 13:38:20 +08:00
|
|
|
|
2024-01-30 05:34:54 +08:00
|
|
|
export function normalizeBlock(block: Block): Node[] {
|
2024-01-30 04:15:52 +08:00
|
|
|
const nodes: Node[] = []
|
2023-12-06 14:59:11 +08:00
|
|
|
if (block instanceof Node) {
|
2024-01-30 04:15:52 +08:00
|
|
|
nodes.push(block)
|
2023-12-06 14:59:11 +08:00
|
|
|
} else if (isArray(block)) {
|
2024-01-30 04:15:52 +08:00
|
|
|
block.forEach(child => nodes.push(...normalizeBlock(child)))
|
|
|
|
} else if (block) {
|
|
|
|
nodes.push(...normalizeBlock(block.nodes))
|
|
|
|
block.anchor && nodes.push(block.anchor)
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
2024-01-30 04:15:52 +08:00
|
|
|
return nodes
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
|
|
|
|
2024-01-30 04:15:52 +08:00
|
|
|
export function insert(
|
|
|
|
block: Block,
|
|
|
|
parent: ParentBlock,
|
|
|
|
anchor: Node | null = null,
|
|
|
|
) {
|
|
|
|
if (isArray(parent)) {
|
|
|
|
const index = anchor ? parent.indexOf(anchor) : -1
|
|
|
|
if (index > -1) {
|
|
|
|
parent.splice(index, 0, block)
|
2024-01-28 01:31:20 +08:00
|
|
|
} else {
|
2024-01-30 05:35:28 +08:00
|
|
|
if (anchor) throw new Error('The child can not be found in the parent.')
|
2024-01-30 04:15:52 +08:00
|
|
|
parent.push(block)
|
2024-01-28 01:31:20 +08:00
|
|
|
}
|
2024-01-30 04:15:52 +08:00
|
|
|
} else {
|
|
|
|
normalizeBlock(block).forEach(node => parent.insertBefore(node, anchor))
|
2024-01-28 01:31:20 +08:00
|
|
|
}
|
2024-01-30 04:15:52 +08:00
|
|
|
}
|
2024-01-28 01:31:20 +08:00
|
|
|
|
2024-01-30 04:15:52 +08:00
|
|
|
export function prepend(parent: ParentBlock, ...blocks: Block[]) {
|
|
|
|
if (isArray(parent)) {
|
|
|
|
parent.unshift(...blocks)
|
|
|
|
} else {
|
|
|
|
parent.prepend(...normalizeBlock(blocks))
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-28 01:31:20 +08:00
|
|
|
export function append(parent: ParentBlock, ...blocks: Block[]) {
|
2024-01-30 04:15:52 +08:00
|
|
|
if (isArray(parent)) {
|
|
|
|
parent.push(...blocks)
|
|
|
|
} else {
|
|
|
|
parent.append(...normalizeBlock(blocks))
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-30 04:15:52 +08:00
|
|
|
export function remove(block: Block, parent: ParentBlock) {
|
|
|
|
if (isArray(parent)) {
|
|
|
|
const index = parent.indexOf(block)
|
2024-01-30 05:35:28 +08:00
|
|
|
if (index === -1)
|
|
|
|
throw Error('The node to be removed is not a child of this node.')
|
|
|
|
parent.splice(index, 1)
|
2023-12-06 14:59:11 +08:00
|
|
|
} else {
|
2024-01-30 04:15:52 +08:00
|
|
|
normalizeBlock(block).forEach(node => parent.removeChild(node))
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type Children = Record<number, [ChildNode, Children]>
|
2024-01-30 04:15:52 +08:00
|
|
|
export function children(nodes: ChildNode[]): Children {
|
2023-12-29 22:05:33 +08:00
|
|
|
const result: Children = {}
|
2024-01-30 04:15:52 +08:00
|
|
|
for (let i = 0; i < nodes.length; i++) {
|
|
|
|
const n = nodes[i]
|
|
|
|
result[i] = [n, children(Array.from(n.childNodes))]
|
2023-12-29 22:05:33 +08:00
|
|
|
}
|
|
|
|
return result
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
|
|
|
|
2024-01-31 13:16:03 +08:00
|
|
|
export function createTextNode(val?: unknown): Text {
|
2023-12-29 22:05:33 +08:00
|
|
|
// eslint-disable-next-line no-restricted-globals
|
2024-01-31 13:16:03 +08:00
|
|
|
return document.createTextNode(val === undefined ? '' : toDisplayString(val))
|
2023-12-06 14:59:11 +08:00
|
|
|
}
|
2024-01-28 20:15:41 +08:00
|
|
|
|
|
|
|
export function createComment(data: string): Comment {
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
|
|
return document.createComment(data)
|
|
|
|
}
|
|
|
|
|
|
|
|
export function querySelector(selectors: string): Element | null {
|
|
|
|
// eslint-disable-next-line no-restricted-globals
|
|
|
|
return document.querySelector(selectors)
|
|
|
|
}
|