@lytjs/platform-adapter 6.5.0 → 6.7.0

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/dist/index.cjs CHANGED
@@ -22,9 +22,7 @@ var AdapterRegistry = class {
22
22
  */
23
23
  register(adapter) {
24
24
  if (!commonIs.isString(adapter.name) || adapter.name.length === 0) {
25
- throw new Error(
26
- "[platform-adapter] \u9002\u914D\u5668\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"
27
- );
25
+ throw new Error("[platform-adapter] \u9002\u914D\u5668\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
28
26
  }
29
27
  this.adapters.set(adapter.name, adapter);
30
28
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter-registry.ts","../src/create-renderer.ts"],"names":["isString","isFunction"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\r\n * 平台适配器注册表\r\n *\r\n * @description\r\n * 管理所有已注册的平台适配器和插件,提供统一的注册、查询和插件管理能力。\r\n * 采用单例模式,全局共享同一个注册表实例。\r\n */\r\n\r\nimport { isString } from '@lytjs/common-is';\r\nimport type { PlatformAdapter, PlatformPlugin } from './types';\r\n\r\n/**\r\n * 适配器注册表类\r\n *\r\n * @description\r\n * 维护平台适配器的注册信息,支持适配器的注册、注销、查询,\r\n * 以及平台级插件的管理。\r\n */\r\nclass AdapterRegistry {\r\n /** 已注册的适配器映射(平台名称 -> 适配器实例) */\r\n private adapters = new Map<string, PlatformAdapter>();\r\n /** 平台插件映射(平台名称 -> 插件数组) */\r\n private plugins = new Map<string, PlatformPlugin[]>();\r\n\r\n /**\r\n * 注册平台适配器\r\n *\r\n * @description\r\n * 将适配器实例注册到注册表中,以适配器的 name 为键。\r\n * 如果同名适配器已存在,将被覆盖。\r\n *\r\n * @param adapter - 平台适配器实例\r\n * @throws {Error} 当 adapter.name 为空时抛出错误\r\n */\r\n register(adapter: PlatformAdapter): void {\r\n if (!isString(adapter.name) || adapter.name.length === 0) {\r\n throw new Error(\r\n '[platform-adapter] 适配器名称不能为空',\r\n );\r\n }\r\n this.adapters.set(adapter.name, adapter);\r\n }\r\n\r\n /**\r\n * 注销平台适配器\r\n *\r\n * @description\r\n * 从注册表中移除指定名称的适配器,同时清除该平台关联的所有插件。\r\n *\r\n * @param name - 平台名称\r\n * @returns 是否成功注销(名称不存在时返回 false)\r\n */\r\n unregister(name: string): boolean {\r\n const removed = this.adapters.delete(name);\r\n if (removed) {\r\n this.plugins.delete(name);\r\n }\r\n return removed;\r\n }\r\n\r\n /**\r\n * 获取指定名称的平台适配器\r\n *\r\n * @param name - 平台名称\r\n * @returns 适配器实例,未找到时返回 undefined\r\n */\r\n get(name: string): PlatformAdapter | undefined {\r\n return this.adapters.get(name);\r\n }\r\n\r\n /**\r\n * 检查指定名称的适配器是否已注册\r\n *\r\n * @param name - 平台名称\r\n * @returns 是否已注册\r\n */\r\n has(name: string): boolean {\r\n return this.adapters.has(name);\r\n }\r\n\r\n /**\r\n * 获取所有已注册的适配器名称\r\n *\r\n * @returns 平台名称数组\r\n */\r\n getNames(): string[] {\r\n return Array.from(this.adapters.keys());\r\n }\r\n\r\n /**\r\n * 为指定平台添加插件\r\n *\r\n * @description\r\n * 将插件添加到目标平台的插件列表中。\r\n * 如果目标平台不存在,会自动创建空的插件列表。\r\n *\r\n * @param platformName - 目标平台名称\r\n * @param plugin - 平台插件实例\r\n */\r\n addPlugin(platformName: string, plugin: PlatformPlugin): void {\r\n const existing = this.plugins.get(platformName);\r\n if (existing) {\r\n existing.push(plugin);\r\n } else {\r\n this.plugins.set(platformName, [plugin]);\r\n }\r\n }\r\n\r\n /**\r\n * 从指定平台移除插件\r\n *\r\n * @param platformName - 目标平台名称\r\n * @param pluginName - 要移除的插件名称\r\n * @returns 是否成功移除(插件不存在时返回 false)\r\n */\r\n removePlugin(platformName: string, pluginName: string): boolean {\r\n const list = this.plugins.get(platformName);\r\n if (!list) return false;\r\n\r\n const index = list.findIndex((p) => p.name === pluginName);\r\n if (index === -1) return false;\r\n\r\n list.splice(index, 1);\r\n return true;\r\n }\r\n\r\n /**\r\n * 获取指定平台的所有插件\r\n *\r\n * @param platformName - 目标平台名称\r\n * @returns 插件数组,平台无插件时返回空数组\r\n */\r\n getPlugins(platformName: string): PlatformPlugin[] {\r\n return this.plugins.get(platformName) ?? [];\r\n }\r\n}\r\n\r\n/** 全局适配器注册表单例 */\r\nexport const adapterRegistry = new AdapterRegistry();\r\n","/**\r\n * 跨平台渲染器工厂\r\n *\r\n * @description\r\n * 基于平台适配器创建渲染器实例,提供统一的 render/unmount API,\r\n * 屏蔽底层平台差异。\r\n */\r\n\r\nimport { isFunction, isString } from '@lytjs/common-is';\r\nimport type { VNode } from '@lytjs/common-vnode';\r\nimport type { PlatformAdapter, PlatformConfig } from './types';\r\n\r\n/**\r\n * 平台渲染器接口\r\n *\r\n * @description\r\n * 封装了平台适配器,提供高层的渲染和卸载 API。\r\n *\r\n * @template HN - 宿主节点类型\r\n * @template HE - 宿主元素类型(extends HN)\r\n */\r\nexport interface PlatformRenderer<HN, HE extends HN> {\r\n /**\r\n * 将 VNode 渲染到指定容器中\r\n *\r\n * @param vnode - 要渲染的虚拟节点\r\n * @param container - 宿主容器节点\r\n */\r\n render(vnode: VNode, container: HN): void;\r\n\r\n /**\r\n * 卸载指定容器中的内容\r\n *\r\n * @param container - 宿主容器节点\r\n */\r\n unmount(container: HN): void;\r\n\r\n /**\r\n * 获取关联的平台适配器\r\n *\r\n * @returns 平台适配器实例\r\n */\r\n getAdapter(): PlatformAdapter<HN, HE>;\r\n}\r\n\r\n/**\r\n * 创建平台渲染器\r\n *\r\n * @description\r\n * 工厂函数,基于给定的平台适配器和配置创建渲染器实例。\r\n * 渲染器内部委托适配器完成实际的 DOM 操作。\r\n *\r\n * @template HN - 宿主节点类型\r\n * @template HE - 宿主元素类型(extends HN)\r\n * @param adapter - 平台适配器实例\r\n * @param config - 平台配置(可选)\r\n * @returns 平台渲染器实例\r\n *\r\n * @example\r\n * ```typescript\r\n * const renderer = createPlatformRenderer(myAdapter, { debug: true });\r\n * renderer.render(vnode, container);\r\n * ```\r\n */\r\nexport function createPlatformRenderer<HN, HE extends HN>(\r\n adapter: PlatformAdapter<HN, HE>,\r\n config?: PlatformConfig,\r\n): PlatformRenderer<HN, HE> {\r\n // 当前容器中已渲染的子节点引用\r\n let currentChild: HN | null = null;\r\n\r\n const renderer: PlatformRenderer<HN, HE> = {\r\n /**\r\n * 将 VNode 渲染到容器中\r\n *\r\n * @description\r\n * 根据 vnode 类型创建对应的宿主节点,并插入到容器中。\r\n * 如果容器中已有内容,会先卸载再重新渲染。\r\n */\r\n render(vnode: VNode, container: HN): void {\r\n // 先卸载已有内容\r\n if (currentChild !== null) {\r\n this.unmount(container);\r\n }\r\n\r\n const node = createHostNodeFromVNode(adapter, vnode);\r\n if (node !== null) {\r\n adapter.insert(node, container, null);\r\n currentChild = node;\r\n }\r\n\r\n if (config?.debug) {\r\n // eslint-disable-next-line no-console\r\n console.log(`[platform-adapter:${adapter.name}] 渲染完成`, vnode);\r\n }\r\n },\r\n\r\n /**\r\n * 卸载容器中的内容\r\n */\r\n unmount(_container: HN): void {\r\n if (currentChild !== null) {\r\n adapter.remove(currentChild);\r\n currentChild = null;\r\n }\r\n\r\n if (config?.debug) {\r\n // eslint-disable-next-line no-console\r\n console.log(`[platform-adapter:${adapter.name}] 卸载完成`);\r\n }\r\n },\r\n\r\n /**\r\n * 获取关联的平台适配器\r\n */\r\n getAdapter(): PlatformAdapter<HN, HE> {\r\n return adapter;\r\n },\r\n };\r\n\r\n return renderer;\r\n}\r\n\r\n/**\r\n * 根据 VNode 类型创建宿主节点\r\n *\r\n * @description\r\n * 将 VNode 映射为平台适配器可操作的宿主节点。\r\n * 支持元素节点、文本节点和注释节点。\r\n *\r\n * @param adapter - 平台适配器\r\n * @param vnode - 虚拟节点\r\n * @returns 宿主节点,无法识别的类型返回 null\r\n */\r\nfunction createHostNodeFromVNode<HN, HE extends HN>(\r\n adapter: PlatformAdapter<HN, HE>,\r\n vnode: VNode,\r\n): HN | null {\r\n const { type, children } = vnode;\r\n\r\n // 元素节点\r\n if (isString(type)) {\r\n const el = adapter.createElement(type);\r\n\r\n // 设置属性\r\n if (vnode.props) {\r\n for (const [key, value] of Object.entries(vnode.props)) {\r\n if (key === 'style' && isString(value)) {\r\n adapter.setStyle(el, value);\r\n } else if (key === 'class' && isString(value)) {\r\n adapter.addClass(el, value);\r\n } else if (isString(value)) {\r\n adapter.setAttribute(el, key, value);\r\n }\r\n }\r\n }\r\n\r\n // 递归处理子节点\r\n if (children && isString(children)) {\r\n adapter.setElementText(el, children);\r\n }\r\n\r\n return el as unknown as HN;\r\n }\r\n\r\n // 文本节点\r\n if (isString(children)) {\r\n return adapter.createText(children);\r\n }\r\n\r\n // 注释节点\r\n if (isFunction(type) === false && type !== null && !isString(type)) {\r\n // 非 string、非 function、非 null 的 type 可能是 Comment Symbol\r\n return adapter.createComment(String(children ?? ''));\r\n }\r\n\r\n return null;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/adapter-registry.ts","../src/create-renderer.ts"],"names":["isString","isFunction"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * 平台适配器注册表\n *\n * @description\n * 管理所有已注册的平台适配器和插件,提供统一的注册、查询和插件管理能力。\n * 采用单例模式,全局共享同一个注册表实例。\n */\n\nimport { isString } from '@lytjs/common-is';\nimport type { PlatformAdapter, PlatformPlugin } from './types';\n\n/**\n * 适配器注册表类\n *\n * @description\n * 维护平台适配器的注册信息,支持适配器的注册、注销、查询,\n * 以及平台级插件的管理。\n */\nclass AdapterRegistry {\n /** 已注册的适配器映射(平台名称 -> 适配器实例) */\n private adapters = new Map<string, PlatformAdapter>();\n /** 平台插件映射(平台名称 -> 插件数组) */\n private plugins = new Map<string, PlatformPlugin[]>();\n\n /**\n * 注册平台适配器\n *\n * @description\n * 将适配器实例注册到注册表中,以适配器的 name 为键。\n * 如果同名适配器已存在,将被覆盖。\n *\n * @param adapter - 平台适配器实例\n * @throws {Error} 当 adapter.name 为空时抛出错误\n */\n register(adapter: PlatformAdapter): void {\n if (!isString(adapter.name) || adapter.name.length === 0) {\n throw new Error('[platform-adapter] 适配器名称不能为空');\n }\n this.adapters.set(adapter.name, adapter);\n }\n\n /**\n * 注销平台适配器\n *\n * @description\n * 从注册表中移除指定名称的适配器,同时清除该平台关联的所有插件。\n *\n * @param name - 平台名称\n * @returns 是否成功注销(名称不存在时返回 false)\n */\n unregister(name: string): boolean {\n const removed = this.adapters.delete(name);\n if (removed) {\n this.plugins.delete(name);\n }\n return removed;\n }\n\n /**\n * 获取指定名称的平台适配器\n *\n * @param name - 平台名称\n * @returns 适配器实例,未找到时返回 undefined\n */\n get(name: string): PlatformAdapter | undefined {\n return this.adapters.get(name);\n }\n\n /**\n * 检查指定名称的适配器是否已注册\n *\n * @param name - 平台名称\n * @returns 是否已注册\n */\n has(name: string): boolean {\n return this.adapters.has(name);\n }\n\n /**\n * 获取所有已注册的适配器名称\n *\n * @returns 平台名称数组\n */\n getNames(): string[] {\n return Array.from(this.adapters.keys());\n }\n\n /**\n * 为指定平台添加插件\n *\n * @description\n * 将插件添加到目标平台的插件列表中。\n * 如果目标平台不存在,会自动创建空的插件列表。\n *\n * @param platformName - 目标平台名称\n * @param plugin - 平台插件实例\n */\n addPlugin(platformName: string, plugin: PlatformPlugin): void {\n const existing = this.plugins.get(platformName);\n if (existing) {\n existing.push(plugin);\n } else {\n this.plugins.set(platformName, [plugin]);\n }\n }\n\n /**\n * 从指定平台移除插件\n *\n * @param platformName - 目标平台名称\n * @param pluginName - 要移除的插件名称\n * @returns 是否成功移除(插件不存在时返回 false)\n */\n removePlugin(platformName: string, pluginName: string): boolean {\n const list = this.plugins.get(platformName);\n if (!list) return false;\n\n const index = list.findIndex((p) => p.name === pluginName);\n if (index === -1) return false;\n\n list.splice(index, 1);\n return true;\n }\n\n /**\n * 获取指定平台的所有插件\n *\n * @param platformName - 目标平台名称\n * @returns 插件数组,平台无插件时返回空数组\n */\n getPlugins(platformName: string): PlatformPlugin[] {\n return this.plugins.get(platformName) ?? [];\n }\n}\n\n/** 全局适配器注册表单例 */\nexport const adapterRegistry = new AdapterRegistry();\n","/**\n * 跨平台渲染器工厂\n *\n * @description\n * 基于平台适配器创建渲染器实例,提供统一的 render/unmount API,\n * 屏蔽底层平台差异。\n */\n\nimport { isFunction, isString } from '@lytjs/common-is';\nimport type { VNode } from '@lytjs/common-vnode';\nimport type { PlatformAdapter, PlatformConfig } from './types';\n\n/**\n * 平台渲染器接口\n *\n * @description\n * 封装了平台适配器,提供高层的渲染和卸载 API。\n *\n * @template HN - 宿主节点类型\n * @template HE - 宿主元素类型(extends HN)\n */\nexport interface PlatformRenderer<HN, HE extends HN> {\n /**\n * 将 VNode 渲染到指定容器中\n *\n * @param vnode - 要渲染的虚拟节点\n * @param container - 宿主容器节点\n */\n render(vnode: VNode, container: HN): void;\n\n /**\n * 卸载指定容器中的内容\n *\n * @param container - 宿主容器节点\n */\n unmount(container: HN): void;\n\n /**\n * 获取关联的平台适配器\n *\n * @returns 平台适配器实例\n */\n getAdapter(): PlatformAdapter<HN, HE>;\n}\n\n/**\n * 创建平台渲染器\n *\n * @description\n * 工厂函数,基于给定的平台适配器和配置创建渲染器实例。\n * 渲染器内部委托适配器完成实际的 DOM 操作。\n *\n * @template HN - 宿主节点类型\n * @template HE - 宿主元素类型(extends HN)\n * @param adapter - 平台适配器实例\n * @param config - 平台配置(可选)\n * @returns 平台渲染器实例\n *\n * @example\n * ```typescript\n * const renderer = createPlatformRenderer(myAdapter, { debug: true });\n * renderer.render(vnode, container);\n * ```\n */\nexport function createPlatformRenderer<HN, HE extends HN>(\n adapter: PlatformAdapter<HN, HE>,\n config?: PlatformConfig,\n): PlatformRenderer<HN, HE> {\n // 当前容器中已渲染的子节点引用\n let currentChild: HN | null = null;\n\n const renderer: PlatformRenderer<HN, HE> = {\n /**\n * 将 VNode 渲染到容器中\n *\n * @description\n * 根据 vnode 类型创建对应的宿主节点,并插入到容器中。\n * 如果容器中已有内容,会先卸载再重新渲染。\n */\n render(vnode: VNode, container: HN): void {\n // 先卸载已有内容\n if (currentChild !== null) {\n this.unmount(container);\n }\n\n const node = createHostNodeFromVNode(adapter, vnode);\n if (node !== null) {\n adapter.insert(node, container, null);\n currentChild = node;\n }\n\n if (config?.debug) {\n // eslint-disable-next-line no-console\n console.log(`[platform-adapter:${adapter.name}] 渲染完成`, vnode);\n }\n },\n\n /**\n * 卸载容器中的内容\n */\n unmount(_container: HN): void {\n if (currentChild !== null) {\n adapter.remove(currentChild);\n currentChild = null;\n }\n\n if (config?.debug) {\n // eslint-disable-next-line no-console\n console.log(`[platform-adapter:${adapter.name}] 卸载完成`);\n }\n },\n\n /**\n * 获取关联的平台适配器\n */\n getAdapter(): PlatformAdapter<HN, HE> {\n return adapter;\n },\n };\n\n return renderer;\n}\n\n/**\n * 根据 VNode 类型创建宿主节点\n *\n * @description\n * 将 VNode 映射为平台适配器可操作的宿主节点。\n * 支持元素节点、文本节点和注释节点。\n *\n * @param adapter - 平台适配器\n * @param vnode - 虚拟节点\n * @returns 宿主节点,无法识别的类型返回 null\n */\nfunction createHostNodeFromVNode<HN, HE extends HN>(\n adapter: PlatformAdapter<HN, HE>,\n vnode: VNode,\n): HN | null {\n const { type, children } = vnode;\n\n // 元素节点\n if (isString(type)) {\n const el = adapter.createElement(type);\n\n // 设置属性\n if (vnode.props) {\n for (const [key, value] of Object.entries(vnode.props)) {\n if (key === 'style' && isString(value)) {\n adapter.setStyle(el, value);\n } else if (key === 'class' && isString(value)) {\n adapter.addClass(el, value);\n } else if (isString(value)) {\n adapter.setAttribute(el, key, value);\n }\n }\n }\n\n // 递归处理子节点\n if (children && isString(children)) {\n adapter.setElementText(el, children);\n }\n\n return el as unknown as HN;\n }\n\n // 文本节点\n if (isString(children)) {\n return adapter.createText(children);\n }\n\n // 注释节点\n if (isFunction(type) === false && type !== null && !isString(type)) {\n // 非 string、非 function、非 null 的 type 可能是 Comment Symbol\n return adapter.createComment(String(children ?? ''));\n }\n\n return null;\n}\n"]}
package/dist/index.mjs CHANGED
@@ -20,9 +20,7 @@ var AdapterRegistry = class {
20
20
  */
21
21
  register(adapter) {
22
22
  if (!isString(adapter.name) || adapter.name.length === 0) {
23
- throw new Error(
24
- "[platform-adapter] \u9002\u914D\u5668\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"
25
- );
23
+ throw new Error("[platform-adapter] \u9002\u914D\u5668\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
26
24
  }
27
25
  this.adapters.set(adapter.name, adapter);
28
26
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/adapter-registry.ts","../src/create-renderer.ts"],"names":["isString"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\r\n * 平台适配器注册表\r\n *\r\n * @description\r\n * 管理所有已注册的平台适配器和插件,提供统一的注册、查询和插件管理能力。\r\n * 采用单例模式,全局共享同一个注册表实例。\r\n */\r\n\r\nimport { isString } from '@lytjs/common-is';\r\nimport type { PlatformAdapter, PlatformPlugin } from './types';\r\n\r\n/**\r\n * 适配器注册表类\r\n *\r\n * @description\r\n * 维护平台适配器的注册信息,支持适配器的注册、注销、查询,\r\n * 以及平台级插件的管理。\r\n */\r\nclass AdapterRegistry {\r\n /** 已注册的适配器映射(平台名称 -> 适配器实例) */\r\n private adapters = new Map<string, PlatformAdapter>();\r\n /** 平台插件映射(平台名称 -> 插件数组) */\r\n private plugins = new Map<string, PlatformPlugin[]>();\r\n\r\n /**\r\n * 注册平台适配器\r\n *\r\n * @description\r\n * 将适配器实例注册到注册表中,以适配器的 name 为键。\r\n * 如果同名适配器已存在,将被覆盖。\r\n *\r\n * @param adapter - 平台适配器实例\r\n * @throws {Error} 当 adapter.name 为空时抛出错误\r\n */\r\n register(adapter: PlatformAdapter): void {\r\n if (!isString(adapter.name) || adapter.name.length === 0) {\r\n throw new Error(\r\n '[platform-adapter] 适配器名称不能为空',\r\n );\r\n }\r\n this.adapters.set(adapter.name, adapter);\r\n }\r\n\r\n /**\r\n * 注销平台适配器\r\n *\r\n * @description\r\n * 从注册表中移除指定名称的适配器,同时清除该平台关联的所有插件。\r\n *\r\n * @param name - 平台名称\r\n * @returns 是否成功注销(名称不存在时返回 false)\r\n */\r\n unregister(name: string): boolean {\r\n const removed = this.adapters.delete(name);\r\n if (removed) {\r\n this.plugins.delete(name);\r\n }\r\n return removed;\r\n }\r\n\r\n /**\r\n * 获取指定名称的平台适配器\r\n *\r\n * @param name - 平台名称\r\n * @returns 适配器实例,未找到时返回 undefined\r\n */\r\n get(name: string): PlatformAdapter | undefined {\r\n return this.adapters.get(name);\r\n }\r\n\r\n /**\r\n * 检查指定名称的适配器是否已注册\r\n *\r\n * @param name - 平台名称\r\n * @returns 是否已注册\r\n */\r\n has(name: string): boolean {\r\n return this.adapters.has(name);\r\n }\r\n\r\n /**\r\n * 获取所有已注册的适配器名称\r\n *\r\n * @returns 平台名称数组\r\n */\r\n getNames(): string[] {\r\n return Array.from(this.adapters.keys());\r\n }\r\n\r\n /**\r\n * 为指定平台添加插件\r\n *\r\n * @description\r\n * 将插件添加到目标平台的插件列表中。\r\n * 如果目标平台不存在,会自动创建空的插件列表。\r\n *\r\n * @param platformName - 目标平台名称\r\n * @param plugin - 平台插件实例\r\n */\r\n addPlugin(platformName: string, plugin: PlatformPlugin): void {\r\n const existing = this.plugins.get(platformName);\r\n if (existing) {\r\n existing.push(plugin);\r\n } else {\r\n this.plugins.set(platformName, [plugin]);\r\n }\r\n }\r\n\r\n /**\r\n * 从指定平台移除插件\r\n *\r\n * @param platformName - 目标平台名称\r\n * @param pluginName - 要移除的插件名称\r\n * @returns 是否成功移除(插件不存在时返回 false)\r\n */\r\n removePlugin(platformName: string, pluginName: string): boolean {\r\n const list = this.plugins.get(platformName);\r\n if (!list) return false;\r\n\r\n const index = list.findIndex((p) => p.name === pluginName);\r\n if (index === -1) return false;\r\n\r\n list.splice(index, 1);\r\n return true;\r\n }\r\n\r\n /**\r\n * 获取指定平台的所有插件\r\n *\r\n * @param platformName - 目标平台名称\r\n * @returns 插件数组,平台无插件时返回空数组\r\n */\r\n getPlugins(platformName: string): PlatformPlugin[] {\r\n return this.plugins.get(platformName) ?? [];\r\n }\r\n}\r\n\r\n/** 全局适配器注册表单例 */\r\nexport const adapterRegistry = new AdapterRegistry();\r\n","/**\r\n * 跨平台渲染器工厂\r\n *\r\n * @description\r\n * 基于平台适配器创建渲染器实例,提供统一的 render/unmount API,\r\n * 屏蔽底层平台差异。\r\n */\r\n\r\nimport { isFunction, isString } from '@lytjs/common-is';\r\nimport type { VNode } from '@lytjs/common-vnode';\r\nimport type { PlatformAdapter, PlatformConfig } from './types';\r\n\r\n/**\r\n * 平台渲染器接口\r\n *\r\n * @description\r\n * 封装了平台适配器,提供高层的渲染和卸载 API。\r\n *\r\n * @template HN - 宿主节点类型\r\n * @template HE - 宿主元素类型(extends HN)\r\n */\r\nexport interface PlatformRenderer<HN, HE extends HN> {\r\n /**\r\n * 将 VNode 渲染到指定容器中\r\n *\r\n * @param vnode - 要渲染的虚拟节点\r\n * @param container - 宿主容器节点\r\n */\r\n render(vnode: VNode, container: HN): void;\r\n\r\n /**\r\n * 卸载指定容器中的内容\r\n *\r\n * @param container - 宿主容器节点\r\n */\r\n unmount(container: HN): void;\r\n\r\n /**\r\n * 获取关联的平台适配器\r\n *\r\n * @returns 平台适配器实例\r\n */\r\n getAdapter(): PlatformAdapter<HN, HE>;\r\n}\r\n\r\n/**\r\n * 创建平台渲染器\r\n *\r\n * @description\r\n * 工厂函数,基于给定的平台适配器和配置创建渲染器实例。\r\n * 渲染器内部委托适配器完成实际的 DOM 操作。\r\n *\r\n * @template HN - 宿主节点类型\r\n * @template HE - 宿主元素类型(extends HN)\r\n * @param adapter - 平台适配器实例\r\n * @param config - 平台配置(可选)\r\n * @returns 平台渲染器实例\r\n *\r\n * @example\r\n * ```typescript\r\n * const renderer = createPlatformRenderer(myAdapter, { debug: true });\r\n * renderer.render(vnode, container);\r\n * ```\r\n */\r\nexport function createPlatformRenderer<HN, HE extends HN>(\r\n adapter: PlatformAdapter<HN, HE>,\r\n config?: PlatformConfig,\r\n): PlatformRenderer<HN, HE> {\r\n // 当前容器中已渲染的子节点引用\r\n let currentChild: HN | null = null;\r\n\r\n const renderer: PlatformRenderer<HN, HE> = {\r\n /**\r\n * 将 VNode 渲染到容器中\r\n *\r\n * @description\r\n * 根据 vnode 类型创建对应的宿主节点,并插入到容器中。\r\n * 如果容器中已有内容,会先卸载再重新渲染。\r\n */\r\n render(vnode: VNode, container: HN): void {\r\n // 先卸载已有内容\r\n if (currentChild !== null) {\r\n this.unmount(container);\r\n }\r\n\r\n const node = createHostNodeFromVNode(adapter, vnode);\r\n if (node !== null) {\r\n adapter.insert(node, container, null);\r\n currentChild = node;\r\n }\r\n\r\n if (config?.debug) {\r\n // eslint-disable-next-line no-console\r\n console.log(`[platform-adapter:${adapter.name}] 渲染完成`, vnode);\r\n }\r\n },\r\n\r\n /**\r\n * 卸载容器中的内容\r\n */\r\n unmount(_container: HN): void {\r\n if (currentChild !== null) {\r\n adapter.remove(currentChild);\r\n currentChild = null;\r\n }\r\n\r\n if (config?.debug) {\r\n // eslint-disable-next-line no-console\r\n console.log(`[platform-adapter:${adapter.name}] 卸载完成`);\r\n }\r\n },\r\n\r\n /**\r\n * 获取关联的平台适配器\r\n */\r\n getAdapter(): PlatformAdapter<HN, HE> {\r\n return adapter;\r\n },\r\n };\r\n\r\n return renderer;\r\n}\r\n\r\n/**\r\n * 根据 VNode 类型创建宿主节点\r\n *\r\n * @description\r\n * 将 VNode 映射为平台适配器可操作的宿主节点。\r\n * 支持元素节点、文本节点和注释节点。\r\n *\r\n * @param adapter - 平台适配器\r\n * @param vnode - 虚拟节点\r\n * @returns 宿主节点,无法识别的类型返回 null\r\n */\r\nfunction createHostNodeFromVNode<HN, HE extends HN>(\r\n adapter: PlatformAdapter<HN, HE>,\r\n vnode: VNode,\r\n): HN | null {\r\n const { type, children } = vnode;\r\n\r\n // 元素节点\r\n if (isString(type)) {\r\n const el = adapter.createElement(type);\r\n\r\n // 设置属性\r\n if (vnode.props) {\r\n for (const [key, value] of Object.entries(vnode.props)) {\r\n if (key === 'style' && isString(value)) {\r\n adapter.setStyle(el, value);\r\n } else if (key === 'class' && isString(value)) {\r\n adapter.addClass(el, value);\r\n } else if (isString(value)) {\r\n adapter.setAttribute(el, key, value);\r\n }\r\n }\r\n }\r\n\r\n // 递归处理子节点\r\n if (children && isString(children)) {\r\n adapter.setElementText(el, children);\r\n }\r\n\r\n return el as unknown as HN;\r\n }\r\n\r\n // 文本节点\r\n if (isString(children)) {\r\n return adapter.createText(children);\r\n }\r\n\r\n // 注释节点\r\n if (isFunction(type) === false && type !== null && !isString(type)) {\r\n // 非 string、非 function、非 null 的 type 可能是 Comment Symbol\r\n return adapter.createComment(String(children ?? ''));\r\n }\r\n\r\n return null;\r\n}\r\n"]}
1
+ {"version":3,"sources":["../src/adapter-registry.ts","../src/create-renderer.ts"],"names":["isString"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * 平台适配器注册表\n *\n * @description\n * 管理所有已注册的平台适配器和插件,提供统一的注册、查询和插件管理能力。\n * 采用单例模式,全局共享同一个注册表实例。\n */\n\nimport { isString } from '@lytjs/common-is';\nimport type { PlatformAdapter, PlatformPlugin } from './types';\n\n/**\n * 适配器注册表类\n *\n * @description\n * 维护平台适配器的注册信息,支持适配器的注册、注销、查询,\n * 以及平台级插件的管理。\n */\nclass AdapterRegistry {\n /** 已注册的适配器映射(平台名称 -> 适配器实例) */\n private adapters = new Map<string, PlatformAdapter>();\n /** 平台插件映射(平台名称 -> 插件数组) */\n private plugins = new Map<string, PlatformPlugin[]>();\n\n /**\n * 注册平台适配器\n *\n * @description\n * 将适配器实例注册到注册表中,以适配器的 name 为键。\n * 如果同名适配器已存在,将被覆盖。\n *\n * @param adapter - 平台适配器实例\n * @throws {Error} 当 adapter.name 为空时抛出错误\n */\n register(adapter: PlatformAdapter): void {\n if (!isString(adapter.name) || adapter.name.length === 0) {\n throw new Error('[platform-adapter] 适配器名称不能为空');\n }\n this.adapters.set(adapter.name, adapter);\n }\n\n /**\n * 注销平台适配器\n *\n * @description\n * 从注册表中移除指定名称的适配器,同时清除该平台关联的所有插件。\n *\n * @param name - 平台名称\n * @returns 是否成功注销(名称不存在时返回 false)\n */\n unregister(name: string): boolean {\n const removed = this.adapters.delete(name);\n if (removed) {\n this.plugins.delete(name);\n }\n return removed;\n }\n\n /**\n * 获取指定名称的平台适配器\n *\n * @param name - 平台名称\n * @returns 适配器实例,未找到时返回 undefined\n */\n get(name: string): PlatformAdapter | undefined {\n return this.adapters.get(name);\n }\n\n /**\n * 检查指定名称的适配器是否已注册\n *\n * @param name - 平台名称\n * @returns 是否已注册\n */\n has(name: string): boolean {\n return this.adapters.has(name);\n }\n\n /**\n * 获取所有已注册的适配器名称\n *\n * @returns 平台名称数组\n */\n getNames(): string[] {\n return Array.from(this.adapters.keys());\n }\n\n /**\n * 为指定平台添加插件\n *\n * @description\n * 将插件添加到目标平台的插件列表中。\n * 如果目标平台不存在,会自动创建空的插件列表。\n *\n * @param platformName - 目标平台名称\n * @param plugin - 平台插件实例\n */\n addPlugin(platformName: string, plugin: PlatformPlugin): void {\n const existing = this.plugins.get(platformName);\n if (existing) {\n existing.push(plugin);\n } else {\n this.plugins.set(platformName, [plugin]);\n }\n }\n\n /**\n * 从指定平台移除插件\n *\n * @param platformName - 目标平台名称\n * @param pluginName - 要移除的插件名称\n * @returns 是否成功移除(插件不存在时返回 false)\n */\n removePlugin(platformName: string, pluginName: string): boolean {\n const list = this.plugins.get(platformName);\n if (!list) return false;\n\n const index = list.findIndex((p) => p.name === pluginName);\n if (index === -1) return false;\n\n list.splice(index, 1);\n return true;\n }\n\n /**\n * 获取指定平台的所有插件\n *\n * @param platformName - 目标平台名称\n * @returns 插件数组,平台无插件时返回空数组\n */\n getPlugins(platformName: string): PlatformPlugin[] {\n return this.plugins.get(platformName) ?? [];\n }\n}\n\n/** 全局适配器注册表单例 */\nexport const adapterRegistry = new AdapterRegistry();\n","/**\n * 跨平台渲染器工厂\n *\n * @description\n * 基于平台适配器创建渲染器实例,提供统一的 render/unmount API,\n * 屏蔽底层平台差异。\n */\n\nimport { isFunction, isString } from '@lytjs/common-is';\nimport type { VNode } from '@lytjs/common-vnode';\nimport type { PlatformAdapter, PlatformConfig } from './types';\n\n/**\n * 平台渲染器接口\n *\n * @description\n * 封装了平台适配器,提供高层的渲染和卸载 API。\n *\n * @template HN - 宿主节点类型\n * @template HE - 宿主元素类型(extends HN)\n */\nexport interface PlatformRenderer<HN, HE extends HN> {\n /**\n * 将 VNode 渲染到指定容器中\n *\n * @param vnode - 要渲染的虚拟节点\n * @param container - 宿主容器节点\n */\n render(vnode: VNode, container: HN): void;\n\n /**\n * 卸载指定容器中的内容\n *\n * @param container - 宿主容器节点\n */\n unmount(container: HN): void;\n\n /**\n * 获取关联的平台适配器\n *\n * @returns 平台适配器实例\n */\n getAdapter(): PlatformAdapter<HN, HE>;\n}\n\n/**\n * 创建平台渲染器\n *\n * @description\n * 工厂函数,基于给定的平台适配器和配置创建渲染器实例。\n * 渲染器内部委托适配器完成实际的 DOM 操作。\n *\n * @template HN - 宿主节点类型\n * @template HE - 宿主元素类型(extends HN)\n * @param adapter - 平台适配器实例\n * @param config - 平台配置(可选)\n * @returns 平台渲染器实例\n *\n * @example\n * ```typescript\n * const renderer = createPlatformRenderer(myAdapter, { debug: true });\n * renderer.render(vnode, container);\n * ```\n */\nexport function createPlatformRenderer<HN, HE extends HN>(\n adapter: PlatformAdapter<HN, HE>,\n config?: PlatformConfig,\n): PlatformRenderer<HN, HE> {\n // 当前容器中已渲染的子节点引用\n let currentChild: HN | null = null;\n\n const renderer: PlatformRenderer<HN, HE> = {\n /**\n * 将 VNode 渲染到容器中\n *\n * @description\n * 根据 vnode 类型创建对应的宿主节点,并插入到容器中。\n * 如果容器中已有内容,会先卸载再重新渲染。\n */\n render(vnode: VNode, container: HN): void {\n // 先卸载已有内容\n if (currentChild !== null) {\n this.unmount(container);\n }\n\n const node = createHostNodeFromVNode(adapter, vnode);\n if (node !== null) {\n adapter.insert(node, container, null);\n currentChild = node;\n }\n\n if (config?.debug) {\n // eslint-disable-next-line no-console\n console.log(`[platform-adapter:${adapter.name}] 渲染完成`, vnode);\n }\n },\n\n /**\n * 卸载容器中的内容\n */\n unmount(_container: HN): void {\n if (currentChild !== null) {\n adapter.remove(currentChild);\n currentChild = null;\n }\n\n if (config?.debug) {\n // eslint-disable-next-line no-console\n console.log(`[platform-adapter:${adapter.name}] 卸载完成`);\n }\n },\n\n /**\n * 获取关联的平台适配器\n */\n getAdapter(): PlatformAdapter<HN, HE> {\n return adapter;\n },\n };\n\n return renderer;\n}\n\n/**\n * 根据 VNode 类型创建宿主节点\n *\n * @description\n * 将 VNode 映射为平台适配器可操作的宿主节点。\n * 支持元素节点、文本节点和注释节点。\n *\n * @param adapter - 平台适配器\n * @param vnode - 虚拟节点\n * @returns 宿主节点,无法识别的类型返回 null\n */\nfunction createHostNodeFromVNode<HN, HE extends HN>(\n adapter: PlatformAdapter<HN, HE>,\n vnode: VNode,\n): HN | null {\n const { type, children } = vnode;\n\n // 元素节点\n if (isString(type)) {\n const el = adapter.createElement(type);\n\n // 设置属性\n if (vnode.props) {\n for (const [key, value] of Object.entries(vnode.props)) {\n if (key === 'style' && isString(value)) {\n adapter.setStyle(el, value);\n } else if (key === 'class' && isString(value)) {\n adapter.addClass(el, value);\n } else if (isString(value)) {\n adapter.setAttribute(el, key, value);\n }\n }\n }\n\n // 递归处理子节点\n if (children && isString(children)) {\n adapter.setElementText(el, children);\n }\n\n return el as unknown as HN;\n }\n\n // 文本节点\n if (isString(children)) {\n return adapter.createText(children);\n }\n\n // 注释节点\n if (isFunction(type) === false && type !== null && !isString(type)) {\n // 非 string、非 function、非 null 的 type 可能是 Comment Symbol\n return adapter.createComment(String(children ?? ''));\n }\n\n return null;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lytjs/platform-adapter",
3
- "version": "6.5.0",
3
+ "version": "6.7.0",
4
4
  "description": "LytJS 跨平台渲染适配器",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,10 +28,10 @@
28
28
  "clean": "rm -rf dist"
29
29
  },
30
30
  "dependencies": {
31
- "@lytjs/common-is": "^6.0.0",
32
- "@lytjs/common-constants": "^6.0.0",
33
- "@lytjs/vdom": "^6.0.0",
34
- "@lytjs/common-vnode": "^6.0.0"
31
+ "@lytjs/common-is": "^6.7.0",
32
+ "@lytjs/common-constants": "^6.7.0",
33
+ "@lytjs/vdom": "^6.7.0",
34
+ "@lytjs/common-vnode": "^6.7.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "tsup": "^8.0.0",