ranuts 0.1.0-alpha → 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/img/sort/bubble.gif +0 -0
- package/assets/img/sort/complexity.png +0 -0
- package/assets/img/sort/select.gif +0 -0
- package/assets/img/sort/sort.png +0 -0
- package/assets/img/tree/balanceTree.png +0 -0
- package/dist/index.d.ts +15 -8
- package/dist/index.js +1078 -44
- package/dist/index.js.map +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/dist/src/file/fileInfo.d.ts +7 -0
- package/dist/src/file/fs.d.ts +2 -0
- package/dist/src/file/readDir.d.ts +6 -0
- package/dist/src/file/readFile.d.ts +8 -0
- package/dist/src/file/watchFile.d.ts +8 -0
- package/dist/src/file/writeFile.d.ts +8 -0
- package/dist/src/mode/subscribe.d.ts +16 -0
- package/dist/src/ranlog/behavior.d.ts +1 -0
- package/dist/src/ranlog/env.d.ts +5 -0
- package/dist/src/ranlog/error.d.ts +2 -0
- package/dist/src/ranlog/index.d.ts +26 -0
- package/dist/src/ranlog/performance.d.ts +21 -0
- package/dist/src/ranlog/report.d.ts +7 -0
- package/dist/src/ranlog/request.d.ts +18 -0
- package/dist/src/ranlog/utils.d.ts +19 -0
- package/dist/src/utils/filterObj.d.ts +8 -0
- package/dist/src/utils/str2Xml.d.ts +8 -0
- package/dist/src/vnode/h.d.ts +6 -0
- package/dist/src/vnode/hooks.d.ts +23 -0
- package/dist/src/vnode/htmlDomApi.d.ts +33 -0
- package/dist/src/vnode/init.d.ts +2 -0
- package/dist/src/vnode/is.d.ts +5 -0
- package/dist/src/vnode/modules/attributes.d.ts +8 -0
- package/dist/src/vnode/modules/class.d.ts +8 -0
- package/dist/src/vnode/modules/index.d.ts +7 -0
- package/dist/src/vnode/modules/listeners.d.ts +14 -0
- package/dist/src/vnode/modules/props.d.ts +8 -0
- package/dist/src/vnode/modules/style.d.ts +14 -0
- package/dist/src/vnode/vnode.d.ts +31 -0
- package/package.json +32 -9
- package/readme.md +1 -0
- package/src/astParser/Parser.ts +654 -0
- package/src/astParser/Tokenizer.ts +447 -0
- package/src/astParser/nodeTypes.ts +194 -0
- package/src/astParser/utils.ts +27 -0
- package/src/babel/parser.ts +10 -0
- package/src/colors/fmt.ts +29 -0
- package/src/colors/isColorSupported.ts +13 -0
- package/src/file/appendFile.ts +29 -0
- package/src/file/fileInfo.ts +22 -0
- package/src/file/fs.ts +9 -0
- package/src/file/readDir.ts +18 -0
- package/src/file/readFile.ts +26 -0
- package/src/file/watchFile.ts +31 -0
- package/src/file/writeFile.ts +38 -0
- package/src/mode/subscribe.ts +89 -0
- package/src/ran/commit.ts +0 -0
- package/src/ran/dom.ts +0 -0
- package/src/ran/hooks.ts +0 -0
- package/src/ran/reconcile.ts +0 -0
- package/src/ran/schedule.ts +0 -0
- package/src/ranlog/behavior.ts +5 -0
- package/src/ranlog/console.ts +16 -0
- package/src/ranlog/env.ts +29 -0
- package/src/ranlog/error.ts +11 -0
- package/src/ranlog/performance.ts +65 -0
- package/src/ranlog/report.ts +33 -0
- package/src/ranlog/request.ts +60 -0
- package/src/ranlog/utils.ts +92 -0
- package/src/ranpack/ast/Declaration.ts +120 -0
- package/src/ranpack/ast/Node.ts +7 -0
- package/src/ranpack/ast/Reference.ts +32 -0
- package/src/ranpack/ast/Scope.ts +80 -0
- package/src/ranpack/bundle.ts +50 -0
- package/src/ranpack/graph.ts +143 -0
- package/src/ranpack/module.ts +431 -0
- package/src/ranpack/moduleLoader.ts +73 -0
- package/src/ranpack/plugins.ts +70 -0
- package/src/ranpack/statement.ts +66 -0
- package/src/ranpack/utils/buildScope.ts +77 -0
- package/src/ranpack/utils/findReference.ts +36 -0
- package/src/ranpack/utils/isFunctionDeclaration.ts +41 -0
- package/src/ranpack/utils/makeLegalIdentifier.ts +18 -0
- package/src/ranpack/utils/object.ts +8 -0
- package/src/ranpack/utils/resolve.ts +32 -0
- package/src/ranpack/utils/walk.ts +66 -0
- package/src/ranpack/ws.ts +269 -0
- package/src/server/connectType.ts +9 -0
- package/src/server/encodeUrl.ts +46 -0
- package/src/server/escapeHtml.ts +46 -0
- package/src/server/get.ts +36 -0
- package/src/server/jitter.ts +77 -0
- package/src/server/mimeType.ts +858 -0
- package/src/server/paresUrl.ts +40 -0
- package/src/server/send.ts +89 -0
- package/src/server/server.ts +67 -0
- package/src/server/status.ts +191 -0
- package/src/server/traverse.ts +54 -0
- package/src/server/websocket.ts +200 -0
- package/src/sort/bubble.ts +21 -0
- package/src/sort/bucket.ts +11 -0
- package/src/sort/count.ts +10 -0
- package/src/sort/heap.ts +10 -0
- package/src/sort/insert.ts +20 -0
- package/src/sort/merge.ts +35 -0
- package/src/sort/quick.ts +50 -0
- package/src/sort/radix.ts +11 -0
- package/src/sort/randomArray.ts +21 -0
- package/src/sort/select.ts +23 -0
- package/src/sort/shell.ts +22 -0
- package/src/utils/compose.ts +37 -0
- package/src/utils/filterObj.ts +21 -0
- package/src/utils/mergeObj.ts +12 -0
- package/src/utils/startTask.ts +15 -0
- package/src/utils/str2Xml.ts +26 -0
- package/src/utils/taskEnd.ts +14 -0
- package/src/vnode/h.ts +108 -0
- package/src/vnode/hooks.ts +25 -0
- package/src/vnode/htmlDomApi.ts +199 -0
- package/src/vnode/init.ts +429 -0
- package/src/vnode/is.ts +17 -0
- package/src/vnode/modules/attributes.ts +70 -0
- package/src/vnode/modules/class.ts +46 -0
- package/src/vnode/modules/listeners.ts +123 -0
- package/src/vnode/modules/props.ts +41 -0
- package/src/vnode/modules/style.ts +118 -0
- package/src/vnode/vnode.ts +65 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 插入排序,维护一个有序的数组,将后面的数字插入到前面的有序数组中国
|
|
3
|
+
* @param {Array} list
|
|
4
|
+
* @return {Array}
|
|
5
|
+
*/
|
|
6
|
+
const insert = (list: Array<string>): Array<string> => {
|
|
7
|
+
const { length } = list
|
|
8
|
+
for (let i = 1; i < length; i++) {
|
|
9
|
+
let preIndex = i - 1
|
|
10
|
+
const current = list[i]
|
|
11
|
+
while (preIndex >= 0 && list[preIndex] > current) {
|
|
12
|
+
list[preIndex + 1] = list[preIndex]
|
|
13
|
+
preIndex--
|
|
14
|
+
}
|
|
15
|
+
list[preIndex + 1] = current
|
|
16
|
+
}
|
|
17
|
+
return list
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default insert
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const combine = (left: Array<number>, right: Array<number>) => {
|
|
2
|
+
const list: Array<number> = []
|
|
3
|
+
while (left.length > 0 && right.length > 0) {
|
|
4
|
+
if (left[0] <= right[0]) {
|
|
5
|
+
list.push(left.shift() as number)
|
|
6
|
+
} else {
|
|
7
|
+
list.push(right.shift() as number)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
while (left.length) {
|
|
12
|
+
list.push(left.shift() as number)
|
|
13
|
+
}
|
|
14
|
+
while (right.length) {
|
|
15
|
+
list.push(right.shift() as number)
|
|
16
|
+
}
|
|
17
|
+
return list
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* @description: 归并排序
|
|
21
|
+
* @param {Array} list
|
|
22
|
+
* @return {Array}
|
|
23
|
+
*/
|
|
24
|
+
const merge = (list: Array<number>): Array<number> => {
|
|
25
|
+
const { length } = list
|
|
26
|
+
if (length < 2) {
|
|
27
|
+
return list
|
|
28
|
+
}
|
|
29
|
+
const middle = Math.floor(length / 2)
|
|
30
|
+
const left = list.slice(0, middle)
|
|
31
|
+
const right = list.slice(middle)
|
|
32
|
+
return combine(merge(left), merge(right))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export default merge
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 设置基准值pivot
|
|
3
|
+
* @param {Array} list
|
|
4
|
+
* @param {number} left
|
|
5
|
+
* @param {number} right
|
|
6
|
+
* @return {number} index
|
|
7
|
+
*/
|
|
8
|
+
const partition = (list: Array<number>, left: number, right: number) => {
|
|
9
|
+
const pivot = left
|
|
10
|
+
let index = pivot + 1
|
|
11
|
+
for (let i = index; i <= right; i++) {
|
|
12
|
+
if (list[i] < list[pivot]) {
|
|
13
|
+
const temp = list[i]
|
|
14
|
+
list[i] = list[index]
|
|
15
|
+
list[index] = temp
|
|
16
|
+
index++
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const temp = list[pivot]
|
|
20
|
+
list[pivot] = list[index - 1]
|
|
21
|
+
list[index - 1] = temp
|
|
22
|
+
return index - 1
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* @description: 不断分区,设置基准值
|
|
26
|
+
* @param {Array} list
|
|
27
|
+
* @param {number} left
|
|
28
|
+
* @param {number} right
|
|
29
|
+
* @return {Array}
|
|
30
|
+
*/
|
|
31
|
+
const combine = (list: Array<number>, left: number, right: number) => {
|
|
32
|
+
let partitionIndex
|
|
33
|
+
if (left < right) {
|
|
34
|
+
partitionIndex = partition(list, left, right)
|
|
35
|
+
combine(list, left, partitionIndex - 1)
|
|
36
|
+
combine(list, partitionIndex + 1, right)
|
|
37
|
+
}
|
|
38
|
+
return list
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @description: 快速排序
|
|
42
|
+
* @param {Array} list
|
|
43
|
+
* @return {Array}
|
|
44
|
+
*/
|
|
45
|
+
const quick = (list: Array<number>): Array<number> => {
|
|
46
|
+
const { length } = list
|
|
47
|
+
return combine(list, 0, length - 1)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default quick
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 通过数组长度,数组最大值,数组的最小值随机生成数组
|
|
3
|
+
* @param {number} length
|
|
4
|
+
* @param {number} min
|
|
5
|
+
* @param {number} max
|
|
6
|
+
* @return {Array<number>}
|
|
7
|
+
*/
|
|
8
|
+
const randomArray = (
|
|
9
|
+
length: number = 10,
|
|
10
|
+
min: number = 0,
|
|
11
|
+
max: number = min + 100,
|
|
12
|
+
): Array<number> => {
|
|
13
|
+
if (min > max) {
|
|
14
|
+
throw new Error('max must be max min')
|
|
15
|
+
}
|
|
16
|
+
return Array.from({ length }, (_) =>
|
|
17
|
+
Math.floor(Math.random() * (max - min) + min),
|
|
18
|
+
)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default randomArray
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 选择排序,遍历一遍,找到最小值,放到最前面,重复n次上述操作。
|
|
3
|
+
* @param {Array} list
|
|
4
|
+
* @return {Array}
|
|
5
|
+
*/
|
|
6
|
+
const select = (list: Array<number>): Array<number> => {
|
|
7
|
+
const { length } = list
|
|
8
|
+
for (let i = 0; i < length; i++) {
|
|
9
|
+
let minIndex = i
|
|
10
|
+
for (let j = i + 1; j < length; j++) {
|
|
11
|
+
if (list[j] <= list[minIndex]) {
|
|
12
|
+
minIndex = j
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const temp = list[i]
|
|
17
|
+
list[i] = list[minIndex]
|
|
18
|
+
list[minIndex] = temp
|
|
19
|
+
}
|
|
20
|
+
return list
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default select
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 希尔排序,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序。
|
|
3
|
+
* @param {Array} list
|
|
4
|
+
* @return {Array}
|
|
5
|
+
*/
|
|
6
|
+
const shell = (list: Array<number>): Array<number> => {
|
|
7
|
+
const { length } = list
|
|
8
|
+
for (let gap = Math.floor(length / 2); gap > 0; gap = Math.floor(gap / 2)) {
|
|
9
|
+
for (let i = gap; i < length; i++) {
|
|
10
|
+
let j = i
|
|
11
|
+
const current = list[i]
|
|
12
|
+
while (j - gap >= 0 && current < list[j - gap]) {
|
|
13
|
+
list[j] = list[j - gap]
|
|
14
|
+
j = j - gap
|
|
15
|
+
}
|
|
16
|
+
list[j] = current
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return list
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export default shell
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type Next = () => Promise<never> | Promise<void>
|
|
2
|
+
|
|
3
|
+
type Middleware<T> = (context: T, next: Next) => any
|
|
4
|
+
|
|
5
|
+
type ComposedMiddleware<T> = (context: T, next?: Next) => Promise<void>
|
|
6
|
+
/**
|
|
7
|
+
* @description: 将异步函数转化为同步的方式进行执行
|
|
8
|
+
* @param {Array} middleware
|
|
9
|
+
* @return {*}
|
|
10
|
+
*/
|
|
11
|
+
export function compose<T>(
|
|
12
|
+
middleware: Array<Middleware<T>>,
|
|
13
|
+
): ComposedMiddleware<T> {
|
|
14
|
+
if (!Array.isArray(middleware))
|
|
15
|
+
throw new TypeError('Middleware stack must be an array!')
|
|
16
|
+
for (const fn of middleware) {
|
|
17
|
+
if (typeof fn !== 'function')
|
|
18
|
+
throw new TypeError('Middleware must be composed of functions!')
|
|
19
|
+
}
|
|
20
|
+
return function (context, next) {
|
|
21
|
+
let index = -1
|
|
22
|
+
return dispatch(0)
|
|
23
|
+
function dispatch(i: number): Promise<never> | Promise<void> {
|
|
24
|
+
if (i <= index)
|
|
25
|
+
return Promise.reject(new Error('next() called multiple times'))
|
|
26
|
+
index = i
|
|
27
|
+
let fn = middleware[i]
|
|
28
|
+
if (i === middleware.length && next) fn = next
|
|
29
|
+
if (!fn) return Promise.resolve()
|
|
30
|
+
try {
|
|
31
|
+
return Promise.resolve(fn(context, dispatch.bind(null, i + 1)))
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return Promise.reject(err)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 过滤对象的属性,去除对象中在list数组里面有的属性,返回一个新对象,一般是用于去除空字符和null
|
|
3
|
+
* @param {Object} obj 传入对象
|
|
4
|
+
* @param {Array} list 传入数组
|
|
5
|
+
* @return {Object}
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const filterObj = (
|
|
9
|
+
obj: Record<string | symbol, any>,
|
|
10
|
+
list: Array<string | symbol>,
|
|
11
|
+
): Record<string | symbol, any> => {
|
|
12
|
+
const result: Record<string | symbol, any> = {}
|
|
13
|
+
Object.keys(obj).forEach((item) => {
|
|
14
|
+
if (!list.includes(obj[item])) {
|
|
15
|
+
result[item] = obj[item]
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
return result
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default filterObj
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { hrtime } from 'node:process'
|
|
2
|
+
|
|
3
|
+
const startTask = (): symbol => {
|
|
4
|
+
if(typeof window !== 'undefined'){
|
|
5
|
+
const startTime = window.performance.now()
|
|
6
|
+
return Symbol.for(`${startTime}`)
|
|
7
|
+
}
|
|
8
|
+
if(typeof process !== 'undefined'){
|
|
9
|
+
const startTime = hrtime.bigint()
|
|
10
|
+
return Symbol.for(`${startTime}`)
|
|
11
|
+
}
|
|
12
|
+
return Symbol.for(`${Date.now()}`)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default startTask
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description: 传入字符串和指定的格式,将字符串转成xml
|
|
3
|
+
* @param {string} xmlStr
|
|
4
|
+
* @param {DOMParserSupportedType} format
|
|
5
|
+
* @return {Document}
|
|
6
|
+
*/
|
|
7
|
+
const str2Xml = (
|
|
8
|
+
xmlStr: string,
|
|
9
|
+
format: DOMParserSupportedType = 'text/xml',
|
|
10
|
+
): HTMLElement | undefined => {
|
|
11
|
+
if (window.DOMParser)
|
|
12
|
+
return new window.DOMParser().parseFromString(xmlStr, format)
|
|
13
|
+
.documentElement
|
|
14
|
+
if (
|
|
15
|
+
typeof window.ActiveXObject !== 'undefined' &&
|
|
16
|
+
new window.ActiveXObject('Microsoft.XMLDOM')
|
|
17
|
+
) {
|
|
18
|
+
const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM')
|
|
19
|
+
xmlDoc.async = 'false'
|
|
20
|
+
xmlDoc.loadXML(xmlStr)
|
|
21
|
+
return xmlDoc
|
|
22
|
+
}
|
|
23
|
+
return undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default str2Xml
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { hrtime } from 'node:process'
|
|
2
|
+
|
|
3
|
+
const taskEnd = (symbol: symbol): number | bigint => {
|
|
4
|
+
const startTime = Symbol.keyFor(symbol)
|
|
5
|
+
if (typeof window !== 'undefined' && startTime) {
|
|
6
|
+
return window.performance.now() - Number(startTime)
|
|
7
|
+
}
|
|
8
|
+
if (typeof process !== 'undefined' && startTime) {
|
|
9
|
+
return hrtime.bigint() - BigInt(startTime)
|
|
10
|
+
}
|
|
11
|
+
return Date.now() - Number(startTime)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export default taskEnd
|
package/src/vnode/h.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
VNode,
|
|
3
|
+
VNodeChildElement,
|
|
4
|
+
VNodeChildren,
|
|
5
|
+
VNodeData,
|
|
6
|
+
VNodes,
|
|
7
|
+
} from './vnode'
|
|
8
|
+
import { vnode } from './vnode'
|
|
9
|
+
// 类型判断
|
|
10
|
+
import * as is from './is'
|
|
11
|
+
|
|
12
|
+
export function addNS(
|
|
13
|
+
data: VNodeData,
|
|
14
|
+
children: Array<VNode | string | number> |undefined,
|
|
15
|
+
sel: string | undefined,
|
|
16
|
+
): void {
|
|
17
|
+
data.ns = 'http://www.w3.org/2000/svg'
|
|
18
|
+
if (sel !== 'foreignObject' && children !== undefined) {
|
|
19
|
+
for (let i = 0; i < children.length; ++i) {
|
|
20
|
+
const child = children[i]
|
|
21
|
+
if (typeof child === 'string' || typeof child === 'number') continue
|
|
22
|
+
const childData = child.data
|
|
23
|
+
if (childData !== undefined) {
|
|
24
|
+
addNS(childData, child.children as VNodes, child.sel)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// h 函数的重载
|
|
31
|
+
export function h(sel: string): VNode
|
|
32
|
+
export function h(sel: string, data: VNodeData | null): VNode
|
|
33
|
+
export function h(sel: string, children: VNodeChildren): VNode
|
|
34
|
+
export function h(
|
|
35
|
+
sel: string,
|
|
36
|
+
data: VNodeData | null,
|
|
37
|
+
children: VNodeChildren,
|
|
38
|
+
): VNode
|
|
39
|
+
export function h(
|
|
40
|
+
sel: string,
|
|
41
|
+
b?: VNodeData | null | VNodeChildren,
|
|
42
|
+
c?: VNodeChildren,
|
|
43
|
+
): VNode {
|
|
44
|
+
// 缓存 VNode 数据
|
|
45
|
+
let data: VNodeData = {}
|
|
46
|
+
// 缓存 children 数据
|
|
47
|
+
let children: VNodeChildElement[] | undefined = undefined
|
|
48
|
+
// 缓存文本数据
|
|
49
|
+
let text: string | number | undefined
|
|
50
|
+
// 用于缓存遍历children的index
|
|
51
|
+
let i: number
|
|
52
|
+
|
|
53
|
+
// 处理参数,实现重载的机制
|
|
54
|
+
if (c !== undefined) {
|
|
55
|
+
// 处理三个参数的情况
|
|
56
|
+
// sel、data、children/text
|
|
57
|
+
if (b != null) {
|
|
58
|
+
data = b as VNodeData
|
|
59
|
+
}
|
|
60
|
+
if (is.array(c)) {
|
|
61
|
+
children = c
|
|
62
|
+
// 如果c是字符串或者数字
|
|
63
|
+
} else if (is.primitive(c)) {
|
|
64
|
+
text = c
|
|
65
|
+
// 如果c是VNode
|
|
66
|
+
} else if (c && c.sel) {
|
|
67
|
+
children = [c]
|
|
68
|
+
}
|
|
69
|
+
} else if (b !== undefined && b != null) {
|
|
70
|
+
// 处理两个参数的情况
|
|
71
|
+
// 如果b是数组
|
|
72
|
+
if (is.array(b)) {
|
|
73
|
+
children = b
|
|
74
|
+
// 如果b是字符串或数字
|
|
75
|
+
} else if (is.primitive(b)) {
|
|
76
|
+
text = b
|
|
77
|
+
} else {
|
|
78
|
+
// 这里由于b没有使用any类型,所以需要进一步判断b是否为VNode
|
|
79
|
+
if (is.isVnode(b)) {
|
|
80
|
+
children = [b]
|
|
81
|
+
} else {
|
|
82
|
+
data = b
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// 处理 children 中的原始值(string/number)
|
|
87
|
+
if (typeof children !== 'undefined') {
|
|
88
|
+
for (i = 0; i < children.length; ++i) {
|
|
89
|
+
// 如果 child 是string/number,创建文本节点
|
|
90
|
+
// 这里由于children没有使用any类型,所以需要进一步判断children[i]是否为string | number
|
|
91
|
+
// 不能直接使用children[i],所以使用msg缓存
|
|
92
|
+
const msg = children[i]
|
|
93
|
+
if (is.primitive(msg)) {
|
|
94
|
+
children[i] = vnode(undefined, undefined, undefined, msg, undefined)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (
|
|
99
|
+
sel[0] === 's' &&
|
|
100
|
+
sel[1] === 'v' &&
|
|
101
|
+
sel[2] === 'g' &&
|
|
102
|
+
(sel.length === 3 || sel[3] === '.' || sel[3] === '#')
|
|
103
|
+
) {
|
|
104
|
+
addNS(data, children, sel)
|
|
105
|
+
}
|
|
106
|
+
// 符合VNode
|
|
107
|
+
return vnode(sel, data, children, text, undefined)
|
|
108
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { VNode } from "./vnode";
|
|
2
|
+
|
|
3
|
+
export type PreHook = () => any;
|
|
4
|
+
export type InitHook = (vNode: VNode) => any;
|
|
5
|
+
export type CreateHook = (emptyVNode: VNode, vNode: VNode) => any;
|
|
6
|
+
export type InsertHook = (vNode: VNode) => any;
|
|
7
|
+
export type PrePatchHook = (oldVNode: VNode, vNode: VNode) => any;
|
|
8
|
+
export type UpdateHook = (oldVNode: VNode, vNode: VNode) => any;
|
|
9
|
+
export type PostPatchHook = (oldVNode: VNode, vNode: VNode) => any;
|
|
10
|
+
export type DestroyHook = (vNode: VNode) => any;
|
|
11
|
+
export type RemoveHook = (vNode: VNode, removeCallback: () => void) => any;
|
|
12
|
+
export type PostHook = () => any;
|
|
13
|
+
|
|
14
|
+
export interface Hooks {
|
|
15
|
+
pre?: PreHook;
|
|
16
|
+
init?: InitHook;
|
|
17
|
+
create?: CreateHook;
|
|
18
|
+
insert?: InsertHook;
|
|
19
|
+
prepatch?: PrePatchHook;
|
|
20
|
+
update?: UpdateHook;
|
|
21
|
+
postpatch?: PostPatchHook;
|
|
22
|
+
destroy?: DestroyHook;
|
|
23
|
+
remove?: RemoveHook;
|
|
24
|
+
post?: PostHook;
|
|
25
|
+
}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
export interface Fragment extends DocumentFragment {
|
|
2
|
+
parent: Node | null
|
|
3
|
+
firstChildNode: ChildNode | null
|
|
4
|
+
lastChildNode: ChildNode | null
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface DOMAPI {
|
|
8
|
+
// 创建元素节点
|
|
9
|
+
createElement: (tagName: any, options?: ElementCreationOptions) => HTMLElement
|
|
10
|
+
createElementNS: (
|
|
11
|
+
namespaceURI: string,
|
|
12
|
+
qualifiedName: string,
|
|
13
|
+
options?: ElementCreationOptions,
|
|
14
|
+
) => Element
|
|
15
|
+
/**
|
|
16
|
+
* @experimental
|
|
17
|
+
* @todo Make it required when the fragment is considered stable.
|
|
18
|
+
*/
|
|
19
|
+
createDocumentFragment?: () => Fragment
|
|
20
|
+
// 创建文本节点
|
|
21
|
+
createTextNode: (text: string) => Text
|
|
22
|
+
// 创建注释节点
|
|
23
|
+
createComment: (text: string) => Comment
|
|
24
|
+
// 在指定的已有子节点之前插入新的子节点。
|
|
25
|
+
insertBefore: (
|
|
26
|
+
parentNode: Node,
|
|
27
|
+
newNode: Node,
|
|
28
|
+
referenceNode: Node | null,
|
|
29
|
+
) => void
|
|
30
|
+
// 删除子节点
|
|
31
|
+
removeChild: (node: Node, child: Node) => void
|
|
32
|
+
// 添加子节点
|
|
33
|
+
appendChild: (node: Node, child: Node) => void
|
|
34
|
+
// 获取元素父节点
|
|
35
|
+
parentNode: (node: Node) => Node | null
|
|
36
|
+
// 获取元素紧跟的节点
|
|
37
|
+
nextSibling: (node: Node) => Node | null
|
|
38
|
+
// 获取元素标签名
|
|
39
|
+
tagName: (elm: Element) => string
|
|
40
|
+
// 设置元素文本内容
|
|
41
|
+
setTextContent: (node: Node, text: string | null) => void
|
|
42
|
+
// 获取元素文本内容
|
|
43
|
+
getTextContent: (node: Node) => string | null
|
|
44
|
+
// 判定是否为元素节点
|
|
45
|
+
isElement: (node: Node) => node is Element
|
|
46
|
+
// 判定是否为文本节点
|
|
47
|
+
isText: (node: Node) => node is Text
|
|
48
|
+
// 判定是否为注释节点
|
|
49
|
+
isComment: (node: Node) => node is Comment
|
|
50
|
+
/**
|
|
51
|
+
* @experimental
|
|
52
|
+
* @todo Make it required when the fragment is considered stable.
|
|
53
|
+
*/
|
|
54
|
+
isDocumentFragment?: (node: Node) => node is DocumentFragment
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function createElement(
|
|
58
|
+
tagName: any,
|
|
59
|
+
options?: ElementCreationOptions,
|
|
60
|
+
): HTMLElement {
|
|
61
|
+
return document.createElement(tagName, options)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createElementNS(
|
|
65
|
+
namespaceURI: string,
|
|
66
|
+
qualifiedName: string,
|
|
67
|
+
options?: ElementCreationOptions,
|
|
68
|
+
): Element {
|
|
69
|
+
return document.createElementNS(namespaceURI, qualifiedName, options)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function createDocumentFragment(): Fragment {
|
|
73
|
+
return parseFragment(document.createDocumentFragment())
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function createTextNode(text: string): Text {
|
|
77
|
+
return document.createTextNode(text)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function createComment(text: string): Comment {
|
|
81
|
+
return document.createComment(text)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function insertBefore(
|
|
85
|
+
parentNode: Node,
|
|
86
|
+
newNode: Node,
|
|
87
|
+
referenceNode: Node | null,
|
|
88
|
+
): void {
|
|
89
|
+
if (isDocumentFragment(parentNode)) {
|
|
90
|
+
let node: Node | null = parentNode
|
|
91
|
+
while (node && isDocumentFragment(node)) {
|
|
92
|
+
const fragment = parseFragment(node)
|
|
93
|
+
node = fragment.parent
|
|
94
|
+
}
|
|
95
|
+
parentNode = node ?? parentNode
|
|
96
|
+
}
|
|
97
|
+
if (isDocumentFragment(newNode)) {
|
|
98
|
+
newNode = parseFragment(newNode, parentNode)
|
|
99
|
+
}
|
|
100
|
+
if (referenceNode && isDocumentFragment(referenceNode)) {
|
|
101
|
+
referenceNode = parseFragment(referenceNode).firstChildNode
|
|
102
|
+
}
|
|
103
|
+
parentNode.insertBefore(newNode, referenceNode)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function removeChild(node: Node, child: Node): void {
|
|
107
|
+
node.removeChild(child)
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function appendChild(node: Node, child: Node): void {
|
|
111
|
+
if (isDocumentFragment(child)) {
|
|
112
|
+
child = parseFragment(child, node)
|
|
113
|
+
}
|
|
114
|
+
node.appendChild(child)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function parentNode(node: Node): Node | null {
|
|
118
|
+
if (isDocumentFragment(node)) {
|
|
119
|
+
while (node && isDocumentFragment(node)) {
|
|
120
|
+
const fragment = parseFragment(node)
|
|
121
|
+
node = fragment.parent as Node
|
|
122
|
+
}
|
|
123
|
+
return node ?? null
|
|
124
|
+
}
|
|
125
|
+
return node.parentNode
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function nextSibling(node: Node): Node | null {
|
|
129
|
+
if (isDocumentFragment(node)) {
|
|
130
|
+
const fragment = parseFragment(node)
|
|
131
|
+
const parent = parentNode(fragment)
|
|
132
|
+
if (parent && fragment.lastChildNode) {
|
|
133
|
+
const children = Array.from(parent.childNodes)
|
|
134
|
+
const index = children.indexOf(fragment.lastChildNode)
|
|
135
|
+
return children[index + 1] ?? null
|
|
136
|
+
}
|
|
137
|
+
return null
|
|
138
|
+
}
|
|
139
|
+
return node.nextSibling
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function tagName(elm: Element): string {
|
|
143
|
+
return elm.tagName
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function setTextContent(node: Node, text: string | null): void {
|
|
147
|
+
node.textContent = text
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function getTextContent(node: Node): string | null {
|
|
151
|
+
return node.textContent
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function isElement(node: Node): node is Element {
|
|
155
|
+
return node.nodeType === 1
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function isText(node: Node): node is Text {
|
|
159
|
+
return node.nodeType === 3
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function isComment(node: Node): node is Comment {
|
|
163
|
+
return node.nodeType === 8
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function isDocumentFragment(node: Node): node is DocumentFragment {
|
|
167
|
+
return node.nodeType === 11
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function parseFragment(
|
|
171
|
+
fragmentNode: DocumentFragment,
|
|
172
|
+
parentNode?: Node | null,
|
|
173
|
+
): Fragment {
|
|
174
|
+
const fragment = fragmentNode as Fragment
|
|
175
|
+
fragment.parent ??= parentNode ?? null
|
|
176
|
+
fragment.firstChildNode ??= fragmentNode.firstChild
|
|
177
|
+
fragment.lastChildNode ??= fragmentNode.lastChild
|
|
178
|
+
return fragment
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export const htmlDomApi: DOMAPI = {
|
|
182
|
+
createElement,
|
|
183
|
+
createElementNS,
|
|
184
|
+
createTextNode,
|
|
185
|
+
createDocumentFragment,
|
|
186
|
+
createComment,
|
|
187
|
+
insertBefore,
|
|
188
|
+
removeChild,
|
|
189
|
+
appendChild,
|
|
190
|
+
parentNode,
|
|
191
|
+
nextSibling,
|
|
192
|
+
tagName,
|
|
193
|
+
setTextContent,
|
|
194
|
+
getTextContent,
|
|
195
|
+
isElement,
|
|
196
|
+
isText,
|
|
197
|
+
isComment,
|
|
198
|
+
isDocumentFragment,
|
|
199
|
+
}
|