From 3581e2604bf55324f9b2bbfbfc91fc1dc7327ad6 Mon Sep 17 00:00:00 2001 From: unanmed <1319491857@qq.com> Date: Wed, 26 Mar 2025 22:06:06 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E8=87=AA=E5=8A=A8=E5=88=9B=E5=BB=BAAPI?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E7=9B=AE=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vitepress/api.ts | 97 +++++ docs/.vitepress/apiSidebar.ts | 338 +++++++++++++++ docs/.vitepress/config.ts | 302 +------------- .../api/motajs-render-elements/BlockCacher.md | 367 +++++++++++++++++ docs/api/motajs-render-elements/Camera.md | 384 ++++++++++++++++++ .../motajs-render-elements/CameraAnimation.md | 199 +++++++++ package.json | 3 +- packages/render-elements/src/block.ts | 7 +- packages/render-elements/src/camera.ts | 14 +- pnpm-lock.yaml | 85 ++++ 10 files changed, 1483 insertions(+), 313 deletions(-) create mode 100644 docs/.vitepress/api.ts create mode 100644 docs/.vitepress/apiSidebar.ts create mode 100644 docs/api/motajs-render-elements/BlockCacher.md create mode 100644 docs/api/motajs-render-elements/Camera.md create mode 100644 docs/api/motajs-render-elements/CameraAnimation.md diff --git a/docs/.vitepress/api.ts b/docs/.vitepress/api.ts new file mode 100644 index 0000000..3a9d98e --- /dev/null +++ b/docs/.vitepress/api.ts @@ -0,0 +1,97 @@ +import fs from 'fs-extra'; +import path from 'path'; +import chokidar from 'chokidar'; +import { DefaultTheme } from 'vitepress'; + +const apiDir = path.resolve('./docs/api'); +const sidebarConfigPath = path.resolve('./docs/.vitepress/apiSidebar.ts'); + +const weight: Record = { + 主页: 10, + 函数: 5 +}; + +function generateSidebar(): void { + const sidebar: DefaultTheme.SidebarItem[] = [ + { text: '目录', link: '/api/' } + ]; + + // 遍历 api 目录,查找 package 目录 + const packages = fs + .readdirSync(apiDir) + .filter(pkg => fs.statSync(path.join(apiDir, pkg)).isDirectory()); + + packages.forEach(pkg => { + const pkgPath = path.join(apiDir, pkg); + const files = fs + .readdirSync(pkgPath) + .filter(file => file.endsWith('.md')); + + const items: DefaultTheme.SidebarItem[] = files.map(file => { + const filePath = `api/${pkg}/${file}`; + const fileName = path.basename(file, '.md'); + + return { + text: + fileName === 'index' + ? '主页' + : fileName === 'functions' + ? '函数' + : fileName, + link: `/${filePath.replace(/\\/g, '/')}` // 兼容 Windows 路径 + }; + }); + + items.sort((a, b) => { + const titleA = a.text ?? ''; + const titleB = b.text ?? ''; + return (weight[titleA] ?? 0) - (weight[titleB] ?? 0); + }); + + sidebar.push({ + text: pkg, + collapsed: true, + items + }); + }); + + // 生成 sidebar.ts + const sidebarContent = `import { DefaultTheme } from 'vitepress'; + +export default ${JSON.stringify( + sidebar, + null, + 4 + )} as DefaultTheme.SidebarItem[];`; + fs.writeFileSync(sidebarConfigPath, sidebarContent); + console.log('✅ Sidebar 配置已更新'); +} + +// 初次运行 +generateSidebar(); + +// 监听文件变动 +chokidar + .watch(apiDir, { ignoreInitial: true }) + .on('add', filePath => { + console.log(`📄 文件新增: ${filePath}`); + generateSidebar(); + }) + .on('unlink', filePath => { + console.log(`❌ 文件删除: ${filePath}`); + generateSidebar(); + }) + .on('addDir', dirPath => { + console.log(`📁 目录新增: ${dirPath}`); + generateSidebar(); + }) + .on('unlinkDir', dirPath => { + console.log(`📁 目录删除: ${dirPath}`); + generateSidebar(); + }) + .on('raw', (event, path, details) => { + if (event === 'rename') { + console.log(`🔄 文件或文件夹重命名: ${path}`); + generateSidebar(); + } + }); diff --git a/docs/.vitepress/apiSidebar.ts b/docs/.vitepress/apiSidebar.ts new file mode 100644 index 0000000..1153d0d --- /dev/null +++ b/docs/.vitepress/apiSidebar.ts @@ -0,0 +1,338 @@ +import { DefaultTheme } from 'vitepress'; + +export default [ + { + "text": "目录", + "link": "/api/" + }, + { + "text": "motajs-client", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-client/index.md" + } + ] + }, + { + "text": "motajs-client-base", + "collapsed": true, + "items": [ + { + "text": "KeyCode", + "link": "/api/motajs-client-base/KeyCode.md" + }, + { + "text": "主页", + "link": "/api/motajs-client-base/index.md" + } + ] + }, + { + "text": "motajs-common", + "collapsed": true, + "items": [ + { + "text": "Logger", + "link": "/api/motajs-common/Logger.md" + }, + { + "text": "函数", + "link": "/api/motajs-common/functions.md" + }, + { + "text": "主页", + "link": "/api/motajs-common/index.md" + } + ] + }, + { + "text": "motajs-legacy-client", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-legacy-client/index.md" + } + ] + }, + { + "text": "motajs-legacy-common", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-legacy-common/index.md" + } + ] + }, + { + "text": "motajs-legacy-system", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-legacy-system/index.md" + } + ] + }, + { + "text": "motajs-legacy-ui", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-legacy-ui/index.md" + } + ] + }, + { + "text": "motajs-render", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-render/index.md" + } + ] + }, + { + "text": "motajs-render-core", + "collapsed": true, + "items": [ + { + "text": "Container", + "link": "/api/motajs-render-core/Container.md" + }, + { + "text": "ContainerCustom", + "link": "/api/motajs-render-core/ContainerCustom.md" + }, + { + "text": "Event", + "link": "/api/motajs-render-core/Event.md" + }, + { + "text": "GL2", + "link": "/api/motajs-render-core/GL2.md" + }, + { + "text": "GL2Program", + "link": "/api/motajs-render-core/GL2Program.md" + }, + { + "text": "MotaOffscreenCanvas2D", + "link": "/api/motajs-render-core/MotaOffscreenCanvas2D.md" + }, + { + "text": "MotaRenderer", + "link": "/api/motajs-render-core/MotaRenderer.md" + }, + { + "text": "RenderAdapter", + "link": "/api/motajs-render-core/RenderAdapter.md" + }, + { + "text": "RenderItem", + "link": "/api/motajs-render-core/RenderItem.md" + }, + { + "text": "Shader", + "link": "/api/motajs-render-core/Shader.md" + }, + { + "text": "ShaderProgram", + "link": "/api/motajs-render-core/ShaderProgram.md" + }, + { + "text": "Sprite", + "link": "/api/motajs-render-core/Sprite.md" + }, + { + "text": "Transform", + "link": "/api/motajs-render-core/Transform.md" + }, + { + "text": "函数", + "link": "/api/motajs-render-core/functions.md" + }, + { + "text": "主页", + "link": "/api/motajs-render-core/index.md" + } + ] + }, + { + "text": "motajs-render-elements", + "collapsed": true, + "items": [ + { + "text": "BlockCacher", + "link": "/api/motajs-render-elements/BlockCacher.md" + }, + { + "text": "Camera", + "link": "/api/motajs-render-elements/Camera.md" + }, + { + "text": "CameraAnimation", + "link": "/api/motajs-render-elements/CameraAnimation.md" + }, + { + "text": "主页", + "link": "/api/motajs-render-elements/index.md" + } + ] + }, + { + "text": "motajs-render-style", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-render-style/index.md" + } + ] + }, + { + "text": "motajs-render-vue", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-render-vue/index.md" + } + ] + }, + { + "text": "motajs-system", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-system/index.md" + } + ] + }, + { + "text": "motajs-system-action", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-system-action/index.md" + } + ] + }, + { + "text": "motajs-system-ui", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-system-ui/index.md" + } + ] + }, + { + "text": "motajs-types", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/motajs-types/index.md" + } + ] + }, + { + "text": "user-client-modules", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-client-modules/index.md" + } + ] + }, + { + "text": "user-data-base", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-data-base/index.md" + } + ] + }, + { + "text": "user-data-fallback", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-data-fallback/index.md" + } + ] + }, + { + "text": "user-data-state", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-data-state/index.md" + } + ] + }, + { + "text": "user-data-utils", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-data-utils/index.md" + } + ] + }, + { + "text": "user-entry-client", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-entry-client/index.md" + } + ] + }, + { + "text": "user-entry-data", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-entry-data/index.md" + } + ] + }, + { + "text": "user-legacy-plugin-client", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-legacy-plugin-client/index.md" + } + ] + }, + { + "text": "user-legacy-plugin-data", + "collapsed": true, + "items": [ + { + "text": "主页", + "link": "/api/user-legacy-plugin-data/index.md" + } + ] + } +] as DefaultTheme.SidebarItem[]; \ No newline at end of file diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 6cc0b65..bccf639 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,5 +1,6 @@ import { defineConfig } from 'vitepress'; import { MermaidMarkdown, MermaidPlugin } from 'vitepress-plugin-mermaid'; +import api from './apiSidebar'; // https://vitepress.dev/reference/site-config export default defineConfig({ @@ -69,306 +70,7 @@ export default defineConfig({ '/api/': [ { text: 'API 列表', - items: [ - { text: '目录', link: '/api/' }, - { - text: '@motajs/client', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-client/' } - ] - }, - { - text: '@motajs/client-base', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-client-base/' - }, - { - text: 'KeyCode', - link: '/api/motajs-client-base/KeyCode' - } - ] - }, - { - text: '@motajs/common', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-common/' }, - { - text: '函数', - link: '/api/motajs-common/functions' - }, - { - text: 'Logger', - link: '/api/motajs-common/Logger' - } - ] - }, - { - text: '@motajs/legacy-client', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-legacy-client/' - } - ] - }, - { - text: '@motajs/legacy-common', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-legacy-common/' - } - ] - }, - { - text: '@motajs/legacy-system', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-legacy-system/' - } - ] - }, - { - text: '@motajs/legacy-ui', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-legacy-ui/' } - ] - }, - { - text: '@motajs/render', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-render/' } - ] - }, - { - text: '@motajs/render-core', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-render-core/' - }, - { - text: '函数', - link: '/api/motajs-render-core/functions' - }, - { - text: '交互事件', - link: '/api/motajs-render-core/Event' - }, - { - text: 'MotaOffscreenCanvas2D', - link: '/api/motajs-render-core/MotaOffscreenCanvas2D' - }, - { - text: 'Transform', - link: '/api/motajs-render-core/Transform' - }, - { - text: 'RenderItem', - link: '/api/motajs-render-core/RenderItem' - }, - { - text: 'Container', - link: '/api/motajs-render-core/Container' - }, - { - text: 'ContainerCustom', - link: '/api/motajs-render-core/ContainerCustom' - }, - { - text: 'Sprite', - link: '/api/motajs-render-core/Sprite' - }, - { - text: 'MotaRenderer', - link: '/api/motajs-render-core/MotaRenderer' - }, - { - text: 'GL2', - link: '/api/motajs-render-core/GL2' - }, - { - text: 'GL2Program', - link: '/api/motajs-render-core/GL2Program' - }, - { - text: 'RenderAdapter', - link: '/api/motajs-render-core/RenderAdapter' - }, - { - text: 'Shader', - link: '/api/motajs-render-core/Shader' - }, - { - text: 'ShaderProgram', - link: '/api/motajs-render-core/ShaderProgram' - } - ] - }, - { - text: '@motajs/render-elements', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-render-elements/' - } - ] - }, - { - text: '@motajs/render-style', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-render-style/' - } - ] - }, - { - text: '@motajs/render-vue', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-render-vue/' - } - ] - }, - { - text: '@motajs/system', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-system/' } - ] - }, - { - text: '@motajs/system-action', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/motajs-system-action/' - } - ] - }, - { - text: '@motajs/system-ui', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-system-ui/' } - ] - }, - { - text: '@motajs/types', - collapsed: true, - items: [ - { text: '主页', link: '/api/motajs-types/' } - ] - }, - { - text: '@user/client-modules', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-client-modules/' - } - ] - }, - { - text: '@user/data-base', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-data-base/' - } - ] - }, - { - text: '@user/data-fallback', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-data-fallback/' - } - ] - }, - { - text: '@user/data-state', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-data-state/' - } - ] - }, - { - text: '@user/data-utils', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-data-utils/' - } - ] - }, - { - text: '@user/entry-client', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-entry-client/' - } - ] - }, - { - text: '@user/entry-data', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-entry-data/' - } - ] - }, - { - text: '@user/legacy-plugin-client', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-legacy-plugin-client/' - } - ] - }, - { - text: '@user/legacy-plugin-data', - collapsed: true, - items: [ - { - text: '主页', - link: '/api/user-legacy-plugin-data/' - } - ] - } - ] + items: api } ] }, diff --git a/docs/api/motajs-render-elements/BlockCacher.md b/docs/api/motajs-render-elements/BlockCacher.md new file mode 100644 index 0000000..1b6882e --- /dev/null +++ b/docs/api/motajs-render-elements/BlockCacher.md @@ -0,0 +1,367 @@ +# BlockCacher API 文档 + +本文档由 `DeepSeek R1` 模型生成并微调。 + +--- + +```mermaid +graph LR + BlockCacher --> EventEmitter +``` + +_继承自 `EventEmitter`,支持事件监听。_ + +--- + +## 属性说明 + +| 属性名 | 类型 | 描述 | +| ------------ | ---------------- | ------------------------------------------------------------------- | +| `width` | `number` | 区域总宽度(元素单位) | +| `height` | `number` | 区域总高度(元素单位) | +| `blockSize` | `number` | 单个分块的大小(元素单位) | +| `blockData` | `BlockData` | 分块计算结果(包含分块数量、最后一个块的尺寸等信息) | +| `cacheDepth` | `number` | 缓存深度(每个分块可存储多个缓存层) | +| `cache` | `Map` | 缓存存储结构,键为精确索引(`(x + y * blockWidth) * depth + deep`) | + +--- + +## 构造方法 + +### `constructor` + +```typescript +function constructor( + width: number, + height: number, + size: number, + depth?: number +): BlockCacher; +``` + +创建分块缓存管理器并自动计算初始分块。 +**示例:** + +```typescript +const cacher = new BlockCacher(800, 600, 64); // 800x600区域,64为分块大小 +``` + +--- + +## 方法说明 + +### `size` + +```typescript +function size(width: number, height: number): void; +``` + +重置区域尺寸并重新分块(触发 `split` 事件)。 +**示例:** + +```typescript +cacher.size(1024, 768); // 重置为1024x768区域 +``` + +### `setBlockSize` + +```typescript +function setBlockSize(size: number): void; +``` + +修改分块尺寸并重新分块(触发 `split` 事件)。 +**示例:** + +```typescript +cacher.setBlockSize(128); // 分块大小改为128 +``` + +### `setCacheDepth` + +```typescript +function setCacheDepth(depth: number): void; +``` + +调整缓存深度(最大 31),自动迁移旧缓存。 +**示例:** + +```typescript +cacher.setCacheDepth(3); // 每个分块支持3层缓存 +``` + +### `split` + +```typescript +function split(): void; +``` + +重新计算分块数据并触发 `'split'` 事件。 +**示例:** + +```typescript +cacher.split(); // 手动触发分块计算(一般无需调用) +``` + +### `clearCache` + +```typescript +function clearCache(index: number, deep: number): void; +``` + +清除指定分块索引的缓存(按二进制掩码清除深度)。 +**示例:** + +```typescript +cacher.clearCache(5, 0b101); // 清除分块5的第0层和第2层缓存 +``` + +### `clearCacheByIndex` + +```typescript +function clearCacheByIndex(index: number): void; +``` + +直接按精确索引清除单个缓存。 +**示例:** + +```typescript +cacher.clearCacheByIndex(42); // 清除精确索引42对应的缓存 +``` + +### `clearAllCache` + +```typescript +function clearAllCache(): void; +``` + +清空所有缓存并销毁关联资源。 +**示例:** + +```typescript +cacher.clearAllCache(); // 完全重置缓存 +``` + +### `getIndex` + +```typescript +function getIndex(x: number, y: number): number; +``` + +根据分块坐标获取分块索引(分块坐标 -> 分块索引)。 +**示例:** + +```typescript +const index = cacher.getIndex(2, 3); // 获取(2,3)分块的索引 +``` + +### `getIndexByLoc` + +```typescript +function getIndexByLoc(x: number, y: number): number; +``` + +根据元素坐标获取所属分块索引(元素坐标 -> 分块索引)。 +**示例:** + +```typescript +const index = cacher.getIndexByLoc(150, 200); // 元素坐标(150,200)所在分块索引 +``` + +### `getBlockXYByIndex` + +```typescript +function getBlockXYByIndex(index: number): [number, number]; +``` + +根据分块索引获取分块坐标(分块索引 -> 分块坐标)。 +**示例:** + +```typescript +const [x, y] = cacher.getBlockXYByIndex(5); // 分块5的坐标 +``` + +### `getBlockXY` + +```typescript +function getBlockXY(x: number, y: number): [number, number]; +``` + +获取一个元素位置所在的分块位置(即使它不在任何分块内)(元素索引 -> 分块坐标)。 +**示例:** + +```typescript +const [x, y] = cacher.getBlockXY(11, 24); // 指定位置所在分块位置 +``` + +### `getPreciseIndex` + +```typescript +function getPreciseIndex(x: number, y: number, deep: number): number; +``` + +根据分块坐标与 `deep` 获取一个分块的精确索引(分块坐标 -> 分块索引)。 +**示例:** + +```typescript +const index = cacher.getPreciseIndex(2, 1, 3); // 指定分块的索引 +``` + +### `getPreciseIndexByLoc` + +```typescript +function getPreciseIndexByLoc(x: number, y: number, deep: number): number; +``` + +根据元素坐标及 `deep` 获取元素所在块的精确索引(元素坐标 -> 分块索引)。 +**示例:** + +```typescript +const index = cacher.getPreciseIndexByLoc(22, 11, 3); // 指定元素所在分块的索引 +``` + +### `updateElementArea` + +```typescript +function updateElementArea( + x: number, + y: number, + width: number, + height: number, + deep: number = 2 ** 31 - 1 +): Set; +``` + +根据元素区域清除相关分块缓存(返回受影响的分块索引集合)(元素坐标->分块清空)。 +**示例:** + +```typescript +const blocks = cacher.updateElementArea(100, 100, 200, 200); // 清除200x200区域内的缓存 +``` + +### `updateArea` + +```typescript +function updateArea( + x: number, + y: number, + width: number, + height: number, + deep: number = 2 ** 31 - 1 +): Set; +``` + +更新指定分块区域内的缓存(注意坐标是分块坐标,而非元素坐标)(分块坐标->分块清空)。 +**示例:** + +```typescript +const blocks = cacher.updateArea(1, 1, 1, 1); // 清除指定分块区域内的缓存 +``` + +### `getIndexOf` + +```typescript +function getIndexOf( + x: number, + y: number, + width: number, + height: number +): Set; +``` + +传入分块坐标与范围,获取该区域内包含的所有分块索引(分块坐标->分块索引集合)。 +**示例:** + +```typescript +const blocks = cacher.getIndexOf(1, 1, 1, 1); // 清除指定分块区域内的缓存 +``` + +### `getIndexOfElement` + +```typescript +function getIndexOfElement( + x: number, + y: number, + width: number, + height: number +): Set; +``` + +传入元素坐标与范围,获取该区域内包含的所有分块索引(元素坐标->分块索引集合)。 +**示例:** + +```typescript +const blocks = cacher.getIndexOfElement(3, 5, 12, 23); // 清除指定元素区域内的缓存 +``` + +### `getRectOfIndex` + +```typescript +function getRectOfIndex(block: number): [number, number, number, number]; +``` + +获取分块索引对应的元素坐标范围(分块索引 -> 元素矩形坐标)。 +**示例:** + +```typescript +const [x1, y1, x2, y2] = cacher.getRectOfIndex(5); // 分块5的坐标范围 +``` + +### `getRectOfBlockXY` + +```typescript +function getRectOfBlockXY( + x: number, + y: number +): [number, number, number, number]; +``` + +根据分块坐标,获取这个分块所在区域的元素矩形范围(左上角横纵坐标及右下角横纵坐标)(分块坐标 -> 元素矩形坐标)。 +**示例:** + +```typescript +const [x1, y1, x2, y2] = cacher.getRectOfIndex(5); // 分块5的坐标范围 +``` + +### `destroy` + +```typescript +function destroy(): void; +``` + +摧毁这个块缓存。 + +--- + +## 事件说明 + +| 事件名 | 参数 | 描述 | +| ------- | ---- | ------------------ | +| `split` | 无 | 分块参数变更时触发 | + +--- + +## 总使用示例 + +```typescript +// 创建缓存管理器 +const cacheManager = new BlockCacher(1024, 768, 64); + +// 监听分块变化 +cacheManager.on('split', () => { + console.log('分块已重新计算'); +}); + +// 添加测试缓存项 +const blockIndex = cacheManager.getIndex(2, 3); +const preciseIndex = cacheManager.getPreciseIndex(2, 3, 0); +cacheManager.cache.set( + preciseIndex, + new CanvasCacheItem(new MotaOffscreenCanvas2D(), 1) +); + +// 清除特定区域缓存 +cacheManager.updateElementArea(150, 150, 100, 100); + +// 销毁管理器 +cacheManager.destroy(); +``` diff --git a/docs/api/motajs-render-elements/Camera.md b/docs/api/motajs-render-elements/Camera.md new file mode 100644 index 0000000..a154b9d --- /dev/null +++ b/docs/api/motajs-render-elements/Camera.md @@ -0,0 +1,384 @@ +# Camera API 文档 + +本文档由 `DeepSeek R1` 模型生成并微调。 + +--- + +```mermaid +graph LR + Camera --> EventEmitter +``` + +_继承自 `EventEmitter`,支持事件监听。_ + +--- + +## 属性说明 + +| 属性名 | 类型 | 描述 | +| --------------------- | ------------------- | ------------------------------------------------ | +| `readonly binded` | `RenderItem` | 当前绑定的渲染元素 | +| `transform` | `Transform` | 目标变换矩阵,默认与 `binded.transform` 共享引用 | +| `protected operation` | `CameraOperation[]` | 当前应用的变换操作列表(平移/旋转/缩放) | + +--- + +## 构造方法 + +### `Camera.for` + +```typescript + function for(item: RenderItem): Camera +``` + +获取或创建与渲染元素关联的摄像机实例。 +**示例:** + +```typescript +const item = new RenderItem(); +const camera = Camera.for(item); // 获取或创建摄像机 +``` + +### `constructor` + +```typescript +function constructor(item: RenderItem): Camera; +``` + +直接创建摄像机实例(不会自动注册到全局映射)。 +**注意:** 推荐优先使用 `Camera.for()` 方法。 + +--- + +## 方法说明 + +### `disable` + +```typescript +function disable(): void; +``` + +禁用摄像机变换效果。 +**示例:** + +```typescript +camera.disable(); // 暂停所有摄像机变换 +``` + +### `enable` + +```typescript +function enable(): void; +``` + +启用摄像机变换效果。 + +### `requestUpdate` + +```typescript +function requestUpdate(): void; +``` + +请求在下一帧强制更新变换矩阵。 + +### `removeOperation` + +```typescript +function removeOperation(operation: CameraOperation): void; +``` + +移除一个变换操作。 +**参数说明** + +- `operation`: 要移除的操作 + +**示例** + +```ts +const operation = camera.addTranslate(); +camera.removeOperation(operation); +``` + +### `clearOperation` + +```ts +function clearOperation(): void; +``` + +清空变换操作列表。 + +### `addTranslate` + +```typescript +function addTranslate(): ICameraTranslate; +``` + +添加平移操作并返回操作对象。 +**示例:** + +```typescript +const translateOp = camera.addTranslate(); +translateOp.x = 100; // 设置横向偏移 +camera.requestUpdate(); +``` + +### `addRotate` + +```typescript +function addRotate(): ICameraRotate; +``` + +添加旋转操作并返回操作对象。 +**示例:** + +```typescript +const rotateOp = camera.addRotate(); +rotateOp.angle = Math.PI / 2; // 设置90度旋转 +camera.requestUpdate(); +``` + +### `addScale` + +```typescript +function addScale(): ICameraScale; +``` + +添加缩放操作并返回操作对象。 +**示例:** + +```typescript +const scaleOp = camera.addScale(); +scaleOp.x = 2; // 横向放大2倍 +camera.requestUpdate(); +``` + +### `applyAnimation` + +```ts +function applyAnimation(time: number, update: () => void): void; +``` + +施加动画。 + +**参数说明** + +- `time`: 动画时长。 +- `update`: 每帧执行的更新函数。 + +### `applyTranslateAnimation` + +```typescript +function applyTranslateAnimation( + operation: ICameraTranslate, + animate: Animation, + time: number +): void; +``` + +为平移操作绑定动画。 +**参数说明:** + +- `animate`: 预定义的动画实例 +- `time`: 动画持续时间(毫秒) + +### `applyRotateAnimation` + +```typescript +function applyRotateAnimation( + operation: ICameraRotate, + animate: Animation, + time: number +): void; +``` + +为旋转操作绑定动画。 + +### `applyScaleAnimation` + +```typescript +function applyScaleAnimation( + operation: ICameraScale, + animate: Animation, + time: number +): void; +``` + +为缩放操作绑定动画。 + +### `applyTranslateTransition` + +```typescript +function applyTranslateTransition( + operation: ICameraTranslate, + animate: Transition, + time: number +): void; +``` + +为平移操作绑定渐变。 +**参数说明:** + +- `animate`: 预定义的渐变实例 +- `time`: 渐变持续时间(毫秒) + +### `applyRotateTransition` + +```typescript +function applyRotateTransition( + operation: ICameraRotate, + animate: Transition, + time: number +): void; +``` + +为旋转操作绑定渐变。 + +### `applyScaleTransition` + +```typescript +function applyScaleTransition( + operation: ICameraScale, + animate: Transition, + time: number +): void; +``` + +为缩放操作绑定渐变。 + +### `stopAllAnimates` + +```ts +function stopAllAnimates(): void; +``` + +停止所有动画。 + +### `destroy` + +```typescript +function destroy(): void; +``` + +销毁摄像机并释放所有资源。 +**示例:** + +```typescript +camera.destroy(); // 解除绑定并清理动画 +``` + +--- + +## 事件说明 + +| 事件名 | 参数 | 描述 | +| --------- | ---- | ------------------ | +| `destroy` | 无 | 摄像机被销毁时触发 | + +--- + +## 总使用示例 + +::: code-group + +```typescript [动画] +import { Animation, linear } from 'mutate-animate'; + +// 获取摄像机实例 +const item = new Sprite(); +const camera = Camera.for(item); + +// 添加平移和缩放操作 +const translate = camera.addTranslate(); +const scale = camera.addScale(); + +// 创建动画实例 +const anim = new Animation() + .mode(linear()) + .time(1000) + .move(100, 100) + .time(800) + .scale(1.5); + +// 绑定动画 +camera.applyTranslateAnimation(translate, anim, 1000); +camera.applyScaleAnimation(scale, anim, 800); + +// 启用摄像机 +camera.enable(); + +// 销毁(当不再需要时) +setTimeout(() => camera.destroy(), 2000); +``` + +```typescript [渐变] +import { Transition, hyper } from 'mutate-animate'; +// 获取摄像机实例 +const item = new Sprite(); +const camera = Camera.for(item); + +// 添加平移和缩放操作 +const translate = camera.addTranslate(); +const scale = camera.addScale(); + +// 创建渐变实例,使用双曲正弦速率曲线 +const tran = new Transition().mode(hyper('sin', 'out')).time(1000); + +// 初始化参数,这一步不会执行渐变 +tran.value.x = 0; +tran.value.y = 0; +tran.value.size = 0; + +// 对参数执行渐变,直接设置即可 +tran.value.x = 100; +tran.value.y = 200; +tran.time(800); // 设置渐变时长为 800 毫秒 +tran.value.size = 1.5; + +// 绑定动画 +camera.applyTranslateTransition(translate, tran, 1000); +camera.applyScaleTransition(scale, tran, 800); + +// 启用摄像机 +camera.enable(); + +// 销毁(当不再需要时) +setTimeout(() => camera.destroy(), 2000); +``` + +::: + +--- + +## 接口说明 + +### `ICameraTranslate` + +```typescript +interface ICameraTranslate { + readonly type: 'translate'; + readonly from: RenderItem; + x: number; // 横向偏移量 + y: number; // 纵向偏移量 +} +``` + +### `ICameraRotate` + +```typescript +interface ICameraRotate { + readonly type: 'rotate'; + readonly from: RenderItem; + angle: number; // 旋转弧度值 +} +``` + +### `ICameraScale` + +```typescript +interface ICameraScale { + readonly type: 'scale'; + readonly from: RenderItem; + x: number; // 横向缩放比 + y: number; // 纵向缩放比 +} +``` diff --git a/docs/api/motajs-render-elements/CameraAnimation.md b/docs/api/motajs-render-elements/CameraAnimation.md new file mode 100644 index 0000000..2386687 --- /dev/null +++ b/docs/api/motajs-render-elements/CameraAnimation.md @@ -0,0 +1,199 @@ +# CameraAnimation API 文档 + +本文档由 `DeepSeek R1` 模型生成并微调。 + +--- + +```mermaid +graph LR + CameraAnimation --> EventEmitter +``` + +_继承自 `EventEmitter`,支持事件监听。_ + +--- + +## 属性说明 + +| 属性名 | 类型 | 描述 | +| -------- | -------- | ---------------- | +| `camera` | `Camera` | 关联的摄像机实例 | + +--- + +## 构造方法 + +### `constructor` + +```typescript +function constructor(camera: Camera): CameraAnimation; +``` + +创建摄像机动画管理器,需绑定到特定 `Camera` 实例。 +**示例:** + +```typescript +const camera = Camera.for(renderItem); +const animation = new CameraAnimation(camera); +``` + +--- + +## 方法说明 + +### `translate` + +```typescript +function translate( + operation: ICameraTranslate, + x: number, + y: number, + time: number, + start: number, + timing: TimingFn +): void; +``` + +为平移操作添加动画。 +**参数说明:** + +- `x`, `y`: 目标偏移量(格子坐标,自动乘以 `32`,之后可能改动) +- `time`: 动画持续时间(毫秒) +- `start`: 动画开始时间(相对于总动画开始的延迟) +- `timing`: 缓动函数(输入时间完成度,输出动画完成度) + +### `rotate` + +```typescript +function rotate( + operation: ICameraRotate, + angle: number, + time: number, + start: number, + timing: TimingFn +): void; +``` + +为旋转操作添加动画。 +**参数说明:** + +- `angle`: 目标旋转弧度(如 `Math.PI` 表示 `180` 度) +- 其余参考[`rotate`](#rotate) + +### `scale` + +```typescript +function scale( + operation: ICameraScale, + scale: number, + time: number, + start: number, + timing: TimingFn +): void; +``` + +为缩放操作添加动画。 +**参数说明:** + +- `scale`: 目标缩放倍率(如 `1.5` 表示放大 `1.5` 倍) +- 其余参考[`rotate`](#rotate) + +### `start` + +```typescript +function start(): void; +``` + +启动所有已添加的动画,按时间顺序执行。 +**注意:** 调用后动画将按 `start` 参数定义的顺序触发。 + +### `destroy` + +```typescript +function destroy(): void; +``` + +销毁动画管理器并释放所有资源(停止未完成的动画)。 + +--- + +## 事件说明 + +| 事件名 | 参数 | 描述 | +| --------- | -------------------------------------------------------------------------------------------------------- | ---------------------------- | +| `animate` | `operation: CameraOperation`
`execution: CameraAnimationExecution`
`item: CameraAnimationData` | 当某个动画片段开始执行时触发 | + +--- + +## 总使用示例 + +```typescript +import { hyper, trigo } from 'mutate-animate'; + +// 创建渲染元素和摄像机 +const renderItem = new Sprite(); +const camera = Camera.for(renderItem); + +// 添加平移和旋转操作 +const translateOp = camera.addTranslate(); +const rotateOp = camera.addRotate(); + +// 创建动画管理器 +const animation = new CameraAnimation(camera); + +// 添加平移动画:1秒后开始,持续2秒,横向移动3格(3*32像素) +animation.translate( + translateOp, + 3, + 0, // x=3, y=0(自动乘32) + 2000, // 动画时长2秒 + 1000, // 延迟1秒开始 + hyper('sin', 'out') // 双曲正弦函数 +); + +// 添加旋转动画:立即开始,持续1.5秒,旋转180度 +animation.rotate( + rotateOp, + Math.PI, // 目标角度(弧度) + 1500, // 动画时长1.5秒 + 0, // 无延迟 + trigo('sin', 'out') // 正弦函数 +); + +// 启动动画 +animation.start(); + +// 监听动画事件 +animation.on('animate', (operation, execution, item) => { + console.log('动画片段开始:', item.type); +}); + +// 销毁(动画结束后) +setTimeout(() => { + animation.destroy(); + camera.destroy(); +}, 5000); +``` + +--- + +## 接口说明 + +### `CameraAnimationExecution` + +```typescript +interface { + data: CameraAnimationData[]; // 动画片段列表 + animation: Animation; // 关联的动画实例 +} +``` + +### `CameraAnimationData` + +```typescript +type CameraAnimationData = + | TranslateAnimation + | TranslateAsAnimation + | RotateAnimation + | ScaleAnimation; +``` diff --git a/package.json b/package.json index 0d5d47e..d5a550b 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "lines": "tsx script/lines.ts packages packages-user", "build:packages": "vue-tsx --noEmit && tsx script/build-packages.ts", "build:game": "vue-tsx --noEmit && tsx script/build-game.ts", - "docs:dev": "vitepress dev docs", + "docs:dev": "concurrently -k -n 'SIDEBAR,VITEPRESS' -c 'blue,green' \"tsx docs/.vitepress/api.ts\" \"vitepress dev docs\"", "docs:build": "vitepress build docs", "docs:preview": "vitepress preview docs" }, @@ -59,6 +59,7 @@ "@vitejs/plugin-vue-jsx": "^4.1.2", "chokidar": "^3.6.0", "compressing": "^1.10.1", + "concurrently": "^9.1.2", "eslint": "^9.22.0", "eslint-plugin-prettier": "^5.2.3", "eslint-plugin-vue": "^9.33.0", diff --git a/packages/render-elements/src/block.ts b/packages/render-elements/src/block.ts index dca40a5..cbebdcd 100644 --- a/packages/render-elements/src/block.ts +++ b/packages/render-elements/src/block.ts @@ -137,7 +137,7 @@ export class BlockCacher< } /** - * 清空指定索引的缓存,与 {@link clearCache} 不同的是,这里会直接清空对应索引的缓存,而不是指定分块的缓存(分块->void) + * 清空指定索引的缓存,与 {@link clearCache} 不同的是,这里会直接清空对应索引的缓存,而不是指定分块的缓存(元素->void) */ clearCacheByIndex(index: number) { const item = this.cache.get(index); @@ -303,10 +303,7 @@ export interface ICanvasCacheItem extends IBlockCacheable { } export class CanvasCacheItem implements ICanvasCacheItem { - constructor( - public canvas: MotaOffscreenCanvas2D, - public symbol: number - ) {} + constructor(public canvas: MotaOffscreenCanvas2D, public symbol: number) {} destroy(): void { this.canvas.delete(); diff --git a/packages/render-elements/src/camera.ts b/packages/render-elements/src/camera.ts index 125ba53..c25469b 100644 --- a/packages/render-elements/src/camera.ts +++ b/packages/render-elements/src/camera.ts @@ -80,7 +80,7 @@ export class Camera extends EventEmitter { }); const ca = Camera.cameraMap.get(item); - if (ca && !ca.enabled) { + if (ca && ca.enabled) { logger.warn(22); } } @@ -371,40 +371,40 @@ interface CameraAnimationBase { start: number; } -interface TranslateAnimation extends CameraAnimationBase { +export interface TranslateAnimation extends CameraAnimationBase { type: 'translate'; timing: TimingFn; x: number; y: number; } -interface TranslateAsAnimation extends CameraAnimationBase { +export interface TranslateAsAnimation extends CameraAnimationBase { type: 'translateAs'; timing: TimingFn<2>; time: number; } -interface RotateAnimation extends CameraAnimationBase { +export interface RotateAnimation extends CameraAnimationBase { type: 'rotate'; timing: TimingFn; angle: number; time: number; } -interface ScaleAnimation extends CameraAnimationBase { +export interface ScaleAnimation extends CameraAnimationBase { type: 'scale'; timing: TimingFn; scale: number; time: number; } -type CameraAnimationData = +export type CameraAnimationData = | TranslateAnimation | TranslateAsAnimation | RotateAnimation | ScaleAnimation; -interface CameraAnimationExecution { +export interface CameraAnimationExecution { data: CameraAnimationData[]; animation: Animation; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8c9c7ed..1f32aa2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -123,6 +123,9 @@ importers: compressing: specifier: ^1.10.1 version: 1.10.1 + concurrently: + specifier: ^9.1.2 + version: 9.1.2 eslint: specifier: ^9.22.0 version: 9.22.0 @@ -2831,6 +2834,10 @@ packages: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clone-buffer@1.0.0: resolution: {integrity: sha512-KLLTJWrvwIP+OPfMn0x2PheDEP20RPUcGXj/ERegTgdmPEZylALQldygiqrPPu8P45uNuPs7ckmReLY6v/iA5g==} engines: {node: '>= 0.10'} @@ -2922,6 +2929,11 @@ packages: resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} engines: {'0': node >= 6.0} + concurrently@9.1.2: + resolution: {integrity: sha512-H9MWcoPsYddwbOGM6difjVwVZHl63nwMEwDJG/L7VGtuaJhb12h2caPG2tVPWs7emuYix252iGfqOyrz1GczTQ==} + engines: {node: '>=18'} + hasBin: true + confbox@0.1.8: resolution: {integrity: sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==} @@ -3634,6 +3646,10 @@ packages: resolution: {integrity: sha512-MtjsmYiCXcYDDrGqtNbeIYdAl85n+5mSv2r3FbzER/YV3ZILw4HNNIw34HuV5pyl0jzs6GFYU1VHVEefhgcNHQ==} engines: {node: '>=18'} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + get-intrinsic@1.3.0: resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} engines: {node: '>= 0.4'} @@ -4920,6 +4936,10 @@ packages: resolution: {integrity: sha512-UszKE5KVK6JvyD92nzMn9cDapSk6w/CaFZ96CnmDMUqH9oowfxF/ZjRITD25H4DnOQClLA4/j7jLGXXLVKxAug==} engines: {node: '>= 10'} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -4998,6 +5018,9 @@ packages: rw@1.3.3: resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==} + rxjs@7.8.2: + resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} @@ -5063,6 +5086,10 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shell-quote@1.8.2: + resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + engines: {node: '>= 0.4'} + shiki@2.5.0: resolution: {integrity: sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ==} @@ -5291,6 +5318,10 @@ packages: tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -5710,6 +5741,10 @@ packages: resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} engines: {node: '>=0.4'} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yallist@3.1.1: resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} @@ -5720,6 +5755,14 @@ packages: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yazl@2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} @@ -8300,6 +8343,12 @@ snapshots: cli-spinners@2.9.2: {} + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clone-buffer@1.0.0: {} clone-stats@0.0.1: {} @@ -8377,6 +8426,16 @@ snapshots: readable-stream: 3.6.2 typedarray: 0.0.6 + concurrently@9.1.2: + dependencies: + chalk: 4.1.2 + lodash: 4.17.21 + rxjs: 7.8.2 + shell-quote: 1.8.2 + supports-color: 8.1.1 + tree-kill: 1.2.2 + yargs: 17.7.2 + confbox@0.1.8: {} confbox@0.2.1: {} @@ -9210,6 +9269,8 @@ snapshots: ast-module-types: 6.0.1 node-source-walk: 7.0.1 + get-caller-file@2.0.5: {} + get-intrinsic@1.3.0: dependencies: call-bind-apply-helpers: 1.0.2 @@ -10620,6 +10681,8 @@ snapshots: replace-ext@2.0.0: {} + require-directory@2.1.1: {} + require-from-string@2.0.2: {} requirejs-config-file@4.0.0: @@ -10706,6 +10769,10 @@ snapshots: rw@1.3.3: {} + rxjs@7.8.2: + dependencies: + tslib: 2.8.1 + safe-buffer@5.1.2: {} safe-buffer@5.2.1: {} @@ -10761,6 +10828,8 @@ snapshots: shebang-regex@3.0.0: {} + shell-quote@1.8.2: {} + shiki@2.5.0: dependencies: '@shikijs/core': 2.5.0 @@ -10998,6 +11067,8 @@ snapshots: tr46@0.0.3: {} + tree-kill@1.2.2: {} + trim-lines@3.0.1: {} trim-newlines@4.1.1: {} @@ -11441,12 +11512,26 @@ snapshots: xtend@4.0.2: {} + y18n@5.0.8: {} + yallist@3.1.1: {} yallist@4.0.0: {} yargs-parser@20.2.9: {} + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yazl@2.5.1: dependencies: buffer-crc32: 0.2.13