ranuts 0.1.0-alpha.2 → 0.1.0-alpha.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ranuts",
3
- "version": "0.1.0-alpha.2",
3
+ "version": "0.1.0-alpha.3",
4
4
  "description": "常用函数",
5
5
  "main": "dist/index.umd.cjs",
6
6
  "module": "dist/index.js",
Binary file
Binary file
Binary file
Binary file
Binary file
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sources":["../src/file/fs.ts","../src/file/writeFile.ts","../src/file/readFile.ts","../src/file/watchFile.ts","../src/mode/subscribe.ts","../src/file/fileInfo.ts","../src/utils/filterObj.ts","../src/file/readDir.ts","../src/utils/str2Xml.ts","../src/vnode/vnode.ts","../src/vnode/htmlDomApi.ts","../src/vnode/is.ts","../src/vnode/modules/attributes.ts","../src/vnode/modules/class.ts","../src/vnode/modules/listeners.ts","../src/vnode/modules/props.ts","../src/vnode/modules/style.ts","../src/vnode/modules/index.ts","../src/vnode/init.ts","../src/vnode/h.ts","../src/ranlog/utils.ts","../src/ranlog/behavior.ts","../src/ranlog/error.ts","../src/ranlog/performance.ts","../src/ranlog/env.ts","../src/ranlog/report.ts","../src/ranlog/request.ts","../src/ranlog/index.ts","../index.ts"],"sourcesContent":["const fs = {}\nlet fileSystem: any = fs\nif (typeof process !== 'undefined' && typeof fileSystem.Stats === 'function') {\n fileSystem._identification = true\n} else {\n fileSystem = { _identification: false, message: 'require is not defined' }\n}\n\nexport default fileSystem\n","import fs from './fs'\n\ntype Error = NodeJS.ErrnoException | null\n\n/**\n * @description: 根据文件路径创建文件,如果文件存在会清空再写入,如果不存在会创建\n * @param {string} path 文件路径\n * @param {string} content 文件内容\n * @return {Promise}\n */\n\nconst writeFile = (\n path: string,\n content: string,\n): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.writeFile(\n path,\n content,\n {\n mode: 438, // 可读可写666,转化为十进制就是438\n flag: 'w+', // r+并不会清空再写入,w+会清空再写入\n encoding: 'utf-8',\n },\n (err: Error) => {\n if (err) {\n reject({ _identification: false, data: err })\n throw err\n } else {\n resolve({ _identification: true, data: { path, content } })\n }\n },\n )\n })\n\nexport default writeFile\n","import fs from './fs'\n\ntype Error = NodeJS.ErrnoException | null\n\n/**\n * @description: 读取一个文件,读取成功返回状态码和文件内容\n * @param {string} path 文件路径\n * @param {string} format 读取格式,默认utf-8\n * @return {Promise}\n */\n\nconst readFile = (\n path: string,\n format: string = 'utf-8',\n): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.readFile(path, format, (err: Error, data: string) => {\n err\n ? reject({ _identification: false, data: err })\n : resolve({ _identification: true, data })\n })\n })\n\nexport default readFile\n","import type { Stats } from 'node:fs'\nimport fs from './fs'\n\n/**\n * @description: 观察一个文件是否被改变,返回状态\n * @param {string} path 监听的文件路径\n * @param {number} interval 监听的时间,单位毫秒,默认20毫秒\n * @return {Promise}\n */\n\nconst watchFile = (\n path: string,\n interval: number = 20,\n): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.watchFile(path, { interval }, (curr: Stats, prev: Stats) => {\n if (curr.mtime !== prev.mtime) {\n fs.unwatchFile(path)\n resolve({ _identification: true, data: { msg: 'file is changed' } })\n } else {\n resolve({\n _identification: false,\n data: { msg: 'file is not changed' },\n })\n }\n })\n })\n\nexport default watchFile\n","type Callback = (...args: any) => unknown\n\ntype EventName = string | symbol\n\ntype EventItem = {\n name?: string | symbol\n callback: Callback\n initialCallback?: Callback\n}\n\nclass Subscribe {\n _events: Record<EventName, Array<EventItem>>\n constructor() {\n this._events = {}\n }\n\n on = (eventName: EventName, eventItem: EventItem | Callback): void => {\n if (this._events[eventName] && eventName !== Symbol.for('new-listener')) {\n // 注册一个 newListener 用于监听新的事件订阅\n this.emit(Symbol.for('new-listener'), eventName)\n }\n // 由于一个事件可能注册多个回调函数,所以使用数组来存储事件队列\n const callbacks = this._events[eventName] || []\n if (typeof eventItem === 'function') {\n callbacks.push({\n name: eventName,\n callback: eventItem,\n })\n } else {\n callbacks.push(eventItem)\n }\n this._events[eventName] = callbacks\n }\n\n emit = (eventName: EventName, ...args: Array<unknown>): void => {\n const callbacks = this._events[eventName] || []\n callbacks.forEach((item) => {\n const { callback } = item\n callback(...args)\n })\n }\n\n once = (eventName: EventName, eventItem: EventItem | Callback): void => {\n let one: EventItem\n if (typeof eventItem === 'function') {\n one = {\n name: eventName,\n callback: (...args: Array<unknown>) => {\n eventItem(...args)\n this.off(eventName, one)\n },\n initialCallback: eventItem,\n }\n } else {\n const { callback } = eventItem\n one = {\n name: eventName,\n callback: (...args: Array<unknown>) => {\n callback(...args)\n this.off(eventName, one)\n },\n initialCallback: callback,\n }\n }\n // 由于需要在回调函数执行后,取消订阅当前事件,所以需要对传入的回调函数做一层包装,然后绑定包装后的函数\n\n // 考虑:如果当前事件在未执行,被用户取消订阅,能否取消?\n // 由于:我们订阅事件的时候,修改了原回调函数的引用,所以,用户触发 off 的时候不能找到对应的回调函数\n // 所以,我们需要在当前函数与用户传入的回调函数做一个绑定,我们通过自定义属性来实现\n this.on(eventName, one)\n }\n\n off = (eventName: EventName, eventItem: EventItem | Callback): void => {\n // 找到事件对应的回调函数,删除对应的回调函数\n const callbacks = this._events[eventName] || []\n const newCallbacks = callbacks.filter((item) => {\n if (typeof eventItem === 'function') {\n return item.callback !== eventItem && item.initialCallback !== eventItem\n } else {\n const { callback } = eventItem\n /* 用于once的取消订阅 */\n return item.callback !== callback && item.initialCallback !== callback\n }\n })\n this._events[eventName] = newCallbacks\n }\n}\n\nexport default Subscribe\n","import fs from './fs'\n\ntype Error = NodeJS.ErrnoException | null\n\n/**\n * @description: 查询一个文件的详细信息,一般用于区分文件还是目录(data.isDirectory())\n * @param {string} path 文件路径\n * @return {Promise}\n */\n\nconst queryFileInfo = (path: string): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.stat(path, (err: Error, data: string) => {\n err\n ? reject({ _identification: false, data: err })\n : resolve({ _identification: true, data })\n })\n })\n\nexport default queryFileInfo\n","/**\n * @description: 过滤对象的属性,去除对象中在list数组里面有的属性,返回一个新对象,一般是用于去除空字符和null\n * @param {Object} obj 传入对象\n * @param {Array} list 传入数组\n * @return {Object}\n */\n\nconst filterObj = (\n obj: Record<string | symbol, any>,\n list: Array<string | symbol>,\n): Record<string | symbol, any> => {\n const result: Record<string | symbol, any> = {}\n Object.keys(obj).forEach((item) => {\n if (!list.includes(obj[item])) {\n result[item] = obj[item]\n }\n })\n return result\n}\n\nexport default filterObj\n","import fs from './fs'\n\ninterface Options {\n dirPath: string\n ignores?: Array<string>\n}\n\nconst readDir = (options: Options): Array<string> => {\n const { dirPath } = options\n try {\n return fs.readdirSync(dirPath)\n } catch (error) {\n console.log('readDir error', error)\n throw error\n }\n}\n\nexport default readDir\n","/**\n * @description: 传入字符串和指定的格式,将字符串转成xml\n * @param {string} xmlStr\n * @param {DOMParserSupportedType} format\n * @return {Document}\n */\nconst str2Xml = (\n xmlStr: string,\n format: DOMParserSupportedType = 'text/xml',\n): HTMLElement | undefined => {\n if (window.DOMParser)\n return new window.DOMParser().parseFromString(xmlStr, format)\n .documentElement\n if (\n typeof window.ActiveXObject !== 'undefined' &&\n new window.ActiveXObject('Microsoft.XMLDOM')\n ) {\n const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM')\n xmlDoc.async = 'false'\n xmlDoc.loadXML(xmlStr)\n return xmlDoc\n }\n return undefined\n}\n\nexport default str2Xml\n","import type { On } from './modules/listeners'\nimport type { Attrs } from './modules/attributes'\nimport type { Classes } from './modules/class'\nimport type { Props } from './modules/props'\nimport type { VNodeStyle } from './modules/style'\nimport type { Hooks } from \"./hooks\";\n\n\nexport type VNodes = VNode[]\nexport type VNodeChildElement = VNode | string | number\nexport type ArrayOrElement<T> = T | T[]\nexport type VNodeChildren = ArrayOrElement<VNodeChildElement>\n\n// key属性类型\nexport type Key = string | number\n\ntype Listener<T> = (this: VNode, ev: T, vnode: VNode) => void\n\n// VNode接口\nexport interface VNode {\n // dom节点的选择器,\n // 虚拟节点的 .sel 属性通过对 h() 传入一个 CSS 选择器生成,\n // 比如: h('div#container', {}, [...]) 将会创建一个虚拟节点并以 div#container 作为其 .sel 属性的值。\n sel: string | undefined\n // 节点数据\n data: VNodeData | undefined\n // 子节点,和text互斥\n children: Array<VNode | string | number> | undefined\n // 存储VNode转化成的真实dom\n elm: Node | undefined\n // 节点的文本内容,和children互斥\n text: string | number | undefined\n // key,用于优化diff算法\n key: Key | undefined\n listener?: EventListenerOrEventListenerObject | undefined\n}\n\nexport interface VNodeData {\n // 设置VNode对应的DOM元素的属性,通过 对象.属性 的方式来设置,它内部不会去处理布尔类型的属性\n props?: Props\n // 设置VNode对应的DOM元素的属性,通过 setAttributes 来设置,它内部不会去处理布尔类型的属性\n attrs?: Attrs\n // 设置VNode对应的DOM元素的class\n class?: Classes\n // 设置VNode对应的DOM元素的css style\n style?: VNodeStyle\n // 设置VNode对应的DOM元素的监听事件\n on?: On\n // 设置VNode对应的key\n key?: Key\n // svg元素\n ns?: string\n hook?: Hooks\n}\n\nexport function vnode(\n sel: string | undefined,\n data: any | undefined,\n children: Array<VNode | string | number> | undefined,\n text: string | number | undefined,\n elm: Element | Text | undefined,\n): VNode {\n const key = data === undefined ? undefined : data.key\n return { sel, data, children, text, elm, key }\n}\n","export interface Fragment extends DocumentFragment {\n parent: Node | null\n firstChildNode: ChildNode | null\n lastChildNode: ChildNode | null\n}\n\nexport interface DOMAPI {\n // 创建元素节点\n createElement: (tagName: any, options?: ElementCreationOptions) => HTMLElement\n createElementNS: (\n namespaceURI: string,\n qualifiedName: string,\n options?: ElementCreationOptions,\n ) => Element\n /**\n * @experimental\n * @todo Make it required when the fragment is considered stable.\n */\n createDocumentFragment?: () => Fragment\n // 创建文本节点\n createTextNode: (text: string) => Text\n // 创建注释节点\n createComment: (text: string) => Comment\n // 在指定的已有子节点之前插入新的子节点。\n insertBefore: (\n parentNode: Node,\n newNode: Node,\n referenceNode: Node | null,\n ) => void\n // 删除子节点\n removeChild: (node: Node, child: Node) => void\n // 添加子节点\n appendChild: (node: Node, child: Node) => void\n // 获取元素父节点\n parentNode: (node: Node) => Node | null\n // 获取元素紧跟的节点\n nextSibling: (node: Node) => Node | null\n // 获取元素标签名\n tagName: (elm: Element) => string\n // 设置元素文本内容\n setTextContent: (node: Node, text: string | null) => void\n // 获取元素文本内容\n getTextContent: (node: Node) => string | null\n // 判定是否为元素节点\n isElement: (node: Node) => node is Element\n // 判定是否为文本节点\n isText: (node: Node) => node is Text\n // 判定是否为注释节点\n isComment: (node: Node) => node is Comment\n /**\n * @experimental\n * @todo Make it required when the fragment is considered stable.\n */\n isDocumentFragment?: (node: Node) => node is DocumentFragment\n}\n\nfunction createElement(\n tagName: any,\n options?: ElementCreationOptions,\n): HTMLElement {\n return document.createElement(tagName, options)\n}\n\nfunction createElementNS(\n namespaceURI: string,\n qualifiedName: string,\n options?: ElementCreationOptions,\n): Element {\n return document.createElementNS(namespaceURI, qualifiedName, options)\n}\n\nfunction createDocumentFragment(): Fragment {\n return parseFragment(document.createDocumentFragment())\n}\n\nfunction createTextNode(text: string): Text {\n return document.createTextNode(text)\n}\n\nfunction createComment(text: string): Comment {\n return document.createComment(text)\n}\n\nfunction insertBefore(\n parentNode: Node,\n newNode: Node,\n referenceNode: Node | null,\n): void {\n if (isDocumentFragment(parentNode)) {\n let node: Node | null = parentNode\n while (node && isDocumentFragment(node)) {\n const fragment = parseFragment(node)\n node = fragment.parent\n }\n parentNode = node ?? parentNode\n }\n if (isDocumentFragment(newNode)) {\n newNode = parseFragment(newNode, parentNode)\n }\n if (referenceNode && isDocumentFragment(referenceNode)) {\n referenceNode = parseFragment(referenceNode).firstChildNode\n }\n parentNode.insertBefore(newNode, referenceNode)\n}\n\nfunction removeChild(node: Node, child: Node): void {\n node.removeChild(child)\n}\n\nfunction appendChild(node: Node, child: Node): void {\n if (isDocumentFragment(child)) {\n child = parseFragment(child, node)\n }\n node.appendChild(child)\n}\n\nfunction parentNode(node: Node): Node | null {\n if (isDocumentFragment(node)) {\n while (node && isDocumentFragment(node)) {\n const fragment = parseFragment(node)\n node = fragment.parent as Node\n }\n return node ?? null\n }\n return node.parentNode\n}\n\nfunction nextSibling(node: Node): Node | null {\n if (isDocumentFragment(node)) {\n const fragment = parseFragment(node)\n const parent = parentNode(fragment)\n if (parent && fragment.lastChildNode) {\n const children = Array.from(parent.childNodes)\n const index = children.indexOf(fragment.lastChildNode)\n return children[index + 1] ?? null\n }\n return null\n }\n return node.nextSibling\n}\n\nfunction tagName(elm: Element): string {\n return elm.tagName\n}\n\nfunction setTextContent(node: Node, text: string | null): void {\n node.textContent = text\n}\n\nfunction getTextContent(node: Node): string | null {\n return node.textContent\n}\n\nfunction isElement(node: Node): node is Element {\n return node.nodeType === 1\n}\n\nfunction isText(node: Node): node is Text {\n return node.nodeType === 3\n}\n\nfunction isComment(node: Node): node is Comment {\n return node.nodeType === 8\n}\n\nfunction isDocumentFragment(node: Node): node is DocumentFragment {\n return node.nodeType === 11\n}\n\nfunction parseFragment(\n fragmentNode: DocumentFragment,\n parentNode?: Node | null,\n): Fragment {\n const fragment = fragmentNode as Fragment\n fragment.parent ??= parentNode ?? null\n fragment.firstChildNode ??= fragmentNode.firstChild\n fragment.lastChildNode ??= fragmentNode.lastChild\n return fragment\n}\n\nexport const htmlDomApi: DOMAPI = {\n createElement,\n createElementNS,\n createTextNode,\n createDocumentFragment,\n createComment,\n insertBefore,\n removeChild,\n appendChild,\n parentNode,\n nextSibling,\n tagName,\n setTextContent,\n getTextContent,\n isElement,\n isText,\n isComment,\n isDocumentFragment,\n}\n","import type { VNode } from './vnode'\n\n// 判断是否为数组\nexport const array = Array.isArray\n\nexport const isStr = (str: unknown): str is string => {\n return typeof str === 'string'\n}\n// 判断是否为字符串或数字\nexport function primitive(s: unknown): s is string | number {\n return typeof s === 'string' || typeof s === 'number'\n}\n// 判断是否为vnode\nexport function isVnode(s: any): s is VNode {\n return !!s?.sel\n}\n\n","import type { VNode, VNodeData } from '../vnode'\n\nexport type Attrs = Record<string, string | number | boolean>\n\nconst xlinkNS = 'http://www.w3.org/1999/xlink'\nconst xmlNS = 'http://www.w3.org/XML/1998/namespace'\nconst colonChar = 58\nconst xChar = 120\n\nfunction updateAttrs(oldVnode: VNode, vnode: VNode): void {\n // 用于缓存attrs的name\n let key: string\n // 用于缓存Vnode的dom\n const elm: Element = vnode.elm as Element\n // 用于缓存旧VNode的attrs\n let oldAttrs = oldVnode.data && oldVnode.data.attrs\n // 用于缓存新VNode的attrs\n let attrs = vnode.data && vnode.data.attrs\n\n // 如果新旧VNode都没有attrs属性,直接返回\n if (!oldAttrs && !attrs) return\n // 如果新旧VNode的attrs属性相同,直接返回\n if (oldAttrs === attrs) return\n // 如果旧VNode没有attrs,将其设置为空对象\n oldAttrs = oldAttrs || {}\n // 如果新VNode没有attrs,将其设置为空对象\n attrs = attrs || {}\n\n // 遍历新VNode的attrs\n for (key in attrs) {\n // 获取当前attrs的值\n const cur = attrs[key]\n // 获取旧VNode对应的attrs的值\n const old = oldAttrs[key]\n // 如果新旧VNode的attrs值不相同\n if (old !== cur) {\n // 如果新VNode的attrs值为true\n if (cur === true) {\n // 通过setAttribute设置为空字符串\n elm.setAttribute(key, '')\n } else if (cur === false) {\n // 如果新VNode的attrs值为false,则删除key\n elm.removeAttribute(key)\n } else {\n // 设置svg的属性\n if (key.charCodeAt(0) !== xChar) {\n elm.setAttribute(key, cur as any)\n } else if (key.charCodeAt(3) === colonChar) {\n // Assume xml namespace\n elm.setAttributeNS(xmlNS, key, cur as any)\n } else if (key.charCodeAt(5) === colonChar) {\n // Assume xlink namespace\n elm.setAttributeNS(xlinkNS, key, cur as any)\n } else {\n // 通过setAttribute设置值\n elm.setAttribute(key, `${cur}`)\n }\n }\n }\n }\n // 遍历旧VNode的attrs\n for (key in oldAttrs) {\n // 如果新VNode的attrs中没有相同的key,则直接删除该attrs属性\n if (!(key in attrs)) {\n elm.removeAttribute(key)\n }\n }\n}\n\nexport const attributesModule = { create: updateAttrs, update: updateAttrs }\n","import type { VNode, VNodeData } from '../vnode'\n\nexport type Classes = Record<string, boolean>\n\nfunction updateClass(oldVnode: VNode, vnode: VNode): void {\n // 用于缓存遍历中当前class属性的值\n let cur: any\n // 用于缓存遍历中当前class的name\n let name: string\n // 获取新VNode的dom元素\n const elm: Element = vnode.elm as Element\n // 获取旧VNode的class数据\n let oldClass = oldVnode.data && oldVnode.data.class\n // 获取新VNode的class数据\n let className = vnode.data && vnode.data.class\n\n // 如果新旧VNode都没有class,直接返回\n if (!oldClass && !className) return\n // 如果新旧VNode完全相同,直接返回\n if (oldClass === className) return\n // 如果旧VNode没有class,将其设置为空对象\n oldClass = oldClass || {}\n // 如果新VNode没有class,将其设置为空对象\n className = className || {}\n\n // 遍历旧VNode的class\n for (name in oldClass) {\n // 如果当前class旧VNode上有但新VNode没有,则删除该VNode\n if (\n oldClass[name] &&\n !Object.prototype.hasOwnProperty.call(className, name)\n ) {\n elm.classList.remove(name)\n }\n }\n // 遍历新Vnodde的class\n for (name in className) {\n // 如果新旧VNode的class值不同,则根据新VNode的class值是true or false来判断是新增还是删除class\n cur = className[name]\n if (cur !== oldClass[name]) {\n (elm.classList as any)[cur ? 'add' : 'remove'](name)\n }\n }\n}\n\nexport const classModule = { create: updateClass, update: updateClass }","import type { VNode, VNodeData } from '../vnode'\n\nconst isFunction = (handler: unknown): handler is Function => {\n return typeof handler === 'function'\n}\n\ntype Listener<T> = (this: VNode, ev: T, vnode: VNode) => void\n\nexport type On = {\n [N in keyof HTMLElementEventMap]?:\n | Listener<HTMLElementEventMap[N]>\n | Array<Listener<HTMLElementEventMap[N]>>\n} & {\n [event: string]: Listener<any> | Array<Listener<any>>\n}\n\ntype SomeListener<N extends keyof HTMLElementEventMap> =\n | Listener<HTMLElementEventMap[N]>\n | Listener<any>\n\nfunction invokeHandler<N extends keyof HTMLElementEventMap>(\n handler: SomeListener<N> | Array<SomeListener<N>>,\n vnode: VNode,\n event?: Event,\n): void {\n if (isFunction(handler)) {\n // 如果类型是function,说明只有一个事件监听,将this指向vnode调用\n (handler as Function).call(vnode, event, vnode)\n } else if (typeof handler === 'object') {\n // 如果类型是对象,说明有多个事件监听,遍历依次调用\n for (let i = 0; i < handler.length; i++) {\n invokeHandler(handler[i], vnode, event)\n }\n }\n}\n\nfunction handleEvent(event: Event, vnode: VNode) {\n const name = event.type\n const on = vnode.data && vnode.data.on\n\n // 如果on中存在事件监听,则进行运行\n if (on && on[name]) {\n invokeHandler(on[name], vnode, event)\n }\n}\n\n// 创建一个事件监听的闭包,这样可以确保每次创建的都是一个独立的事件监听\nfunction createListener() {\n return function handler(event: Event) {\n handleEvent(event, (handler as any).vnode)\n }\n}\n\nfunction updateEventListeners(oldVnode: VNode, vnode?: VNode): void {\n // 获取旧VNode中监听的事件\n const oldOn = oldVnode?.data?.on\n // 获取旧VNode中已经创建的监听事件\n const oldListener = oldVnode?.listener\n // 获取旧VNode的dom\n const oldElm: Element = oldVnode.elm as Element\n // 获取新VNode中监听的事件\n const on = vnode?.data?.on\n // 获取新VNode中已经创建的监听事件\n const elm: Element = (vnode && vnode.elm) as Element\n // 缓存遍历中当前事件的名称\n let name: string\n\n // 如果新旧VNode监听事件完全一样,直接返回\n if (oldOn === on) {\n return\n }\n\n // 如果旧VNode中有已经创建的事件监听\n if (oldOn && oldListener) {\n // 如果新VNode中没有事件监听\n if (!on) {\n for (name in oldOn) {\n // 删除旧VNode中的事件监听\n oldElm.removeEventListener(name, oldListener, false)\n }\n } else {\n // 如果新VNode中有事件监听,则遍历旧VNode\n for (name in oldOn) {\n // 如果新VNode中没有当前的事件监听,则删除该事件监听\n if (!on[name]) {\n oldElm.removeEventListener(name, oldListener, false)\n }\n }\n }\n }\n\n // 如果新VNode有事件监听\n if (on) {\n // 如果新VNode上已经存在事件监听,则直接继承,如果没有则创建一个新事件监听\n const listener = vnode.listener = oldVnode.listener || createListener()\n // 更新listener上的vnode\n // listener.vnode = vnode\n\n // 如果旧VNode没有事件监听\n if (!oldOn) {\n // 遍历新VNode上的事件监听\n for (name in on) {\n // 将其添加到dom上\n elm.addEventListener(name, listener, false)\n }\n } else {\n // 如果旧VNode有事件监听\n // 遍历新VNode上的事件监听\n for (name in on) {\n // 将旧VNode上没有的事件监听添加到dom上\n if (!oldOn[name]) {\n elm.addEventListener(name, listener, false)\n }\n }\n }\n }\n}\n\nexport const eventListenersModule = {\n create: updateEventListeners,\n update: updateEventListeners,\n destroy: updateEventListeners,\n}\n","import type { VNode, VNodeData } from '../vnode'\n\nexport type Props = Record<string, any>\n\nfunction updateProps(oldVnode: VNode, vnode: VNode): void {\n // 用于缓存props的name\n let key: string\n // 缓存遍历中当前props的值\n let cur: any\n // 缓存遍历中旧props的值\n let old: any\n // 缓存VNode的dom元素\n const elm = vnode.elm\n // 获取旧VNode的props属性\n let oldProps = oldVnode.data ? oldVnode.data.props : undefined\n // 获取新VNode的props属性\n let props = vnode.data ? vnode.data.props : undefined\n\n // 如果新旧VNode都没有props属性,直接返回\n if (!oldProps && !props) return\n // 如果新旧VNode的props属性完全一样,直接返回\n if (oldProps === props) return\n // 如果旧VNode没有props,将其设置为空对象\n oldProps = oldProps || {}\n // 如果新VNode没有props,将其设置为空对象\n props = props || {}\n\n // 遍历新VNode的props\n for (key in props) {\n // 缓存当前prop属性的值\n cur = props[key]\n // 缓存旧VNode中同名prop的值\n old = oldProps[key]\n // 如果新旧prop值不同,同时当dom是含有value属性的元素(如:input),当前value值和当前prop值不同时,将值设置为当前prop的值\n if (old !== cur && (key !== 'value' || (elm as any)[key] !== cur)) {\n (elm as any)[key] = cur\n }\n }\n}\n\nexport const propsModule = { create: updateProps, update: updateProps }","import type { VNode, VNodeData } from '../vnode'\n\nexport type VNodeStyle = Record<string, any>\n\n/**\n * 在snabbdom中style有三个额外的生命周期delayed, remove和destroy,主要是方便我们css动画的使用,而我们terdom是为了学习虚拟dom\n * 的原理,所以这里我删除这两个生命周期,方便源码的阅读。\n * */\n\nlet reflowForced = false\n\nfunction updateStyle(oldVnode: VNode, vnode: VNode): void {\n // 缓存遍历中当前新VNode中的style\n let cur: any\n // 缓存遍历中当前style的name\n let name: string\n // 获取dom节点\n const elm = vnode.elm\n // 获取旧VNode的style\n let oldStyle = (oldVnode.data as VNodeData).style\n // 获取新VNode的style\n let style = (vnode.data as VNodeData).style\n\n // 如果新旧VNode都没有设置style,直接返回\n if (!oldStyle && !style) return\n // 如果新旧VNode的style完全相同,直接返回\n if (oldStyle === style) return\n // 如果没有旧VNode的style,设置为空对象\n oldStyle = oldStyle || {}\n // 如果没有新VNode的style,设置为空对象\n style = style || {}\n\n // 遍历旧VNode的style\n for (name in oldStyle) {\n // 如果新VNode中没有相同name的style\n if (!style[name]) {\n if (name[0] === '-' && name[1] === '-') {\n // 如果是以 -- 开头,代表是css变量,使用removeProperty删除\n ;(elm as any).style.removeProperty(name)\n } else {\n // 否则直接设为空\n ;(elm as any).style[name] = ''\n }\n }\n }\n\n // 遍历新VNode中的style\n for (name in style) {\n // 缓存当前style的值\n cur = style[name]\n if (cur !== oldStyle[name]) {\n if (name[0] === '-' && name[1] === '-') {\n // 如果是以 -- 开头,代表是css变量,使用setProperty设置\n ;(elm as any).style.setProperty(name, cur)\n } else {\n // 否则直接设置\n ;(elm as any).style[name] = cur\n }\n }\n }\n}\n\nfunction forceReflow(): void {\n reflowForced = false\n}\n\nfunction applyDestroyStyle(vnode: VNode): void {\n let style: any\n let name: string\n const elm = vnode.elm\n const s = (vnode.data as VNodeData).style\n if (!s || !(style = s.destroy)) return\n for (name in style) {\n ;(elm as any).style[name] = style[name]\n }\n}\n\nfunction applyRemoveStyle(vnode: VNode, rm: () => void): void {\n const s = (vnode.data as VNodeData).style\n if (!s || !s.remove) {\n rm()\n return\n }\n if (!reflowForced) {\n ;(vnode.elm as any).offsetLeft\n reflowForced = true\n }\n let name: string\n const elm = vnode.elm\n let i = 0\n const style = s.remove\n let amount = 0\n const applied: string[] = []\n for (name in style) {\n applied.push(name)\n ;(elm as any).style[name] = style[name]\n }\n const compStyle = getComputedStyle(elm as Element)\n const props = (compStyle as any)['transition-property'].split(', ')\n for (; i < props.length; ++i) {\n if (applied.indexOf(props[i]) !== -1) amount++\n }\n ;(elm as any).addEventListener(\n 'transitionend',\n function (ev: TransitionEvent) {\n if (ev.target === elm) --amount\n if (amount === 0) rm()\n },\n )\n}\n\nexport const styleModule = {\n pre: forceReflow,\n create: updateStyle,\n update: updateStyle,\n destroy: applyDestroyStyle,\n remove: applyRemoveStyle,\n}\n","import { attributesModule } from './attributes'\nimport { classModule } from './class'\nimport { eventListenersModule } from './listeners'\nimport { propsModule } from './props'\nimport { styleModule } from './style'\nimport type { VNode } from '@/vnode/vnode'\n\nexport type ModuleHook = any\n\nexport type Modules = {\n [key: string]: {\n [key: string]: ModuleHook\n }\n }\n\nexport const modules: Modules = {\n attributesModule,\n classModule,\n eventListenersModule,\n propsModule,\n styleModule\n}","// 虚拟dom\nimport type { VNode } from './vnode'\nimport { vnode } from './vnode'\n// 引入操作的dom api的相关方法\nimport type { DOMAPI } from './htmlDomApi'\nimport { htmlDomApi } from './htmlDomApi'\n// 类型判断\nimport * as is from './is'\n// 导入模块\nimport type { ModuleHook } from './modules';\nimport { modules } from './modules'\n\ntype NonUndefined<T> = T extends undefined ? never : T\n\ntype KeyToIndexMap = { [key: string]: number }\n\ninterface Cbs {\n [key: string]: ModuleHook[]\n create: Array<ModuleHook>\n update: Array<ModuleHook>\n destroy: Array<(oldVnode: VNode, vnode?: VNode) => void>\n}\n\n// 如果2个VNode节点的key和sel属性都相同,我们就认为它们是相同的VNode节点\nfunction sameVnode(vnode1: VNode, vnode2: VNode): boolean {\n return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel\n}\n\n// 判断是否为Vnode\nfunction isVnode(vnode: any): vnode is VNode {\n return vnode.sel !== undefined\n}\n\n// 根据children item的key属性,创建Key Map\nfunction createKeyToOldIdx(\n children: VNode[],\n beginIdx: number,\n endIdx: number,\n): KeyToIndexMap {\n const map: KeyToIndexMap = {}\n for (let i = beginIdx; i <= endIdx; ++i) {\n const key = children[i]?.key\n if (key !== undefined) {\n map[key] = i\n }\n }\n return map\n}\n\n// 创建一个空白VNode,用于createElm中触发create钩子函数时调用\nconst emptyNode = vnode('', {}, [], undefined, undefined)\n\nexport function init(): (oldVnode: VNode | Element, vnode: VNode) => VNode {\n // 获取操作html dom的api\n const api: DOMAPI = htmlDomApi\n\n // 用于缓存各个模块的钩子函数\n const cbs: Cbs = {\n create: [],\n update: [],\n destroy: [],\n }\n // 遍历cbs\n for (const key of Object.keys(cbs)) {\n // 初始化为数组\n cbs[key] = []\n // 遍历modules\n for (const module of Object.keys(modules)) {\n // 获取模块中对应的生命周期\n const hook = modules[module][key]\n // 如果生命周期有值\n if (hook !== undefined) {\n // 将其加入cbs对应的属性中\n cbs[key].push(hook)\n }\n }\n }\n\n // 创建一个只有标签名和选择器的空白VNode\n function emptyNodeAt(elm: Element) {\n const id = elm.id ? '#' + elm.id : ''\n const c = elm.className ? '.' + elm.className.split(' ').join('.') : ''\n return vnode(\n api.tagName(elm).toLowerCase() + id + c,\n {},\n [],\n undefined,\n elm,\n )\n }\n\n // 判断是否为undefined\n function isUndef(s: unknown): boolean {\n return s === undefined\n }\n\n // 判断是否为defined\n function isDef<A>(s: A): s is NonUndefined<A> {\n return s !== undefined\n }\n\n // 根据VNode创建dom\n function createElm(vnode: VNode): Node {\n // 缓存循环children中的index\n let i: number\n // 缓存VNode的children\n const children = vnode.children\n // 缓存VNode的选择器\n const sel = vnode.sel\n // 把 vnode 转化成真实DOM对象(没有渲染到页面)\n if (sel === '!') {\n // 如果选择器是!,创建注释节点\n if (isUndef(vnode.text)) {\n vnode.text = ''\n }\n vnode.elm = api.createComment(`${vnode.text!}`)\n } else if (sel !== undefined) {\n // 如果选择器不为空,解析选择器\n // 缓存id\n const hashIdx = sel.indexOf('#')\n // 缓存class\n const dotIdx = sel.indexOf('.', hashIdx)\n // 缓存 # 的位置\n const hash = hashIdx > 0 ? hashIdx : sel.length\n // 缓存 . 的位置\n const dot = dotIdx > 0 ? dotIdx : sel.length\n // 缓存标签\n const tag =\n hashIdx !== -1 || dotIdx !== -1\n ? sel.slice(0, Math.min(hash, dot))\n : sel\n // 创建dom\n const elm = (vnode.elm = api.createElement(tag))\n // dom设置id\n if (hash < dot) elm.setAttribute('id', sel.slice(hash + 1, dot))\n // dom设置class\n if (dotIdx > 0)\n elm.setAttribute('class', sel.slice(dot + 1).replace(/\\./g, ' '))\n // 触发各个模块的create钩子函数\n for (i = 0; i < cbs.create.length; ++i) {\n cbs.create[i](emptyNode, vnode)\n }\n // 如果vnode中有子节点,创建子vnode对应的DOM元素并追加到DOM树上\n if (is.array(children)) {\n for (i = 0; i < children.length; ++i) {\n const ch = children[i]\n if (ch != null) {\n api.appendChild(elm, createElm(ch as VNode))\n }\n }\n } else if (is.primitive(vnode.text)) {\n // 如果有子文本节点,也创建并追加到DOM树上\n api.appendChild(elm, api.createTextNode(`${vnode.text!}`))\n }\n } else {\n // 如果选择器为空,创建文本节点\n vnode.elm = api.createTextNode(`${vnode.text!}`)\n }\n // 返回新创建的DOM\n return vnode.elm\n }\n\n // 根据VNode新增dom\n function addVnodes(\n parentElm: Node,\n before: Node | null,\n vnodes: VNode[],\n startIdx: number,\n endIdx: number,\n ) {\n // 遍历传入的VNode数组,创建对应的dom,再将dom插入到指定的dom元素之前\n for (; startIdx <= endIdx; ++startIdx) {\n const ch = vnodes[startIdx]\n if (ch != null) {\n api.insertBefore(parentElm, createElm(ch), before)\n }\n }\n }\n\n // 触发destroy钩子函数\n function invokeDestroyHook(vnode: VNode) {\n // 获取VNode的data属性\n const data = vnode.data\n // 当data不为空时\n if (data !== undefined) {\n // 触发各个模块的destroy钩子函数\n for (let i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)\n // 当VNode有子节点,且子节点不为字符串或数字,触发子节点VNode的destroy钩子函数\n if (vnode.children !== undefined) {\n for (let j = 0; j < vnode.children.length; ++j) {\n const child = vnode.children[j]\n if (\n child != null &&\n typeof child !== 'string' &&\n typeof child !== 'number'\n ) {\n invokeDestroyHook(child)\n }\n }\n }\n }\n }\n\n // 创建删除子节点dom的方法\n function createRmCb(childElm: Node) {\n return function rmCb() {\n // 这里是一个闭包将需要删除的dom节点缓存起来,方便之后调用rmCb方法删除\n const parent = api.parentNode(childElm) as Node\n api.removeChild(parent, childElm)\n }\n }\n\n // 删除VNode对应dom\n function removeVnodes(\n parentElm: Node,\n vnodes: VNode[],\n startIdx: number,\n endIdx: number,\n ): void {\n for (; startIdx <= endIdx; ++startIdx) {\n // 用于缓存删除dom的方法\n let rm: () => void\n // 获取当前要删除节点\n const ch = vnodes[startIdx]\n if (ch != null) {\n if (isDef(ch.sel)) {\n // 触发destroy钩子函数\n invokeDestroyHook(ch)\n /*\n * 在dom中这里需要判断remove钩子函数是否全部调用,而我们dom没有remove钩子函数,所以\n * 不需要判断\n */\n rm = createRmCb(ch.elm!)\n // 删除子节点\n rm()\n } else {\n // 删除文本节点\n api.removeChild(parentElm, ch.elm!)\n }\n }\n }\n }\n\n // 更新children\n function updateChildren(parentElm: Node, oldCh: VNode[], newCh: VNode[]) {\n // 旧VNode的children头索引\n let oldStartIdx = 0\n // 新VNode的children头索引\n let newStartIdx = 0\n // 旧VNode的children尾索引\n let oldEndIdx = oldCh.length - 1\n // 新VNode的children尾索引\n let newEndIdx = newCh.length - 1\n // 旧VNode的children的头VNode\n let oldStartVnode = oldCh[0]\n // 旧VNode的children的尾VNode\n let oldEndVnode = oldCh[oldEndIdx]\n // 新VNode的children的头VNode\n let newStartVnode = newCh[0]\n // 新VNode的children的尾VNode\n let newEndVnode = newCh[newEndIdx]\n // 旧VNode的children的Key Map\n let oldKeyToIdx: KeyToIndexMap | undefined\n // 用于缓存key相同的新旧VNode\n let idxInOld: number\n // 用于缓存将要移动的旧VNode\n let elmToMove: VNode\n // 用于缓存将要插入新增VNode的位置之前的VNode\n let before: any\n\n // 遍历新旧children数组,直到其中之一遍历完\n while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n // 我们之后可能会对oldStartVnode、oldEndVnode、newStartVnode、newEndVnode重新赋值,可能会出现等于null的情况\n if (oldStartVnode == null) {\n oldStartVnode = oldCh[++oldStartIdx]\n } else if (oldEndVnode == null) {\n oldEndVnode = oldCh[--oldEndIdx]\n } else if (newStartVnode == null) {\n newStartVnode = newCh[++newStartIdx]\n } else if (newEndVnode == null) {\n newEndVnode = newCh[--newEndIdx]\n // key 和 sel 相同,则就是相同节点\n } else if (sameVnode(oldStartVnode, newStartVnode)) {\n // 当旧头VNode和新头VNode是相同VNode时,将新头VNode差异更新到旧头VNode上,同时将新旧头索引后移\n // 对比两个节点,如果newVnode有vnodeData,\n // 执行update钩子,更新oldNode上的模块的内容\n // 更新加载过的模块里的内容\n // 判断节点的类型,文本节点直接替换,如果不是文本节点\n // 判断是否有子元素,更新子元素\n patchVnode(oldStartVnode, newStartVnode)\n oldStartVnode = oldCh[++oldStartIdx]\n newStartVnode = newCh[++newStartIdx]\n } else if (sameVnode(oldEndVnode, newEndVnode)) {\n // 当旧尾VNode和新尾VNode是相同VNode时,将新尾VNode差异更新到旧尾VNode上,同时将新旧尾索引前移\n patchVnode(oldEndVnode, newEndVnode)\n oldEndVnode = oldCh[--oldEndIdx]\n newEndVnode = newCh[--newEndIdx]\n } else if (sameVnode(oldStartVnode, newEndVnode)) {\n /**\n * 当旧头VNode和新尾VNode是相同节点时,将新尾VNode差异更新到旧头VNode上,然后将旧头VNode插入到旧尾VNode后\n * 最后将旧头索引后移,新尾索引前移\n */\n patchVnode(oldStartVnode, newEndVnode)\n api.insertBefore(parentElm,oldStartVnode.elm!,api.nextSibling(oldEndVnode.elm!))\n oldStartVnode = oldCh[++oldStartIdx]\n newEndVnode = newCh[--newEndIdx]\n } else if (sameVnode(oldEndVnode, newStartVnode)) {\n /**\n * 当旧尾VNode和新头VNode是相同节点时,将新头VNode差异更新到旧尾VNode上,然后将旧尾VNode插入到旧头VNode前\n * 最后将旧尾索引前移,新头索引后移\n */\n patchVnode(oldEndVnode, newStartVnode)\n api.insertBefore(parentElm, oldEndVnode.elm!, oldStartVnode.elm!)\n oldEndVnode = oldCh[--oldEndIdx]\n newStartVnode = newCh[++newStartIdx]\n } else {\n // 如果没有Key Map则创建Key Map,用于根据key来更新VNode\n if (oldKeyToIdx === undefined) {\n oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)\n }\n // 根据Key Map获取当前新头VNode的对应的旧VNode的index\n idxInOld = oldKeyToIdx[newStartVnode.key as string]\n\n if (isUndef(idxInOld)) {\n // 如果没有设置key属性,直接根据新头VNode创建dom元素,插入到旧头VNode对应dom之前\n api.insertBefore(\n parentElm,\n createElm(newStartVnode),\n oldStartVnode.elm!,\n )\n } else {\n // 如果设置key属性,获取到key对应的旧VNode\n elmToMove = oldCh[idxInOld]\n if (elmToMove.sel !== newStartVnode.sel) {\n // 如果旧VNode和新VNode的sel属性不同,则直接创建新VNode对应的dom,插入到旧头VNode对应dom之前\n api.insertBefore(\n parentElm,\n createElm(newStartVnode),\n oldStartVnode.elm!,\n )\n } else {\n // 如果sel属性相同,则将新VNode数据更新到旧VNode上\n patchVnode(elmToMove, newStartVnode)\n // 删除旧children对应的VNode,代表已经更新过\n oldCh[idxInOld] = undefined as any\n // 创建VNode对应的dom,插入到旧头VNode对应dom之前\n api.insertBefore(parentElm, elmToMove.elm!, oldStartVnode.elm!)\n }\n }\n // 将新头VNode设置为新children数组中新头索引后一位\n newStartVnode = newCh[++newStartIdx]\n }\n }\n // 循环完成后,当旧头索引小于等于旧尾索引,或新头索引大于等于新尾索引时,说明新旧children其中之一已经遍历完成\n if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {\n // 如果存在旧头索引大于旧尾索引情况,说明新children中新增了VNode\n if (oldStartIdx > oldEndIdx) {\n // 获取新增VNode后一位的VNode对应的dom\n before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm\n // 将新增VNode对应dom插入对应dom树位置\n addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx)\n } else {\n // 删除多余dom节点\n removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)\n }\n }\n }\n\n // 对比新旧vnode差异,将差异更新到旧VNode上。\n function patchVnode(oldVnode: VNode, vnode: VNode) {\n // 当VNode的data属性存在时,触发update钩子函数\n if (vnode.data !== undefined) {\n for (let i = 0; i < cbs.update.length; ++i) {\n cbs.update[i](oldVnode, vnode)\n }\n }\n\n // 由于是相同的VNode节点,使用新旧VNode的真实dom元素相同\n const elm = (vnode.elm = oldVnode.elm!)\n // 获取旧VNode的children\n const oldCh = oldVnode.children as VNode[]\n // 获取新VNode的children\n const ch = vnode.children as VNode[]\n\n // 如果新旧节点完全相同,直接返回\n if (oldVnode === vnode) return\n // 判断VNode是否为文本节点\n if (isUndef(vnode.text)) {\n // 如果不是文本节点,判断新旧VNode是否同时有children\n if (isDef(oldCh) && isDef(ch)) {\n // 如果同时有children属性,且children属性不相同就更新children\n if (oldCh !== ch) {\n updateChildren(elm, oldCh, ch)\n }\n }\n }\n }\n\n return function patch(oldVnode: VNode | Element, vnode: VNode): VNode {\n // 缓存dom节点和父dom节点\n let elm: Node, parent: Node\n\n // 当oldVnode不是VNode时,说明是初次加载,创建一个空白VNode\n if (!isVnode(oldVnode)) {\n oldVnode = emptyNodeAt(oldVnode)\n }\n\n // 判断是否为相同VNode节点\n if (sameVnode(oldVnode, vnode)) {\n // 更新VNode节点差异\n patchVnode(oldVnode, vnode)\n } else {\n // 获取旧VNode的dom\n elm = oldVnode.elm!\n // 获取父节点dom\n parent = api.parentNode(elm) as Node\n // 创建dom元素\n createElm(vnode)\n // 当父节点不为空时\n if (parent != null) {\n // 将新创建的dom插入dom树\n api.insertBefore(parent, vnode.elm!, api.nextSibling(elm))\n // 删除旧VNode节点\n removeVnodes(parent, [oldVnode], 0, 0)\n }\n }\n return vnode\n }\n}\n","import type {\n VNode,\n VNodeChildElement,\n VNodeChildren,\n VNodeData,\n VNodes,\n} from './vnode'\nimport { vnode } from './vnode'\n// 类型判断\nimport * as is from './is'\n\nexport function addNS(\n data: VNodeData,\n children: Array<VNode | string | number> |undefined,\n sel: string | undefined,\n): void {\n data.ns = 'http://www.w3.org/2000/svg'\n if (sel !== 'foreignObject' && children !== undefined) {\n for (let i = 0; i < children.length; ++i) {\n const child = children[i]\n if (typeof child === 'string' || typeof child === 'number') continue\n const childData = child.data\n if (childData !== undefined) {\n addNS(childData, child.children as VNodes, child.sel)\n }\n }\n }\n}\n\n// h 函数的重载\nexport function h(sel: string): VNode\nexport function h(sel: string, data: VNodeData | null): VNode\nexport function h(sel: string, children: VNodeChildren): VNode\nexport function h(\n sel: string,\n data: VNodeData | null,\n children: VNodeChildren,\n): VNode\nexport function h(\n sel: string,\n b?: VNodeData | null | VNodeChildren,\n c?: VNodeChildren,\n): VNode {\n // 缓存 VNode 数据\n let data: VNodeData = {}\n // 缓存 children 数据\n let children: VNodeChildElement[] | undefined = undefined\n // 缓存文本数据\n let text: string | number | undefined\n // 用于缓存遍历children的index\n let i: number\n\n // 处理参数,实现重载的机制\n if (c !== undefined) {\n // 处理三个参数的情况\n // sel、data、children/text\n if (b != null) {\n data = b as VNodeData\n }\n if (is.array(c)) {\n children = c\n // 如果c是字符串或者数字\n } else if (is.primitive(c)) {\n text = c\n // 如果c是VNode\n } else if (c && c.sel) {\n children = [c]\n }\n } else if (b !== undefined && b != null) {\n // 处理两个参数的情况\n // 如果b是数组\n if (is.array(b)) {\n children = b\n // 如果b是字符串或数字\n } else if (is.primitive(b)) {\n text = b\n } else {\n // 这里由于b没有使用any类型,所以需要进一步判断b是否为VNode\n if (is.isVnode(b)) {\n children = [b]\n } else {\n data = b\n }\n }\n }\n // 处理 children 中的原始值(string/number)\n if (typeof children !== 'undefined') {\n for (i = 0; i < children.length; ++i) {\n // 如果 child 是string/number,创建文本节点\n // 这里由于children没有使用any类型,所以需要进一步判断children[i]是否为string | number\n // 不能直接使用children[i],所以使用msg缓存\n const msg = children[i]\n if (is.primitive(msg)) {\n children[i] = vnode(undefined, undefined, undefined, msg, undefined)\n }\n }\n }\n if (\n sel[0] === 's' &&\n sel[1] === 'v' &&\n sel[2] === 'g' &&\n (sel.length === 3 || sel[3] === '.' || sel[3] === '#')\n ) {\n addNS(data, children, sel)\n }\n // 符合VNode\n return vnode(sel, data, children, text, undefined)\n}\n","\nexport function querystring(data = {}): string {\n if (typeof data !== \"object\") {\n throw new TypeError(\"param must be object\");\n }\n return Object.entries(data).reduce((searchParams, [name, value]) => value === undefined || value == null ? searchParams : (searchParams.append(decodeURIComponent(name), decodeURIComponent(value)), searchParams), new URLSearchParams()).toString();\n}\n\nexport function randomString(len: number = 8): string {\n const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';\n const maxPos = chars.length;\n let pwd = '';\n for (let i = 0; i < len; i++) {\n pwd += chars.charAt(Math.floor(Math.random() * maxPos))\n }\n return `${Date.now()}-${pwd}`;\n}\n\nexport function getCookie(name: string): string {\n const cookieList = window.document.cookie.match(\n new RegExp(`(^| )${name}(?:=([^;]*))?(;|$)`)\n );\n if (cookieList && cookieList[2]) return cookieList[2];\n return \"\";\n}\n\nexport function createData(params: Record<string, unknown> = {}): Record<string, unknown> {\n return Object.assign({}, {\n id: randomString(),\n path: window.location.href,\n time: Date.now(),\n userAgent: window.navigator.userAgent,\n referrer: document.referrer,\n ip: window.returnCitySN || { cid: \"\", cip: \"\", cname: \"\" },\n userId: getCookie('chaxus_prod')\n }, params)\n}\n\nexport const throttle = (fn: Function, wait: number = 300): Function => {\n let timer: NodeJS.Timeout | null = null;\n return function (this: unknown, ...args: unknown[]) {\n const context = this;\n if (!timer) {\n timer = setTimeout(() => {\n timer = null;\n fn.apply(context, args);\n }, wait);\n }\n };\n};\n\nexport const Noop = ():void => {}\n\nexport function changeHumpToLowerCase(str: string): string { // str ====> fullName\n const arr = str.split(\"\"); // 将字符串用split拆为单个字母为元素的数组,fullName ====> [\"f\", \"u\", \"l\", \"l\", \"N\", \"a\", \"m\", \"e\"]\n const lowerCase = arr.map(val => {\n if (val.toUpperCase() === val) { // 由此判断出,当前字符为大写字母\n return \"_\" + val.toLowerCase(); // 在大写字母前面加上下划线,并将该大写字母转为小写字母\n } else {\n return val;\n }\n });\n // 此时lowerCase =====> [\"f\", \"u\", \"l\", \"l\", \"_n\", \"a\", \"m\", \"e\"]\n str = lowerCase.join(\"\"); // 将数组元素连接起来,不用分隔符,这里必须用\"\" ,若省略的话,join方法会默认用逗号连接\n return str; // 此时,str ====> full_name\n}\n\n/**\n * 重写对象上面的某个属性\n *\n * @export\n * @param {IAnyObject} source 需要被重写的对象\n * @param {string} name 需要被重写对象的key\n * @param {(...args: any[]) => any} replacement 以原有的函数作为参数,执行并重写原有函数\n * @param {boolean} isForced 是否强制重写(可能原先没有该属性)\n */\nexport function replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean): void {\n if (typeof source === \"undefined\") return;\n if (name in source || isForced) {\n const original = source[name];\n const wrapped = replacement(original);\n if (typeof wrapped === 'function') {\n source[name] = wrapped;\n }\n }\n}\n\nexport const isString = (obj: unknown): boolean => {\n return toString.call(obj) === '[object String]';\n}\n\nexport type Hooks = (...args: unknown[]) => void\n","import { Noop } from './utils'\n\nexport const handleClick = (hooks:(event: MouseEvent) => void = Noop): void => {\n document.addEventListener('click', function (event) { hooks(event) }, true);\n}","import { Noop } from './utils'\nimport type { Hooks } from './utils'\n\nexport const handleError = (hooks: Hooks = Noop): void => {\n window.addEventListener('unhandledrejection', (error) => {hooks(error)}, true);\n window.addEventListener('error', (error) => {\n hooks(error)\n return false // 取消默认事件\n }, true) // 捕获阶段\n}\n\n","\ninterface BasicType {\n [x:string]: number | undefined\n dnsSearch: number; // DNS 解析耗时\n tcpConnect: number; // TCP 连接耗时\n sslConnect: number; // SSL安全连接耗时\n request: number; // TTFB 网络请求耗时\n response: number; // 数据传输耗时\n parseDomTree: number; // DOM 解析耗时\n resource: number; // 资源加载耗时\n domReady: number; // DOM Ready\n httpHead: number; // http 头部大小\n interactive: number; // 首次可交互时间\n complete: number; // 页面完全加载\n redirect: number; // 重定向次数\n redirectTime: number; // 重定向耗时\n duration: number; // 资源请求的总耗时 responseEnd-startTime\n fp: number | undefined; // 渲染出第一个像素点,白屏时间\n fcp: number | undefined; // 渲染出第一个内容,首屏结束时间\n}\n\nexport function getPerformance(): BasicType {\n const [performanceNavigationTiming] = performance.getEntriesByType('navigation')\n const [firstPaint, firstContentfulPaint] = performance.getEntriesByType('paint')\n const {\n domainLookupEnd,\n domainLookupStart,\n connectEnd,\n connectStart,\n secureConnectionStart,\n loadEventStart,\n domInteractive,\n domContentLoadedEventEnd,\n duration,\n responseStart,\n requestStart,\n responseEnd,\n fetchStart,\n transferSize,\n encodedBodySize,\n redirectEnd,\n redirectStart,\n redirectCount\n } = performanceNavigationTiming as PerformanceNavigationTiming;\n const { startTime: fp } = firstPaint;\n const { startTime: fcp } = firstContentfulPaint;\n return {\n dnsSearch: domainLookupEnd - domainLookupStart,\n tcpConnect: connectEnd - connectStart,\n sslConnect: connectEnd - secureConnectionStart,\n request: responseStart - requestStart,\n response: responseEnd - responseStart,\n parseDomTree: domInteractive - responseEnd,\n resource: loadEventStart - domContentLoadedEventEnd,\n domReady: domContentLoadedEventEnd - fetchStart,\n interactive: domInteractive - fetchStart,\n complete: loadEventStart - fetchStart,\n httpHead: transferSize - encodedBodySize,\n redirect: redirectCount,\n redirectTime: redirectEnd - redirectStart,\n duration: duration,\n fp: fp,\n fcp: fcp,\n };\n}\n","\nimport { isString } from './utils'\n/**\n * @description: Gets the current environment configuration\n * @return {string}\n */\nexport const getHost = (env?: string): string => {\n let host = ''\n if (env && isString(env)) {\n if (/trunk|neibu|release/.test(env)) {\n host = `.${env}`\n } else if (/test/.test(env)) {\n host = env\n } else if (/prod/.test(env)) {\n host = ''\n } else {\n host = ''\n }\n\n } else {\n const env = /\\w(\\.trunk|\\.neibu|\\.release|test)\\./.exec(\n window.location.hostname\n );\n if (env) {\n host = env[1]\n }\n }\n return host ? `https://log${host}.chaxus.com` : \"https://log.chaxus.com\";\n}","import { querystring } from './utils'\nimport { getHost } from './env'\n\ninterface BeaconPayload {\n url?: string,\n type?: string,\n payload: Record<string, unknown>\n}\n\n\nconst sendBeacon = ({ url = '', type = 'application/json; charset=UTF-8', payload = {} }: BeaconPayload) => {\n const requestUrl = url ? url : getHost()\n if (navigator.sendBeacon) { // 判断sendBeacon是否支持可用\n const param = new Blob([JSON.stringify(payload)], { type });\n return navigator.sendBeacon(requestUrl, param)\n }\n}\n\nconst sendImage = ({ url = \"\", payload = {} }) => {\n const requestUrl = url ? url : getHost()\n const image = new Image();\n image.width = 1;\n image.height = 1;\n image.src = `${requestUrl}?${querystring(payload)}`\n}\n\nexport const report = ({ url = '', type = 'application/json; charset=UTF-8', payload = {} }: BeaconPayload): boolean | undefined | void => {\n const requestUrl = url ? url : getHost()\n if (typeof navigator.sendBeacon !== 'undefined') { // 判断sendBeacon是否支持可用\n return sendBeacon({ url: requestUrl, type, payload })\n }\n return sendImage({ url: requestUrl, payload })\n}","import { Noop, replaceOld } from './utils'\nimport type { Hooks } from './utils'\n\ninterface Options {\n requestHook: Hooks,\n responseHook: Hooks,\n errorHook: Hooks\n}\n/**\n * @description: fetch\n * @param {Partial} options\n */\nexport const handleFetchHook = (options: Partial<Options> = {}): void => {\n if (typeof window !== 'undefined') {\n const { requestHook = Noop, responseHook = Noop, errorHook = Noop } = options\n const replacement = (originalFetch: any) => {\n return (url: string, config?: any) => {\n requestHook(url, config)\n return originalFetch.apply(window, [url, config])\n .then((response: Response) => {\n responseHook(url, config, response)\n return response\n })\n .catch((error: Error) => {\n errorHook(url, error)\n throw error;\n })\n }\n }\n replaceOld(window, 'fetch', replacement)\n }\n}\n/**\n * @description: xhr\n * @param {Partial} options\n * @return {*}\n */\nexport const handleXhrHook = (options: Partial<Options> = {}): void => {\n const originalXhrProto = XMLHttpRequest.prototype;\n const { requestHook = Noop, responseHook = Noop, errorHook = Noop } = options\n const replacementXhrOpen = (originalOpen: any) => {\n return function (this: XMLHttpRequest, ...args: unknown[]): void {\n requestHook(args)\n originalOpen.apply(this, args);\n };\n }\n replaceOld(originalXhrProto, 'open', replacementXhrOpen);\n const replacementXhrSend = (originalSend: any) => {\n return function (this: any, ...args: any[]): void {\n this.addEventListener('loadend', function (this: unknown) {\n responseHook(this)\n });\n this.addEventListener('error', function (this: unknown) {\n errorHook(this)\n });\n originalSend.apply(this, args);\n };\n }\n replaceOld(originalXhrProto, 'send', replacementXhrSend);\n}\n","import { handleClick } from './behavior'\nimport { handleError } from './error'\nimport { getPerformance } from './performance'\nimport { createData, throttle } from './utils'\nimport { report } from './report'\nimport { handleFetchHook, handleXhrHook } from './request'\n\nexport interface Payload {\n payload: Record<string, unknown>,\n type?: string\n}\nclass Monitor {\n /**\n * @description: 页面加载性能上报\n * @param {Payload} param1\n */\n reportPerformance(): void {\n const params = getPerformance()\n const payload = createData()\n report({\n payload: {\n ...params,\n ...payload\n }\n })\n }\n /**\n * @description: 手动触发的上报\n * @param {Record} payload\n * @param {*} unknown\n */\n log(payload: Record<string, unknown>): void {\n report({ payload })\n }\n /**\n * @description: 点击上报\n * @return {*}\n */\n reportClick(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const hook = (event: MouseEvent) => {\n throttleReport({ payload: { ...payload, event, type: 'click' } })\n }\n handleClick(hook)\n }\n // ajax 上报\n reportXhr(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const requestHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'xhrRequest' } })\n }\n const responseHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'xhrResponse' } })\n }\n const errorHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'xhrError' } })\n }\n handleXhrHook({ requestHook, responseHook, errorHook })\n }\n reportFetch(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const requestHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'fetchRequest' } })\n }\n const responseHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'fetchResponse' } })\n }\n const errorHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'fetchError' } })\n }\n handleFetchHook({ requestHook, responseHook, errorHook })\n }\n reportError(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const hook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'error' } })\n }\n handleError(hook)\n }\n}\n\nexport default Monitor","import writeFile from './src/file/writeFile'\nimport readFile from './src/file/readFile'\nimport watchFile from './src/file/watchFile'\nimport EventEmitter from './src/mode/subscribe'\nimport queryFileInfo from './src/file/fileInfo'\nimport filterObj from './src/utils/filterObj'\nimport readDir from './src/file/readDir'\nimport str2Xml from './src/utils/str2Xml'\nimport { init } from '@/vnode/init'\nimport { h } from '@/vnode/h'\nimport Monitor from '@/ranlog'\n\nconst vnode = {\n init,\n h\n}\n\nexport {\n writeFile,\n readFile,\n watchFile,\n EventEmitter,\n queryFileInfo,\n filterObj,\n str2Xml,\n readDir,\n vnode,\n Monitor\n}\n"],"names":["fs","vnode","tagName","parentNode","isVnode","is.array","is.primitive","is.isVnode","env"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.umd.cjs","sources":["../src/file/fs.ts","../src/vnode/vnode.ts","../src/vnode/htmlDomApi.ts","../src/vnode/is.ts","../src/vnode/modules/attributes.ts","../src/vnode/modules/class.ts","../src/vnode/modules/listeners.ts","../src/vnode/modules/props.ts","../src/vnode/modules/style.ts","../src/vnode/modules/index.ts","../src/vnode/init.ts","../src/vnode/h.ts","../src/ranlog/utils.ts","../src/ranlog/env.ts","../src/ranlog/report.ts","../src/ranlog/request.ts","../index.ts","../src/mode/subscribe.ts","../src/ranlog/index.ts","../src/ranlog/performance.ts","../src/ranlog/behavior.ts","../src/ranlog/error.ts","../src/utils/filterObj.ts","../src/file/fileInfo.ts","../src/file/readDir.ts","../src/file/readFile.ts","../src/utils/str2Xml.ts","../src/file/watchFile.ts","../src/file/writeFile.ts"],"sourcesContent":["const fs = {}\nlet fileSystem: any = fs\nif (typeof process !== 'undefined' && typeof fileSystem.Stats === 'function') {\n fileSystem._identification = true\n} else {\n fileSystem = { _identification: false, message: 'require is not defined' }\n}\n\nexport default fileSystem\n","import type { On } from './modules/listeners'\nimport type { Attrs } from './modules/attributes'\nimport type { Classes } from './modules/class'\nimport type { Props } from './modules/props'\nimport type { VNodeStyle } from './modules/style'\nimport type { Hooks } from \"./hooks\";\n\n\nexport type VNodes = VNode[]\nexport type VNodeChildElement = VNode | string | number\nexport type ArrayOrElement<T> = T | T[]\nexport type VNodeChildren = ArrayOrElement<VNodeChildElement>\n\n// key属性类型\nexport type Key = string | number\n\ntype Listener<T> = (this: VNode, ev: T, vnode: VNode) => void\n\n// VNode接口\nexport interface VNode {\n // dom节点的选择器,\n // 虚拟节点的 .sel 属性通过对 h() 传入一个 CSS 选择器生成,\n // 比如: h('div#container', {}, [...]) 将会创建一个虚拟节点并以 div#container 作为其 .sel 属性的值。\n sel: string | undefined\n // 节点数据\n data: VNodeData | undefined\n // 子节点,和text互斥\n children: Array<VNode | string | number> | undefined\n // 存储VNode转化成的真实dom\n elm: Node | undefined\n // 节点的文本内容,和children互斥\n text: string | number | undefined\n // key,用于优化diff算法\n key: Key | undefined\n listener?: EventListenerOrEventListenerObject | undefined\n}\n\nexport interface VNodeData {\n // 设置VNode对应的DOM元素的属性,通过 对象.属性 的方式来设置,它内部不会去处理布尔类型的属性\n props?: Props\n // 设置VNode对应的DOM元素的属性,通过 setAttributes 来设置,它内部不会去处理布尔类型的属性\n attrs?: Attrs\n // 设置VNode对应的DOM元素的class\n class?: Classes\n // 设置VNode对应的DOM元素的css style\n style?: VNodeStyle\n // 设置VNode对应的DOM元素的监听事件\n on?: On\n // 设置VNode对应的key\n key?: Key\n // svg元素\n ns?: string\n hook?: Hooks\n}\n\nexport function vnode(\n sel: string | undefined,\n data: any | undefined,\n children: Array<VNode | string | number> | undefined,\n text: string | number | undefined,\n elm: Element | Text | undefined,\n): VNode {\n const key = data === undefined ? undefined : data.key\n return { sel, data, children, text, elm, key }\n}\n","export interface Fragment extends DocumentFragment {\n parent: Node | null\n firstChildNode: ChildNode | null\n lastChildNode: ChildNode | null\n}\n\nexport interface DOMAPI {\n // 创建元素节点\n createElement: (tagName: any, options?: ElementCreationOptions) => HTMLElement\n createElementNS: (\n namespaceURI: string,\n qualifiedName: string,\n options?: ElementCreationOptions,\n ) => Element\n /**\n * @experimental\n * @todo Make it required when the fragment is considered stable.\n */\n createDocumentFragment?: () => Fragment\n // 创建文本节点\n createTextNode: (text: string) => Text\n // 创建注释节点\n createComment: (text: string) => Comment\n // 在指定的已有子节点之前插入新的子节点。\n insertBefore: (\n parentNode: Node,\n newNode: Node,\n referenceNode: Node | null,\n ) => void\n // 删除子节点\n removeChild: (node: Node, child: Node) => void\n // 添加子节点\n appendChild: (node: Node, child: Node) => void\n // 获取元素父节点\n parentNode: (node: Node) => Node | null\n // 获取元素紧跟的节点\n nextSibling: (node: Node) => Node | null\n // 获取元素标签名\n tagName: (elm: Element) => string\n // 设置元素文本内容\n setTextContent: (node: Node, text: string | null) => void\n // 获取元素文本内容\n getTextContent: (node: Node) => string | null\n // 判定是否为元素节点\n isElement: (node: Node) => node is Element\n // 判定是否为文本节点\n isText: (node: Node) => node is Text\n // 判定是否为注释节点\n isComment: (node: Node) => node is Comment\n /**\n * @experimental\n * @todo Make it required when the fragment is considered stable.\n */\n isDocumentFragment?: (node: Node) => node is DocumentFragment\n}\n\nfunction createElement(\n tagName: any,\n options?: ElementCreationOptions,\n): HTMLElement {\n return document.createElement(tagName, options)\n}\n\nfunction createElementNS(\n namespaceURI: string,\n qualifiedName: string,\n options?: ElementCreationOptions,\n): Element {\n return document.createElementNS(namespaceURI, qualifiedName, options)\n}\n\nfunction createDocumentFragment(): Fragment {\n return parseFragment(document.createDocumentFragment())\n}\n\nfunction createTextNode(text: string): Text {\n return document.createTextNode(text)\n}\n\nfunction createComment(text: string): Comment {\n return document.createComment(text)\n}\n\nfunction insertBefore(\n parentNode: Node,\n newNode: Node,\n referenceNode: Node | null,\n): void {\n if (isDocumentFragment(parentNode)) {\n let node: Node | null = parentNode\n while (node && isDocumentFragment(node)) {\n const fragment = parseFragment(node)\n node = fragment.parent\n }\n parentNode = node ?? parentNode\n }\n if (isDocumentFragment(newNode)) {\n newNode = parseFragment(newNode, parentNode)\n }\n if (referenceNode && isDocumentFragment(referenceNode)) {\n referenceNode = parseFragment(referenceNode).firstChildNode\n }\n parentNode.insertBefore(newNode, referenceNode)\n}\n\nfunction removeChild(node: Node, child: Node): void {\n node.removeChild(child)\n}\n\nfunction appendChild(node: Node, child: Node): void {\n if (isDocumentFragment(child)) {\n child = parseFragment(child, node)\n }\n node.appendChild(child)\n}\n\nfunction parentNode(node: Node): Node | null {\n if (isDocumentFragment(node)) {\n while (node && isDocumentFragment(node)) {\n const fragment = parseFragment(node)\n node = fragment.parent as Node\n }\n return node ?? null\n }\n return node.parentNode\n}\n\nfunction nextSibling(node: Node): Node | null {\n if (isDocumentFragment(node)) {\n const fragment = parseFragment(node)\n const parent = parentNode(fragment)\n if (parent && fragment.lastChildNode) {\n const children = Array.from(parent.childNodes)\n const index = children.indexOf(fragment.lastChildNode)\n return children[index + 1] ?? null\n }\n return null\n }\n return node.nextSibling\n}\n\nfunction tagName(elm: Element): string {\n return elm.tagName\n}\n\nfunction setTextContent(node: Node, text: string | null): void {\n node.textContent = text\n}\n\nfunction getTextContent(node: Node): string | null {\n return node.textContent\n}\n\nfunction isElement(node: Node): node is Element {\n return node.nodeType === 1\n}\n\nfunction isText(node: Node): node is Text {\n return node.nodeType === 3\n}\n\nfunction isComment(node: Node): node is Comment {\n return node.nodeType === 8\n}\n\nfunction isDocumentFragment(node: Node): node is DocumentFragment {\n return node.nodeType === 11\n}\n\nfunction parseFragment(\n fragmentNode: DocumentFragment,\n parentNode?: Node | null,\n): Fragment {\n const fragment = fragmentNode as Fragment\n fragment.parent ??= parentNode ?? null\n fragment.firstChildNode ??= fragmentNode.firstChild\n fragment.lastChildNode ??= fragmentNode.lastChild\n return fragment\n}\n\nexport const htmlDomApi: DOMAPI = {\n createElement,\n createElementNS,\n createTextNode,\n createDocumentFragment,\n createComment,\n insertBefore,\n removeChild,\n appendChild,\n parentNode,\n nextSibling,\n tagName,\n setTextContent,\n getTextContent,\n isElement,\n isText,\n isComment,\n isDocumentFragment,\n}\n","import type { VNode } from './vnode'\n\n// 判断是否为数组\nexport const array = Array.isArray\n\nexport const isStr = (str: unknown): str is string => {\n return typeof str === 'string'\n}\n// 判断是否为字符串或数字\nexport function primitive(s: unknown): s is string | number {\n return typeof s === 'string' || typeof s === 'number'\n}\n// 判断是否为vnode\nexport function isVnode(s: any): s is VNode {\n return !!s?.sel\n}\n\n","import type { VNode, VNodeData } from '../vnode'\n\nexport type Attrs = Record<string, string | number | boolean>\n\nconst xlinkNS = 'http://www.w3.org/1999/xlink'\nconst xmlNS = 'http://www.w3.org/XML/1998/namespace'\nconst colonChar = 58\nconst xChar = 120\n\nfunction updateAttrs(oldVnode: VNode, vnode: VNode): void {\n // 用于缓存attrs的name\n let key: string\n // 用于缓存Vnode的dom\n const elm: Element = vnode.elm as Element\n // 用于缓存旧VNode的attrs\n let oldAttrs = oldVnode.data && oldVnode.data.attrs\n // 用于缓存新VNode的attrs\n let attrs = vnode.data && vnode.data.attrs\n\n // 如果新旧VNode都没有attrs属性,直接返回\n if (!oldAttrs && !attrs) return\n // 如果新旧VNode的attrs属性相同,直接返回\n if (oldAttrs === attrs) return\n // 如果旧VNode没有attrs,将其设置为空对象\n oldAttrs = oldAttrs || {}\n // 如果新VNode没有attrs,将其设置为空对象\n attrs = attrs || {}\n\n // 遍历新VNode的attrs\n for (key in attrs) {\n // 获取当前attrs的值\n const cur = attrs[key]\n // 获取旧VNode对应的attrs的值\n const old = oldAttrs[key]\n // 如果新旧VNode的attrs值不相同\n if (old !== cur) {\n // 如果新VNode的attrs值为true\n if (cur === true) {\n // 通过setAttribute设置为空字符串\n elm.setAttribute(key, '')\n } else if (cur === false) {\n // 如果新VNode的attrs值为false,则删除key\n elm.removeAttribute(key)\n } else {\n // 设置svg的属性\n if (key.charCodeAt(0) !== xChar) {\n elm.setAttribute(key, cur as any)\n } else if (key.charCodeAt(3) === colonChar) {\n // Assume xml namespace\n elm.setAttributeNS(xmlNS, key, cur as any)\n } else if (key.charCodeAt(5) === colonChar) {\n // Assume xlink namespace\n elm.setAttributeNS(xlinkNS, key, cur as any)\n } else {\n // 通过setAttribute设置值\n elm.setAttribute(key, `${cur}`)\n }\n }\n }\n }\n // 遍历旧VNode的attrs\n for (key in oldAttrs) {\n // 如果新VNode的attrs中没有相同的key,则直接删除该attrs属性\n if (!(key in attrs)) {\n elm.removeAttribute(key)\n }\n }\n}\n\nexport const attributesModule = { create: updateAttrs, update: updateAttrs }\n","import type { VNode, VNodeData } from '../vnode'\n\nexport type Classes = Record<string, boolean>\n\nfunction updateClass(oldVnode: VNode, vnode: VNode): void {\n // 用于缓存遍历中当前class属性的值\n let cur: any\n // 用于缓存遍历中当前class的name\n let name: string\n // 获取新VNode的dom元素\n const elm: Element = vnode.elm as Element\n // 获取旧VNode的class数据\n let oldClass = oldVnode.data && oldVnode.data.class\n // 获取新VNode的class数据\n let className = vnode.data && vnode.data.class\n\n // 如果新旧VNode都没有class,直接返回\n if (!oldClass && !className) return\n // 如果新旧VNode完全相同,直接返回\n if (oldClass === className) return\n // 如果旧VNode没有class,将其设置为空对象\n oldClass = oldClass || {}\n // 如果新VNode没有class,将其设置为空对象\n className = className || {}\n\n // 遍历旧VNode的class\n for (name in oldClass) {\n // 如果当前class旧VNode上有但新VNode没有,则删除该VNode\n if (\n oldClass[name] &&\n !Object.prototype.hasOwnProperty.call(className, name)\n ) {\n elm.classList.remove(name)\n }\n }\n // 遍历新Vnodde的class\n for (name in className) {\n // 如果新旧VNode的class值不同,则根据新VNode的class值是true or false来判断是新增还是删除class\n cur = className[name]\n if (cur !== oldClass[name]) {\n (elm.classList as any)[cur ? 'add' : 'remove'](name)\n }\n }\n}\n\nexport const classModule = { create: updateClass, update: updateClass }","import type { VNode, VNodeData } from '../vnode'\n\nconst isFunction = (handler: unknown): handler is Function => {\n return typeof handler === 'function'\n}\n\ntype Listener<T> = (this: VNode, ev: T, vnode: VNode) => void\n\nexport type On = {\n [N in keyof HTMLElementEventMap]?:\n | Listener<HTMLElementEventMap[N]>\n | Array<Listener<HTMLElementEventMap[N]>>\n} & {\n [event: string]: Listener<any> | Array<Listener<any>>\n}\n\ntype SomeListener<N extends keyof HTMLElementEventMap> =\n | Listener<HTMLElementEventMap[N]>\n | Listener<any>\n\nfunction invokeHandler<N extends keyof HTMLElementEventMap>(\n handler: SomeListener<N> | Array<SomeListener<N>>,\n vnode: VNode,\n event?: Event,\n): void {\n if (isFunction(handler)) {\n // 如果类型是function,说明只有一个事件监听,将this指向vnode调用\n (handler as Function).call(vnode, event, vnode)\n } else if (typeof handler === 'object') {\n // 如果类型是对象,说明有多个事件监听,遍历依次调用\n for (let i = 0; i < handler.length; i++) {\n invokeHandler(handler[i], vnode, event)\n }\n }\n}\n\nfunction handleEvent(event: Event, vnode: VNode) {\n const name = event.type\n const on = vnode.data && vnode.data.on\n\n // 如果on中存在事件监听,则进行运行\n if (on && on[name]) {\n invokeHandler(on[name], vnode, event)\n }\n}\n\n// 创建一个事件监听的闭包,这样可以确保每次创建的都是一个独立的事件监听\nfunction createListener() {\n return function handler(event: Event) {\n handleEvent(event, (handler as any).vnode)\n }\n}\n\nfunction updateEventListeners(oldVnode: VNode, vnode?: VNode): void {\n // 获取旧VNode中监听的事件\n const oldOn = oldVnode?.data?.on\n // 获取旧VNode中已经创建的监听事件\n const oldListener = oldVnode?.listener\n // 获取旧VNode的dom\n const oldElm: Element = oldVnode.elm as Element\n // 获取新VNode中监听的事件\n const on = vnode?.data?.on\n // 获取新VNode中已经创建的监听事件\n const elm: Element = (vnode && vnode.elm) as Element\n // 缓存遍历中当前事件的名称\n let name: string\n\n // 如果新旧VNode监听事件完全一样,直接返回\n if (oldOn === on) {\n return\n }\n\n // 如果旧VNode中有已经创建的事件监听\n if (oldOn && oldListener) {\n // 如果新VNode中没有事件监听\n if (!on) {\n for (name in oldOn) {\n // 删除旧VNode中的事件监听\n oldElm.removeEventListener(name, oldListener, false)\n }\n } else {\n // 如果新VNode中有事件监听,则遍历旧VNode\n for (name in oldOn) {\n // 如果新VNode中没有当前的事件监听,则删除该事件监听\n if (!on[name]) {\n oldElm.removeEventListener(name, oldListener, false)\n }\n }\n }\n }\n\n // 如果新VNode有事件监听\n if (on) {\n // 如果新VNode上已经存在事件监听,则直接继承,如果没有则创建一个新事件监听\n const listener = vnode.listener = oldVnode.listener || createListener()\n // 更新listener上的vnode\n // listener.vnode = vnode\n\n // 如果旧VNode没有事件监听\n if (!oldOn) {\n // 遍历新VNode上的事件监听\n for (name in on) {\n // 将其添加到dom上\n elm.addEventListener(name, listener, false)\n }\n } else {\n // 如果旧VNode有事件监听\n // 遍历新VNode上的事件监听\n for (name in on) {\n // 将旧VNode上没有的事件监听添加到dom上\n if (!oldOn[name]) {\n elm.addEventListener(name, listener, false)\n }\n }\n }\n }\n}\n\nexport const eventListenersModule = {\n create: updateEventListeners,\n update: updateEventListeners,\n destroy: updateEventListeners,\n}\n","import type { VNode, VNodeData } from '../vnode'\n\nexport type Props = Record<string, any>\n\nfunction updateProps(oldVnode: VNode, vnode: VNode): void {\n // 用于缓存props的name\n let key: string\n // 缓存遍历中当前props的值\n let cur: any\n // 缓存遍历中旧props的值\n let old: any\n // 缓存VNode的dom元素\n const elm = vnode.elm\n // 获取旧VNode的props属性\n let oldProps = oldVnode.data ? oldVnode.data.props : undefined\n // 获取新VNode的props属性\n let props = vnode.data ? vnode.data.props : undefined\n\n // 如果新旧VNode都没有props属性,直接返回\n if (!oldProps && !props) return\n // 如果新旧VNode的props属性完全一样,直接返回\n if (oldProps === props) return\n // 如果旧VNode没有props,将其设置为空对象\n oldProps = oldProps || {}\n // 如果新VNode没有props,将其设置为空对象\n props = props || {}\n\n // 遍历新VNode的props\n for (key in props) {\n // 缓存当前prop属性的值\n cur = props[key]\n // 缓存旧VNode中同名prop的值\n old = oldProps[key]\n // 如果新旧prop值不同,同时当dom是含有value属性的元素(如:input),当前value值和当前prop值不同时,将值设置为当前prop的值\n if (old !== cur && (key !== 'value' || (elm as any)[key] !== cur)) {\n (elm as any)[key] = cur\n }\n }\n}\n\nexport const propsModule = { create: updateProps, update: updateProps }","import type { VNode, VNodeData } from '../vnode'\n\nexport type VNodeStyle = Record<string, any>\n\n/**\n * 在snabbdom中style有三个额外的生命周期delayed, remove和destroy,主要是方便我们css动画的使用,而我们terdom是为了学习虚拟dom\n * 的原理,所以这里我删除这两个生命周期,方便源码的阅读。\n * */\n\nlet reflowForced = false\n\nfunction updateStyle(oldVnode: VNode, vnode: VNode): void {\n // 缓存遍历中当前新VNode中的style\n let cur: any\n // 缓存遍历中当前style的name\n let name: string\n // 获取dom节点\n const elm = vnode.elm\n // 获取旧VNode的style\n let oldStyle = (oldVnode.data as VNodeData).style\n // 获取新VNode的style\n let style = (vnode.data as VNodeData).style\n\n // 如果新旧VNode都没有设置style,直接返回\n if (!oldStyle && !style) return\n // 如果新旧VNode的style完全相同,直接返回\n if (oldStyle === style) return\n // 如果没有旧VNode的style,设置为空对象\n oldStyle = oldStyle || {}\n // 如果没有新VNode的style,设置为空对象\n style = style || {}\n\n // 遍历旧VNode的style\n for (name in oldStyle) {\n // 如果新VNode中没有相同name的style\n if (!style[name]) {\n if (name[0] === '-' && name[1] === '-') {\n // 如果是以 -- 开头,代表是css变量,使用removeProperty删除\n ;(elm as any).style.removeProperty(name)\n } else {\n // 否则直接设为空\n ;(elm as any).style[name] = ''\n }\n }\n }\n\n // 遍历新VNode中的style\n for (name in style) {\n // 缓存当前style的值\n cur = style[name]\n if (cur !== oldStyle[name]) {\n if (name[0] === '-' && name[1] === '-') {\n // 如果是以 -- 开头,代表是css变量,使用setProperty设置\n ;(elm as any).style.setProperty(name, cur)\n } else {\n // 否则直接设置\n ;(elm as any).style[name] = cur\n }\n }\n }\n}\n\nfunction forceReflow(): void {\n reflowForced = false\n}\n\nfunction applyDestroyStyle(vnode: VNode): void {\n let style: any\n let name: string\n const elm = vnode.elm\n const s = (vnode.data as VNodeData).style\n if (!s || !(style = s.destroy)) return\n for (name in style) {\n ;(elm as any).style[name] = style[name]\n }\n}\n\nfunction applyRemoveStyle(vnode: VNode, rm: () => void): void {\n const s = (vnode.data as VNodeData).style\n if (!s || !s.remove) {\n rm()\n return\n }\n if (!reflowForced) {\n ;(vnode.elm as any).offsetLeft\n reflowForced = true\n }\n let name: string\n const elm = vnode.elm\n let i = 0\n const style = s.remove\n let amount = 0\n const applied: string[] = []\n for (name in style) {\n applied.push(name)\n ;(elm as any).style[name] = style[name]\n }\n const compStyle = getComputedStyle(elm as Element)\n const props = (compStyle as any)['transition-property'].split(', ')\n for (; i < props.length; ++i) {\n if (applied.indexOf(props[i]) !== -1) amount++\n }\n ;(elm as any).addEventListener(\n 'transitionend',\n function (ev: TransitionEvent) {\n if (ev.target === elm) --amount\n if (amount === 0) rm()\n },\n )\n}\n\nexport const styleModule = {\n pre: forceReflow,\n create: updateStyle,\n update: updateStyle,\n destroy: applyDestroyStyle,\n remove: applyRemoveStyle,\n}\n","import { attributesModule } from './attributes'\nimport { classModule } from './class'\nimport { eventListenersModule } from './listeners'\nimport { propsModule } from './props'\nimport { styleModule } from './style'\nimport type { VNode } from '@/vnode/vnode'\n\nexport type ModuleHook = any\n\nexport type Modules = {\n [key: string]: {\n [key: string]: ModuleHook\n }\n }\n\nexport const modules: Modules = {\n attributesModule,\n classModule,\n eventListenersModule,\n propsModule,\n styleModule\n}","// 虚拟dom\nimport type { VNode } from './vnode'\nimport { vnode } from './vnode'\n// 引入操作的dom api的相关方法\nimport type { DOMAPI } from './htmlDomApi'\nimport { htmlDomApi } from './htmlDomApi'\n// 类型判断\nimport * as is from './is'\n// 导入模块\nimport type { ModuleHook } from './modules';\nimport { modules } from './modules'\n\ntype NonUndefined<T> = T extends undefined ? never : T\n\ntype KeyToIndexMap = { [key: string]: number }\n\ninterface Cbs {\n [key: string]: ModuleHook[]\n create: Array<ModuleHook>\n update: Array<ModuleHook>\n destroy: Array<(oldVnode: VNode, vnode?: VNode) => void>\n}\n\n// 如果2个VNode节点的key和sel属性都相同,我们就认为它们是相同的VNode节点\nfunction sameVnode(vnode1: VNode, vnode2: VNode): boolean {\n return vnode1.key === vnode2.key && vnode1.sel === vnode2.sel\n}\n\n// 判断是否为Vnode\nfunction isVnode(vnode: any): vnode is VNode {\n return vnode.sel !== undefined\n}\n\n// 根据children item的key属性,创建Key Map\nfunction createKeyToOldIdx(\n children: VNode[],\n beginIdx: number,\n endIdx: number,\n): KeyToIndexMap {\n const map: KeyToIndexMap = {}\n for (let i = beginIdx; i <= endIdx; ++i) {\n const key = children[i]?.key\n if (key !== undefined) {\n map[key] = i\n }\n }\n return map\n}\n\n// 创建一个空白VNode,用于createElm中触发create钩子函数时调用\nconst emptyNode = vnode('', {}, [], undefined, undefined)\n\nexport function init(): (oldVnode: VNode | Element, vnode: VNode) => VNode {\n // 获取操作html dom的api\n const api: DOMAPI = htmlDomApi\n\n // 用于缓存各个模块的钩子函数\n const cbs: Cbs = {\n create: [],\n update: [],\n destroy: [],\n }\n // 遍历cbs\n for (const key of Object.keys(cbs)) {\n // 初始化为数组\n cbs[key] = []\n // 遍历modules\n for (const module of Object.keys(modules)) {\n // 获取模块中对应的生命周期\n const hook = modules[module][key]\n // 如果生命周期有值\n if (hook !== undefined) {\n // 将其加入cbs对应的属性中\n cbs[key].push(hook)\n }\n }\n }\n\n // 创建一个只有标签名和选择器的空白VNode\n function emptyNodeAt(elm: Element) {\n const id = elm.id ? '#' + elm.id : ''\n const c = elm.className ? '.' + elm.className.split(' ').join('.') : ''\n return vnode(\n api.tagName(elm).toLowerCase() + id + c,\n {},\n [],\n undefined,\n elm,\n )\n }\n\n // 判断是否为undefined\n function isUndef(s: unknown): boolean {\n return s === undefined\n }\n\n // 判断是否为defined\n function isDef<A>(s: A): s is NonUndefined<A> {\n return s !== undefined\n }\n\n // 根据VNode创建dom\n function createElm(vnode: VNode): Node {\n // 缓存循环children中的index\n let i: number\n // 缓存VNode的children\n const children = vnode.children\n // 缓存VNode的选择器\n const sel = vnode.sel\n // 把 vnode 转化成真实DOM对象(没有渲染到页面)\n if (sel === '!') {\n // 如果选择器是!,创建注释节点\n if (isUndef(vnode.text)) {\n vnode.text = ''\n }\n vnode.elm = api.createComment(`${vnode.text!}`)\n } else if (sel !== undefined) {\n // 如果选择器不为空,解析选择器\n // 缓存id\n const hashIdx = sel.indexOf('#')\n // 缓存class\n const dotIdx = sel.indexOf('.', hashIdx)\n // 缓存 # 的位置\n const hash = hashIdx > 0 ? hashIdx : sel.length\n // 缓存 . 的位置\n const dot = dotIdx > 0 ? dotIdx : sel.length\n // 缓存标签\n const tag =\n hashIdx !== -1 || dotIdx !== -1\n ? sel.slice(0, Math.min(hash, dot))\n : sel\n // 创建dom\n const elm = (vnode.elm = api.createElement(tag))\n // dom设置id\n if (hash < dot) elm.setAttribute('id', sel.slice(hash + 1, dot))\n // dom设置class\n if (dotIdx > 0)\n elm.setAttribute('class', sel.slice(dot + 1).replace(/\\./g, ' '))\n // 触发各个模块的create钩子函数\n for (i = 0; i < cbs.create.length; ++i) {\n cbs.create[i](emptyNode, vnode)\n }\n // 如果vnode中有子节点,创建子vnode对应的DOM元素并追加到DOM树上\n if (is.array(children)) {\n for (i = 0; i < children.length; ++i) {\n const ch = children[i]\n if (ch != null) {\n api.appendChild(elm, createElm(ch as VNode))\n }\n }\n } else if (is.primitive(vnode.text)) {\n // 如果有子文本节点,也创建并追加到DOM树上\n api.appendChild(elm, api.createTextNode(`${vnode.text!}`))\n }\n } else {\n // 如果选择器为空,创建文本节点\n vnode.elm = api.createTextNode(`${vnode.text!}`)\n }\n // 返回新创建的DOM\n return vnode.elm\n }\n\n // 根据VNode新增dom\n function addVnodes(\n parentElm: Node,\n before: Node | null,\n vnodes: VNode[],\n startIdx: number,\n endIdx: number,\n ) {\n // 遍历传入的VNode数组,创建对应的dom,再将dom插入到指定的dom元素之前\n for (; startIdx <= endIdx; ++startIdx) {\n const ch = vnodes[startIdx]\n if (ch != null) {\n api.insertBefore(parentElm, createElm(ch), before)\n }\n }\n }\n\n // 触发destroy钩子函数\n function invokeDestroyHook(vnode: VNode) {\n // 获取VNode的data属性\n const data = vnode.data\n // 当data不为空时\n if (data !== undefined) {\n // 触发各个模块的destroy钩子函数\n for (let i = 0; i < cbs.destroy.length; ++i) cbs.destroy[i](vnode)\n // 当VNode有子节点,且子节点不为字符串或数字,触发子节点VNode的destroy钩子函数\n if (vnode.children !== undefined) {\n for (let j = 0; j < vnode.children.length; ++j) {\n const child = vnode.children[j]\n if (\n child != null &&\n typeof child !== 'string' &&\n typeof child !== 'number'\n ) {\n invokeDestroyHook(child)\n }\n }\n }\n }\n }\n\n // 创建删除子节点dom的方法\n function createRmCb(childElm: Node) {\n return function rmCb() {\n // 这里是一个闭包将需要删除的dom节点缓存起来,方便之后调用rmCb方法删除\n const parent = api.parentNode(childElm) as Node\n api.removeChild(parent, childElm)\n }\n }\n\n // 删除VNode对应dom\n function removeVnodes(\n parentElm: Node,\n vnodes: VNode[],\n startIdx: number,\n endIdx: number,\n ): void {\n for (; startIdx <= endIdx; ++startIdx) {\n // 用于缓存删除dom的方法\n let rm: () => void\n // 获取当前要删除节点\n const ch = vnodes[startIdx]\n if (ch != null) {\n if (isDef(ch.sel)) {\n // 触发destroy钩子函数\n invokeDestroyHook(ch)\n /*\n * 在dom中这里需要判断remove钩子函数是否全部调用,而我们dom没有remove钩子函数,所以\n * 不需要判断\n */\n rm = createRmCb(ch.elm!)\n // 删除子节点\n rm()\n } else {\n // 删除文本节点\n api.removeChild(parentElm, ch.elm!)\n }\n }\n }\n }\n\n // 更新children\n function updateChildren(parentElm: Node, oldCh: VNode[], newCh: VNode[]) {\n // 旧VNode的children头索引\n let oldStartIdx = 0\n // 新VNode的children头索引\n let newStartIdx = 0\n // 旧VNode的children尾索引\n let oldEndIdx = oldCh.length - 1\n // 新VNode的children尾索引\n let newEndIdx = newCh.length - 1\n // 旧VNode的children的头VNode\n let oldStartVnode = oldCh[0]\n // 旧VNode的children的尾VNode\n let oldEndVnode = oldCh[oldEndIdx]\n // 新VNode的children的头VNode\n let newStartVnode = newCh[0]\n // 新VNode的children的尾VNode\n let newEndVnode = newCh[newEndIdx]\n // 旧VNode的children的Key Map\n let oldKeyToIdx: KeyToIndexMap | undefined\n // 用于缓存key相同的新旧VNode\n let idxInOld: number\n // 用于缓存将要移动的旧VNode\n let elmToMove: VNode\n // 用于缓存将要插入新增VNode的位置之前的VNode\n let before: any\n\n // 遍历新旧children数组,直到其中之一遍历完\n while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {\n // 我们之后可能会对oldStartVnode、oldEndVnode、newStartVnode、newEndVnode重新赋值,可能会出现等于null的情况\n if (oldStartVnode == null) {\n oldStartVnode = oldCh[++oldStartIdx]\n } else if (oldEndVnode == null) {\n oldEndVnode = oldCh[--oldEndIdx]\n } else if (newStartVnode == null) {\n newStartVnode = newCh[++newStartIdx]\n } else if (newEndVnode == null) {\n newEndVnode = newCh[--newEndIdx]\n // key 和 sel 相同,则就是相同节点\n } else if (sameVnode(oldStartVnode, newStartVnode)) {\n // 当旧头VNode和新头VNode是相同VNode时,将新头VNode差异更新到旧头VNode上,同时将新旧头索引后移\n // 对比两个节点,如果newVnode有vnodeData,\n // 执行update钩子,更新oldNode上的模块的内容\n // 更新加载过的模块里的内容\n // 判断节点的类型,文本节点直接替换,如果不是文本节点\n // 判断是否有子元素,更新子元素\n patchVnode(oldStartVnode, newStartVnode)\n oldStartVnode = oldCh[++oldStartIdx]\n newStartVnode = newCh[++newStartIdx]\n } else if (sameVnode(oldEndVnode, newEndVnode)) {\n // 当旧尾VNode和新尾VNode是相同VNode时,将新尾VNode差异更新到旧尾VNode上,同时将新旧尾索引前移\n patchVnode(oldEndVnode, newEndVnode)\n oldEndVnode = oldCh[--oldEndIdx]\n newEndVnode = newCh[--newEndIdx]\n } else if (sameVnode(oldStartVnode, newEndVnode)) {\n /**\n * 当旧头VNode和新尾VNode是相同节点时,将新尾VNode差异更新到旧头VNode上,然后将旧头VNode插入到旧尾VNode后\n * 最后将旧头索引后移,新尾索引前移\n */\n patchVnode(oldStartVnode, newEndVnode)\n api.insertBefore(parentElm,oldStartVnode.elm!,api.nextSibling(oldEndVnode.elm!))\n oldStartVnode = oldCh[++oldStartIdx]\n newEndVnode = newCh[--newEndIdx]\n } else if (sameVnode(oldEndVnode, newStartVnode)) {\n /**\n * 当旧尾VNode和新头VNode是相同节点时,将新头VNode差异更新到旧尾VNode上,然后将旧尾VNode插入到旧头VNode前\n * 最后将旧尾索引前移,新头索引后移\n */\n patchVnode(oldEndVnode, newStartVnode)\n api.insertBefore(parentElm, oldEndVnode.elm!, oldStartVnode.elm!)\n oldEndVnode = oldCh[--oldEndIdx]\n newStartVnode = newCh[++newStartIdx]\n } else {\n // 如果没有Key Map则创建Key Map,用于根据key来更新VNode\n if (oldKeyToIdx === undefined) {\n oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)\n }\n // 根据Key Map获取当前新头VNode的对应的旧VNode的index\n idxInOld = oldKeyToIdx[newStartVnode.key as string]\n\n if (isUndef(idxInOld)) {\n // 如果没有设置key属性,直接根据新头VNode创建dom元素,插入到旧头VNode对应dom之前\n api.insertBefore(\n parentElm,\n createElm(newStartVnode),\n oldStartVnode.elm!,\n )\n } else {\n // 如果设置key属性,获取到key对应的旧VNode\n elmToMove = oldCh[idxInOld]\n if (elmToMove.sel !== newStartVnode.sel) {\n // 如果旧VNode和新VNode的sel属性不同,则直接创建新VNode对应的dom,插入到旧头VNode对应dom之前\n api.insertBefore(\n parentElm,\n createElm(newStartVnode),\n oldStartVnode.elm!,\n )\n } else {\n // 如果sel属性相同,则将新VNode数据更新到旧VNode上\n patchVnode(elmToMove, newStartVnode)\n // 删除旧children对应的VNode,代表已经更新过\n oldCh[idxInOld] = undefined as any\n // 创建VNode对应的dom,插入到旧头VNode对应dom之前\n api.insertBefore(parentElm, elmToMove.elm!, oldStartVnode.elm!)\n }\n }\n // 将新头VNode设置为新children数组中新头索引后一位\n newStartVnode = newCh[++newStartIdx]\n }\n }\n // 循环完成后,当旧头索引小于等于旧尾索引,或新头索引大于等于新尾索引时,说明新旧children其中之一已经遍历完成\n if (oldStartIdx <= oldEndIdx || newStartIdx <= newEndIdx) {\n // 如果存在旧头索引大于旧尾索引情况,说明新children中新增了VNode\n if (oldStartIdx > oldEndIdx) {\n // 获取新增VNode后一位的VNode对应的dom\n before = newCh[newEndIdx + 1] == null ? null : newCh[newEndIdx + 1].elm\n // 将新增VNode对应dom插入对应dom树位置\n addVnodes(parentElm, before, newCh, newStartIdx, newEndIdx)\n } else {\n // 删除多余dom节点\n removeVnodes(parentElm, oldCh, oldStartIdx, oldEndIdx)\n }\n }\n }\n\n // 对比新旧vnode差异,将差异更新到旧VNode上。\n function patchVnode(oldVnode: VNode, vnode: VNode) {\n // 当VNode的data属性存在时,触发update钩子函数\n if (vnode.data !== undefined) {\n for (let i = 0; i < cbs.update.length; ++i) {\n cbs.update[i](oldVnode, vnode)\n }\n }\n\n // 由于是相同的VNode节点,使用新旧VNode的真实dom元素相同\n const elm = (vnode.elm = oldVnode.elm!)\n // 获取旧VNode的children\n const oldCh = oldVnode.children as VNode[]\n // 获取新VNode的children\n const ch = vnode.children as VNode[]\n\n // 如果新旧节点完全相同,直接返回\n if (oldVnode === vnode) return\n // 判断VNode是否为文本节点\n if (isUndef(vnode.text)) {\n // 如果不是文本节点,判断新旧VNode是否同时有children\n if (isDef(oldCh) && isDef(ch)) {\n // 如果同时有children属性,且children属性不相同就更新children\n if (oldCh !== ch) {\n updateChildren(elm, oldCh, ch)\n }\n }\n }\n }\n\n return function patch(oldVnode: VNode | Element, vnode: VNode): VNode {\n // 缓存dom节点和父dom节点\n let elm: Node, parent: Node\n\n // 当oldVnode不是VNode时,说明是初次加载,创建一个空白VNode\n if (!isVnode(oldVnode)) {\n oldVnode = emptyNodeAt(oldVnode)\n }\n\n // 判断是否为相同VNode节点\n if (sameVnode(oldVnode, vnode)) {\n // 更新VNode节点差异\n patchVnode(oldVnode, vnode)\n } else {\n // 获取旧VNode的dom\n elm = oldVnode.elm!\n // 获取父节点dom\n parent = api.parentNode(elm) as Node\n // 创建dom元素\n createElm(vnode)\n // 当父节点不为空时\n if (parent != null) {\n // 将新创建的dom插入dom树\n api.insertBefore(parent, vnode.elm!, api.nextSibling(elm))\n // 删除旧VNode节点\n removeVnodes(parent, [oldVnode], 0, 0)\n }\n }\n return vnode\n }\n}\n","import type {\n VNode,\n VNodeChildElement,\n VNodeChildren,\n VNodeData,\n VNodes,\n} from './vnode'\nimport { vnode } from './vnode'\n// 类型判断\nimport * as is from './is'\n\nexport function addNS(\n data: VNodeData,\n children: Array<VNode | string | number> |undefined,\n sel: string | undefined,\n): void {\n data.ns = 'http://www.w3.org/2000/svg'\n if (sel !== 'foreignObject' && children !== undefined) {\n for (let i = 0; i < children.length; ++i) {\n const child = children[i]\n if (typeof child === 'string' || typeof child === 'number') continue\n const childData = child.data\n if (childData !== undefined) {\n addNS(childData, child.children as VNodes, child.sel)\n }\n }\n }\n}\n\n// h 函数的重载\nexport function h(sel: string): VNode\nexport function h(sel: string, data: VNodeData | null): VNode\nexport function h(sel: string, children: VNodeChildren): VNode\nexport function h(\n sel: string,\n data: VNodeData | null,\n children: VNodeChildren,\n): VNode\nexport function h(\n sel: string,\n b?: VNodeData | null | VNodeChildren,\n c?: VNodeChildren,\n): VNode {\n // 缓存 VNode 数据\n let data: VNodeData = {}\n // 缓存 children 数据\n let children: VNodeChildElement[] | undefined = undefined\n // 缓存文本数据\n let text: string | number | undefined\n // 用于缓存遍历children的index\n let i: number\n\n // 处理参数,实现重载的机制\n if (c !== undefined) {\n // 处理三个参数的情况\n // sel、data、children/text\n if (b != null) {\n data = b as VNodeData\n }\n if (is.array(c)) {\n children = c\n // 如果c是字符串或者数字\n } else if (is.primitive(c)) {\n text = c\n // 如果c是VNode\n } else if (c && c.sel) {\n children = [c]\n }\n } else if (b !== undefined && b != null) {\n // 处理两个参数的情况\n // 如果b是数组\n if (is.array(b)) {\n children = b\n // 如果b是字符串或数字\n } else if (is.primitive(b)) {\n text = b\n } else {\n // 这里由于b没有使用any类型,所以需要进一步判断b是否为VNode\n if (is.isVnode(b)) {\n children = [b]\n } else {\n data = b\n }\n }\n }\n // 处理 children 中的原始值(string/number)\n if (typeof children !== 'undefined') {\n for (i = 0; i < children.length; ++i) {\n // 如果 child 是string/number,创建文本节点\n // 这里由于children没有使用any类型,所以需要进一步判断children[i]是否为string | number\n // 不能直接使用children[i],所以使用msg缓存\n const msg = children[i]\n if (is.primitive(msg)) {\n children[i] = vnode(undefined, undefined, undefined, msg, undefined)\n }\n }\n }\n if (\n sel[0] === 's' &&\n sel[1] === 'v' &&\n sel[2] === 'g' &&\n (sel.length === 3 || sel[3] === '.' || sel[3] === '#')\n ) {\n addNS(data, children, sel)\n }\n // 符合VNode\n return vnode(sel, data, children, text, undefined)\n}\n","\nexport function querystring(data = {}): string {\n if (typeof data !== \"object\") {\n throw new TypeError(\"param must be object\");\n }\n return Object.entries(data).reduce((searchParams, [name, value]) => value === undefined || value == null ? searchParams : (searchParams.append(decodeURIComponent(name), decodeURIComponent(value)), searchParams), new URLSearchParams()).toString();\n}\n\nexport function randomString(len: number = 8): string {\n const chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';\n const maxPos = chars.length;\n let pwd = '';\n for (let i = 0; i < len; i++) {\n pwd += chars.charAt(Math.floor(Math.random() * maxPos))\n }\n return `${Date.now()}-${pwd}`;\n}\n\nexport function getCookie(name: string): string {\n const cookieList = window.document.cookie.match(\n new RegExp(`(^| )${name}(?:=([^;]*))?(;|$)`)\n );\n if (cookieList && cookieList[2]) return cookieList[2];\n return \"\";\n}\n\nexport function createData(params: Record<string, unknown> = {}): Record<string, unknown> {\n return Object.assign({}, {\n id: randomString(),\n path: window.location.href,\n time: Date.now(),\n userAgent: window.navigator.userAgent,\n referrer: document.referrer,\n ip: window.returnCitySN || { cid: \"\", cip: \"\", cname: \"\" },\n userId: getCookie('chaxus_prod')\n }, params)\n}\n\nexport const throttle = (fn: Function, wait: number = 300): Function => {\n let timer: NodeJS.Timeout | null = null;\n return function (this: unknown, ...args: unknown[]) {\n const context = this;\n if (!timer) {\n timer = setTimeout(() => {\n timer = null;\n fn.apply(context, args);\n }, wait);\n }\n };\n};\n\nexport const Noop = ():void => {}\n\nexport function changeHumpToLowerCase(str: string): string { // str ====> fullName\n const arr = str.split(\"\"); // 将字符串用split拆为单个字母为元素的数组,fullName ====> [\"f\", \"u\", \"l\", \"l\", \"N\", \"a\", \"m\", \"e\"]\n const lowerCase = arr.map(val => {\n if (val.toUpperCase() === val) { // 由此判断出,当前字符为大写字母\n return \"_\" + val.toLowerCase(); // 在大写字母前面加上下划线,并将该大写字母转为小写字母\n } else {\n return val;\n }\n });\n // 此时lowerCase =====> [\"f\", \"u\", \"l\", \"l\", \"_n\", \"a\", \"m\", \"e\"]\n str = lowerCase.join(\"\"); // 将数组元素连接起来,不用分隔符,这里必须用\"\" ,若省略的话,join方法会默认用逗号连接\n return str; // 此时,str ====> full_name\n}\n\n/**\n * 重写对象上面的某个属性\n *\n * @export\n * @param {IAnyObject} source 需要被重写的对象\n * @param {string} name 需要被重写对象的key\n * @param {(...args: any[]) => any} replacement 以原有的函数作为参数,执行并重写原有函数\n * @param {boolean} isForced 是否强制重写(可能原先没有该属性)\n */\nexport function replaceOld(source: any, name: string, replacement: (...args: unknown[]) => unknown, isForced?: boolean): void {\n if (typeof source === \"undefined\") return;\n if (name in source || isForced) {\n const original = source[name];\n const wrapped = replacement(original);\n if (typeof wrapped === 'function') {\n source[name] = wrapped;\n }\n }\n}\n\nexport const isString = (obj: unknown): boolean => {\n return toString.call(obj) === '[object String]';\n}\n\nexport type Hooks = (...args: unknown[]) => void\n","\nimport { isString } from './utils'\n/**\n * @description: Gets the current environment configuration\n * @return {string}\n */\nexport const getHost = (env?: string): string => {\n let host = ''\n if (env && isString(env)) {\n if (/trunk|neibu|release/.test(env)) {\n host = `.${env}`\n } else if (/test/.test(env)) {\n host = env\n } else if (/prod/.test(env)) {\n host = ''\n } else {\n host = ''\n }\n\n } else {\n const env = /\\w(\\.trunk|\\.neibu|\\.release|test)\\./.exec(\n window.location.hostname\n );\n if (env) {\n host = env[1]\n }\n }\n return host ? `https://log${host}.chaxus.com` : \"https://log.chaxus.com\";\n}","import { querystring } from './utils'\nimport { getHost } from './env'\n\ninterface BeaconPayload {\n url?: string,\n type?: string,\n payload: Record<string, unknown>\n}\n\n\nconst sendBeacon = ({ url = '', type = 'application/json; charset=UTF-8', payload = {} }: BeaconPayload) => {\n const requestUrl = url ? url : getHost()\n if (navigator.sendBeacon) { // 判断sendBeacon是否支持可用\n const param = new Blob([JSON.stringify(payload)], { type });\n return navigator.sendBeacon(requestUrl, param)\n }\n}\n\nconst sendImage = ({ url = \"\", payload = {} }) => {\n const requestUrl = url ? url : getHost()\n const image = new Image();\n image.width = 1;\n image.height = 1;\n image.src = `${requestUrl}?${querystring(payload)}`\n}\n\nexport const report = ({ url = '', type = 'application/json; charset=UTF-8', payload = {} }: BeaconPayload): boolean | undefined | void => {\n const requestUrl = url ? url : getHost()\n if (typeof navigator.sendBeacon !== 'undefined') { // 判断sendBeacon是否支持可用\n return sendBeacon({ url: requestUrl, type, payload })\n }\n return sendImage({ url: requestUrl, payload })\n}","import { Noop, replaceOld } from './utils'\nimport type { Hooks } from './utils'\n\ninterface Options {\n requestHook: Hooks,\n responseHook: Hooks,\n errorHook: Hooks\n}\n/**\n * @description: fetch\n * @param {Partial} options\n */\nexport const handleFetchHook = (options: Partial<Options> = {}): void => {\n if (typeof window !== 'undefined') {\n const { requestHook = Noop, responseHook = Noop, errorHook = Noop } = options\n const replacement = (originalFetch: any) => {\n return (url: string, config?: any) => {\n requestHook(url, config)\n return originalFetch.apply(window, [url, config])\n .then((response: Response) => {\n responseHook(url, config, response)\n return response\n })\n .catch((error: Error) => {\n errorHook(url, error)\n throw error;\n })\n }\n }\n replaceOld(window, 'fetch', replacement)\n }\n}\n/**\n * @description: xhr\n * @param {Partial} options\n * @return {*}\n */\nexport const handleXhrHook = (options: Partial<Options> = {}): void => {\n const originalXhrProto = XMLHttpRequest.prototype;\n const { requestHook = Noop, responseHook = Noop, errorHook = Noop } = options\n const replacementXhrOpen = (originalOpen: any) => {\n return function (this: XMLHttpRequest, ...args: unknown[]): void {\n requestHook(args)\n originalOpen.apply(this, args);\n };\n }\n replaceOld(originalXhrProto, 'open', replacementXhrOpen);\n const replacementXhrSend = (originalSend: any) => {\n return function (this: any, ...args: any[]): void {\n this.addEventListener('loadend', function (this: unknown) {\n responseHook(this)\n });\n this.addEventListener('error', function (this: unknown) {\n errorHook(this)\n });\n originalSend.apply(this, args);\n };\n }\n replaceOld(originalXhrProto, 'send', replacementXhrSend);\n}\n","import writeFile from './src/file/writeFile'\nimport readFile from './src/file/readFile'\nimport watchFile from './src/file/watchFile'\nimport EventEmitter from './src/mode/subscribe'\nimport queryFileInfo from './src/file/fileInfo'\nimport filterObj from './src/utils/filterObj'\nimport readDir from './src/file/readDir'\nimport str2Xml from './src/utils/str2Xml'\nimport { init } from '@/vnode/init'\nimport { h } from '@/vnode/h'\nimport Monitor from '@/ranlog'\n\nconst vnode = {\n init,\n h\n}\n\nexport {\n writeFile,\n readFile,\n watchFile,\n EventEmitter,\n queryFileInfo,\n filterObj,\n str2Xml,\n readDir,\n vnode,\n Monitor\n}\n","type Callback = (...args: any) => unknown\n\ntype EventName = string | symbol\n\ntype EventItem = {\n name?: string | symbol\n callback: Callback\n initialCallback?: Callback\n}\n\nclass Subscribe {\n _events: Record<EventName, Array<EventItem>>\n constructor() {\n this._events = {}\n }\n\n on = (eventName: EventName, eventItem: EventItem | Callback): void => {\n if (this._events[eventName] && eventName !== Symbol.for('new-listener')) {\n // 注册一个 newListener 用于监听新的事件订阅\n this.emit(Symbol.for('new-listener'), eventName)\n }\n // 由于一个事件可能注册多个回调函数,所以使用数组来存储事件队列\n const callbacks = this._events[eventName] || []\n if (typeof eventItem === 'function') {\n callbacks.push({\n name: eventName,\n callback: eventItem,\n })\n } else {\n callbacks.push(eventItem)\n }\n this._events[eventName] = callbacks\n }\n\n emit = (eventName: EventName, ...args: Array<unknown>): void => {\n const callbacks = this._events[eventName] || []\n callbacks.forEach((item) => {\n const { callback } = item\n callback(...args)\n })\n }\n\n once = (eventName: EventName, eventItem: EventItem | Callback): void => {\n let one: EventItem\n if (typeof eventItem === 'function') {\n one = {\n name: eventName,\n callback: (...args: Array<unknown>) => {\n eventItem(...args)\n this.off(eventName, one)\n },\n initialCallback: eventItem,\n }\n } else {\n const { callback } = eventItem\n one = {\n name: eventName,\n callback: (...args: Array<unknown>) => {\n callback(...args)\n this.off(eventName, one)\n },\n initialCallback: callback,\n }\n }\n // 由于需要在回调函数执行后,取消订阅当前事件,所以需要对传入的回调函数做一层包装,然后绑定包装后的函数\n\n // 考虑:如果当前事件在未执行,被用户取消订阅,能否取消?\n // 由于:我们订阅事件的时候,修改了原回调函数的引用,所以,用户触发 off 的时候不能找到对应的回调函数\n // 所以,我们需要在当前函数与用户传入的回调函数做一个绑定,我们通过自定义属性来实现\n this.on(eventName, one)\n }\n\n off = (eventName: EventName, eventItem: EventItem | Callback): void => {\n // 找到事件对应的回调函数,删除对应的回调函数\n const callbacks = this._events[eventName] || []\n const newCallbacks = callbacks.filter((item) => {\n if (typeof eventItem === 'function') {\n return item.callback !== eventItem && item.initialCallback !== eventItem\n } else {\n const { callback } = eventItem\n /* 用于once的取消订阅 */\n return item.callback !== callback && item.initialCallback !== callback\n }\n })\n this._events[eventName] = newCallbacks\n }\n}\n\nexport default Subscribe\n","import { handleClick } from './behavior'\nimport { handleError } from './error'\nimport { getPerformance } from './performance'\nimport { createData, throttle } from './utils'\nimport { report } from './report'\nimport { handleFetchHook, handleXhrHook } from './request'\n\nexport interface Payload {\n payload: Record<string, unknown>,\n type?: string\n}\nclass Monitor {\n /**\n * @description: 页面加载性能上报\n * @param {Payload} param1\n */\n reportPerformance(): void {\n const params = getPerformance()\n const payload = createData()\n report({\n payload: {\n ...params,\n ...payload\n }\n })\n }\n /**\n * @description: 手动触发的上报\n * @param {Record} payload\n * @param {*} unknown\n */\n log(payload: Record<string, unknown>): void {\n report({ payload })\n }\n /**\n * @description: 点击上报\n * @return {*}\n */\n reportClick(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const hook = (event: MouseEvent) => {\n throttleReport({ payload: { ...payload, event, type: 'click' } })\n }\n handleClick(hook)\n }\n // ajax 上报\n reportXhr(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const requestHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'xhrRequest' } })\n }\n const responseHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'xhrResponse' } })\n }\n const errorHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'xhrError' } })\n }\n handleXhrHook({ requestHook, responseHook, errorHook })\n }\n reportFetch(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const requestHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'fetchRequest' } })\n }\n const responseHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'fetchResponse' } })\n }\n const errorHook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'fetchError' } })\n }\n handleFetchHook({ requestHook, responseHook, errorHook })\n }\n reportError(): void {\n const throttleReport = throttle(report)\n const payload = createData()\n const hook = (...args: unknown[]) => {\n throttleReport({ payload: { ...payload, ...args, type: 'error' } })\n }\n handleError(hook)\n }\n}\n\nexport default Monitor","\ninterface BasicType {\n [x:string]: number | undefined\n dnsSearch: number; // DNS 解析耗时\n tcpConnect: number; // TCP 连接耗时\n sslConnect: number; // SSL安全连接耗时\n request: number; // TTFB 网络请求耗时\n response: number; // 数据传输耗时\n parseDomTree: number; // DOM 解析耗时\n resource: number; // 资源加载耗时\n domReady: number; // DOM Ready\n httpHead: number; // http 头部大小\n interactive: number; // 首次可交互时间\n complete: number; // 页面完全加载\n redirect: number; // 重定向次数\n redirectTime: number; // 重定向耗时\n duration: number; // 资源请求的总耗时 responseEnd-startTime\n fp: number | undefined; // 渲染出第一个像素点,白屏时间\n fcp: number | undefined; // 渲染出第一个内容,首屏结束时间\n}\n\nexport function getPerformance(): BasicType {\n const [performanceNavigationTiming] = performance.getEntriesByType('navigation')\n const [firstPaint, firstContentfulPaint] = performance.getEntriesByType('paint')\n const {\n domainLookupEnd,\n domainLookupStart,\n connectEnd,\n connectStart,\n secureConnectionStart,\n loadEventStart,\n domInteractive,\n domContentLoadedEventEnd,\n duration,\n responseStart,\n requestStart,\n responseEnd,\n fetchStart,\n transferSize,\n encodedBodySize,\n redirectEnd,\n redirectStart,\n redirectCount\n } = performanceNavigationTiming as PerformanceNavigationTiming;\n const { startTime: fp } = firstPaint;\n const { startTime: fcp } = firstContentfulPaint;\n return {\n dnsSearch: domainLookupEnd - domainLookupStart,\n tcpConnect: connectEnd - connectStart,\n sslConnect: connectEnd - secureConnectionStart,\n request: responseStart - requestStart,\n response: responseEnd - responseStart,\n parseDomTree: domInteractive - responseEnd,\n resource: loadEventStart - domContentLoadedEventEnd,\n domReady: domContentLoadedEventEnd - fetchStart,\n interactive: domInteractive - fetchStart,\n complete: loadEventStart - fetchStart,\n httpHead: transferSize - encodedBodySize,\n redirect: redirectCount,\n redirectTime: redirectEnd - redirectStart,\n duration: duration,\n fp: fp,\n fcp: fcp,\n };\n}\n","import { Noop } from './utils'\n\nexport const handleClick = (hooks:(event: MouseEvent) => void = Noop): void => {\n document.addEventListener('click', function (event) { hooks(event) }, true);\n}","import { Noop } from './utils'\nimport type { Hooks } from './utils'\n\nexport const handleError = (hooks: Hooks = Noop): void => {\n window.addEventListener('unhandledrejection', (error) => {hooks(error)}, true);\n window.addEventListener('error', (error) => {\n hooks(error)\n return false // 取消默认事件\n }, true) // 捕获阶段\n}\n\n","/**\n * @description: 过滤对象的属性,去除对象中在list数组里面有的属性,返回一个新对象,一般是用于去除空字符和null\n * @param {Object} obj 传入对象\n * @param {Array} list 传入数组\n * @return {Object}\n */\n\nconst filterObj = (\n obj: Record<string | symbol, any>,\n list: Array<string | symbol>,\n): Record<string | symbol, any> => {\n const result: Record<string | symbol, any> = {}\n Object.keys(obj).forEach((item) => {\n if (!list.includes(obj[item])) {\n result[item] = obj[item]\n }\n })\n return result\n}\n\nexport default filterObj\n","import fs from './fs'\n\ntype Error = NodeJS.ErrnoException | null\n\n/**\n * @description: 查询一个文件的详细信息,一般用于区分文件还是目录(data.isDirectory())\n * @param {string} path 文件路径\n * @return {Promise}\n */\n\nconst queryFileInfo = (path: string): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.stat(path, (err: Error, data: string) => {\n err\n ? reject({ _identification: false, data: err })\n : resolve({ _identification: true, data })\n })\n })\n\nexport default queryFileInfo\n","import fs from './fs'\n\ninterface Options {\n dirPath: string\n ignores?: Array<string>\n}\n\nconst readDir = (options: Options): Array<string> => {\n const { dirPath } = options\n try {\n return fs.readdirSync(dirPath)\n } catch (error) {\n console.log('readDir error', error)\n throw error\n }\n}\n\nexport default readDir\n","import fs from './fs'\n\ntype Error = NodeJS.ErrnoException | null\n\n/**\n * @description: 读取一个文件,读取成功返回状态码和文件内容\n * @param {string} path 文件路径\n * @param {string} format 读取格式,默认utf-8\n * @return {Promise}\n */\n\nconst readFile = (\n path: string,\n format: string = 'utf-8',\n): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.readFile(path, format, (err: Error, data: string) => {\n err\n ? reject({ _identification: false, data: err })\n : resolve({ _identification: true, data })\n })\n })\n\nexport default readFile\n","/**\n * @description: 传入字符串和指定的格式,将字符串转成xml\n * @param {string} xmlStr\n * @param {DOMParserSupportedType} format\n * @return {Document}\n */\nconst str2Xml = (\n xmlStr: string,\n format: DOMParserSupportedType = 'text/xml',\n): HTMLElement | undefined => {\n if (window.DOMParser)\n return new window.DOMParser().parseFromString(xmlStr, format)\n .documentElement\n if (\n typeof window.ActiveXObject !== 'undefined' &&\n new window.ActiveXObject('Microsoft.XMLDOM')\n ) {\n const xmlDoc = new window.ActiveXObject('Microsoft.XMLDOM')\n xmlDoc.async = 'false'\n xmlDoc.loadXML(xmlStr)\n return xmlDoc\n }\n return undefined\n}\n\nexport default str2Xml\n","import type { Stats } from 'node:fs'\nimport fs from './fs'\n\n/**\n * @description: 观察一个文件是否被改变,返回状态\n * @param {string} path 监听的文件路径\n * @param {number} interval 监听的时间,单位毫秒,默认20毫秒\n * @return {Promise}\n */\n\nconst watchFile = (\n path: string,\n interval: number = 20,\n): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.watchFile(path, { interval }, (curr: Stats, prev: Stats) => {\n if (curr.mtime !== prev.mtime) {\n fs.unwatchFile(path)\n resolve({ _identification: true, data: { msg: 'file is changed' } })\n } else {\n resolve({\n _identification: false,\n data: { msg: 'file is not changed' },\n })\n }\n })\n })\n\nexport default watchFile\n","import fs from './fs'\n\ntype Error = NodeJS.ErrnoException | null\n\n/**\n * @description: 根据文件路径创建文件,如果文件存在会清空再写入,如果不存在会创建\n * @param {string} path 文件路径\n * @param {string} content 文件内容\n * @return {Promise}\n */\n\nconst writeFile = (\n path: string,\n content: string,\n): Promise<Ranuts.Identification> =>\n new Promise((resolve, reject) => {\n if (!fs._identification)\n return reject({ _identification: false, data: 'fs is not loaded' })\n fs.writeFile(\n path,\n content,\n {\n mode: 438, // 可读可写666,转化为十进制就是438\n flag: 'w+', // r+并不会清空再写入,w+会清空再写入\n encoding: 'utf-8',\n },\n (err: Error) => {\n if (err) {\n reject({ _identification: false, data: err })\n throw err\n } else {\n resolve({ _identification: true, data: { path, content } })\n }\n },\n )\n })\n\nexport default writeFile\n"],"names":["fileSystem","process","Stats","_identification","message","fs$1","vnode","sel","data","children","text","elm","key","parentNode","node","isDocumentFragment","parseFragment","parent","nodeType","fragmentNode","fragment","parentNode2","firstChildNode","firstChild","lastChildNode","lastChild","htmlDomApi","createElement","tagName","options","document","createElementNS","namespaceURI","qualifiedName","createTextNode","createDocumentFragment","createComment","insertBefore","newNode","referenceNode","removeChild","child","appendChild","nextSibling","Array","from","childNodes","index","indexOf","_a","setTextContent","textContent","getTextContent","isElement","isText","isComment","array","isArray","primitive","s","updateAttrs","oldVnode","oldAttrs","attrs","cur","setAttribute","removeAttribute","charCodeAt","setAttributeNS","updateClass","name","oldClass","class","className","Object","prototype","hasOwnProperty","call","classList","remove","invokeHandler","handler","event","isFunction","i","length","handleEvent","type","on","updateEventListeners","oldOn","oldListener","listener","oldElm","_b","removeEventListener","addEventListener","updateProps","old","oldProps","props","reflowForced","updateStyle","oldStyle","style","removeProperty","setProperty","modules","attributesModule","create","update","classModule","eventListenersModule","destroy","propsModule","styleModule","pre","rm","offsetLeft","amount","applied","push","getComputedStyle","split","ev","target","sameVnode","vnode1","vnode2","createKeyToOldIdx","beginIdx","endIdx","map","emptyNode","addNS","ns","childData","randomString","len","chars","maxPos","pwd","charAt","Math","floor","random","Date","now","getCookie","cookieList","window","cookie","match","RegExp","createData","params","assign","id","path","location","href","time","userAgent","navigator","referrer","ip","returnCitySN","cid","cip","cname","userId","throttle","fn","wait","timer","args","context","this","setTimeout","apply","Noop","replaceOld","source","replacement","isForced","wrapped","getHost","env","host","obj","toString","test","exec","hostname","sendImage","url","payload","requestUrl","image","Image","width","height","src","TypeError","entries","reduce","searchParams","value","append","decodeURIComponent","URLSearchParams","querystring","report","sendBeacon","param","Blob","JSON","stringify","handleXhrHook","originalXhrProto","XMLHttpRequest","requestHook","responseHook","errorHook","originalOpen","originalSend","init","api","cbs","keys","module","hook","isUndef","isDef","createElm","hashIdx","dotIdx","hash","dot","tag","slice","min","replace","is.array","ch","is.primitive","invokeDestroyHook","j","createRmCb","childElm","removeVnodes","parentElm","vnodes","startIdx","updateChildren","oldCh","newCh","oldKeyToIdx","idxInOld","elmToMove","before","oldStartIdx","newStartIdx","oldEndIdx","newEndIdx","oldStartVnode","oldEndVnode","newStartVnode","newEndVnode","patchVnode","addVnodes","isVnode","c","join","toLowerCase","emptyNodeAt","h","b","msg","constructor","__publicField","eventName","eventItem","_events","Symbol","for","emit","callbacks","callback","forEach","item","one","off","initialCallback","newCallbacks","filter","reportPerformance","performanceNavigationTiming","performance","getEntriesByType","firstPaint","firstContentfulPaint","domainLookupEnd","domainLookupStart","connectEnd","connectStart","secureConnectionStart","loadEventStart","domInteractive","domContentLoadedEventEnd","duration","responseStart","requestStart","responseEnd","fetchStart","transferSize","encodedBodySize","redirectEnd","redirectStart","redirectCount","startTime","fp","fcp","dnsSearch","tcpConnect","sslConnect","request","response","parseDomTree","resource","domReady","interactive","complete","httpHead","redirect","redirectTime","getPerformance","log","reportClick","throttleReport","hooks","handleClick","reportXhr","reportFetch","originalFetch","config","then","catch","error","handleFetchHook","reportError","handleError","list","result","includes","Promise","resolve","reject","fs","stat","err","dirPath","readdirSync","console","format","readFile","xmlStr","DOMParser","parseFromString","documentElement","ActiveXObject","xmlDoc","async","loadXML","interval","watchFile","curr","prev","mtime","unwatchFile","content","writeFile","mode","flag","encoding"],"mappings":"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"}