From 4a396e723e10507da707c67a847edb0e00a85497 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin.wml@antgroup.com>
Date: Tue, 26 Mar 2024 14:36:17 +0800
Subject: [PATCH 01/62] feat: init

---
 src/components.ts     | 83 +++++++++++++++++++++++++++++++++++++++++++
 src/index.ts          |  1 +
 src/item/base-item.ts |  5 +++
 3 files changed, 89 insertions(+)
 create mode 100644 src/components.ts

diff --git a/src/components.ts b/src/components.ts
new file mode 100644
index 0000000..820bd31
--- /dev/null
+++ b/src/components.ts
@@ -0,0 +1,83 @@
+export enum DataType {
+    VFXItemData = 0,
+    EffectComponent,
+    Material,
+    Shader,
+    SpriteComponent,
+    ParticleSystem,
+    InteractComponent,
+    CameraController,
+    Geometry,
+    Texture,
+    TextComponent,
+  
+    // FIXME: 先完成ECS的场景转换,后面移到spec中
+    MeshComponent = 10000,
+    SkyboxComponent,
+    LightComponent,
+    CameraComponent,
+    ModelPluginComponent,
+    TreeComponent,
+  }
+
+  export interface DataPath {
+    id: string,
+  }
+  
+  export interface EffectsObjectData {
+    id: string,
+    name?: string,
+    dataType: string,
+  }
+
+  export interface ComponentData{
+    item: DataPath,
+  }
+  
+  export interface MaterialData extends EffectsObjectData {
+    shader: DataPath,
+    blending?: boolean,
+    zWrite?: boolean,
+    zTest?: boolean,
+    floats: Record<string, number>,
+    ints: Record<string, number>,
+    vector4s: Record<string, { x: number, y: number, z: number, w: number }>,
+    colors: Record<string, { r: number, g: number, b: number, a: number }>,
+    textures?: Record<string, DataPath>,
+  }
+  
+  export interface GeometryData extends EffectsObjectData {
+    vertexData: VertexData,
+    indexFormat: number,
+    indexOffset: number,
+    buffer: string,
+  }
+  
+  export interface VertexData {
+    vertexCount: number,
+    channels: VertexChannel[],
+  }
+  
+  export interface VertexChannel {
+    offset: number,
+    format: number,
+    dimension: number,
+  }
+  
+  export interface ShaderData extends EffectsObjectData {
+    vertex: string,
+    fragment: string,
+    properties?: string,
+  }
+  
+  export interface EffectComponentData extends ComponentData {
+    _priority: number,
+    materials: DataPath[],
+    geometry: DataPath,
+  }
+
+  export interface EffectsPackageData {
+    fileSummary: { guid: string, assetType: string },
+    exportObjects: EffectsObjectData[],
+  }
+  
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index a7d5b36..37f9155 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -20,3 +20,4 @@ export * from './item/text-item';
 export * from './item/model';
 export * from './binary';
 export * from './text';
+export * from "./components"
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index cfb1a8c..65a6eb6 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -15,6 +15,7 @@ import type { vec3, vec4 } from '../numberExpression';
 import type { CameraContent } from './camera-item';
 import type { FilterContent } from '../../src/item/filter-item';
 import type { TextContent } from './text-item';
+import { ComponentData } from '../components';
 
 export enum ItemEndBehavior {
   destroy = END_BEHAVIOR_DESTROY,
@@ -92,6 +93,10 @@ export interface BaseItem {
    * 元素的基础位置
    */
   transform?: BaseItemTransform,
+  /**
+   * 元素的组件数据
+   */
+  components: ComponentData[],
 }
 
 export interface BaseItemTransform {

From b48210810b01d9f8cedfef1587bb31291c3e4d6c Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin.wml@antgroup.com>
Date: Wed, 27 Mar 2024 10:43:21 +0800
Subject: [PATCH 02/62] feat: update

---
 src/components.ts     | 176 +++++++++++++++++++++++-------------------
 src/composition.ts    |  48 ++++++++++++
 src/item/base-item.ts |  21 ++---
 src/vfx-item-data.ts  |  75 ++++++++++++++++++
 4 files changed, 228 insertions(+), 92 deletions(-)
 create mode 100644 src/vfx-item-data.ts

diff --git a/src/components.ts b/src/components.ts
index 820bd31..5b6dc21 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -1,83 +1,101 @@
 export enum DataType {
-    VFXItemData = 0,
-    EffectComponent,
-    Material,
-    Shader,
-    SpriteComponent,
-    ParticleSystem,
-    InteractComponent,
-    CameraController,
-    Geometry,
-    Texture,
-    TextComponent,
-  
-    // FIXME: 先完成ECS的场景转换,后面移到spec中
-    MeshComponent = 10000,
-    SkyboxComponent,
-    LightComponent,
-    CameraComponent,
-    ModelPluginComponent,
-    TreeComponent,
-  }
+  VFXItemData = "VFXItemData",
+  EffectComponent = "EffectComponent",
+  Material = "Material",
+  Shader = "Shader",
+  SpriteComponent = "SpriteComponent",
+  ParticleSystem = "ParticleSystem",
+  InteractComponent = "InteractComponent",
+  CameraController = "CameraController",
+  Geometry = "Geometry",
+  Texture = "Texture",
+  TextComponent = "TextComponent",
 
-  export interface DataPath {
-    id: string,
-  }
-  
-  export interface EffectsObjectData {
-    id: string,
-    name?: string,
-    dataType: string,
-  }
+  // FIXME: 先完成ECS的场景转换,后面移到spec中
+  MeshComponent = "MeshComponent",
+  SkyboxComponent = "SkyboxComponent",
+  LightComponent = "LightComponent",
+  CameraComponent = "CameraComponent",
+  ModelPluginComponent = "ModelPluginComponent",
+  TreeComponent = "TreeComponent",
+}
 
-  export interface ComponentData{
-    item: DataPath,
-  }
-  
-  export interface MaterialData extends EffectsObjectData {
-    shader: DataPath,
-    blending?: boolean,
-    zWrite?: boolean,
-    zTest?: boolean,
-    floats: Record<string, number>,
-    ints: Record<string, number>,
-    vector4s: Record<string, { x: number, y: number, z: number, w: number }>,
-    colors: Record<string, { r: number, g: number, b: number, a: number }>,
-    textures?: Record<string, DataPath>,
-  }
-  
-  export interface GeometryData extends EffectsObjectData {
-    vertexData: VertexData,
-    indexFormat: number,
-    indexOffset: number,
-    buffer: string,
-  }
-  
-  export interface VertexData {
-    vertexCount: number,
-    channels: VertexChannel[],
-  }
-  
-  export interface VertexChannel {
-    offset: number,
-    format: number,
-    dimension: number,
-  }
-  
-  export interface ShaderData extends EffectsObjectData {
-    vertex: string,
-    fragment: string,
-    properties?: string,
-  }
-  
-  export interface EffectComponentData extends ComponentData {
-    _priority: number,
-    materials: DataPath[],
-    geometry: DataPath,
-  }
+export interface DataPath {
+  id: string,
+}
 
-  export interface EffectsPackageData {
-    fileSummary: { guid: string, assetType: string },
-    exportObjects: EffectsObjectData[],
-  }
-  
\ No newline at end of file
+export interface EffectsObjectData {
+  id: string,
+  name?: string,
+  dataType: string,
+}
+
+export interface ComponentData {
+  item: DataPath,
+}
+
+export interface ColorData{
+  r: number, 
+  g: number, 
+  b: number, 
+  a: number
+}
+
+export interface Vector4Data{
+  x: number, 
+  y: number, 
+  z: number, 
+  w: number
+}
+
+export interface MaterialData extends EffectsObjectData {
+  shader: DataPath,
+  blending?: boolean,
+  zWrite?: boolean,
+  zTest?: boolean,
+  floats: Record<string, number>,
+  ints: Record<string, number>,
+  vector4s: Record<string, Vector4Data>,
+  colors: Record<string, ColorData>,
+  textures?: Record<string, DataPath>,
+}
+
+export interface GeometryData extends EffectsObjectData {
+  vertexData: VertexData,
+  indexFormat: number,
+  indexOffset: number,
+  buffer: string,
+}
+
+export interface VertexData {
+  vertexCount: number,
+  channels: VertexChannel[],
+}
+
+export interface VertexChannel {
+  offset: number,
+  format: number,
+  dimension: number,
+}
+
+export interface ShaderData extends EffectsObjectData {
+  vertex: string,
+  fragment: string,
+  properties?: string,
+}
+
+export interface EffectComponentData extends ComponentData {
+  _priority: number,
+  materials: DataPath[],
+  geometry: DataPath,
+}
+
+export interface EffectsPackageData {
+  fileSummary: FileSummary,
+  exportObjects: EffectsObjectData[],
+}
+
+export interface FileSummary {
+  guid: string,
+  assetType: string
+}
diff --git a/src/composition.ts b/src/composition.ts
index 9fe9816..3334a78 100644
--- a/src/composition.ts
+++ b/src/composition.ts
@@ -8,6 +8,7 @@ import {
   END_BEHAVIOR_PAUSE_AND_DESTROY,
   END_BEHAVIOR_RESTART,
 } from './constants';
+import { DataPath } from './components';
 
 export enum CameraClipMode {
   /**
@@ -123,3 +124,50 @@ export interface Composition {
    */
   fallbackImage?: string,
 }
+
+
+/**
+ * 合成数据
+ */
+export interface CompositionData {
+  /**
+   * 合成ID
+   */
+  id: string,
+  /**
+   * 合成名称
+   */
+  name: string,
+  /**
+   * 合成持续时间
+   */
+  duration: number,
+
+  /**
+   * 合成开始播放的时间,单位妙
+   * @default 0
+   */
+  startTime?: number,
+  /**
+   * 合成结束行为
+   */
+  endBehavior: CompositionEndBehavior,
+  /**
+   * 合成相机信息
+   */
+  camera: CameraOptions,
+  /**
+   * 元素信息
+   */
+  items: DataPath[],
+  /**
+   * 合成视窗预览大小
+   * 如果没有提供,默认为 player 的 container 大小
+   * @default [0,0]
+   */
+  previewSize?: [width: number, height: number],
+  /**
+   * 降级图
+   */
+  fallbackImage?: string,
+}
\ No newline at end of file
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index 65a6eb6..71ebdcb 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -1,10 +1,4 @@
-import type { ItemType, RenderLevel } from '../type';
-import type { NullContent } from './null-item';
-import type { PluginContent } from './plugin-item';
-import type { SpriteContent } from './sprite-item';
-import type { InteractContent } from './interact-item';
-import type { ParticleContent } from './particle-item';
-import type { CompositionContent } from './composition-item';
+import type { FilterContent } from '../../src/item/filter-item';
 import {
   END_BEHAVIOR_DESTROY,
   END_BEHAVIOR_DESTROY_CHILDREN,
@@ -12,10 +6,15 @@ import {
   END_BEHAVIOR_RESTART,
 } from '../constants';
 import type { vec3, vec4 } from '../numberExpression';
+import type { ItemType, RenderLevel } from '../type';
 import type { CameraContent } from './camera-item';
-import type { FilterContent } from '../../src/item/filter-item';
+import type { CompositionContent } from './composition-item';
+import type { InteractContent } from './interact-item';
+import type { NullContent } from './null-item';
+import type { ParticleContent } from './particle-item';
+import type { PluginContent } from './plugin-item';
+import type { SpriteContent } from './sprite-item';
 import type { TextContent } from './text-item';
-import { ComponentData } from '../components';
 
 export enum ItemEndBehavior {
   destroy = END_BEHAVIOR_DESTROY,
@@ -93,10 +92,6 @@ export interface BaseItem {
    * 元素的基础位置
    */
   transform?: BaseItemTransform,
-  /**
-   * 元素的组件数据
-   */
-  components: ComponentData[],
 }
 
 export interface BaseItemTransform {
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
new file mode 100644
index 0000000..4124549
--- /dev/null
+++ b/src/vfx-item-data.ts
@@ -0,0 +1,75 @@
+import { ComponentData, EffectsObjectData } from "./components";
+import { ItemEndBehavior, ParentItemEndBehavior, BaseContent, BaseItemTransform } from "./item/base-item";
+import { ItemType, RenderLevel } from "./type";
+
+export interface VFXItemData extends EffectsObjectData {
+    /**
+     * 元素 id
+     * 非预合成的元素 id 为 int 类型的数字字符串
+     * 预合成元素 id 为 `'{ref元素id}+{合成内id}'` 字符串
+     */
+    id: string,
+    /**
+     * 元素名称
+     */
+    name: string,
+    /**
+     * 元素时常,单位秒
+     */
+    duration: number,
+    /**
+     * 元素类型,string 类型
+     * Galacean Effects 内部元素使用 int 数字字符串
+     * plugin 模块实现者自由实现命名
+     * 2022.12更新: spine: "spine", 陀螺仪: "5"
+     */
+    type: ItemType | string,
+    /**
+     * 父节点ID
+     * 如果父节点无法找到,播放将直接报错
+     */
+    parentId?: string,
+    /**
+     * 元素可视状态
+     * 如果为 true 或者不存在时,元素可见
+     * 仅当为 false 时,元素不被创建
+     */
+    visible?: boolean,
+    /**
+     * 元素结束行为
+     * @default destroy
+     */
+    endBehavior: ItemEndBehavior | ParentItemEndBehavior,
+    /**
+     * 元素播放延时(单位秒)
+     * @default 0
+     */
+    delay?: number,
+    /**
+     * 元素渲染信息属性
+     */
+    content: BaseContent,
+    /**
+     * 元素渲染等级
+     */
+    renderLevel?: RenderLevel,
+    /**
+     * 元素的插件模块名,如果不指定,则和 type 相同
+     * 从数组的 plugins 中获取 name
+     * 例如:pn:1, plugins:["model@1.0",'spine@1.0']
+     * pn 实际为 spine
+     */
+    pn?: number,
+    /**
+     * 元素的插件模块名, 优先级高于 pn
+     */
+    pluginName?: string,
+    /**
+     * 元素的基础位置
+     */
+    transform?: BaseItemTransform,
+    /**
+     * 元素的组件数据
+     */
+    components: ComponentData[],
+}

From 3b058012f53ac351265c405e089feec45be92c47 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 27 Mar 2024 11:01:17 +0800
Subject: [PATCH 03/62] feat: update

---
 src/components.ts       |  4 ++--
 src/item/sprite-item.ts | 50 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+), 2 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 5b6dc21..0998904 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -53,11 +53,11 @@ export interface MaterialData extends EffectsObjectData {
   blending?: boolean,
   zWrite?: boolean,
   zTest?: boolean,
-  floats: Record<string, number>,
   ints: Record<string, number>,
+  floats: Record<string, number>,
   vector4s: Record<string, Vector4Data>,
   colors: Record<string, ColorData>,
-  textures?: Record<string, DataPath>,
+  textures: Record<string, DataPath>,
 }
 
 export interface GeometryData extends EffectsObjectData {
diff --git a/src/item/sprite-item.ts b/src/item/sprite-item.ts
index 3bb0da3..5cd80e7 100644
--- a/src/item/sprite-item.ts
+++ b/src/item/sprite-item.ts
@@ -13,6 +13,7 @@ import type {
 import type {
   RGBAColorValue,
 } from '../numberExpression';
+import { ComponentData } from 'src/components';
 
 /**
  * 图层元素
@@ -87,3 +88,52 @@ export interface SpriteContent {
     behavior: InteractBehavior,
   },
 }
+
+
+/**
+ * 图层组件属性
+ */
+export interface SpriteComponentData extends ComponentData {
+  /**
+   * added by loader
+   * @default null
+   */
+  splits?: SplitParameter[],
+  /**
+   * 图层元素基础属性
+   */
+  options: SpriteContentOptions,
+  /**
+   * 图层元素材质渲染属性
+   */
+  renderer: RendererOptions,
+  /**
+   * 图层元素大小变化属性
+   */
+  sizeOverLifetime?: SizeOverLifetime,
+  /**
+   * 图层元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 图层元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
+  /**
+   * 图层元素色彩变化属性
+   */
+  colorOverLifetime?: ColorOverLifetime,
+  /**
+   * 图层元素贴图变化属性
+   */
+  textureSheetAnimation?: TextureSheetAnimation,
+  /**
+   * 图层交互
+   */
+  interaction?: {
+    /**
+     * 交互行为
+     */
+    behavior: InteractBehavior,
+  },
+}
\ No newline at end of file

From 331bde8c4ad131e397163bec49b7ca4bc5fffe47 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 27 Mar 2024 11:08:58 +0800
Subject: [PATCH 04/62] feat: add new json scene

---
 src/scene.ts | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 107 insertions(+)

diff --git a/src/scene.ts b/src/scene.ts
index a191a6c..5f338dd 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -4,6 +4,8 @@ import type { PlayerVersion, Shape } from './type';
 import type { TemplateImage, Image, CompressedImage, TextureDefine } from './image';
 import type { FontBase, FontDefine } from './text';
 import type { BinaryFile } from './binary';
+import { ComponentData, GeometryData, MaterialData, ShaderData } from './components';
+import { VFXItemData } from './vfx-item-data';
 
 /**
  * 场景信息
@@ -93,3 +95,108 @@ export interface JSONScene {
  * 如果是内置模块,但是需要额外的代码引入,比如滤镜则会加入 requires 数组中
  */
 export type SceneRequire = 'filter';
+
+
+/**
+ * 2.0 场景信息
+ * 素材信息存放于统一数据结构中
+ */
+export interface JSONSceneVersion3 {
+  /************** 文件版本不是 Player 版本,应用于文件变更后在 editor/player 中加载时的分类处理 **************/
+  /**
+   * JSON 版本
+   *
+   * 1.1 增加数据模板
+   * 1.2 增加 anchor
+   * 1.3 增加二进制文件格式
+   * 1.5 增加 Spine 数据
+   * 2.0 改造升级
+   * 2.1 增加文本元素
+   * 2.2 数据类型兼容
+   */
+  version: string,
+  /**
+   * 播放器版本信息
+   */
+  playerVersion: PlayerVersion,
+  /**
+   * 类型为 Galacean Effects
+   */
+  type: string,
+  /*************************************** 用于加载 json 后复原合成 **************************************/
+  /**
+   * 选中合成ID
+   * 如果没有设置,选择合成中的第一个
+   */
+  compositionId?: string,
+  /**
+   * 渲染所需合成列表
+   */
+  compositions: Composition[],
+  /******************************** 以下皆为可复用信息,加载在对应 Manager 中 *******************************/
+  /**
+   * 贴图信息
+   */
+  images: (TemplateImage | Image | CompressedImage)[],
+  /**
+   * 根据合成ID,每个合成用到的 image 的数组索引
+   */
+  imgUsage?: Record<string, number[]>,
+  /**
+   * 根据合成id,每个合成用到的 bin 的数组索引
+   */
+  binUsage?: Record<string, number[]>,
+  /**
+   * 蒙版形状信息
+   */
+  shapes: Shape[],
+  /**
+   * 插件类型信息
+   * 'model@1.0'
+   */
+  plugins: string[],
+  /**
+   * 保留字段
+   */
+  requires: SceneRequire[],
+  /**
+   * 字体资源
+   * 数据模板下掉可以不要 FontBase[]
+   */
+  fonts?: FontBase[] | FontDefine[],
+  /**
+   * spine 资源
+   * @version 1.5
+   */
+  spines?: SpineResource[],
+  /**
+   * 二进制文件地址
+   * @version 1.3
+   */
+  bins?: BinaryFile[],
+  /**
+   * textures 配置
+   * 从 v1.3 开始,images 数组会对应创建 textures 数组
+   */
+  textures?: TextureDefine[],
+  /**
+   * 元素数据
+   */
+  items: VFXItemData[],
+  /**
+   * 组件数据
+   */
+  components: ComponentData[],
+  /**
+   * 材质数据
+   */
+  materials: MaterialData[],
+  /**
+   * 着色器数据
+   */
+  shaders: ShaderData[],
+  /**
+   * 几何体数据
+   */
+  geometries: GeometryData[],
+}
\ No newline at end of file

From 2fb32051e7b3c60f0fb05892cd53ccd197085097 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 27 Mar 2024 11:35:14 +0800
Subject: [PATCH 05/62] feat: update

---
 src/item/interact-item.ts | 11 ++++++
 src/item/particle-item.ts | 75 +++++++++++++++++++++++++++++++++++++++
 src/item/text-item.ts     | 45 +++++++++++++++++++++++
 3 files changed, 131 insertions(+)

diff --git a/src/item/interact-item.ts b/src/item/interact-item.ts
index 6691374..8e40282 100644
--- a/src/item/interact-item.ts
+++ b/src/item/interact-item.ts
@@ -1,6 +1,7 @@
 import type { InteractBehavior, InteractType, ItemType } from '../type';
 import type { RGBAColor } from '../numberExpression';
 import type { BaseItem, ItemEndBehavior } from './base-item';
+import { ComponentData } from 'src/components';
 
 /**
  * 交互元素
@@ -27,6 +28,16 @@ export interface InteractContent {
   options: InteractOption,
 }
 
+/**
+ * 交互元素渲染属性
+ */
+export interface InteractComponentData extends ComponentData{
+  /**
+   * 交互元素基础属性
+   */
+  options: InteractOption,
+}
+
 /**
  * 交互元素基础属性
  */
diff --git a/src/item/particle-item.ts b/src/item/particle-item.ts
index 9771505..ef1d12a 100644
--- a/src/item/particle-item.ts
+++ b/src/item/particle-item.ts
@@ -16,6 +16,7 @@ import type {
 import type { BaseItem, ItemEndBehavior } from './base-item';
 import type { ParticleShape } from './particle-shape';
 import type { DistortionFilterParams } from './filter-item';
+import { ComponentData } from 'src/components';
 
 /**
  * 粒子交互行为
@@ -363,6 +364,80 @@ export interface ParticleContent {
   filter?: DistortionFilterParams,
 }
 
+/**
+ * 粒子元素渲染属性
+ */
+export interface ParticleSystemData extends ComponentData {
+  // added by loader
+  splits?: SplitParameter[],
+  /**
+   * 粒子元素基础属性
+   */
+  options: ParticleOptions,
+  /**
+   * 粒子元素材质渲染属性
+   */
+  renderer: RendererOptions,
+  /**
+   * 粒子元素发射器形状属性
+   */
+  shape?: ParticleShape,
+  /**
+   * 粒子元素发射参数属性
+   */
+  emission: ParticleEmission,
+  /**
+   * 粒子元素大小变化属性
+   */
+  sizeOverLifetime?: ParticleSizeOverLifetime,
+  /**
+   * 发射器 transform 变化
+   */
+  emitterTransform?: {
+    /**
+     * 位置变化
+     */
+    path?: FixedVec3Expression,
+  },
+
+  positionOverLifetime?: ParticlePositionOverLifetime,
+  /**
+   * 粒子元素旋转变化属性
+   */
+  rotationOverLifetime?: ParticleRotationOverLifetime,
+  /**
+   * 粒子元素色彩变化属性
+   */
+  colorOverLifetime?: ParticleColorOverLifetime,
+  /**
+   * 粒子元素贴图变化属性
+   */
+  textureSheetAnimation?: ParticleTextureSheetAnimation,
+  /**
+   * 粒子元素拖尾参数
+   */
+  trails?: ParticleTrail,
+  /**
+   * 粒子元素交互参数
+   */
+  interaction?: {
+    /**
+     * 交互行为
+     */
+    behavior?: ParticleInteractionBehavior,
+    /**
+     * 重叠元素响应开关
+     */
+    multiple?: boolean,
+    /**
+     * ray cast 射线拾取时 sphere 的半径
+     * @default 0.4
+     */
+    radius?: number,
+  },
+  filter?: DistortionFilterParams,
+}
+
 /**
  * 粒子拖尾参数
  */
diff --git a/src/item/text-item.ts b/src/item/text-item.ts
index 3f817ca..a44e8e4 100644
--- a/src/item/text-item.ts
+++ b/src/item/text-item.ts
@@ -13,6 +13,7 @@ import type {
   RGBAColorValue,
 } from '../numberExpression';
 import type { FontStyle, TextAlignment, TextBaseline, TextOverflow, TextWeight } from 'src/text';
+import { ComponentData } from 'src/components';
 
 /**
  * 文本元素
@@ -185,3 +186,47 @@ export interface TextContent {
     behavior: InteractBehavior,
   },
 }
+
+
+/**
+ * 文本元素渲染属性
+ */
+export interface TextComponentData extends ComponentData {
+  /**
+   * 文本元素基础属性
+   */
+  options: TextContentOptions,
+  /**
+   * 文本元素材质渲染属性
+   */
+  renderer: RendererOptions,
+  /**
+   * 文本元素大小变化属性
+   */
+  sizeOverLifetime?: SizeOverLifetime,
+  /**
+   * 文本元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 文本元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
+  /**
+   * 文本元素色彩变化属性
+   */
+  colorOverLifetime?: ColorOverLifetime,
+  /**
+   * 文本元素贴图变化属性
+   */
+  textureSheetAnimation?: TextureSheetAnimation,
+  /**
+   * 图层交互
+   */
+  interaction?: {
+    /**
+     * 交互行为
+     */
+    behavior: InteractBehavior,
+  },
+}

From 5cfec6c3463031f045e9b140264eb02295500b06 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 27 Mar 2024 14:05:35 +0800
Subject: [PATCH 06/62] feat: update

---
 src/item/base-item.ts | 25 +++++++++++++++++++++++++
 src/vfx-item-data.ts  |  4 ++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index 71ebdcb..dd5a504 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -118,6 +118,31 @@ export interface BaseItemTransform {
   quat?: vec4,
 }
 
+export interface Vector3Data {
+  x: number,
+  y: number,
+  z: number,
+}
+
+export interface Vector2Data {
+  x: number,
+  y: number,
+}
+
+export interface EulerData{
+  x: number,
+  y: number,
+  z: number,
+}
+
+export interface TransformData {
+  position: Vector3Data;
+  rotation: EulerData;
+  scale: Vector3Data;
+  size?: Vector2Data,
+  anchor?: Vector2Data,
+}
+
 export type BaseContent =
   | SpriteContent
   | ParticleContent
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index 4124549..6e401bc 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -1,5 +1,5 @@
 import { ComponentData, EffectsObjectData } from "./components";
-import { ItemEndBehavior, ParentItemEndBehavior, BaseContent, BaseItemTransform } from "./item/base-item";
+import { ItemEndBehavior, ParentItemEndBehavior, BaseContent, BaseItemTransform, TransformData } from "./item/base-item";
 import { ItemType, RenderLevel } from "./type";
 
 export interface VFXItemData extends EffectsObjectData {
@@ -67,7 +67,7 @@ export interface VFXItemData extends EffectsObjectData {
     /**
      * 元素的基础位置
      */
-    transform?: BaseItemTransform,
+    transform?: TransformData,
     /**
      * 元素的组件数据
      */

From 6c212498c16c0061d69b57bb17a9769b8ea9870a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Wed, 27 Mar 2024 15:17:50 +0800
Subject: [PATCH 07/62] refactor: 3d spec (#4)

* refactor: 3d spec

* fix: adjust import path
---
 src/item/model/camera.ts | 16 ++++++++++++++++
 src/item/model/light.ts  | 16 ++++++++++++++++
 src/item/model/mesh.ts   | 15 +++++++++++++++
 src/item/model/skybox.ts | 24 ++++++++++++++++++++++++
 4 files changed, 71 insertions(+)

diff --git a/src/item/model/camera.ts b/src/item/model/camera.ts
index aff1980..5f74ba3 100644
--- a/src/item/model/camera.ts
+++ b/src/item/model/camera.ts
@@ -1,6 +1,7 @@
 import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { CameraOptions } from '../../composition';
 import type { RotationOverLifetime, PositionOverLifetime } from '../../type';
+import type { ComponentData } from '../../components';
 
 export interface ModelCameraOptions extends CameraOptions {
   parent?: number,
@@ -35,3 +36,18 @@ export interface ModelCameraItem extends BaseItem {
   content: ModelCameraContent,
   endBehavior: ItemEndBehavior,
 }
+
+export interface ModelCameraComponentData extends ComponentData {
+  /**
+   * 3D相机元素基础属性
+   */
+  options: ModelCameraOptions,
+  /**
+   * 3D相机元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 3D相机元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
+}
\ No newline at end of file
diff --git a/src/item/model/light.ts b/src/item/model/light.ts
index dbfaaf5..055a60e 100644
--- a/src/item/model/light.ts
+++ b/src/item/model/light.ts
@@ -1,6 +1,7 @@
 import type { RGBAColorValue } from '../../numberExpression';
 import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
+import type { ComponentData } from '../../components';
 
 export interface ModelLightBaseOptions {
   /**
@@ -86,3 +87,18 @@ export interface ModelLightItem extends BaseItem {
   content: ModelLightContent,
   endBehavior: ItemEndBehavior,
 }
+
+export interface ModelLightComponentData extends ComponentData {
+  /**
+   * 灯光元素基础属性
+   */
+  options: ModelLightOptions,
+  /**
+   * 灯光元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 灯光元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
+}
\ No newline at end of file
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index bd5c21d..20f8556 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -5,6 +5,7 @@ import type { GeometryPointer } from './binary';
 import type { vec3 } from '../../numberExpression';
 import type { InteractBehavior, ItemType } from '../../type';
 import type { ModelAnimationTrackDataPointer } from './binary';
+import type { ComponentData, GeometryData, MaterialData } from '../../components';
 
 export type BufferType =
   | WebGLRenderingContext['FLOAT']
@@ -90,3 +91,17 @@ export interface ModelMeshItem<T extends BinaryEnv> extends BaseItem {
   endBehavior: ItemEndBehavior,
 }
 
+export interface PrimitiveComponentOptions {
+  geometry: GeometryData,
+  material: MaterialData,
+}
+
+export interface ModelMeshComponentOptions {
+  primitives: PrimitiveComponentOptions[],
+  hide?: boolean,
+}
+
+export interface ModelMeshComponentData extends ComponentData {
+  options: ModelMeshComponentOptions,
+  interaction?: ModelItemBounding,
+}
diff --git a/src/item/model/skybox.ts b/src/item/model/skybox.ts
index 65963dc..f74824e 100644
--- a/src/item/model/skybox.ts
+++ b/src/item/model/skybox.ts
@@ -2,6 +2,7 @@ import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { BinaryEnv } from '../../binary';
 import type { SkyboxCubeTexturePointer } from './binary';
 import type { ItemType } from 'src/type';
+import type { ComponentData, DataPath } from '../../components';
 
 export interface SkyboxOptions<T extends BinaryEnv> {
   // Skybox 是否渲染,UI显示"可见"
@@ -60,3 +61,26 @@ export interface ModelSkyboxItem<T extends BinaryEnv> extends BaseItem {
  * },
  * bins:[{url:'https://big/bin/'}]
  */
+
+export interface SkyboxComponentOptions {
+  // Skybox 是否渲染,UI显示"可见"
+  renderable: boolean,
+  // Diffuse 强度,UI显示"环境光强度"
+  intensity: number,
+  // Specular 强度,UI显示"环境反射强度"
+  reflectionsIntensity: number,
+  // SH 系数,先不在UI面板上显示(原先为二维数组,注意兼容性!!!)
+  irradianceCoeffs?: number[],
+  // 漫反射贴图,UI显示"漫反射贴图"
+  diffuseImage?: DataPath,
+  // 高光贴图,UI显示"高光贴图"
+  specularImage: DataPath,
+  // 高光贴图大小,UI不显示
+  specularImageSize: number,
+  // 高光贴图 mipmap 数,UI不显示
+  specularMipCount: number,
+}
+
+export interface SkyboxComponentData extends ComponentData {
+  options: SkyboxComponentOptions,
+}

From 0579b4e1cbbbb58dbc5c8a8908d88c42d00a163d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Wed, 27 Mar 2024 15:48:28 +0800
Subject: [PATCH 08/62] feat: add TimelineComponent data (#5)

* feat: add TimelineComponent data

* perf: opt import
---
 src/item/base-item.ts |  2 +-
 src/item/null-item.ts | 45 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index dd5a504..a5a2042 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -137,7 +137,7 @@ export interface EulerData{
 
 export interface TransformData {
   position: Vector3Data;
-  rotation: EulerData;
+  eulerHint: EulerData;
   scale: Vector3Data;
   size?: Vector2Data,
   anchor?: Vector2Data,
diff --git a/src/item/null-item.ts b/src/item/null-item.ts
index aefc31c..0df4ec7 100644
--- a/src/item/null-item.ts
+++ b/src/item/null-item.ts
@@ -7,6 +7,7 @@ import type {
 } from '../type';
 import type { RGBAColorValue } from '../numberExpression';
 import type { BaseItem } from './base-item';
+import { ComponentData, EffectsObjectData } from '../components';
 /**
  * 空节点元素
  */
@@ -51,3 +52,47 @@ export interface NullContent {
    */
   colorOverLifetime?: ColorOverLifetime,
 }
+
+export interface TimelineComponentData extends ComponentData {
+  /**
+   * 轨道数据
+   */
+  tracks: TrackData[];
+}
+
+export interface TrackData {
+  type: string,
+  clips: TimelineClipData[],
+}
+
+export interface TimelineClipData {
+  start: number,
+  duration: number,
+  asset: EffectsObjectData,
+}
+
+export interface TransformAnimationClipData extends EffectsObjectData {
+  /**
+   * 空节点元素大小变化属性
+   */
+  sizeOverLifetime?: SizeOverLifetime,
+  /**
+   * 空节点元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 空节点元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
+}
+
+export interface SpriteColorAnimationClipData extends EffectsObjectData {
+  /**
+   * 空节点元素色彩变化属性
+   */
+  colorOverLifetime?: ColorOverLifetime,
+  /**
+   * 图层初始颜色
+   */
+  startColor?: RGBAColorValue,
+}
\ No newline at end of file

From cd61185764a88a0922f990582c0df1cba52dc696 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 27 Mar 2024 19:19:34 +0800
Subject: [PATCH 09/62] feat: add notes

---
 src/components.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 0998904..04da66a 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -64,12 +64,12 @@ export interface GeometryData extends EffectsObjectData {
   vertexData: VertexData,
   indexFormat: number,
   indexOffset: number,
-  buffer: string,
+  buffer: string, // 存放 position, uv, normal, indices 的打包数据
 }
 
 export interface VertexData {
   vertexCount: number,
-  channels: VertexChannel[],
+  channels: VertexChannel[],  // channel 存放顺序 position, uv, normal
 }
 
 export interface VertexChannel {

From 96eee199e26bbc1ea1e071038199f0a4aa8a14c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Tue, 2 Apr 2024 14:08:28 +0800
Subject: [PATCH 10/62] refactor: timeline (#9)

* feat: update TimelineComponent structure

* feat: update

* feat: update TimelineComponentData

* perf: material property add offset and scale

* style: typo

* fix: fix type

* fix: fix type

* perf: note

---------

Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 src/components.ts         |  66 +++++++++--------
 src/composition.ts        |   3 +-
 src/index.ts              |   2 +-
 src/item/base-item.ts     |   8 +--
 src/item/interact-item.ts |   4 +-
 src/item/null-item.ts     |  21 ++++--
 src/item/particle-item.ts |   2 +-
 src/item/sprite-item.ts   |   3 +-
 src/item/text-item.ts     |   3 +-
 src/scene.ts              |   5 +-
 src/vfx-item-data.ts      | 144 +++++++++++++++++++-------------------
 11 files changed, 138 insertions(+), 123 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 04da66a..369b380 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -1,23 +1,25 @@
+import type { Vector2Data } from './item/base-item';
+
 export enum DataType {
-  VFXItemData = "VFXItemData",
-  EffectComponent = "EffectComponent",
-  Material = "Material",
-  Shader = "Shader",
-  SpriteComponent = "SpriteComponent",
-  ParticleSystem = "ParticleSystem",
-  InteractComponent = "InteractComponent",
-  CameraController = "CameraController",
-  Geometry = "Geometry",
-  Texture = "Texture",
-  TextComponent = "TextComponent",
+  VFXItemData = 'VFXItemData',
+  EffectComponent = 'EffectComponent',
+  Material = 'Material',
+  Shader = 'Shader',
+  SpriteComponent = 'SpriteComponent',
+  ParticleSystem = 'ParticleSystem',
+  InteractComponent = 'InteractComponent',
+  CameraController = 'CameraController',
+  Geometry = 'Geometry',
+  Texture = 'Texture',
+  TextComponent = 'TextComponent',
 
   // FIXME: 先完成ECS的场景转换,后面移到spec中
-  MeshComponent = "MeshComponent",
-  SkyboxComponent = "SkyboxComponent",
-  LightComponent = "LightComponent",
-  CameraComponent = "CameraComponent",
-  ModelPluginComponent = "ModelPluginComponent",
-  TreeComponent = "TreeComponent",
+  MeshComponent = 'MeshComponent',
+  SkyboxComponent = 'SkyboxComponent',
+  LightComponent = 'LightComponent',
+  CameraComponent = 'CameraComponent',
+  ModelPluginComponent = 'ModelPluginComponent',
+  TreeComponent = 'TreeComponent',
 }
 
 export interface DataPath {
@@ -34,18 +36,24 @@ export interface ComponentData {
   item: DataPath,
 }
 
-export interface ColorData{
-  r: number, 
-  g: number, 
-  b: number, 
-  a: number
+export interface ColorData {
+  r: number,
+  g: number,
+  b: number,
+  a: number,
+}
+
+export interface Vector4Data {
+  x: number,
+  y: number,
+  z: number,
+  w: number,
 }
 
-export interface Vector4Data{
-  x: number, 
-  y: number, 
-  z: number, 
-  w: number
+export interface MaterialTextureProperty {
+  texture: DataPath,
+  offset: Vector2Data,
+  scale: Vector2Data,
 }
 
 export interface MaterialData extends EffectsObjectData {
@@ -57,7 +65,7 @@ export interface MaterialData extends EffectsObjectData {
   floats: Record<string, number>,
   vector4s: Record<string, Vector4Data>,
   colors: Record<string, ColorData>,
-  textures: Record<string, DataPath>,
+  textures: Record<string, MaterialTextureProperty>,
 }
 
 export interface GeometryData extends EffectsObjectData {
@@ -97,5 +105,5 @@ export interface EffectsPackageData {
 
 export interface FileSummary {
   guid: string,
-  assetType: string
+  assetType: string,
 }
diff --git a/src/composition.ts b/src/composition.ts
index 3334a78..754073e 100644
--- a/src/composition.ts
+++ b/src/composition.ts
@@ -8,7 +8,7 @@ import {
   END_BEHAVIOR_PAUSE_AND_DESTROY,
   END_BEHAVIOR_RESTART,
 } from './constants';
-import { DataPath } from './components';
+import type { DataPath } from './components';
 
 export enum CameraClipMode {
   /**
@@ -125,7 +125,6 @@ export interface Composition {
   fallbackImage?: string,
 }
 
-
 /**
  * 合成数据
  */
diff --git a/src/index.ts b/src/index.ts
index 37f9155..88c7434 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -20,4 +20,4 @@ export * from './item/text-item';
 export * from './item/model';
 export * from './binary';
 export * from './text';
-export * from "./components"
+export * from './components';
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index a5a2042..3ac71d8 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -129,16 +129,16 @@ export interface Vector2Data {
   y: number,
 }
 
-export interface EulerData{
+export interface EulerData {
   x: number,
   y: number,
   z: number,
 }
 
 export interface TransformData {
-  position: Vector3Data;
-  eulerHint: EulerData;
-  scale: Vector3Data;
+  position: Vector3Data,
+  eulerHint: EulerData,
+  scale: Vector3Data,
   size?: Vector2Data,
   anchor?: Vector2Data,
 }
diff --git a/src/item/interact-item.ts b/src/item/interact-item.ts
index 8e40282..d6c66b3 100644
--- a/src/item/interact-item.ts
+++ b/src/item/interact-item.ts
@@ -1,7 +1,7 @@
 import type { InteractBehavior, InteractType, ItemType } from '../type';
 import type { RGBAColor } from '../numberExpression';
 import type { BaseItem, ItemEndBehavior } from './base-item';
-import { ComponentData } from 'src/components';
+import type { ComponentData } from 'src/components';
 
 /**
  * 交互元素
@@ -31,7 +31,7 @@ export interface InteractContent {
 /**
  * 交互元素渲染属性
  */
-export interface InteractComponentData extends ComponentData{
+export interface InteractComponentData extends ComponentData {
   /**
    * 交互元素基础属性
    */
diff --git a/src/item/null-item.ts b/src/item/null-item.ts
index 0df4ec7..db7b21e 100644
--- a/src/item/null-item.ts
+++ b/src/item/null-item.ts
@@ -7,7 +7,7 @@ import type {
 } from '../type';
 import type { RGBAColorValue } from '../numberExpression';
 import type { BaseItem } from './base-item';
-import { ComponentData, EffectsObjectData } from '../components';
+import type { ComponentData, DataPath, EffectsObjectData } from '../components';
 /**
  * 空节点元素
  */
@@ -57,18 +57,29 @@ export interface TimelineComponentData extends ComponentData {
   /**
    * 轨道数据
    */
-  tracks: TrackData[];
+  tracks: TrackAssetData[],
 }
 
-export interface TrackData {
-  type: string,
+export interface PlayableAssetData {
+  dataType: string,
+}
+
+export interface TrackAssetData extends PlayableAssetData {
   clips: TimelineClipData[],
 }
 
 export interface TimelineClipData {
   start: number,
   duration: number,
-  asset: EffectsObjectData,
+  clipAsset: DataPath, // PlayableData
+}
+
+export interface TransformAnimationPlayableAssetData extends PlayableAssetData {
+  animationClip: DataPath, // TransformAnimationClipData
+}
+
+export interface SpriteColorAnimationPlayableAssetData extends PlayableAssetData {
+  animationClip: DataPath, // SpriteColorAnimationClipData
 }
 
 export interface TransformAnimationClipData extends EffectsObjectData {
diff --git a/src/item/particle-item.ts b/src/item/particle-item.ts
index ef1d12a..98d1627 100644
--- a/src/item/particle-item.ts
+++ b/src/item/particle-item.ts
@@ -16,7 +16,7 @@ import type {
 import type { BaseItem, ItemEndBehavior } from './base-item';
 import type { ParticleShape } from './particle-shape';
 import type { DistortionFilterParams } from './filter-item';
-import { ComponentData } from 'src/components';
+import type { ComponentData } from 'src/components';
 
 /**
  * 粒子交互行为
diff --git a/src/item/sprite-item.ts b/src/item/sprite-item.ts
index 5cd80e7..a018be6 100644
--- a/src/item/sprite-item.ts
+++ b/src/item/sprite-item.ts
@@ -13,7 +13,7 @@ import type {
 import type {
   RGBAColorValue,
 } from '../numberExpression';
-import { ComponentData } from 'src/components';
+import type { ComponentData } from 'src/components';
 
 /**
  * 图层元素
@@ -89,7 +89,6 @@ export interface SpriteContent {
   },
 }
 
-
 /**
  * 图层组件属性
  */
diff --git a/src/item/text-item.ts b/src/item/text-item.ts
index a44e8e4..9913c52 100644
--- a/src/item/text-item.ts
+++ b/src/item/text-item.ts
@@ -13,7 +13,7 @@ import type {
   RGBAColorValue,
 } from '../numberExpression';
 import type { FontStyle, TextAlignment, TextBaseline, TextOverflow, TextWeight } from 'src/text';
-import { ComponentData } from 'src/components';
+import type { ComponentData } from 'src/components';
 
 /**
  * 文本元素
@@ -187,7 +187,6 @@ export interface TextContent {
   },
 }
 
-
 /**
  * 文本元素渲染属性
  */
diff --git a/src/scene.ts b/src/scene.ts
index 5f338dd..f4d9899 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -4,8 +4,8 @@ import type { PlayerVersion, Shape } from './type';
 import type { TemplateImage, Image, CompressedImage, TextureDefine } from './image';
 import type { FontBase, FontDefine } from './text';
 import type { BinaryFile } from './binary';
-import { ComponentData, GeometryData, MaterialData, ShaderData } from './components';
-import { VFXItemData } from './vfx-item-data';
+import type { ComponentData, GeometryData, MaterialData, ShaderData } from './components';
+import type { VFXItemData } from './vfx-item-data';
 
 /**
  * 场景信息
@@ -96,7 +96,6 @@ export interface JSONScene {
  */
 export type SceneRequire = 'filter';
 
-
 /**
  * 2.0 场景信息
  * 素材信息存放于统一数据结构中
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index 6e401bc..7cd9586 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -1,75 +1,75 @@
-import { ComponentData, EffectsObjectData } from "./components";
-import { ItemEndBehavior, ParentItemEndBehavior, BaseContent, BaseItemTransform, TransformData } from "./item/base-item";
-import { ItemType, RenderLevel } from "./type";
+import type { ComponentData, EffectsObjectData } from './components';
+import type { ItemEndBehavior, ParentItemEndBehavior, BaseContent, TransformData } from './item/base-item';
+import type { ItemType, RenderLevel } from './type';
 
 export interface VFXItemData extends EffectsObjectData {
-    /**
-     * 元素 id
-     * 非预合成的元素 id 为 int 类型的数字字符串
-     * 预合成元素 id 为 `'{ref元素id}+{合成内id}'` 字符串
-     */
-    id: string,
-    /**
-     * 元素名称
-     */
-    name: string,
-    /**
-     * 元素时常,单位秒
-     */
-    duration: number,
-    /**
-     * 元素类型,string 类型
-     * Galacean Effects 内部元素使用 int 数字字符串
-     * plugin 模块实现者自由实现命名
-     * 2022.12更新: spine: "spine", 陀螺仪: "5"
-     */
-    type: ItemType | string,
-    /**
-     * 父节点ID
-     * 如果父节点无法找到,播放将直接报错
-     */
-    parentId?: string,
-    /**
-     * 元素可视状态
-     * 如果为 true 或者不存在时,元素可见
-     * 仅当为 false 时,元素不被创建
-     */
-    visible?: boolean,
-    /**
-     * 元素结束行为
-     * @default destroy
-     */
-    endBehavior: ItemEndBehavior | ParentItemEndBehavior,
-    /**
-     * 元素播放延时(单位秒)
-     * @default 0
-     */
-    delay?: number,
-    /**
-     * 元素渲染信息属性
-     */
-    content: BaseContent,
-    /**
-     * 元素渲染等级
-     */
-    renderLevel?: RenderLevel,
-    /**
-     * 元素的插件模块名,如果不指定,则和 type 相同
-     * 从数组的 plugins 中获取 name
-     * 例如:pn:1, plugins:["model@1.0",'spine@1.0']
-     * pn 实际为 spine
-     */
-    pn?: number,
-    /**
-     * 元素的插件模块名, 优先级高于 pn
-     */
-    pluginName?: string,
-    /**
-     * 元素的基础位置
-     */
-    transform?: TransformData,
-    /**
-     * 元素的组件数据
-     */
-    components: ComponentData[],
+  /**
+   * 元素 id
+   * 非预合成的元素 id 为 int 类型的数字字符串
+   * 预合成元素 id 为 `'{ref元素id}+{合成内id}'` 字符串
+   */
+  id: string,
+  /**
+   * 元素名称
+   */
+  name: string,
+  /**
+   * 元素时常,单位秒
+   */
+  duration: number,
+  /**
+   * 元素类型,string 类型
+   * Galacean Effects 内部元素使用 int 数字字符串
+   * plugin 模块实现者自由实现命名
+   * 2022.12更新: spine: "spine", 陀螺仪: "5"
+   */
+  type: ItemType | string,
+  /**
+   * 父节点ID
+   * 如果父节点无法找到,播放将直接报错
+   */
+  parentId?: string,
+  /**
+   * 元素可视状态
+   * 如果为 true 或者不存在时,元素可见
+   * 仅当为 false 时,元素不被创建
+   */
+  visible?: boolean,
+  /**
+   * 元素结束行为
+   * @default destroy
+   */
+  endBehavior: ItemEndBehavior | ParentItemEndBehavior,
+  /**
+   * 元素播放延时(单位秒)
+   * @default 0
+   */
+  delay?: number,
+  /**
+   * 元素渲染信息属性
+   */
+  content: BaseContent,
+  /**
+   * 元素渲染等级
+   */
+  renderLevel?: RenderLevel,
+  /**
+   * 元素的插件模块名,如果不指定,则和 type 相同
+   * 从数组的 plugins 中获取 name
+   * 例如:pn:1, plugins:["model@1.0",'spine@1.0']
+   * pn 实际为 spine
+   */
+  pn?: number,
+  /**
+   * 元素的插件模块名, 优先级高于 pn
+   */
+  pluginName?: string,
+  /**
+   * 元素的基础位置
+   */
+  transform?: TransformData,
+  /**
+   * 元素的组件数据
+   */
+  components: ComponentData[],
 }

From 1299c0e9bf84393aecc1da495673937dc7252e85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Mon, 8 Apr 2024 15:13:56 +0800
Subject: [PATCH 11/62] refractor: update 3d component data (#10)

* fix: update 3d spec

* fix: update data type

* fix: add animation data

* chore: rename
---
 src/item/model/camera.ts | 24 +++++++++++++-------
 src/item/model/light.ts  | 49 +++++++++++++++++++++++++++++++++-------
 src/item/model/mesh.ts   | 29 +++++++++++++++++++-----
 src/item/model/skybox.ts | 33 ++++++++++++++++++++++++++-
 src/item/model/tree.ts   | 25 ++++++++++++++++++++
 5 files changed, 137 insertions(+), 23 deletions(-)

diff --git a/src/item/model/camera.ts b/src/item/model/camera.ts
index 5f74ba3..55915c8 100644
--- a/src/item/model/camera.ts
+++ b/src/item/model/camera.ts
@@ -1,5 +1,5 @@
 import type { BaseItem, ItemEndBehavior } from '../base-item';
-import type { CameraOptions } from '../../composition';
+import type { CameraClipMode, CameraOptions } from '../../composition';
 import type { RotationOverLifetime, PositionOverLifetime } from '../../type';
 import type { ComponentData } from '../../components';
 
@@ -39,15 +39,23 @@ export interface ModelCameraItem extends BaseItem {
 
 export interface ModelCameraComponentData extends ComponentData {
   /**
-   * 3D相机元素基础属性
+   * 视角属性
    */
-  options: ModelCameraOptions,
+  fov: number,
   /**
-   * 3D相机元素旋转变化属性
+   * 相机远平面
    */
-  rotationOverLifetime?: RotationOverLifetime,
+  far: number,
   /**
-   * 3D相机元素位置变化属性
+   * 相机近平面
    */
-  positionOverLifetime?: PositionOverLifetime,
-}
\ No newline at end of file
+  near: number,
+  /**
+   * 默认不提供,等于 canvas 的 `width/height`
+   */
+  aspect?: number,
+  /**
+   * 相机剪裁模式
+   */
+  clipMode: CameraClipMode,
+}
diff --git a/src/item/model/light.ts b/src/item/model/light.ts
index 055a60e..2d611f2 100644
--- a/src/item/model/light.ts
+++ b/src/item/model/light.ts
@@ -1,7 +1,7 @@
 import type { RGBAColorValue } from '../../numberExpression';
 import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
-import type { ComponentData } from '../../components';
+import type { ColorData, ComponentData } from '../../components';
 
 export interface ModelLightBaseOptions {
   /**
@@ -88,17 +88,50 @@ export interface ModelLightItem extends BaseItem {
   endBehavior: ItemEndBehavior,
 }
 
+export enum LightType {
+  /**
+   * 点光源
+   */
+  point = 'point',
+  /**
+   * 聚光灯
+   */
+  spot = 'spot',
+  /**
+   * 方向光
+   */
+  directional = 'directional',
+  /**
+   * 环境光
+   */
+  ambient = 'ambient',
+}
+
 export interface ModelLightComponentData extends ComponentData {
+  lightType: LightType,
   /**
-   * 灯光元素基础属性
+   * 灯光颜色,线性空间
+   * @default [255,255,255]
    */
-  options: ModelLightOptions,
+  color: ColorData,
   /**
-   * 灯光元素旋转变化属性
+   * 灯光强度
+   * @default 1
    */
-  rotationOverLifetime?: RotationOverLifetime,
+  intensity: number,
   /**
-   * 灯光元素位置变化属性
+   * 点光源和聚光灯
+   * @default Infinity
    */
-  positionOverLifetime?: PositionOverLifetime,
-}
\ No newline at end of file
+  range?: number,
+  /**
+   * 聚光灯
+   * @default 0
+   */
+  innerConeAngle?: number,
+  /**
+   * 聚光灯
+   * @default 45度
+   */
+  outerConeAngle?: number,
+}
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index 20f8556..36cc189 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -5,7 +5,8 @@ import type { GeometryPointer } from './binary';
 import type { vec3 } from '../../numberExpression';
 import type { InteractBehavior, ItemType } from '../../type';
 import type { ModelAnimationTrackDataPointer } from './binary';
-import type { ComponentData, GeometryData, MaterialData } from '../../components';
+import type { ComponentData, DataPath, GeometryData, MaterialData } from '../../components';
+import type { VFXItemData } from 'src/vfx-item-data';
 
 export type BufferType =
   | WebGLRenderingContext['FLOAT']
@@ -91,17 +92,33 @@ export interface ModelMeshItem<T extends BinaryEnv> extends BaseItem {
   endBehavior: ItemEndBehavior,
 }
 
-export interface PrimitiveComponentOptions {
+export interface PrimitiveData {
   geometry: GeometryData,
   material: MaterialData,
 }
 
-export interface ModelMeshComponentOptions {
-  primitives: PrimitiveComponentOptions[],
-  hide?: boolean,
+export interface SkinData {
+  name?: string,
+  joints: DataPath[],
+  skeleton?: DataPath,
+  // 数据量会很大
+  inverseBindMatrices: number[],
+}
+
+export interface MorphData {
+  weights: number[],
 }
 
 export interface ModelMeshComponentData extends ComponentData {
-  options: ModelMeshComponentOptions,
+  hide?: boolean,
+  /**
+   * 蒙皮数据
+   */
+  skin?: SkinData,
+  /**
+   * Morph数据
+   */
+  morph?: MorphData,
+  primitives: PrimitiveData[],
   interaction?: ModelItemBounding,
 }
diff --git a/src/item/model/skybox.ts b/src/item/model/skybox.ts
index f74824e..2c7803e 100644
--- a/src/item/model/skybox.ts
+++ b/src/item/model/skybox.ts
@@ -82,5 +82,36 @@ export interface SkyboxComponentOptions {
 }
 
 export interface SkyboxComponentData extends ComponentData {
-  options: SkyboxComponentOptions,
+  /**
+   * Skybox 是否渲染,UI显示"可见"
+   */
+  renderable: boolean,
+  /**
+   * Diffuse 强度,UI显示"环境光强度"
+   */
+  intensity: number,
+  /**
+   * Specular 强度,UI显示"环境反射强度"
+   */
+  reflectionsIntensity: number,
+  /**
+   * SH 系数,先不在UI面板上显示(原先为二维数组,注意兼容性!!!)
+   */
+  irradianceCoeffs?: number[],
+  /**
+   * 漫反射贴图,UI显示"漫反射贴图"
+   */
+  diffuseImage?: DataPath,
+  /**
+   * 高光贴图,UI显示"高光贴图"
+   */
+  specularImage: DataPath,
+  /**
+   * 高光贴图大小,UI不显示
+   */
+  specularImageSize: number,
+  /**
+   * 高光贴图 mipmap 数,UI不显示
+   */
+  specularMipCount: number,
 }
diff --git a/src/item/model/tree.ts b/src/item/model/tree.ts
index 2caa2d6..c948f20 100644
--- a/src/item/model/tree.ts
+++ b/src/item/model/tree.ts
@@ -2,6 +2,7 @@ import type { BinaryEnv } from '../../binary';
 import type { ModelAnimationTrackDataPointer } from './binary';
 import type { BaseItem, BaseItemTransform } from '../base-item';
 import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
+import type { ComponentData, DataPath } from '../../components';
 
 export interface TreeNodeOptions {
   name?: string,
@@ -70,3 +71,27 @@ export interface ModelTreeItem<T extends BinaryEnv> extends BaseItem {
   type: ItemType.tree,
   content: ModelTreeContent<T>,
 }
+
+export interface ModelAnimationTrackData {
+  item: DataPath,
+  input: number[],
+  output: number[],
+  path: 'translation' | 'rotation' | 'scale' | 'weights',
+  interpolation: 'LINEAR' | 'STEP' | 'CUBICSPLINE',
+}
+
+export interface ModelAnimationData {
+  name?: string,
+  tracks: ModelAnimationTrackData[],
+}
+
+export interface ModelAnimationComponentData extends ComponentData {
+  /**
+   * 默认动画索引,-1表示不播放动画
+   */
+  animation?: number,
+  /**
+   * 3D场景树中所有的动画数据
+   */
+  animations: ModelAnimationData[],
+}

From c76845bd3f366aec5a8ffce958f6e80840956df8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Tue, 9 Apr 2024 20:10:29 +0800
Subject: [PATCH 12/62] feat: add json 3.0 fallback (#12)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* feat: add json 3.0 fallback

* perf: opt code

* feat: materialData add string tags

* perf: add vfx-item-data export

* fix: uuid 使用 browser 产物,避免走到 node 模式

* chore: 规范文件命名,优化引入路径

* perf: opt code

* feat: 重命名 JSONScene,老 Scene 接口改为 legacy

* fix: 更正测试案例结果

* chore: 移除老 JSONScene 版本

---------

Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
Co-authored-by: chishao <603173553@qq.com>
---
 fallback/index.ts                             |  15 +-
 fallback/migration.ts                         | 297 +++++++++++++++++-
 fallback/utils.ts                             |  33 +-
 package-lock.json                             |  16 +-
 package.json                                  |   3 +-
 src/binary.ts                                 |   2 +-
 src/components.ts                             |   3 +-
 src/composition.ts                            |   5 +
 src/index.ts                                  |   4 +-
 src/item/base-item.ts                         |  12 +-
 src/item/camera-item.ts                       |   2 +-
 src/item/composition-item.ts                  |   2 +-
 src/item/effect-item.ts                       |  19 ++
 src/item/filter-item.ts                       |   6 +-
 src/item/interact-item.ts                     |   4 +-
 src/item/model/light.ts                       |   2 +-
 src/item/model/material.ts                    |   2 +-
 src/item/model/mesh.ts                        |   2 +-
 src/item/model/skybox.ts                      |   2 +-
 src/item/null-item.ts                         |  10 +-
 src/item/particle-item.ts                     |  10 +-
 src/item/particle-shape.ts                    |   2 +-
 src/item/plugin-item.ts                       |   7 +-
 src/item/sprite-item.ts                       |   8 +-
 src/item/text-item.ts                         |   8 +-
 ...mberExpression.ts => number-expression.ts} |   0
 src/scene.ts                                  |  19 +-
 src/text.ts                                   |   2 +-
 src/type.ts                                   |   8 +-
 src/types/shim.d.ts                           |   1 +
 test/cases/model/index.test.mjs               |  59 ++--
 test/cases/null/end-behavior.test.mjs         |   2 +-
 test/cases/particle/base.test.mjs             |   4 +-
 33 files changed, 467 insertions(+), 104 deletions(-)
 create mode 100644 src/item/effect-item.ts
 rename src/{numberExpression.ts => number-expression.ts} (100%)
 create mode 100644 src/types/shim.d.ts

diff --git a/fallback/index.ts b/fallback/index.ts
index efb56ef..cd27a42 100644
--- a/fallback/index.ts
+++ b/fallback/index.ts
@@ -11,6 +11,7 @@ import type {
   TemplateImage,
   VideoImage,
   FilterItem,
+  JSONSceneLegacy,
 } from '../src';
 import { CAMERA_CLIP_MODE_NORMAL, ItemEndBehavior, ItemType } from '../src';
 import { getStandardParticleContent } from './particle';
@@ -19,7 +20,7 @@ import { getStandardInteractContent } from './interact';
 import { arrAdd, quatFromXYZRotation, rotationZYXFromQuat } from './utils';
 import { getStandardCameraContent } from './camera';
 import { getStandardFilterContent } from './filter';
-import { version21Migration, version22Migration } from './migration';
+import { version21Migration, version22Migration, version30Migration } from './migration';
 
 export * from './utils';
 
@@ -32,20 +33,20 @@ export function getStandardJSON (json: any): JSONScene {
     throw Error('expect a json object');
   }
 
-  // 修正老版本数据中,meshItem以及lightItem结束行为错误问题
+  // 修正老版本数据中,meshItem 以及 lightItem 结束行为错误问题
   version22Migration(json);
 
   if (v0.test(json.version)) {
     reverseParticle = (/^(\d+)/).exec(json.version)?.[0] === '0';
 
-    return version21Migration(getStandardJSONFromV0(json));
+    return version30Migration(version21Migration(getStandardJSONFromV0(json)));
   }
 
   const mainVersion = standardVersion.exec(json.version)?.[1];
 
   if (mainVersion) {
-    if (Number(mainVersion) < 2) {
-      return version21Migration(json);
+    if (Number(mainVersion) < 3) {
+      return version30Migration(version21Migration(json));
     }
 
     return json;
@@ -56,7 +57,7 @@ export function getStandardJSON (json: any): JSONScene {
 
 let currentVersion: '1.0' | '1.1' | '1.3' = '1.0';
 
-function getStandardJSONFromV0 (json: any): JSONScene {
+function getStandardJSONFromV0 (json: any): JSONSceneLegacy {
   currentVersion = '1.0';
   const plugins = json.plugins || [];
 
@@ -66,7 +67,7 @@ function getStandardJSONFromV0 (json: any): JSONScene {
   const requires: string[] = (json.requires || []).slice();
   const images = json.images.map((img: any, index: number) => getStandardImage(img, index, json.imageTags || []));
   const textures = json.textures || images.map((img: any, i: number) => ({ source: i, flipY: true }));
-  const ret: JSONScene = {
+  const ret: JSONSceneLegacy = {
     plugins: plugins,
     shapes: json.shapes || [],
     type: 'ge',
diff --git a/fallback/migration.ts b/fallback/migration.ts
index c48e4f0..d04e2c0 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -1,10 +1,11 @@
-import type { JSONScene } from '../src/scene';
-import { ItemType, ItemEndBehavior } from '../src';
+import type { JSONScene, JSONSceneLegacy } from '../src';
+import { ItemType, ItemEndBehavior, END_BEHAVIOR_PAUSE_AND_DESTROY, END_BEHAVIOR_FREEZE, END_BEHAVIOR_PAUSE, DataType } from '../src';
+import { convertAnchor, generateGUID } from './utils';
 
 /**
  * 2.1 以下版本数据适配(mars-player@2.4.0 及以上版本支持 2.1 以下数据的适配)
  */
-export function version21Migration (json: JSONScene): JSONScene {
+export function version21Migration (json: JSONSceneLegacy): JSONSceneLegacy {
   json.compositions.forEach(composition => {
     composition.items.forEach(item => {
       if (item.type === ItemType.null) {
@@ -23,7 +24,7 @@ export function version21Migration (json: JSONScene): JSONScene {
 /**
  * 2.2 以下版本数据适配(mars-player@2.5.0 及以上版本支持 2.2 以下数据的适配)
  */
-export function version22Migration (json: JSONScene): JSONScene {
+export function version22Migration (json: JSONSceneLegacy): JSONSceneLegacy {
   const singleVersion = json.version?.split('.');
 
   if (!singleVersion || Number(singleVersion[0]) > 2 || (Number(singleVersion[0]) === 2 && Number(singleVersion[1]) >= 2)) {
@@ -40,3 +41,291 @@ export function version22Migration (json: JSONScene): JSONScene {
 
   return json;
 }
+
+/**
+ * 3.0 以下版本数据适配(runtime 2.0及以上版本支持)
+ */
+export function version30Migration (json: JSONSceneLegacy): JSONScene {
+  const result: JSONScene = Object.assign({}, json, {
+    items: [],
+    components: [],
+    materials: [],
+    shaders: [],
+    geometries: [],
+  });
+
+  // 兼容老版本数据中不存在textures的情况
+  result.textures ??= [];
+  result.textures.forEach(textureOptions => {
+    Object.assign(textureOptions, {
+      id: generateGUID(),
+      dataType: DataType.Texture,
+    });
+  });
+
+  if (result.textures.length < result.images.length) {
+    for (let i = result.textures.length; i < result.images.length; i++) {
+      result.textures.push({
+        //@ts-expect-error
+        id: generateGUID(),
+        dataType: DataType.Texture,
+        source: i,
+        flipY: true,
+      });
+    }
+  }
+
+  // 更正Composition.endBehavior
+  for (const composition of json.compositions) {
+    // composition 的 endbehaviour 兼容
+    if (composition.endBehavior === END_BEHAVIOR_PAUSE_AND_DESTROY || composition.endBehavior === END_BEHAVIOR_PAUSE) {
+      composition.endBehavior = END_BEHAVIOR_FREEZE;
+    }
+
+    const itemGuidMap: Record<string, string> = {};
+
+    for (const item of composition.items) {
+      itemGuidMap[item.id] = generateGUID();
+      // TODO: 编辑器测试用,上线后删除
+      //@ts-expect-error
+      item.oldId = item.id;
+      item.id = itemGuidMap[item.id];
+    }
+
+    composition.items.forEach((item, index) => {
+      if (item.parentId) {
+        if (item.parentId.includes('^')) {
+          const parentId = (item.parentId).split('^')[0];
+          const nodeId = (item.parentId).split('^')[1];
+
+          item.parentId = itemGuidMap[parentId] + '^' + nodeId;
+        } else {
+          item.parentId = itemGuidMap[item.parentId];
+        }
+      }
+
+      // @ts-expect-error fix item type
+      result.items.push(item);
+
+      // @ts-expect-error fix item type
+      composition.items[index] = { id: item.id };
+    });
+
+    for (const item of result.items) {
+      // 原 texture 索引转为统一 guid 索引
+      if (item.content) {
+        if (item.content.renderer) {
+          if (item.content.renderer.texture !== undefined) {
+            const oldTextureId = item.content.renderer.texture;
+
+            //@ts-expect-error
+            item.content.renderer.texture = { id: result.textures[oldTextureId].id };
+          }
+        }
+
+        if (item.content.trails) {
+          if (item.content.trails.texture !== undefined) {
+            const oldTextureId = item.content.trails.texture;
+
+            //@ts-expect-error
+            item.content.trails.texture = { id: result.textures[oldTextureId].id };
+          }
+        }
+      }
+
+      // item 的 transform 属性由数组转为 {x:n, y:n, z:n}
+      if (item.transform) {
+        //@ts-expect-error
+        const position = [...item.transform.position ?? [0, 0, 0]];
+        //@ts-expect-error
+        const rotation = [...item.transform.rotation ?? [0, 0, 0]] as number[];
+        //@ts-expect-error
+        const scale = [...item.transform.scale ?? [1, 1, 1]];
+
+        Object.assign(item, {
+          transform: {
+            position: { x: position[0], y: position[1], z: position[2] },
+            rotation: { x: rotation[0], y: rotation[1], z: rotation[2] },
+            scale: { x: scale[0], y: scale[1], z: scale[0] },
+          },
+        });
+
+        // sprite 的 scale 转为 size
+        if (item.type === ItemType.sprite) {
+          item.transform.size = { x: scale[0], y: scale[1] };
+          item.transform.scale = { x: 1, y: 1, z: 1 };
+        }
+
+        // sprite 的 anchor 修正
+        if (item.type === ItemType.sprite) {
+          const content = item.content;
+
+          if (!content.renderer) {
+            content.renderer = {};
+          }
+          const renderer = content.renderer;
+          const realAnchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
+          const startSize = item.transform.size;
+
+          // 兼容旧JSON(anchor和particleOrigin可能同时存在)
+          if (!renderer.anchor && renderer.particleOrigin !== undefined) {
+            //@ts-expect-error
+            item.transform.position.x += -realAnchor[0] * startSize.x;
+            //@ts-expect-error
+            item.transform.position.y += -realAnchor[1] * startSize.y;
+          }
+          //@ts-expect-error
+          item.transform.anchor = { x: realAnchor[0] * startSize.x, y: realAnchor[1] * startSize.y };
+        }
+      }
+
+      if (item.type === ItemType.particle) {
+        const content = item.content;
+
+        if (!content.renderer) {
+          content.renderer = {};
+        }
+        const renderer = content.renderer;
+
+        content.renderer.anchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
+      }
+
+      // 动画数据转化 TODO: 动画数据移到 TimelineComponentData
+      item.content.tracks = [];
+      const tracks = item.content.tracks;
+
+      if (item.type !== ItemType.particle) {
+        tracks.push({
+          clips: [
+            {
+              dataType: 'TransformAnimationPlayableAsset',
+              animationClip: {
+                sizeOverLifetime: item.content.sizeOverLifetime,
+                rotationOverLifetime: item.content.rotationOverLifetime,
+                positionOverLifetime: item.content.positionOverLifetime,
+              },
+            },
+          ],
+        });
+      }
+
+      if (item.type === ItemType.sprite) {
+        tracks.push({
+          clips: [
+            {
+              dataType: 'SpriteColorAnimationPlayableAsset',
+              animationClip: {
+                colorOverLifetime: item.content.colorOverLifetime,
+                startColor: item.content.options.startColor,
+              },
+            },
+          ],
+        });
+      }
+
+      // gizmo 的 target id 转换为新的 item guid
+      if (item.content.options.target) {
+        item.content.options.target = itemGuidMap[item.content.options.target];
+      }
+
+      // item 的 content 转为 component data 加入 JSONScene.components
+      const uuid = generateGUID();
+
+      if (item.type === ItemType.sprite) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.SpriteComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.particle) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.ParticleSystem;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.mesh) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.MeshComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.skybox) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.SkyboxComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.light) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.LightComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === 'camera') {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.CameraComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.tree) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.TreeComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.interact) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.InteractComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.camera) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.CameraController;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      } else if (item.type === ItemType.text) {
+        item.components = [];
+        result.components.push(item.content);
+        item.content.id = uuid;
+        item.content.dataType = DataType.TextComponent;
+        item.content.item = { id: item.id };
+        item.dataType = DataType.VFXItemData;
+        //@ts-expect-error
+        item.components.push({ id: item.content.id });
+      }
+    }
+  }
+
+  result.version = '3.0';
+
+  return result;
+}
diff --git a/fallback/utils.ts b/fallback/utils.ts
index b5bd736..bbaa1b2 100644
--- a/fallback/utils.ts
+++ b/fallback/utils.ts
@@ -8,8 +8,10 @@ import type {
   FixedVec3Expression,
   vec4,
   vec3,
+  vec2,
 } from '../src';
-import { ValueType } from '../src';
+import { ValueType, ParticleOrigin } from '../src';
+import uuidV4 from 'uuid/dist/esm-browser/v4';
 
 export function arrAdd<T> (arr: T[], item: T): boolean | undefined {
   if (!arr.includes(item)) {
@@ -259,3 +261,32 @@ export function rotationZYXFromQuat (out: vec3 | number[], quat: vec4): vec3 {
 
   return out as vec3;
 }
+
+export function generateGUID (): string {
+  return uuidV4().replace(/-/g, '');
+}
+
+/**
+ * 提取并转换 JSON 数据中的 anchor 值
+ */
+export function convertAnchor (anchor?: vec2, particleOrigin?: ParticleOrigin): vec2 {
+  if (anchor) {
+    return [anchor[0] - 0.5, 0.5 - anchor[1]];
+  } else if (particleOrigin) {
+    return particleOriginTranslateMap[particleOrigin];
+  } else {
+    return [0, 0];
+  }
+}
+
+export const particleOriginTranslateMap: Record<number, vec2> = {
+  [ParticleOrigin.PARTICLE_ORIGIN_CENTER]: [0, 0],
+  [ParticleOrigin.PARTICLE_ORIGIN_CENTER_BOTTOM]: [0, -0.5],
+  [ParticleOrigin.PARTICLE_ORIGIN_CENTER_TOP]: [0, 0.5],
+  [ParticleOrigin.PARTICLE_ORIGIN_LEFT_TOP]: [-0.5, 0.5],
+  [ParticleOrigin.PARTICLE_ORIGIN_LEFT_CENTER]: [-0.5, 0],
+  [ParticleOrigin.PARTICLE_ORIGIN_LEFT_BOTTOM]: [-0.5, -0.5],
+  [ParticleOrigin.PARTICLE_ORIGIN_RIGHT_CENTER]: [0.5, 0],
+  [ParticleOrigin.PARTICLE_ORIGIN_RIGHT_BOTTOM]: [0.5, -0.5],
+  [ParticleOrigin.PARTICLE_ORIGIN_RIGHT_TOP]: [0.5, 0.5],
+};
diff --git a/package-lock.json b/package-lock.json
index 36aa025..09eff1a 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -32,7 +32,8 @@
         "rollup": "^2.70.1",
         "rollup-plugin-livereload": "^2.0.5",
         "rollup-plugin-serve": "^1.1.0",
-        "typescript": "^4.6.2"
+        "typescript": "^4.6.2",
+        "uuid": "9.0.1"
       }
     },
     "node_modules/@aashutoshrathi/word-wrap": {
@@ -4489,6 +4490,19 @@
       "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
       "dev": true
     },
+    "node_modules/uuid": {
+      "version": "9.0.1",
+      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+      "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+      "dev": true,
+      "funding": [
+        "https://github.com/sponsors/broofa",
+        "https://github.com/sponsors/ctavan"
+      ],
+      "bin": {
+        "uuid": "dist/bin/uuid"
+      }
+    },
     "node_modules/validate-npm-package-license": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
diff --git a/package.json b/package.json
index 0f97638..c1f69af 100644
--- a/package.json
+++ b/package.json
@@ -60,7 +60,8 @@
     "rollup": "^2.70.1",
     "rollup-plugin-livereload": "^2.0.5",
     "rollup-plugin-serve": "^1.1.0",
-    "typescript": "^4.6.2"
+    "typescript": "^4.6.2",
+    "uuid": "9.0.1"
   },
   "author": "Ant Group CO., Ltd.",
   "license": "MIT",
diff --git a/src/binary.ts b/src/binary.ts
index ecd8ac1..36edee0 100644
--- a/src/binary.ts
+++ b/src/binary.ts
@@ -1,5 +1,5 @@
 import type { RenderLevel } from './type';
-import type { ValueType } from './numberExpression';
+import type { ValueType } from './number-expression';
 
 /**
  * index: 指向 json 中 bins 数组
diff --git a/src/components.ts b/src/components.ts
index 369b380..6003d3d 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -32,7 +32,7 @@ export interface EffectsObjectData {
   dataType: string,
 }
 
-export interface ComponentData {
+export interface ComponentData extends EffectsObjectData {
   item: DataPath,
 }
 
@@ -61,6 +61,7 @@ export interface MaterialData extends EffectsObjectData {
   blending?: boolean,
   zWrite?: boolean,
   zTest?: boolean,
+  stringTags: Record<string, string>,
   ints: Record<string, number>,
   floats: Record<string, number>,
   vector4s: Record<string, Vector4Data>,
diff --git a/src/composition.ts b/src/composition.ts
index 754073e..0212e82 100644
--- a/src/composition.ts
+++ b/src/composition.ts
@@ -4,6 +4,7 @@ import {
   CAMERA_CLIP_MODE_VERTICAL,
   END_BEHAVIOR_DESTROY,
   END_BEHAVIOR_FORWARD,
+  END_BEHAVIOR_FREEZE,
   END_BEHAVIOR_PAUSE,
   END_BEHAVIOR_PAUSE_AND_DESTROY,
   END_BEHAVIOR_RESTART,
@@ -77,6 +78,10 @@ export enum CompositionEndBehavior {
    * 销毁并保留最后一帧
    */
   pause_destroy = END_BEHAVIOR_PAUSE_AND_DESTROY,
+  /**
+   * 冻结
+   */
+  freeze = END_BEHAVIOR_FREEZE,
 }
 
 /**
diff --git a/src/index.ts b/src/index.ts
index 88c7434..166d4c9 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,8 +1,9 @@
+export * from 'uuid/dist/esm-browser/v4';
 export * from './type';
 export * from './composition';
 export * from './image';
 export * from './constants';
-export * from './numberExpression';
+export * from './number-expression';
 export * from './scene';
 export * from './item';
 export * from './item/base-item';
@@ -21,3 +22,4 @@ export * from './item/model';
 export * from './binary';
 export * from './text';
 export * from './components';
+export * from './vfx-item-data';
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index 3ac71d8..c004b37 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -1,11 +1,11 @@
-import type { FilterContent } from '../../src/item/filter-item';
+import type { FilterContent } from './filter-item';
 import {
   END_BEHAVIOR_DESTROY,
   END_BEHAVIOR_DESTROY_CHILDREN,
   END_BEHAVIOR_FREEZE,
   END_BEHAVIOR_RESTART,
 } from '../constants';
-import type { vec3, vec4 } from '../numberExpression';
+import type { vec3, vec4 } from '../number-expression';
 import type { ItemType, RenderLevel } from '../type';
 import type { CameraContent } from './camera-item';
 import type { CompositionContent } from './composition-item';
@@ -129,15 +129,9 @@ export interface Vector2Data {
   y: number,
 }
 
-export interface EulerData {
-  x: number,
-  y: number,
-  z: number,
-}
-
 export interface TransformData {
   position: Vector3Data,
-  eulerHint: EulerData,
+  eulerHint: Vector3Data,
   scale: Vector3Data,
   size?: Vector2Data,
   anchor?: Vector2Data,
diff --git a/src/item/camera-item.ts b/src/item/camera-item.ts
index 1b13b4a..c66d58a 100644
--- a/src/item/camera-item.ts
+++ b/src/item/camera-item.ts
@@ -1,6 +1,6 @@
 import type { BaseItem, ItemEndBehavior } from './base-item';
 import type { ItemType, RotationOverLifetime } from '../type';
-import type { FixedNumberExpression, FixedVec3Expression } from '../numberExpression';
+import type { FixedNumberExpression, FixedVec3Expression } from '../number-expression';
 import type { CameraClipMode } from '../composition';
 
 export interface CameraItem extends BaseItem {
diff --git a/src/item/composition-item.ts b/src/item/composition-item.ts
index 47dd1b8..5773e82 100644
--- a/src/item/composition-item.ts
+++ b/src/item/composition-item.ts
@@ -2,7 +2,7 @@ import type { BaseItem, ItemEndBehavior } from './base-item';
 import type {
   SizeOverLifetime, RotationOverLifetime, ColorOverLifetime, ItemType,
 } from '../type';
-import type { RGBAColorValue, vec3 } from '../numberExpression';
+import type { RGBAColorValue, vec3 } from '../number-expression';
 import type { PositionOverLifetime } from '../type';
 
 /**
diff --git a/src/item/effect-item.ts b/src/item/effect-item.ts
new file mode 100644
index 0000000..74793f8
--- /dev/null
+++ b/src/item/effect-item.ts
@@ -0,0 +1,19 @@
+import type { ItemType } from '../type';
+import type { BaseItem, ItemEndBehavior } from './base-item';
+
+/**
+ * 特效元素
+ */
+export interface SpineItem extends BaseItem {
+  type: ItemType.effect,
+  content: EffectContent,
+  endBehavior: ItemEndBehavior,
+}
+
+/**
+ * 特效元素属性
+ */
+export interface EffectContent {
+  materials: number[],
+  geometry: number,
+}
diff --git a/src/item/filter-item.ts b/src/item/filter-item.ts
index a9e7b09..5501abf 100644
--- a/src/item/filter-item.ts
+++ b/src/item/filter-item.ts
@@ -1,7 +1,7 @@
 import type {
-  BaseItem, ColorOverLifetime, FixedNumberExpression, FixedVec3Expression, FunctionExpression, ItemEndBehavior, ItemType,
-  MaskMode, NumberExpression, RenderMode, RotationOverLifetime, ShapeGeometry,
-  SideMode, SizeOverLifetime, SpriteContentOptions, vec2, vec3,
+  BaseItem, ColorOverLifetime, FixedNumberExpression, FixedVec3Expression, FunctionExpression,
+  ItemEndBehavior, ItemType, MaskMode, NumberExpression, RenderMode, RotationOverLifetime,
+  ShapeGeometry, SideMode, SizeOverLifetime, SpriteContentOptions, vec2, vec3,
 } from '../index';
 
 export interface FilterItem extends BaseItem {
diff --git a/src/item/interact-item.ts b/src/item/interact-item.ts
index d6c66b3..17542eb 100644
--- a/src/item/interact-item.ts
+++ b/src/item/interact-item.ts
@@ -1,7 +1,7 @@
 import type { InteractBehavior, InteractType, ItemType } from '../type';
-import type { RGBAColor } from '../numberExpression';
+import type { RGBAColor } from '../number-expression';
 import type { BaseItem, ItemEndBehavior } from './base-item';
-import type { ComponentData } from 'src/components';
+import type { ComponentData } from '../components';
 
 /**
  * 交互元素
diff --git a/src/item/model/light.ts b/src/item/model/light.ts
index 2d611f2..ff0dc5d 100644
--- a/src/item/model/light.ts
+++ b/src/item/model/light.ts
@@ -1,4 +1,4 @@
-import type { RGBAColorValue } from '../../numberExpression';
+import type { RGBAColorValue } from '../../number-expression';
 import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
 import type { ColorData, ComponentData } from '../../components';
diff --git a/src/item/model/material.ts b/src/item/model/material.ts
index a7c3856..b47bf73 100644
--- a/src/item/model/material.ts
+++ b/src/item/model/material.ts
@@ -1,5 +1,5 @@
 // 纹理坐标变换
-import type { RGBAColorValue, vec2 } from '../../numberExpression';
+import type { RGBAColorValue, vec2 } from '../../number-expression';
 import type { BinaryEnv } from '../../binary';
 import type { SideMode } from '../../type';
 import type { TexturePointer } from './binary';
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index 36cc189..53468f7 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -2,7 +2,7 @@ import type { BinaryEnv } from '../../binary';
 import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { MaterialOptions } from './material';
 import type { GeometryPointer } from './binary';
-import type { vec3 } from '../../numberExpression';
+import type { vec3 } from '../../number-expression';
 import type { InteractBehavior, ItemType } from '../../type';
 import type { ModelAnimationTrackDataPointer } from './binary';
 import type { ComponentData, DataPath, GeometryData, MaterialData } from '../../components';
diff --git a/src/item/model/skybox.ts b/src/item/model/skybox.ts
index 2c7803e..c1fb06d 100644
--- a/src/item/model/skybox.ts
+++ b/src/item/model/skybox.ts
@@ -1,7 +1,7 @@
 import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { BinaryEnv } from '../../binary';
 import type { SkyboxCubeTexturePointer } from './binary';
-import type { ItemType } from 'src/type';
+import type { ItemType } from '../../type';
 import type { ComponentData, DataPath } from '../../components';
 
 export interface SkyboxOptions<T extends BinaryEnv> {
diff --git a/src/item/null-item.ts b/src/item/null-item.ts
index db7b21e..2285337 100644
--- a/src/item/null-item.ts
+++ b/src/item/null-item.ts
@@ -1,11 +1,7 @@
 import type {
-  SizeOverLifetime,
-  RotationOverLifetime,
-  PositionOverLifetime,
-  ColorOverLifetime,
-  ItemType,
+  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime, ItemType,
 } from '../type';
-import type { RGBAColorValue } from '../numberExpression';
+import type { RGBAColorValue } from '../number-expression';
 import type { BaseItem } from './base-item';
 import type { ComponentData, DataPath, EffectsObjectData } from '../components';
 /**
@@ -106,4 +102,4 @@ export interface SpriteColorAnimationClipData extends EffectsObjectData {
    * 图层初始颜色
    */
   startColor?: RGBAColorValue,
-}
\ No newline at end of file
+}
diff --git a/src/item/particle-item.ts b/src/item/particle-item.ts
index 98d1627..4606985 100644
--- a/src/item/particle-item.ts
+++ b/src/item/particle-item.ts
@@ -1,9 +1,5 @@
 import type {
-  ItemType,
-  RendererOptions,
-  TextureSheetAnimation,
-  BlendingMode,
-  SplitParameter,
+  ItemType, RendererOptions, TextureSheetAnimation, BlendingMode, SplitParameter,
 } from '../type';
 import type {
   FixedNumberExpression,
@@ -12,11 +8,11 @@ import type {
   vec3, FixedVec3Expression,
   ColorExpression,
   FunctionExpression,
-} from '../numberExpression';
+} from '../number-expression';
 import type { BaseItem, ItemEndBehavior } from './base-item';
 import type { ParticleShape } from './particle-shape';
 import type { DistortionFilterParams } from './filter-item';
-import type { ComponentData } from 'src/components';
+import type { ComponentData } from '../components';
 
 /**
  * 粒子交互行为
diff --git a/src/item/particle-shape.ts b/src/item/particle-shape.ts
index 782ff02..6a015e2 100644
--- a/src/item/particle-shape.ts
+++ b/src/item/particle-shape.ts
@@ -1,5 +1,5 @@
 import type { ShapeType } from '../type';
-import type { NumberExpression, vec3 } from '../numberExpression';
+import type { NumberExpression, vec3 } from '../number-expression';
 
 export enum ShapeArcMode {
   /**
diff --git a/src/item/plugin-item.ts b/src/item/plugin-item.ts
index 9ea4268..7d401c1 100644
--- a/src/item/plugin-item.ts
+++ b/src/item/plugin-item.ts
@@ -1,9 +1,4 @@
-import type {
-  ItemType,
-  PluginGyroscopeTarget,
-  PluginType,
-  RendererOptions,
-} from '../type';
+import type { ItemType, PluginGyroscopeTarget, PluginType, RendererOptions } from '../type';
 import type { BaseItem, ItemEndBehavior } from './base-item';
 
 /**
diff --git a/src/item/sprite-item.ts b/src/item/sprite-item.ts
index a018be6..6c799d1 100644
--- a/src/item/sprite-item.ts
+++ b/src/item/sprite-item.ts
@@ -10,10 +10,8 @@ import type {
   SplitParameter,
   InteractBehavior,
 } from '../type';
-import type {
-  RGBAColorValue,
-} from '../numberExpression';
-import type { ComponentData } from 'src/components';
+import type { RGBAColorValue } from '../number-expression';
+import type { ComponentData } from '../components';
 
 /**
  * 图层元素
@@ -135,4 +133,4 @@ export interface SpriteComponentData extends ComponentData {
      */
     behavior: InteractBehavior,
   },
-}
\ No newline at end of file
+}
diff --git a/src/item/text-item.ts b/src/item/text-item.ts
index 9913c52..eb44d2e 100644
--- a/src/item/text-item.ts
+++ b/src/item/text-item.ts
@@ -9,11 +9,9 @@ import type {
   RendererOptions,
   InteractBehavior,
 } from '../type';
-import type {
-  RGBAColorValue,
-} from '../numberExpression';
-import type { FontStyle, TextAlignment, TextBaseline, TextOverflow, TextWeight } from 'src/text';
-import type { ComponentData } from 'src/components';
+import type { RGBAColorValue } from '../number-expression';
+import type { FontStyle, TextAlignment, TextBaseline, TextOverflow, TextWeight } from '../text';
+import type { ComponentData } from '../components';
 
 /**
  * 文本元素
diff --git a/src/numberExpression.ts b/src/number-expression.ts
similarity index 100%
rename from src/numberExpression.ts
rename to src/number-expression.ts
diff --git a/src/scene.ts b/src/scene.ts
index f4d9899..2c255c3 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -8,10 +8,11 @@ import type { ComponentData, GeometryData, MaterialData, ShaderData } from './co
 import type { VFXItemData } from './vfx-item-data';
 
 /**
- * 场景信息
+ * runtime 2.0 之前的场景信息
  * 素材信息存放于统一数据结构中
+ * @deprecated
  */
-export interface JSONScene {
+export interface JSONSceneLegacy {
   /************** 文件版本不是 Player 版本,应用于文件变更后在 editor/player 中加载时的分类处理 **************/
   /**
    * JSON 版本
@@ -97,21 +98,15 @@ export interface JSONScene {
 export type SceneRequire = 'filter';
 
 /**
- * 2.0 场景信息
+ * 场景信息
  * 素材信息存放于统一数据结构中
  */
-export interface JSONSceneVersion3 {
+export interface JSONScene {
   /************** 文件版本不是 Player 版本,应用于文件变更后在 editor/player 中加载时的分类处理 **************/
   /**
    * JSON 版本
    *
-   * 1.1 增加数据模板
-   * 1.2 增加 anchor
-   * 1.3 增加二进制文件格式
-   * 1.5 增加 Spine 数据
-   * 2.0 改造升级
-   * 2.1 增加文本元素
-   * 2.2 数据类型兼容
+   * 3.0 EC 改造
    */
   version: string,
   /**
@@ -198,4 +193,4 @@ export interface JSONSceneVersion3 {
    * 几何体数据
    */
   geometries: GeometryData[],
-}
\ No newline at end of file
+}
diff --git a/src/text.ts b/src/text.ts
index 46560d6..edc3f1b 100644
--- a/src/text.ts
+++ b/src/text.ts
@@ -1,4 +1,4 @@
-import type { RGBAColor } from './numberExpression';
+import type { RGBAColor } from './number-expression';
 
 export interface StringTemplate {
   fonts: FontBase[],
diff --git a/src/type.ts b/src/type.ts
index 07d82b4..c989d64 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -1,4 +1,6 @@
-import type { FixedVec3Expression, vec2, vec3, GradientColor, ShapePoints, ShapeSplits, FixedNumberExpression } from './numberExpression';
+import type {
+  FixedVec3Expression, vec2, vec3, GradientColor, ShapePoints, ShapeSplits, FixedNumberExpression,
+} from './number-expression';
 
 /**
  * 播放器版本
@@ -567,6 +569,10 @@ export enum ItemType {
    * 天空盒元素
    */
   skybox = 'skybox',
+  /**
+   * 特效元素
+   */
+  effect = 'effect',
 }
 
 /**
diff --git a/src/types/shim.d.ts b/src/types/shim.d.ts
new file mode 100644
index 0000000..0484f1c
--- /dev/null
+++ b/src/types/shim.d.ts
@@ -0,0 +1 @@
+declare module 'uuid/dist/esm-browser/v4';
diff --git a/test/cases/model/index.test.mjs b/test/cases/model/index.test.mjs
index 0d7f28f..ab7d2a9 100644
--- a/test/cases/model/index.test.mjs
+++ b/test/cases/model/index.test.mjs
@@ -108,11 +108,15 @@ describe('model plugin items', () => {
       ],
     });
 
+    const item0 = scn.items.find(item => item.id === scn.compositions[0].items[0].id);
+    const item1 = scn.items.find(item => item.id === scn.compositions[0].items[1].id);
+
     expect(scn.plugins).to.deep.equal(['model']);
     expect(scn.compositions[0].items.length).to.eql(2);
-    expect(scn.compositions[0].items[0].pn).to.eql(0);
-    expect(scn.compositions[0].items[0].endBehavior).to.eql(5);
-    expect(scn.compositions[0].items[1].pn).to.eql(0);
+    expect(scn.items.length).to.eql(2);
+    expect(item0.pn).to.eql(0);
+    expect(item0.endBehavior).to.eql(5);
+    expect(item1.pn).to.eql(0);
 
     const scn08MeshFix = getStandardJSON({
       compositionId: 0,
@@ -193,10 +197,15 @@ describe('model plugin items', () => {
       ],
     });
 
-    expect(scn08MeshFix.compositions[0].items[0].endBehavior).to.eql(0);
-    expect(scn08MeshFix.compositions[0].items[1].endBehavior).to.eql(4);
-    expect(scn08MeshFix.compositions[0].items[2].endBehavior).to.eql(0);
-    expect(scn08MeshFix.compositions[0].items[3].endBehavior).to.eql(4);
+    const item0From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[0].id);
+    const item1From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[1].id);
+    const item2From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[2].id);
+    const item3From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[3].id);
+
+    expect(item0From08.endBehavior).to.eql(0);
+    expect(item1From08.endBehavior).to.eql(4);
+    expect(item2From08.endBehavior).to.eql(0);
+    expect(item3From08.endBehavior).to.eql(4);
 
     const scn18MeshFix = getStandardJSON({
       compositionId: 0,
@@ -276,11 +285,15 @@ describe('model plugin items', () => {
         },
       ],
     });
+    const item0From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[0].id);
+    const item1From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[1].id);
+    const item2From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[2].id);
+    const item3From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[3].id);
 
-    expect(scn18MeshFix.compositions[0].items[0].endBehavior).to.eql(0);
-    expect(scn18MeshFix.compositions[0].items[1].endBehavior).to.eql(4);
-    expect(scn18MeshFix.compositions[0].items[2].endBehavior).to.eql(0);
-    expect(scn18MeshFix.compositions[0].items[3].endBehavior).to.eql(4);
+    expect(item0From18.endBehavior).to.eql(0);
+    expect(item1From18.endBehavior).to.eql(4);
+    expect(item2From18.endBehavior).to.eql(0);
+    expect(item3From18.endBehavior).to.eql(4);
 
     const scn21MeshFix = getStandardJSON({
       compositionId: 0,
@@ -360,11 +373,15 @@ describe('model plugin items', () => {
         },
       ],
     });
+    const item0From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[0].id);
+    const item1From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[1].id);
+    const item2From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[2].id);
+    const item3From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[3].id);
 
-    expect(scn21MeshFix.compositions[0].items[0].endBehavior).to.eql(0);
-    expect(scn21MeshFix.compositions[0].items[1].endBehavior).to.eql(4);
-    expect(scn21MeshFix.compositions[0].items[2].endBehavior).to.eql(0);
-    expect(scn21MeshFix.compositions[0].items[3].endBehavior).to.eql(4);
+    expect(item0From21.endBehavior).to.eql(0);
+    expect(item1From21.endBehavior).to.eql(4);
+    expect(item2From21.endBehavior).to.eql(0);
+    expect(item3From21.endBehavior).to.eql(4);
 
     const scn22MeshFix = getStandardJSON({
       compositionId: 0,
@@ -444,10 +461,14 @@ describe('model plugin items', () => {
         },
       ],
     });
+    const item0From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[0].id);
+    const item1From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[1].id);
+    const item2From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[2].id);
+    const item3From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[3].id);
 
-    expect(scn22MeshFix.compositions[0].items[0].endBehavior).to.eql(1);
-    expect(scn22MeshFix.compositions[0].items[1].endBehavior).to.eql(4);
-    expect(scn22MeshFix.compositions[0].items[2].endBehavior).to.eql(1);
-    expect(scn22MeshFix.compositions[0].items[3].endBehavior).to.eql(4);
+    expect(item0From22.endBehavior).to.eql(1);
+    expect(item1From22.endBehavior).to.eql(4);
+    expect(item2From22.endBehavior).to.eql(1);
+    expect(item3From22.endBehavior).to.eql(4);
   });
 });
diff --git a/test/cases/null/end-behavior.test.mjs b/test/cases/null/end-behavior.test.mjs
index c5a4e0d..fe3ec32 100644
--- a/test/cases/null/end-behavior.test.mjs
+++ b/test/cases/null/end-behavior.test.mjs
@@ -8,7 +8,7 @@ describe('Null item endBehavior', () => {
     const json = '{"images":[],"spines":[],"version":"1.5","shapes":[],"plugins":[],"type":"mars","compositions":[{"id":"6","name":"新建合成1","duration":5,"startTime":0,"endBehavior":1,"previewSize":[750,1624],"items":[{"id":"1","name":"sprite_1","duration":5,"type":"1","parentId":"2","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1},"positionOverLifetime":{"direction":[0,0,0],"startSpeed":0,"gravity":[0,0,0],"gravityOverLifetime":[0,1]}},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[1.2,1.2,1]}},{"id":"2","name":"null_2","duration":5,"type":"3","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"positionOverLifetime":{}},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[1,1,1]}}],"camera":{"fov":60,"far":40,"near":0.1,"clipMode":1,"position":[0,0,8],"rotation":[0,0,0]}}],"requires":[],"compositionId":"6","bins":[],"textures":[]}';
     const { version, compositions } = getStandardJSON(JSON.parse(json));
 
-    expect(version).to.eq('2.1');
+    expect(version).to.eq('3.0');
     compositions.forEach(({ items }) => {
       items.forEach(item => {
         if (item.type === ItemType.null) {
diff --git a/test/cases/particle/base.test.mjs b/test/cases/particle/base.test.mjs
index 1eee7b6..d331e04 100644
--- a/test/cases/particle/base.test.mjs
+++ b/test/cases/particle/base.test.mjs
@@ -423,10 +423,10 @@ describe('particle base', () => {
       ],
     };
     const res = getStandardJSON(oldParticle);
-    const pt = res.compositions[0].items[0];
+    const pt = res.items.find(item => item.id === res.compositions[0].items[0].id);
     const r2 = pt.transform.rotation;
 
-    expect([+r2[0].toFixed(1), +r2[1].toFixed(1), +r2[2].toFixed(1)]).to.eql([-90.0, -20.0, 30.0], 'oldParticle rotation');
+    expect([+r2.x.toFixed(1), +r2.y.toFixed(1), +r2.z.toFixed(1)]).to.eql([-90.0, -20.0, 30.0], 'oldParticle rotation');
   });
 
   it('particle emitter transform path linear, constant, bezier', () => {

From b29ff0cb98f8a3e5f5f5638249f83bd5e71898cd Mon Sep 17 00:00:00 2001
From: Sruim <934274351@qq.com>
Date: Wed, 10 Apr 2024 11:13:14 +0800
Subject: [PATCH 13/62] =?UTF-8?q?refractor:=203d=20=E6=95=B0=E6=8D=AE=20EC?=
 =?UTF-8?q?=20=E5=8C=96=20(#18)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* fix: update 3d spec

* fix: update data type

* fix: add animation data

* chore: rename

* fix: add orthographic camera

* feat: 增加`ComponentData`的继承关系

* perf: 优化代码

* feat: 增加`ComponentData`继承关系

* feat: 增加`VFXItemData`导出

---------

Co-authored-by: liuxi150 <liuxi150@hotmail.com>
Co-authored-by: 云垣 <suruimeng.srm@antgroup.com>
---
 src/components.ts        |  4 ++--
 src/index.ts             |  1 +
 src/item/model/camera.ts | 25 +++++++++++++++++++++----
 3 files changed, 24 insertions(+), 6 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 6003d3d..092c6cc 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -52,8 +52,8 @@ export interface Vector4Data {
 
 export interface MaterialTextureProperty {
   texture: DataPath,
-  offset: Vector2Data,
-  scale: Vector2Data,
+  offset?: Vector2Data,
+  scale?: Vector2Data,
 }
 
 export interface MaterialData extends EffectsObjectData {
diff --git a/src/index.ts b/src/index.ts
index 166d4c9..9601362 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -19,6 +19,7 @@ export * from './item/spine-item';
 export * from './item/filter-item';
 export * from './item/text-item';
 export * from './item/model';
+export * from './vfx-item-data';
 export * from './binary';
 export * from './text';
 export * from './components';
diff --git a/src/item/model/camera.ts b/src/item/model/camera.ts
index 55915c8..b555e99 100644
--- a/src/item/model/camera.ts
+++ b/src/item/model/camera.ts
@@ -37,25 +37,42 @@ export interface ModelCameraItem extends BaseItem {
   endBehavior: ItemEndBehavior,
 }
 
+export enum CameraType {
+  orthographic = 'orthographic',
+  perspective = 'perspective',
+}
+
 export interface ModelCameraComponentData extends ComponentData {
+  /**
+   * 相机类型,默认是透视相机
+   */
+  type?: CameraType,
   /**
    * 视角属性
    */
-  fov: number,
+  fov?: number,
   /**
    * 相机远平面
    */
-  far: number,
+  far?: number,
   /**
    * 相机近平面
    */
-  near: number,
+  near?: number,
   /**
    * 默认不提供,等于 canvas 的 `width/height`
    */
   aspect?: number,
+  /**
+   * x轴上范围(正交相机)
+   */
+  xmag?: number,
+  /**
+   * y轴上范围(正交相机)
+   */
+  ymag?: number,
   /**
    * 相机剪裁模式
    */
-  clipMode: CameraClipMode,
+  clipMode?: CameraClipMode,
 }

From 83034be6561e47900122a854bf16cc509950fd45 Mon Sep 17 00:00:00 2001
From: YYL <50564179+Fzc09@users.noreply.github.com>
Date: Wed, 10 Apr 2024 14:56:32 +0800
Subject: [PATCH 14/62] =?UTF-8?q?fix:=20=E6=96=B0=E5=A2=9E=E7=89=B9?=
 =?UTF-8?q?=E6=95=88=E5=85=83=E7=B4=A0=E7=9A=84=20k=20=E5=B8=A7=E5=B1=9E?=
 =?UTF-8?q?=E6=80=A7=E4=BB=A5=E5=8F=8A=E7=B1=BB=E5=9E=8B=E5=AF=BC=E5=87=BA?=
 =?UTF-8?q?=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* feat: add json 3.0 fallback

* perf: opt code

* feat: materialData add string tags

* perf: add vfx-item-data export

* fix: uuid 使用 browser 产物,避免走到 node 模式

* chore: 规范文件命名,优化引入路径

* perf: opt code

* fix: 补充 EffectItem 类型导出

* fix: 补充提交,还原代码

---------

Co-authored-by: wumaolinmaoan <wumaolin1998@outlook.com>
Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 fallback/migration.ts   |  9 +++------
 src/index.ts            |  1 +
 src/item/effect-item.ts | 22 ++++++++++++++++++++--
 3 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/fallback/migration.ts b/fallback/migration.ts
index d04e2c0..2b18e07 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -169,13 +169,10 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
 
           // 兼容旧JSON(anchor和particleOrigin可能同时存在)
           if (!renderer.anchor && renderer.particleOrigin !== undefined) {
-            //@ts-expect-error
-            item.transform.position.x += -realAnchor[0] * startSize.x;
-            //@ts-expect-error
-            item.transform.position.y += -realAnchor[1] * startSize.y;
+            item.transform.position.x += -realAnchor[0] * (startSize?.x ?? 1);
+            item.transform.position.y += -realAnchor[1] * (startSize?.y ?? 1);
           }
-          //@ts-expect-error
-          item.transform.anchor = { x: realAnchor[0] * startSize.x, y: realAnchor[1] * startSize.y };
+          item.transform.anchor = { x: realAnchor[0] * (startSize?.x ?? 1), y: realAnchor[1] * (startSize?.y ?? 1) };
         }
       }
 
diff --git a/src/index.ts b/src/index.ts
index 9601362..4c798fb 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -17,6 +17,7 @@ export * from './item/plugin-item';
 export * from './item/sprite-item';
 export * from './item/spine-item';
 export * from './item/filter-item';
+export * from './item/effect-item';
 export * from './item/text-item';
 export * from './item/model';
 export * from './vfx-item-data';
diff --git a/src/item/effect-item.ts b/src/item/effect-item.ts
index 74793f8..3af5587 100644
--- a/src/item/effect-item.ts
+++ b/src/item/effect-item.ts
@@ -1,10 +1,10 @@
-import type { ItemType } from '../type';
+import type { ItemType, PositionOverLifetime, RotationOverLifetime, SizeOverLifetime } from '../type';
 import type { BaseItem, ItemEndBehavior } from './base-item';
 
 /**
  * 特效元素
  */
-export interface SpineItem extends BaseItem {
+export interface EffectItem extends BaseItem {
   type: ItemType.effect,
   content: EffectContent,
   endBehavior: ItemEndBehavior,
@@ -14,6 +14,24 @@ export interface SpineItem extends BaseItem {
  * 特效元素属性
  */
 export interface EffectContent {
+  /**
+   * 特效元素材质数据索引组
+   */
   materials: number[],
+  /**
+   * 特效元素几何数据索引
+   */
   geometry: number,
+  /**
+   * 特效元素大小变化属性
+   */
+  sizeOverLifetime?: SizeOverLifetime,
+  /**
+   * 特效元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 特效元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
 }

From 94f40916cc4ed3c7b3b32fa9586a2765e5032ec6 Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Fri, 12 Apr 2024 19:18:41 +0800
Subject: [PATCH 15/62] =?UTF-8?q?chore:=20=E6=9B=BF=E6=8D=A2=20Object.assi?=
 =?UTF-8?q?gn=20=E4=B8=BA=E8=A7=A3=E6=9E=84=E8=AF=AD=E6=B3=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 fallback/index.ts     |  2 +-
 fallback/migration.ts | 11 +++++++----
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/fallback/index.ts b/fallback/index.ts
index cd27a42..320429e 100644
--- a/fallback/index.ts
+++ b/fallback/index.ts
@@ -142,7 +142,7 @@ export function getStandardImage (image: any, index: number, imageTags: RenderLe
 export function getStandardComposition (composition: any, opt: { plugins?: string[], requires?: string[] } = {}): Composition {
   const ret: Composition = {
     id: composition.id + '',
-    camera: Object.assign({ clipMode: CAMERA_CLIP_MODE_NORMAL }, composition.camera),
+    camera: { clipMode: CAMERA_CLIP_MODE_NORMAL, ...composition.camera },
     duration: composition.duration,
     endBehavior: composition.endBehavior,
     items: composition.items.map((item: any) => getStandardItem(item, opt)),
diff --git a/fallback/migration.ts b/fallback/migration.ts
index 2b18e07..001f07e 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -46,21 +46,24 @@ export function version22Migration (json: JSONSceneLegacy): JSONSceneLegacy {
  * 3.0 以下版本数据适配(runtime 2.0及以上版本支持)
  */
 export function version30Migration (json: JSONSceneLegacy): JSONScene {
-  const result: JSONScene = Object.assign({}, json, {
+  const result: JSONScene = {
+    ...json,
     items: [],
     components: [],
     materials: [],
     shaders: [],
     geometries: [],
-  });
+  };
 
   // 兼容老版本数据中不存在textures的情况
   result.textures ??= [];
   result.textures.forEach(textureOptions => {
-    Object.assign(textureOptions, {
+    textureOptions = {
+      ...textureOptions,
+      // @ts-expect-error
       id: generateGUID(),
       dataType: DataType.Texture,
-    });
+    };
   });
 
   if (result.textures.length < result.images.length) {

From e46f31861a8b2f3474d3b6daeac2182664850435 Mon Sep 17 00:00:00 2001
From: Sruim <934274351@qq.com>
Date: Mon, 15 Apr 2024 10:03:59 +0800
Subject: [PATCH 16/62] refactor: geometry data (#21)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* feat: 增加`geometry`的`mode`参数

* chore: typo

---------

Co-authored-by: 云垣 <suruimeng.srm@antgroup.com>
Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 src/components.ts | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/src/components.ts b/src/components.ts
index 092c6cc..1713d6c 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -73,9 +73,47 @@ export interface GeometryData extends EffectsObjectData {
   vertexData: VertexData,
   indexFormat: number,
   indexOffset: number,
-  buffer: string, // 存放 position, uv, normal, indices 的打包数据
+  /**
+   * 模型绘制模式,默认为 GeometryType.TRIANGLES(三角形)
+   * @default GeometryType.TRIANGLES
+   */
+  mode: GeometryType,
+  /**
+   * 存放 position, uv, normal, indices 的打包数据
+   */
+  buffer: string,
 }
 
+export enum GeometryType {
+  /**
+   * Draw single points.
+   */
+  POINTS,
+  /**
+   * Draw lines. Each vertex connects to the one after it.
+   */
+  LINES,
+  /**
+   * Draw lines. Each set of two vertices is treated as a separate line segment.
+   */
+  LINE_LOOP,
+  /**
+   * Draw a connected group of line segments from the first vertex to the last.
+   */
+  LINE_STRIP,
+  /**
+   * Draw triangles. Each set of three vertices creates a separate triangle.
+   */
+  TRIANGLES,
+  /**
+   * Draw a connected strip of triangles.
+   */
+  TRIANGLE_STRIP,
+  /**
+   * Draw a connected group of triangles. Each vertex connects to the previous and the first vertex in the fan.
+   */
+  TRIANGLE_FAN,
+}
 export interface VertexData {
   vertexCount: number,
   channels: VertexChannel[],  // channel 存放顺序 position, uv, normal

From 5ced2a21b306763038126579366a0542b8f3539f Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Mon, 15 Apr 2024 10:58:13 +0800
Subject: [PATCH 17/62] perf: opt code

---
 fallback/migration.ts | 10 ----------
 src/vfx-item-data.ts  |  4 ++--
 2 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/fallback/migration.ts b/fallback/migration.ts
index 2b18e07..105e3af 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -235,7 +235,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.SpriteComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.particle) {
         item.components = [];
@@ -244,7 +243,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.ParticleSystem;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.mesh) {
         item.components = [];
@@ -253,7 +251,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.MeshComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.skybox) {
         item.components = [];
@@ -262,7 +259,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.SkyboxComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.light) {
         item.components = [];
@@ -271,7 +267,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.LightComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === 'camera') {
         item.components = [];
@@ -280,7 +275,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.CameraComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.tree) {
         item.components = [];
@@ -289,7 +283,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.TreeComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.interact) {
         item.components = [];
@@ -298,7 +291,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.InteractComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.camera) {
         item.components = [];
@@ -307,7 +299,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.CameraController;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       } else if (item.type === ItemType.text) {
         item.components = [];
@@ -316,7 +307,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         item.content.dataType = DataType.TextComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
-        //@ts-expect-error
         item.components.push({ id: item.content.id });
       }
     }
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index 7cd9586..716b519 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -1,4 +1,4 @@
-import type { ComponentData, EffectsObjectData } from './components';
+import type { ComponentData, DataPath, EffectsObjectData } from './components';
 import type { ItemEndBehavior, ParentItemEndBehavior, BaseContent, TransformData } from './item/base-item';
 import type { ItemType, RenderLevel } from './type';
 
@@ -71,5 +71,5 @@ export interface VFXItemData extends EffectsObjectData {
   /**
    * 元素的组件数据
    */
-  components: ComponentData[],
+  components: DataPath[],
 }

From 0a7918c4e40528ba5a023a271dd11c0f019ee2f7 Mon Sep 17 00:00:00 2001
From: liuxi150 <liuxi150@hotmail.com>
Date: Mon, 15 Apr 2024 11:18:55 +0800
Subject: [PATCH 18/62] fix: primitive data problem

---
 src/item/model/mesh.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index 53468f7..b6d7445 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -93,8 +93,8 @@ export interface ModelMeshItem<T extends BinaryEnv> extends BaseItem {
 }
 
 export interface PrimitiveData {
-  geometry: GeometryData,
-  material: MaterialData,
+  geometry: DataPath,
+  material: DataPath,
 }
 
 export interface SkinData {

From 64a15dac820913c3f330f596fbcb19970fd6af56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Mon, 15 Apr 2024 17:27:00 +0800
Subject: [PATCH 19/62] perf: opt migration function (#25)

* perf: opt Migration function

* perf: opt code

---------

Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 fallback/migration.ts | 131 ++++++++++++++++++------------------------
 1 file changed, 56 insertions(+), 75 deletions(-)

diff --git a/fallback/migration.ts b/fallback/migration.ts
index 1c8803b..b15a58e 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -148,7 +148,7 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
         Object.assign(item, {
           transform: {
             position: { x: position[0], y: position[1], z: position[2] },
-            rotation: { x: rotation[0], y: rotation[1], z: rotation[2] },
+            eulerHint: { x: rotation[0], y: rotation[1], z: rotation[2] },
             scale: { x: scale[0], y: scale[1], z: scale[0] },
           },
         });
@@ -231,87 +231,68 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
       // item 的 content 转为 component data 加入 JSONScene.components
       const uuid = generateGUID();
 
-      if (item.type === ItemType.sprite) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.SpriteComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.particle) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.ParticleSystem;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.mesh) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.MeshComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.skybox) {
+      if (
+        item.type === ItemType.sprite ||
+        item.type === ItemType.particle ||
+        item.type === ItemType.mesh ||
+        item.type === ItemType.skybox ||
+        item.type === ItemType.light ||
+        item.type === 'camera' ||
+        item.type === ItemType.tree ||
+        item.type === ItemType.interact ||
+        item.type === ItemType.camera ||
+        item.type === ItemType.text
+      ) {
         item.components = [];
         result.components.push(item.content);
         item.content.id = uuid;
-        item.content.dataType = DataType.SkyboxComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.light) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.LightComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === 'camera') {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.CameraComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.tree) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.TreeComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.interact) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.InteractComponent;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.camera) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.CameraController;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      } else if (item.type === ItemType.text) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.dataType = DataType.TextComponent;
         item.content.item = { id: item.id };
         item.dataType = DataType.VFXItemData;
         item.components.push({ id: item.content.id });
       }
+
+      switch (item.type) {
+        case ItemType.sprite:
+          item.content.dataType = DataType.SpriteComponent;
+
+          break;
+        case ItemType.particle:
+          item.content.dataType = DataType.ParticleSystem;
+
+          break;
+        case ItemType.mesh:
+          item.content.dataType = DataType.MeshComponent;
+
+          break;
+        case ItemType.skybox:
+          item.content.dataType = DataType.SkyboxComponent;
+
+          break;
+        case ItemType.light:
+          item.content.dataType = DataType.LightComponent;
+
+          break;
+        case 'camera':
+          item.content.dataType = DataType.CameraComponent;
+
+          break;
+        case ItemType.tree:
+          item.content.dataType = DataType.TreeComponent;
+
+          break;
+        case ItemType.interact:
+          item.content.dataType = DataType.InteractComponent;
+
+          break;
+        case ItemType.camera:
+          item.content.dataType = DataType.CameraController;
+
+          break;
+        case ItemType.text:
+          item.content.dataType = DataType.TextComponent;
+
+          break;
+      }
     }
   }
 

From d80d94199be1cf75c4526b1b0dc85e6f54c5e88c Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Tue, 16 Apr 2024 15:33:53 +0800
Subject: [PATCH 20/62] chore: update commitlint cli

---
 package-lock.json | 1700 ++++++++++++++++++++++++---------------------
 package.json      |    2 +-
 2 files changed, 893 insertions(+), 809 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 9ef015f..f186a71 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -9,7 +9,7 @@
       "version": "1.1.0",
       "license": "MIT",
       "devDependencies": {
-        "@commitlint/cli": "^13.2.1",
+        "@commitlint/cli": "^19.2.2",
         "@commitlint/config-conventional": "^13.2.0",
         "@rollup/plugin-commonjs": "^21.0.3",
         "@rollup/plugin-node-resolve": "^13.1.3",
@@ -224,26 +224,158 @@
       }
     },
     "node_modules/@commitlint/cli": {
-      "version": "13.2.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-13.2.1.tgz",
-      "integrity": "sha512-JGzYk2ay5JkRS5w+FLQzr0u/Kih52ds4HPpa3vnwVOQN8Q+S1VYr8Nk/6kRm6uNYsAcC1nejtuDxRdLcLh/9TA==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/format": "^13.2.0",
-        "@commitlint/lint": "^13.2.0",
-        "@commitlint/load": "^13.2.1",
-        "@commitlint/read": "^13.2.0",
-        "@commitlint/types": "^13.2.0",
-        "lodash": "^4.17.19",
-        "resolve-from": "5.0.0",
-        "resolve-global": "1.0.0",
+      "version": "19.2.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.2.2.tgz",
+      "integrity": "sha512-P8cbOHfg2PQRzfICLSrzUVOCVMqjEZ8Hlth6mtJ4yOEjT47Q5PbIGymgX3rLVylNw+3IAT2Djn9IJ2wHbXFzBg==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/format": "^19.0.3",
+        "@commitlint/lint": "^19.2.2",
+        "@commitlint/load": "^19.2.0",
+        "@commitlint/read": "^19.2.1",
+        "@commitlint/types": "^19.0.3",
+        "execa": "^8.0.1",
         "yargs": "^17.0.0"
       },
       "bin": {
         "commitlint": "cli.js"
       },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/execa": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
+      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^8.0.1",
+        "human-signals": "^5.0.0",
+        "is-stream": "^3.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^5.1.0",
+        "onetime": "^6.0.0",
+        "signal-exit": "^4.1.0",
+        "strip-final-newline": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=16.17"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/get-stream": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
+      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+      "dev": true,
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/human-signals": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
+      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.17.0"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/is-stream": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/mimic-fn": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/npm-run-path": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/onetime": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/path-key": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/@commitlint/cli/node_modules/strip-final-newline": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/@commitlint/config-conventional": {
@@ -258,222 +390,663 @@
         "node": ">=v12"
       }
     },
+    "node_modules/@commitlint/config-validator": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz",
+      "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "ajv": "^8.11.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/config-validator/node_modules/ajv": {
+      "version": "8.12.0",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+      "dev": true,
+      "dependencies": {
+        "fast-deep-equal": "^3.1.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2",
+        "uri-js": "^4.2.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+      "dev": true
+    },
     "node_modules/@commitlint/ensure": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-13.2.0.tgz",
-      "integrity": "sha512-rqhT62RehdLTRBu8OrPHnRCCd/7RmHEE4TiTlT4BLlr5ls5jlZhecOQWJ8np872uCNirrJ5NFjnjYYdbkNoW9Q==",
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz",
+      "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==",
       "dev": true,
       "dependencies": {
-        "@commitlint/types": "^13.2.0",
-        "lodash": "^4.17.19"
+        "@commitlint/types": "^19.0.3",
+        "lodash.camelcase": "^4.3.0",
+        "lodash.kebabcase": "^4.1.1",
+        "lodash.snakecase": "^4.1.1",
+        "lodash.startcase": "^4.4.0",
+        "lodash.upperfirst": "^4.3.1"
       },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
       }
     },
     "node_modules/@commitlint/execute-rule": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-13.2.0.tgz",
-      "integrity": "sha512-6nPwpN0hwTYmsH3WM4hCdN+NrMopgRIuQ0aqZa+jnwMoS/g6ljliQNYfL+m5WO306BaIu1W3yYpbW5aI8gEr0g==",
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz",
+      "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==",
       "dev": true,
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
       }
     },
     "node_modules/@commitlint/format": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-13.2.0.tgz",
-      "integrity": "sha512-yNBQJe6YFhM1pJAta4LvzQxccSKof6axJH7ALYjuhQqfT8AKlad7Y/2SuJ07ioyreNIqwOTuF2UfU8yJ7JzEIQ==",
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.0.3.tgz",
+      "integrity": "sha512-QjjyGyoiVWzx1f5xOteKHNLFyhyweVifMgopozSgx1fGNrGV8+wp7k6n1t6StHdJ6maQJ+UUtO2TcEiBFRyR6Q==",
       "dev": true,
       "dependencies": {
-        "@commitlint/types": "^13.2.0",
-        "chalk": "^4.0.0"
+        "@commitlint/types": "^19.0.3",
+        "chalk": "^5.3.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/format/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
     "node_modules/@commitlint/is-ignored": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-13.2.0.tgz",
-      "integrity": "sha512-onnx4WctHFPPkHGFFAZBIWRSaNwuhixIIfbwPhcZ6IewwQX5n4jpjwM1GokA7vhlOnQ57W7AavbKUGjzIVtnRQ==",
+      "version": "19.2.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.2.2.tgz",
+      "integrity": "sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==",
       "dev": true,
       "dependencies": {
-        "@commitlint/types": "^13.2.0",
-        "semver": "7.3.5"
+        "@commitlint/types": "^19.0.3",
+        "semver": "^7.6.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/lint": {
+      "version": "19.2.2",
+      "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.2.2.tgz",
+      "integrity": "sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/is-ignored": "^19.2.2",
+        "@commitlint/parse": "^19.0.3",
+        "@commitlint/rules": "^19.0.3",
+        "@commitlint/types": "^19.0.3"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/load": {
+      "version": "19.2.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.2.0.tgz",
+      "integrity": "sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/config-validator": "^19.0.3",
+        "@commitlint/execute-rule": "^19.0.0",
+        "@commitlint/resolve-extends": "^19.1.0",
+        "@commitlint/types": "^19.0.3",
+        "chalk": "^5.3.0",
+        "cosmiconfig": "^9.0.0",
+        "cosmiconfig-typescript-loader": "^5.0.0",
+        "lodash.isplainobject": "^4.0.6",
+        "lodash.merge": "^4.6.2",
+        "lodash.uniq": "^4.5.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
+      "dev": true,
+      "engines": {
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/cosmiconfig": {
+      "version": "9.0.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
+      "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
+      "dev": true,
+      "dependencies": {
+        "env-paths": "^2.2.1",
+        "import-fresh": "^3.3.0",
+        "js-yaml": "^4.1.0",
+        "parse-json": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/d-fischer"
+      },
+      "peerDependencies": {
+        "typescript": ">=4.9.5"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz",
+      "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==",
+      "dev": true,
+      "dependencies": {
+        "jiti": "^1.19.1"
+      },
+      "engines": {
+        "node": ">=v16"
+      },
+      "peerDependencies": {
+        "@types/node": "*",
+        "cosmiconfig": ">=8.2",
+        "typescript": ">=4"
+      }
+    },
+    "node_modules/@commitlint/message": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz",
+      "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==",
+      "dev": true,
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/parse": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz",
+      "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/types": "^19.0.3",
+        "conventional-changelog-angular": "^7.0.0",
+        "conventional-commits-parser": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/read": {
+      "version": "19.2.1",
+      "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.2.1.tgz",
+      "integrity": "sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/top-level": "^19.0.0",
+        "@commitlint/types": "^19.0.3",
+        "execa": "^8.0.1",
+        "git-raw-commits": "^4.0.0",
+        "minimist": "^1.2.8"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/execa": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
+      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^8.0.1",
+        "human-signals": "^5.0.0",
+        "is-stream": "^3.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^5.1.0",
+        "onetime": "^6.0.0",
+        "signal-exit": "^4.1.0",
+        "strip-final-newline": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=16.17"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/get-stream": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
+      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+      "dev": true,
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/human-signals": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
+      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.17.0"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/is-stream": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/mimic-fn": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/npm-run-path": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/onetime": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/path-key": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/@commitlint/read/node_modules/strip-final-newline": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/resolve-extends": {
+      "version": "19.1.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz",
+      "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/config-validator": "^19.0.3",
+        "@commitlint/types": "^19.0.3",
+        "global-directory": "^4.0.1",
+        "import-meta-resolve": "^4.0.0",
+        "lodash.mergewith": "^4.6.2",
+        "resolve-from": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/rules": {
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz",
+      "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==",
+      "dev": true,
+      "dependencies": {
+        "@commitlint/ensure": "^19.0.3",
+        "@commitlint/message": "^19.0.0",
+        "@commitlint/to-lines": "^19.0.0",
+        "@commitlint/types": "^19.0.3",
+        "execa": "^8.0.1"
+      },
+      "engines": {
+        "node": ">=v18"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/execa": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
+      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
+      "dev": true,
+      "dependencies": {
+        "cross-spawn": "^7.0.3",
+        "get-stream": "^8.0.1",
+        "human-signals": "^5.0.0",
+        "is-stream": "^3.0.0",
+        "merge-stream": "^2.0.0",
+        "npm-run-path": "^5.1.0",
+        "onetime": "^6.0.0",
+        "signal-exit": "^4.1.0",
+        "strip-final-newline": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=16.17"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/execa?sponsor=1"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/get-stream": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
+      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
+      "dev": true,
+      "engines": {
+        "node": ">=16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/human-signals": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
+      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=16.17.0"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/is-stream": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
+      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
+      "dev": true,
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/mimic-fn": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
+      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/npm-run-path": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
+      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
+      "dev": true,
+      "dependencies": {
+        "path-key": "^4.0.0"
+      },
+      "engines": {
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/onetime": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
+      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
+      "dev": true,
+      "dependencies": {
+        "mimic-fn": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/@commitlint/rules/node_modules/path-key": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
+      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
+      "dev": true,
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@commitlint/is-ignored/node_modules/semver": {
-      "version": "7.3.5",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
-      "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
+    "node_modules/@commitlint/rules/node_modules/signal-exit": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
       "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
       "engines": {
-        "node": ">=10"
+        "node": ">=14"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
       }
     },
-    "node_modules/@commitlint/lint": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-13.2.0.tgz",
-      "integrity": "sha512-5XYkh0e9ehHjA7BxAHFpjPgr1qqbFY8OFG1wpBiAhycbYBtJnQmculA2wcwqTM40YCUBqEvWFdq86jTG8fbkMw==",
+    "node_modules/@commitlint/rules/node_modules/strip-final-newline": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
+      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
       "dev": true,
-      "dependencies": {
-        "@commitlint/is-ignored": "^13.2.0",
-        "@commitlint/parse": "^13.2.0",
-        "@commitlint/rules": "^13.2.0",
-        "@commitlint/types": "^13.2.0"
-      },
       "engines": {
-        "node": ">=v12"
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@commitlint/load": {
-      "version": "13.2.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-13.2.1.tgz",
-      "integrity": "sha512-qlaJkj0hfa9gtWRfCfbgFBTK3GYQRmjZhba4l9mUu4wV9lEZ4ICFlrLtd/8kaLXf/8xbrPhkAPkVFOAqM0YwUQ==",
+    "node_modules/@commitlint/to-lines": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz",
+      "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==",
       "dev": true,
-      "dependencies": {
-        "@commitlint/execute-rule": "^13.2.0",
-        "@commitlint/resolve-extends": "^13.2.0",
-        "@commitlint/types": "^13.2.0",
-        "@endemolshinegroup/cosmiconfig-typescript-loader": "^3.0.2",
-        "chalk": "^4.0.0",
-        "cosmiconfig": "^7.0.0",
-        "lodash": "^4.17.19",
-        "resolve-from": "^5.0.0",
-        "typescript": "^4.4.3"
-      },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
       }
     },
-    "node_modules/@commitlint/message": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-13.2.0.tgz",
-      "integrity": "sha512-+LlErJj2F2AC86xJb33VJIvSt25xqSF1I0b0GApSgoUtQBeJhx4SxIj1BLvGcLVmbRmbgTzAFq/QylwLId7EhA==",
+    "node_modules/@commitlint/top-level": {
+      "version": "19.0.0",
+      "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz",
+      "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==",
       "dev": true,
+      "dependencies": {
+        "find-up": "^7.0.0"
+      },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
       }
     },
-    "node_modules/@commitlint/parse": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-13.2.0.tgz",
-      "integrity": "sha512-AtfKSQJQADbDhW+kuC5PxOyBANsYCuuJlZRZ2PYslOz2rvWwZ93zt+nKjM4g7C9ETbz0uq4r7/EoOsTJ2nJqfQ==",
+    "node_modules/@commitlint/top-level/node_modules/find-up": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz",
+      "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==",
       "dev": true,
       "dependencies": {
-        "@commitlint/types": "^13.2.0",
-        "conventional-changelog-angular": "^5.0.11",
-        "conventional-commits-parser": "^3.2.2"
+        "locate-path": "^7.2.0",
+        "path-exists": "^5.0.0",
+        "unicorn-magic": "^0.1.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@commitlint/read": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-13.2.0.tgz",
-      "integrity": "sha512-7db5e1Bn3re6hQN0SqygTMF/QX6/MQauoJn3wJiUHE93lvwO6aFQxT3qAlYeyBPwfWsmDz/uSH454jtrSsv3Uw==",
+    "node_modules/@commitlint/top-level/node_modules/locate-path": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+      "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
       "dev": true,
       "dependencies": {
-        "@commitlint/top-level": "^13.2.0",
-        "@commitlint/types": "^13.2.0",
-        "fs-extra": "^10.0.0",
-        "git-raw-commits": "^2.0.0"
+        "p-locate": "^6.0.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@commitlint/resolve-extends": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-13.2.0.tgz",
-      "integrity": "sha512-HLCMkqMKtvl1yYLZ1Pm0UpFvd0kYjsm1meLOGZ7VkOd9G/XX+Fr1S2G5AT2zeiDw7WUVYK8lGVMNa319bnV+aw==",
+    "node_modules/@commitlint/top-level/node_modules/p-limit": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+      "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
       "dev": true,
       "dependencies": {
-        "import-fresh": "^3.0.0",
-        "lodash": "^4.17.19",
-        "resolve-from": "^5.0.0",
-        "resolve-global": "^1.0.0"
+        "yocto-queue": "^1.0.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@commitlint/rules": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-13.2.0.tgz",
-      "integrity": "sha512-O3A9S7blOzvHfzrJrUQe9JxdtGy154ol/GXHwvd8WfMJ10y5ryBB4b6+0YZ1XhItWzrEASOfOKbD++EdLV90dQ==",
+    "node_modules/@commitlint/top-level/node_modules/p-locate": {
+      "version": "6.0.0",
+      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+      "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
       "dev": true,
       "dependencies": {
-        "@commitlint/ensure": "^13.2.0",
-        "@commitlint/message": "^13.2.0",
-        "@commitlint/to-lines": "^13.2.0",
-        "@commitlint/types": "^13.2.0",
-        "execa": "^5.0.0"
+        "p-limit": "^4.0.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/@commitlint/to-lines": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-13.2.0.tgz",
-      "integrity": "sha512-ZfWZix2y/CzewReCrj5g0nKOEfj5HW9eBMDrqjJJMPApve00CWv0tYrFCGXuGlv244lW4uvWJt6J/0HLRWsfyg==",
+    "node_modules/@commitlint/top-level/node_modules/path-exists": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+      "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
       "dev": true,
       "engines": {
-        "node": ">=v12"
+        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
       }
     },
-    "node_modules/@commitlint/top-level": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-13.2.0.tgz",
-      "integrity": "sha512-knBvWYbIq6VV6VPHrVeDsxDiJq4Zq6cv5NIYU3iesKAsmK2KlLfsZPa+Ig96Y4AqAPU3zNJwjHxYkz9qxdBbfA==",
+    "node_modules/@commitlint/top-level/node_modules/yocto-queue": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
+      "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
       "dev": true,
-      "dependencies": {
-        "find-up": "^5.0.0"
-      },
       "engines": {
-        "node": ">=v12"
+        "node": ">=12.20"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/@commitlint/types": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-13.2.0.tgz",
-      "integrity": "sha512-RRVHEqmk1qn/dIaSQhvuca6k/6Z54G+r/KyimZ8gnAFielGiGUpsFRhIY3qhd5rXClVxDaa3nlcyTWckSccotQ==",
+      "version": "19.0.3",
+      "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz",
+      "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==",
       "dev": true,
       "dependencies": {
-        "chalk": "^4.0.0"
+        "@types/conventional-commits-parser": "^5.0.0",
+        "chalk": "^5.3.0"
       },
       "engines": {
-        "node": ">=v12"
+        "node": ">=v18"
       }
     },
-    "node_modules/@endemolshinegroup/cosmiconfig-typescript-loader": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/@endemolshinegroup/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-3.0.2.tgz",
-      "integrity": "sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==",
+    "node_modules/@commitlint/types/node_modules/chalk": {
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
+      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
       "dev": true,
-      "dependencies": {
-        "lodash.get": "^4",
-        "make-error": "^1",
-        "ts-node": "^9",
-        "tslib": "^2"
-      },
       "engines": {
-        "node": ">=10.0.0"
+        "node": "^12.17.0 || ^14.13 || >=16.0.0"
       },
-      "peerDependencies": {
-        "cosmiconfig": ">=6"
+      "funding": {
+        "url": "https://github.com/chalk/chalk?sponsor=1"
       }
     },
     "node_modules/@eslint-community/eslint-utils": {
@@ -708,6 +1281,15 @@
         "@types/chai": "*"
       }
     },
+    "node_modules/@types/conventional-commits-parser": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
+      "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
     "node_modules/@types/estree": {
       "version": "0.0.39",
       "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
@@ -720,12 +1302,6 @@
       "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
       "dev": true
     },
-    "node_modules/@types/minimist": {
-      "version": "1.2.5",
-      "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
-      "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
-      "dev": true
-    },
     "node_modules/@types/mocha": {
       "version": "10.0.4",
       "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.4.tgz",
@@ -738,12 +1314,6 @@
       "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
       "dev": true
     },
-    "node_modules/@types/normalize-package-data": {
-      "version": "2.4.4",
-      "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
-      "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
-      "dev": true
-    },
     "node_modules/@types/parse-json": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
@@ -1082,12 +1652,6 @@
         "node": ">= 8"
       }
     },
-    "node_modules/arg": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
-      "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
-      "dev": true
-    },
     "node_modules/argparse": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -1109,15 +1673,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/arrify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz",
-      "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/assertion-error": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
@@ -1206,12 +1761,6 @@
         "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
       }
     },
-    "node_modules/buffer-from": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
-      "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
-      "dev": true
-    },
     "node_modules/builtin-modules": {
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
@@ -1233,32 +1782,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/camelcase": {
-      "version": "5.3.1",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
-      "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/camelcase-keys": {
-      "version": "6.2.2",
-      "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz",
-      "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==",
-      "dev": true,
-      "dependencies": {
-        "camelcase": "^5.3.1",
-        "map-obj": "^4.0.0",
-        "quick-lru": "^4.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/caniuse-lite": {
       "version": "1.0.30001577",
       "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz",
@@ -1469,16 +1992,15 @@
       "dev": true
     },
     "node_modules/conventional-changelog-angular": {
-      "version": "5.0.13",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz",
-      "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz",
+      "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==",
       "dev": true,
       "dependencies": {
-        "compare-func": "^2.0.0",
-        "q": "^1.5.1"
+        "compare-func": "^2.0.0"
       },
       "engines": {
-        "node": ">=10"
+        "node": ">=16"
       }
     },
     "node_modules/conventional-changelog-conventionalcommits": {
@@ -1496,23 +2018,21 @@
       }
     },
     "node_modules/conventional-commits-parser": {
-      "version": "3.2.4",
-      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.4.tgz",
-      "integrity": "sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
+      "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==",
       "dev": true,
       "dependencies": {
-        "is-text-path": "^1.0.1",
-        "JSONStream": "^1.0.4",
-        "lodash": "^4.17.15",
-        "meow": "^8.0.0",
-        "split2": "^3.0.0",
-        "through2": "^4.0.0"
+        "is-text-path": "^2.0.0",
+        "JSONStream": "^1.3.5",
+        "meow": "^12.0.1",
+        "split2": "^4.0.0"
       },
       "bin": {
-        "conventional-commits-parser": "cli.js"
+        "conventional-commits-parser": "cli.mjs"
       },
       "engines": {
-        "node": ">=10"
+        "node": ">=16"
       }
     },
     "node_modules/cosmiconfig": {
@@ -1531,12 +2051,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/create-require": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
-      "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
-      "dev": true
-    },
     "node_modules/cross-spawn": {
       "version": "7.0.3",
       "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@@ -1552,12 +2066,15 @@
       }
     },
     "node_modules/dargs": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz",
-      "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==",
+      "version": "8.1.0",
+      "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz",
+      "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==",
       "dev": true,
       "engines": {
-        "node": ">=8"
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/debug": {
@@ -1577,40 +2094,6 @@
         }
       }
     },
-    "node_modules/decamelize": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
-      "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/decamelize-keys": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz",
-      "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==",
-      "dev": true,
-      "dependencies": {
-        "decamelize": "^1.1.0",
-        "map-obj": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/decamelize-keys/node_modules/map-obj": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz",
-      "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/deep-eql": {
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
@@ -1708,6 +2191,15 @@
         "node": ">=8.6"
       }
     },
+    "node_modules/env-paths": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+      "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+      "dev": true,
+      "engines": {
+        "node": ">=6"
+      }
+    },
     "node_modules/error-ex": {
       "version": "1.3.2",
       "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -2106,20 +2598,6 @@
       "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
       "dev": true
     },
-    "node_modules/fs-extra": {
-      "version": "10.1.0",
-      "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
-      "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
-      "dev": true,
-      "dependencies": {
-        "graceful-fs": "^4.2.0",
-        "jsonfile": "^6.0.1",
-        "universalify": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
     "node_modules/fs.realpath": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
@@ -2186,22 +2664,20 @@
       }
     },
     "node_modules/git-raw-commits": {
-      "version": "2.0.11",
-      "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz",
-      "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz",
+      "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==",
       "dev": true,
       "dependencies": {
-        "dargs": "^7.0.0",
-        "lodash": "^4.17.15",
-        "meow": "^8.0.0",
-        "split2": "^3.0.0",
-        "through2": "^4.0.0"
+        "dargs": "^8.0.0",
+        "meow": "^12.0.1",
+        "split2": "^4.0.0"
       },
       "bin": {
-        "git-raw-commits": "cli.js"
+        "git-raw-commits": "cli.mjs"
       },
       "engines": {
-        "node": ">=10"
+        "node": ">=16"
       }
     },
     "node_modules/glob": {
@@ -2236,16 +2712,19 @@
         "node": ">=10.13.0"
       }
     },
-    "node_modules/global-dirs": {
-      "version": "0.1.1",
-      "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz",
-      "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==",
+    "node_modules/global-directory": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz",
+      "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==",
       "dev": true,
       "dependencies": {
-        "ini": "^1.3.4"
+        "ini": "4.1.1"
       },
       "engines": {
-        "node": ">=4"
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/globals": {
@@ -2283,27 +2762,12 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/graceful-fs": {
-      "version": "4.2.11",
-      "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
-      "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
-      "dev": true
-    },
     "node_modules/graphemer": {
       "version": "1.4.0",
       "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
       "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
       "dev": true
     },
-    "node_modules/hard-rejection": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz",
-      "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/has-flag": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
@@ -2334,18 +2798,6 @@
         "he": "bin/he"
       }
     },
-    "node_modules/hosted-git-info": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz",
-      "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
     "node_modules/human-signals": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
@@ -2404,6 +2856,16 @@
         "node": ">=4"
       }
     },
+    "node_modules/import-meta-resolve": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
+      "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==",
+      "dev": true,
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
     "node_modules/imurmurhash": {
       "version": "0.1.4",
       "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
@@ -2439,10 +2901,13 @@
       "dev": true
     },
     "node_modules/ini": {
-      "version": "1.3.8",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-      "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
-      "dev": true
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
+      "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
+      "dev": true,
+      "engines": {
+        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
+      }
     },
     "node_modules/is-arrayish": {
       "version": "0.2.1",
@@ -2552,15 +3017,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/is-plain-obj": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
-      "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/is-reference": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
@@ -2592,15 +3048,15 @@
       }
     },
     "node_modules/is-text-path": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz",
-      "integrity": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz",
+      "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==",
       "dev": true,
       "dependencies": {
-        "text-extensions": "^1.0.0"
+        "text-extensions": "^2.0.0"
       },
       "engines": {
-        "node": ">=0.10.0"
+        "node": ">=8"
       }
     },
     "node_modules/is-unicode-supported": {
@@ -2621,6 +3077,15 @@
       "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
       "dev": true
     },
+    "node_modules/jiti": {
+      "version": "1.21.0",
+      "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
+      "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
+      "dev": true,
+      "bin": {
+        "jiti": "bin/jiti.js"
+      }
+    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -2663,18 +3128,6 @@
       "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
       "dev": true
     },
-    "node_modules/jsonfile": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
-      "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
-      "dev": true,
-      "dependencies": {
-        "universalify": "^2.0.0"
-      },
-      "optionalDependencies": {
-        "graceful-fs": "^4.1.6"
-      }
-    },
     "node_modules/jsonparse": {
       "version": "1.3.1",
       "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
@@ -2709,15 +3162,6 @@
         "json-buffer": "3.0.1"
       }
     },
-    "node_modules/kind-of": {
-      "version": "6.0.3",
-      "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
-      "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
     "node_modules/levn": {
       "version": "0.4.1",
       "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
@@ -2858,10 +3302,22 @@
       "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
       "dev": true
     },
-    "node_modules/lodash.get": {
-      "version": "4.4.2",
-      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
-      "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==",
+    "node_modules/lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+      "dev": true
+    },
+    "node_modules/lodash.isplainobject": {
+      "version": "4.0.6",
+      "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+      "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+      "dev": true
+    },
+    "node_modules/lodash.kebabcase": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
+      "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
       "dev": true
     },
     "node_modules/lodash.memoize": {
@@ -2876,6 +3332,36 @@
       "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
       "dev": true
     },
+    "node_modules/lodash.mergewith": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
+      "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
+      "dev": true
+    },
+    "node_modules/lodash.snakecase": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
+      "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
+      "dev": true
+    },
+    "node_modules/lodash.startcase": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
+      "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
+      "dev": true
+    },
+    "node_modules/lodash.uniq": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+      "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+      "dev": true
+    },
+    "node_modules/lodash.upperfirst": {
+      "version": "4.3.1",
+      "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
+      "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
+      "dev": true
+    },
     "node_modules/log-symbols": {
       "version": "4.1.0",
       "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
@@ -2971,56 +3457,13 @@
         "sourcemap-codec": "^1.4.8"
       }
     },
-    "node_modules/make-error": {
-      "version": "1.3.6",
-      "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
-      "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
-      "dev": true
-    },
-    "node_modules/map-obj": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz",
-      "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
     "node_modules/meow": {
-      "version": "8.1.2",
-      "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz",
-      "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==",
-      "dev": true,
-      "dependencies": {
-        "@types/minimist": "^1.2.0",
-        "camelcase-keys": "^6.2.2",
-        "decamelize-keys": "^1.1.0",
-        "hard-rejection": "^2.1.0",
-        "minimist-options": "4.1.0",
-        "normalize-package-data": "^3.0.0",
-        "read-pkg-up": "^7.0.1",
-        "redent": "^3.0.0",
-        "trim-newlines": "^3.0.0",
-        "type-fest": "^0.18.0",
-        "yargs-parser": "^20.2.3"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/meow/node_modules/type-fest": {
-      "version": "0.18.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz",
-      "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==",
+      "version": "12.1.1",
+      "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz",
+      "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==",
       "dev": true,
       "engines": {
-        "node": ">=10"
+        "node": ">=16.10"
       },
       "funding": {
         "url": "https://github.com/sponsors/sindresorhus"
@@ -3075,15 +3518,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/min-indent": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
-      "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
     "node_modules/minimatch": {
       "version": "3.1.2",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -3096,18 +3530,13 @@
         "node": "*"
       }
     },
-    "node_modules/minimist-options": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz",
-      "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==",
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
       "dev": true,
-      "dependencies": {
-        "arrify": "^1.0.1",
-        "is-plain-obj": "^1.1.0",
-        "kind-of": "^6.0.3"
-      },
-      "engines": {
-        "node": ">= 6"
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
       }
     },
     "node_modules/mocha": {
@@ -3307,21 +3736,6 @@
       "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
       "dev": true
     },
-    "node_modules/normalize-package-data": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz",
-      "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==",
-      "dev": true,
-      "dependencies": {
-        "hosted-git-info": "^4.0.1",
-        "is-core-module": "^2.5.0",
-        "semver": "^7.3.4",
-        "validate-npm-package-license": "^3.0.1"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
     "node_modules/normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
@@ -3444,15 +3858,6 @@
         "url": "https://github.com/sponsors/sindresorhus"
       }
     },
-    "node_modules/p-try": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
-      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/parent-module": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -3609,15 +4014,6 @@
         }
       ]
     },
-    "node_modules/quick-lru": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz",
-      "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/randombytes": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
@@ -3627,149 +4023,6 @@
         "safe-buffer": "^5.1.0"
       }
     },
-    "node_modules/read-pkg": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
-      "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
-      "dev": true,
-      "dependencies": {
-        "@types/normalize-package-data": "^2.4.0",
-        "normalize-package-data": "^2.5.0",
-        "parse-json": "^5.0.0",
-        "type-fest": "^0.6.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/read-pkg-up": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
-      "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
-      "dev": true,
-      "dependencies": {
-        "find-up": "^4.1.0",
-        "read-pkg": "^5.2.0",
-        "type-fest": "^0.8.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/read-pkg-up/node_modules/find-up": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
-      "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
-      "dev": true,
-      "dependencies": {
-        "locate-path": "^5.0.0",
-        "path-exists": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/read-pkg-up/node_modules/locate-path": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
-      "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
-      "dev": true,
-      "dependencies": {
-        "p-locate": "^4.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/read-pkg-up/node_modules/p-limit": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
-      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
-      "dev": true,
-      "dependencies": {
-        "p-try": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/read-pkg-up/node_modules/p-locate": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
-      "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
-      "dev": true,
-      "dependencies": {
-        "p-limit": "^2.2.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/read-pkg-up/node_modules/type-fest": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
-      "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/read-pkg/node_modules/hosted-git-info": {
-      "version": "2.8.9",
-      "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
-      "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
-      "dev": true
-    },
-    "node_modules/read-pkg/node_modules/normalize-package-data": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
-      "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
-      "dev": true,
-      "dependencies": {
-        "hosted-git-info": "^2.1.4",
-        "resolve": "^1.10.0",
-        "semver": "2 || 3 || 4 || 5",
-        "validate-npm-package-license": "^3.0.1"
-      }
-    },
-    "node_modules/read-pkg/node_modules/semver": {
-      "version": "5.7.2",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
-      "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
-      "dev": true,
-      "bin": {
-        "semver": "bin/semver"
-      }
-    },
-    "node_modules/read-pkg/node_modules/type-fest": {
-      "version": "0.6.0",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
-      "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/readable-stream": {
-      "version": "3.6.2",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
-      "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
-      "dev": true,
-      "dependencies": {
-        "inherits": "^2.0.3",
-        "string_decoder": "^1.1.1",
-        "util-deprecate": "^1.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
     "node_modules/readdirp": {
       "version": "3.6.0",
       "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
@@ -3782,19 +4035,6 @@
         "node": ">=8.10.0"
       }
     },
-    "node_modules/redent": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
-      "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
-      "dev": true,
-      "dependencies": {
-        "indent-string": "^4.0.0",
-        "strip-indent": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/require-directory": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
@@ -3804,6 +4044,15 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
     "node_modules/resolve": {
       "version": "1.22.8",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
@@ -3830,18 +4079,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/resolve-global": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz",
-      "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==",
-      "dev": true,
-      "dependencies": {
-        "global-dirs": "^0.1.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/restore-cursor": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
@@ -4055,25 +4292,6 @@
         "node": ">=8"
       }
     },
-    "node_modules/source-map": {
-      "version": "0.6.1",
-      "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/source-map-support": {
-      "version": "0.5.21",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
-      "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
-      "dev": true,
-      "dependencies": {
-        "buffer-from": "^1.0.0",
-        "source-map": "^0.6.0"
-      }
-    },
     "node_modules/sourcemap-codec": {
       "version": "1.4.8",
       "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
@@ -4081,54 +4299,13 @@
       "deprecated": "Please use @jridgewell/sourcemap-codec instead",
       "dev": true
     },
-    "node_modules/spdx-correct": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
-      "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
-      "dev": true,
-      "dependencies": {
-        "spdx-expression-parse": "^3.0.0",
-        "spdx-license-ids": "^3.0.0"
-      }
-    },
-    "node_modules/spdx-exceptions": {
-      "version": "2.5.0",
-      "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
-      "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
-      "dev": true
-    },
-    "node_modules/spdx-expression-parse": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
-      "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
-      "dev": true,
-      "dependencies": {
-        "spdx-exceptions": "^2.1.0",
-        "spdx-license-ids": "^3.0.0"
-      }
-    },
-    "node_modules/spdx-license-ids": {
-      "version": "3.0.17",
-      "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz",
-      "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==",
-      "dev": true
-    },
     "node_modules/split2": {
-      "version": "3.2.2",
-      "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
-      "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
-      "dev": true,
-      "dependencies": {
-        "readable-stream": "^3.0.0"
-      }
-    },
-    "node_modules/string_decoder": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
-      "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+      "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
       "dev": true,
-      "dependencies": {
-        "safe-buffer": "~5.2.0"
+      "engines": {
+        "node": ">= 10.x"
       }
     },
     "node_modules/string-argv": {
@@ -4198,18 +4375,6 @@
         "node": ">=6"
       }
     },
-    "node_modules/strip-indent": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
-      "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
-      "dev": true,
-      "dependencies": {
-        "min-indent": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
     "node_modules/strip-json-comments": {
       "version": "3.1.1",
       "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
@@ -4247,12 +4412,15 @@
       }
     },
     "node_modules/text-extensions": {
-      "version": "1.9.0",
-      "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz",
-      "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==",
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
+      "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==",
       "dev": true,
       "engines": {
-        "node": ">=0.10"
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/text-table": {
@@ -4267,15 +4435,6 @@
       "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
       "dev": true
     },
-    "node_modules/through2": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz",
-      "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==",
-      "dev": true,
-      "dependencies": {
-        "readable-stream": "3"
-      }
-    },
     "node_modules/to-regex-range": {
       "version": "5.0.1",
       "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@@ -4288,50 +4447,6 @@
         "node": ">=8.0"
       }
     },
-    "node_modules/trim-newlines": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz",
-      "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ts-node": {
-      "version": "9.1.1",
-      "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-9.1.1.tgz",
-      "integrity": "sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==",
-      "dev": true,
-      "dependencies": {
-        "arg": "^4.1.0",
-        "create-require": "^1.1.0",
-        "diff": "^4.0.1",
-        "make-error": "^1.1.1",
-        "source-map-support": "^0.5.17",
-        "yn": "3.1.1"
-      },
-      "bin": {
-        "ts-node": "dist/bin.js",
-        "ts-node-script": "dist/bin-script.js",
-        "ts-node-transpile-only": "dist/bin-transpile.js",
-        "ts-script": "dist/bin-script-deprecated.js"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "typescript": ">=2.7"
-      }
-    },
-    "node_modules/ts-node/node_modules/diff": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
-      "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.3.1"
-      }
-    },
     "node_modules/tslib": {
       "version": "2.6.2",
       "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
@@ -4405,13 +4520,16 @@
         "node": ">=4.2.0"
       }
     },
-    "node_modules/universalify": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
-      "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+    "node_modules/unicorn-magic": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
+      "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
       "dev": true,
       "engines": {
-        "node": ">= 10.0.0"
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
       }
     },
     "node_modules/update-browserslist-db": {
@@ -4439,12 +4557,6 @@
         "punycode": "^2.1.0"
       }
     },
-    "node_modules/util-deprecate": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
-      "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
-      "dev": true
-    },
     "node_modules/uuid": {
       "version": "9.0.1",
       "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
@@ -4458,16 +4570,6 @@
         "uuid": "dist/bin/uuid"
       }
     },
-    "node_modules/validate-npm-package-license": {
-      "version": "3.0.4",
-      "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
-      "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
-      "dev": true,
-      "dependencies": {
-        "spdx-correct": "^3.0.0",
-        "spdx-expression-parse": "^3.0.0"
-      }
-    },
     "node_modules/which": {
       "version": "2.0.2",
       "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -4575,15 +4677,6 @@
         "node": ">=12"
       }
     },
-    "node_modules/yargs-parser": {
-      "version": "20.2.9",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
-      "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
     "node_modules/yargs-unparser": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
@@ -4641,15 +4734,6 @@
         "node": ">=12"
       }
     },
-    "node_modules/yn": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
-      "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
     "node_modules/yocto-queue": {
       "version": "0.1.0",
       "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
diff --git a/package.json b/package.json
index 24fc26f..24624f4 100644
--- a/package.json
+++ b/package.json
@@ -37,7 +37,7 @@
     "iOS 9"
   ],
   "devDependencies": {
-    "@commitlint/cli": "^13.2.1",
+    "@commitlint/cli": "^19.2.2",
     "@commitlint/config-conventional": "^13.2.0",
     "@rollup/plugin-commonjs": "^21.0.3",
     "@rollup/plugin-node-resolve": "^13.1.3",

From b6ec7e51083330ff0580825deca443156e9a9a45 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 16 Apr 2024 18:09:51 +0800
Subject: [PATCH 21/62] fix: fix texture id

---
 fallback/migration.ts | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/fallback/migration.ts b/fallback/migration.ts
index b15a58e..04fcee3 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -58,12 +58,10 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
   // 兼容老版本数据中不存在textures的情况
   result.textures ??= [];
   result.textures.forEach(textureOptions => {
-    textureOptions = {
-      ...textureOptions,
-      // @ts-expect-error
-      id: generateGUID(),
-      dataType: DataType.Texture,
-    };
+    //@ts-expect-error
+    textureOptions.id = generateGUID();
+    //@ts-expect-error
+    textureOptions.dataType = DataType.Texture;
   });
 
   if (result.textures.length < result.images.length) {

From 7e9d079c4155ab85752bc1c89d9d31462430c0d4 Mon Sep 17 00:00:00 2001
From: Sruim <934274351@qq.com>
Date: Thu, 18 Apr 2024 17:35:19 +0800
Subject: [PATCH 22/62] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20effect=20obje?=
 =?UTF-8?q?ct=20datatype=20=E7=B1=BB=E5=9E=8B=20(#31)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: 云垣 <suruimeng.srm@antgroup.com>
---
 fallback/migration.ts | 5 -----
 src/components.ts     | 2 +-
 src/image.ts          | 4 ++++
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/fallback/migration.ts b/fallback/migration.ts
index 04fcee3..41bc5b8 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -58,16 +58,13 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
   // 兼容老版本数据中不存在textures的情况
   result.textures ??= [];
   result.textures.forEach(textureOptions => {
-    //@ts-expect-error
     textureOptions.id = generateGUID();
-    //@ts-expect-error
     textureOptions.dataType = DataType.Texture;
   });
 
   if (result.textures.length < result.images.length) {
     for (let i = result.textures.length; i < result.images.length; i++) {
       result.textures.push({
-        //@ts-expect-error
         id: generateGUID(),
         dataType: DataType.Texture,
         source: i,
@@ -119,7 +116,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
           if (item.content.renderer.texture !== undefined) {
             const oldTextureId = item.content.renderer.texture;
 
-            //@ts-expect-error
             item.content.renderer.texture = { id: result.textures[oldTextureId].id };
           }
         }
@@ -128,7 +124,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
           if (item.content.trails.texture !== undefined) {
             const oldTextureId = item.content.trails.texture;
 
-            //@ts-expect-error
             item.content.trails.texture = { id: result.textures[oldTextureId].id };
           }
         }
diff --git a/src/components.ts b/src/components.ts
index 1713d6c..425419d 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -29,7 +29,7 @@ export interface DataPath {
 export interface EffectsObjectData {
   id: string,
   name?: string,
-  dataType: string,
+  dataType: DataType,
 }
 
 export interface ComponentData extends EffectsObjectData {
diff --git a/src/image.ts b/src/image.ts
index fae08b4..16ce165 100644
--- a/src/image.ts
+++ b/src/image.ts
@@ -1,6 +1,7 @@
 import type { RenderLevel } from './type';
 import type { StringTemplate } from './text';
 import type { BinaryPointer } from './binary';
+import type { DataType } from './components';
 
 export interface TextureFormatOptions {
   format?: GLenum,
@@ -9,6 +10,9 @@ export interface TextureFormatOptions {
 }
 
 export interface TextureConfigOptionsBase {
+  generateMipmap?: boolean,
+  id?: string,
+  dataType?: DataType.Texture,
   name?: string,
   wrapS?: GLenum,
   wrapT?: GLenum,

From 175130fc1919dfbca7039c95ca2c449d368e278e Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Thu, 18 Apr 2024 17:45:17 +0800
Subject: [PATCH 23/62] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20dataType=20?=
 =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/components.ts    | 2 +-
 src/vfx-item-data.ts | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 1713d6c..425419d 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -29,7 +29,7 @@ export interface DataPath {
 export interface EffectsObjectData {
   id: string,
   name?: string,
-  dataType: string,
+  dataType: DataType,
 }
 
 export interface ComponentData extends EffectsObjectData {
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index 716b519..e8ab391 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -1,4 +1,4 @@
-import type { ComponentData, DataPath, EffectsObjectData } from './components';
+import type { DataPath, EffectsObjectData } from './components';
 import type { ItemEndBehavior, ParentItemEndBehavior, BaseContent, TransformData } from './item/base-item';
 import type { ItemType, RenderLevel } from './type';
 

From 869d5814ae0241019d6d7573d32ac5861ec71cb9 Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Fri, 19 Apr 2024 16:16:14 +0800
Subject: [PATCH 24/62] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E6=BB=A4?=
 =?UTF-8?q?=E9=95=9C=E5=85=83=E7=B4=A0=E7=9B=B8=E5=85=B3=E7=B1=BB=E5=9E=8B?=
 =?UTF-8?q?=E5=92=8C=20fallback=20=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 fallback/filter.ts                |  33 -------
 fallback/index.ts                 |  25 +-----
 fallback/migration.ts             |  16 ++++
 fallback/particle.ts              |  29 +-----
 src/index.ts                      |   1 -
 src/item.ts                       |   2 -
 src/item/base-item.ts             |   7 +-
 src/item/filter-item.ts           | 137 -----------------------------
 src/item/particle-item.ts         |  11 +--
 src/scene.ts                      |   6 +-
 src/type.ts                       |   4 -
 test/cases/particle/base.test.mjs |  63 +------------
 test/cases/sprite/filter.test.mjs | 141 ++++++------------------------
 13 files changed, 55 insertions(+), 420 deletions(-)
 delete mode 100644 fallback/filter.ts
 delete mode 100644 src/item/filter-item.ts

diff --git a/fallback/filter.ts b/fallback/filter.ts
deleted file mode 100644
index dee0995..0000000
--- a/fallback/filter.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { ensureFixedNumber, ensureFixedVec3, forEach } from './utils';
-import type { FilterParams } from '../src/item/filter-item';
-
-const convertParams = [
-  'strength',
-  'bloomAddon',
-  'colorAddon',
-  'period',
-  'waveMovement',
-  'colorThreshold',
-  'xOpacity',
-  'yOpacity',
-  'feather',
-];
-const pathParams = [
-  'path', 'position',
-];
-
-export function getStandardFilterContent (filter: any): FilterParams {
-  const ret: Record<string, any> = {};
-
-  forEach(filter, function (val, key) {
-    if (convertParams.includes(key)) {
-      ret[key] = ensureFixedNumber(val);
-    } else if (pathParams.includes(key)) {
-      ret[key] = ensureFixedVec3(val);
-    } else {
-      ret[key] = val;
-    }
-  });
-
-  return ret as FilterParams;
-}
diff --git a/fallback/index.ts b/fallback/index.ts
index b471e95..383ec1f 100644
--- a/fallback/index.ts
+++ b/fallback/index.ts
@@ -1,16 +1,6 @@
 import type {
-  BaseItem,
-  BaseItemTransform,
-  Composition,
-  CompressedImage,
-  Image,
-  JSONScene,
-  ParticleItem,
-  RenderLevel,
-  SpriteItem,
-  TemplateImage,
-  FilterItem,
-  JSONSceneLegacy,
+  BaseItem, BaseItemTransform, Composition, CompressedImage, Image, JSONScene, ParticleItem,
+  RenderLevel, SpriteItem, TemplateImage, JSONSceneLegacy, Item,
 } from '../src';
 import { CAMERA_CLIP_MODE_NORMAL, ItemEndBehavior, ItemType } from '../src';
 import { getStandardParticleContent } from './particle';
@@ -18,7 +8,6 @@ import { getStandardNullContent, getStandardSpriteContent } from './sprite';
 import { getStandardInteractContent } from './interact';
 import { arrAdd, quatFromXYZRotation, rotationZYXFromQuat } from './utils';
 import { getStandardCameraContent } from './camera';
-import { getStandardFilterContent } from './filter';
 import { version21Migration, version22Migration, version30Migration } from './migration';
 
 export * from './utils';
@@ -166,7 +155,7 @@ const tempQuat = [0, 0, 0, 1];
 
 const stdAnchor = 0.5;
 
-export function getStandardItem (item: any, opt: { plugins?: string[], requires?: string[] } = {}): SpriteItem | ParticleItem | BaseItem | FilterItem {
+export function getStandardItem (item: any, opt: { plugins?: string[], requires?: string[] } = {}): SpriteItem | ParticleItem | BaseItem {
   let type: ItemType | string = ItemType.base;
   let transform: BaseItemTransform;
   let originContent;
@@ -190,14 +179,6 @@ export function getStandardItem (item: any, opt: { plugins?: string[], requires?
       duration = item.duration;
     }
     transform = item.transform || getTransform(originContent.transform);
-    if (type === ItemType.filter) {
-      if (currentVersion < '1.1') {
-        currentVersion = '1.1';
-      }
-      content = getStandardSpriteContent(originContent, transform);
-      // @ts-expect-error
-      content.filter = getStandardFilterContent(originContent.filter);
-    }
   } else if (item.particle) {
     type = ItemType.particle;
     originContent = item.particle;
diff --git a/fallback/migration.ts b/fallback/migration.ts
index 41bc5b8..a14a875 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -80,6 +80,22 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
       composition.endBehavior = END_BEHAVIOR_FREEZE;
     }
 
+    // 过滤掉滤镜元素
+    composition.items = composition.items.filter(item => item.type !== '8' as ItemType);
+
+    // 过滤掉粒子滤镜(扭曲)
+    composition.items.forEach(item => {
+      if (item.type === ItemType.particle) {
+        // @ts-expect-error
+        const filterData = item.content['filter'];
+
+        if (filterData) {
+          // @ts-expect-error
+          delete item.content['filter'];
+        }
+      }
+    });
+
     const itemGuidMap: Record<string, string> = {};
 
     for (const item of composition.items) {
diff --git a/fallback/particle.ts b/fallback/particle.ts
index 5bf324e..1c4da3b 100644
--- a/fallback/particle.ts
+++ b/fallback/particle.ts
@@ -1,22 +1,8 @@
-import type {
-  ParticleContent,
-  ParticleShape,
-  ParticleShapeSphere,
-  ColorOverLifetime,
-  DistortionFilterParams,
-} from '../src';
+import type { ParticleContent, ParticleShape, ParticleShapeSphere, ColorOverLifetime } from '../src';
 import { ShapeType } from '../src';
 import {
-  deleteEmptyValue,
-  ensureColorExpression,
-  ensureFixedNumber,
-  ensureFixedNumberWithRandom,
-  ensureFixedVec3,
-  ensureNumberExpression,
-  getGradientColor,
-  objectValueToNumber,
-  forEach,
-  ensureValueGetter,
+  deleteEmptyValue, ensureColorExpression, ensureFixedNumber, ensureFixedNumberWithRandom,
+  ensureFixedVec3, ensureNumberExpression, getGradientColor, objectValueToNumber,
 } from './utils';
 
 export function getStandardParticleContent (particle: any): ParticleContent {
@@ -83,15 +69,6 @@ export function getStandardParticleContent (particle: any): ParticleContent {
     ret.options.startRotationY = ensureNumberExpression(options.startRotationY);
   }
 
-  if (particle.filter) {
-    const filter = {} as DistortionFilterParams;
-
-    forEach(particle.filter, function (val, key) {
-      // @ts-expect-error
-      filter[key] = ensureValueGetter(val);
-    });
-    ret.filter = filter;
-  }
   if (transform && transform.path) {
     ret.emitterTransform = {
       path: ensureFixedVec3(transform.path),
diff --git a/src/index.ts b/src/index.ts
index 4c798fb..b62e98f 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -16,7 +16,6 @@ export * from './item/particle-shape';
 export * from './item/plugin-item';
 export * from './item/sprite-item';
 export * from './item/spine-item';
-export * from './item/filter-item';
 export * from './item/effect-item';
 export * from './item/text-item';
 export * from './item/model';
diff --git a/src/item.ts b/src/item.ts
index a38c535..c5cf4c0 100644
--- a/src/item.ts
+++ b/src/item.ts
@@ -5,7 +5,6 @@ import type { PluginItem } from './item/plugin-item';
 import type { ParticleItem } from './item/particle-item';
 import type { InteractItem } from './item/interact-item';
 import type { ModelCameraItem, ModelLightItem, ModelMeshItem, ModelSkyboxItem, ModelTreeItem } from './item/model';
-import type { FilterItem } from './item/filter-item';
 import type { CameraItem } from './item/camera-item';
 import type { CompositionItem } from './item/composition-item';
 import type { TextItem } from './item/text-item';
@@ -20,7 +19,6 @@ export type Item =
   | NullItem
   | PluginItem
   | InteractItem
-  | FilterItem
   | CameraItem
   | TextItem
   | ModelMeshItem<'json'>
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index c004b37..efef67b 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -1,9 +1,5 @@
-import type { FilterContent } from './filter-item';
 import {
-  END_BEHAVIOR_DESTROY,
-  END_BEHAVIOR_DESTROY_CHILDREN,
-  END_BEHAVIOR_FREEZE,
-  END_BEHAVIOR_RESTART,
+  END_BEHAVIOR_DESTROY, END_BEHAVIOR_DESTROY_CHILDREN, END_BEHAVIOR_FREEZE, END_BEHAVIOR_RESTART,
 } from '../constants';
 import type { vec3, vec4 } from '../number-expression';
 import type { ItemType, RenderLevel } from '../type';
@@ -145,7 +141,6 @@ export type BaseContent =
   | PluginContent
   | CompositionContent
   | CameraContent
-  | FilterContent
   | TextContent
   | any
   ;
diff --git a/src/item/filter-item.ts b/src/item/filter-item.ts
deleted file mode 100644
index 5501abf..0000000
--- a/src/item/filter-item.ts
+++ /dev/null
@@ -1,137 +0,0 @@
-import type {
-  BaseItem, ColorOverLifetime, FixedNumberExpression, FixedVec3Expression, FunctionExpression,
-  ItemEndBehavior, ItemType, MaskMode, NumberExpression, RenderMode, RotationOverLifetime,
-  ShapeGeometry, SideMode, SizeOverLifetime, SpriteContentOptions, vec2, vec3,
-} from '../index';
-
-export interface FilterItem extends BaseItem {
-  type: ItemType.filter,
-  content: FilterContent,
-  endBehavior: ItemEndBehavior,
-}
-
-export type FilterParams =
-  | NoneFilterParams
-  | GaussianFilterParams
-  | BloomFilterPrams
-  | DelayFilterPrams
-  | DistortionFilterParams
-  | CameraMoveFilterParams
-  | AlphaMaskFilterParams
-  | AlphaFrameFilterParams
-  ;
-
-export interface FilterContent {
-  options: SpriteContentOptions,
-
-  filter: FilterParams,
-
-  renderer?: FilterContentRenderer,
-
-  colorOverLifetime?: ColorOverLifetime,
-  /**
-   * 图层元素大小变化属性
-   */
-  sizeOverLifetime?: SizeOverLifetime,
-  /**
-   * 图层元素旋转变化属性
-   */
-  rotationOverLifetime?: RotationOverLifetime,
-  /**
-   * 图层元素位置变化属性
-   */
-  positionOverLifetime?: FilterPositionOverLifetime,
-}
-
-export interface FilterPositionOverLifetime {
-  path: FixedVec3Expression,
-}
-
-export interface BaseFilterParams {
-  name: string,
-  /**
-   * 边缘透明度
-   * @default 1
-   */
-  feather?: FunctionExpression,
-}
-
-export interface NoneFilterParams extends BaseFilterParams {
-  name: 'none',
-}
-
-// 高斯模糊
-export interface GaussianFilterParams extends BaseFilterParams {
-  name: 'gaussian',
-  radius: number,
-}
-
-// 动作延迟
-export interface DelayFilterPrams extends BaseFilterParams {
-  name: 'delay',
-}
-
-// 发光
-export interface BloomFilterPrams extends BaseFilterParams {
-  name: 'bloom',
-  colorThreshold?: vec3,
-  bloomAddon?: FixedNumberExpression,
-  colorAddon?: FixedNumberExpression,
-  radius?: number,
-}
-
-// 扭曲
-export interface DistortionFilterParams extends BaseFilterParams {
-  name: 'distortion',
-  center?: vec2,
-  direction?: vec2,
-  period: NumberExpression,
-  waveMovement: NumberExpression,
-  strength: NumberExpression,
-}
-
-// 移动镜头
-export interface CameraMoveFilterParams extends BaseFilterParams {
-  name: 'cameraMove',
-  position?: FixedVec3Expression,
-}
-
-// 渐变滤镜
-export interface AlphaMaskFilterParams extends BaseFilterParams {
-  name: 'alphaMask',
-  xOpacity: FixedNumberExpression,
-  yOpacity: FixedNumberExpression,
-}
-
-// 透明视频
-export interface AlphaFrameFilterParams extends BaseFilterParams {
-  name: 'alphaFrame',
-  colorRange?: [x: number, y: number],
-  alphaRange?: [x: number, y: number],
-}
-
-export const BloomFilterThresholdAvgColor = 0;
-
-export interface FilterContentRenderer {
-  /**
-   * 渲染模式
-   */
-  renderMode?: RenderMode,
-  /**
-   * 锚点信息
-   */
-  anchor?: vec2,
-  /**
-   * 单双面模式
-   */
-  side?: SideMode,
-  /**
-   * 蒙版模式
-   * @default none
-   */
-  maskMode?: MaskMode,
-  /**
-   * 形状
-   */
-  shape?: number | ShapeGeometry,
-}
diff --git a/src/item/particle-item.ts b/src/item/particle-item.ts
index 4606985..7a24c2c 100644
--- a/src/item/particle-item.ts
+++ b/src/item/particle-item.ts
@@ -2,16 +2,11 @@ import type {
   ItemType, RendererOptions, TextureSheetAnimation, BlendingMode, SplitParameter,
 } from '../type';
 import type {
-  FixedNumberExpression,
-  NumberExpression,
-  GradientColor,
-  vec3, FixedVec3Expression,
-  ColorExpression,
-  FunctionExpression,
+  FixedNumberExpression, NumberExpression, GradientColor, vec3, FixedVec3Expression,
+  ColorExpression, FunctionExpression,
 } from '../number-expression';
 import type { BaseItem, ItemEndBehavior } from './base-item';
 import type { ParticleShape } from './particle-shape';
-import type { DistortionFilterParams } from './filter-item';
 import type { ComponentData } from '../components';
 
 /**
@@ -357,7 +352,6 @@ export interface ParticleContent {
      */
     radius?: number,
   },
-  filter?: DistortionFilterParams,
 }
 
 /**
@@ -431,7 +425,6 @@ export interface ParticleSystemData extends ComponentData {
      */
     radius?: number,
   },
-  filter?: DistortionFilterParams,
 }
 
 /**
diff --git a/src/scene.ts b/src/scene.ts
index b8f6327..ab20db7 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -107,7 +107,7 @@ export interface JSONScene {
   /**
    * JSON 版本
    *
-   * 3.0 EC 改造
+   * 3.0 EC 改造、移除滤镜元素
    */
   version: string,
   /**
@@ -150,10 +150,6 @@ export interface JSONScene {
    * 'model@1.0'
    */
   plugins: string[],
-  /**
-   * 保留字段
-   */
-  requires: SceneRequire[],
   /**
    * 字体资源
    * 数据模板下掉可以不要 FontBase[]
diff --git a/src/type.ts b/src/type.ts
index 4c5d10d..4fb425b 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -541,10 +541,6 @@ export enum ItemType {
    * 预合成元素
    */
   composition = '7',
-  /**
-   * 滤镜图层
-   */
-  filter = '8',
   /**
    * Spine 元素
    */
diff --git a/test/cases/particle/base.test.mjs b/test/cases/particle/base.test.mjs
index d331e04..0ce26f0 100644
--- a/test/cases/particle/base.test.mjs
+++ b/test/cases/particle/base.test.mjs
@@ -1,15 +1,7 @@
 import { getStandardItem, getStandardJSON } from '../../../dist/fallback.mjs';
 import {
-  ItemType,
-  ValueType,
-  END_BEHAVIOR_FREEZE,
-  ShapeType,
-  RenderMode,
-  ParticleOrigin,
-  BlendingMode,
-  MaskMode,
-  SideMode,
-  ParticleInteractionBehavior,
+  ItemType, ValueType, END_BEHAVIOR_FREEZE, ShapeType, RenderMode, ParticleOrigin,
+  BlendingMode, MaskMode, SideMode, ParticleInteractionBehavior,
 } from '../../../dist/index.mjs';
 
 const { expect } = chai;
@@ -1069,55 +1061,4 @@ describe('particle base', () => {
     expect(tsa2.animationDuration[0]).to.eql(ValueType.CONSTANT, 'animationDelay.type');
     expect(tsa2.animationDuration[1]).to.eql(2, 'animationDelay.value');
   });
-
-  it('particle filter content', () => {
-    const item = {
-      'name': 'distortion',
-      'delay': 0,
-      'id': 2,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 5,
-          'startSize': 10,
-          'sizeAspect': 21.818181818181817,
-          'startSpeed': 0,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 1,
-          'gravityModifier': 1,
-          'endBehavior': 4,
-          'start3DSize': true,
-          'startSizeX': 6,
-          'startSizeY': 9,
-          'startDelay': 0,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'filter': {
-          'name': 'distortion',
-          'center': [0.5, 0],
-          'direction': [0.2, 1],
-          'strength': 0.008,
-          'period': 6,
-          'waveMovement': ['lines', [[0, 0], [1, 6]]],
-        },
-        'renderer': { 'texture': 0, 'order': 1 },
-        'transform': { 'position': [1.723219445898673, 3.100635886398397, 0] },
-        'rotationOverLifetime': { 'asRotation': true, 'angularVelocity': 5 },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.content.filter).to.exist;
-
-    expect(neo.content.filter).to.contains({
-      'name': 'distortion',
-      'strength': 0.008,
-      'period': 6,
-    });
-    expect(neo.content.filter.direction).to.deep.equals([0.2, 1]);
-    expect(neo.content.filter.center).to.deep.equals([0.5, 0]);
-    expect(neo.content.filter.waveMovement).to.deep.equals([ValueType.LINE, [[0, 0], [1, 6]]]);
-  });
 });
diff --git a/test/cases/sprite/filter.test.mjs b/test/cases/sprite/filter.test.mjs
index a7e6fae..7a5b812 100644
--- a/test/cases/sprite/filter.test.mjs
+++ b/test/cases/sprite/filter.test.mjs
@@ -1,126 +1,39 @@
+/**
+ * 主要用于测试 filter 字段被过滤掉
+ */
 import { ItemType, ValueType } from '../../../dist/index.mjs';
-import { getStandardItem, deleteEmptyValue, forEach } from '../../../dist/fallback.mjs';
+import { getStandardJSON, deleteEmptyValue, forEach } from '../../../dist/fallback.mjs';
 
 const { expect } = chai;
 
-describe('filter base', () => {
-  it('filter static options', () => {
-    const item = {
-      type: '8',
-      delay: 0.5,
-      id: '3',
-      parentId: '5',
-      content: {
-        options: {
-          'startSize': 1.2,
-          'sizeAspect': 0.5,
-          'duration': 2,
-          'renderLevel': 'S',
-        },
-        renderer: {
-          renderMode: 1,
-          shape: 0,
-          maskMode: 1,
-          side: 2,
-        },
-        transform: {
-          rotation: [0, 90, 0],
-          position: [0, 2, 1],
-          path: [1, 0, 0],
-        },
-        sizeOverLifetime: {
-          size: ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-        },
-        filter: {
-          name: 'gaussian',
-          radius: 30,
-        },
-      },
-    };
-    const neo = getStandardItem(item);
+describe('filter', () => {
+  it('filter 元素被过滤掉', () => {
+    const json = '{"images":[{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*Gf_HTrsSzDsAAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*38e1QrhwaiQAAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"},{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*8e9dTrz9YHoAAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*fmxKRbvqN94AAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"}],"spines":[],"version":"1.5","shapes":[{"g":{"p":[[0.523076923076923,-0.06282055194561309,1.1128206693209133,-0.33461538461538476,-0.0666668231670674,0.20897428072415858],[-0.9153846153846154,0.11666658841646638,-0.8557690987220177,-0.10972656126267621,-0.9181889955814069,0.14354689803562992],[-0.9897437462439904,1.0064102466289815,-0.9897437462439904,0.5556653317332156,-0.1737037249563922,1.0064102466289815],[1,1,0.6194916379724837,1,1,0.09353119090398587],[0.9948716383713943,-0.7012822077824519,0.9948716383713943,-0.22468717446296677,0.16157083885709955,-0.7012822077824519],[0.6217947152944712,-0.7153846153846153,0.9987177922175481,-0.6858975923978363,0.10765047236582011,-0.7352564885066104]],"s":[[0,0.0625,0.125,0.1875,0.25,0.375,0.5,0.75,0.8125,0.875,1],[0,0.5,1],[0,1],[0,1],[0,0.25,0.5,1],[0,0.0625,0.125,0.25,0.375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,0.96875,1]]}}],"plugins":[],"type":"mars","compositions":[{"id":"28","name":"欢呼粒子","duration":3,"startTime":0,"endBehavior":2,"previewSize":[750,750],"items":[{"id":"557","name":"face","duration":2,"type":"2","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"Cone","radius":0.6,"arc":360,"arcMode":0,"angle":33,"type":2,"alignSpeedDirection":false,"turbulenceX":[0,0],"turbulenceY":[0,0],"turbulenceZ":[0,0]},"splits":[[0.5400390625,0.0009765625,0.3125,0.078125,0]],"options":{"startColor":[8,[1,1,1,1]],"maxCount":100,"startLifetime":[4,[1,1.4]],"startDelay":[0,0],"startSize":[4,[0.2,0.4]],"sizeAspect":[0,1],"start3DSize":false,"startRotationZ":[4,[0,360]]},"renderer":{"renderMode":1,"texture":0},"emission":{"rateOverTime":[0,0],"burstOffsets":[{"index":0,"x":0,"y":0,"z":0},{"index":1,"x":0,"y":0,"z":0},{"index":2,"x":0,"y":0,"z":0}],"bursts":[{"time":0,"count":22,"cycles":1,"interval":0},{"time":0.5,"count":22,"cycles":1,"interval":0},{"time":1,"count":22,"cycles":1,"interval":0}]},"positionOverLifetime":{"asMovement":false,"speedOverLifetime":[6,[[0,1,0,0],[0.2169,0.8442,-1.3,-1.22],[0.4336,0.1332,-0.4662,-0.5119],[1,0,0,0]]],"linearY":[0,0],"linearX":[0,0],"linearZ":[0,0],"startSpeed":[4,[9,16]],"gravity":[0,-7,0],"gravityOverLifetime":[0,1]},"sizeOverLifetime":{"size":[5,[[0,0.8],[0.2547,1.4018],[1,1.6]]]},"rotationOverLifetime":{"asRotation":false,"z":[4,[260,400]]},"colorOverLifetime":{"opacity":[5,[[0,0],[0.1769,1],[0.8198,1],[1,0]]]},"textureSheetAnimation":{"col":4,"animate":false,"total":0,"row":1}},"transform":{"position":[-0.06231099026667142,-4.154147151879992,0],"rotation":[89.99999999999999,0,0],"scale":[1,1,1]}},{"id":"558","name":"鱼卡","duration":2,"type":"1","parentId":"561","visible":true,"endBehavior":5,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1,"texture":1},"positionOverLifetime":{},"splits":[[0.5009765625,0.0009765625,0.267578125,0.37890625,1],[0.0009765625,0.5009765625,0.267578125,0.37890625,0],[0.5009765625,0.2705078125,0.267578125,0.37890625,1],[0.2705078125,0.5400390625,0.267578125,0.37890625,0]]},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[3.117122635624778,4.41402767380443,1]}},{"id":"559","name":"敬业福卡面","duration":2,"type":"1","parentId":"561","visible":true,"endBehavior":5,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1,"side":1032,"shape":0,"texture":0,"maskMode":0},"positionOverLifetime":{},"splits":[[0.0009765625,0.0009765625,0.537109375,0.751953125,0]]},"transform":{"position":[-0.07,0,0],"rotation":[0,0,0],"scale":[3.17,4.438,1]}},{"id":"560","name":"福字牌-1","duration":2,"type":"1","parentId":"561","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1,"texture":1,"maskMode":0},"positionOverLifetime":{},"splits":[[0.0009765625,0.0009765625,0.498046875,0.498046875,0]]},"transform":{"position":[0.02,-0.8255811824343184,-0.0000023182466755145015],"rotation":[0,0,0],"scale":[1.4,1.4,1]}},{"id":"561","name":"牌子节点","duration":4,"type":"3","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"positionOverLifetime":{"asMovement":true,"linearY":[6,[[0.75,0,-0.065,-0.065],[0.8,1,0,0],[0.999,-10,0.042,0.042]]]},"sizeOverLifetime":{"size":[6,[[0.05,0.002,-0.005,-0.005],[0.092,0.325,11.542,11.542],[0.189,1.11,0,0],[0.329,0.98,-0.082,-0.082],[0.5,1.002,-0.014,-0.014],[0.8,1.002,-0.013,-0.013],[0.878,0.415,-6.729,-6.729],[0.999,0.002,0.001,0.001]]]},"rotationOverLifetime":{"asRotation":true,"separateAxes":true,"y":[6,[[0.05,270,0.022,0.022],[0.12,86.979,-4.195,-4.195],[0.3,4.342,-0.029,-0.029]]]}},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[1,1,1]}},{"id":"562","name":"filter_447","duration":5,"type":"8","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{},"filter":{"name":"bloom","radius":32,"colorThreshold":[220,220,220],"bloomAddon":[0,0.6],"colorAddon":[0,0.7]},"renderer":{"renderMode":0},"positionOverLifetime":{"path":[2,[0,0,0]]}},"transform":{"position":[0,0,-0.000002098084138424383],"rotation":[0,0,0],"scale":[9,9,1]}}],"camera":{"fov":60,"far":20,"near":2,"position":[0,0,8],"rotation":[0,0,0],"clipMode":0}}],"requires":["filter"],"compositionId":"28","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
+    const result = getStandardJSON(JSON.parse(json));
+    const filterItems = result.items.filter(item => item.type === '8');
 
-    expect(neo).contains({
-      type: ItemType.filter,
-      delay: 0.5,
-      duration: 2,
-      parentId: '5',
-      id: '3',
-      renderLevel: 'S',
-    });
-    expect(neo.transform).to.deep.equals({
-      scale: [1.2, 2.4, 1],
-      rotation: [0, 90, 0],
-      position: [0, 2, 1],
-    });
-    expect(neo.content.positionOverLifetime).to.deep
-      .equals({ path: [ValueType.CONSTANT_VEC3, [1, 0, 0]] });
-    expect(neo.content.renderer).to.deep.equals({
-      renderMode: 1,
-      shape: 0,
-      maskMode: 1,
-      side: 2,
-    });
-    expect(deleteEmptyValue(neo.content.sizeOverLifetime)).to.deep.equals({
-      size: [ValueType.LINE, [[0, 1], [0.5, 0], [1, 1]]],
-    });
-    expect(neo.content.filter).to.deep.equals({ name: 'gaussian', radius: 30 });
+    expect(filterItems.length).eq(0);
   });
-  it('convert filter content', () => {
-    const item = {
-      'name': 'filter_1',
-      'delay': 0,
-      'id': 2,
-      'type': '8',
-      'content': {
-        'options': { 'duration': 5, 'startSize': 6, 'sizeAspect': 1, 'renderLevel': 'B+' },
-        'renderer': { 'renderMode': 0 },
-        'filter': {
-          'name': 'bloom',
-          'radius': 20,
-          'colorThreshold': ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-          'bloomAddon': ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-          'colorAddon': ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-          feather: ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-        },
-      },
-      'duration': 5,
-    };
-    const neo = getStandardItem(item);
 
-    expect(neo.content.filter).to.exist;
-    const result = {
-      name: 'bloom',
-      radius: 20,
-      colorThreshold: [ValueType.LINE, [[0, 1], [0.5, 0], [1, 1]]],
-      bloomAddon: [ValueType.LINE, [[0, 1], [0.5, 0], [1, 1]]],
-      colorAddon: [ValueType.LINE, [[0, 1], [0.5, 0], [1, 1]]],
-      feather: [ValueType.LINE, [[0, 1], [0.5, 0], [1, 1]]],
-    };
+  it('过滤逻辑不影响不包含 filter 元素的合成', () => {
+    const json = '{"compositionId":3,"requires":[],"compositions":[{"name":"彩色纸片_满屏落下","id":3,"duration":9,"endBehavior":1,"camera":{"fov":60,"far":20,"near":0.1,"position":[0,0,8],"clipMode":0,"z":8},"items":[{"name":"彩色纸片","delay":0,"id":11,"ro":0.1,"particle":{"options":{"startLifetime":["random",[2,3]],"startSize":["random",[0.15,0.2]],"sizeAspect":1.040983606557377,"startSpeed":["random",[1,3]],"startColor":["colors",["rgba(245, 166 , 35 , 1)","rgba(80, 227 , 194 , 1)","rgba(89, 58 , 245 , 1)","rgba(54, 16 , 242 , 1)","rgba(208, 2 , 27 , 1)"]],"duration":9,"maxCount":100,"gravityModifier":1,"gravity":[0,-1,0],"looping":false,"start3DRotation":true,"startRotationZ":4,"startRotationY":3,"startRotationX":4,"renderLevel":"B+"},"emission":{"rateOverTime":["lines",[[0,55],[0.1974,55],[0.3105,0],[1,0]]],"burstOffsets":[{"index":0,"x":0,"y":0,"z":0}],"bursts":[]},"shape":{"shape":"Edge","radius":0.8,"arc":360,"arcMode":0,"angle":32,"width":10},"renderer":{"texture":0},"textureSheetAnimation":{"col":2,"row":2},"transform":{"rotation":[0,0,180],"position":[0,5,0]},"colorOverLifetime":{"opacity":["curve",[[0,0,0,4.3235],[0.1569,0.9994,0,0],[0.72,0.82,-0.98,-1.1],[1,0,-5,7]]]},"rotationOverLifetime":{"angularVelocity":["random",[300,500]]},"splits":[[0.00390625,0.00390625,0.49609375,0.4765625,0]]}}],"meta":{"previewSize":[0,0]}}],"gltf":[],"images":["https://gw.alipayobjects.com/zos/gltf-asset/mars-cli/MNJVBYCSYDWN/760117553-3d179.png"],"version":"0.1.47","shapes":[],"plugins":[],"type":"mars","_imgs":{"3":[0]},"imageTags":["B+"]}';
+    const result = getStandardJSON(JSON.parse(json));
+    const filterItems = result.items.filter(item => item.type === '8');
 
-    forEach(neo.content.filter, (val, name) => {
-      expect(val).to.deep.equals(result[name], name);
+    expect(filterItems.length).eq(0);
+  });
+
+  it('particle filter 被过滤掉', () => {
+    const json = '{"images":[{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*K8wjTLPLe70AAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*ZJiYRqCa5bwAAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"},{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*0uSnT5vW9XgAAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*3WtFTLzrybAAAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"}],"spines":[],"version":"1.5","shapes":[],"plugins":[],"type":"mars","compositions":[{"id":"25","name":"distortion","duration":5,"startTime":0,"endBehavior":0,"previewSize":[0,0],"items":[{"id":"36","name":"distortion","duration":5,"type":"2","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"None","radius":1,"arc":360,"arcMode":0,"type":0},"options":{"startColor":[8,[1,1,1,1]],"maxCount":1,"startLifetime":[0,5],"startDelay":[0,0],"start3DSize":true,"startSizeX":[0,6],"startSizeY":[0,9]},"renderer":{"texture":0,"order":1},"emission":{"rateOverTime":[0,5]},"positionOverLifetime":{"startSpeed":[0,0],"gravityOverLifetime":[0,1]},"rotationOverLifetime":{"asRotation":true,"z":[0,5]},"filter":{"name":"distortion","center":[0.5,0],"direction":[0.2,1],"strength":[0,0.008],"period":[0,6],"waveMovement":[5,[[0,0],[1,6]]]}},"transform":{"position":[1.723219445898673,3.100635886398397,0],"rotation":[0,0,0],"scale":[1,1,1]}},{"id":"37","name":"virus","duration":5,"type":"1","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"texture":1,"order":2},"positionOverLifetime":{},"splits":[[0.001953125,0.001953125,0.673828125,0.619140625,0]]},"transform":{"position":[-0.14902922818470277,-0.1669679315773056,0],"rotation":[0,0,0],"scale":[3.5,3.2159420289855074,1]}}],"camera":{"fov":60,"far":20,"near":0.1,"position":[0,0,8],"rotation":[0,0,0],"clipMode":0}}],"requires":[],"compositionId":"25","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
+    const result = getStandardJSON(JSON.parse(json));
+    const filterItems = result.items.filter(item => {
+      if (item.type === '2' && item.content.filter) {
+        return true;
+      }
+
+      return false;
     });
 
+    expect(filterItems.length).eq(0);
   });
-  it('convert path filter content', () => {
-    const item = {
-      'name': 'filter_4',
-      'delay': 0,
-      'id': 5,
-      'type': '8',
-      'content': {
-        'options': { 'duration': 5, 'startSize': 6, 'sizeAspect': 1, 'renderLevel': 'B+' },
-        'renderer': { 'renderMode': 0 },
-        'filter': {
-          'name': 'cameraMove',
-          'position': ['path', [[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, 0], [1, 0, 0]]]],
-        },
-      },
-      'duration': 5,
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.content.filter.position).to.eql([ValueType.LINEAR_PATH, [[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, 0], [1, 0, 0]]]]);
-  }
-  );
 });

From 9764f3fc525d1502a1791cef05b5c826aab86c92 Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Mon, 22 Apr 2024 15:20:13 +0800
Subject: [PATCH 25/62] =?UTF-8?q?chore:=20=E4=BC=98=E5=8C=96=E6=B5=8B?=
 =?UTF-8?q?=E8=AF=95=E6=95=B0=E6=8D=AE?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 test/cases/sprite/filter.test.mjs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/cases/sprite/filter.test.mjs b/test/cases/sprite/filter.test.mjs
index 7a5b812..251c921 100644
--- a/test/cases/sprite/filter.test.mjs
+++ b/test/cases/sprite/filter.test.mjs
@@ -8,7 +8,7 @@ const { expect } = chai;
 
 describe('filter', () => {
   it('filter 元素被过滤掉', () => {
-    const json = '{"images":[{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*Gf_HTrsSzDsAAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*38e1QrhwaiQAAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"},{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*8e9dTrz9YHoAAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*fmxKRbvqN94AAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"}],"spines":[],"version":"1.5","shapes":[{"g":{"p":[[0.523076923076923,-0.06282055194561309,1.1128206693209133,-0.33461538461538476,-0.0666668231670674,0.20897428072415858],[-0.9153846153846154,0.11666658841646638,-0.8557690987220177,-0.10972656126267621,-0.9181889955814069,0.14354689803562992],[-0.9897437462439904,1.0064102466289815,-0.9897437462439904,0.5556653317332156,-0.1737037249563922,1.0064102466289815],[1,1,0.6194916379724837,1,1,0.09353119090398587],[0.9948716383713943,-0.7012822077824519,0.9948716383713943,-0.22468717446296677,0.16157083885709955,-0.7012822077824519],[0.6217947152944712,-0.7153846153846153,0.9987177922175481,-0.6858975923978363,0.10765047236582011,-0.7352564885066104]],"s":[[0,0.0625,0.125,0.1875,0.25,0.375,0.5,0.75,0.8125,0.875,1],[0,0.5,1],[0,1],[0,1],[0,0.25,0.5,1],[0,0.0625,0.125,0.25,0.375,0.5,0.5625,0.625,0.6875,0.75,0.8125,0.875,0.9375,0.96875,1]]}}],"plugins":[],"type":"mars","compositions":[{"id":"28","name":"欢呼粒子","duration":3,"startTime":0,"endBehavior":2,"previewSize":[750,750],"items":[{"id":"557","name":"face","duration":2,"type":"2","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"Cone","radius":0.6,"arc":360,"arcMode":0,"angle":33,"type":2,"alignSpeedDirection":false,"turbulenceX":[0,0],"turbulenceY":[0,0],"turbulenceZ":[0,0]},"splits":[[0.5400390625,0.0009765625,0.3125,0.078125,0]],"options":{"startColor":[8,[1,1,1,1]],"maxCount":100,"startLifetime":[4,[1,1.4]],"startDelay":[0,0],"startSize":[4,[0.2,0.4]],"sizeAspect":[0,1],"start3DSize":false,"startRotationZ":[4,[0,360]]},"renderer":{"renderMode":1,"texture":0},"emission":{"rateOverTime":[0,0],"burstOffsets":[{"index":0,"x":0,"y":0,"z":0},{"index":1,"x":0,"y":0,"z":0},{"index":2,"x":0,"y":0,"z":0}],"bursts":[{"time":0,"count":22,"cycles":1,"interval":0},{"time":0.5,"count":22,"cycles":1,"interval":0},{"time":1,"count":22,"cycles":1,"interval":0}]},"positionOverLifetime":{"asMovement":false,"speedOverLifetime":[6,[[0,1,0,0],[0.2169,0.8442,-1.3,-1.22],[0.4336,0.1332,-0.4662,-0.5119],[1,0,0,0]]],"linearY":[0,0],"linearX":[0,0],"linearZ":[0,0],"startSpeed":[4,[9,16]],"gravity":[0,-7,0],"gravityOverLifetime":[0,1]},"sizeOverLifetime":{"size":[5,[[0,0.8],[0.2547,1.4018],[1,1.6]]]},"rotationOverLifetime":{"asRotation":false,"z":[4,[260,400]]},"colorOverLifetime":{"opacity":[5,[[0,0],[0.1769,1],[0.8198,1],[1,0]]]},"textureSheetAnimation":{"col":4,"animate":false,"total":0,"row":1}},"transform":{"position":[-0.06231099026667142,-4.154147151879992,0],"rotation":[89.99999999999999,0,0],"scale":[1,1,1]}},{"id":"558","name":"鱼卡","duration":2,"type":"1","parentId":"561","visible":true,"endBehavior":5,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1,"texture":1},"positionOverLifetime":{},"splits":[[0.5009765625,0.0009765625,0.267578125,0.37890625,1],[0.0009765625,0.5009765625,0.267578125,0.37890625,0],[0.5009765625,0.2705078125,0.267578125,0.37890625,1],[0.2705078125,0.5400390625,0.267578125,0.37890625,0]]},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[3.117122635624778,4.41402767380443,1]}},{"id":"559","name":"敬业福卡面","duration":2,"type":"1","parentId":"561","visible":true,"endBehavior":5,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1,"side":1032,"shape":0,"texture":0,"maskMode":0},"positionOverLifetime":{},"splits":[[0.0009765625,0.0009765625,0.537109375,0.751953125,0]]},"transform":{"position":[-0.07,0,0],"rotation":[0,0,0],"scale":[3.17,4.438,1]}},{"id":"560","name":"福字牌-1","duration":2,"type":"1","parentId":"561","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1,"texture":1,"maskMode":0},"positionOverLifetime":{},"splits":[[0.0009765625,0.0009765625,0.498046875,0.498046875,0]]},"transform":{"position":[0.02,-0.8255811824343184,-0.0000023182466755145015],"rotation":[0,0,0],"scale":[1.4,1.4,1]}},{"id":"561","name":"牌子节点","duration":4,"type":"3","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"positionOverLifetime":{"asMovement":true,"linearY":[6,[[0.75,0,-0.065,-0.065],[0.8,1,0,0],[0.999,-10,0.042,0.042]]]},"sizeOverLifetime":{"size":[6,[[0.05,0.002,-0.005,-0.005],[0.092,0.325,11.542,11.542],[0.189,1.11,0,0],[0.329,0.98,-0.082,-0.082],[0.5,1.002,-0.014,-0.014],[0.8,1.002,-0.013,-0.013],[0.878,0.415,-6.729,-6.729],[0.999,0.002,0.001,0.001]]]},"rotationOverLifetime":{"asRotation":true,"separateAxes":true,"y":[6,[[0.05,270,0.022,0.022],[0.12,86.979,-4.195,-4.195],[0.3,4.342,-0.029,-0.029]]]}},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[1,1,1]}},{"id":"562","name":"filter_447","duration":5,"type":"8","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{},"filter":{"name":"bloom","radius":32,"colorThreshold":[220,220,220],"bloomAddon":[0,0.6],"colorAddon":[0,0.7]},"renderer":{"renderMode":0},"positionOverLifetime":{"path":[2,[0,0,0]]}},"transform":{"position":[0,0,-0.000002098084138424383],"rotation":[0,0,0],"scale":[9,9,1]}}],"camera":{"fov":60,"far":20,"near":2,"position":[0,0,8],"rotation":[0,0,0],"clipMode":0}}],"requires":["filter"],"compositionId":"28","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
+    const json = '{"images":[],"version":"1.5","type":"mars","compositions":[{"id":"28","name":"欢呼粒子","duration":3,"startTime":0,"endBehavior":2,"previewSize":[750,750],"items":[{"id":"557","name":"face","duration":2,"type":"2","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"Cone","radius":0.6,"arc":360,"arcMode":0,"angle":33,"type":2,"alignSpeedDirection":false,"turbulenceX":[0,0],"turbulenceY":[0,0],"turbulenceZ":[0,0]},"splits":[[0.5400390625,0.0009765625,0.3125,0.078125,0]],"options":{"startColor":[8,[1,1,1,1]],"maxCount":100,"startLifetime":[4,[1,1.4]],"startDelay":[0,0],"startSize":[4,[0.2,0.4]],"sizeAspect":[0,1],"start3DSize":false,"startRotationZ":[4,[0,360]]},"renderer":{"renderMode":1,"texture":0},"emission":{"rateOverTime":[0,0],"burstOffsets":[{"index":0,"x":0,"y":0,"z":0},{"index":1,"x":0,"y":0,"z":0},{"index":2,"x":0,"y":0,"z":0}],"bursts":[{"time":0,"count":22,"cycles":1,"interval":0},{"time":0.5,"count":22,"cycles":1,"interval":0},{"time":1,"count":22,"cycles":1,"interval":0}]},"positionOverLifetime":{"asMovement":false,"speedOverLifetime":[6,[[0,1,0,0],[0.2169,0.8442,-1.3,-1.22],[0.4336,0.1332,-0.4662,-0.5119],[1,0,0,0]]],"linearY":[0,0],"linearX":[0,0],"linearZ":[0,0],"startSpeed":[4,[9,16]],"gravity":[0,-7,0],"gravityOverLifetime":[0,1]},"sizeOverLifetime":{"size":[5,[[0,0.8],[0.2547,1.4018],[1,1.6]]]},"rotationOverLifetime":{"asRotation":false,"z":[4,[260,400]]},"colorOverLifetime":{"opacity":[5,[[0,0],[0.1769,1],[0.8198,1],[1,0]]]},"textureSheetAnimation":{"col":4,"animate":false,"total":0,"row":1}}},{"id":"562","name":"filter_447","duration":5,"type":"8","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{},"filter":{"name":"bloom","radius":32,"colorThreshold":[220,220,220],"bloomAddon":[0,0.6],"colorAddon":[0,0.7]},"renderer":{"renderMode":0},"positionOverLifetime":{"path":[2,[0,0,0]]}},"transform":{"position":[0,0,-0.000002098084138424383],"rotation":[0,0,0],"scale":[9,9,1]}}]}],"compositionId":"28","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
     const result = getStandardJSON(JSON.parse(json));
     const filterItems = result.items.filter(item => item.type === '8');
 
@@ -24,7 +24,7 @@ describe('filter', () => {
   });
 
   it('particle filter 被过滤掉', () => {
-    const json = '{"images":[{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*K8wjTLPLe70AAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*ZJiYRqCa5bwAAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"},{"url":"https://mdn.alipayobjects.com/mars/afts/img/A*0uSnT5vW9XgAAAAAAAAAAAAADlB4AQ/original","webp":"https://mdn.alipayobjects.com/mars/afts/img/A*3WtFTLzrybAAAAAAAAAAAAAADlB4AQ/original","renderLevel":"B+"}],"spines":[],"version":"1.5","shapes":[],"plugins":[],"type":"mars","compositions":[{"id":"25","name":"distortion","duration":5,"startTime":0,"endBehavior":0,"previewSize":[0,0],"items":[{"id":"36","name":"distortion","duration":5,"type":"2","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"None","radius":1,"arc":360,"arcMode":0,"type":0},"options":{"startColor":[8,[1,1,1,1]],"maxCount":1,"startLifetime":[0,5],"startDelay":[0,0],"start3DSize":true,"startSizeX":[0,6],"startSizeY":[0,9]},"renderer":{"texture":0,"order":1},"emission":{"rateOverTime":[0,5]},"positionOverLifetime":{"startSpeed":[0,0],"gravityOverLifetime":[0,1]},"rotationOverLifetime":{"asRotation":true,"z":[0,5]},"filter":{"name":"distortion","center":[0.5,0],"direction":[0.2,1],"strength":[0,0.008],"period":[0,6],"waveMovement":[5,[[0,0],[1,6]]]}},"transform":{"position":[1.723219445898673,3.100635886398397,0],"rotation":[0,0,0],"scale":[1,1,1]}},{"id":"37","name":"virus","duration":5,"type":"1","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"texture":1,"order":2},"positionOverLifetime":{},"splits":[[0.001953125,0.001953125,0.673828125,0.619140625,0]]},"transform":{"position":[-0.14902922818470277,-0.1669679315773056,0],"rotation":[0,0,0],"scale":[3.5,3.2159420289855074,1]}}],"camera":{"fov":60,"far":20,"near":0.1,"position":[0,0,8],"rotation":[0,0,0],"clipMode":0}}],"requires":[],"compositionId":"25","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
+    const json = '{"images":[],"spines":[],"version":"1.5","shapes":[],"plugins":[],"type":"mars","compositions":[{"id":"25","name":"distortion","duration":5,"startTime":0,"endBehavior":0,"previewSize":[0,0],"items":[{"id":"36","name":"distortion","duration":5,"type":"2","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"None","radius":1,"arc":360,"arcMode":0,"type":0},"options":{"startColor":[8,[1,1,1,1]],"maxCount":1,"startLifetime":[0,5],"startDelay":[0,0],"start3DSize":true,"startSizeX":[0,6],"startSizeY":[0,9]},"renderer":{"texture":0,"order":1},"emission":{"rateOverTime":[0,5]},"positionOverLifetime":{"startSpeed":[0,0],"gravityOverLifetime":[0,1]},"rotationOverLifetime":{"asRotation":true,"z":[0,5]},"filter":{"name":"distortion","center":[0.5,0],"direction":[0.2,1],"strength":[0,0.008],"period":[0,6],"waveMovement":[5,[[0,0],[1,6]]]}},"transform":{"position":[1.723219445898673,3.100635886398397,0],"rotation":[0,0,0],"scale":[1,1,1]}},{"id":"37","name":"virus","duration":5,"type":"1","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"texture":1,"order":2},"positionOverLifetime":{},"splits":[[0.001953125,0.001953125,0.673828125,0.619140625,0]]},"transform":{"position":[-0.14902922818470277,-0.1669679315773056,0],"rotation":[0,0,0],"scale":[3.5,3.2159420289855074,1]}}]}],"requires":[],"compositionId":"25","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
     const result = getStandardJSON(JSON.parse(json));
     const filterItems = result.items.filter(item => {
       if (item.type === '2' && item.content.filter) {

From 80b6ea9aa91dbc34ee7a3d8e15d80ad755c80caf Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Mon, 22 Apr 2024 15:38:40 +0800
Subject: [PATCH 26/62] fix: migration

---
 fallback/migration.ts | 291 +++++++++++++++++++++---------------------
 1 file changed, 145 insertions(+), 146 deletions(-)

diff --git a/fallback/migration.ts b/fallback/migration.ts
index 41bc5b8..6f17dbd 100644
--- a/fallback/migration.ts
+++ b/fallback/migration.ts
@@ -73,6 +73,8 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
     }
   }
 
+  const itemGuidMap: Record<string, string> = {};
+
   // 更正Composition.endBehavior
   for (const composition of json.compositions) {
     // composition 的 endbehaviour 兼容
@@ -80,8 +82,6 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
       composition.endBehavior = END_BEHAVIOR_FREEZE;
     }
 
-    const itemGuidMap: Record<string, string> = {};
-
     for (const item of composition.items) {
       itemGuidMap[item.id] = generateGUID();
       // TODO: 编辑器测试用,上线后删除
@@ -108,184 +108,183 @@ export function version30Migration (json: JSONSceneLegacy): JSONScene {
       // @ts-expect-error fix item type
       composition.items[index] = { id: item.id };
     });
-
-    for (const item of result.items) {
-      // 原 texture 索引转为统一 guid 索引
-      if (item.content) {
-        if (item.content.renderer) {
-          if (item.content.renderer.texture !== undefined) {
-            const oldTextureId = item.content.renderer.texture;
-
-            item.content.renderer.texture = { id: result.textures[oldTextureId].id };
-          }
+  }
+  for (const item of result.items) {
+    // 原 texture 索引转为统一 guid 索引
+    if (item.content) {
+      if (item.content.renderer) {
+        if (item.content.renderer.texture !== undefined) {
+          const oldTextureId = item.content.renderer.texture;
+
+          item.content.renderer.texture = { id: result.textures[oldTextureId].id };
         }
+      }
 
-        if (item.content.trails) {
-          if (item.content.trails.texture !== undefined) {
-            const oldTextureId = item.content.trails.texture;
+      if (item.content.trails) {
+        if (item.content.trails.texture !== undefined) {
+          const oldTextureId = item.content.trails.texture;
 
-            item.content.trails.texture = { id: result.textures[oldTextureId].id };
-          }
+          item.content.trails.texture = { id: result.textures[oldTextureId].id };
         }
       }
+    }
 
-      // item 的 transform 属性由数组转为 {x:n, y:n, z:n}
-      if (item.transform) {
-        //@ts-expect-error
-        const position = [...item.transform.position ?? [0, 0, 0]];
-        //@ts-expect-error
-        const rotation = [...item.transform.rotation ?? [0, 0, 0]] as number[];
-        //@ts-expect-error
-        const scale = [...item.transform.scale ?? [1, 1, 1]];
-
-        Object.assign(item, {
-          transform: {
-            position: { x: position[0], y: position[1], z: position[2] },
-            eulerHint: { x: rotation[0], y: rotation[1], z: rotation[2] },
-            scale: { x: scale[0], y: scale[1], z: scale[0] },
-          },
-        });
-
-        // sprite 的 scale 转为 size
-        if (item.type === ItemType.sprite) {
-          item.transform.size = { x: scale[0], y: scale[1] };
-          item.transform.scale = { x: 1, y: 1, z: 1 };
-        }
+    // item 的 transform 属性由数组转为 {x:n, y:n, z:n}
+    if (item.transform) {
+      //@ts-expect-error
+      const position = [...item.transform.position ?? [0, 0, 0]];
+      //@ts-expect-error
+      const rotation = [...item.transform.rotation ?? [0, 0, 0]] as number[];
+      //@ts-expect-error
+      const scale = [...item.transform.scale ?? [1, 1, 1]];
+
+      Object.assign(item, {
+        transform: {
+          position: { x: position[0], y: position[1], z: position[2] },
+          eulerHint: { x: rotation[0], y: rotation[1], z: rotation[2] },
+          scale: { x: scale[0], y: scale[1], z: scale[0] },
+        },
+      });
 
-        // sprite 的 anchor 修正
-        if (item.type === ItemType.sprite) {
-          const content = item.content;
-
-          if (!content.renderer) {
-            content.renderer = {};
-          }
-          const renderer = content.renderer;
-          const realAnchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
-          const startSize = item.transform.size;
-
-          // 兼容旧JSON(anchor和particleOrigin可能同时存在)
-          if (!renderer.anchor && renderer.particleOrigin !== undefined) {
-            item.transform.position.x += -realAnchor[0] * (startSize?.x ?? 1);
-            item.transform.position.y += -realAnchor[1] * (startSize?.y ?? 1);
-          }
-          item.transform.anchor = { x: realAnchor[0] * (startSize?.x ?? 1), y: realAnchor[1] * (startSize?.y ?? 1) };
-        }
+      // sprite 的 scale 转为 size
+      if (item.type === ItemType.sprite) {
+        item.transform.size = { x: scale[0], y: scale[1] };
+        item.transform.scale = { x: 1, y: 1, z: 1 };
       }
 
-      if (item.type === ItemType.particle) {
+      // sprite 的 anchor 修正
+      if (item.type === ItemType.sprite) {
         const content = item.content;
 
         if (!content.renderer) {
           content.renderer = {};
         }
         const renderer = content.renderer;
+        const realAnchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
+        const startSize = item.transform.size;
+
+        // 兼容旧JSON(anchor和particleOrigin可能同时存在)
+        if (!renderer.anchor && renderer.particleOrigin !== undefined) {
+          item.transform.position.x += -realAnchor[0] * (startSize?.x ?? 1);
+          item.transform.position.y += -realAnchor[1] * (startSize?.y ?? 1);
+        }
+        item.transform.anchor = { x: realAnchor[0] * (startSize?.x ?? 1), y: realAnchor[1] * (startSize?.y ?? 1) };
+      }
+    }
+
+    if (item.type === ItemType.particle) {
+      const content = item.content;
 
-        content.renderer.anchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
+      if (!content.renderer) {
+        content.renderer = {};
       }
+      const renderer = content.renderer;
+
+      content.renderer.anchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
+    }
 
-      // 动画数据转化 TODO: 动画数据移到 TimelineComponentData
-      item.content.tracks = [];
-      const tracks = item.content.tracks;
-
-      if (item.type !== ItemType.particle) {
-        tracks.push({
-          clips: [
-            {
-              dataType: 'TransformAnimationPlayableAsset',
-              animationClip: {
-                sizeOverLifetime: item.content.sizeOverLifetime,
-                rotationOverLifetime: item.content.rotationOverLifetime,
-                positionOverLifetime: item.content.positionOverLifetime,
-              },
+    // 动画数据转化 TODO: 动画数据移到 TimelineComponentData
+    item.content.tracks = [];
+    const tracks = item.content.tracks;
+
+    if (item.type !== ItemType.particle) {
+      tracks.push({
+        clips: [
+          {
+            dataType: 'TransformAnimationPlayableAsset',
+            animationClip: {
+              sizeOverLifetime: item.content.sizeOverLifetime,
+              rotationOverLifetime: item.content.rotationOverLifetime,
+              positionOverLifetime: item.content.positionOverLifetime,
             },
-          ],
-        });
-      }
+          },
+        ],
+      });
+    }
 
-      if (item.type === ItemType.sprite) {
-        tracks.push({
-          clips: [
-            {
-              dataType: 'SpriteColorAnimationPlayableAsset',
-              animationClip: {
-                colorOverLifetime: item.content.colorOverLifetime,
-                startColor: item.content.options.startColor,
-              },
+    if (item.type === ItemType.sprite) {
+      tracks.push({
+        clips: [
+          {
+            dataType: 'SpriteColorAnimationPlayableAsset',
+            animationClip: {
+              colorOverLifetime: item.content.colorOverLifetime,
+              startColor: item.content.options.startColor,
             },
-          ],
-        });
-      }
+          },
+        ],
+      });
+    }
 
-      // gizmo 的 target id 转换为新的 item guid
-      if (item.content.options.target) {
-        item.content.options.target = itemGuidMap[item.content.options.target];
-      }
+    // gizmo 的 target id 转换为新的 item guid
+    if (item.content.options.target) {
+      item.content.options.target = itemGuidMap[item.content.options.target];
+    }
 
-      // item 的 content 转为 component data 加入 JSONScene.components
-      const uuid = generateGUID();
-
-      if (
-        item.type === ItemType.sprite ||
-        item.type === ItemType.particle ||
-        item.type === ItemType.mesh ||
-        item.type === ItemType.skybox ||
-        item.type === ItemType.light ||
-        item.type === 'camera' ||
-        item.type === ItemType.tree ||
-        item.type === ItemType.interact ||
-        item.type === ItemType.camera ||
-        item.type === ItemType.text
-      ) {
-        item.components = [];
-        result.components.push(item.content);
-        item.content.id = uuid;
-        item.content.item = { id: item.id };
-        item.dataType = DataType.VFXItemData;
-        item.components.push({ id: item.content.id });
-      }
+    // item 的 content 转为 component data 加入 JSONScene.components
+    const uuid = generateGUID();
+
+    if (
+      item.type === ItemType.sprite ||
+      item.type === ItemType.particle ||
+      item.type === ItemType.mesh ||
+      item.type === ItemType.skybox ||
+      item.type === ItemType.light ||
+      item.type === 'camera' ||
+      item.type === ItemType.tree ||
+      item.type === ItemType.interact ||
+      item.type === ItemType.camera ||
+      item.type === ItemType.text
+    ) {
+      item.components = [];
+      result.components.push(item.content);
+      item.content.id = uuid;
+      item.content.item = { id: item.id };
+      item.dataType = DataType.VFXItemData;
+      item.components.push({ id: item.content.id });
+    }
 
-      switch (item.type) {
-        case ItemType.sprite:
-          item.content.dataType = DataType.SpriteComponent;
+    switch (item.type) {
+      case ItemType.sprite:
+        item.content.dataType = DataType.SpriteComponent;
 
-          break;
-        case ItemType.particle:
-          item.content.dataType = DataType.ParticleSystem;
+        break;
+      case ItemType.particle:
+        item.content.dataType = DataType.ParticleSystem;
 
-          break;
-        case ItemType.mesh:
-          item.content.dataType = DataType.MeshComponent;
+        break;
+      case ItemType.mesh:
+        item.content.dataType = DataType.MeshComponent;
 
-          break;
-        case ItemType.skybox:
-          item.content.dataType = DataType.SkyboxComponent;
+        break;
+      case ItemType.skybox:
+        item.content.dataType = DataType.SkyboxComponent;
 
-          break;
-        case ItemType.light:
-          item.content.dataType = DataType.LightComponent;
+        break;
+      case ItemType.light:
+        item.content.dataType = DataType.LightComponent;
 
-          break;
-        case 'camera':
-          item.content.dataType = DataType.CameraComponent;
+        break;
+      case 'camera':
+        item.content.dataType = DataType.CameraComponent;
 
-          break;
-        case ItemType.tree:
-          item.content.dataType = DataType.TreeComponent;
+        break;
+      case ItemType.tree:
+        item.content.dataType = DataType.TreeComponent;
 
-          break;
-        case ItemType.interact:
-          item.content.dataType = DataType.InteractComponent;
+        break;
+      case ItemType.interact:
+        item.content.dataType = DataType.InteractComponent;
 
-          break;
-        case ItemType.camera:
-          item.content.dataType = DataType.CameraController;
+        break;
+      case ItemType.camera:
+        item.content.dataType = DataType.CameraController;
 
-          break;
-        case ItemType.text:
-          item.content.dataType = DataType.TextComponent;
+        break;
+      case ItemType.text:
+        item.content.dataType = DataType.TextComponent;
 
-          break;
-      }
+        break;
     }
   }
 

From 5e2aa3a808344855821a9067debcfc3ac7ed61cf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=84=8F=E7=BB=AE?= <yfj5tzl2005@sina.com>
Date: Tue, 23 Apr 2024 14:41:37 +0800
Subject: [PATCH 27/62] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=E6=96=87?=
 =?UTF-8?q?=E5=AD=97=E6=A8=A1=E7=89=88=E7=9B=B8=E5=85=B3=E7=B1=BB=E5=9E=8B?=
 =?UTF-8?q?=E5=AE=9A=E4=B9=89=20(#36)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/image.ts            | 37 ++++++++++---------------------------
 src/item/camera-item.ts |  2 +-
 src/text.ts             |  8 --------
 3 files changed, 11 insertions(+), 36 deletions(-)

diff --git a/src/image.ts b/src/image.ts
index 16ce165..05feb5a 100644
--- a/src/image.ts
+++ b/src/image.ts
@@ -1,5 +1,4 @@
 import type { RenderLevel } from './type';
-import type { StringTemplate } from './text';
 import type { BinaryPointer } from './binary';
 import type { DataType } from './components';
 
@@ -57,39 +56,23 @@ export type TextureJSONOptions = SerializedTextureSource;
 
 export type TextureDefine = TextureJSONOptions;
 
-export interface TemplateContentBase {
-  x?: number,
-  y?: number,
-  variables: Record<string, number | string>,
-  /**
-   * 当template宽高和image不相同时,会对template进行缩放,使其和image相同。
-   */
-  width: number,
-  height: number,
-}
-
-export interface TemplateContentV1 extends TemplateContentBase {
-  /**
-   * 贴图属性,svg 字段
-   */
-  content: string,
-  asImage?: boolean,
-  backgroundWidth: number,
-  backgroundHeight: number,
-}
-
 /**
  * 动态换图类型
- * @since 1.3.0
+ * @since 1.1.0
  */
 export enum BackgroundType {
   video = 'video',
   image = 'image',
 }
 
-export interface TemplateContentV2 extends TemplateContentBase {
-  v: 2,
-  content?: StringTemplate,
+export interface TemplateContent {
+  variables: Record<string, number | string>,
+  /**
+   * 当 template 宽高和 image 不相同时,会对 template 进行缩放,使其和 image 相同。
+   */
+  width: number,
+  height: number,
+  // 绘制 canvas 的背景图片,替换掉原来的那张图片,如果没有就不替换
   background?: {
     type: BackgroundType,
     name: string,
@@ -133,7 +116,7 @@ export interface Image {
  * 模板贴图属性
  */
 export interface TemplateImage extends Image {
-  template: TemplateContentV1 | TemplateContentV2,
+  template: TemplateContent,
 }
 
 /**
diff --git a/src/item/camera-item.ts b/src/item/camera-item.ts
index c66d58a..ec9e4bc 100644
--- a/src/item/camera-item.ts
+++ b/src/item/camera-item.ts
@@ -39,7 +39,7 @@ export interface CameraContent {
     clipMode?: CameraClipMode,
 
     /**
-     * 默认不提供,等于canvas width/height
+     * 默认不提供,等于 canvas width/height
      */
     aspect?: number,
   },
diff --git a/src/text.ts b/src/text.ts
index edc3f1b..35c2447 100644
--- a/src/text.ts
+++ b/src/text.ts
@@ -1,11 +1,3 @@
-import type { RGBAColor } from './number-expression';
-
-export interface StringTemplate {
-  fonts: FontBase[],
-  texts: Text[],
-  colors: RGBAColor[], //rgba rgba(0-255), a default 255
-}
-
 /**
  * 字体资源
  * @version 2.3

From 8cdbf243c82efddbab802f124ac0bf8b77a8044e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Tue, 23 Apr 2024 15:21:18 +0800
Subject: [PATCH 28/62] feat: add BuiltInObjectGuid (#37)

* feat: add BuiltInObjectGuid

* feat: add 3d guid

* perf: opt code

* perf: opt code
---
 src/buitin-object-guid.ts | 5 +++++
 src/index.ts              | 1 +
 2 files changed, 6 insertions(+)
 create mode 100644 src/buitin-object-guid.ts

diff --git a/src/buitin-object-guid.ts b/src/buitin-object-guid.ts
new file mode 100644
index 0000000..ba15e3c
--- /dev/null
+++ b/src/buitin-object-guid.ts
@@ -0,0 +1,5 @@
+export class BuiltinObjectGUID {
+  static readonly WhiteTexture = 'whitetexture00000000000000000000';
+  static readonly PBRShader = 'pbr00000000000000000000000000000';
+  static readonly UnlitShader = 'unlit000000000000000000000000000';
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index b62e98f..05468f2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -24,3 +24,4 @@ export * from './binary';
 export * from './text';
 export * from './components';
 export * from './vfx-item-data';
+export * from './buitin-object-guid';

From bff78f9441ffe294f5568db352238158aab1e3be Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 24 Apr 2024 10:34:43 +0800
Subject: [PATCH 29/62] perf: materialData add macros

---
 src/components.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/components.ts b/src/components.ts
index 425419d..fb24306 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -62,6 +62,7 @@ export interface MaterialData extends EffectsObjectData {
   zWrite?: boolean,
   zTest?: boolean,
   stringTags: Record<string, string>,
+  macros: string[],
   ints: Record<string, number>,
   floats: Record<string, number>,
   vector4s: Record<string, Vector4Data>,

From bdc41d014f3a7001ebd9544e0442aba2d3bb571a Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Fri, 26 Apr 2024 17:38:03 +0800
Subject: [PATCH 30/62] fix: fix test

---
 test/cases/particle/base.test.mjs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/test/cases/particle/base.test.mjs b/test/cases/particle/base.test.mjs
index 0ce26f0..a499436 100644
--- a/test/cases/particle/base.test.mjs
+++ b/test/cases/particle/base.test.mjs
@@ -290,7 +290,6 @@ describe('particle base', () => {
     expect([+r[0].toFixed(1), +r[1].toFixed(1), +r[2].toFixed(1)]).to.deep.equal([90.0, -20.0, 77.0]);
     // @ts-expect-error
     delete item.particle.transform;
-
     const neo2 = getStandardItem(item);
 
     expect(neo2.transform.position, 'position').not.exist;
@@ -416,7 +415,7 @@ describe('particle base', () => {
     };
     const res = getStandardJSON(oldParticle);
     const pt = res.items.find(item => item.id === res.compositions[0].items[0].id);
-    const r2 = pt.transform.rotation;
+    const r2 = pt.transform.eulerHint;
 
     expect([+r2.x.toFixed(1), +r2.y.toFixed(1), +r2.z.toFixed(1)]).to.eql([-90.0, -20.0, 30.0], 'oldParticle rotation');
   });

From db22571f4b426a0c076f9ec7a1f3eae44b284241 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=84=8F=E7=BB=AE?= <yfj5tzl2005@sina.com>
Date: Tue, 7 May 2024 17:18:51 +0800
Subject: [PATCH 31/62] =?UTF-8?q?refactor:=20=E5=B0=86=20fallback=20?=
 =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=A7=BB=E5=88=B0=20runtime=20=E4=B8=8B=20(#?=
 =?UTF-8?q?41)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* refactor: 将 fallback 代码移到 runtime 下

* chore: 移动 test 到 runtime

* chore: update exports

* chore: 规范 VFXItemData 的 type 类型
---
 .eslintrc.js                                |   14 +-
 .gitignore                                  |    5 +-
 .lintstagedrc.json                          |    2 +-
 README.md                                   |   12 +-
 fallback/camera.ts                          |   45 -
 fallback/index.ts                           |  310 --
 fallback/interact.ts                        |   49 -
 fallback/migration.ts                       |  346 --
 fallback/particle.ts                        |  191 -
 fallback/sprite.ts                          |  120 -
 fallback/utils.ts                           |  387 --
 package-lock.json                           | 4750 -------------------
 package.json                                |   61 +-
 pnpm-lock.yaml                              | 2263 +++++++++
 rollup.config.js                            |   65 -
 src/binary.ts                               |    2 +-
 src/index.ts                                |    1 -
 src/item/base-item.ts                       |   11 +
 src/item/model/mesh.ts                      |    3 +-
 src/types/shim.d.ts                         |    1 -
 src/vfx-item-data.ts                        |    2 +-
 test/cases/composition/composition.test.mjs |  110 -
 test/cases/image/image.test.mjs             |   67 -
 test/cases/index.mjs                        |   12 -
 test/cases/model/camera.test.mjs            |  163 -
 test/cases/model/index.test.mjs             |  474 --
 test/cases/null/base.test.mjs               |  311 --
 test/cases/null/end-behavior.test.mjs       |   20 -
 test/cases/particle/base.test.mjs           | 1063 -----
 test/cases/particle/trails.test.mjs         |   85 -
 test/cases/sprite/base.test.mjs             |  635 ---
 test/cases/sprite/filter.test.mjs           |   39 -
 test/cases/ui/ui.test.mjs                   |  117 -
 test/index.html                             |   24 -
 tsconfig.build.json                         |   12 +
 tsconfig.bundle.json                        |   12 -
 tsconfig.json                               |   38 +-
 37 files changed, 2329 insertions(+), 9493 deletions(-)
 delete mode 100644 fallback/camera.ts
 delete mode 100644 fallback/index.ts
 delete mode 100644 fallback/interact.ts
 delete mode 100644 fallback/migration.ts
 delete mode 100644 fallback/particle.ts
 delete mode 100644 fallback/sprite.ts
 delete mode 100644 fallback/utils.ts
 delete mode 100644 package-lock.json
 create mode 100644 pnpm-lock.yaml
 delete mode 100644 rollup.config.js
 delete mode 100644 src/types/shim.d.ts
 delete mode 100644 test/cases/composition/composition.test.mjs
 delete mode 100644 test/cases/image/image.test.mjs
 delete mode 100644 test/cases/index.mjs
 delete mode 100644 test/cases/model/camera.test.mjs
 delete mode 100644 test/cases/model/index.test.mjs
 delete mode 100644 test/cases/null/base.test.mjs
 delete mode 100644 test/cases/null/end-behavior.test.mjs
 delete mode 100644 test/cases/particle/base.test.mjs
 delete mode 100644 test/cases/particle/trails.test.mjs
 delete mode 100644 test/cases/sprite/base.test.mjs
 delete mode 100644 test/cases/sprite/filter.test.mjs
 delete mode 100644 test/cases/ui/ui.test.mjs
 delete mode 100644 test/index.html
 create mode 100644 tsconfig.build.json
 delete mode 100644 tsconfig.bundle.json

diff --git a/.eslintrc.js b/.eslintrc.js
index 8f28844..10fccae 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -8,11 +8,9 @@ module.exports = {
   env: {
     browser: true,
     node: true,
-    mocha: true,
   },
-  globals: { 'chai': true },
   ignorePatterns: [
-    '**/{node_modules,libs}',
+    '**/{node_modules,es}',
     '*.js',
     '*.d.ts',
   ],
@@ -137,13 +135,5 @@ module.exports = {
       },
     ],
     "compat/compat": "error",
-  },
-  overrides: [
-    {
-      "files": ["**/test/**/*.ts", "**/demo/**/*.ts"],
-      "rules": {
-        "compat/compat": "off"
-      }
-    }
-  ]
+  }
 };
diff --git a/.gitignore b/.gitignore
index 3468bae..bea985d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -91,7 +91,4 @@ typings/
 
 .idea
 .history
-dist
-dist-rollup
-test/dev/*
-node/index.js
+es
diff --git a/.lintstagedrc.json b/.lintstagedrc.json
index 94d8311..5c81507 100644
--- a/.lintstagedrc.json
+++ b/.lintstagedrc.json
@@ -1,5 +1,5 @@
 {
-  "{src,fallback,test}/**/*.{ts,mjs}": [
+  "src/**/*.ts": [
     "eslint --cache --fix",
     "sh -c 'tsc -b tsconfig.check.json'"
   ]
diff --git a/README.md b/README.md
index 06b7968..db5775b 100644
--- a/README.md
+++ b/README.md
@@ -8,15 +8,7 @@
 
 ``` bash
 # 1. Install dependencies (first time)
-npm install
+pnpm install
 # 2. Build
-npm run build
+pnpm run build
 ```
-
-## Testing
-
-``` bash
-npm run test
-```
-
-> Open browser and open: http://localhost:9003/test/
diff --git a/fallback/camera.ts b/fallback/camera.ts
deleted file mode 100644
index a5d78e9..0000000
--- a/fallback/camera.ts
+++ /dev/null
@@ -1,45 +0,0 @@
-import type { CameraContent, CameraPositionOverLifetime } from '../src/item/camera-item';
-import type { RotationOverLifetime } from '../src';
-import { deleteEmptyValue, ensureFixedNumber, ensureFixedVec3 } from './utils';
-
-export function getStandardCameraContent (model: any): CameraContent {
-  const opt = model.options;
-  const ret: CameraContent = {
-    options: {
-      fov: opt.fov!,
-      far: opt.far!,
-      near: opt.near!,
-      clipMode: opt.clipMode,
-    },
-  };
-
-  const velocityOverLifetime = model.velocityOverLifetime;
-
-  if (velocityOverLifetime || model.transform?.path) {
-    const positionOverLifetime: CameraPositionOverLifetime = {
-      path: ensureFixedVec3(model.transform?.path),
-      linearX: ensureFixedNumber(velocityOverLifetime?.translateX),
-      linearY: ensureFixedNumber(velocityOverLifetime?.translateY),
-      linearZ: ensureFixedNumber(velocityOverLifetime?.translateZ),
-    };
-
-    deleteEmptyValue(positionOverLifetime);
-    ret.positionOverLifetime = positionOverLifetime;
-  }
-
-  const rol = model.rotationOverLifetime;
-
-  if (rol) {
-    const rotationOverLifetime: RotationOverLifetime = {
-      separateAxes: rol.separateAxes,
-      x: ensureFixedNumber(rol?.rotateX),
-      y: ensureFixedNumber(rol?.rotateY),
-      z: rol.separateAxes ? ensureFixedNumber(rol?.rotateZ) : ensureFixedNumber(rol.rotation),
-    };
-
-    deleteEmptyValue(rotationOverLifetime);
-    ret.rotationOverLifetime = rotationOverLifetime;
-  }
-
-  return ret;
-}
diff --git a/fallback/index.ts b/fallback/index.ts
deleted file mode 100644
index 77e4e25..0000000
--- a/fallback/index.ts
+++ /dev/null
@@ -1,310 +0,0 @@
-import type {
-  BaseItem, BaseItemTransform, Composition, CompressedImage, Image, JSONScene, ParticleItem,
-  RenderLevel, SpriteItem, TemplateImage, JSONSceneLegacy, Item,
-} from '../src';
-import { CAMERA_CLIP_MODE_NORMAL, ItemEndBehavior, ItemType } from '../src';
-import { getStandardParticleContent } from './particle';
-import { getStandardNullContent, getStandardSpriteContent } from './sprite';
-import { getStandardInteractContent } from './interact';
-import { arrAdd, quatFromXYZRotation, rotationZYXFromQuat } from './utils';
-import { getStandardCameraContent } from './camera';
-import { version21Migration, version22Migration, version24Migration, version30Migration } from './migration';
-
-export * from './utils';
-
-const v0 = /^(\d+)\.(\d+)\.(\d+)(-(\w+)\.\d+)?$/;
-const standardVersion = /^(\d+)\.(\d+)$/;
-let reverseParticle = false;
-
-export function getStandardJSON (json: any): JSONScene {
-  if (!json || typeof json !== 'object') {
-    throw Error('expect a json object');
-  }
-
-  // 修正老版本数据中,meshItem 以及 lightItem 结束行为错误问题
-  version22Migration(json);
-
-  if (v0.test(json.version)) {
-    reverseParticle = (/^(\d+)/).exec(json.version)?.[0] === '0';
-
-    return version30Migration(version21Migration(getStandardJSONFromV0(json)));
-  }
-
-  const vs = standardVersion.exec(json.version) || [];
-  const mainVersion = Number(vs[1]);
-  const minorVersion = Number(vs[2]);
-
-  if (mainVersion) {
-    if (mainVersion < 2 || (mainVersion === 2 && minorVersion < 4)) {
-      json = version24Migration(json);
-    }
-    if (mainVersion < 3) {
-      return version30Migration(version21Migration(json));
-    }
-
-    return json;
-  }
-
-  throw Error('invalid json version ' + json.version);
-}
-
-let currentVersion: '1.0' | '1.1' | '1.3' = '1.0';
-
-function getStandardJSONFromV0 (json: any): JSONSceneLegacy {
-  currentVersion = '1.0';
-  const plugins = json.plugins || [];
-
-  if (json.bins?.length) {
-    currentVersion = '1.3';
-  }
-  const requires: string[] = (json.requires || []).slice();
-  const images = json.images.map((img: any, index: number) => getStandardImage(img, index, json.imageTags || []));
-  const textures = json.textures || images.map((img: any, i: number) => ({ source: i, flipY: true }));
-  const ret: JSONSceneLegacy = {
-    plugins: plugins,
-    shapes: json.shapes || [],
-    type: 'ge',
-    version: currentVersion,
-    playerVersion: json.playerVersion ?? {
-      web: '',
-      native: '',
-    },
-    compositionId: json.compositionId + '',
-    compositions: json.compositions.map((comp: any) => getStandardComposition(comp, { plugins, requires })),
-    images,
-    imgUsage: json._imgs,
-    binUsage: json.binUsage,
-    spines: json.spines,
-    requires: json.requires,
-    textures,
-    bins: (json.bins || []).slice(),
-  };
-
-  if (json._textures) {
-    (ret as any)._textures = json._textures;
-  }
-
-  return ret;
-}
-
-export function getStandardImage (image: any, index: number, imageTags: RenderLevel[]): TemplateImage | Image | CompressedImage {
-  const renderLevel = imageTags[index];
-
-  const oriY = image.oriY;
-
-  if (typeof image === 'string') {
-    return {
-      renderLevel,
-      url: image,
-      oriY,
-    };
-  } else if (image.template) {
-    return {
-      url: image.url,
-      template: image.template,
-      webp: image.webp,
-      renderLevel,
-      oriY,
-    };
-  } else if (image.compressed) {
-    return {
-      url: image.url,
-      oriY,
-      compressed: {
-        astc: image.compressed.android,
-        pvrtc: image.compressed.iOS,
-      },
-      webp: image.webp,
-      renderLevel,
-    };
-  } else if (image.url) {
-    return {
-      url: image.url,
-      webp: image.webp,
-      renderLevel,
-      oriY,
-    };
-  } else if (image && image.sourceType) {
-    return image;
-  }
-  throw Error('invalid image type');
-}
-
-export function getStandardComposition (composition: any, opt: { plugins?: string[], requires?: string[] } = {}): Composition {
-  const ret: Composition = {
-    id: composition.id + '',
-    camera: { clipMode: CAMERA_CLIP_MODE_NORMAL, ...composition.camera },
-    duration: composition.duration,
-    endBehavior: composition.endBehavior,
-    items: composition.items.map((item: any) => getStandardItem(item, opt)),
-    name: composition.name,
-  };
-  const startTime = composition.startTime || composition.st;
-
-  if (startTime) {
-    ret.startTime = startTime;
-  }
-  let previewSize = composition.meta?.previewSize;
-
-  if (previewSize && previewSize[0] === previewSize[1] && previewSize[0] === 0) {
-    previewSize = undefined;
-  }
-  if (previewSize) {
-    ret.previewSize = previewSize;
-  }
-
-  return ret;
-}
-
-const tempQuat = [0, 0, 0, 1];
-
-const stdAnchor = 0.5;
-
-export function getStandardItem (item: any, opt: { plugins?: string[], requires?: string[] } = {}): SpriteItem | ParticleItem | BaseItem {
-  let type: ItemType | string = ItemType.base;
-  let transform: BaseItemTransform;
-  let originContent;
-  let content;
-  let endBehavior: ItemEndBehavior = item.endBehavior;
-  let renderLevel: RenderLevel;
-  let pluginName: string;
-  let duration = NaN;
-  let pn: number;
-
-  if (item.content) {
-    type = item.type || ItemType.plugin;
-    pn = item.pn;
-    pluginName = item.pluginName;
-    content = item.content;
-    originContent = item.content;
-    if (isNaN(pn) && !pluginName) {
-      pluginName = content.options.type;
-    }
-    if (item.duration) {
-      duration = item.duration;
-    }
-    transform = item.transform || getTransform(originContent.transform);
-  } else if (item.particle) {
-    type = ItemType.particle;
-    originContent = item.particle;
-    transform = getTransform(originContent.transform, reverseParticle, true);
-    content = getStandardParticleContent(originContent);
-  } else if (item.sprite) {
-    type = ItemType.sprite;
-    originContent = item.sprite;
-    transform = getTransform(originContent.transform, false, true);
-    content = getStandardSpriteContent(originContent, transform);
-  } else if (item.cal) {
-    type = ItemType.null;
-    originContent = item.cal;
-    transform = getTransform(originContent.transform, false, true);
-    content = getStandardNullContent(originContent, transform);
-  } else if (item.ui) {
-    type = ItemType.interact;
-    originContent = item.ui;
-    transform = getTransform(originContent.transform);
-    content = getStandardInteractContent(originContent);
-    transform.scale = [originContent.options.width || 1, originContent.options.height || 1, 1];
-  } else if (item.model) {
-    originContent = item.model;
-    if (item.model.options.type === 1) {
-      type = ItemType.camera;
-      transform = getTransform(originContent.transform);
-      content = getStandardCameraContent(originContent);
-    }
-  }
-  if (content.renderer?.anchor) {
-    const anchor = new Float32Array(content.renderer.anchor);
-
-    if (anchor[0] == stdAnchor && anchor[1] == stdAnchor) {
-      delete content.renderer.anchor;
-    } else if (opt.requires) {
-      arrAdd(opt.requires, 'anchor');
-    }
-  }
-  if (originContent) {
-    const looping = originContent.options?.looping;
-
-    if (looping) {
-      if (Array.isArray(looping)) {
-        endBehavior = looping[1] ? ItemEndBehavior.loop : ItemEndBehavior.destroy;
-      } else {
-        endBehavior = ItemEndBehavior.loop;
-      }
-    } else {
-      endBehavior = endBehavior || originContent?.options?.endBehavior || ItemEndBehavior.destroy;
-    }
-    if (originContent.options.renderLevel) {
-      renderLevel = originContent.options.renderLevel;
-    }
-    if (isNaN(duration)) {
-      duration = originContent.options.duration;
-    }
-  }
-
-  const ret: BaseItem = {
-    type,
-    name: item.name,
-    delay: item.delay,
-    duration,
-    id: item.id + '',
-    // @ts-expect-error
-    transform,
-    endBehavior,
-    // @ts-expect-error
-    renderLevel,
-    content,
-  };
-
-  // @ts-expect-error
-  if (pluginName) {
-    if (opt.plugins) {
-      arrAdd(opt.plugins, pluginName);
-      ret.pn = opt.plugins.indexOf(pluginName);
-    } else {
-      ret.pluginName = pluginName;
-    }
-    // @ts-expect-error
-  } else if (Number.isInteger(pn)) {
-    // @ts-expect-error
-    ret.pn = pn;
-  }
-  if (item.parentId) {
-    ret.parentId = item.parentId + '';
-  }
-
-  return ret;
-
-  function getTransform (originTransform: BaseItemTransform, inverseRotation?: boolean, changeOrder?: boolean): BaseItemTransform {
-    if (originTransform) {
-      const transform: BaseItemTransform = {};
-      const rotation = originTransform.rotation;
-
-      if (rotation) {
-        if (inverseRotation) {
-          transform.rotation = [-rotation[0], -rotation[1], -rotation[2]];
-        } else {
-          transform.rotation = [rotation[0], rotation[1], rotation[2]];
-        }
-        if (changeOrder) {
-          const q = quatFromXYZRotation(tempQuat, transform.rotation[0], transform.rotation[1], transform.rotation[2]);
-
-          transform.rotation = rotationZYXFromQuat([], q);
-        }
-      }
-      const position = originTransform.position;
-
-      if (position) {
-        transform.position = originTransform.position;
-      }
-      if (Array.isArray(originTransform.scale)) {
-        transform.scale = [originTransform.scale[0] || 1, originTransform.scale[1] || 1, originTransform.scale[2] || 1];
-      }
-
-      return transform;
-    }
-
-    return {};
-  }
-}
-
diff --git a/fallback/interact.ts b/fallback/interact.ts
deleted file mode 100644
index 8655856..0000000
--- a/fallback/interact.ts
+++ /dev/null
@@ -1,49 +0,0 @@
-import type { InteractContent, InteractOption } from '../src';
-import { InteractType, InteractBehavior } from '../src';
-import { ensureRGBAValue } from './utils';
-
-export function getStandardInteractContent (ui: any): InteractContent {
-  const options = ui.options;
-  let option: InteractOption;
-
-  switch (options.type) {
-    case 'click': {
-      option = {
-        type: InteractType.CLICK,
-        showPreview: options.showPreview,
-        previewColor: options.previewColor && ensureRGBAValue(options.previewColor),
-        behavior: options.behavior || InteractBehavior.NOTIFY,
-      };
-
-      break;
-    }
-    case 'drag': {
-      option = {
-        type: InteractType.DRAG,
-        enableInEditor: !!options.enableInEditor,
-        dxRange: options.dxRange,
-        dyRange: options.dyRange,
-        target: options.target,
-      };
-
-      break;
-    }
-    case 'message': {
-      option = {
-        type: InteractType.MESSAGE,
-      };
-
-      break;
-    }
-    default: {
-      break;
-    }
-  }
-
-  const ret: InteractContent = {
-    // @ts-expect-error
-    options: option,
-  };
-
-  return ret;
-}
diff --git a/fallback/migration.ts b/fallback/migration.ts
deleted file mode 100644
index c0beb2f..0000000
--- a/fallback/migration.ts
+++ /dev/null
@@ -1,346 +0,0 @@
-import type { JSONScene, JSONSceneLegacy, BaseContent } from '../src';
-import { ItemType, ItemEndBehavior, END_BEHAVIOR_PAUSE_AND_DESTROY, END_BEHAVIOR_FREEZE, END_BEHAVIOR_PAUSE, DataType } from '../src';
-import { convertAnchor, generateGUID, ensureFixedNumber, ensureFixedVec3 } from './utils';
-
-/**
- * 2.1 以下版本数据适配(mars-player@2.4.0 及以上版本支持 2.1 以下数据的适配)
- */
-export function version21Migration (json: JSONSceneLegacy): JSONSceneLegacy {
-  json.compositions.forEach(composition => {
-    composition.items.forEach(item => {
-      if (item.type === ItemType.null) {
-        if (item.endBehavior === ItemEndBehavior.destroy) {
-          item.endBehavior = ItemEndBehavior.freeze;
-        }
-      }
-    });
-  });
-
-  json.version = '2.1';
-
-  return json;
-}
-
-/**
- * 2.2 以下版本数据适配(mars-player@2.5.0 及以上版本支持 2.2 以下数据的适配)
- */
-export function version22Migration (json: JSONSceneLegacy): JSONSceneLegacy {
-  const singleVersion = json.version?.split('.');
-
-  if (!singleVersion || Number(singleVersion[0]) > 2 || (Number(singleVersion[0]) === 2 && Number(singleVersion[1]) >= 2)) {
-    return json;
-  }
-
-  json.compositions.forEach(composition => {
-    composition.items.forEach(item => {
-      if (item.type === ItemType.mesh || item.type === ItemType.light) {
-        item.endBehavior = item.endBehavior as unknown === 1 ? ItemEndBehavior.destroy : item.endBehavior;
-      }
-    });
-  });
-
-  return json;
-}
-
-/**
- * 3.0 以下版本数据适配(runtime 2.0及以上版本支持)
- */
-export function version30Migration (json: JSONSceneLegacy): JSONScene {
-  const result: JSONScene = {
-    ...json,
-    items: [],
-    components: [],
-    materials: [],
-    shaders: [],
-    geometries: [],
-  };
-
-  // 兼容老版本数据中不存在textures的情况
-  result.textures ??= [];
-  result.textures.forEach(textureOptions => {
-    textureOptions.id = generateGUID();
-    textureOptions.dataType = DataType.Texture;
-  });
-
-  if (result.textures.length < result.images.length) {
-    for (let i = result.textures.length; i < result.images.length; i++) {
-      result.textures.push({
-        id: generateGUID(),
-        dataType: DataType.Texture,
-        source: i,
-        flipY: true,
-      });
-    }
-  }
-
-  const itemGuidMap: Record<string, string> = {};
-
-  // 更正Composition.endBehavior
-  for (const composition of json.compositions) {
-    // composition 的 endbehaviour 兼容
-    if (composition.endBehavior === END_BEHAVIOR_PAUSE_AND_DESTROY || composition.endBehavior === END_BEHAVIOR_PAUSE) {
-      composition.endBehavior = END_BEHAVIOR_FREEZE;
-    }
-
-    // 过滤掉滤镜元素
-    composition.items = composition.items.filter(item => item.type !== '8' as ItemType);
-
-    // 过滤掉粒子滤镜(扭曲)
-    composition.items.forEach(item => {
-      if (item.type === ItemType.particle) {
-        // @ts-expect-error
-        const filterData = item.content['filter'];
-
-        if (filterData) {
-          // @ts-expect-error
-          delete item.content['filter'];
-        }
-      }
-    });
-
-    const itemGuidMap: Record<string, string> = {};
-
-    for (const item of composition.items) {
-      itemGuidMap[item.id] = generateGUID();
-      // TODO: 编辑器测试用,上线后删除
-      //@ts-expect-error
-      item.oldId = item.id;
-      item.id = itemGuidMap[item.id];
-    }
-
-    composition.items.forEach((item, index) => {
-      if (item.parentId) {
-        if (item.parentId.includes('^')) {
-          const parentId = (item.parentId).split('^')[0];
-          const nodeId = (item.parentId).split('^')[1];
-
-          item.parentId = itemGuidMap[parentId] + '^' + nodeId;
-        } else {
-          item.parentId = itemGuidMap[item.parentId];
-        }
-      }
-
-      // @ts-expect-error fix item type
-      result.items.push(item);
-
-      // @ts-expect-error fix item type
-      composition.items[index] = { id: item.id };
-    });
-  }
-  for (const item of result.items) {
-    // 原 texture 索引转为统一 guid 索引
-    if (item.content) {
-      if (item.content.renderer) {
-        if (item.content.renderer.texture !== undefined) {
-          const oldTextureId = item.content.renderer.texture;
-
-          item.content.renderer.texture = { id: result.textures[oldTextureId].id };
-        }
-      }
-
-      if (item.content.trails) {
-        if (item.content.trails.texture !== undefined) {
-          const oldTextureId = item.content.trails.texture;
-
-          item.content.trails.texture = { id: result.textures[oldTextureId].id };
-        }
-      }
-    }
-
-    // item 的 transform 属性由数组转为 {x:n, y:n, z:n}
-    if (item.transform) {
-      //@ts-expect-error
-      const position = [...item.transform.position ?? [0, 0, 0]];
-      //@ts-expect-error
-      const rotation = [...item.transform.rotation ?? [0, 0, 0]] as number[];
-      //@ts-expect-error
-      const scale = [...item.transform.scale ?? [1, 1, 1]];
-
-      Object.assign(item, {
-        transform: {
-          position: { x: position[0], y: position[1], z: position[2] },
-          eulerHint: { x: rotation[0], y: rotation[1], z: rotation[2] },
-          scale: { x: scale[0], y: scale[1], z: scale[0] },
-        },
-      });
-
-      // sprite 的 scale 转为 size
-      if (item.type === ItemType.sprite) {
-        item.transform.size = { x: scale[0], y: scale[1] };
-        item.transform.scale = { x: 1, y: 1, z: 1 };
-      }
-
-      // sprite 的 anchor 修正
-      if (item.type === ItemType.sprite) {
-        const content = item.content;
-
-        if (!content.renderer) {
-          content.renderer = {};
-        }
-        const renderer = content.renderer;
-        const realAnchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
-        const startSize = item.transform.size;
-
-        // 兼容旧JSON(anchor和particleOrigin可能同时存在)
-        if (!renderer.anchor && renderer.particleOrigin !== undefined) {
-          item.transform.position.x += -realAnchor[0] * (startSize?.x ?? 1);
-          item.transform.position.y += -realAnchor[1] * (startSize?.y ?? 1);
-        }
-        item.transform.anchor = { x: realAnchor[0] * (startSize?.x ?? 1), y: realAnchor[1] * (startSize?.y ?? 1) };
-      }
-    }
-
-    if (item.type === ItemType.particle) {
-      const content = item.content;
-
-      if (!content.renderer) {
-        content.renderer = {};
-      }
-      const renderer = content.renderer;
-
-      content.renderer.anchor = convertAnchor(renderer.anchor, renderer.particleOrigin);
-    }
-
-    // 动画数据转化 TODO: 动画数据移到 TimelineComponentData
-    item.content.tracks = [];
-    const tracks = item.content.tracks;
-
-    if (item.type !== ItemType.particle) {
-      tracks.push({
-        clips: [
-          {
-            dataType: 'TransformAnimationPlayableAsset',
-            animationClip: {
-              sizeOverLifetime: item.content.sizeOverLifetime,
-              rotationOverLifetime: item.content.rotationOverLifetime,
-              positionOverLifetime: item.content.positionOverLifetime,
-            },
-          },
-        ],
-      });
-    }
-
-    if (item.type === ItemType.sprite) {
-      tracks.push({
-        clips: [
-          {
-            dataType: 'SpriteColorAnimationPlayableAsset',
-            animationClip: {
-              colorOverLifetime: item.content.colorOverLifetime,
-              startColor: item.content.options.startColor,
-            },
-          },
-        ],
-      });
-    }
-
-    // gizmo 的 target id 转换为新的 item guid
-    if (item.content.options.target) {
-      item.content.options.target = itemGuidMap[item.content.options.target];
-    }
-
-    // item 的 content 转为 component data 加入 JSONScene.components
-    const uuid = generateGUID();
-
-    if (
-      item.type === ItemType.sprite ||
-      item.type === ItemType.particle ||
-      item.type === ItemType.mesh ||
-      item.type === ItemType.skybox ||
-      item.type === ItemType.light ||
-      item.type === 'camera' ||
-      item.type === ItemType.tree ||
-      item.type === ItemType.interact ||
-      item.type === ItemType.camera ||
-      item.type === ItemType.text
-    ) {
-      item.components = [];
-      result.components.push(item.content);
-      item.content.id = uuid;
-      item.content.item = { id: item.id };
-      item.dataType = DataType.VFXItemData;
-      item.components.push({ id: item.content.id });
-    }
-
-    switch (item.type) {
-      case ItemType.sprite:
-        item.content.dataType = DataType.SpriteComponent;
-
-        break;
-      case ItemType.particle:
-        item.content.dataType = DataType.ParticleSystem;
-
-        break;
-      case ItemType.mesh:
-        item.content.dataType = DataType.MeshComponent;
-
-        break;
-      case ItemType.skybox:
-        item.content.dataType = DataType.SkyboxComponent;
-
-        break;
-      case ItemType.light:
-        item.content.dataType = DataType.LightComponent;
-
-        break;
-      case 'camera':
-        item.content.dataType = DataType.CameraComponent;
-
-        break;
-      case ItemType.tree:
-        item.content.dataType = DataType.TreeComponent;
-
-        break;
-      case ItemType.interact:
-        item.content.dataType = DataType.InteractComponent;
-
-        break;
-      case ItemType.camera:
-        item.content.dataType = DataType.CameraController;
-
-        break;
-      case ItemType.text:
-        item.content.dataType = DataType.TextComponent;
-
-        break;
-    }
-  }
-
-  result.version = '3.0';
-
-  return result;
-}
-
-/**
- * 2.5 以下版本 赫尔米特数据转换成贝塞尔数据
- */
-export function version24Migration (json: JSONScene): JSONScene {
-  // 曲线转换成贝塞尔
-  json.compositions.map((comp: any) => {
-    for (const item of comp.items) {
-      convertParam(item.content);
-    }
-  });
-
-  return json;
-}
-
-export function convertParam (content: BaseContent | undefined | null) {
-  if (!content) {
-    return;
-  }
-  for (const key of Object.keys(content)) {
-    const value = content[key];
-    const isArray = Array.isArray(value);
-
-    if (isArray && value.length === 2 && Array.isArray(value[1])) {
-      if (key === 'path') {
-        content[key] = ensureFixedVec3(value);
-      } else {
-        content[key] = ensureFixedNumber(value);
-      }
-    } else if (!isArray && typeof value === 'object') {
-      convertParam(value);
-    }
-  }
-}
diff --git a/fallback/particle.ts b/fallback/particle.ts
deleted file mode 100644
index 1c4da3b..0000000
--- a/fallback/particle.ts
+++ /dev/null
@@ -1,191 +0,0 @@
-import type { ParticleContent, ParticleShape, ParticleShapeSphere, ColorOverLifetime } from '../src';
-import { ShapeType } from '../src';
-import {
-  deleteEmptyValue, ensureColorExpression, ensureFixedNumber, ensureFixedNumberWithRandom,
-  ensureFixedVec3, ensureNumberExpression, getGradientColor, objectValueToNumber,
-} from './utils';
-
-export function getStandardParticleContent (particle: any): ParticleContent {
-  const options = particle.options;
-  const transform = particle.transform;
-  let shape: ParticleShape = {
-    type: ShapeType.NONE,
-  };
-
-  if (particle.shape) {
-    const shapeType = particle.shape.shape?.replace(/([A-Z])/g, '_$1').toUpperCase().replace(/^_/, '');
-
-    shape = {
-      ...particle.shape,
-      type: ShapeType[shapeType as keyof typeof ShapeType],
-    };
-    if (particle.shape.upDirection) {
-      const [x, y, z] = particle.shape.upDirection;
-
-      if (x === 0 && y === 0 && z === 0) {
-        delete (shape as ParticleShapeSphere).upDirection;
-      }
-    }
-  }
-  if (options.startTurbulence) {
-    shape.turbulenceX = ensureNumberExpression(options.turbulenceX);
-    shape.turbulenceY = ensureNumberExpression(options.turbulenceY);
-    shape.turbulenceZ = ensureNumberExpression(options.turbulenceZ);
-  }
-  const emission = particle.emission;
-
-  if (emission.bursts && emission.bursts.length > 0) {
-    emission.bursts = emission.bursts.map((b: any) => objectValueToNumber(b));
-  }
-  if (emission.burstOffsets && emission.burstOffsets.length > 0) {
-    emission.burstOffsets = emission.burstOffsets.map((b: any) => objectValueToNumber(b));
-  }
-  if (emission.rateOverTime) {
-    emission.rateOverTime = ensureNumberExpression(emission.rateOverTime);
-  }
-
-  const ret: ParticleContent = {
-    renderer: particle.renderer,
-    shape,
-    splits: particle.splits,
-    emission: emission,
-    options: {
-      startLifetime: ensureNumberExpression(options.startLifetime)!,
-      start3DSize: !!options.start3DSize,
-      startSize: ensureNumberExpression(options.startSize),
-      startSizeX: ensureNumberExpression(options.startSizeX),
-      startSizeY: ensureNumberExpression(options.startSizeY),
-      sizeAspect: ensureNumberExpression(options.sizeAspect),
-      maxCount: options.maxCount,
-      startDelay: ensureNumberExpression(options.startDelay),
-      startColor: ensureColorExpression(options.startColor, true),
-      startRotationZ: ensureNumberExpression(options.startRotation || options.startRotationZ),
-      particleFollowParent: options.particleFollowParent,
-    },
-  };
-
-  if (options.start3DRotation) {
-    ret.options.startRotationX = ensureNumberExpression(options.startRotationX);
-    ret.options.startRotationY = ensureNumberExpression(options.startRotationY);
-  }
-
-  if (transform && transform.path) {
-    ret.emitterTransform = {
-      path: ensureFixedVec3(transform.path),
-    };
-  }
-  const sizeOverLifetime = particle.sizeOverLifetime;
-
-  if (sizeOverLifetime) {
-    if (sizeOverLifetime.separateAxes) {
-      ret.sizeOverLifetime = {
-        separateAxes: true,
-        x: ensureNumberExpression(sizeOverLifetime.x),
-        y: ensureNumberExpression(sizeOverLifetime.y),
-      };
-    } else {
-      ret.sizeOverLifetime = {
-        size: ensureNumberExpression(sizeOverLifetime.size),
-      };
-    }
-  }
-  const velocityOverLifetime = particle.velocityOverLifetime || {};
-  let sol = velocityOverLifetime.speedOverLifetime;
-
-  if (sol) {
-    sol = ensureFixedNumber(sol);
-  } else {
-    sol = undefined;
-  }
-  ret.positionOverLifetime = {
-    gravity: options.gravity,
-    gravityOverLifetime: ensureFixedNumber(options.gravityModifier),
-    startSpeed: ensureNumberExpression(options.startSpeed),
-    speedOverLifetime: sol,
-    asMovement: velocityOverLifetime.asMovement,
-    linearX: ensureNumberExpression(velocityOverLifetime.linearX),
-    linearY: ensureNumberExpression(velocityOverLifetime.linearY),
-    linearZ: ensureNumberExpression(velocityOverLifetime.linearZ),
-    asRotation: velocityOverLifetime.asRotation,
-    orbCenter: velocityOverLifetime.orbCenter,
-    orbitalX: ensureNumberExpression(velocityOverLifetime.orbitalX),
-    orbitalY: ensureNumberExpression(velocityOverLifetime.orbitalY),
-    orbitalZ: ensureNumberExpression(velocityOverLifetime.orbitalZ),
-    forceTarget: velocityOverLifetime.forceTarget,
-    target: velocityOverLifetime.target,
-    forceCurve: ensureFixedNumber(velocityOverLifetime.forceCurve) as any,
-  };
-  deleteEmptyValue(ret.positionOverLifetime);
-  const rotationOverLifetime = particle.rotationOverLifetime;
-
-  if (rotationOverLifetime) {
-    ret.rotationOverLifetime = {
-      separateAxes: rotationOverLifetime.separateAxes,
-      asRotation: rotationOverLifetime.asRotation,
-      z: ensureNumberExpression(rotationOverLifetime.separateAxes ? rotationOverLifetime.z : rotationOverLifetime.angularVelocity),
-    };
-    if (rotationOverLifetime.separateAxes) {
-      ret.rotationOverLifetime.y = ensureFixedNumber(rotationOverLifetime.y);
-      ret.rotationOverLifetime.x = ensureFixedNumber(rotationOverLifetime.x);
-    }
-  }
-  const colorOverLifetime = particle.colorOverLifetime;
-
-  if (colorOverLifetime) {
-    const col: ColorOverLifetime = ret.colorOverLifetime = {
-      opacity: ensureFixedNumber(colorOverLifetime.opacity),
-    };
-
-    if (colorOverLifetime.color) {
-      col.color = getGradientColor(colorOverLifetime.color);
-    }
-  }
-  const textureSheetAnimation = particle.textureSheetAnimation;
-
-  if (textureSheetAnimation) {
-    ret.textureSheetAnimation = {
-      row: textureSheetAnimation.row,
-      col: textureSheetAnimation.col,
-      total: textureSheetAnimation.total,
-      animate: textureSheetAnimation.animate,
-      cycles: ensureFixedNumber(textureSheetAnimation.cycles)!,
-      animationDelay: ensureFixedNumberWithRandom(textureSheetAnimation.animationDelay, 0),
-      animationDuration: ensureFixedNumberWithRandom(textureSheetAnimation.animationDuration, 0)!,
-    };
-  }
-  const trials = particle.trails;
-
-  if (trials) {
-    ret.trails = {
-      lifetime: ensureNumberExpression(trials.lifetime)!,
-      dieWithParticles: trials.dieWithParticles,
-      maxPointPerTrail: trials.maxPointPerTrail,
-      minimumVertexDistance: trials.minimumVertexDistance,
-      widthOverTrail: ensureFixedNumber(trials.widthOverTrail)!,
-      colorOverTrail: trials.colorOverTrail && getGradientColor(trials.colorOverTrail, false),
-      blending: trials.blending,
-      colorOverLifetime: trials.colorOverLifetime && getGradientColor(trials.colorOverLifetime, false),
-      inheritParticleColor: trials.inheritParticleColor,
-      occlusion: trials.occlusion,
-      transparentOcclusion: trials.transparentOcclusion,
-      orderOffset: trials.orderOffset,
-      sizeAffectsLifetime: trials.sizeAffectsLifetime,
-      sizeAffectsWidth: trials.sizeAffectsWidth,
-      texture: trials.texture,
-      parentAffectsPosition: trials.parentAffectsPosition,
-      opacityOverLifetime: ensureNumberExpression(trials.opacityOverLifetime),
-    };
-  }
-  ret.trails && deleteEmptyValue(ret.trails);
-  const interaction = particle.interaction;
-
-  if (interaction) {
-    ret.interaction = {
-      behavior: interaction.behavior,
-      radius: interaction.radius,
-      multiple: interaction.multiple,
-    };
-  }
-
-  return ret;
-}
diff --git a/fallback/sprite.ts b/fallback/sprite.ts
deleted file mode 100644
index c905728..0000000
--- a/fallback/sprite.ts
+++ /dev/null
@@ -1,120 +0,0 @@
-import type {
-  BaseItemTransform,
-  NullContent,
-  PositionOverLifetime,
-  RotationOverLifetime,
-  ColorOverLifetime,
-  SpriteContent,
-} from '../src';
-import {
-  deleteEmptyValue,
-  ensureFixedNumber,
-  ensureFixedVec3,
-  ensureRGBAValue,
-  getGradientColor,
-} from './utils';
-
-export function getStandardNullContent (sprite: any, transform: BaseItemTransform): NullContent {
-  const opt = sprite.options;
-  const velocityOverLifetime = sprite.velocityOverLifetime || {};
-  const positionOverLifetime: PositionOverLifetime = {
-    path: ensureFixedVec3(sprite.transform?.path),
-    gravity: opt.gravity,
-    gravityOverLifetime: ensureFixedNumber(opt.gravityModifier),
-    direction: opt.direction,
-    startSpeed: opt.startSpeed,
-    asMovement: velocityOverLifetime.asMovement,
-    linearX: ensureFixedNumber(velocityOverLifetime.linearX),
-    linearY: ensureFixedNumber(velocityOverLifetime.linearY),
-    linearZ: ensureFixedNumber(velocityOverLifetime.linearZ),
-    asRotation: velocityOverLifetime.asRotation,
-    orbCenter: velocityOverLifetime.orbCenter,
-    orbitalX: ensureFixedNumber(velocityOverLifetime.orbitalX),
-    orbitalY: ensureFixedNumber(velocityOverLifetime.orbitalY),
-    orbitalZ: ensureFixedNumber(velocityOverLifetime.orbitalZ),
-    speedOverLifetime: ensureFixedNumber(velocityOverLifetime.speedOverLifetime),
-  };
-
-  deleteEmptyValue(positionOverLifetime);
-  const ret: NullContent = {
-    options: {
-      startColor: ensureRGBAValue(opt.startColor),
-    },
-    positionOverLifetime,
-  };
-
-  if (opt.startSize) {
-    transform.scale = [opt.startSize, opt.startSize / (opt.sizeAspect || 1), 1];
-  }
-  if (opt.startRotation) {
-    if (!transform.rotation) {
-      transform.rotation = [0, 0, opt.startRotation];
-    } else {
-      transform.rotation[2] += opt.startRotation;
-    }
-  }
-  const rotationOverLifetime = sprite.rotationOverLifetime;
-
-  if (rotationOverLifetime) {
-    const rot: RotationOverLifetime = ret.rotationOverLifetime = {
-      separateAxes: rotationOverLifetime.separateAxes,
-      asRotation: rotationOverLifetime.asRotation,
-    };
-
-    if (rot.separateAxes) {
-      rot.x = ensureFixedNumber(rotationOverLifetime.x);
-      rot.y = ensureFixedNumber(rotationOverLifetime.y);
-      rot.z = ensureFixedNumber(rotationOverLifetime.z);
-    } else {
-      rot.z = ensureFixedNumber(rotationOverLifetime.angularVelocity);
-    }
-  }
-
-  const colorOverLifetime = sprite.colorOverLifetime;
-
-  if (colorOverLifetime) {
-    const col: ColorOverLifetime = ret.colorOverLifetime = {
-      opacity: ensureFixedNumber(colorOverLifetime.opacity),
-    };
-
-    if (colorOverLifetime.color) {
-      col.color = getGradientColor(colorOverLifetime.color);
-    }
-  }
-  const sizeOverLifetime = sprite.sizeOverLifetime;
-
-  if (sizeOverLifetime) {
-    ret.sizeOverLifetime = {
-      separateAxes: sizeOverLifetime.separateAxes,
-      size: ensureFixedNumber(sizeOverLifetime.size),
-      x: ensureFixedNumber(sizeOverLifetime.x),
-      y: ensureFixedNumber(sizeOverLifetime.y),
-      z: ensureFixedNumber(sizeOverLifetime.z),
-    };
-  }
-
-  return ret;
-}
-
-export function getStandardSpriteContent (sprite: any, transform: BaseItemTransform): SpriteContent {
-  const ret = getStandardNullContent(sprite, transform) as SpriteContent;
-  const texAni = sprite.textureSheetAnimation;
-
-  if (texAni) {
-    ret.textureSheetAnimation = {
-      row: texAni.row,
-      col: texAni.col,
-      total: texAni.total || undefined,
-      animate: texAni.animate,
-    };
-  }
-  ret.renderer = sprite.renderer;
-  if (sprite.splits) {
-    ret.splits = sprite.splits;
-  }
-  if (sprite.interaction) {
-    ret.interaction = sprite.interaction;
-  }
-
-  return ret;
-}
diff --git a/fallback/utils.ts b/fallback/utils.ts
deleted file mode 100644
index dfa300c..0000000
--- a/fallback/utils.ts
+++ /dev/null
@@ -1,387 +0,0 @@
-import uuidV4 from 'uuid/dist/esm-browser/v4';
-import type {
-  FixedNumberExpression, RGBAColorValue, ColorExpression, NumberExpression, GradientColor,
-  GradientStop, FixedVec3Expression, vec4, vec3, BezierKeyframeValue,
-  vec2,
-} from '../src';
-import { BezierKeyframeType, ValueType, ParticleOrigin } from '../src';
-
-export function arrAdd<T> (arr: T[], item: T): boolean | undefined {
-  if (!arr.includes(item)) {
-    arr.push(item);
-
-    return true;
-  }
-}
-
-/**
- * @deprecated 请直接使用 Array.prototype.forEach 或 for...of
- * @param object
- * @param callback
- * @returns the mutated input object
- */
-export function forEach<T> (object: null | undefined | { [key: string]: T | Record<any, T> }, callback: (val: T, key: string) => void, thisObj?: any) {
-  if (object) {
-    for (const name in object) {
-      if (Object.hasOwnProperty.call(object, name)) {
-        callback.call(thisObj, object[name] as T, name);
-      }
-    }
-  }
-
-  return object;
-}
-
-export function ensureFixedNumber (a: any): FixedNumberExpression | undefined {
-  if (Number.isFinite(a)) {
-    return [ValueType.CONSTANT, a];
-  }
-  if (a) {
-    const valueType = a[0];
-    const valueData = a[1];
-
-    if (Array.isArray(valueType)) {
-      // 没有数据类型的数据
-      return;
-    }
-
-    if (valueType === 'static' || valueType === ValueType.CONSTANT) {
-      return [ValueType.CONSTANT, a[1]];
-    }
-    if (valueType === 'lines') {
-      return [ValueType.LINE, a[1]];
-    }
-    if (valueType === ValueType.LINE) {
-      // @ts-expect-error
-      const keyframes: LineKeyframeValue[] = valueData.map(data => [BezierKeyframeType.LINE, data]);
-
-      return [ValueType.BEZIER_CURVE, keyframes];
-    }
-    if (valueType === 'curve' || valueType === ValueType.CURVE) {
-      return [ValueType.BEZIER_CURVE, getBezierCurveFromHermiteInGE(valueData)];
-    }
-
-    return a;
-  }
-}
-
-export function ensureFixedNumberWithRandom (a: any, p: number): FixedNumberExpression | undefined {
-  if (Array.isArray(a) && a[0] === 'random') {
-    return [ValueType.CONSTANT, a[1][p]];
-  }
-
-  return ensureFixedNumber(a);
-}
-
-export function ensureRGBAValue (a: any): RGBAColorValue {
-  if (a && a[0] === 'color') {
-    return colorToArr(a[1], true);
-  }
-
-  return [1, 1, 1, 1];
-}
-
-export function ensureColorExpression (a: any, normalized?: boolean): ColorExpression | undefined {
-  if (a) {
-    if (a[0] === 'colors') {
-      return [ValueType.COLORS, a[1].map((color: any) => colorToArr(color, normalized))];
-    } else if (a[0] === 'gradient') {
-      return ensureGradient(a[1], normalized);
-    } else if (a[0] === 'color') {
-      return [ValueType.RGBA_COLOR, colorToArr(a[1], normalized)];
-    }
-
-    return a;
-  }
-}
-
-export function ensureNumberExpression (a: any): NumberExpression | undefined {
-  if (a && a[0] === 'random') {
-    return [ValueType.RANDOM, a[1]];
-  }
-
-  return ensureFixedNumber(a);
-}
-
-export function ensureValueGetter (a: any): NumberExpression | any {
-  if (Array.isArray(a) && typeof a[0] === 'string') {
-    return ensureNumberExpression(a) || ensureFixedVec3(a) || ensureColorExpression(a) || a;
-  }
-
-  return a;
-}
-
-export function ensureGradient (a: any, normalized?: boolean): GradientColor | undefined {
-  if (a) {
-    let stops: GradientStop[] = [];
-
-    Object.getOwnPropertyNames(a).forEach(p => {
-      const stop = parsePercent(p);
-      const color = colorToArr(a[p], normalized);
-
-      stops.push([stop, color[0], color[1], color[2], color[3]]);
-    });
-    stops = stops.sort((a, b) => a[0] - b[0]);
-
-    return [ValueType.GRADIENT_COLOR, stops];
-  }
-}
-
-export function colorToArr (hex: string | number[], normalized?: boolean): vec4 {
-  let ret: vec4;
-
-  if (typeof hex === 'string') {
-    hex = hex.replace(/[\s\t\r\n]/g, '');
-    let m = /rgba?\(([.\d]+),([.\d]+),([.\d]+),?([.\d]+)?\)/.exec(hex);
-
-    if (m) {
-      const a = +m[4];
-
-      ret = [+m[1], +m[2], +m[3], isNaN(a) ? 255 : Math.round(a * 255)];
-    } else if (/^#[a-f\d]{3}$/i.test(hex)) {
-      ret = [parseInt(hex[1] + hex[1], 16), parseInt(hex[2] + hex[2], 16), parseInt(hex[3] + hex[3], 16), 255];
-      // eslint-disable-next-line no-cond-assign
-    } else if (m = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)) {
-      ret = [parseInt(m[1], 16), parseInt(m[2], 16), parseInt(m[3], 16), 255] || [0, 0, 0, 255];
-    }
-  } else if (hex instanceof Array) {
-    ret = [hex[0], hex[1], hex[2], isNaN(hex[3]) ? 255 : Math.round(hex[3] * 255)];
-  }
-
-  if (normalized) {
-    // @ts-expect-error
-    ret = normalizeColor(ret) as unknown as vec4;
-  }
-
-  // @ts-expect-error
-  return ret;
-}
-
-export function normalizeColor (a: number[]): number[] | undefined {
-  if (Array.isArray(a)) {
-    return a.map(i => Number.isFinite(i / 255) ? Number((i / 255).toFixed(6)) : 0);
-  }
-}
-
-export function parsePercent (c: string): number {
-  const match = /^(-)?([\d+.]+)%$/.exec(c);
-
-  if (match) {
-    return +match[2] / 100 * (match[1] ? -1 : 1);
-  }
-
-  return +c;
-}
-
-export function getGradientColor (color: string | Array<string | number[]> | GradientColor, normalized?: boolean): GradientColor | undefined {
-  if (Array.isArray(color)) {
-    if (color[0] === ValueType.GRADIENT_COLOR) {
-      return color as GradientColor;
-    }
-
-    // @ts-expect-error
-    return (color[0] === 'gradient' || color[0] === 'color') && ensureGradient(color[1], normalized);
-  } else {
-    return ensureGradient(color, normalized);
-  }
-}
-
-export function ensureFixedVec3 (a: any): FixedVec3Expression | undefined {
-  if (a) {
-    if (a.length === 3) {
-      return [ValueType.CONSTANT_VEC3, a];
-    }
-    const valueType = a[0];
-
-    if (
-      valueType === 'path' ||
-      valueType === 'bezier' ||
-      valueType === ValueType.BEZIER_PATH ||
-      valueType === ValueType.LINEAR_PATH
-    ) {
-      const valueData = a[1];
-      const easing = valueData[0];
-      const points = valueData[1];
-      let controlPoints = valueData[2];
-      const bezierEasing = getBezierCurveFromHermiteInGE(easing);
-
-      // linear path没有controlPoints
-      if (!controlPoints) {
-        controlPoints = [];
-        for (let keyframeIndex = 0; keyframeIndex < points.length; keyframeIndex++) {
-          const point = points[keyframeIndex].slice();
-
-          if (keyframeIndex === 0) {
-            controlPoints.push(point);
-          } else if (keyframeIndex < points.length - 1) {
-            controlPoints.push(point);
-            controlPoints.push(point);
-          } else {
-            controlPoints.push(point);
-          }
-        }
-      }
-
-      return [ValueType.BEZIER_CURVE_PATH, [bezierEasing, points, controlPoints]];
-    }
-
-    return a;
-  }
-}
-
-export function objectValueToNumber (o: Record<string, any>): object {
-  for (const key of Object.keys(o)) {
-    o[key] = Number(o[key]);
-  }
-
-  return o;
-}
-
-export function deleteEmptyValue (o: Record<string, any>): object {
-  for (const key of Object.keys(o)) {
-    if (o[key] === undefined) {
-      delete o[key];
-    }
-  }
-
-  return o;
-}
-
-const cos = Math.cos;
-const sin = Math.sin;
-const d2r = Math.PI / 180;
-const r2d = 180 / Math.PI;
-
-export function quatFromXYZRotation (out: vec4 | number[], x: number, y: number, z: number): vec4 {
-  const c1 = cos((x * d2r) / 2);
-  const c2 = cos((y * d2r) / 2);
-  const c3 = cos((z * d2r) / 2);
-
-  const s1 = sin((x * d2r) / 2);
-  const s2 = sin((y * d2r) / 2);
-  const s3 = sin((z * d2r) / 2);
-
-  out[0] = s1 * c2 * c3 + c1 * s2 * s3;
-  out[1] = c1 * s2 * c3 - s1 * c2 * s3;
-  out[2] = c1 * c2 * s3 + s1 * s2 * c3;
-  out[3] = c1 * c2 * c3 - s1 * s2 * s3;
-
-  return out as vec4;
-}
-
-function clamp (v: number, min: number, max: number): number {
-  return v > max ? max : (v < min ? min : v);
-}
-
-export function rotationZYXFromQuat (out: vec3 | number[], quat: vec4): vec3 {
-  const x = quat[0];
-  const y = quat[1];
-  const z = quat[2];
-  const w = quat[3];
-  const x2 = x + x;
-  const y2 = y + y;
-  const z2 = z + z;
-  const xx = x * x2;
-  const yx = y * x2;
-  const yy = y * y2;
-  const zx = z * x2;
-  const zy = z * y2;
-  const zz = z * z2;
-  const wx = w * x2;
-  const wy = w * y2;
-  const wz = w * z2;
-  const m11 = 1 - yy - zz, m12 = yx - wz, m13 = zx + wy;
-  const m21 = yx + wz, m22 = 1 - xx - zz, m23 = zy - wx;
-  const m31 = zx - wy, m32 = zy + wx, m33 = 1 - xx - yy;
-
-  out[1] = Math.asin(clamp(-m31, -1, 1)) * r2d;
-  if (Math.abs(m31) < 0.9999999) {
-    out[0] = Math.atan2(m32, m33) * r2d;
-    out[2] = Math.atan2(m21, m11) * r2d;
-  } else {
-    out[0] = 0;
-    out[2] = Math.atan2(-m12, m22) * r2d;
-  }
-
-  return out as vec3;
-}
-
-export function generateGUID (): string {
-  return uuidV4().replace(/-/g, '');
-}
-
-/**
- * 提取并转换 JSON 数据中的 anchor 值
- */
-export function convertAnchor (anchor?: vec2, particleOrigin?: ParticleOrigin): vec2 {
-  if (anchor) {
-    return [anchor[0] - 0.5, 0.5 - anchor[1]];
-  } else if (particleOrigin) {
-    return particleOriginTranslateMap[particleOrigin];
-  } else {
-    return [0, 0];
-  }
-}
-
-export const particleOriginTranslateMap: Record<number, vec2> = {
-  [ParticleOrigin.PARTICLE_ORIGIN_CENTER]: [0, 0],
-  [ParticleOrigin.PARTICLE_ORIGIN_CENTER_BOTTOM]: [0, -0.5],
-  [ParticleOrigin.PARTICLE_ORIGIN_CENTER_TOP]: [0, 0.5],
-  [ParticleOrigin.PARTICLE_ORIGIN_LEFT_TOP]: [-0.5, 0.5],
-  [ParticleOrigin.PARTICLE_ORIGIN_LEFT_CENTER]: [-0.5, 0],
-  [ParticleOrigin.PARTICLE_ORIGIN_LEFT_BOTTOM]: [-0.5, -0.5],
-  [ParticleOrigin.PARTICLE_ORIGIN_RIGHT_CENTER]: [0.5, 0],
-  [ParticleOrigin.PARTICLE_ORIGIN_RIGHT_BOTTOM]: [0.5, -0.5],
-  [ParticleOrigin.PARTICLE_ORIGIN_RIGHT_TOP]: [0.5, 0.5],
-};
-function getBezierCurveFromHermite (m0: number, m1: number, p0: number[], p3: number[]) {
-  const xStart = p0[0];
-  const yStart = p0[1];
-  const xEnd = p3[0];
-  const yEnd = p3[1];
-  const dt = xEnd - xStart;
-
-  m0 = m0 * dt;
-  m1 = m1 * dt;
-  const bezierControlPoints = [[xStart + (xEnd - xStart) / 3, yStart + m0 / 3], [xEnd - (xEnd - xStart) / 3, yEnd - m1 / 3]];
-
-  return bezierControlPoints;
-}
-
-export function getBezierCurveFromHermiteInGE (geHermiteCurves: number[][]): BezierKeyframeValue[] {
-  let ymax = -1000000;
-  let ymin = 1000000;
-
-  for (let i = 0; i < geHermiteCurves.length; i++) {
-    ymax = Math.max(ymax, geHermiteCurves[i][1]);
-    ymin = Math.min(ymin, geHermiteCurves[i][1]);
-  }
-  const geBezierCurves = [[geHermiteCurves[0][0], geHermiteCurves[0][1]]];
-
-  for (let i = 0; i < geHermiteCurves.length - 1; i++) {
-    const m0 = geHermiteCurves[i][3] * (ymax - ymin);
-    const m1 = geHermiteCurves[i + 1][2] * (ymax - ymin);
-    const p0 = [geHermiteCurves[i][0], geHermiteCurves[i][1]];
-    const p3 = [geHermiteCurves[i + 1][0], geHermiteCurves[i + 1][1]];
-
-    if (p0[0] != p3[0]) {
-      const bezierControlPoints = getBezierCurveFromHermite(m0, m1, p0, p3);
-      const p1 = bezierControlPoints[0];
-      const p2 = bezierControlPoints[1];
-
-      geBezierCurves[geBezierCurves.length - 1].push(p1[0]);
-      geBezierCurves[geBezierCurves.length - 1].push(p1[1]);
-      geBezierCurves.push([p2[0], p2[1], p3[0], p3[1]]);
-    } else {
-      geBezierCurves[geBezierCurves.length - 1].push(p3[0]);
-      geBezierCurves[geBezierCurves.length - 1].push(p3[1]);
-    }
-  }
-
-  // 添加关键帧类型
-  return geBezierCurves.map((curve, index) => {
-    return index === 0 ? [BezierKeyframeType.EASE_OUT, curve as [number, number, number, number]]
-      : index === geBezierCurves.length - 1 ? [BezierKeyframeType.EASE_IN, curve as [number, number, number, number]]
-        : [BezierKeyframeType.EASE, curve as [number, number, number, number, number, number]];
-  });
-}
diff --git a/package-lock.json b/package-lock.json
deleted file mode 100644
index c8ade41..0000000
--- a/package-lock.json
+++ /dev/null
@@ -1,4750 +0,0 @@
-{
-  "name": "@galacean/effects-specification",
-  "version": "1.2.0",
-  "lockfileVersion": 3,
-  "requires": true,
-  "packages": {
-    "": {
-      "name": "@galacean/effects-specification",
-      "version": "1.2.0",
-      "license": "MIT",
-      "devDependencies": {
-        "@commitlint/cli": "^19.2.2",
-        "@commitlint/config-conventional": "^13.2.0",
-        "@rollup/plugin-commonjs": "^21.0.3",
-        "@rollup/plugin-node-resolve": "^13.1.3",
-        "@rollup/plugin-typescript": "^8.3.1",
-        "@types/chai": "^4.3.0",
-        "@types/chai-spies": "^1.0.0",
-        "@types/mocha": "^10.0.1",
-        "@types/node": "^17.0.21",
-        "@typescript-eslint/eslint-plugin": "^5.26.0",
-        "@typescript-eslint/parser": "^5.26.0",
-        "chai": "^4.3.6",
-        "chai-spies": "^1.0.0",
-        "eslint": "^8.13.0",
-        "eslint-plugin-compat": "^4.2.0",
-        "eslint-plugin-promise": "^6.1.1",
-        "husky": "^7.0.4",
-        "lint-staged": "^11.2.6",
-        "mocha": "^10.2.0",
-        "rimraf": "^3.0.2",
-        "rollup": "^2.70.1",
-        "rollup-plugin-livereload": "^2.0.5",
-        "rollup-plugin-serve": "^1.1.0",
-        "typescript": "^4.6.2",
-        "uuid": "9.0.1"
-      }
-    },
-    "node_modules/@aashutoshrathi/word-wrap": {
-      "version": "1.2.6",
-      "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
-      "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/@babel/code-frame": {
-      "version": "7.22.13",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
-      "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
-      "dev": true,
-      "dependencies": {
-        "@babel/highlight": "^7.22.13",
-        "chalk": "^2.4.2"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "dev": true
-    },
-    "node_modules/@babel/code-frame/node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/code-frame/node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/helper-validator-identifier": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
-      "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
-      "dev": true,
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/highlight": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
-      "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/helper-validator-identifier": "^7.22.20",
-        "chalk": "^2.4.2",
-        "js-tokens": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6.9.0"
-      }
-    },
-    "node_modules/@babel/highlight/node_modules/ansi-styles": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
-      "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^1.9.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/highlight/node_modules/chalk": {
-      "version": "2.4.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
-      "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^3.2.1",
-        "escape-string-regexp": "^1.0.5",
-        "supports-color": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/highlight/node_modules/color-convert": {
-      "version": "1.9.3",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
-      "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "1.1.3"
-      }
-    },
-    "node_modules/@babel/highlight/node_modules/color-name": {
-      "version": "1.1.3",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
-      "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
-      "dev": true
-    },
-    "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
-      "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.0"
-      }
-    },
-    "node_modules/@babel/highlight/node_modules/has-flag": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
-      "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@babel/highlight/node_modules/supports-color": {
-      "version": "5.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-      "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/@commitlint/cli": {
-      "version": "19.2.2",
-      "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-19.2.2.tgz",
-      "integrity": "sha512-P8cbOHfg2PQRzfICLSrzUVOCVMqjEZ8Hlth6mtJ4yOEjT47Q5PbIGymgX3rLVylNw+3IAT2Djn9IJ2wHbXFzBg==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/format": "^19.0.3",
-        "@commitlint/lint": "^19.2.2",
-        "@commitlint/load": "^19.2.0",
-        "@commitlint/read": "^19.2.1",
-        "@commitlint/types": "^19.0.3",
-        "execa": "^8.0.1",
-        "yargs": "^17.0.0"
-      },
-      "bin": {
-        "commitlint": "cli.js"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/execa": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
-      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^7.0.3",
-        "get-stream": "^8.0.1",
-        "human-signals": "^5.0.0",
-        "is-stream": "^3.0.0",
-        "merge-stream": "^2.0.0",
-        "npm-run-path": "^5.1.0",
-        "onetime": "^6.0.0",
-        "signal-exit": "^4.1.0",
-        "strip-final-newline": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=16.17"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/execa?sponsor=1"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/get-stream": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
-      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
-      "dev": true,
-      "engines": {
-        "node": ">=16"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/human-signals": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
-      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=16.17.0"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/is-stream": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
-      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
-      "dev": true,
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/mimic-fn": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
-      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/npm-run-path": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
-      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^4.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/onetime": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
-      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/path-key": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
-      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/signal-exit": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-      "dev": true,
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/@commitlint/cli/node_modules/strip-final-newline": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
-      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/config-conventional": {
-      "version": "13.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-13.2.0.tgz",
-      "integrity": "sha512-7u7DdOiF+3qSdDlbQGfpvCH8DCQdLFvnI2+VucYmmV7E92iD6t9PBj+UjIoSQCaMAzYp27Vkall78AkcXBh6Xw==",
-      "dev": true,
-      "dependencies": {
-        "conventional-changelog-conventionalcommits": "^4.3.1"
-      },
-      "engines": {
-        "node": ">=v12"
-      }
-    },
-    "node_modules/@commitlint/config-validator": {
-      "version": "19.0.3",
-      "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz",
-      "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/types": "^19.0.3",
-        "ajv": "^8.11.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/config-validator/node_modules/ajv": {
-      "version": "8.12.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
-      "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "json-schema-traverse": "^1.0.0",
-        "require-from-string": "^2.0.2",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/@commitlint/config-validator/node_modules/json-schema-traverse": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
-      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
-      "dev": true
-    },
-    "node_modules/@commitlint/ensure": {
-      "version": "19.0.3",
-      "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-19.0.3.tgz",
-      "integrity": "sha512-SZEpa/VvBLoT+EFZVb91YWbmaZ/9rPH3ESrINOl0HD2kMYsjvl0tF7nMHh0EpTcv4+gTtZBAe1y/SS6/OhfZzQ==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/types": "^19.0.3",
-        "lodash.camelcase": "^4.3.0",
-        "lodash.kebabcase": "^4.1.1",
-        "lodash.snakecase": "^4.1.1",
-        "lodash.startcase": "^4.4.0",
-        "lodash.upperfirst": "^4.3.1"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/execute-rule": {
-      "version": "19.0.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz",
-      "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==",
-      "dev": true,
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/format": {
-      "version": "19.0.3",
-      "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-19.0.3.tgz",
-      "integrity": "sha512-QjjyGyoiVWzx1f5xOteKHNLFyhyweVifMgopozSgx1fGNrGV8+wp7k6n1t6StHdJ6maQJ+UUtO2TcEiBFRyR6Q==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/types": "^19.0.3",
-        "chalk": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/format/node_modules/chalk": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
-      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
-      "dev": true,
-      "engines": {
-        "node": "^12.17.0 || ^14.13 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@commitlint/is-ignored": {
-      "version": "19.2.2",
-      "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-19.2.2.tgz",
-      "integrity": "sha512-eNX54oXMVxncORywF4ZPFtJoBm3Tvp111tg1xf4zWXGfhBPKpfKG6R+G3G4v5CPlRROXpAOpQ3HMhA9n1Tck1g==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/types": "^19.0.3",
-        "semver": "^7.6.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/lint": {
-      "version": "19.2.2",
-      "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-19.2.2.tgz",
-      "integrity": "sha512-xrzMmz4JqwGyKQKTpFzlN0dx0TAiT7Ran1fqEBgEmEj+PU98crOFtysJgY+QdeSagx6EDRigQIXJVnfrI0ratA==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/is-ignored": "^19.2.2",
-        "@commitlint/parse": "^19.0.3",
-        "@commitlint/rules": "^19.0.3",
-        "@commitlint/types": "^19.0.3"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/load": {
-      "version": "19.2.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.2.0.tgz",
-      "integrity": "sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/config-validator": "^19.0.3",
-        "@commitlint/execute-rule": "^19.0.0",
-        "@commitlint/resolve-extends": "^19.1.0",
-        "@commitlint/types": "^19.0.3",
-        "chalk": "^5.3.0",
-        "cosmiconfig": "^9.0.0",
-        "cosmiconfig-typescript-loader": "^5.0.0",
-        "lodash.isplainobject": "^4.0.6",
-        "lodash.merge": "^4.6.2",
-        "lodash.uniq": "^4.5.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/load/node_modules/chalk": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
-      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
-      "dev": true,
-      "engines": {
-        "node": "^12.17.0 || ^14.13 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@commitlint/load/node_modules/cosmiconfig": {
-      "version": "9.0.0",
-      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz",
-      "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==",
-      "dev": true,
-      "dependencies": {
-        "env-paths": "^2.2.1",
-        "import-fresh": "^3.3.0",
-        "js-yaml": "^4.1.0",
-        "parse-json": "^5.2.0"
-      },
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/d-fischer"
-      },
-      "peerDependencies": {
-        "typescript": ">=4.9.5"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@commitlint/load/node_modules/cosmiconfig-typescript-loader": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz",
-      "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==",
-      "dev": true,
-      "dependencies": {
-        "jiti": "^1.19.1"
-      },
-      "engines": {
-        "node": ">=v16"
-      },
-      "peerDependencies": {
-        "@types/node": "*",
-        "cosmiconfig": ">=8.2",
-        "typescript": ">=4"
-      }
-    },
-    "node_modules/@commitlint/message": {
-      "version": "19.0.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-19.0.0.tgz",
-      "integrity": "sha512-c9czf6lU+9oF9gVVa2lmKaOARJvt4soRsVmbR7Njwp9FpbBgste5i7l/2l5o8MmbwGh4yE1snfnsy2qyA2r/Fw==",
-      "dev": true,
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/parse": {
-      "version": "19.0.3",
-      "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-19.0.3.tgz",
-      "integrity": "sha512-Il+tNyOb8VDxN3P6XoBBwWJtKKGzHlitEuXA5BP6ir/3loWlsSqDr5aecl6hZcC/spjq4pHqNh0qPlfeWu38QA==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/types": "^19.0.3",
-        "conventional-changelog-angular": "^7.0.0",
-        "conventional-commits-parser": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/read": {
-      "version": "19.2.1",
-      "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-19.2.1.tgz",
-      "integrity": "sha512-qETc4+PL0EUv7Q36lJbPG+NJiBOGg7SSC7B5BsPWOmei+Dyif80ErfWQ0qXoW9oCh7GTpTNRoaVhiI8RbhuaNw==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/top-level": "^19.0.0",
-        "@commitlint/types": "^19.0.3",
-        "execa": "^8.0.1",
-        "git-raw-commits": "^4.0.0",
-        "minimist": "^1.2.8"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/execa": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
-      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^7.0.3",
-        "get-stream": "^8.0.1",
-        "human-signals": "^5.0.0",
-        "is-stream": "^3.0.0",
-        "merge-stream": "^2.0.0",
-        "npm-run-path": "^5.1.0",
-        "onetime": "^6.0.0",
-        "signal-exit": "^4.1.0",
-        "strip-final-newline": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=16.17"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/execa?sponsor=1"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/get-stream": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
-      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
-      "dev": true,
-      "engines": {
-        "node": ">=16"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/human-signals": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
-      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=16.17.0"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/is-stream": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
-      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
-      "dev": true,
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/mimic-fn": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
-      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/npm-run-path": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
-      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^4.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/onetime": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
-      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/path-key": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
-      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/signal-exit": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-      "dev": true,
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/@commitlint/read/node_modules/strip-final-newline": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
-      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/resolve-extends": {
-      "version": "19.1.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz",
-      "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/config-validator": "^19.0.3",
-        "@commitlint/types": "^19.0.3",
-        "global-directory": "^4.0.1",
-        "import-meta-resolve": "^4.0.0",
-        "lodash.mergewith": "^4.6.2",
-        "resolve-from": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/rules": {
-      "version": "19.0.3",
-      "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-19.0.3.tgz",
-      "integrity": "sha512-TspKb9VB6svklxNCKKwxhELn7qhtY1rFF8ls58DcFd0F97XoG07xugPjjbVnLqmMkRjZDbDIwBKt9bddOfLaPw==",
-      "dev": true,
-      "dependencies": {
-        "@commitlint/ensure": "^19.0.3",
-        "@commitlint/message": "^19.0.0",
-        "@commitlint/to-lines": "^19.0.0",
-        "@commitlint/types": "^19.0.3",
-        "execa": "^8.0.1"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/execa": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
-      "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^7.0.3",
-        "get-stream": "^8.0.1",
-        "human-signals": "^5.0.0",
-        "is-stream": "^3.0.0",
-        "merge-stream": "^2.0.0",
-        "npm-run-path": "^5.1.0",
-        "onetime": "^6.0.0",
-        "signal-exit": "^4.1.0",
-        "strip-final-newline": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=16.17"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/execa?sponsor=1"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/get-stream": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
-      "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
-      "dev": true,
-      "engines": {
-        "node": ">=16"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/human-signals": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
-      "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=16.17.0"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/is-stream": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
-      "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
-      "dev": true,
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/mimic-fn": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
-      "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/npm-run-path": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
-      "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^4.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/onetime": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
-      "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/path-key": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
-      "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/signal-exit": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
-      "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
-      "dev": true,
-      "engines": {
-        "node": ">=14"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/@commitlint/rules/node_modules/strip-final-newline": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
-      "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/to-lines": {
-      "version": "19.0.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-19.0.0.tgz",
-      "integrity": "sha512-vkxWo+VQU5wFhiP9Ub9Sre0FYe019JxFikrALVoD5UGa8/t3yOJEpEhxC5xKiENKKhUkTpEItMTRAjHw2SCpZw==",
-      "dev": true,
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/top-level": {
-      "version": "19.0.0",
-      "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-19.0.0.tgz",
-      "integrity": "sha512-KKjShd6u1aMGNkCkaX4aG1jOGdn7f8ZI8TR1VEuNqUOjWTOdcDSsmglinglJ18JTjuBX5I1PtjrhQCRcixRVFQ==",
-      "dev": true,
-      "dependencies": {
-        "find-up": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/top-level/node_modules/find-up": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-7.0.0.tgz",
-      "integrity": "sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==",
-      "dev": true,
-      "dependencies": {
-        "locate-path": "^7.2.0",
-        "path-exists": "^5.0.0",
-        "unicorn-magic": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/top-level/node_modules/locate-path": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
-      "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
-      "dev": true,
-      "dependencies": {
-        "p-locate": "^6.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/top-level/node_modules/p-limit": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
-      "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
-      "dev": true,
-      "dependencies": {
-        "yocto-queue": "^1.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/top-level/node_modules/p-locate": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
-      "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
-      "dev": true,
-      "dependencies": {
-        "p-limit": "^4.0.0"
-      },
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/top-level/node_modules/path-exists": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
-      "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
-      "dev": true,
-      "engines": {
-        "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
-      }
-    },
-    "node_modules/@commitlint/top-level/node_modules/yocto-queue": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
-      "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
-      "dev": true,
-      "engines": {
-        "node": ">=12.20"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/@commitlint/types": {
-      "version": "19.0.3",
-      "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz",
-      "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==",
-      "dev": true,
-      "dependencies": {
-        "@types/conventional-commits-parser": "^5.0.0",
-        "chalk": "^5.3.0"
-      },
-      "engines": {
-        "node": ">=v18"
-      }
-    },
-    "node_modules/@commitlint/types/node_modules/chalk": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
-      "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
-      "dev": true,
-      "engines": {
-        "node": "^12.17.0 || ^14.13 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/@eslint-community/eslint-utils": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
-      "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
-      "dev": true,
-      "dependencies": {
-        "eslint-visitor-keys": "^3.3.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "peerDependencies": {
-        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
-      }
-    },
-    "node_modules/@eslint-community/regexpp": {
-      "version": "4.10.0",
-      "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
-      "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
-      "dev": true,
-      "engines": {
-        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
-      }
-    },
-    "node_modules/@eslint/eslintrc": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.3.tgz",
-      "integrity": "sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==",
-      "dev": true,
-      "dependencies": {
-        "ajv": "^6.12.4",
-        "debug": "^4.3.2",
-        "espree": "^9.6.0",
-        "globals": "^13.19.0",
-        "ignore": "^5.2.0",
-        "import-fresh": "^3.2.1",
-        "js-yaml": "^4.1.0",
-        "minimatch": "^3.1.2",
-        "strip-json-comments": "^3.1.1"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/@eslint/js": {
-      "version": "8.54.0",
-      "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.54.0.tgz",
-      "integrity": "sha512-ut5V+D+fOoWPgGGNj83GGjnntO39xDy6DWxO0wb7Jp3DcMX0TfIqdzHF85VTQkerdyGmuuMD9AKAo5KiNlf/AQ==",
-      "dev": true,
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      }
-    },
-    "node_modules/@humanwhocodes/config-array": {
-      "version": "0.11.13",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz",
-      "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==",
-      "dev": true,
-      "dependencies": {
-        "@humanwhocodes/object-schema": "^2.0.1",
-        "debug": "^4.1.1",
-        "minimatch": "^3.0.5"
-      },
-      "engines": {
-        "node": ">=10.10.0"
-      }
-    },
-    "node_modules/@humanwhocodes/module-importer": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
-      "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
-      "dev": true,
-      "engines": {
-        "node": ">=12.22"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/nzakas"
-      }
-    },
-    "node_modules/@humanwhocodes/object-schema": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz",
-      "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==",
-      "dev": true
-    },
-    "node_modules/@mdn/browser-compat-data": {
-      "version": "5.5.6",
-      "resolved": "https://registry.npmmirror.com/@mdn/browser-compat-data/-/browser-compat-data-5.5.6.tgz",
-      "integrity": "sha512-dZgfsA1v8r+8QBPh7YqPaNz9KRlLi/iyac1/mwbaIV7yFrtW1qCkmzBJiJGsMhI1/JdayJvC81lVS/UEzHsgbA==",
-      "dev": true
-    },
-    "node_modules/@nodelib/fs.scandir": {
-      "version": "2.1.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
-      "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "2.0.5",
-        "run-parallel": "^1.1.9"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.stat": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
-      "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@nodelib/fs.walk": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
-      "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.scandir": "2.1.5",
-        "fastq": "^1.6.0"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/@rollup/plugin-commonjs": {
-      "version": "21.1.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-21.1.0.tgz",
-      "integrity": "sha512-6ZtHx3VHIp2ReNNDxHjuUml6ur+WcQ28N1yHgCQwsbNkQg2suhxGMDQGJOn/KuDxKtd1xuZP5xSTwBA4GQ8hbA==",
-      "dev": true,
-      "dependencies": {
-        "@rollup/pluginutils": "^3.1.0",
-        "commondir": "^1.0.1",
-        "estree-walker": "^2.0.1",
-        "glob": "^7.1.6",
-        "is-reference": "^1.2.1",
-        "magic-string": "^0.25.7",
-        "resolve": "^1.17.0"
-      },
-      "engines": {
-        "node": ">= 8.0.0"
-      },
-      "peerDependencies": {
-        "rollup": "^2.38.3"
-      }
-    },
-    "node_modules/@rollup/plugin-node-resolve": {
-      "version": "13.3.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz",
-      "integrity": "sha512-Lus8rbUo1eEcnS4yTFKLZrVumLPY+YayBdWXgFSHYhTT2iJbMhoaaBL3xl5NCdeRytErGr8tZ0L71BMRmnlwSw==",
-      "dev": true,
-      "dependencies": {
-        "@rollup/pluginutils": "^3.1.0",
-        "@types/resolve": "1.17.1",
-        "deepmerge": "^4.2.2",
-        "is-builtin-module": "^3.1.0",
-        "is-module": "^1.0.0",
-        "resolve": "^1.19.0"
-      },
-      "engines": {
-        "node": ">= 10.0.0"
-      },
-      "peerDependencies": {
-        "rollup": "^2.42.0"
-      }
-    },
-    "node_modules/@rollup/plugin-typescript": {
-      "version": "8.5.0",
-      "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.5.0.tgz",
-      "integrity": "sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==",
-      "dev": true,
-      "dependencies": {
-        "@rollup/pluginutils": "^3.1.0",
-        "resolve": "^1.17.0"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      },
-      "peerDependencies": {
-        "rollup": "^2.14.0",
-        "tslib": "*",
-        "typescript": ">=3.7.0"
-      },
-      "peerDependenciesMeta": {
-        "tslib": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@rollup/pluginutils": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz",
-      "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==",
-      "dev": true,
-      "dependencies": {
-        "@types/estree": "0.0.39",
-        "estree-walker": "^1.0.1",
-        "picomatch": "^2.2.2"
-      },
-      "engines": {
-        "node": ">= 8.0.0"
-      },
-      "peerDependencies": {
-        "rollup": "^1.20.0||^2.0.0"
-      }
-    },
-    "node_modules/@rollup/pluginutils/node_modules/estree-walker": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz",
-      "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==",
-      "dev": true
-    },
-    "node_modules/@types/chai": {
-      "version": "4.3.10",
-      "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.10.tgz",
-      "integrity": "sha512-of+ICnbqjmFCiixUnqRulbylyXQrPqIGf/B3Jax1wIF3DvSheysQxAWvqHhZiW3IQrycvokcLcFQlveGp+vyNg==",
-      "dev": true
-    },
-    "node_modules/@types/chai-spies": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/@types/chai-spies/-/chai-spies-1.0.6.tgz",
-      "integrity": "sha512-xkk4HmhBB9OQeTAifa9MJ+6R5/Rq9+ungDe4JidZD+vqZVeiWZwc2i7/pd1ZKjyGlSBIQePoWdyUyFUGT0rv5w==",
-      "dev": true,
-      "dependencies": {
-        "@types/chai": "*"
-      }
-    },
-    "node_modules/@types/conventional-commits-parser": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
-      "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/estree": {
-      "version": "0.0.39",
-      "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz",
-      "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==",
-      "dev": true
-    },
-    "node_modules/@types/json-schema": {
-      "version": "7.0.15",
-      "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
-      "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
-      "dev": true
-    },
-    "node_modules/@types/mocha": {
-      "version": "10.0.4",
-      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.4.tgz",
-      "integrity": "sha512-xKU7bUjiFTIttpWaIZ9qvgg+22O1nmbA+HRxdlR+u6TWsGfmFdXrheJoK4fFxrHNVIOBDvDNKZG+LYBpMHpX3w==",
-      "dev": true
-    },
-    "node_modules/@types/node": {
-      "version": "17.0.45",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz",
-      "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==",
-      "dev": true
-    },
-    "node_modules/@types/parse-json": {
-      "version": "4.0.2",
-      "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
-      "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
-      "dev": true
-    },
-    "node_modules/@types/resolve": {
-      "version": "1.17.1",
-      "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz",
-      "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==",
-      "dev": true,
-      "dependencies": {
-        "@types/node": "*"
-      }
-    },
-    "node_modules/@types/semver": {
-      "version": "7.5.5",
-      "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.5.tgz",
-      "integrity": "sha512-+d+WYC1BxJ6yVOgUgzK8gWvp5qF8ssV5r4nsDcZWKRWcDQLQ619tvWAxJQYGgBrO1MnLJC7a5GtiYsAoQ47dJg==",
-      "dev": true
-    },
-    "node_modules/@typescript-eslint/eslint-plugin": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
-      "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
-      "dev": true,
-      "dependencies": {
-        "@eslint-community/regexpp": "^4.4.0",
-        "@typescript-eslint/scope-manager": "5.62.0",
-        "@typescript-eslint/type-utils": "5.62.0",
-        "@typescript-eslint/utils": "5.62.0",
-        "debug": "^4.3.4",
-        "graphemer": "^1.4.0",
-        "ignore": "^5.2.0",
-        "natural-compare-lite": "^1.4.0",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "@typescript-eslint/parser": "^5.0.0",
-        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/parser": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
-      "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/scope-manager": "5.62.0",
-        "@typescript-eslint/types": "5.62.0",
-        "@typescript-eslint/typescript-estree": "5.62.0",
-        "debug": "^4.3.4"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/scope-manager": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
-      "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/types": "5.62.0",
-        "@typescript-eslint/visitor-keys": "5.62.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      }
-    },
-    "node_modules/@typescript-eslint/type-utils": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
-      "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/typescript-estree": "5.62.0",
-        "@typescript-eslint/utils": "5.62.0",
-        "debug": "^4.3.4",
-        "tsutils": "^3.21.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "eslint": "*"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/types": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
-      "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
-      "dev": true,
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      }
-    },
-    "node_modules/@typescript-eslint/typescript-estree": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
-      "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/types": "5.62.0",
-        "@typescript-eslint/visitor-keys": "5.62.0",
-        "debug": "^4.3.4",
-        "globby": "^11.1.0",
-        "is-glob": "^4.0.3",
-        "semver": "^7.3.7",
-        "tsutils": "^3.21.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependenciesMeta": {
-        "typescript": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/@typescript-eslint/utils": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
-      "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
-      "dev": true,
-      "dependencies": {
-        "@eslint-community/eslint-utils": "^4.2.0",
-        "@types/json-schema": "^7.0.9",
-        "@types/semver": "^7.3.12",
-        "@typescript-eslint/scope-manager": "5.62.0",
-        "@typescript-eslint/types": "5.62.0",
-        "@typescript-eslint/typescript-estree": "5.62.0",
-        "eslint-scope": "^5.1.1",
-        "semver": "^7.3.7"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      },
-      "peerDependencies": {
-        "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
-      }
-    },
-    "node_modules/@typescript-eslint/visitor-keys": {
-      "version": "5.62.0",
-      "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
-      "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
-      "dev": true,
-      "dependencies": {
-        "@typescript-eslint/types": "5.62.0",
-        "eslint-visitor-keys": "^3.3.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/typescript-eslint"
-      }
-    },
-    "node_modules/@ungap/structured-clone": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
-      "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
-      "dev": true
-    },
-    "node_modules/acorn": {
-      "version": "8.11.2",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
-      "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==",
-      "dev": true,
-      "bin": {
-        "acorn": "bin/acorn"
-      },
-      "engines": {
-        "node": ">=0.4.0"
-      }
-    },
-    "node_modules/acorn-jsx": {
-      "version": "5.3.2",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
-      "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
-      "dev": true,
-      "peerDependencies": {
-        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
-      }
-    },
-    "node_modules/aggregate-error": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
-      "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
-      "dev": true,
-      "dependencies": {
-        "clean-stack": "^2.0.0",
-        "indent-string": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ajv": {
-      "version": "6.12.6",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
-      "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
-      "dev": true,
-      "dependencies": {
-        "fast-deep-equal": "^3.1.1",
-        "fast-json-stable-stringify": "^2.0.0",
-        "json-schema-traverse": "^0.4.1",
-        "uri-js": "^4.2.2"
-      },
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/epoberezkin"
-      }
-    },
-    "node_modules/ansi-colors": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
-      "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/ansi-escapes": {
-      "version": "4.3.2",
-      "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
-      "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
-      "dev": true,
-      "dependencies": {
-        "type-fest": "^0.21.3"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ansi-escapes/node_modules/type-fest": {
-      "version": "0.21.3",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
-      "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/ansi-regex": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-      "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/ansi-styles": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
-      "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
-      "dev": true,
-      "dependencies": {
-        "color-convert": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
-      }
-    },
-    "node_modules/anymatch": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
-      "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
-      "dev": true,
-      "dependencies": {
-        "normalize-path": "^3.0.0",
-        "picomatch": "^2.0.4"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/argparse": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
-      "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
-      "dev": true
-    },
-    "node_modules/array-ify": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz",
-      "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==",
-      "dev": true
-    },
-    "node_modules/array-union": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
-      "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/assertion-error": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
-      "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/ast-metadata-inferer": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmmirror.com/ast-metadata-inferer/-/ast-metadata-inferer-0.8.0.tgz",
-      "integrity": "sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==",
-      "dev": true,
-      "dependencies": {
-        "@mdn/browser-compat-data": "^5.2.34"
-      }
-    },
-    "node_modules/astral-regex": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
-      "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/balanced-match": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
-      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
-      "dev": true
-    },
-    "node_modules/binary-extensions": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
-      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
-      "dev": true,
-      "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
-      }
-    },
-    "node_modules/braces": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
-      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
-      "dev": true,
-      "dependencies": {
-        "fill-range": "^7.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/browser-stdout": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
-      "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
-      "dev": true
-    },
-    "node_modules/browserslist": {
-      "version": "4.22.2",
-      "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.22.2.tgz",
-      "integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
-      "dev": true,
-      "dependencies": {
-        "caniuse-lite": "^1.0.30001565",
-        "electron-to-chromium": "^1.4.601",
-        "node-releases": "^2.0.14",
-        "update-browserslist-db": "^1.0.13"
-      },
-      "bin": {
-        "browserslist": "cli.js"
-      },
-      "engines": {
-        "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
-      }
-    },
-    "node_modules/builtin-modules": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz",
-      "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/callsites": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
-      "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/caniuse-lite": {
-      "version": "1.0.30001577",
-      "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001577.tgz",
-      "integrity": "sha512-rs2ZygrG1PNXMfmncM0B5H1hndY5ZCC9b5TkFaVNfZ+AUlyqcMyVIQtc3fsezi0NUCk5XZfDf9WS6WxMxnfdrg==",
-      "dev": true
-    },
-    "node_modules/chai": {
-      "version": "4.3.10",
-      "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.10.tgz",
-      "integrity": "sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==",
-      "dev": true,
-      "dependencies": {
-        "assertion-error": "^1.1.0",
-        "check-error": "^1.0.3",
-        "deep-eql": "^4.1.3",
-        "get-func-name": "^2.0.2",
-        "loupe": "^2.3.6",
-        "pathval": "^1.1.1",
-        "type-detect": "^4.0.8"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/chai-spies": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-1.1.0.tgz",
-      "integrity": "sha512-ikaUhQvQWchRYj2K54itFp3nrcxaFRpSDQxDlRzSn9aWgu9Pi7lD8yFxTso4WnQ39+WZ69oB/qOvqp+isJIIWA==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4.0.0"
-      },
-      "peerDependencies": {
-        "chai": "*"
-      }
-    },
-    "node_modules/chalk": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
-      "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.1.0",
-        "supports-color": "^7.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/chalk?sponsor=1"
-      }
-    },
-    "node_modules/check-error": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz",
-      "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==",
-      "dev": true,
-      "dependencies": {
-        "get-func-name": "^2.0.2"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/chokidar": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
-      "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "individual",
-          "url": "https://paulmillr.com/funding/"
-        }
-      ],
-      "dependencies": {
-        "anymatch": "~3.1.2",
-        "braces": "~3.0.2",
-        "glob-parent": "~5.1.2",
-        "is-binary-path": "~2.1.0",
-        "is-glob": "~4.0.1",
-        "normalize-path": "~3.0.0",
-        "readdirp": "~3.6.0"
-      },
-      "engines": {
-        "node": ">= 8.10.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/chokidar/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/clean-stack": {
-      "version": "2.2.0",
-      "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
-      "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/cli-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
-      "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
-      "dev": true,
-      "dependencies": {
-        "restore-cursor": "^3.1.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/cli-truncate": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz",
-      "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==",
-      "dev": true,
-      "dependencies": {
-        "slice-ansi": "^3.0.0",
-        "string-width": "^4.2.0"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/cliui": {
-      "version": "8.0.1",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
-      "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.1",
-        "wrap-ansi": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/color-convert": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
-      "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
-      "dev": true,
-      "dependencies": {
-        "color-name": "~1.1.4"
-      },
-      "engines": {
-        "node": ">=7.0.0"
-      }
-    },
-    "node_modules/color-name": {
-      "version": "1.1.4",
-      "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
-      "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
-      "dev": true
-    },
-    "node_modules/colorette": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
-      "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
-      "dev": true
-    },
-    "node_modules/commander": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
-      "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
-      "dev": true,
-      "engines": {
-        "node": ">= 12"
-      }
-    },
-    "node_modules/commondir": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
-      "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
-      "dev": true
-    },
-    "node_modules/compare-func": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz",
-      "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==",
-      "dev": true,
-      "dependencies": {
-        "array-ify": "^1.0.0",
-        "dot-prop": "^5.1.0"
-      }
-    },
-    "node_modules/concat-map": {
-      "version": "0.0.1",
-      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
-      "dev": true
-    },
-    "node_modules/conventional-changelog-angular": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz",
-      "integrity": "sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==",
-      "dev": true,
-      "dependencies": {
-        "compare-func": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=16"
-      }
-    },
-    "node_modules/conventional-changelog-conventionalcommits": {
-      "version": "4.6.3",
-      "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.3.tgz",
-      "integrity": "sha512-LTTQV4fwOM4oLPad317V/QNQ1FY4Hju5qeBIM1uTHbrnCE+Eg4CdRZ3gO2pUeR+tzWdp80M2j3qFFEDWVqOV4g==",
-      "dev": true,
-      "dependencies": {
-        "compare-func": "^2.0.0",
-        "lodash": "^4.17.15",
-        "q": "^1.5.1"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/conventional-commits-parser": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz",
-      "integrity": "sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==",
-      "dev": true,
-      "dependencies": {
-        "is-text-path": "^2.0.0",
-        "JSONStream": "^1.3.5",
-        "meow": "^12.0.1",
-        "split2": "^4.0.0"
-      },
-      "bin": {
-        "conventional-commits-parser": "cli.mjs"
-      },
-      "engines": {
-        "node": ">=16"
-      }
-    },
-    "node_modules/cosmiconfig": {
-      "version": "7.1.0",
-      "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
-      "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
-      "dev": true,
-      "dependencies": {
-        "@types/parse-json": "^4.0.0",
-        "import-fresh": "^3.2.1",
-        "parse-json": "^5.0.0",
-        "path-type": "^4.0.0",
-        "yaml": "^1.10.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/cross-spawn": {
-      "version": "7.0.3",
-      "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
-      "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^3.1.0",
-        "shebang-command": "^2.0.0",
-        "which": "^2.0.1"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/dargs": {
-      "version": "8.1.0",
-      "resolved": "https://registry.npmjs.org/dargs/-/dargs-8.1.0.tgz",
-      "integrity": "sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/debug": {
-      "version": "4.3.4",
-      "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
-      "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
-      "dev": true,
-      "dependencies": {
-        "ms": "2.1.2"
-      },
-      "engines": {
-        "node": ">=6.0"
-      },
-      "peerDependenciesMeta": {
-        "supports-color": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/deep-eql": {
-      "version": "4.1.3",
-      "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
-      "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==",
-      "dev": true,
-      "dependencies": {
-        "type-detect": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/deep-is": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
-      "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
-      "dev": true
-    },
-    "node_modules/deepmerge": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
-      "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/diff": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
-      "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.3.1"
-      }
-    },
-    "node_modules/dir-glob": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
-      "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
-      "dev": true,
-      "dependencies": {
-        "path-type": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/doctrine": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
-      "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
-      "dev": true,
-      "dependencies": {
-        "esutils": "^2.0.2"
-      },
-      "engines": {
-        "node": ">=6.0.0"
-      }
-    },
-    "node_modules/dot-prop": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
-      "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
-      "dev": true,
-      "dependencies": {
-        "is-obj": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/electron-to-chromium": {
-      "version": "1.4.632",
-      "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.4.632.tgz",
-      "integrity": "sha512-JGmudTwg7yxMYvR/gWbalqqQiyu7WTFv2Xu3vw4cJHXPFxNgAk0oy8UHaer8nLF4lZJa+rNoj6GsrKIVJTV6Tw==",
-      "dev": true
-    },
-    "node_modules/emoji-regex": {
-      "version": "8.0.0",
-      "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-      "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
-      "dev": true
-    },
-    "node_modules/enquirer": {
-      "version": "2.4.1",
-      "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
-      "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-colors": "^4.1.1",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
-    "node_modules/env-paths": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
-      "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/error-ex": {
-      "version": "1.3.2",
-      "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
-      "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
-      "dev": true,
-      "dependencies": {
-        "is-arrayish": "^0.2.1"
-      }
-    },
-    "node_modules/escalade": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
-      "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/escape-string-regexp": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
-      "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/eslint": {
-      "version": "8.54.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.54.0.tgz",
-      "integrity": "sha512-NY0DfAkM8BIZDVl6PgSa1ttZbx3xHgJzSNJKYcQglem6CppHyMhRIQkBVSSMaSRnLhig3jsDbEzOjwCVt4AmmA==",
-      "dev": true,
-      "dependencies": {
-        "@eslint-community/eslint-utils": "^4.2.0",
-        "@eslint-community/regexpp": "^4.6.1",
-        "@eslint/eslintrc": "^2.1.3",
-        "@eslint/js": "8.54.0",
-        "@humanwhocodes/config-array": "^0.11.13",
-        "@humanwhocodes/module-importer": "^1.0.1",
-        "@nodelib/fs.walk": "^1.2.8",
-        "@ungap/structured-clone": "^1.2.0",
-        "ajv": "^6.12.4",
-        "chalk": "^4.0.0",
-        "cross-spawn": "^7.0.2",
-        "debug": "^4.3.2",
-        "doctrine": "^3.0.0",
-        "escape-string-regexp": "^4.0.0",
-        "eslint-scope": "^7.2.2",
-        "eslint-visitor-keys": "^3.4.3",
-        "espree": "^9.6.1",
-        "esquery": "^1.4.2",
-        "esutils": "^2.0.2",
-        "fast-deep-equal": "^3.1.3",
-        "file-entry-cache": "^6.0.1",
-        "find-up": "^5.0.0",
-        "glob-parent": "^6.0.2",
-        "globals": "^13.19.0",
-        "graphemer": "^1.4.0",
-        "ignore": "^5.2.0",
-        "imurmurhash": "^0.1.4",
-        "is-glob": "^4.0.0",
-        "is-path-inside": "^3.0.3",
-        "js-yaml": "^4.1.0",
-        "json-stable-stringify-without-jsonify": "^1.0.1",
-        "levn": "^0.4.1",
-        "lodash.merge": "^4.6.2",
-        "minimatch": "^3.1.2",
-        "natural-compare": "^1.4.0",
-        "optionator": "^0.9.3",
-        "strip-ansi": "^6.0.1",
-        "text-table": "^0.2.0"
-      },
-      "bin": {
-        "eslint": "bin/eslint.js"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/eslint-plugin-compat": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmmirror.com/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz",
-      "integrity": "sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==",
-      "dev": true,
-      "dependencies": {
-        "@mdn/browser-compat-data": "^5.3.13",
-        "ast-metadata-inferer": "^0.8.0",
-        "browserslist": "^4.21.10",
-        "caniuse-lite": "^1.0.30001524",
-        "find-up": "^5.0.0",
-        "lodash.memoize": "^4.1.2",
-        "semver": "^7.5.4"
-      },
-      "engines": {
-        "node": ">=14.x"
-      },
-      "peerDependencies": {
-        "eslint": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
-      }
-    },
-    "node_modules/eslint-plugin-promise": {
-      "version": "6.1.1",
-      "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz",
-      "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==",
-      "dev": true,
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "peerDependencies": {
-        "eslint": "^7.0.0 || ^8.0.0"
-      }
-    },
-    "node_modules/eslint-scope": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
-      "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
-      "dev": true,
-      "dependencies": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^4.1.1"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/eslint-visitor-keys": {
-      "version": "3.4.3",
-      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
-      "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
-      "dev": true,
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/eslint/node_modules/eslint-scope": {
-      "version": "7.2.2",
-      "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
-      "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
-      "dev": true,
-      "dependencies": {
-        "esrecurse": "^4.3.0",
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/eslint/node_modules/estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/espree": {
-      "version": "9.6.1",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
-      "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
-      "dev": true,
-      "dependencies": {
-        "acorn": "^8.9.0",
-        "acorn-jsx": "^5.3.2",
-        "eslint-visitor-keys": "^3.4.1"
-      },
-      "engines": {
-        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
-      },
-      "funding": {
-        "url": "https://opencollective.com/eslint"
-      }
-    },
-    "node_modules/esquery": {
-      "version": "1.5.0",
-      "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
-      "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
-      "dev": true,
-      "dependencies": {
-        "estraverse": "^5.1.0"
-      },
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
-    "node_modules/esquery/node_modules/estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/esrecurse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
-      "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
-      "dev": true,
-      "dependencies": {
-        "estraverse": "^5.2.0"
-      },
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/esrecurse/node_modules/estraverse": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
-      "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/estraverse": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
-      "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
-      "dev": true,
-      "engines": {
-        "node": ">=4.0"
-      }
-    },
-    "node_modules/estree-walker": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
-      "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
-      "dev": true
-    },
-    "node_modules/esutils": {
-      "version": "2.0.3",
-      "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-      "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/execa": {
-      "version": "5.1.1",
-      "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
-      "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
-      "dev": true,
-      "dependencies": {
-        "cross-spawn": "^7.0.3",
-        "get-stream": "^6.0.0",
-        "human-signals": "^2.1.0",
-        "is-stream": "^2.0.0",
-        "merge-stream": "^2.0.0",
-        "npm-run-path": "^4.0.1",
-        "onetime": "^5.1.2",
-        "signal-exit": "^3.0.3",
-        "strip-final-newline": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sindresorhus/execa?sponsor=1"
-      }
-    },
-    "node_modules/fast-deep-equal": {
-      "version": "3.1.3",
-      "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
-      "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
-      "dev": true
-    },
-    "node_modules/fast-glob": {
-      "version": "3.3.2",
-      "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
-      "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
-      "dev": true,
-      "dependencies": {
-        "@nodelib/fs.stat": "^2.0.2",
-        "@nodelib/fs.walk": "^1.2.3",
-        "glob-parent": "^5.1.2",
-        "merge2": "^1.3.0",
-        "micromatch": "^4.0.4"
-      },
-      "engines": {
-        "node": ">=8.6.0"
-      }
-    },
-    "node_modules/fast-glob/node_modules/glob-parent": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
-      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/fast-json-stable-stringify": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
-      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
-      "dev": true
-    },
-    "node_modules/fast-levenshtein": {
-      "version": "2.0.6",
-      "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
-      "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
-      "dev": true
-    },
-    "node_modules/fastq": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
-      "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
-      "dev": true,
-      "dependencies": {
-        "reusify": "^1.0.4"
-      }
-    },
-    "node_modules/file-entry-cache": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
-      "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
-      "dev": true,
-      "dependencies": {
-        "flat-cache": "^3.0.4"
-      },
-      "engines": {
-        "node": "^10.12.0 || >=12.0.0"
-      }
-    },
-    "node_modules/fill-range": {
-      "version": "7.0.1",
-      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
-      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
-      "dev": true,
-      "dependencies": {
-        "to-regex-range": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/find-up": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
-      "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
-      "dev": true,
-      "dependencies": {
-        "locate-path": "^6.0.0",
-        "path-exists": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/flat": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
-      "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
-      "dev": true,
-      "bin": {
-        "flat": "cli.js"
-      }
-    },
-    "node_modules/flat-cache": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
-      "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
-      "dev": true,
-      "dependencies": {
-        "flatted": "^3.2.9",
-        "keyv": "^4.5.3",
-        "rimraf": "^3.0.2"
-      },
-      "engines": {
-        "node": "^10.12.0 || >=12.0.0"
-      }
-    },
-    "node_modules/flatted": {
-      "version": "3.2.9",
-      "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
-      "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
-      "dev": true
-    },
-    "node_modules/fs.realpath": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
-      "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
-      "dev": true
-    },
-    "node_modules/fsevents": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
-      "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
-      "dev": true,
-      "hasInstallScript": true,
-      "optional": true,
-      "os": [
-        "darwin"
-      ],
-      "engines": {
-        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
-      }
-    },
-    "node_modules/function-bind": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
-      "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/get-caller-file": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
-      "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
-      "dev": true,
-      "engines": {
-        "node": "6.* || 8.* || >= 10.*"
-      }
-    },
-    "node_modules/get-func-name": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz",
-      "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/get-own-enumerable-property-symbols": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz",
-      "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==",
-      "dev": true
-    },
-    "node_modules/get-stream": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
-      "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/git-raw-commits": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz",
-      "integrity": "sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==",
-      "dev": true,
-      "dependencies": {
-        "dargs": "^8.0.0",
-        "meow": "^12.0.1",
-        "split2": "^4.0.0"
-      },
-      "bin": {
-        "git-raw-commits": "cli.mjs"
-      },
-      "engines": {
-        "node": ">=16"
-      }
-    },
-    "node_modules/glob": {
-      "version": "7.2.3",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
-      "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
-      "dev": true,
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.1.1",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/glob-parent": {
-      "version": "6.0.2",
-      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
-      "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
-      "dev": true,
-      "dependencies": {
-        "is-glob": "^4.0.3"
-      },
-      "engines": {
-        "node": ">=10.13.0"
-      }
-    },
-    "node_modules/global-directory": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz",
-      "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==",
-      "dev": true,
-      "dependencies": {
-        "ini": "4.1.1"
-      },
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/globals": {
-      "version": "13.23.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz",
-      "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==",
-      "dev": true,
-      "dependencies": {
-        "type-fest": "^0.20.2"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/globby": {
-      "version": "11.1.0",
-      "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
-      "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
-      "dev": true,
-      "dependencies": {
-        "array-union": "^2.1.0",
-        "dir-glob": "^3.0.1",
-        "fast-glob": "^3.2.9",
-        "ignore": "^5.2.0",
-        "merge2": "^1.4.1",
-        "slash": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/graphemer": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
-      "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
-      "dev": true
-    },
-    "node_modules/has-flag": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
-      "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/hasown": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz",
-      "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==",
-      "dev": true,
-      "dependencies": {
-        "function-bind": "^1.1.2"
-      },
-      "engines": {
-        "node": ">= 0.4"
-      }
-    },
-    "node_modules/he": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
-      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
-      "dev": true,
-      "bin": {
-        "he": "bin/he"
-      }
-    },
-    "node_modules/human-signals": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
-      "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
-      "dev": true,
-      "engines": {
-        "node": ">=10.17.0"
-      }
-    },
-    "node_modules/husky": {
-      "version": "7.0.4",
-      "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz",
-      "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
-      "dev": true,
-      "bin": {
-        "husky": "lib/bin.js"
-      },
-      "engines": {
-        "node": ">=12"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/typicode"
-      }
-    },
-    "node_modules/ignore": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
-      "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 4"
-      }
-    },
-    "node_modules/import-fresh": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
-      "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
-      "dev": true,
-      "dependencies": {
-        "parent-module": "^1.0.0",
-        "resolve-from": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/import-fresh/node_modules/resolve-from": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
-      "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/import-meta-resolve": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
-      "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==",
-      "dev": true,
-      "funding": {
-        "type": "github",
-        "url": "https://github.com/sponsors/wooorm"
-      }
-    },
-    "node_modules/imurmurhash": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
-      "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.8.19"
-      }
-    },
-    "node_modules/indent-string": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
-      "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/inflight": {
-      "version": "1.0.6",
-      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
-      "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
-      "dev": true,
-      "dependencies": {
-        "once": "^1.3.0",
-        "wrappy": "1"
-      }
-    },
-    "node_modules/inherits": {
-      "version": "2.0.4",
-      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
-      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
-      "dev": true
-    },
-    "node_modules/ini": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
-      "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
-      "dev": true,
-      "engines": {
-        "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
-      }
-    },
-    "node_modules/is-arrayish": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
-      "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
-      "dev": true
-    },
-    "node_modules/is-binary-path": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
-      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
-      "dev": true,
-      "dependencies": {
-        "binary-extensions": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-builtin-module": {
-      "version": "3.2.1",
-      "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz",
-      "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==",
-      "dev": true,
-      "dependencies": {
-        "builtin-modules": "^3.3.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-core-module": {
-      "version": "2.13.1",
-      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz",
-      "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==",
-      "dev": true,
-      "dependencies": {
-        "hasown": "^2.0.0"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/is-extglob": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
-      "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-fullwidth-code-point": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
-      "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-glob": {
-      "version": "4.0.3",
-      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
-      "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
-      "dev": true,
-      "dependencies": {
-        "is-extglob": "^2.1.1"
-      },
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-module": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz",
-      "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==",
-      "dev": true
-    },
-    "node_modules/is-number": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
-      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.12.0"
-      }
-    },
-    "node_modules/is-obj": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
-      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-path-inside": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
-      "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-reference": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz",
-      "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==",
-      "dev": true,
-      "dependencies": {
-        "@types/estree": "*"
-      }
-    },
-    "node_modules/is-regexp": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz",
-      "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/is-stream": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
-      "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/is-text-path": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-2.0.0.tgz",
-      "integrity": "sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==",
-      "dev": true,
-      "dependencies": {
-        "text-extensions": "^2.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/is-unicode-supported": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
-      "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/isexe": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
-      "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
-      "dev": true
-    },
-    "node_modules/jiti": {
-      "version": "1.21.0",
-      "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz",
-      "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==",
-      "dev": true,
-      "bin": {
-        "jiti": "bin/jiti.js"
-      }
-    },
-    "node_modules/js-tokens": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
-      "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
-      "dev": true
-    },
-    "node_modules/js-yaml": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
-      "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
-      "dev": true,
-      "dependencies": {
-        "argparse": "^2.0.1"
-      },
-      "bin": {
-        "js-yaml": "bin/js-yaml.js"
-      }
-    },
-    "node_modules/json-buffer": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
-      "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
-      "dev": true
-    },
-    "node_modules/json-parse-even-better-errors": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
-      "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
-      "dev": true
-    },
-    "node_modules/json-schema-traverse": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
-      "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
-      "dev": true
-    },
-    "node_modules/json-stable-stringify-without-jsonify": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
-      "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
-      "dev": true
-    },
-    "node_modules/jsonparse": {
-      "version": "1.3.1",
-      "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz",
-      "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==",
-      "dev": true,
-      "engines": [
-        "node >= 0.2.0"
-      ]
-    },
-    "node_modules/JSONStream": {
-      "version": "1.3.5",
-      "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz",
-      "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==",
-      "dev": true,
-      "dependencies": {
-        "jsonparse": "^1.2.0",
-        "through": ">=2.2.7 <3"
-      },
-      "bin": {
-        "JSONStream": "bin.js"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/keyv": {
-      "version": "4.5.4",
-      "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
-      "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
-      "dev": true,
-      "dependencies": {
-        "json-buffer": "3.0.1"
-      }
-    },
-    "node_modules/levn": {
-      "version": "0.4.1",
-      "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
-      "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
-      "dev": true,
-      "dependencies": {
-        "prelude-ls": "^1.2.1",
-        "type-check": "~0.4.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/lines-and-columns": {
-      "version": "1.2.4",
-      "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
-      "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
-      "dev": true
-    },
-    "node_modules/lint-staged": {
-      "version": "11.2.6",
-      "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-11.2.6.tgz",
-      "integrity": "sha512-Vti55pUnpvPE0J9936lKl0ngVeTdSZpEdTNhASbkaWX7J5R9OEifo1INBGQuGW4zmy6OG+TcWPJ3m5yuy5Q8Tg==",
-      "dev": true,
-      "dependencies": {
-        "cli-truncate": "2.1.0",
-        "colorette": "^1.4.0",
-        "commander": "^8.2.0",
-        "cosmiconfig": "^7.0.1",
-        "debug": "^4.3.2",
-        "enquirer": "^2.3.6",
-        "execa": "^5.1.1",
-        "listr2": "^3.12.2",
-        "micromatch": "^4.0.4",
-        "normalize-path": "^3.0.0",
-        "please-upgrade-node": "^3.2.0",
-        "string-argv": "0.3.1",
-        "stringify-object": "3.3.0",
-        "supports-color": "8.1.1"
-      },
-      "bin": {
-        "lint-staged": "bin/lint-staged.js"
-      },
-      "funding": {
-        "url": "https://opencollective.com/lint-staged"
-      }
-    },
-    "node_modules/lint-staged/node_modules/supports-color": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
-      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/supports-color?sponsor=1"
-      }
-    },
-    "node_modules/listr2": {
-      "version": "3.14.0",
-      "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz",
-      "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==",
-      "dev": true,
-      "dependencies": {
-        "cli-truncate": "^2.1.0",
-        "colorette": "^2.0.16",
-        "log-update": "^4.0.0",
-        "p-map": "^4.0.0",
-        "rfdc": "^1.3.0",
-        "rxjs": "^7.5.1",
-        "through": "^2.3.8",
-        "wrap-ansi": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "peerDependencies": {
-        "enquirer": ">= 2.3.0 < 3"
-      },
-      "peerDependenciesMeta": {
-        "enquirer": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/listr2/node_modules/colorette": {
-      "version": "2.0.20",
-      "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
-      "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
-      "dev": true
-    },
-    "node_modules/livereload": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz",
-      "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==",
-      "dev": true,
-      "dependencies": {
-        "chokidar": "^3.5.0",
-        "livereload-js": "^3.3.1",
-        "opts": ">= 1.2.0",
-        "ws": "^7.4.3"
-      },
-      "bin": {
-        "livereload": "bin/livereload.js"
-      },
-      "engines": {
-        "node": ">=8.0.0"
-      }
-    },
-    "node_modules/livereload-js": {
-      "version": "3.4.1",
-      "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz",
-      "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==",
-      "dev": true
-    },
-    "node_modules/locate-path": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
-      "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
-      "dev": true,
-      "dependencies": {
-        "p-locate": "^5.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/lodash": {
-      "version": "4.17.21",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
-      "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
-      "dev": true
-    },
-    "node_modules/lodash.camelcase": {
-      "version": "4.3.0",
-      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
-      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
-      "dev": true
-    },
-    "node_modules/lodash.isplainobject": {
-      "version": "4.0.6",
-      "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
-      "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
-      "dev": true
-    },
-    "node_modules/lodash.kebabcase": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
-      "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
-      "dev": true
-    },
-    "node_modules/lodash.memoize": {
-      "version": "4.1.2",
-      "resolved": "https://registry.npmmirror.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
-      "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
-      "dev": true
-    },
-    "node_modules/lodash.merge": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
-      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
-      "dev": true
-    },
-    "node_modules/lodash.mergewith": {
-      "version": "4.6.2",
-      "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz",
-      "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==",
-      "dev": true
-    },
-    "node_modules/lodash.snakecase": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
-      "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==",
-      "dev": true
-    },
-    "node_modules/lodash.startcase": {
-      "version": "4.4.0",
-      "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz",
-      "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==",
-      "dev": true
-    },
-    "node_modules/lodash.uniq": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
-      "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
-      "dev": true
-    },
-    "node_modules/lodash.upperfirst": {
-      "version": "4.3.1",
-      "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz",
-      "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==",
-      "dev": true
-    },
-    "node_modules/log-symbols": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
-      "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
-      "dev": true,
-      "dependencies": {
-        "chalk": "^4.1.0",
-        "is-unicode-supported": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/log-update": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz",
-      "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==",
-      "dev": true,
-      "dependencies": {
-        "ansi-escapes": "^4.3.0",
-        "cli-cursor": "^3.1.0",
-        "slice-ansi": "^4.0.0",
-        "wrap-ansi": "^6.2.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/log-update/node_modules/slice-ansi": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
-      "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "astral-regex": "^2.0.0",
-        "is-fullwidth-code-point": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/slice-ansi?sponsor=1"
-      }
-    },
-    "node_modules/log-update/node_modules/wrap-ansi": {
-      "version": "6.2.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
-      "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/loupe": {
-      "version": "2.3.7",
-      "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz",
-      "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==",
-      "dev": true,
-      "dependencies": {
-        "get-func-name": "^2.0.1"
-      }
-    },
-    "node_modules/lru-cache": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
-      "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
-      "dev": true,
-      "dependencies": {
-        "yallist": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/magic-string": {
-      "version": "0.25.9",
-      "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
-      "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
-      "dev": true,
-      "dependencies": {
-        "sourcemap-codec": "^1.4.8"
-      }
-    },
-    "node_modules/meow": {
-      "version": "12.1.1",
-      "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz",
-      "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==",
-      "dev": true,
-      "engines": {
-        "node": ">=16.10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/merge-stream": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
-      "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
-      "dev": true
-    },
-    "node_modules/merge2": {
-      "version": "1.4.1",
-      "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
-      "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/micromatch": {
-      "version": "4.0.5",
-      "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
-      "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
-      "dev": true,
-      "dependencies": {
-        "braces": "^3.0.2",
-        "picomatch": "^2.3.1"
-      },
-      "engines": {
-        "node": ">=8.6"
-      }
-    },
-    "node_modules/mime": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
-      "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
-      "dev": true,
-      "bin": {
-        "mime": "cli.js"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      }
-    },
-    "node_modules/mimic-fn": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
-      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/minimist": {
-      "version": "1.2.8",
-      "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
-      "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
-      "dev": true,
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/mocha": {
-      "version": "10.2.0",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
-      "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
-      "dev": true,
-      "dependencies": {
-        "ansi-colors": "4.1.1",
-        "browser-stdout": "1.3.1",
-        "chokidar": "3.5.3",
-        "debug": "4.3.4",
-        "diff": "5.0.0",
-        "escape-string-regexp": "4.0.0",
-        "find-up": "5.0.0",
-        "glob": "7.2.0",
-        "he": "1.2.0",
-        "js-yaml": "4.1.0",
-        "log-symbols": "4.1.0",
-        "minimatch": "5.0.1",
-        "ms": "2.1.3",
-        "nanoid": "3.3.3",
-        "serialize-javascript": "6.0.0",
-        "strip-json-comments": "3.1.1",
-        "supports-color": "8.1.1",
-        "workerpool": "6.2.1",
-        "yargs": "16.2.0",
-        "yargs-parser": "20.2.4",
-        "yargs-unparser": "2.0.0"
-      },
-      "bin": {
-        "_mocha": "bin/_mocha",
-        "mocha": "bin/mocha.js"
-      },
-      "engines": {
-        "node": ">= 14.0.0"
-      },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/mochajs"
-      }
-    },
-    "node_modules/mocha/node_modules/ansi-colors": {
-      "version": "4.1.1",
-      "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
-      "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/mocha/node_modules/cliui": {
-      "version": "7.0.4",
-      "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
-      "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
-      "dev": true,
-      "dependencies": {
-        "string-width": "^4.2.0",
-        "strip-ansi": "^6.0.0",
-        "wrap-ansi": "^7.0.0"
-      }
-    },
-    "node_modules/mocha/node_modules/glob": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
-      "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
-      "dev": true,
-      "dependencies": {
-        "fs.realpath": "^1.0.0",
-        "inflight": "^1.0.4",
-        "inherits": "2",
-        "minimatch": "^3.0.4",
-        "once": "^1.3.0",
-        "path-is-absolute": "^1.0.0"
-      },
-      "engines": {
-        "node": "*"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/mocha/node_modules/glob/node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^1.1.7"
-      },
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/mocha/node_modules/minimatch": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
-      "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
-      "dev": true,
-      "dependencies": {
-        "brace-expansion": "^2.0.1"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-      "dev": true,
-      "dependencies": {
-        "balanced-match": "^1.0.0"
-      }
-    },
-    "node_modules/mocha/node_modules/ms": {
-      "version": "2.1.3",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
-      "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
-      "dev": true
-    },
-    "node_modules/mocha/node_modules/supports-color": {
-      "version": "8.1.1",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
-      "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/supports-color?sponsor=1"
-      }
-    },
-    "node_modules/mocha/node_modules/yargs": {
-      "version": "16.2.0",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
-      "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
-      "dev": true,
-      "dependencies": {
-        "cliui": "^7.0.2",
-        "escalade": "^3.1.1",
-        "get-caller-file": "^2.0.5",
-        "require-directory": "^2.1.1",
-        "string-width": "^4.2.0",
-        "y18n": "^5.0.5",
-        "yargs-parser": "^20.2.2"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/mocha/node_modules/yargs-parser": {
-      "version": "20.2.4",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
-      "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/ms": {
-      "version": "2.1.2",
-      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
-      "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
-      "dev": true
-    },
-    "node_modules/nanoid": {
-      "version": "3.3.3",
-      "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
-      "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
-      "dev": true,
-      "bin": {
-        "nanoid": "bin/nanoid.cjs"
-      },
-      "engines": {
-        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
-      }
-    },
-    "node_modules/natural-compare": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
-      "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
-      "dev": true
-    },
-    "node_modules/natural-compare-lite": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
-      "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
-      "dev": true
-    },
-    "node_modules/node-releases": {
-      "version": "2.0.14",
-      "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.14.tgz",
-      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
-      "dev": true
-    },
-    "node_modules/normalize-path": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
-      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/npm-run-path": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
-      "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
-      "dev": true,
-      "dependencies": {
-        "path-key": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/once": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
-      "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
-      "dev": true,
-      "dependencies": {
-        "wrappy": "1"
-      }
-    },
-    "node_modules/onetime": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
-      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
-      "dev": true,
-      "dependencies": {
-        "mimic-fn": "^2.1.0"
-      },
-      "engines": {
-        "node": ">=6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/opener": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
-      "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
-      "dev": true,
-      "bin": {
-        "opener": "bin/opener-bin.js"
-      }
-    },
-    "node_modules/optionator": {
-      "version": "0.9.3",
-      "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
-      "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
-      "dev": true,
-      "dependencies": {
-        "@aashutoshrathi/word-wrap": "^1.2.3",
-        "deep-is": "^0.1.3",
-        "fast-levenshtein": "^2.0.6",
-        "levn": "^0.4.1",
-        "prelude-ls": "^1.2.1",
-        "type-check": "^0.4.0"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/opts": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz",
-      "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==",
-      "dev": true
-    },
-    "node_modules/p-limit": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
-      "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
-      "dev": true,
-      "dependencies": {
-        "yocto-queue": "^0.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-locate": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
-      "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
-      "dev": true,
-      "dependencies": {
-        "p-limit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/p-map": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
-      "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
-      "dev": true,
-      "dependencies": {
-        "aggregate-error": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/parent-module": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
-      "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
-      "dev": true,
-      "dependencies": {
-        "callsites": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/parse-json": {
-      "version": "5.2.0",
-      "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
-      "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
-      "dev": true,
-      "dependencies": {
-        "@babel/code-frame": "^7.0.0",
-        "error-ex": "^1.3.1",
-        "json-parse-even-better-errors": "^2.3.0",
-        "lines-and-columns": "^1.1.6"
-      },
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/path-exists": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
-      "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-is-absolute": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
-      "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/path-key": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
-      "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/path-parse": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
-      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
-      "dev": true
-    },
-    "node_modules/path-type": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
-      "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/pathval": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz",
-      "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==",
-      "dev": true,
-      "engines": {
-        "node": "*"
-      }
-    },
-    "node_modules/picocolors": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.0.0.tgz",
-      "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
-      "dev": true
-    },
-    "node_modules/picomatch": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
-      "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8.6"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/jonschlinkert"
-      }
-    },
-    "node_modules/please-upgrade-node": {
-      "version": "3.2.0",
-      "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz",
-      "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==",
-      "dev": true,
-      "dependencies": {
-        "semver-compare": "^1.0.0"
-      }
-    },
-    "node_modules/prelude-ls": {
-      "version": "1.2.1",
-      "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
-      "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/punycode": {
-      "version": "2.3.1",
-      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
-      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/q": {
-      "version": "1.5.1",
-      "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
-      "integrity": "sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.6.0",
-        "teleport": ">=0.2.0"
-      }
-    },
-    "node_modules/queue-microtask": {
-      "version": "1.2.3",
-      "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
-      "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/randombytes": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
-      "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
-      "dev": true,
-      "dependencies": {
-        "safe-buffer": "^5.1.0"
-      }
-    },
-    "node_modules/readdirp": {
-      "version": "3.6.0",
-      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
-      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
-      "dev": true,
-      "dependencies": {
-        "picomatch": "^2.2.1"
-      },
-      "engines": {
-        "node": ">=8.10.0"
-      }
-    },
-    "node_modules/require-directory": {
-      "version": "2.1.1",
-      "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
-      "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/require-from-string": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
-      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/resolve": {
-      "version": "1.22.8",
-      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
-      "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
-      "dev": true,
-      "dependencies": {
-        "is-core-module": "^2.13.0",
-        "path-parse": "^1.0.7",
-        "supports-preserve-symlinks-flag": "^1.0.0"
-      },
-      "bin": {
-        "resolve": "bin/resolve"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/resolve-from": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
-      "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/restore-cursor": {
-      "version": "3.1.0",
-      "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
-      "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
-      "dev": true,
-      "dependencies": {
-        "onetime": "^5.1.0",
-        "signal-exit": "^3.0.2"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/reusify": {
-      "version": "1.0.4",
-      "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
-      "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
-      "dev": true,
-      "engines": {
-        "iojs": ">=1.0.0",
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/rfdc": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz",
-      "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==",
-      "dev": true
-    },
-    "node_modules/rimraf": {
-      "version": "3.0.2",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
-      "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
-      "dev": true,
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/isaacs"
-      }
-    },
-    "node_modules/rollup": {
-      "version": "2.79.1",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
-      "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
-      "dev": true,
-      "bin": {
-        "rollup": "dist/bin/rollup"
-      },
-      "engines": {
-        "node": ">=10.0.0"
-      },
-      "optionalDependencies": {
-        "fsevents": "~2.3.2"
-      }
-    },
-    "node_modules/rollup-plugin-livereload": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz",
-      "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==",
-      "dev": true,
-      "dependencies": {
-        "livereload": "^0.9.1"
-      },
-      "engines": {
-        "node": ">=8.3"
-      }
-    },
-    "node_modules/rollup-plugin-serve": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-serve/-/rollup-plugin-serve-1.1.0.tgz",
-      "integrity": "sha512-pYkSsuA0/psKqhhictkJw1c2klya5b+LlCvipWqI9OE1aG2M97mRumZCbBlry5CMEOzYBBgSDgd1694sNbmyIw==",
-      "dev": true,
-      "dependencies": {
-        "mime": ">=2.4.6",
-        "opener": "1"
-      }
-    },
-    "node_modules/run-parallel": {
-      "version": "1.2.0",
-      "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
-      "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ],
-      "dependencies": {
-        "queue-microtask": "^1.2.2"
-      }
-    },
-    "node_modules/rxjs": {
-      "version": "7.8.1",
-      "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
-      "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
-      "dev": true,
-      "dependencies": {
-        "tslib": "^2.1.0"
-      }
-    },
-    "node_modules/safe-buffer": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
-      "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
-      "dev": true,
-      "funding": [
-        {
-          "type": "github",
-          "url": "https://github.com/sponsors/feross"
-        },
-        {
-          "type": "patreon",
-          "url": "https://www.patreon.com/feross"
-        },
-        {
-          "type": "consulting",
-          "url": "https://feross.org/support"
-        }
-      ]
-    },
-    "node_modules/semver": {
-      "version": "7.6.0",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz",
-      "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==",
-      "dev": true,
-      "dependencies": {
-        "lru-cache": "^6.0.0"
-      },
-      "bin": {
-        "semver": "bin/semver.js"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/semver-compare": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz",
-      "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==",
-      "dev": true
-    },
-    "node_modules/serialize-javascript": {
-      "version": "6.0.0",
-      "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
-      "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
-      "dev": true,
-      "dependencies": {
-        "randombytes": "^2.1.0"
-      }
-    },
-    "node_modules/shebang-command": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
-      "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
-      "dev": true,
-      "dependencies": {
-        "shebang-regex": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/shebang-regex": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
-      "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/signal-exit": {
-      "version": "3.0.7",
-      "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
-      "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
-      "dev": true
-    },
-    "node_modules/slash": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
-      "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/slice-ansi": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz",
-      "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "astral-regex": "^2.0.0",
-        "is-fullwidth-code-point": "^3.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/sourcemap-codec": {
-      "version": "1.4.8",
-      "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz",
-      "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==",
-      "deprecated": "Please use @jridgewell/sourcemap-codec instead",
-      "dev": true
-    },
-    "node_modules/split2": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
-      "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 10.x"
-      }
-    },
-    "node_modules/string-argv": {
-      "version": "0.3.1",
-      "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz",
-      "integrity": "sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.6.19"
-      }
-    },
-    "node_modules/string-width": {
-      "version": "4.2.3",
-      "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-      "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-      "dev": true,
-      "dependencies": {
-        "emoji-regex": "^8.0.0",
-        "is-fullwidth-code-point": "^3.0.0",
-        "strip-ansi": "^6.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/stringify-object": {
-      "version": "3.3.0",
-      "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz",
-      "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==",
-      "dev": true,
-      "dependencies": {
-        "get-own-enumerable-property-symbols": "^3.0.0",
-        "is-obj": "^1.0.1",
-        "is-regexp": "^1.0.0"
-      },
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/stringify-object/node_modules/is-obj": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
-      "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
-      "dev": true,
-      "engines": {
-        "node": ">=0.10.0"
-      }
-    },
-    "node_modules/strip-ansi": {
-      "version": "6.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-      "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-      "dev": true,
-      "dependencies": {
-        "ansi-regex": "^5.0.1"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/strip-final-newline": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
-      "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
-      "dev": true,
-      "engines": {
-        "node": ">=6"
-      }
-    },
-    "node_modules/strip-json-comments": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
-      "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/supports-color": {
-      "version": "7.2.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
-      "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
-      "dev": true,
-      "dependencies": {
-        "has-flag": "^4.0.0"
-      },
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/supports-preserve-symlinks-flag": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
-      "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
-      "dev": true,
-      "engines": {
-        "node": ">= 0.4"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/ljharb"
-      }
-    },
-    "node_modules/text-extensions": {
-      "version": "2.4.0",
-      "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-2.4.0.tgz",
-      "integrity": "sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/text-table": {
-      "version": "0.2.0",
-      "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
-      "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
-      "dev": true
-    },
-    "node_modules/through": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
-      "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
-      "dev": true
-    },
-    "node_modules/to-regex-range": {
-      "version": "5.0.1",
-      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
-      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
-      "dev": true,
-      "dependencies": {
-        "is-number": "^7.0.0"
-      },
-      "engines": {
-        "node": ">=8.0"
-      }
-    },
-    "node_modules/tslib": {
-      "version": "2.6.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
-      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
-      "dev": true
-    },
-    "node_modules/tsutils": {
-      "version": "3.21.0",
-      "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
-      "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
-      "dev": true,
-      "dependencies": {
-        "tslib": "^1.8.1"
-      },
-      "engines": {
-        "node": ">= 6"
-      },
-      "peerDependencies": {
-        "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
-      }
-    },
-    "node_modules/tsutils/node_modules/tslib": {
-      "version": "1.14.1",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
-      "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
-      "dev": true
-    },
-    "node_modules/type-check": {
-      "version": "0.4.0",
-      "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
-      "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
-      "dev": true,
-      "dependencies": {
-        "prelude-ls": "^1.2.1"
-      },
-      "engines": {
-        "node": ">= 0.8.0"
-      }
-    },
-    "node_modules/type-detect": {
-      "version": "4.0.8",
-      "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
-      "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
-      "dev": true,
-      "engines": {
-        "node": ">=4"
-      }
-    },
-    "node_modules/type-fest": {
-      "version": "0.20.2",
-      "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
-      "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/typescript": {
-      "version": "4.9.5",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
-      "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
-      "dev": true,
-      "bin": {
-        "tsc": "bin/tsc",
-        "tsserver": "bin/tsserver"
-      },
-      "engines": {
-        "node": ">=4.2.0"
-      }
-    },
-    "node_modules/unicorn-magic": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz",
-      "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=18"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/update-browserslist-db": {
-      "version": "1.0.13",
-      "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
-      "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
-      "dev": true,
-      "dependencies": {
-        "escalade": "^3.1.1",
-        "picocolors": "^1.0.0"
-      },
-      "bin": {
-        "update-browserslist-db": "cli.js"
-      },
-      "peerDependencies": {
-        "browserslist": ">= 4.21.0"
-      }
-    },
-    "node_modules/uri-js": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
-      "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
-      "dev": true,
-      "dependencies": {
-        "punycode": "^2.1.0"
-      }
-    },
-    "node_modules/uuid": {
-      "version": "9.0.1",
-      "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
-      "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
-      "dev": true,
-      "funding": [
-        "https://github.com/sponsors/broofa",
-        "https://github.com/sponsors/ctavan"
-      ],
-      "bin": {
-        "uuid": "dist/bin/uuid"
-      }
-    },
-    "node_modules/which": {
-      "version": "2.0.2",
-      "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
-      "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
-      "dev": true,
-      "dependencies": {
-        "isexe": "^2.0.0"
-      },
-      "bin": {
-        "node-which": "bin/node-which"
-      },
-      "engines": {
-        "node": ">= 8"
-      }
-    },
-    "node_modules/workerpool": {
-      "version": "6.2.1",
-      "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
-      "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
-      "dev": true
-    },
-    "node_modules/wrap-ansi": {
-      "version": "7.0.0",
-      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-      "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-      "dev": true,
-      "dependencies": {
-        "ansi-styles": "^4.0.0",
-        "string-width": "^4.1.0",
-        "strip-ansi": "^6.0.0"
-      },
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
-      }
-    },
-    "node_modules/wrappy": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
-      "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
-      "dev": true
-    },
-    "node_modules/ws": {
-      "version": "7.5.9",
-      "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
-      "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=8.3.0"
-      },
-      "peerDependencies": {
-        "bufferutil": "^4.0.1",
-        "utf-8-validate": "^5.0.2"
-      },
-      "peerDependenciesMeta": {
-        "bufferutil": {
-          "optional": true
-        },
-        "utf-8-validate": {
-          "optional": true
-        }
-      }
-    },
-    "node_modules/y18n": {
-      "version": "5.0.8",
-      "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
-      "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/yallist": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-      "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
-      "dev": true
-    },
-    "node_modules/yaml": {
-      "version": "1.10.2",
-      "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
-      "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
-      "dev": true,
-      "engines": {
-        "node": ">= 6"
-      }
-    },
-    "node_modules/yargs": {
-      "version": "17.7.2",
-      "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
-      "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
-      "dev": true,
-      "dependencies": {
-        "cliui": "^8.0.1",
-        "escalade": "^3.1.1",
-        "get-caller-file": "^2.0.5",
-        "require-directory": "^2.1.1",
-        "string-width": "^4.2.3",
-        "y18n": "^5.0.5",
-        "yargs-parser": "^21.1.1"
-      },
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/yargs-unparser": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
-      "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
-      "dev": true,
-      "dependencies": {
-        "camelcase": "^6.0.0",
-        "decamelize": "^4.0.0",
-        "flat": "^5.0.2",
-        "is-plain-obj": "^2.1.0"
-      },
-      "engines": {
-        "node": ">=10"
-      }
-    },
-    "node_modules/yargs-unparser/node_modules/camelcase": {
-      "version": "6.3.0",
-      "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
-      "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/yargs-unparser/node_modules/decamelize": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
-      "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    },
-    "node_modules/yargs-unparser/node_modules/is-plain-obj": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
-      "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
-      "dev": true,
-      "engines": {
-        "node": ">=8"
-      }
-    },
-    "node_modules/yargs/node_modules/yargs-parser": {
-      "version": "21.1.1",
-      "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
-      "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
-      "dev": true,
-      "engines": {
-        "node": ">=12"
-      }
-    },
-    "node_modules/yocto-queue": {
-      "version": "0.1.0",
-      "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
-      "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
-      "dev": true,
-      "engines": {
-        "node": ">=10"
-      },
-      "funding": {
-        "url": "https://github.com/sponsors/sindresorhus"
-      }
-    }
-  }
-}
diff --git a/package.json b/package.json
index f3aa6df..8cf2f4e 100644
--- a/package.json
+++ b/package.json
@@ -2,34 +2,28 @@
   "name": "@galacean/effects-specification",
   "version": "1.2.0",
   "description": "Galacean Effects JSON Specification",
-  "module": "./dist/index.mjs",
-  "main": "./dist/index.js",
-  "types": "./dist/src/index.d.ts",
+  "module": "./es/index.js",
+  "main": "./es/index.js",
+  "types": "./es/index.d.ts",
   "files": [
-    "dist"
+    "es"
   ],
   "exports": {
     ".": {
-      "import": "./dist/index.mjs",
-      "require": "./dist/index.js",
-      "types": "./dist/src/index.d.ts"
-    },
-    "./dist/fallback": {
-      "import": "./dist/fallback.mjs",
-      "require": "./dist/fallback.js",
-      "types": "./dist/fallback/index.d.ts"
+      "import": "./es/index.js",
+      "require": "./es/index.js",
+      "types": "./es/index.d.ts"
     }
   },
   "scripts": {
     "prebuild": "npm run clean:all",
-    "build": "npm run build:dist",
-    "build:dist": "rollup -c",
-    "lint": "eslint {src,fallback,test} --ext .ts,.mjs",
-    "lint:fix": "eslint {src,fallback,test} --fix --quiet --ext .ts,.mjs",
+    "build": "npm run build:lib",
+    "build:lib": "tsc -b tsconfig.build.json",
+    "lint": "eslint src --ext .ts,.mjs",
+    "lint:fix": "eslint src --fix --quiet --ext .ts,.mjs",
     "check:ts": "tsc -b tsconfig.check.json",
-    "clean:all": "npm run clean:dist",
-    "clean:dist": "rimraf dist/**",
-    "test": "rollup -c --watch --test",
+    "clean:all": "npm run clean:lib",
+    "clean:lib": "rimraf es/**",
     "prepare": "husky install",
     "prepublishOnly": "npm run build"
   },
@@ -37,31 +31,18 @@
     "iOS 9"
   ],
   "devDependencies": {
-    "@commitlint/cli": "^19.2.2",
-    "@commitlint/config-conventional": "^13.2.0",
-    "@rollup/plugin-commonjs": "^21.0.3",
-    "@rollup/plugin-node-resolve": "^13.1.3",
-    "@rollup/plugin-typescript": "^8.3.1",
-    "@types/chai": "^4.3.0",
-    "@types/chai-spies": "^1.0.0",
-    "@types/mocha": "^10.0.1",
-    "@types/node": "^17.0.21",
-    "@typescript-eslint/eslint-plugin": "^5.26.0",
-    "@typescript-eslint/parser": "^5.26.0",
-    "chai": "^4.3.6",
-    "chai-spies": "^1.0.0",
-    "eslint": "^8.13.0",
+    "@commitlint/cli": "^13.2.1",
+    "@commitlint/config-conventional": "^18.4.3",
+    "@typescript-eslint/eslint-plugin": "^7.7.0",
+    "@typescript-eslint/parser": "^7.7.0",
+    "eslint": "^8.56.0",
     "eslint-plugin-compat": "^4.2.0",
     "eslint-plugin-promise": "^6.1.1",
-    "husky": "^7.0.4",
+    "husky": "^9.0.11",
     "lint-staged": "^11.2.6",
-    "mocha": "^10.2.0",
+    "pnpm": "^8.15.7",
     "rimraf": "^3.0.2",
-    "rollup": "^2.70.1",
-    "rollup-plugin-livereload": "^2.0.5",
-    "rollup-plugin-serve": "^1.1.0",
-    "typescript": "^4.6.2",
-    "uuid": "9.0.1"
+    "typescript": "^5.3.3"
   },
   "author": "Ant Group CO., Ltd.",
   "license": "MIT",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
new file mode 100644
index 0000000..e64e68a
--- /dev/null
+++ b/pnpm-lock.yaml
@@ -0,0 +1,2263 @@
+lockfileVersion: '6.0'
+
+settings:
+  autoInstallPeers: true
+  excludeLinksFromLockfile: false
+
+devDependencies:
+  '@commitlint/cli':
+    specifier: ^13.2.1
+    version: 13.2.1
+  '@commitlint/config-conventional':
+    specifier: ^18.4.3
+    version: 18.4.4
+  '@typescript-eslint/eslint-plugin':
+    specifier: ^7.7.0
+    version: 7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.3.3)
+  '@typescript-eslint/parser':
+    specifier: ^7.7.0
+    version: 7.8.0(eslint@8.57.0)(typescript@5.3.3)
+  eslint:
+    specifier: ^8.56.0
+    version: 8.57.0
+  eslint-plugin-compat:
+    specifier: ^4.2.0
+    version: 4.2.0(eslint@8.57.0)
+  eslint-plugin-promise:
+    specifier: ^6.1.1
+    version: 6.1.1(eslint@8.57.0)
+  husky:
+    specifier: ^9.0.11
+    version: 9.0.11
+  lint-staged:
+    specifier: ^11.2.6
+    version: 11.2.6
+  pnpm:
+    specifier: ^8.15.7
+    version: 8.15.8
+  rimraf:
+    specifier: ^3.0.2
+    version: 3.0.2
+  typescript:
+    specifier: ^5.3.3
+    version: 5.3.3
+
+packages:
+
+  /@babel/code-frame@7.24.2:
+    resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/highlight': 7.24.5
+      picocolors: 1.0.0
+    dev: true
+
+  /@babel/helper-validator-identifier@7.24.5:
+    resolution: {integrity: sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==}
+    engines: {node: '>=6.9.0'}
+    dev: true
+
+  /@babel/highlight@7.24.5:
+    resolution: {integrity: sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==}
+    engines: {node: '>=6.9.0'}
+    dependencies:
+      '@babel/helper-validator-identifier': 7.24.5
+      chalk: 2.4.2
+      js-tokens: 4.0.0
+      picocolors: 1.0.0
+    dev: true
+
+  /@commitlint/cli@13.2.1:
+    resolution: {integrity: sha512-JGzYk2ay5JkRS5w+FLQzr0u/Kih52ds4HPpa3vnwVOQN8Q+S1VYr8Nk/6kRm6uNYsAcC1nejtuDxRdLcLh/9TA==}
+    engines: {node: '>=v12'}
+    hasBin: true
+    dependencies:
+      '@commitlint/format': 13.2.0
+      '@commitlint/lint': 13.2.0
+      '@commitlint/load': 13.2.1
+      '@commitlint/read': 13.2.0
+      '@commitlint/types': 13.2.0
+      lodash: 4.17.21
+      resolve-from: 5.0.0
+      resolve-global: 1.0.0
+      yargs: 17.7.2
+    dev: true
+
+  /@commitlint/config-conventional@18.4.4:
+    resolution: {integrity: sha512-Bz3sPQSboBN+Et/KyZrR+OJ3z9PrHDw7Bls0/hv94PmuHBtMq1dCGxS9XzTGzxeMNlytCC4kxF083tbhPljl3Q==}
+    engines: {node: '>=v18'}
+    dependencies:
+      conventional-changelog-conventionalcommits: 7.0.2
+    dev: true
+
+  /@commitlint/ensure@13.2.0:
+    resolution: {integrity: sha512-rqhT62RehdLTRBu8OrPHnRCCd/7RmHEE4TiTlT4BLlr5ls5jlZhecOQWJ8np872uCNirrJ5NFjnjYYdbkNoW9Q==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/types': 13.2.0
+      lodash: 4.17.21
+    dev: true
+
+  /@commitlint/execute-rule@13.2.0:
+    resolution: {integrity: sha512-6nPwpN0hwTYmsH3WM4hCdN+NrMopgRIuQ0aqZa+jnwMoS/g6ljliQNYfL+m5WO306BaIu1W3yYpbW5aI8gEr0g==}
+    engines: {node: '>=v12'}
+    dev: true
+
+  /@commitlint/format@13.2.0:
+    resolution: {integrity: sha512-yNBQJe6YFhM1pJAta4LvzQxccSKof6axJH7ALYjuhQqfT8AKlad7Y/2SuJ07ioyreNIqwOTuF2UfU8yJ7JzEIQ==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/types': 13.2.0
+      chalk: 4.1.2
+    dev: true
+
+  /@commitlint/is-ignored@13.2.0:
+    resolution: {integrity: sha512-onnx4WctHFPPkHGFFAZBIWRSaNwuhixIIfbwPhcZ6IewwQX5n4jpjwM1GokA7vhlOnQ57W7AavbKUGjzIVtnRQ==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/types': 13.2.0
+      semver: 7.3.5
+    dev: true
+
+  /@commitlint/lint@13.2.0:
+    resolution: {integrity: sha512-5XYkh0e9ehHjA7BxAHFpjPgr1qqbFY8OFG1wpBiAhycbYBtJnQmculA2wcwqTM40YCUBqEvWFdq86jTG8fbkMw==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/is-ignored': 13.2.0
+      '@commitlint/parse': 13.2.0
+      '@commitlint/rules': 13.2.0
+      '@commitlint/types': 13.2.0
+    dev: true
+
+  /@commitlint/load@13.2.1:
+    resolution: {integrity: sha512-qlaJkj0hfa9gtWRfCfbgFBTK3GYQRmjZhba4l9mUu4wV9lEZ4ICFlrLtd/8kaLXf/8xbrPhkAPkVFOAqM0YwUQ==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/execute-rule': 13.2.0
+      '@commitlint/resolve-extends': 13.2.0
+      '@commitlint/types': 13.2.0
+      '@endemolshinegroup/cosmiconfig-typescript-loader': 3.0.2(cosmiconfig@7.1.0)(typescript@4.9.5)
+      chalk: 4.1.2
+      cosmiconfig: 7.1.0
+      lodash: 4.17.21
+      resolve-from: 5.0.0
+      typescript: 4.9.5
+    dev: true
+
+  /@commitlint/message@13.2.0:
+    resolution: {integrity: sha512-+LlErJj2F2AC86xJb33VJIvSt25xqSF1I0b0GApSgoUtQBeJhx4SxIj1BLvGcLVmbRmbgTzAFq/QylwLId7EhA==}
+    engines: {node: '>=v12'}
+    dev: true
+
+  /@commitlint/parse@13.2.0:
+    resolution: {integrity: sha512-AtfKSQJQADbDhW+kuC5PxOyBANsYCuuJlZRZ2PYslOz2rvWwZ93zt+nKjM4g7C9ETbz0uq4r7/EoOsTJ2nJqfQ==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/types': 13.2.0
+      conventional-changelog-angular: 5.0.13
+      conventional-commits-parser: 3.2.4
+    dev: true
+
+  /@commitlint/read@13.2.0:
+    resolution: {integrity: sha512-7db5e1Bn3re6hQN0SqygTMF/QX6/MQauoJn3wJiUHE93lvwO6aFQxT3qAlYeyBPwfWsmDz/uSH454jtrSsv3Uw==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/top-level': 13.2.0
+      '@commitlint/types': 13.2.0
+      fs-extra: 10.1.0
+      git-raw-commits: 2.0.11
+    dev: true
+
+  /@commitlint/resolve-extends@13.2.0:
+    resolution: {integrity: sha512-HLCMkqMKtvl1yYLZ1Pm0UpFvd0kYjsm1meLOGZ7VkOd9G/XX+Fr1S2G5AT2zeiDw7WUVYK8lGVMNa319bnV+aw==}
+    engines: {node: '>=v12'}
+    dependencies:
+      import-fresh: 3.3.0
+      lodash: 4.17.21
+      resolve-from: 5.0.0
+      resolve-global: 1.0.0
+    dev: true
+
+  /@commitlint/rules@13.2.0:
+    resolution: {integrity: sha512-O3A9S7blOzvHfzrJrUQe9JxdtGy154ol/GXHwvd8WfMJ10y5ryBB4b6+0YZ1XhItWzrEASOfOKbD++EdLV90dQ==}
+    engines: {node: '>=v12'}
+    dependencies:
+      '@commitlint/ensure': 13.2.0
+      '@commitlint/message': 13.2.0
+      '@commitlint/to-lines': 13.2.0
+      '@commitlint/types': 13.2.0
+      execa: 5.1.1
+    dev: true
+
+  /@commitlint/to-lines@13.2.0:
+    resolution: {integrity: sha512-ZfWZix2y/CzewReCrj5g0nKOEfj5HW9eBMDrqjJJMPApve00CWv0tYrFCGXuGlv244lW4uvWJt6J/0HLRWsfyg==}
+    engines: {node: '>=v12'}
+    dev: true
+
+  /@commitlint/top-level@13.2.0:
+    resolution: {integrity: sha512-knBvWYbIq6VV6VPHrVeDsxDiJq4Zq6cv5NIYU3iesKAsmK2KlLfsZPa+Ig96Y4AqAPU3zNJwjHxYkz9qxdBbfA==}
+    engines: {node: '>=v12'}
+    dependencies:
+      find-up: 5.0.0
+    dev: true
+
+  /@commitlint/types@13.2.0:
+    resolution: {integrity: sha512-RRVHEqmk1qn/dIaSQhvuca6k/6Z54G+r/KyimZ8gnAFielGiGUpsFRhIY3qhd5rXClVxDaa3nlcyTWckSccotQ==}
+    engines: {node: '>=v12'}
+    dependencies:
+      chalk: 4.1.2
+    dev: true
+
+  /@endemolshinegroup/cosmiconfig-typescript-loader@3.0.2(cosmiconfig@7.1.0)(typescript@4.9.5):
+    resolution: {integrity: sha512-QRVtqJuS1mcT56oHpVegkKBlgtWjXw/gHNWO3eL9oyB5Sc7HBoc2OLG/nYpVfT/Jejvo3NUrD0Udk7XgoyDKkA==}
+    engines: {node: '>=10.0.0'}
+    peerDependencies:
+      cosmiconfig: '>=6'
+    dependencies:
+      cosmiconfig: 7.1.0
+      lodash.get: 4.4.2
+      make-error: 1.3.6
+      ts-node: 9.1.1(typescript@4.9.5)
+      tslib: 2.6.2
+    transitivePeerDependencies:
+      - typescript
+    dev: true
+
+  /@eslint-community/eslint-utils@4.4.0(eslint@8.57.0):
+    resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
+    dependencies:
+      eslint: 8.57.0
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /@eslint-community/regexpp@4.10.0:
+    resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
+    engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
+    dev: true
+
+  /@eslint/eslintrc@2.1.4:
+    resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dependencies:
+      ajv: 6.12.6
+      debug: 4.3.4(supports-color@8.1.1)
+      espree: 9.6.1
+      globals: 13.24.0
+      ignore: 5.3.1
+      import-fresh: 3.3.0
+      js-yaml: 4.1.0
+      minimatch: 3.1.2
+      strip-json-comments: 3.1.1
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@eslint/js@8.57.0:
+    resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dev: true
+
+  /@humanwhocodes/config-array@0.11.14:
+    resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
+    engines: {node: '>=10.10.0'}
+    dependencies:
+      '@humanwhocodes/object-schema': 2.0.3
+      debug: 4.3.4(supports-color@8.1.1)
+      minimatch: 3.1.2
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@humanwhocodes/module-importer@1.0.1:
+    resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
+    engines: {node: '>=12.22'}
+    dev: true
+
+  /@humanwhocodes/object-schema@2.0.3:
+    resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==}
+    dev: true
+
+  /@mdn/browser-compat-data@5.5.25:
+    resolution: {integrity: sha512-0AobSA9fCuAoJnBSIIWWpoAEuyWC3gCG5u2TshSDHzMOAO4/ef2Lv6Qma+u/wMnH3oPP3tOWsNeZMbazgkiuDg==}
+    dev: true
+
+  /@nodelib/fs.scandir@2.1.5:
+    resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
+    engines: {node: '>= 8'}
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      run-parallel: 1.2.0
+    dev: true
+
+  /@nodelib/fs.stat@2.0.5:
+    resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==}
+    engines: {node: '>= 8'}
+    dev: true
+
+  /@nodelib/fs.walk@1.2.8:
+    resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
+    engines: {node: '>= 8'}
+    dependencies:
+      '@nodelib/fs.scandir': 2.1.5
+      fastq: 1.17.1
+    dev: true
+
+  /@types/json-schema@7.0.15:
+    resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==}
+    dev: true
+
+  /@types/minimist@1.2.5:
+    resolution: {integrity: sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==}
+    dev: true
+
+  /@types/normalize-package-data@2.4.4:
+    resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
+    dev: true
+
+  /@types/parse-json@4.0.2:
+    resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==}
+    dev: true
+
+  /@types/semver@7.5.8:
+    resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==}
+    dev: true
+
+  /@typescript-eslint/eslint-plugin@7.8.0(@typescript-eslint/parser@7.8.0)(eslint@8.57.0)(typescript@5.3.3):
+    resolution: {integrity: sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      '@typescript-eslint/parser': ^7.0.0
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@eslint-community/regexpp': 4.10.0
+      '@typescript-eslint/parser': 7.8.0(eslint@8.57.0)(typescript@5.3.3)
+      '@typescript-eslint/scope-manager': 7.8.0
+      '@typescript-eslint/type-utils': 7.8.0(eslint@8.57.0)(typescript@5.3.3)
+      '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.3.3)
+      '@typescript-eslint/visitor-keys': 7.8.0
+      debug: 4.3.4(supports-color@8.1.1)
+      eslint: 8.57.0
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      natural-compare: 1.4.0
+      semver: 7.6.0
+      ts-api-utils: 1.3.0(typescript@5.3.3)
+      typescript: 5.3.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/parser@7.8.0(eslint@8.57.0)(typescript@5.3.3):
+    resolution: {integrity: sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/scope-manager': 7.8.0
+      '@typescript-eslint/types': 7.8.0
+      '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.3.3)
+      '@typescript-eslint/visitor-keys': 7.8.0
+      debug: 4.3.4(supports-color@8.1.1)
+      eslint: 8.57.0
+      typescript: 5.3.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/scope-manager@7.8.0:
+    resolution: {integrity: sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dependencies:
+      '@typescript-eslint/types': 7.8.0
+      '@typescript-eslint/visitor-keys': 7.8.0
+    dev: true
+
+  /@typescript-eslint/type-utils@7.8.0(eslint@8.57.0)(typescript@5.3.3):
+    resolution: {integrity: sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.3.3)
+      '@typescript-eslint/utils': 7.8.0(eslint@8.57.0)(typescript@5.3.3)
+      debug: 4.3.4(supports-color@8.1.1)
+      eslint: 8.57.0
+      ts-api-utils: 1.3.0(typescript@5.3.3)
+      typescript: 5.3.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/types@7.8.0:
+    resolution: {integrity: sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dev: true
+
+  /@typescript-eslint/typescript-estree@7.8.0(typescript@5.3.3):
+    resolution: {integrity: sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      typescript: '*'
+    peerDependenciesMeta:
+      typescript:
+        optional: true
+    dependencies:
+      '@typescript-eslint/types': 7.8.0
+      '@typescript-eslint/visitor-keys': 7.8.0
+      debug: 4.3.4(supports-color@8.1.1)
+      globby: 11.1.0
+      is-glob: 4.0.3
+      minimatch: 9.0.4
+      semver: 7.6.0
+      ts-api-utils: 1.3.0(typescript@5.3.3)
+      typescript: 5.3.3
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /@typescript-eslint/utils@7.8.0(eslint@8.57.0)(typescript@5.3.3):
+    resolution: {integrity: sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    peerDependencies:
+      eslint: ^8.56.0
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+      '@types/json-schema': 7.0.15
+      '@types/semver': 7.5.8
+      '@typescript-eslint/scope-manager': 7.8.0
+      '@typescript-eslint/types': 7.8.0
+      '@typescript-eslint/typescript-estree': 7.8.0(typescript@5.3.3)
+      eslint: 8.57.0
+      semver: 7.6.0
+    transitivePeerDependencies:
+      - supports-color
+      - typescript
+    dev: true
+
+  /@typescript-eslint/visitor-keys@7.8.0:
+    resolution: {integrity: sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==}
+    engines: {node: ^18.18.0 || >=20.0.0}
+    dependencies:
+      '@typescript-eslint/types': 7.8.0
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /@ungap/structured-clone@1.2.0:
+    resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
+    dev: true
+
+  /JSONStream@1.3.5:
+    resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==}
+    hasBin: true
+    dependencies:
+      jsonparse: 1.3.1
+      through: 2.3.8
+    dev: true
+
+  /acorn-jsx@5.3.2(acorn@8.11.3):
+    resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
+    peerDependencies:
+      acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
+    dependencies:
+      acorn: 8.11.3
+    dev: true
+
+  /acorn@8.11.3:
+    resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==}
+    engines: {node: '>=0.4.0'}
+    hasBin: true
+    dev: true
+
+  /aggregate-error@3.1.0:
+    resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==}
+    engines: {node: '>=8'}
+    dependencies:
+      clean-stack: 2.2.0
+      indent-string: 4.0.0
+    dev: true
+
+  /ajv@6.12.6:
+    resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+    dependencies:
+      fast-deep-equal: 3.1.3
+      fast-json-stable-stringify: 2.1.0
+      json-schema-traverse: 0.4.1
+      uri-js: 4.4.1
+    dev: true
+
+  /ansi-colors@4.1.3:
+    resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /ansi-escapes@4.3.2:
+    resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      type-fest: 0.21.3
+    dev: true
+
+  /ansi-regex@5.0.1:
+    resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /ansi-styles@3.2.1:
+    resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+    engines: {node: '>=4'}
+    dependencies:
+      color-convert: 1.9.3
+    dev: true
+
+  /ansi-styles@4.3.0:
+    resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+    engines: {node: '>=8'}
+    dependencies:
+      color-convert: 2.0.1
+    dev: true
+
+  /arg@4.1.3:
+    resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==}
+    dev: true
+
+  /argparse@2.0.1:
+    resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+    dev: true
+
+  /array-ify@1.0.0:
+    resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
+    dev: true
+
+  /array-union@2.1.0:
+    resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /arrify@1.0.1:
+    resolution: {integrity: sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /ast-metadata-inferer@0.8.0:
+    resolution: {integrity: sha512-jOMKcHht9LxYIEQu+RVd22vtgrPaVCtDRQ/16IGmurdzxvYbDd5ynxjnyrzLnieG96eTcAyaoj/wN/4/1FyyeA==}
+    dependencies:
+      '@mdn/browser-compat-data': 5.5.25
+    dev: true
+
+  /astral-regex@2.0.0:
+    resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /balanced-match@1.0.2:
+    resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+    dev: true
+
+  /brace-expansion@1.1.11:
+    resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+    dependencies:
+      balanced-match: 1.0.2
+      concat-map: 0.0.1
+    dev: true
+
+  /brace-expansion@2.0.1:
+    resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+    dependencies:
+      balanced-match: 1.0.2
+    dev: true
+
+  /braces@3.0.2:
+    resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==}
+    engines: {node: '>=8'}
+    dependencies:
+      fill-range: 7.0.1
+    dev: true
+
+  /browserslist@4.23.0:
+    resolution: {integrity: sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==}
+    engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+    hasBin: true
+    dependencies:
+      caniuse-lite: 1.0.30001616
+      electron-to-chromium: 1.4.757
+      node-releases: 2.0.14
+      update-browserslist-db: 1.0.15(browserslist@4.23.0)
+    dev: true
+
+  /buffer-from@1.1.2:
+    resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+    dev: true
+
+  /callsites@3.1.0:
+    resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /camelcase-keys@6.2.2:
+    resolution: {integrity: sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==}
+    engines: {node: '>=8'}
+    dependencies:
+      camelcase: 5.3.1
+      map-obj: 4.3.0
+      quick-lru: 4.0.1
+    dev: true
+
+  /camelcase@5.3.1:
+    resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /caniuse-lite@1.0.30001616:
+    resolution: {integrity: sha512-RHVYKov7IcdNjVHJFNY/78RdG4oGVjbayxv8u5IO74Wv7Hlq4PnJE6mo/OjFijjVFNy5ijnCt6H3IIo4t+wfEw==}
+    dev: true
+
+  /chalk@2.4.2:
+    resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+    engines: {node: '>=4'}
+    dependencies:
+      ansi-styles: 3.2.1
+      escape-string-regexp: 1.0.5
+      supports-color: 5.5.0
+    dev: true
+
+  /chalk@4.1.2:
+    resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-styles: 4.3.0
+      supports-color: 7.2.0
+    dev: true
+
+  /clean-stack@2.2.0:
+    resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /cli-cursor@3.1.0:
+    resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==}
+    engines: {node: '>=8'}
+    dependencies:
+      restore-cursor: 3.1.0
+    dev: true
+
+  /cli-truncate@2.1.0:
+    resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
+    engines: {node: '>=8'}
+    dependencies:
+      slice-ansi: 3.0.0
+      string-width: 4.2.3
+    dev: true
+
+  /cliui@8.0.1:
+    resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+      wrap-ansi: 7.0.0
+    dev: true
+
+  /color-convert@1.9.3:
+    resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+    dependencies:
+      color-name: 1.1.3
+    dev: true
+
+  /color-convert@2.0.1:
+    resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+    engines: {node: '>=7.0.0'}
+    dependencies:
+      color-name: 1.1.4
+    dev: true
+
+  /color-name@1.1.3:
+    resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+    dev: true
+
+  /color-name@1.1.4:
+    resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+    dev: true
+
+  /colorette@1.4.0:
+    resolution: {integrity: sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==}
+    dev: true
+
+  /colorette@2.0.20:
+    resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==}
+    dev: true
+
+  /commander@8.3.0:
+    resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==}
+    engines: {node: '>= 12'}
+    dev: true
+
+  /compare-func@2.0.0:
+    resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==}
+    dependencies:
+      array-ify: 1.0.0
+      dot-prop: 5.3.0
+    dev: true
+
+  /concat-map@0.0.1:
+    resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+    dev: true
+
+  /conventional-changelog-angular@5.0.13:
+    resolution: {integrity: sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==}
+    engines: {node: '>=10'}
+    dependencies:
+      compare-func: 2.0.0
+      q: 1.5.1
+    dev: true
+
+  /conventional-changelog-conventionalcommits@7.0.2:
+    resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==}
+    engines: {node: '>=16'}
+    dependencies:
+      compare-func: 2.0.0
+    dev: true
+
+  /conventional-commits-parser@3.2.4:
+    resolution: {integrity: sha512-nK7sAtfi+QXbxHCYfhpZsfRtaitZLIA6889kFIouLvz6repszQDgxBu7wf2WbU+Dco7sAnNCJYERCwt54WPC2Q==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dependencies:
+      JSONStream: 1.3.5
+      is-text-path: 1.0.1
+      lodash: 4.17.21
+      meow: 8.1.2
+      split2: 3.2.2
+      through2: 4.0.2
+    dev: true
+
+  /cosmiconfig@7.1.0:
+    resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==}
+    engines: {node: '>=10'}
+    dependencies:
+      '@types/parse-json': 4.0.2
+      import-fresh: 3.3.0
+      parse-json: 5.2.0
+      path-type: 4.0.0
+      yaml: 1.10.2
+    dev: true
+
+  /create-require@1.1.1:
+    resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==}
+    dev: true
+
+  /cross-spawn@7.0.3:
+    resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+    engines: {node: '>= 8'}
+    dependencies:
+      path-key: 3.1.1
+      shebang-command: 2.0.0
+      which: 2.0.2
+    dev: true
+
+  /dargs@7.0.0:
+    resolution: {integrity: sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /debug@4.3.4(supports-color@8.1.1):
+    resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+    engines: {node: '>=6.0'}
+    peerDependencies:
+      supports-color: '*'
+    peerDependenciesMeta:
+      supports-color:
+        optional: true
+    dependencies:
+      ms: 2.1.2
+      supports-color: 8.1.1
+    dev: true
+
+  /decamelize-keys@1.1.1:
+    resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      decamelize: 1.2.0
+      map-obj: 1.0.1
+    dev: true
+
+  /decamelize@1.2.0:
+    resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /deep-is@0.1.4:
+    resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
+    dev: true
+
+  /diff@4.0.2:
+    resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==}
+    engines: {node: '>=0.3.1'}
+    dev: true
+
+  /dir-glob@3.0.1:
+    resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==}
+    engines: {node: '>=8'}
+    dependencies:
+      path-type: 4.0.0
+    dev: true
+
+  /doctrine@3.0.0:
+    resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+    engines: {node: '>=6.0.0'}
+    dependencies:
+      esutils: 2.0.3
+    dev: true
+
+  /dot-prop@5.3.0:
+    resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
+    engines: {node: '>=8'}
+    dependencies:
+      is-obj: 2.0.0
+    dev: true
+
+  /electron-to-chromium@1.4.757:
+    resolution: {integrity: sha512-jftDaCknYSSt/+KKeXzH3LX5E2CvRLm75P3Hj+J/dv3CL0qUYcOt13d5FN1NiL5IJbbhzHrb3BomeG2tkSlZmw==}
+    dev: true
+
+  /emoji-regex@8.0.0:
+    resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+    dev: true
+
+  /enquirer@2.4.1:
+    resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      ansi-colors: 4.1.3
+      strip-ansi: 6.0.1
+    dev: true
+
+  /error-ex@1.3.2:
+    resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
+    dependencies:
+      is-arrayish: 0.2.1
+    dev: true
+
+  /escalade@3.1.2:
+    resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /escape-string-regexp@1.0.5:
+    resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+    engines: {node: '>=0.8.0'}
+    dev: true
+
+  /escape-string-regexp@4.0.0:
+    resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /eslint-plugin-compat@4.2.0(eslint@8.57.0):
+    resolution: {integrity: sha512-RDKSYD0maWy5r7zb5cWQS+uSPc26mgOzdORJ8hxILmWM7S/Ncwky7BcAtXVY5iRbKjBdHsWU8Yg7hfoZjtkv7w==}
+    engines: {node: '>=14.x'}
+    peerDependencies:
+      eslint: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+    dependencies:
+      '@mdn/browser-compat-data': 5.5.25
+      ast-metadata-inferer: 0.8.0
+      browserslist: 4.23.0
+      caniuse-lite: 1.0.30001616
+      eslint: 8.57.0
+      find-up: 5.0.0
+      lodash.memoize: 4.1.2
+      semver: 7.6.0
+    dev: true
+
+  /eslint-plugin-promise@6.1.1(eslint@8.57.0):
+    resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    peerDependencies:
+      eslint: ^7.0.0 || ^8.0.0
+    dependencies:
+      eslint: 8.57.0
+    dev: true
+
+  /eslint-scope@7.2.2:
+    resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dependencies:
+      esrecurse: 4.3.0
+      estraverse: 5.3.0
+    dev: true
+
+  /eslint-visitor-keys@3.4.3:
+    resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dev: true
+
+  /eslint@8.57.0:
+    resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    hasBin: true
+    dependencies:
+      '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+      '@eslint-community/regexpp': 4.10.0
+      '@eslint/eslintrc': 2.1.4
+      '@eslint/js': 8.57.0
+      '@humanwhocodes/config-array': 0.11.14
+      '@humanwhocodes/module-importer': 1.0.1
+      '@nodelib/fs.walk': 1.2.8
+      '@ungap/structured-clone': 1.2.0
+      ajv: 6.12.6
+      chalk: 4.1.2
+      cross-spawn: 7.0.3
+      debug: 4.3.4(supports-color@8.1.1)
+      doctrine: 3.0.0
+      escape-string-regexp: 4.0.0
+      eslint-scope: 7.2.2
+      eslint-visitor-keys: 3.4.3
+      espree: 9.6.1
+      esquery: 1.5.0
+      esutils: 2.0.3
+      fast-deep-equal: 3.1.3
+      file-entry-cache: 6.0.1
+      find-up: 5.0.0
+      glob-parent: 6.0.2
+      globals: 13.24.0
+      graphemer: 1.4.0
+      ignore: 5.3.1
+      imurmurhash: 0.1.4
+      is-glob: 4.0.3
+      is-path-inside: 3.0.3
+      js-yaml: 4.1.0
+      json-stable-stringify-without-jsonify: 1.0.1
+      levn: 0.4.1
+      lodash.merge: 4.6.2
+      minimatch: 3.1.2
+      natural-compare: 1.4.0
+      optionator: 0.9.4
+      strip-ansi: 6.0.1
+      text-table: 0.2.0
+    transitivePeerDependencies:
+      - supports-color
+    dev: true
+
+  /espree@9.6.1:
+    resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
+    engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+    dependencies:
+      acorn: 8.11.3
+      acorn-jsx: 5.3.2(acorn@8.11.3)
+      eslint-visitor-keys: 3.4.3
+    dev: true
+
+  /esquery@1.5.0:
+    resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
+    engines: {node: '>=0.10'}
+    dependencies:
+      estraverse: 5.3.0
+    dev: true
+
+  /esrecurse@4.3.0:
+    resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
+    engines: {node: '>=4.0'}
+    dependencies:
+      estraverse: 5.3.0
+    dev: true
+
+  /estraverse@5.3.0:
+    resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
+    engines: {node: '>=4.0'}
+    dev: true
+
+  /esutils@2.0.3:
+    resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /execa@5.1.1:
+    resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+    engines: {node: '>=10'}
+    dependencies:
+      cross-spawn: 7.0.3
+      get-stream: 6.0.1
+      human-signals: 2.1.0
+      is-stream: 2.0.1
+      merge-stream: 2.0.0
+      npm-run-path: 4.0.1
+      onetime: 5.1.2
+      signal-exit: 3.0.7
+      strip-final-newline: 2.0.0
+    dev: true
+
+  /fast-deep-equal@3.1.3:
+    resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+    dev: true
+
+  /fast-glob@3.3.2:
+    resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==}
+    engines: {node: '>=8.6.0'}
+    dependencies:
+      '@nodelib/fs.stat': 2.0.5
+      '@nodelib/fs.walk': 1.2.8
+      glob-parent: 5.1.2
+      merge2: 1.4.1
+      micromatch: 4.0.5
+    dev: true
+
+  /fast-json-stable-stringify@2.1.0:
+    resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+    dev: true
+
+  /fast-levenshtein@2.0.6:
+    resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==}
+    dev: true
+
+  /fastq@1.17.1:
+    resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==}
+    dependencies:
+      reusify: 1.0.4
+    dev: true
+
+  /file-entry-cache@6.0.1:
+    resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
+    engines: {node: ^10.12.0 || >=12.0.0}
+    dependencies:
+      flat-cache: 3.2.0
+    dev: true
+
+  /fill-range@7.0.1:
+    resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      to-regex-range: 5.0.1
+    dev: true
+
+  /find-up@4.1.0:
+    resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
+    engines: {node: '>=8'}
+    dependencies:
+      locate-path: 5.0.0
+      path-exists: 4.0.0
+    dev: true
+
+  /find-up@5.0.0:
+    resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==}
+    engines: {node: '>=10'}
+    dependencies:
+      locate-path: 6.0.0
+      path-exists: 4.0.0
+    dev: true
+
+  /flat-cache@3.2.0:
+    resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
+    engines: {node: ^10.12.0 || >=12.0.0}
+    dependencies:
+      flatted: 3.3.1
+      keyv: 4.5.4
+      rimraf: 3.0.2
+    dev: true
+
+  /flatted@3.3.1:
+    resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
+    dev: true
+
+  /fs-extra@10.1.0:
+    resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+    engines: {node: '>=12'}
+    dependencies:
+      graceful-fs: 4.2.11
+      jsonfile: 6.1.0
+      universalify: 2.0.1
+    dev: true
+
+  /fs.realpath@1.0.0:
+    resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+    dev: true
+
+  /function-bind@1.1.2:
+    resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+    dev: true
+
+  /get-caller-file@2.0.5:
+    resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+    engines: {node: 6.* || 8.* || >= 10.*}
+    dev: true
+
+  /get-own-enumerable-property-symbols@3.0.2:
+    resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==}
+    dev: true
+
+  /get-stream@6.0.1:
+    resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /git-raw-commits@2.0.11:
+    resolution: {integrity: sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dependencies:
+      dargs: 7.0.0
+      lodash: 4.17.21
+      meow: 8.1.2
+      split2: 3.2.2
+      through2: 4.0.2
+    dev: true
+
+  /glob-parent@5.1.2:
+    resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==}
+    engines: {node: '>= 6'}
+    dependencies:
+      is-glob: 4.0.3
+    dev: true
+
+  /glob-parent@6.0.2:
+    resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==}
+    engines: {node: '>=10.13.0'}
+    dependencies:
+      is-glob: 4.0.3
+    dev: true
+
+  /glob@7.2.3:
+    resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+    dependencies:
+      fs.realpath: 1.0.0
+      inflight: 1.0.6
+      inherits: 2.0.4
+      minimatch: 3.1.2
+      once: 1.4.0
+      path-is-absolute: 1.0.1
+    dev: true
+
+  /global-dirs@0.1.1:
+    resolution: {integrity: sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==}
+    engines: {node: '>=4'}
+    dependencies:
+      ini: 1.3.8
+    dev: true
+
+  /globals@13.24.0:
+    resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      type-fest: 0.20.2
+    dev: true
+
+  /globby@11.1.0:
+    resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==}
+    engines: {node: '>=10'}
+    dependencies:
+      array-union: 2.1.0
+      dir-glob: 3.0.1
+      fast-glob: 3.3.2
+      ignore: 5.3.1
+      merge2: 1.4.1
+      slash: 3.0.0
+    dev: true
+
+  /graceful-fs@4.2.11:
+    resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+    dev: true
+
+  /graphemer@1.4.0:
+    resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==}
+    dev: true
+
+  /hard-rejection@2.1.0:
+    resolution: {integrity: sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /has-flag@3.0.0:
+    resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /has-flag@4.0.0:
+    resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /hasown@2.0.2:
+    resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==}
+    engines: {node: '>= 0.4'}
+    dependencies:
+      function-bind: 1.1.2
+    dev: true
+
+  /hosted-git-info@2.8.9:
+    resolution: {integrity: sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==}
+    dev: true
+
+  /hosted-git-info@4.1.0:
+    resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
+    engines: {node: '>=10'}
+    dependencies:
+      lru-cache: 6.0.0
+    dev: true
+
+  /human-signals@2.1.0:
+    resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+    engines: {node: '>=10.17.0'}
+    dev: true
+
+  /husky@9.0.11:
+    resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==}
+    engines: {node: '>=18'}
+    hasBin: true
+    dev: true
+
+  /ignore@5.3.1:
+    resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
+    engines: {node: '>= 4'}
+    dev: true
+
+  /import-fresh@3.3.0:
+    resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
+    engines: {node: '>=6'}
+    dependencies:
+      parent-module: 1.0.1
+      resolve-from: 4.0.0
+    dev: true
+
+  /imurmurhash@0.1.4:
+    resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==}
+    engines: {node: '>=0.8.19'}
+    dev: true
+
+  /indent-string@4.0.0:
+    resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /inflight@1.0.6:
+    resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+    dependencies:
+      once: 1.4.0
+      wrappy: 1.0.2
+    dev: true
+
+  /inherits@2.0.4:
+    resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+    dev: true
+
+  /ini@1.3.8:
+    resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+    dev: true
+
+  /is-arrayish@0.2.1:
+    resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
+    dev: true
+
+  /is-core-module@2.13.1:
+    resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==}
+    dependencies:
+      hasown: 2.0.2
+    dev: true
+
+  /is-extglob@2.1.1:
+    resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-fullwidth-code-point@3.0.0:
+    resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-glob@4.0.3:
+    resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      is-extglob: 2.1.1
+    dev: true
+
+  /is-number@7.0.0:
+    resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
+    engines: {node: '>=0.12.0'}
+    dev: true
+
+  /is-obj@1.0.1:
+    resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-obj@2.0.0:
+    resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-path-inside@3.0.3:
+    resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-plain-obj@1.1.0:
+    resolution: {integrity: sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-regexp@1.0.0:
+    resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /is-stream@2.0.1:
+    resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /is-text-path@1.0.1:
+    resolution: {integrity: sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==}
+    engines: {node: '>=0.10.0'}
+    dependencies:
+      text-extensions: 1.9.0
+    dev: true
+
+  /isexe@2.0.0:
+    resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+    dev: true
+
+  /js-tokens@4.0.0:
+    resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+    dev: true
+
+  /js-yaml@4.1.0:
+    resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+    hasBin: true
+    dependencies:
+      argparse: 2.0.1
+    dev: true
+
+  /json-buffer@3.0.1:
+    resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+    dev: true
+
+  /json-parse-even-better-errors@2.3.1:
+    resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
+    dev: true
+
+  /json-schema-traverse@0.4.1:
+    resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+    dev: true
+
+  /json-stable-stringify-without-jsonify@1.0.1:
+    resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==}
+    dev: true
+
+  /jsonfile@6.1.0:
+    resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+    dependencies:
+      universalify: 2.0.1
+    optionalDependencies:
+      graceful-fs: 4.2.11
+    dev: true
+
+  /jsonparse@1.3.1:
+    resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==}
+    engines: {'0': node >= 0.2.0}
+    dev: true
+
+  /keyv@4.5.4:
+    resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==}
+    dependencies:
+      json-buffer: 3.0.1
+    dev: true
+
+  /kind-of@6.0.3:
+    resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /levn@0.4.1:
+    resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+    dev: true
+
+  /lines-and-columns@1.2.4:
+    resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
+    dev: true
+
+  /lint-staged@11.2.6:
+    resolution: {integrity: sha512-Vti55pUnpvPE0J9936lKl0ngVeTdSZpEdTNhASbkaWX7J5R9OEifo1INBGQuGW4zmy6OG+TcWPJ3m5yuy5Q8Tg==}
+    hasBin: true
+    dependencies:
+      cli-truncate: 2.1.0
+      colorette: 1.4.0
+      commander: 8.3.0
+      cosmiconfig: 7.1.0
+      debug: 4.3.4(supports-color@8.1.1)
+      enquirer: 2.4.1
+      execa: 5.1.1
+      listr2: 3.14.0(enquirer@2.4.1)
+      micromatch: 4.0.5
+      normalize-path: 3.0.0
+      please-upgrade-node: 3.2.0
+      string-argv: 0.3.1
+      stringify-object: 3.3.0
+      supports-color: 8.1.1
+    dev: true
+
+  /listr2@3.14.0(enquirer@2.4.1):
+    resolution: {integrity: sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==}
+    engines: {node: '>=10.0.0'}
+    peerDependencies:
+      enquirer: '>= 2.3.0 < 3'
+    peerDependenciesMeta:
+      enquirer:
+        optional: true
+    dependencies:
+      cli-truncate: 2.1.0
+      colorette: 2.0.20
+      enquirer: 2.4.1
+      log-update: 4.0.0
+      p-map: 4.0.0
+      rfdc: 1.3.1
+      rxjs: 7.8.1
+      through: 2.3.8
+      wrap-ansi: 7.0.0
+    dev: true
+
+  /locate-path@5.0.0:
+    resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
+    engines: {node: '>=8'}
+    dependencies:
+      p-locate: 4.1.0
+    dev: true
+
+  /locate-path@6.0.0:
+    resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==}
+    engines: {node: '>=10'}
+    dependencies:
+      p-locate: 5.0.0
+    dev: true
+
+  /lodash.get@4.4.2:
+    resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==}
+    dev: true
+
+  /lodash.memoize@4.1.2:
+    resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==}
+    dev: true
+
+  /lodash.merge@4.6.2:
+    resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==}
+    dev: true
+
+  /lodash@4.17.21:
+    resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+    dev: true
+
+  /log-update@4.0.0:
+    resolution: {integrity: sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-escapes: 4.3.2
+      cli-cursor: 3.1.0
+      slice-ansi: 4.0.0
+      wrap-ansi: 6.2.0
+    dev: true
+
+  /lru-cache@6.0.0:
+    resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+    engines: {node: '>=10'}
+    dependencies:
+      yallist: 4.0.0
+    dev: true
+
+  /make-error@1.3.6:
+    resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
+    dev: true
+
+  /map-obj@1.0.1:
+    resolution: {integrity: sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /map-obj@4.3.0:
+    resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /meow@8.1.2:
+    resolution: {integrity: sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==}
+    engines: {node: '>=10'}
+    dependencies:
+      '@types/minimist': 1.2.5
+      camelcase-keys: 6.2.2
+      decamelize-keys: 1.1.1
+      hard-rejection: 2.1.0
+      minimist-options: 4.1.0
+      normalize-package-data: 3.0.3
+      read-pkg-up: 7.0.1
+      redent: 3.0.0
+      trim-newlines: 3.0.1
+      type-fest: 0.18.1
+      yargs-parser: 20.2.9
+    dev: true
+
+  /merge-stream@2.0.0:
+    resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+    dev: true
+
+  /merge2@1.4.1:
+    resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
+    engines: {node: '>= 8'}
+    dev: true
+
+  /micromatch@4.0.5:
+    resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      braces: 3.0.2
+      picomatch: 2.3.1
+    dev: true
+
+  /mimic-fn@2.1.0:
+    resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /min-indent@1.0.1:
+    resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /minimatch@3.1.2:
+    resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+    dependencies:
+      brace-expansion: 1.1.11
+    dev: true
+
+  /minimatch@9.0.4:
+    resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==}
+    engines: {node: '>=16 || 14 >=14.17'}
+    dependencies:
+      brace-expansion: 2.0.1
+    dev: true
+
+  /minimist-options@4.1.0:
+    resolution: {integrity: sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==}
+    engines: {node: '>= 6'}
+    dependencies:
+      arrify: 1.0.1
+      is-plain-obj: 1.1.0
+      kind-of: 6.0.3
+    dev: true
+
+  /ms@2.1.2:
+    resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+    dev: true
+
+  /natural-compare@1.4.0:
+    resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
+    dev: true
+
+  /node-releases@2.0.14:
+    resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+    dev: true
+
+  /normalize-package-data@2.5.0:
+    resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
+    dependencies:
+      hosted-git-info: 2.8.9
+      resolve: 1.22.8
+      semver: 5.7.2
+      validate-npm-package-license: 3.0.4
+    dev: true
+
+  /normalize-package-data@3.0.3:
+    resolution: {integrity: sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==}
+    engines: {node: '>=10'}
+    dependencies:
+      hosted-git-info: 4.1.0
+      is-core-module: 2.13.1
+      semver: 7.6.0
+      validate-npm-package-license: 3.0.4
+    dev: true
+
+  /normalize-path@3.0.0:
+    resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /npm-run-path@4.0.1:
+    resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+    engines: {node: '>=8'}
+    dependencies:
+      path-key: 3.1.1
+    dev: true
+
+  /once@1.4.0:
+    resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+    dependencies:
+      wrappy: 1.0.2
+    dev: true
+
+  /onetime@5.1.2:
+    resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+    engines: {node: '>=6'}
+    dependencies:
+      mimic-fn: 2.1.0
+    dev: true
+
+  /optionator@0.9.4:
+    resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      deep-is: 0.1.4
+      fast-levenshtein: 2.0.6
+      levn: 0.4.1
+      prelude-ls: 1.2.1
+      type-check: 0.4.0
+      word-wrap: 1.2.5
+    dev: true
+
+  /p-limit@2.3.0:
+    resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==}
+    engines: {node: '>=6'}
+    dependencies:
+      p-try: 2.2.0
+    dev: true
+
+  /p-limit@3.1.0:
+    resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      yocto-queue: 0.1.0
+    dev: true
+
+  /p-locate@4.1.0:
+    resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==}
+    engines: {node: '>=8'}
+    dependencies:
+      p-limit: 2.3.0
+    dev: true
+
+  /p-locate@5.0.0:
+    resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==}
+    engines: {node: '>=10'}
+    dependencies:
+      p-limit: 3.1.0
+    dev: true
+
+  /p-map@4.0.0:
+    resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      aggregate-error: 3.1.0
+    dev: true
+
+  /p-try@2.2.0:
+    resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /parent-module@1.0.1:
+    resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
+    engines: {node: '>=6'}
+    dependencies:
+      callsites: 3.1.0
+    dev: true
+
+  /parse-json@5.2.0:
+    resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
+    engines: {node: '>=8'}
+    dependencies:
+      '@babel/code-frame': 7.24.2
+      error-ex: 1.3.2
+      json-parse-even-better-errors: 2.3.1
+      lines-and-columns: 1.2.4
+    dev: true
+
+  /path-exists@4.0.0:
+    resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /path-is-absolute@1.0.1:
+    resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /path-key@3.1.1:
+    resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /path-parse@1.0.7:
+    resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==}
+    dev: true
+
+  /path-type@4.0.0:
+    resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /picocolors@1.0.0:
+    resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+    dev: true
+
+  /picomatch@2.3.1:
+    resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
+    engines: {node: '>=8.6'}
+    dev: true
+
+  /please-upgrade-node@3.2.0:
+    resolution: {integrity: sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==}
+    dependencies:
+      semver-compare: 1.0.0
+    dev: true
+
+  /pnpm@8.15.8:
+    resolution: {integrity: sha512-0aAp4aRHrZC8ls1YsPrUhtKZPVMYVjlve6vy2D6xgju4PFo9D8GPZ1stEDIdSesWH+zjb+gTSqWCPs0hX+7Tkg==}
+    engines: {node: '>=16.14'}
+    hasBin: true
+    dev: true
+
+  /prelude-ls@1.2.1:
+    resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
+    engines: {node: '>= 0.8.0'}
+    dev: true
+
+  /punycode@2.3.1:
+    resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /q@1.5.1:
+    resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==}
+    engines: {node: '>=0.6.0', teleport: '>=0.2.0'}
+    dev: true
+
+  /queue-microtask@1.2.3:
+    resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
+    dev: true
+
+  /quick-lru@4.0.1:
+    resolution: {integrity: sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /read-pkg-up@7.0.1:
+    resolution: {integrity: sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==}
+    engines: {node: '>=8'}
+    dependencies:
+      find-up: 4.1.0
+      read-pkg: 5.2.0
+      type-fest: 0.8.1
+    dev: true
+
+  /read-pkg@5.2.0:
+    resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==}
+    engines: {node: '>=8'}
+    dependencies:
+      '@types/normalize-package-data': 2.4.4
+      normalize-package-data: 2.5.0
+      parse-json: 5.2.0
+      type-fest: 0.6.0
+    dev: true
+
+  /readable-stream@3.6.2:
+    resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+    engines: {node: '>= 6'}
+    dependencies:
+      inherits: 2.0.4
+      string_decoder: 1.3.0
+      util-deprecate: 1.0.2
+    dev: true
+
+  /redent@3.0.0:
+    resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
+    engines: {node: '>=8'}
+    dependencies:
+      indent-string: 4.0.0
+      strip-indent: 3.0.0
+    dev: true
+
+  /require-directory@2.1.1:
+    resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /resolve-from@4.0.0:
+    resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
+    engines: {node: '>=4'}
+    dev: true
+
+  /resolve-from@5.0.0:
+    resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /resolve-global@1.0.0:
+    resolution: {integrity: sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==}
+    engines: {node: '>=8'}
+    dependencies:
+      global-dirs: 0.1.1
+    dev: true
+
+  /resolve@1.22.8:
+    resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==}
+    hasBin: true
+    dependencies:
+      is-core-module: 2.13.1
+      path-parse: 1.0.7
+      supports-preserve-symlinks-flag: 1.0.0
+    dev: true
+
+  /restore-cursor@3.1.0:
+    resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==}
+    engines: {node: '>=8'}
+    dependencies:
+      onetime: 5.1.2
+      signal-exit: 3.0.7
+    dev: true
+
+  /reusify@1.0.4:
+    resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==}
+    engines: {iojs: '>=1.0.0', node: '>=0.10.0'}
+    dev: true
+
+  /rfdc@1.3.1:
+    resolution: {integrity: sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==}
+    dev: true
+
+  /rimraf@3.0.2:
+    resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+    hasBin: true
+    dependencies:
+      glob: 7.2.3
+    dev: true
+
+  /run-parallel@1.2.0:
+    resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
+    dependencies:
+      queue-microtask: 1.2.3
+    dev: true
+
+  /rxjs@7.8.1:
+    resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
+    dependencies:
+      tslib: 2.6.2
+    dev: true
+
+  /safe-buffer@5.2.1:
+    resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+    dev: true
+
+  /semver-compare@1.0.0:
+    resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
+    dev: true
+
+  /semver@5.7.2:
+    resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
+    hasBin: true
+    dev: true
+
+  /semver@7.3.5:
+    resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dependencies:
+      lru-cache: 6.0.0
+    dev: true
+
+  /semver@7.6.0:
+    resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==}
+    engines: {node: '>=10'}
+    hasBin: true
+    dependencies:
+      lru-cache: 6.0.0
+    dev: true
+
+  /shebang-command@2.0.0:
+    resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+    engines: {node: '>=8'}
+    dependencies:
+      shebang-regex: 3.0.0
+    dev: true
+
+  /shebang-regex@3.0.0:
+    resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /signal-exit@3.0.7:
+    resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+    dev: true
+
+  /slash@3.0.0:
+    resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /slice-ansi@3.0.0:
+    resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      ansi-styles: 4.3.0
+      astral-regex: 2.0.0
+      is-fullwidth-code-point: 3.0.0
+    dev: true
+
+  /slice-ansi@4.0.0:
+    resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-styles: 4.3.0
+      astral-regex: 2.0.0
+      is-fullwidth-code-point: 3.0.0
+    dev: true
+
+  /source-map-support@0.5.21:
+    resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+    dependencies:
+      buffer-from: 1.1.2
+      source-map: 0.6.1
+    dev: true
+
+  /source-map@0.6.1:
+    resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /spdx-correct@3.2.0:
+    resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
+    dependencies:
+      spdx-expression-parse: 3.0.1
+      spdx-license-ids: 3.0.17
+    dev: true
+
+  /spdx-exceptions@2.5.0:
+    resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
+    dev: true
+
+  /spdx-expression-parse@3.0.1:
+    resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
+    dependencies:
+      spdx-exceptions: 2.5.0
+      spdx-license-ids: 3.0.17
+    dev: true
+
+  /spdx-license-ids@3.0.17:
+    resolution: {integrity: sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==}
+    dev: true
+
+  /split2@3.2.2:
+    resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==}
+    dependencies:
+      readable-stream: 3.6.2
+    dev: true
+
+  /string-argv@0.3.1:
+    resolution: {integrity: sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg==}
+    engines: {node: '>=0.6.19'}
+    dev: true
+
+  /string-width@4.2.3:
+    resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+    engines: {node: '>=8'}
+    dependencies:
+      emoji-regex: 8.0.0
+      is-fullwidth-code-point: 3.0.0
+      strip-ansi: 6.0.1
+    dev: true
+
+  /string_decoder@1.3.0:
+    resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+    dependencies:
+      safe-buffer: 5.2.1
+    dev: true
+
+  /stringify-object@3.3.0:
+    resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==}
+    engines: {node: '>=4'}
+    dependencies:
+      get-own-enumerable-property-symbols: 3.0.2
+      is-obj: 1.0.1
+      is-regexp: 1.0.0
+    dev: true
+
+  /strip-ansi@6.0.1:
+    resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+    engines: {node: '>=8'}
+    dependencies:
+      ansi-regex: 5.0.1
+    dev: true
+
+  /strip-final-newline@2.0.0:
+    resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /strip-indent@3.0.0:
+    resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
+    engines: {node: '>=8'}
+    dependencies:
+      min-indent: 1.0.1
+    dev: true
+
+  /strip-json-comments@3.1.1:
+    resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /supports-color@5.5.0:
+    resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+    engines: {node: '>=4'}
+    dependencies:
+      has-flag: 3.0.0
+    dev: true
+
+  /supports-color@7.2.0:
+    resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+    engines: {node: '>=8'}
+    dependencies:
+      has-flag: 4.0.0
+    dev: true
+
+  /supports-color@8.1.1:
+    resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==}
+    engines: {node: '>=10'}
+    dependencies:
+      has-flag: 4.0.0
+    dev: true
+
+  /supports-preserve-symlinks-flag@1.0.0:
+    resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
+    engines: {node: '>= 0.4'}
+    dev: true
+
+  /text-extensions@1.9.0:
+    resolution: {integrity: sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==}
+    engines: {node: '>=0.10'}
+    dev: true
+
+  /text-table@0.2.0:
+    resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
+    dev: true
+
+  /through2@4.0.2:
+    resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==}
+    dependencies:
+      readable-stream: 3.6.2
+    dev: true
+
+  /through@2.3.8:
+    resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+    dev: true
+
+  /to-regex-range@5.0.1:
+    resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
+    engines: {node: '>=8.0'}
+    dependencies:
+      is-number: 7.0.0
+    dev: true
+
+  /trim-newlines@3.0.1:
+    resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /ts-api-utils@1.3.0(typescript@5.3.3):
+    resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
+    engines: {node: '>=16'}
+    peerDependencies:
+      typescript: '>=4.2.0'
+    dependencies:
+      typescript: 5.3.3
+    dev: true
+
+  /ts-node@9.1.1(typescript@4.9.5):
+    resolution: {integrity: sha512-hPlt7ZACERQGf03M253ytLY3dHbGNGrAq9qIHWUY9XHYl1z7wYngSr3OQ5xmui8o2AaxsONxIzjafLUiWBo1Fg==}
+    engines: {node: '>=10.0.0'}
+    hasBin: true
+    peerDependencies:
+      typescript: '>=2.7'
+    dependencies:
+      arg: 4.1.3
+      create-require: 1.1.1
+      diff: 4.0.2
+      make-error: 1.3.6
+      source-map-support: 0.5.21
+      typescript: 4.9.5
+      yn: 3.1.1
+    dev: true
+
+  /tslib@2.6.2:
+    resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+    dev: true
+
+  /type-check@0.4.0:
+    resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
+    engines: {node: '>= 0.8.0'}
+    dependencies:
+      prelude-ls: 1.2.1
+    dev: true
+
+  /type-fest@0.18.1:
+    resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /type-fest@0.20.2:
+    resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /type-fest@0.21.3:
+    resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /type-fest@0.6.0:
+    resolution: {integrity: sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /type-fest@0.8.1:
+    resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==}
+    engines: {node: '>=8'}
+    dev: true
+
+  /typescript@4.9.5:
+    resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
+    engines: {node: '>=4.2.0'}
+    hasBin: true
+    dev: true
+
+  /typescript@5.3.3:
+    resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==}
+    engines: {node: '>=14.17'}
+    hasBin: true
+    dev: true
+
+  /universalify@2.0.1:
+    resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+    engines: {node: '>= 10.0.0'}
+    dev: true
+
+  /update-browserslist-db@1.0.15(browserslist@4.23.0):
+    resolution: {integrity: sha512-K9HWH62x3/EalU1U6sjSZiylm9C8tgq2mSvshZpqc7QE69RaA2qjhkW2HlNA0tFpEbtyFz7HTqbSdN4MSwUodA==}
+    hasBin: true
+    peerDependencies:
+      browserslist: '>= 4.21.0'
+    dependencies:
+      browserslist: 4.23.0
+      escalade: 3.1.2
+      picocolors: 1.0.0
+    dev: true
+
+  /uri-js@4.4.1:
+    resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+    dependencies:
+      punycode: 2.3.1
+    dev: true
+
+  /util-deprecate@1.0.2:
+    resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+    dev: true
+
+  /validate-npm-package-license@3.0.4:
+    resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
+    dependencies:
+      spdx-correct: 3.2.0
+      spdx-expression-parse: 3.0.1
+    dev: true
+
+  /which@2.0.2:
+    resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+    engines: {node: '>= 8'}
+    hasBin: true
+    dependencies:
+      isexe: 2.0.0
+    dev: true
+
+  /word-wrap@1.2.5:
+    resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
+    engines: {node: '>=0.10.0'}
+    dev: true
+
+  /wrap-ansi@6.2.0:
+    resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
+    engines: {node: '>=8'}
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+    dev: true
+
+  /wrap-ansi@7.0.0:
+    resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+    engines: {node: '>=10'}
+    dependencies:
+      ansi-styles: 4.3.0
+      string-width: 4.2.3
+      strip-ansi: 6.0.1
+    dev: true
+
+  /wrappy@1.0.2:
+    resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+    dev: true
+
+  /y18n@5.0.8:
+    resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /yallist@4.0.0:
+    resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+    dev: true
+
+  /yaml@1.10.2:
+    resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==}
+    engines: {node: '>= 6'}
+    dev: true
+
+  /yargs-parser@20.2.9:
+    resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
+    engines: {node: '>=10'}
+    dev: true
+
+  /yargs-parser@21.1.1:
+    resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+    engines: {node: '>=12'}
+    dev: true
+
+  /yargs@17.7.2:
+    resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+    engines: {node: '>=12'}
+    dependencies:
+      cliui: 8.0.1
+      escalade: 3.1.2
+      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
+    dev: true
+
+  /yn@3.1.1:
+    resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==}
+    engines: {node: '>=6'}
+    dev: true
+
+  /yocto-queue@0.1.0:
+    resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
+    engines: {node: '>=10'}
+    dev: true
diff --git a/rollup.config.js b/rollup.config.js
deleted file mode 100644
index 49aad14..0000000
--- a/rollup.config.js
+++ /dev/null
@@ -1,65 +0,0 @@
-import resolve from '@rollup/plugin-node-resolve';
-import commonjs from '@rollup/plugin-commonjs';
-import typescript from '@rollup/plugin-typescript';
-import serve from 'rollup-plugin-serve';
-import livereload from 'rollup-plugin-livereload';
-
-const pkg = require('./package.json');
-const banner = `/*!
- * Name: ${pkg.name}
- * Description: ${pkg.description}
- * Author: ${pkg.author}
- * Version: v${pkg.version}
- */
-`;
-
-const plugins = [
-  typescript({ tsconfig: './tsconfig.bundle.json' }),
-  resolve(),
-  commonjs({
-    ignoreGlobal: true,
-  }),
-];
-
-export default (commandLineArgs) => {
-  if (commandLineArgs.watch) {
-    const contentBase = '.';
-    const plugins = [
-      typescript({ compilerOptions: { declaration: false, declarationDir: null } }),
-      resolve(),
-      commonjs(),
-      serve({
-        contentBase,
-        host: 'localhost',
-        port: 9003,
-      }),
-      livereload(contentBase),
-    ];
-
-    if (commandLineArgs.test) {
-      // test server 配置
-    }
-  }
-
-  const config = [];
-
-  ['src', 'fallback'].forEach(entry => {
-    config.push({
-      input: `${entry}/index.ts`,
-      output: [{
-        file: entry === 'src' ? pkg.module : `./dist/${entry}.mjs`,
-        format: 'es',
-        banner,
-        sourcemap: true,
-      }, {
-        file: entry === 'src' ? pkg.main : `./dist/${entry}.js`,
-        format: 'cjs',
-        banner,
-        sourcemap: true,
-      }],
-      plugins,
-    });
-  });
-
-  return config;
-}
diff --git a/src/binary.ts b/src/binary.ts
index 36edee0..825ddbf 100644
--- a/src/binary.ts
+++ b/src/binary.ts
@@ -20,7 +20,7 @@ import type { ValueType } from './number-expression';
  */
 export type BinaryPointerContent = [index: number, start?: number, byteLength?: number, type?: BinaryType];
 export type BinaryPointer = [ValueType.BINARY, BinaryPointerContent];
-export type BinaryType = 'u8' | 'i8' | 'i16' | 'u16' | 'f32' | 'u32' | 'i32' | 'f64' | string;
+export type BinaryType = 'u8' | 'i8' | 'i16' | 'u16' | 'f32' | 'u32' | 'i32' | 'f64' | '';
 
 /**
  * 线上二进制地址
diff --git a/src/index.ts b/src/index.ts
index 05468f2..4a56262 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,4 +1,3 @@
-export * from 'uuid/dist/esm-browser/v4';
 export * from './type';
 export * from './composition';
 export * from './image';
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index efef67b..8dbf2f4 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -1,3 +1,5 @@
+/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
+import type { BinaryEnv } from '../binary';
 import {
   END_BEHAVIOR_DESTROY, END_BEHAVIOR_DESTROY_CHILDREN, END_BEHAVIOR_FREEZE, END_BEHAVIOR_RESTART,
 } from '../constants';
@@ -5,10 +7,13 @@ import type { vec3, vec4 } from '../number-expression';
 import type { ItemType, RenderLevel } from '../type';
 import type { CameraContent } from './camera-item';
 import type { CompositionContent } from './composition-item';
+import type { EffectContent } from './effect-item';
 import type { InteractContent } from './interact-item';
+import type { ModelLightContent, ModelMeshItemContent, ModelTreeContent, SkyboxContent } from './model';
 import type { NullContent } from './null-item';
 import type { ParticleContent } from './particle-item';
 import type { PluginContent } from './plugin-item';
+import type { SpineContent } from './spine-item';
 import type { SpriteContent } from './sprite-item';
 import type { TextContent } from './text-item';
 
@@ -142,5 +147,11 @@ export type BaseContent =
   | CompositionContent
   | CameraContent
   | TextContent
+  | SpineContent
+  | EffectContent
+  | ModelTreeContent<BinaryEnv>
+  | ModelMeshItemContent<BinaryEnv>
+  | ModelLightContent
+  | SkyboxContent<BinaryEnv>
   | any
   ;
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index b6d7445..e41b97f 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -5,8 +5,7 @@ import type { GeometryPointer } from './binary';
 import type { vec3 } from '../../number-expression';
 import type { InteractBehavior, ItemType } from '../../type';
 import type { ModelAnimationTrackDataPointer } from './binary';
-import type { ComponentData, DataPath, GeometryData, MaterialData } from '../../components';
-import type { VFXItemData } from 'src/vfx-item-data';
+import type { ComponentData, DataPath } from '../../components';
 
 export type BufferType =
   | WebGLRenderingContext['FLOAT']
diff --git a/src/types/shim.d.ts b/src/types/shim.d.ts
deleted file mode 100644
index 0484f1c..0000000
--- a/src/types/shim.d.ts
+++ /dev/null
@@ -1 +0,0 @@
-declare module 'uuid/dist/esm-browser/v4';
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index e8ab391..74ffc7f 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -23,7 +23,7 @@ export interface VFXItemData extends EffectsObjectData {
    * plugin 模块实现者自由实现命名
    * 2022.12更新: spine: "spine", 陀螺仪: "5"
    */
-  type: ItemType | string,
+  type: ItemType,
   /**
    * 父节点ID
    * 如果父节点无法找到,播放将直接报错
diff --git a/test/cases/composition/composition.test.mjs b/test/cases/composition/composition.test.mjs
deleted file mode 100644
index ed94d17..0000000
--- a/test/cases/composition/composition.test.mjs
+++ /dev/null
@@ -1,110 +0,0 @@
-import { getStandardComposition } from '../../../dist/fallback.mjs';
-
-const { expect } = chai;
-
-describe('composition', () => {
-  it('composition previewSize', () => {
-    const composition = {
-      'name': '帧动画',
-      'id': 3,
-      'endBehavior': 2,
-      'duration': 5,
-      'st': 1.2,
-      'camera': {
-        'fov': 60,
-        'far': 20,
-        'near': 0.1,
-        'position': [0, 0, 8],
-        'clipMode': 0,
-        'z': 8,
-      },
-      'items': [
-        {
-          'name': 'earth',
-          'delay': 0,
-          'id': 12,
-          'ro': 0.01,
-          'sprite': {
-            'options': {
-              'startLifetime': 2,
-              'startSize': 6,
-              'sizeAspect': 1.1183294663573087,
-              'startColor': ['color', [255, 255, 255]],
-              'duration': 2,
-              'gravityModifier': 0,
-              'endBehavior': 4,
-              'renderLevel': 'B+',
-            },
-            'renderer': {
-              'texture': 1,
-              'order': 0,
-            },
-            'transform': {
-              'position': [0.022863817233533368, -0.021775064031936076, -2.5],
-            },
-            'splits': [[0.001953125, 0.001953125, 0.94140625, 0.841796875, 0],
-            ],
-          },
-        },
-      ],
-      'meta': { 'previewSize': [750, 1624] },
-    };
-    const comp = getStandardComposition(composition);
-    const previewSize = comp.previewSize;
-
-    expect(comp.startTime).to.eql(1.2);
-    expect(previewSize?.length, 'previewSize.length').to.eql(2);
-    expect(previewSize?.[0]).to.eql(750, 'previewSize.width');
-    expect(previewSize?.[1]).to.eql(1624, 'previewSize.height');
-
-    const compotision2 = {
-      'name': '帧动画',
-      'id': 3,
-      'endBehavior': 2,
-      'duration': 5,
-      startTime: 2.2,
-      'camera': {
-        'fov': 60,
-        'far': 20,
-        'near': 0.1,
-        'position': [0, 0, 8],
-        'clipMode': 0,
-        'z': 8,
-      },
-      'items': [
-        {
-          'name': 'earth',
-          'delay': 0,
-          'id': 12,
-          'ro': 0.01,
-          'sprite': {
-            'options': {
-              'startLifetime': 2,
-              'startSize': 6,
-              'sizeAspect': 1.1183294663573087,
-              'startColor': ['color', [255, 255, 255]],
-              'duration': 2,
-              'gravityModifier': 0,
-              'endBehavior': 4,
-              'renderLevel': 'B+',
-            },
-            'renderer': {
-              'texture': 1,
-              'order': 0,
-            },
-            'transform': {
-              'position': [0.022863817233533368, -0.021775064031936076, -2.5],
-            },
-            'splits': [[0.001953125, 0.001953125, 0.94140625, 0.841796875, 0],
-            ],
-          },
-        },
-      ],
-    };
-    const comp2 = getStandardComposition(compotision2);
-
-    expect(comp2.startTime).to.eql(2.2);
-    expect(comp2.previewSize).to.be.undefined;
-  });
-
-});
diff --git a/test/cases/image/image.test.mjs b/test/cases/image/image.test.mjs
deleted file mode 100644
index 15ef5cd..0000000
--- a/test/cases/image/image.test.mjs
+++ /dev/null
@@ -1,67 +0,0 @@
-import { getStandardImage } from '../../../dist/fallback.mjs';
-import { RenderLevel } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('images', () => {
-  it('compressed images', () => {
-    const images = [
-      {
-        'compressed': {
-          'android': 'https://gw.alipayobjects.com/os/gltf-asset/mars-cli/OETSLEJGJROX/-1973629481-44fd2.ktx',
-          'iOS': 'https://gw.alipayobjects.com/os/gltf-asset/mars-cli/OETSLEJGJROX/-1973629473-d139a.ktx',
-        },
-        'webp': 'fake_webp',
-        oriY: 1,
-        'url': 'https://gw.alipayobjects.com/zos/gltf-asset/mars-cli/OETSLEJGJROX/760117553-fc8fa.png',
-      },
-    ];
-    const imageTags = [RenderLevel.BPlus];
-
-    images.forEach((image, index) => {
-      const ret = getStandardImage(image, index, imageTags);
-
-      expect(ret.url, 'url').to.be.an('string');
-      expect(ret.compressed.astc).to.eql('https://gw.alipayobjects.com/os/gltf-asset/mars-cli/OETSLEJGJROX/-1973629481-44fd2.ktx');
-      expect(ret.compressed.pvrtc).to.eql('https://gw.alipayobjects.com/os/gltf-asset/mars-cli/OETSLEJGJROX/-1973629473-d139a.ktx');
-      expect(ret.renderLevel).to.eql(RenderLevel.BPlus);
-      expect(ret.webp).to.eql('fake_webp');
-      expect(ret.oriY).to.eql(1);
-    });
-
-  });
-
-  it('template image', () => {
-    const images = [
-      {
-        'template': {
-          'content': '<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="256px" height="512px" viewBox="0 0 444 654" version="1.1"><title>1.3获得卡</title><g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="1.3获得卡"><image id="获得卡-图" x="0" y="96" width="444" height="558" xlink:href="$image_main$"/><image id="获得卡-文" x="36" y="144" width="372" height="165" xlink:href="$image_main2$"/><text id="获得今日品牌身份卡" fill-rule="nonzero" font-family="PingFangSC-Medium, PingFang SC" font-size="45" font-weight="400" fill="#FFFFFF"><tspan x="220" y="48" text-anchor="middle">$name$</tspan></text></g></g></svg>',
-          'width': 256,
-          'height': 512,
-          'backgroundWidth': 256,
-          'backgroundHeight': 512,
-          'variables': {
-            'image_main': 'https://gw.alipayobjects.com/mdn/rms_ab4795/afts/img/A*Ww4OQbMokPYAAAAAAAAAAAAAARQnAQ',
-            'name': '可配置可配置可配置',
-          },
-        },
-        'webp': 'fake_webp',
-        'url': 'https://gw.alipayobjects.com/zos/gltf-asset/mars-cli/NCQSMUABPTXM/-272956899-b18bf.png',
-      },
-    ];
-
-    images.forEach((image, index) => {
-      const ret = getStandardImage(image, index, [RenderLevel.S]);
-      const regex = /<svg(S*?)[^>]*>/;
-
-      expect(ret.url).to.eql('https://gw.alipayobjects.com/zos/gltf-asset/mars-cli/NCQSMUABPTXM/-272956899-b18bf.png', 'url');
-      expect(ret.template.content).to.match(regex);
-      expect(ret.template.variables).to.eql({
-        'image_main': 'https://gw.alipayobjects.com/mdn/rms_ab4795/afts/img/A*Ww4OQbMokPYAAAAAAAAAAAAAARQnAQ',
-        'name': '可配置可配置可配置',
-      });
-      expect(ret.webp).to.eql('fake_webp');
-    });
-  });
-
-});
diff --git a/test/cases/index.mjs b/test/cases/index.mjs
deleted file mode 100644
index 4e5fa69..0000000
--- a/test/cases/index.mjs
+++ /dev/null
@@ -1,12 +0,0 @@
-import './sprite/base.test.mjs';
-import './sprite/filter.test.mjs';
-import './particle/base.test.mjs';
-import './particle/trails.test.mjs';
-import './null/base.test.mjs';
-import './null/end-behavior.test.mjs';
-import './composition/composition.test.mjs';
-import './image/image.test.mjs';
-import './ui/ui.test.mjs';
-import './model/index.test.mjs';
-import './model/camera.test.mjs';
-
diff --git a/test/cases/model/camera.test.mjs b/test/cases/model/camera.test.mjs
deleted file mode 100644
index e1d8792..0000000
--- a/test/cases/model/camera.test.mjs
+++ /dev/null
@@ -1,163 +0,0 @@
-import { getStandardItem, ensureFixedNumber } from '../../../dist/fallback.mjs';
-import { ItemEndBehavior, ItemType, ValueType } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('camera item', () => {
-  it('camera duration,delay,renderLevel,type, transform, options', () => {
-    const item = {
-      'name': '3DModel_1',
-      'delay': 1,
-      'id': 14,
-      'model': {
-        'options': {
-          'type': 1,
-          'duration': 5,
-          'near': 0.2,
-          'far': ['curve', [[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]]],
-          'fov': ['lines', [[0, 15], [1, 20]]],
-          'clipMode': 1,
-          'renderLevel': 'B+',
-          'startSize': 0,
-          'looping': false,
-        },
-        'transform': { 'position': [0, 0, 12], 'rotation': [10, 20, 30] },
-      },
-    };
-
-    const neo = getStandardItem(item);
-
-    expect(neo.delay).to.eql(1, 'delay');
-    expect(neo.duration).to.eql(5, 'duration');
-    expect(neo.renderLevel).to.eql('B+', 'renderLevel');
-    expect(neo.endBehavior).to.eql(ItemEndBehavior.destroy);
-    expect(neo.type).to.eql(ItemType.camera);
-    expect(neo.transform.position).to.eql([0, 0, 12], 'position');
-    expect(neo.transform.rotation).to.eql([10, 20, 30], 'rotation');
-
-    const opt = neo.content.options;
-    const nearFixed = ensureFixedNumber(opt.near);
-    const fovFixed = ensureFixedNumber(opt.fov);
-    const farFixed = ensureFixedNumber(opt.far);
-
-    expect(nearFixed[0]).to.eql(ValueType.CONSTANT, 'near.type');
-    expect(nearFixed[1]).to.eql(0.2, 'near.value');
-    expect(fovFixed[0]).to.eql(ValueType.LINE, 'fov.type');
-    expect(fovFixed[1]).to.eql([[0, 15], [1, 20]], 'fov.value');
-    expect(farFixed[0]).to.eql(ValueType.BEZIER_CURVE, 'far.type');
-    // expect(farFixed[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'far.value');
-    expect(opt.clipMode).to.eql(1);
-  });
-
-  it('camera rotationOverLifetime', () => {
-    const item = {
-      'name': '3DModel_1',
-      'delay': 1,
-      'id': 14,
-      'model': {
-        'options': {
-          'type': 1,
-          'duration': 5,
-          'near': 0.2,
-          'far': 20,
-          'fov': 30,
-          'renderLevel': 'B+',
-          'startSize': 0,
-          'looping': false,
-        },
-        'rotationOverLifetime': {
-          'separateAxes': true,
-          'rotateX': 2,
-          'rotateY': ['curve', [[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]]],
-          'rotateZ': ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const rol = neo.content.rotationOverLifetime;
-
-    expect(rol.separateAxes).to.be.true;
-    expect(rol.x[0]).to.eql(ValueType.CONSTANT, 'x.type');
-    expect(rol.x[1]).to.eql(2, 'x.value');
-    expect(rol.y[0]).to.eql(ValueType.BEZIER_CURVE, 'y.type');
-    // expect(rol.y[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'y.value');
-    expect(rol.z[0]).to.eql(ValueType.LINE, 'z.value');
-    expect(rol.z[1]).to.eql([[0, 1], [0.5, 0], [1, 1]], 'z.value');
-  });
-
-  it('camera positionOverLifetime', () => {
-    const item = {
-      'name': '3DModel_1',
-      'delay': 1,
-      'id': 14,
-      'model': {
-        'options': {
-          'type': 1,
-          'duration': 5,
-          'near': 0.2,
-          'far': 20,
-          'fov': 30,
-          'renderLevel': 'B+',
-          'startSize': 0,
-          'looping': false,
-        },
-        'velocityOverLifetime': {
-          'translateX': ['lines', [[0, -1], [1, 3]]],
-          'translateY': 1,
-          'translateZ': ['curve', [[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const pol = neo.content.positionOverLifetime;
-
-    expect(pol.linearX[0]).to.eql(ValueType.LINE, 'linearX.type');
-    expect(pol.linearX[1]).to.eql([[0, -1], [1, 3]], 'linearX.value');
-    expect(pol.linearY[0]).to.eql(ValueType.CONSTANT, 'linearY.type');
-    expect(pol.linearY[1]).to.eql(1, 'linearY.value');
-    expect(pol.linearZ[0]).to.eql(ValueType.BEZIER_CURVE, 'linearZ.type');
-    // expect(pol.linearZ[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'linearZ.value');
-  });
-
-  it('camera transform path linear, constant, bezier', () => {
-    const getItem = path => ({
-      'name': '3DModel_1',
-      'delay': 1,
-      'id': 14,
-      'model': {
-        'options': {
-          'type': 1,
-          'duration': 5,
-          'near': 0.2,
-          'far': 20,
-          'fov': 30,
-          'renderLevel': 'B+',
-          'startSize': 0,
-          'looping': false,
-        },
-        'transform': { path },
-      },
-    });
-    const constantPath = [1, 1, 2];
-    const linearPath = ['path', [[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, 0], [1, 1, 2]]]];
-    const bezierPath = ['bezier', [[[0, 0, 1, 1], [1, 1, 1, 1]], [[-1.3, 0, 0], [3, 0, 0]], [[1, 1.5, 0], [2.5, 1.2, 0]]]];
-    const ct = getStandardItem(getItem(constantPath));
-
-    expect(ct.content.positionOverLifetime.path[0]).to.eql(ValueType.CONSTANT_VEC3, 'constantPath.type');
-    expect(ct.content.positionOverLifetime.path[1]).to.eql([1, 1, 2], 'constantPath.value');
-
-    const lt = getStandardItem(getItem(linearPath));
-
-    expect(lt.content.positionOverLifetime.path[0]).to.eql(ValueType.BEZIER_CURVE_PATH, 'constantPath.type');
-    // expect(lt.content.positionOverLifetime.path[1]).to.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, 0], [1, 1, 2]]], 'constantPath.value');
-
-    const bt = getStandardItem(getItem(bezierPath));
-
-    expect(bt.content.positionOverLifetime.path[0]).to.eql(ValueType.BEZIER_CURVE_PATH, 'constantPath.type');
-    // expect(bt.content.positionOverLifetime.path[1]).to.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[-1.3, 0, 0], [3, 0, 0]], [[1, 1.5, 0], [2.5, 1.2, 0]]], 'constantPath.value');
-  });
-
-});
-
diff --git a/test/cases/model/index.test.mjs b/test/cases/model/index.test.mjs
deleted file mode 100644
index ab7d2a9..0000000
--- a/test/cases/model/index.test.mjs
+++ /dev/null
@@ -1,474 +0,0 @@
-import { getStandardItem, getStandardJSON } from '../../../dist/fallback.mjs';
-
-const { expect } = chai;
-
-describe('model plugin items', () => {
-  it('load camera item', () => {
-    const item = getStandardItem({
-      id: 'extra-camera',
-      duration: 8,
-      name: 'extra-camera',
-      pn: 0,
-      type: 'camera',
-      transform: {
-        position: [0, 0, 5],
-        rotation: [0, 40, 0],
-      },
-      content: {
-        options: {
-          duration: 8,
-          near: 0.1,
-          far: 5000,
-          fov: 60,
-        },
-      },
-    });
-
-    expect(item.type).to.eql('camera');
-    expect(item.transform.position).to.eql([0, 0, 5]);
-    expect(item.transform.rotation).to.eql([0, 40, 0]);
-    expect(item.content.options).to.exist;
-    expect(item.pn).to.eql(0);
-    expect(item.duration).to.eql(8);
-    expect(item.content.options).to.contains({
-      duration: 8, near: 0.1, far: 5000, fov: 60,
-    });
-  });
-
-  it('load mesh item', () => {
-    const geometry = {};
-    const item = getStandardItem({
-      id: 'extra-camera',
-      duration: 8,
-      name: 'extra-camera',
-      pluginName: 'model',
-      type: 'mesh',
-      transform: {
-        position: [0, 0, 5],
-        rotation: [0, 40, 0],
-      },
-      content: {
-        options: {
-          geometry,
-        },
-      },
-    });
-
-    expect(item.type).to.eql('mesh');
-    expect(item.pluginName).to.eql('model');
-    expect(item.transform).to.deep.equals({
-      position: [0, 0, 5],
-      rotation: [0, 40, 0],
-    });
-    expect(item.duration).to.eql(8);
-    expect(item.content.options).to.contains({ geometry });
-  });
-
-  it('load model json', () => {
-    const scn = getStandardJSON({
-      compositionId: 0,
-      version: '0.8.1',
-      images: [],
-      gltf: ['xxx'],
-      _imgs: {},
-      compositions: [
-        {
-          id: 0,
-          items: [
-            {
-              id: 1,
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:5,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: 'mesh',
-              duration: 8,
-              name: 'extra-camera',
-              pluginName: 'model',
-              type: 'mesh',
-              transform: {
-                position: [0, 0, 5],
-                rotation: [0, 40, 0],
-              },
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-          ],
-        },
-      ],
-    });
-
-    const item0 = scn.items.find(item => item.id === scn.compositions[0].items[0].id);
-    const item1 = scn.items.find(item => item.id === scn.compositions[0].items[1].id);
-
-    expect(scn.plugins).to.deep.equal(['model']);
-    expect(scn.compositions[0].items.length).to.eql(2);
-    expect(scn.items.length).to.eql(2);
-    expect(item0.pn).to.eql(0);
-    expect(item0.endBehavior).to.eql(5);
-    expect(item1.pn).to.eql(0);
-
-    const scn08MeshFix = getStandardJSON({
-      compositionId: 0,
-      version: '0.8.1',
-      images: [],
-      gltf: ['xxx'],
-      _imgs: {},
-      compositions: [
-        {
-          id: 0,
-          items: [
-            {
-              id: '1',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '12',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '13',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '14',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: 'mesh',
-              duration: 8,
-              name: 'extra-camera',
-              pluginName: 'model',
-              type: 'mesh',
-              transform: {
-                position: [0, 0, 5],
-                rotation: [0, 40, 0],
-              },
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-          ],
-        },
-      ],
-    });
-
-    const item0From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[0].id);
-    const item1From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[1].id);
-    const item2From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[2].id);
-    const item3From08 = scn08MeshFix.items.find(item => item.id === scn08MeshFix.compositions[0].items[3].id);
-
-    expect(item0From08.endBehavior).to.eql(0);
-    expect(item1From08.endBehavior).to.eql(4);
-    expect(item2From08.endBehavior).to.eql(0);
-    expect(item3From08.endBehavior).to.eql(4);
-
-    const scn18MeshFix = getStandardJSON({
-      compositionId: 0,
-      version: '1.8',
-      images: [],
-      gltf: ['xxx'],
-      _imgs: {},
-      compositions: [
-        {
-          id: 0,
-          items: [
-            {
-              id: '1',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '12',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '13',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '14',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: 'mesh',
-              duration: 8,
-              name: 'extra-camera',
-              pluginName: 'model',
-              type: 'mesh',
-              transform: {
-                position: [0, 0, 5],
-                rotation: [0, 40, 0],
-              },
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-          ],
-        },
-      ],
-    });
-    const item0From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[0].id);
-    const item1From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[1].id);
-    const item2From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[2].id);
-    const item3From18 = scn18MeshFix.items.find(item => item.id === scn18MeshFix.compositions[0].items[3].id);
-
-    expect(item0From18.endBehavior).to.eql(0);
-    expect(item1From18.endBehavior).to.eql(4);
-    expect(item2From18.endBehavior).to.eql(0);
-    expect(item3From18.endBehavior).to.eql(4);
-
-    const scn21MeshFix = getStandardJSON({
-      compositionId: 0,
-      version: '2.1',
-      images: [],
-      gltf: ['xxx'],
-      _imgs: {},
-      compositions: [
-        {
-          id: 0,
-          items: [
-            {
-              id: '1',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '12',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '13',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '14',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: 'mesh',
-              duration: 8,
-              name: 'extra-camera',
-              pluginName: 'model',
-              type: 'mesh',
-              transform: {
-                position: [0, 0, 5],
-                rotation: [0, 40, 0],
-              },
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-          ],
-        },
-      ],
-    });
-    const item0From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[0].id);
-    const item1From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[1].id);
-    const item2From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[2].id);
-    const item3From21 = scn21MeshFix.items.find(item => item.id === scn21MeshFix.compositions[0].items[3].id);
-
-    expect(item0From21.endBehavior).to.eql(0);
-    expect(item1From21.endBehavior).to.eql(4);
-    expect(item2From21.endBehavior).to.eql(0);
-    expect(item3From21.endBehavior).to.eql(4);
-
-    const scn22MeshFix = getStandardJSON({
-      compositionId: 0,
-      version: '2.2',
-      images: [],
-      gltf: ['xxx'],
-      _imgs: {},
-      compositions: [
-        {
-          id: 0,
-          items: [
-            {
-              id: '1',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '12',
-              type: 'mesh',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '13',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:1,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: '14',
-              type: 'light',
-              pluginName: 'model',
-              duration: 4,
-              endBehavior:4,
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-            {
-              id: 'mesh',
-              duration: 8,
-              name: 'extra-camera',
-              pluginName: 'model',
-              type: 'mesh',
-              transform: {
-                position: [0, 0, 5],
-                rotation: [0, 40, 0],
-              },
-              content: {
-                options: {
-                  geometry: {},
-                },
-              },
-            },
-          ],
-        },
-      ],
-    });
-    const item0From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[0].id);
-    const item1From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[1].id);
-    const item2From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[2].id);
-    const item3From22 = scn22MeshFix.items.find(item => item.id === scn22MeshFix.compositions[0].items[3].id);
-
-    expect(item0From22.endBehavior).to.eql(1);
-    expect(item1From22.endBehavior).to.eql(4);
-    expect(item2From22.endBehavior).to.eql(1);
-    expect(item3From22.endBehavior).to.eql(4);
-  });
-});
diff --git a/test/cases/null/base.test.mjs b/test/cases/null/base.test.mjs
deleted file mode 100644
index 82b1e7a..0000000
--- a/test/cases/null/base.test.mjs
+++ /dev/null
@@ -1,311 +0,0 @@
-import { getStandardItem, normalizeColor } from '../../../dist/fallback.mjs';
-import { ValueType, ItemType, END_BEHAVIOR_FREEZE, END_BEHAVIOR_DESTROY } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('nullItem base', () => {
-  it('duration, renderLevel, type, endBehavior, startColor', () => {
-    const item = {
-      'name': 'null_11',
-      'id': 1,
-      'parentId': 14,
-      'cal': {
-        'options': {
-          'duration': 3,
-          'startSize': 1,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-          'endBehavior': 4,
-          'startColor': ['color', [245, 166, 35, 0.5]],
-        },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.duration).to.eql(3, 'duration');
-    expect(neo.renderLevel).to.eql('B+', 'renderLevel');
-    expect(neo.type).to.eql(ItemType.null, 'type');
-    expect(neo.parentId).to.eql('14', 'parentId');
-    expect(neo.pn, 'pn').not.exist;
-    expect(neo.endBehavior).to.eql(END_BEHAVIOR_FREEZE, 'endBehavior');
-
-    const content = neo.content;
-
-    expect(content).to.be.an('object');
-    expect(content.options.startColor).to.eql(normalizeColor([245, 166, 35, 128]));
-
-    delete item.cal.options.endBehavior;
-
-    const neo2 = getStandardItem(item);
-
-    expect(neo2.endBehavior).to.eql(END_BEHAVIOR_DESTROY, 'endBehavior');
-
-  });
-
-  it('static transform', () => {
-    const t = { 'position': [1, 1, 1], 'rotation': [-30, 30, 30] };
-    const item = {
-      'name': 'null_1',
-      'id': 1,
-      'cal': {
-        'options': {
-          'duration': 3,
-          'startSize': 2,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-        },
-        'transform': t,
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.transform.position).to.eql(t.position);
-
-    const r = neo.transform.rotation;
-
-    expect([+r[0].toFixed(1), +r[1].toFixed(1), +r[2].toFixed(1)]).to.deep.equal([-16.1, 38.7, 16.1]);
-    expect(neo.transform.scale).to.eql([2, 2, 1]);
-
-    delete item.cal.transform;
-
-    const neo2 = getStandardItem(item);
-
-    expect(neo2.transform?.position).not.exist;
-    expect(neo2.transform?.rotation).not.exist;
-    expect(neo2.transform?.scale).to.eql([2, 2, 1]);
-  });
-
-  it('colorOverLifetime', () => {
-    const opacityLine = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 3,
-          'startSize': 5,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-
-        },
-        'colorOverLifetime': {
-          'color': ['gradient', { '0.00': 'rgba(211,27,27,1)', '1.00': 'rgba(10,28,230,0.4)' }],
-          'opacity': ['lines', [[0, 0], [1, 1]]],
-        },
-      },
-    };
-
-    const opacityCurve = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 3,
-          'startSize': 5,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-        },
-        'colorOverLifetime': {
-          'opacity': ['curve', [[0, 100, 0, -3], [0.5, 0, 0, 0], [1, 100, 3, 0]]],
-        },
-      },
-    };
-
-    const neo1 = getStandardItem(opacityLine);
-
-    expect(neo1.content.colorOverLifetime.opacity[0]).to.eql(ValueType.LINE, 'opacity.type');
-    expect(neo1.content.colorOverLifetime.opacity[1]).to.eql([[0, 0], [1, 1]], 'opacity.value');
-    expect(neo1.content.colorOverLifetime.color[0]).to.eql(ValueType.GRADIENT_COLOR, 'colorGradient.type');
-    expect(neo1.content.colorOverLifetime.color[1][0]).to.eql([0, 211, 27, 27, 255], 'colorGradient.value');
-    expect(neo1.content.colorOverLifetime.color[1][1]).to.eql([1, 10, 28, 230, 102], 'colorGradient.value');
-
-    const neo2 = getStandardItem(opacityCurve);
-
-    expect(neo2.content.colorOverLifetime.opacity[0]).to.eql(ValueType.BEZIER_CURVE, 'opacity.type');
-    // expect(neo2.content.colorOverLifetime.opacity[1]).to.eql([[0, 100, 0, -3], [0.5, 0, 0, 0], [1, 100, 3, 0]], 'opacity.value');
-
-  });
-
-  it('sizeOverLifetime', () => {
-    const constantSize = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 3,
-          'startSize': 5,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-        },
-        'sizeOverLifetime': {
-          'size': 3,
-        },
-      },
-    };
-    const sizeSeparate = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 3,
-          'startSize': 5,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-
-        },
-        'sizeOverLifetime': {
-          'separateAxes': true,
-          'x': ['lines', [[0, 0], [1, 10]]],
-          'y': 2,
-          'z': ['curve', [[0, 0, 1, 0], [0.73, 0.24, 1, 1.1], [1, 1, 5, 1]]],
-        },
-      },
-    };
-
-    const neo1 = getStandardItem(constantSize);
-
-    expect(neo1.content.sizeOverLifetime.size[0]).to.eql(ValueType.CONSTANT, 'size.type');
-    expect(neo1.content.sizeOverLifetime.size[1]).to.eql(3, 'size.value');
-    expect(neo1.content.sizeOverLifetime.separateAxes, 'separateAxes').to.be.undefined;
-    expect(neo1.content.sizeOverLifetime.x, 'x').to.be.undefined;
-    expect(neo1.content.sizeOverLifetime.y, 'y').to.be.undefined;
-    expect(neo1.content.sizeOverLifetime.z, 'z').to.be.undefined;
-
-    const neo2 = getStandardItem(sizeSeparate);
-
-    expect(neo2.content.sizeOverLifetime.separateAxes, 'separateAxes').to.be.true;
-    expect(neo2.content.sizeOverLifetime.size, 'size').to.be.undefined;
-    expect(neo2.content.sizeOverLifetime.x[0]).to.eql(ValueType.LINE, 'sizeX.type');
-    expect(neo2.content.sizeOverLifetime.x[1]).to.eql([[0, 0], [1, 10]], 'sizeX.value');
-    expect(neo2.content.sizeOverLifetime.y[0]).to.eql(ValueType.CONSTANT, 'sizeY.type');
-    expect(neo2.content.sizeOverLifetime.y[1]).to.eql(2, 'sizeY.value');
-    expect(neo2.content.sizeOverLifetime.z[0]).to.eql(ValueType.BEZIER_CURVE, 'sizeZ.type');
-    // expect(neo2.content.sizeOverLifetime.z[1]).to.eql([[0, 0, 1, 0], [0.73, 0.24, 1, 1.1], [1, 1, 5, 1]], 'sizeZ.value');
-  });
-
-  it('velocityOverLifetime', () => {
-    const item = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 5,
-          'startSize': 1,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-        },
-        'velocityOverLifetime': {
-          'asMovement': false,
-          'linearX': 2,
-          'linearY': ['lines', [[0, 0], [0.25, 5], [0.75, 5], [1, 0]]],
-          'linearZ': ['curve', [[0, 1, 0, 0], [0.35, 0.85, -1.3, -1.22], [0.56, 0.16, -1, -1.2], [1, 0, 0, 0]]],
-          'asRotation': true,
-          'orbitalX': 30,
-          'orbitalY': ['lines', [[0, 180], [0.25, 90], [0.75, 90], [1, 0]]],
-          'orbitalZ': ['curve', [[0, 30, 0, -2], [0.2, 15.6, -0.8, -0.7], [0.82, 12.6, -0.57, -0.55], [1, 0, -4.9, 1]]],
-          'speedOverLifetime': 10,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const positionOverLifetime = neo.content.positionOverLifetime;
-
-    expect(positionOverLifetime.asMovement, 'asMovement').to.be.false;
-    expect(positionOverLifetime.linearX[0]).to.eql(ValueType.CONSTANT, 'linearX.type');
-    expect(positionOverLifetime.linearX[1]).to.eql(2, 'linearX.value');
-    expect(positionOverLifetime.linearY[0]).to.eql(ValueType.LINE, 'linearY.type');
-    expect(positionOverLifetime.linearY[1]).to.eql([[0, 0], [0.25, 5], [0.75, 5], [1, 0]], 'linearY.value');
-    expect(positionOverLifetime.linearZ[0]).to.eql(ValueType.BEZIER_CURVE, 'linearZ.type');
-    // expect(positionOverLifetime.linearZ[1]).to.eql([[0, 1, 0, 0], [0.35, 0.85, -1.3, -1.22], [0.56, 0.16, -1, -1.2], [1, 0, 0, 0]], 'linearZ.value');
-    expect(positionOverLifetime.asRotation, 'asRotate').to.be.true;
-    expect(positionOverLifetime.orbitalX[0]).to.eql(ValueType.CONSTANT, 'orbitalX.type');
-    expect(positionOverLifetime.orbitalX[1]).to.eql(30, 'orbitalX.value');
-    expect(positionOverLifetime.orbitalY[0]).to.eql(ValueType.LINE, 'orbitalY.type');
-    expect(positionOverLifetime.orbitalY[1]).to.eql([[0, 180], [0.25, 90], [0.75, 90], [1, 0]], 'orbitalY.value');
-    expect(positionOverLifetime.orbitalZ[0]).to.eql(ValueType.BEZIER_CURVE, 'orbitalZ.type');
-    // expect(positionOverLifetime.orbitalZ[1]).to.eql([[0, 30, 0, -2], [0.2, 15.6, -0.8, -0.7], [0.82, 12.6, -0.57, -0.55], [1, 0, -4.9, 1]], 'orbitalZ.value');
-    expect(positionOverLifetime.speedOverLifetime[0]).to.eql(ValueType.CONSTANT, 'speedOverLifetime.type');
-    expect(positionOverLifetime.speedOverLifetime[1]).to.eql(10, 'speedOverLifetime.value');
-    expect(positionOverLifetime.startSpeed, 'startSpeed').to.be.undefined;
-    expect(positionOverLifetime.gravity, 'gravity').to.be.undefined;
-    expect(positionOverLifetime.gravityOverLifetime, 'gravityOverLifetime').to.be.undefined;
-
-  });
-
-  it('rotateOverLifetime', () => {
-    const item = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 5,
-          'startSize': 1,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-        },
-        'rotationOverLifetime': {
-          'asRotation': true,
-          'angularVelocity': ['curve', [[0, 0, 1, 6], [0.17, 0.54, 0.72, 0.72], [0.78, 0.7, 1, 1], [1, 1, 1, 1]]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const rot = neo.content.rotationOverLifetime;
-
-    expect(rot.asRotation, 'asRotation').to.be.true;
-    expect(rot.separateAxes, 'separateAxes').to.be.undefined;
-    expect(rot.z[0]).eql(ValueType.BEZIER_CURVE, 'angularVelocity.type');
-    // expect(rot.z[1]).eql([[0, 0, 1, 6], [0.17, 0.54, 0.72, 0.72], [0.78, 0.7, 1, 1], [1, 1, 1, 1]], 'angularVelocity.value');
-
-    const separateItem = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'cal': {
-        'options': {
-          'duration': 5,
-          'startSize': 1,
-          'sizeAspect': 1,
-          'relative': true,
-          'renderLevel': 'B+',
-        },
-        'rotationOverLifetime': {
-          'asRotation': true,
-          'angularVelocity': ['curve', [[0, 0, 1, 6], [0.17, 0.54, 0.72, 0.72], [0.78, 0.7, 1, 1], [1, 1, 1, 1]]],
-          'separateAxes': true,
-          'x': 10,
-          'y': ['lines', [[0, 1], [0.25, 0], [0.75, 0], [1, 1]]],
-          'z': ['curve', [[0, 1, 0, 0], [0.72, 0.82, -0.98, -1.1], [1, 0, -5, 7]]],
-        },
-      },
-    };
-
-    const neo2 = getStandardItem(separateItem);
-    const rot2 = neo2.content.rotationOverLifetime;
-
-    expect(rot2.asRotation, 'asRotation').to.be.true;
-    expect(rot2.separateAxes, 'separateAxes').to.be.true;
-    expect(rot2.x[0]).eql(ValueType.CONSTANT, 'x.type');
-    expect(rot2.x[1]).eql(10, 'x.value');
-    expect(rot2.y[0]).eql(ValueType.LINE, 'y.type');
-    expect(rot2.y[1]).eql([[0, 1], [0.25, 0], [0.75, 0], [1, 1]], 'y.value');
-    expect(rot2.z[0]).eql(ValueType.BEZIER_CURVE, 'z.type');
-    // expect(rot2.z[1]).eql([[0, 1, 0, 0], [0.72, 0.82, -0.98, -1.1], [1, 0, -5, 7]], 'z.value');
-  });
-});
-
diff --git a/test/cases/null/end-behavior.test.mjs b/test/cases/null/end-behavior.test.mjs
deleted file mode 100644
index fe3ec32..0000000
--- a/test/cases/null/end-behavior.test.mjs
+++ /dev/null
@@ -1,20 +0,0 @@
-import { getStandardJSON } from '../../../dist/fallback.mjs';
-import { ItemType, ItemEndBehavior } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('Null item endBehavior', () => {
-  it('destroy to forward', () => {
-    const json = '{"images":[],"spines":[],"version":"1.5","shapes":[],"plugins":[],"type":"mars","compositions":[{"id":"6","name":"新建合成1","duration":5,"startTime":0,"endBehavior":1,"previewSize":[750,1624],"items":[{"id":"1","name":"sprite_1","duration":5,"type":"1","parentId":"2","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"renderMode":1},"positionOverLifetime":{"direction":[0,0,0],"startSpeed":0,"gravity":[0,0,0],"gravityOverLifetime":[0,1]}},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[1.2,1.2,1]}},{"id":"2","name":"null_2","duration":5,"type":"3","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"positionOverLifetime":{}},"transform":{"position":[0,0,0],"rotation":[0,0,0],"scale":[1,1,1]}}],"camera":{"fov":60,"far":40,"near":0.1,"clipMode":1,"position":[0,0,8],"rotation":[0,0,0]}}],"requires":[],"compositionId":"6","bins":[],"textures":[]}';
-    const { version, compositions } = getStandardJSON(JSON.parse(json));
-
-    expect(version).to.eq('3.0');
-    compositions.forEach(({ items }) => {
-      items.forEach(item => {
-        if (item.type === ItemType.null) {
-          expect(item.endBehavior).to.eq(ItemEndBehavior.freeze);
-        }
-      });
-    });
-  });
-});
diff --git a/test/cases/particle/base.test.mjs b/test/cases/particle/base.test.mjs
deleted file mode 100644
index 6e478c6..0000000
--- a/test/cases/particle/base.test.mjs
+++ /dev/null
@@ -1,1063 +0,0 @@
-import { getStandardItem, getStandardJSON } from '../../../dist/fallback.mjs';
-import {
-  ItemType, ValueType, END_BEHAVIOR_FREEZE, ShapeType, RenderMode, ParticleOrigin,
-  BlendingMode, MaskMode, SideMode, ParticleInteractionBehavior,
-} from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('particle base', () => {
-  it('particle options: duration, delay, renderLevel,type,gravity, endBehavior, startRotateCurve, startSize', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'gravity': [1, 1, 1],
-          'renderLevel': 'B+',
-          'startTurbulence': true,
-          'turbulenceX': 45,
-          'turbulenceY': ['lines', [[0, 0], [1, 30]]],
-          'turbulenceZ': ['random', [0, 30]],
-          'start3DRotation': true,
-          'endBehavior': 4,
-          'startRotation': ['curve', [[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]]],
-          'startRotationY': ['curve', [[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]]],
-        },
-        'emission': { 'rateOverTime': 5 },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.delay).to.eql(0.56, 'delay');
-    expect(neo.duration).to.eql(2, 'duration');
-    expect(neo.renderLevel).to.eql('B+', 'renderLevel');
-    expect(neo.type).to.eql(ItemType.particle, 'type');
-    expect(neo.parentId).to.eql('5', 'parentId');
-    expect(neo.pn, 'pn').not.exist;
-
-    const content = neo.content;
-
-    expect(content).to.be.an('object');
-    expect(content.positionOverLifetime.gravityOverLifetime[0]).to.eql(ValueType.CONSTANT);
-    expect(content.positionOverLifetime.gravityOverLifetime[1]).to.eql(2);
-    expect(content.positionOverLifetime.gravity).to.eql([1, 1, 1]);
-    expect(content.emission.rateOverTime[0]).to.eql(ValueType.CONSTANT, 'rateOverTime.type');
-    expect(content.emission.rateOverTime[1]).to.eql(5, 'rateOverTime.value');
-
-    const shape = content.shape;
-
-    expect(shape.turbulenceX[0]).to.be.eql(ValueType.CONSTANT, 'turbulenceX.type');
-    expect(shape.turbulenceX[1]).to.be.eql(45, 'turbulenceX.value');
-    expect(shape.turbulenceY[0]).to.be.eql(ValueType.LINE, 'turbulenceY.type');
-    expect(shape.turbulenceY[1]).to.be.eql([[0, 0], [1, 30]], 'turbulenceX.value');
-    expect(shape.turbulenceZ[0]).to.be.eql(ValueType.RANDOM, 'turbulenceZ.type');
-    expect(shape.turbulenceZ[1]).to.be.eql([0, 30], 'turbulenceZ.value');
-    expect(neo.endBehavior).to.be.eql(END_BEHAVIOR_FREEZE, 'endBehavior');
-    expect(content.options.startRotationZ[0]).to.be.eql(ValueType.BEZIER_CURVE, 'startRotationZ.type');
-    // expect(content.options.startRotationZ[1]).to.be.eql([[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]], 'startRotation.value');
-    expect(content.options.startRotationY[0]).to.be.eql(ValueType.BEZIER_CURVE, 'startRotationY.type');
-  });
-  it('particle start3DRotation', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'gravity': [1, 1, 1],
-          'renderLevel': 'B+',
-          'startTurbulence': true,
-          'turbulenceX': 45,
-          'turbulenceY': ['lines', [[0, 0], [1, 30]]],
-          'turbulenceZ': ['random', [0, 30]],
-          'start3DRotation': true,
-          'endBehavior': 4,
-          'startRotationZ': ['curve', [[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]]],
-          'startRotationY': ['curve', [[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]]],
-        },
-        'emission': { 'rateOverTime': 5 },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.delay).to.eql(0.56, 'delay');
-    expect(neo.duration).to.eql(2, 'duration');
-    expect(neo.renderLevel).to.eql('B+', 'renderLevel');
-    expect(neo.type).to.eql(ItemType.particle, 'type');
-    expect(neo.parentId).to.eql('5', 'parentId');
-    expect(neo.pn, 'pn').not.exist;
-    const content = neo.content;
-
-    expect(content).to.be.an('object');
-    expect(content.positionOverLifetime.gravityOverLifetime[0]).to.eql(ValueType.CONSTANT);
-    expect(content.positionOverLifetime.gravityOverLifetime[1]).to.eql(2);
-    expect(content.positionOverLifetime.gravity).to.eql([1, 1, 1]);
-    expect(content.emission.rateOverTime[0]).to.eql(ValueType.CONSTANT, 'rateOverTime.type');
-    expect(content.emission.rateOverTime[1]).to.eql(5, 'rateOverTime.value');
-    const shape = content.shape;
-
-    expect(shape.turbulenceX[0]).to.be.eql(ValueType.CONSTANT, 'turbulenceX.type');
-    expect(shape.turbulenceX[1]).to.be.eql(45, 'turbulenceX.value');
-    expect(shape.turbulenceY[0]).to.be.eql(ValueType.LINE, 'turbulenceY.type');
-    expect(shape.turbulenceY[1]).to.be.eql([[0, 0], [1, 30]], 'turbulenceX.value');
-    expect(shape.turbulenceZ[0]).to.be.eql(ValueType.RANDOM, 'turbulenceZ.type');
-    expect(shape.turbulenceZ[1]).to.be.eql([0, 30], 'turbulenceZ.value');
-    expect(neo.endBehavior).to.be.eql(END_BEHAVIOR_FREEZE, 'endBehavior');
-    expect(content.options.startRotationZ[0]).to.be.eql(ValueType.BEZIER_CURVE, 'startRotation.type');
-    // expect(content.options.startRotationZ[1]).to.be.eql([[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]], 'startRotation.value');
-    expect(content.options.startRotationY[0]).to.be.eql(ValueType.BEZIER_CURVE, 'startRotation.type');
-    // expect(content.options.startRotationY[1]).to.be.eql([[0, 360, 0, -3], [0.5, 0, 0, 0], [1, 360, 3, 0]], 'startRotation.value');
-    expect(content.options.startSizeX).not.exist;
-  });
-
-  it('particle start3D size', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'gravity': [1, 1, 1],
-          'renderLevel': 'B+',
-          'start3DSize': true,
-          'startSizeX': ['lines', [[0, 0], [1, 1]]],
-          'startSizeY': ['curve', [[0, 0, 1, 0], [0.3, 0.7, 1.4, 1.28], [0.63, 4.45, 1.1, 1], [1, 5, 0, 0]]],
-        },
-        'emission': { 'rateOverTime': 5 },
-      },
-    };
-
-    const neo = getStandardItem(item);
-
-    expect(neo.content.options.start3DSize).to.be.true;
-    expect(neo.content.options.startSizeX[0]).to.eql(ValueType.LINE, 'startSizeX.type');
-    expect(neo.content.options.startSizeX[1]).to.eql([[0, 0], [1, 1]], 'startSizeX.value');
-    expect(neo.content.options.startSizeY[0]).to.eql(ValueType.BEZIER_CURVE, 'startSizeY.type');
-    // expect(neo.content.options.startSizeY[1]).to.eql([[0, 0, 1, 0], [0.3, 0.7, 1.4, 1.28], [0.63, 4.45, 1.1, 1], [1, 5, 0, 0]], 'startSizeY.value');
-
-  });
-
-  it('particle emitter shape', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'gravity': [1, 1, 1],
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'shape': {
-          'shape': 'RectangleEdge', 'radius': 1, 'arc': 360, 'arcMode': 0,
-        },
-      },
-    };
-    const neo = getStandardItem(item);
-    const shape = neo.content.shape;
-
-    expect(shape.type).to.be.eql(ShapeType.RECTANGLE_EDGE);
-    expect(shape.radius).to.be.eql(1);
-  });
-
-  it('particle emission params', () => {
-    const item = {
-      'name': 'item_5',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 6,
-          'burstOffsets': [{
-            'index': 0, 'x': '1', 'y': '1', 'z': '1',
-          }],
-          'bursts': [{
-            'time': '0.5', 'count': '5', 'cycles': '1', 'interval': '0.1',
-          }],
-        },
-        'shape': {
-          'shape': 'Sphere', 'radius': 1, 'arc': 360, 'arcMode': 0,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const emission = neo.content.emission;
-
-    expect(emission.rateOverTime[0]).to.eql(ValueType.CONSTANT, 'rateOverTime.type');
-    expect(emission.rateOverTime[1]).to.eql(6, 'rateOverTime.value');
-    expect(emission.bursts).to.be.an('array');
-    expect(emission.bursts[0].time).to.be.eql(0.5, 'time');
-    expect(emission.bursts[0].count).to.be.eql(5, 'count');
-    expect(emission.bursts[0].cycles).to.be.eql(1, 'cycles');
-    expect(emission.bursts[0].interval).to.be.eql(0.1, 'interval');
-
-    expect(emission.burstOffsets).to.be.an('array');
-    expect(emission.burstOffsets[0].index).to.be.eql(0, 'index');
-    expect(emission.burstOffsets[0].x).to.be.eql(1, 'x');
-    expect(emission.burstOffsets[0].y).to.be.eql(1, 'y');
-    expect(emission.burstOffsets[0].z).to.be.eql(1, 'z');
-  });
-
-  it('particle emitter static transform', () => {
-    const item = {
-      'name': 'item_2',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'shape': {
-          'shape': 'Sphere', 'radius': 1, 'arc': 360, 'arcMode': 0,
-        },
-        'transform': { 'position': [1, 2, 1], 'rotation': [90, 77, 20] },
-      },
-    };
-    const neo = getStandardItem(item);
-    const transform = neo.transform;
-
-    expect(neo.transform.position).to.eql(transform.position, 'position');
-
-    const r = neo.transform.rotation;
-
-    expect([+r[0].toFixed(1), +r[1].toFixed(1), +r[2].toFixed(1)]).to.deep.equal([90.0, -20.0, 77.0]);
-    // @ts-expect-error
-    delete item.particle.transform;
-    const neo2 = getStandardItem(item);
-
-    expect(neo2.transform.position, 'position').not.exist;
-    expect(neo2.transform.rotation, 'rotation').not.exist;
-
-    const oldParticle = {
-      'compositionId': 11,
-      'requires': [],
-      'compositions': [
-        {
-          'name': '桃花',
-          'id': 11,
-          'duration': 15,
-          'camera': {
-            'fov': 60,
-            'far': 20,
-            'near': 2,
-            'position': [
-              0,
-              0,
-              8,
-            ],
-            'clipMode': 0,
-            'z': 8,
-          },
-          'items': [
-            {
-              'name': 'item_4',
-              'delay': 0,
-              'id': 19,
-              'ro': 0.1,
-              'particle': {
-                'options': {
-                  'startLifetime': [
-                    'random',
-                    [
-                      3,
-                      4,
-                    ],
-                  ],
-                  'startSize': [
-                    'random',
-                    [
-                      0.3,
-                      0.4,
-                    ],
-                  ],
-                  'startSpeed': [
-                    'random',
-                    [
-                      1.8,
-                      2.2,
-                    ],
-                  ],
-                  'startColor': [
-                    'color',
-                    [
-                      255,
-                      255,
-                      255,
-                    ],
-                  ],
-                  'duration': 10,
-                  'maxCount': 200,
-                  'gravityModifier': 1,
-                  'start3DSize': false,
-                  'gravity': [
-                    0,
-                    -0.2,
-                    0,
-                  ],
-                  'renderLevel': 'B+',
-                },
-                'emission': {
-                  'rateOverTime': 30,
-                },
-                'shape': {
-                  'shape': 'Rectangle',
-                  'radius': 2,
-                  'arc': 360,
-                  'arcMode': 0,
-                  'angle': 10,
-                  'width': 12,
-                  'height': 12,
-                },
-                'renderer': {
-                  'texture': 0,
-                },
-                'transform': {
-                  'rotation': [
-                    90,
-                    30,
-                    20,
-                  ],
-                },
-              },
-            },
-          ],
-          'meta': {
-            'previewSize': [
-              0,
-              0,
-            ],
-          },
-        },
-      ],
-      'gltf': [],
-      'images': [
-        'https://gw.alipayobjects.com/zos/gltf-asset/mars-cli/RXJVVGVKNJAW/-105869846-e926c.png',
-      ],
-      'version': '0.1.47',
-      'shapes': [],
-      'plugins': [],
-      'type': 'mars',
-      '_imgs': {
-        '11': [
-          0,
-        ],
-      },
-      'imageTags': [
-        'B+',
-      ],
-    };
-    const res = getStandardJSON(oldParticle);
-    const pt = res.items.find(item => item.id === res.compositions[0].items[0].id);
-    const r2 = pt.transform.eulerHint;
-
-    expect([+r2.x.toFixed(1), +r2.y.toFixed(1), +r2.z.toFixed(1)]).to.eql([-90.0, -20.0, 30.0], 'oldParticle rotation');
-  });
-
-  it('particle emitter transform path linear, constant, bezier', () => {
-    const linearPath = ['path', [[[0, 0, 1, 1], [1, 1, 1, 1]], [[-2, -2, -5], [1, 2, 0]]]];
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'shape': {
-          'shape': 'Sphere', 'radius': 1, 'arc': 360, 'arcMode': 0,
-        },
-        'transform': {
-          'path': linearPath,
-        },
-      },
-    };
-    const neo = getStandardItem(item);
-    const p = neo.content.emitterTransform.path;
-
-    expect(p[0]).to.be.eql(ValueType.BEZIER_CURVE_PATH, 'path type');
-    // expect(p[1]).to.be.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[-2, -2, -5], [1, 2, 0]]], 'path value');
-
-    const item2 = {
-      'name': 'item_2',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'shape': {
-          'shape': 'Sphere', 'radius': 1, 'arc': 360, 'arcMode': 0,
-        },
-        'transform': {
-          'path': [1, 1, 1],
-        },
-      },
-    };
-    const neo2 = getStandardItem(item2);
-    const p2 = neo2.content.emitterTransform.path;
-
-    expect(p2[0]).to.be.eql(ValueType.CONSTANT_VEC3, 'path type');
-    expect(p2[1]).to.be.eql([1, 1, 1], 'path value');
-
-    const bezierPath = ['bezier', [[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, -0.1], [3, 0, -0]], [[0.1, 1, -0], [2, 1, 0]]]];
-    const item3 = {
-      'name': 'item_2',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'maxCount': 10,
-          'gravityModifier': 2,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'shape': {
-          'shape': 'Sphere', 'radius': 1, 'arc': 360, 'arcMode': 0,
-        },
-        'transform': {
-          'path': bezierPath,
-        },
-      },
-    };
-
-    const neo3 = getStandardItem(item3);
-    const p3 = neo3.content.emitterTransform.path;
-
-    expect(p3[0]).to.be.eql(ValueType.BEZIER_CURVE_PATH, 'path type');
-    // expect(p3[1]).to.be.eql([[[0, 0, 1, 1], [1, 1, 1, 1]], [[0, 0, -0.1], [3, 0, -0]], [[0.1, 1, -0], [2, 1, 0]]], 'path value');
-
-  });
-
-  it('particle renderer', () => {
-    const item = {
-      'name': 'item_11',
-      'delay': 0,
-      'id': 11,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 0.75,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'renderer': {
-          'renderMode': 1,
-          'particleOrigin': 4,
-          'blending': 5,
-          'texture': 2,
-          'order': 1,
-          'occlusion': true,
-          'transparentOcclusion': true,
-          'maskMode': 2,
-          'side': 1028,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const renderer = neo.content.renderer;
-
-    expect(renderer.renderMode).to.eql(RenderMode.MESH, 'renderMode');
-    expect(renderer.particleOrigin).to.eql(ParticleOrigin.PARTICLE_ORIGIN_CENTER_TOP, 'ParticleOrigin');
-    expect(renderer.blending).to.eql(BlendingMode.STRONG_LIGHT, 'blending');
-    expect(renderer.texture, 'texture').to.eql(2);
-    expect(renderer.occlusion, 'occlusion').to.be.true;
-    expect(renderer.transparentOcclusion, 'transparentOcclusion').to.be.true;
-    expect(renderer.maskMode).to.eql(MaskMode.OBSCURED, 'maskMode');
-    expect(renderer.side).to.eql(SideMode.FRONT, 'side');
-  });
-
-  it('particle colorOverLifetime', () => {
-    const opacityLine = {
-      'name': 'item_1',
-      'delay': 0,
-      'id': 12,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 0.75,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'colorOverLifetime': {
-          'color': ['gradient', { '0.00': 'rgba(211,27,27,1)', '1.00': 'rgba(10,28,230,0.4)' }],
-          'opacity': ['lines', [[0, 0], [1, 1]]],
-        },
-      },
-    };
-
-    const opacityCurve = {
-      'name': 'item_1',
-      'delay': 0,
-      'id': 12,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 0.75,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': { 'rateOverTime': 5 },
-        'colorOverLifetime': {
-          'opacity': ['curve', [[0, 100, 0, -3], [0.5, 0, 0, 0], [1, 100, 3, 0]]],
-        },
-      },
-    };
-
-    const neo1 = getStandardItem(opacityLine);
-
-    expect(neo1.content.colorOverLifetime.opacity[0]).to.eql(ValueType.LINE, 'opacity.type');
-    expect(neo1.content.colorOverLifetime.opacity[1]).to.eql([[0, 0], [1, 1]], 'opacity.value');
-    expect(neo1.content.colorOverLifetime.color[0]).to.eql(ValueType.GRADIENT_COLOR, 'colorGradient.type');
-    expect(neo1.content.colorOverLifetime.color[1][0]).to.eql([0, 211, 27, 27, 255], 'colorGradient.value');
-    expect(neo1.content.colorOverLifetime.color[1][1]).to.eql([1, 10, 28, 230, 102], 'colorGradient.value');
-
-    const neo2 = getStandardItem(opacityCurve);
-
-    expect(neo2.content.colorOverLifetime.opacity[0]).to.eql(ValueType.BEZIER_CURVE, 'opacity.type');
-    // expect(neo2.content.colorOverLifetime.opacity[1]).to.eql([[0, 100, 0, -3], [0.5, 0, 0, 0], [1, 100, 3, 0]], 'opacity.value');
-  });
-
-  it('particle sizeOverLifetime', () => {
-    const constantSize = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'shape': {
-          'shape': 'Sphere',
-          'radius': 1,
-          'arc': 360,
-          'arcMode': 0,
-        },
-        'sizeOverLifetime': {
-          'separateAxes': false,
-          'size': 10,
-        },
-      },
-    };
-    const sizeSeparate = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'shape': {
-          'shape': 'Sphere',
-          'radius': 1,
-          'arc': 360,
-          'arcMode': 0,
-        },
-        'sizeOverLifetime': {
-          'separateAxes': true,
-          'size': 10,
-          'x': ['lines', [[0, 0], [0.25, 0.5], [0.75, 0.5], [1, 1]]],
-          'y': ['random', [1, 2]],
-        },
-      },
-    };
-
-    const neo1 = getStandardItem(constantSize);
-    const sizeOverLifetime1 = neo1.content.sizeOverLifetime;
-
-    expect(sizeOverLifetime1.size[0]).to.eql(ValueType.CONSTANT, 'size.type');
-    expect(sizeOverLifetime1.size[1]).to.eql(10, 'size.value');
-    expect(sizeOverLifetime1.separateAxes, 'separateAxes').to.be.undefined;
-    expect(sizeOverLifetime1.x, 'x').to.be.undefined;
-    expect(sizeOverLifetime1.y, 'y').to.be.undefined;
-    expect(sizeOverLifetime1.z, 'z').to.be.undefined;
-
-    const neo2 = getStandardItem(sizeSeparate);
-    const sizeOverLifetime2 = neo2.content.sizeOverLifetime;
-
-    expect(sizeOverLifetime2.separateAxes, 'separateAxes').to.be.true;
-    expect(sizeOverLifetime2.size, 'size').to.be.undefined;
-    expect(sizeOverLifetime2.x[0]).to.eql(ValueType.LINE, 'sizeX.type');
-    expect(sizeOverLifetime2.x[1]).to.eql([[0, 0], [0.25, 0.5], [0.75, 0.5], [1, 1]], 'sizeX.value');
-    expect(sizeOverLifetime2.y[0]).to.eql(ValueType.RANDOM, 'sizeY.type');
-    expect(sizeOverLifetime2.y[1]).to.eql([1, 2], 'sizeY.value');
-
-  });
-
-  it('particle rotateOverLifetime', () => {
-    const item = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'shape': {
-          'shape': 'Sphere',
-          'radius': 1,
-          'arc': 360,
-          'arcMode': 0,
-        },
-        'rotationOverLifetime': {
-          'asRotation': true,
-          'angularVelocity': ['random', [0, 180]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const rot = neo.content.rotationOverLifetime;
-
-    expect(rot.asRotation, 'asRotation').to.be.true;
-    expect(rot.separateAxes, 'separateAxes').to.be.undefined;
-    expect(rot.z[0]).eql(ValueType.RANDOM, 'angularVelocity.type');
-    expect(rot.z[1]).eql([0, 180], 'angularVelocity.value');
-
-    const separateItem = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'shape': {
-          'shape': 'Sphere',
-          'radius': 1,
-          'arc': 360,
-          'arcMode': 0,
-        },
-        'rotationOverLifetime': {
-          'asRotation': true,
-          'angularVelocity': ['random', [0, 180]],
-          'separateAxes': true,
-          'x': 30,
-          'y': ['lines', [[0, 0], [1, 360]]],
-          'z': ['curve', [[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]]],
-        },
-      },
-    };
-
-    const neo2 = getStandardItem(separateItem);
-    const rot2 = neo2.content.rotationOverLifetime;
-
-    expect(rot2.asRotation, 'asRotation').to.be.true;
-    expect(rot2.separateAxes, 'separateAxes').to.be.true;
-    expect(rot2.x[0]).eql(ValueType.CONSTANT, 'x.type');
-    expect(rot2.x[1]).eql(30, 'x.value');
-    expect(rot2.y[0]).eql(ValueType.LINE, 'y.type');
-    expect(rot2.y[1]).eql([[0, 0], [1, 360]], 'y.value');
-    expect(rot2.z[0]).eql(ValueType.BEZIER_CURVE, 'z.type');
-    // expect(rot2.z[1]).eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'z.value');
-  });
-
-  it('velocityOverLifetime', () => {
-    const item = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': ['random', [0, 1]],
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'renderer': {
-          'texture': 0,
-        },
-        'velocityOverLifetime': {
-          'asMovement': true,
-          'linearX': 1,
-          'linearY': ['random', [0, 1]],
-          'linearZ': ['curve', [[0, 0, 1, 0], [0.3, 0.14, 1.4, 1.28], [0.63, 0.89, 1.1, 1], [1, 1, 0, 0]]],
-          'asRotation': true,
-          'orbitalX': 30,
-          'orbitalY': ['lines', [[0, 0], [1, 1]]],
-          'orbitalZ': ['random', [0, 90]],
-          'orbCenter': [1, 1, 1],
-          'speedOverLifetime': 4,
-          'forceTarget': true,
-          'target': [2, 2, 10],
-          'forceCurve': ['curve', [[0, 1, 0, 0], [0.72, 0.82, -0.98, -1.1], [1, 0, -5, 7]]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const positionOverLifetime = neo.content.positionOverLifetime;
-
-    expect(positionOverLifetime.asMovement, 'asMovement').to.be.true;
-    expect(positionOverLifetime.linearX[0]).to.eql(ValueType.CONSTANT, 'linearX.type');
-    expect(positionOverLifetime.linearX[1]).to.eql(1, 'linearX.value');
-    expect(positionOverLifetime.linearY[0]).to.eql(ValueType.RANDOM, 'linearY.type');
-    expect(positionOverLifetime.linearY[1]).to.eql([0, 1], 'linearY.value');
-    expect(positionOverLifetime.linearZ[0]).to.eql(ValueType.BEZIER_CURVE, 'linearZ.type');
-    // expect(positionOverLifetime.linearZ[1]).to.eql([[0, 0, 1, 0], [0.3, 0.14, 1.4, 1.28], [0.63, 0.89, 1.1, 1], [1, 1, 0, 0]], 'linearZ.value');
-    expect(positionOverLifetime.asRotation, 'asRotation').to.be.true;
-    expect(positionOverLifetime.orbitalX[0]).to.eql(ValueType.CONSTANT, 'orbitalX.type');
-    expect(positionOverLifetime.orbitalX[1]).to.eql(30, 'orbitalX.value');
-    expect(positionOverLifetime.orbitalY[0]).to.eql(ValueType.LINE, 'orbitalY.type');
-    expect(positionOverLifetime.orbitalY[1]).to.eql([[0, 0], [1, 1]], 'orbitalY.value');
-    expect(positionOverLifetime.orbitalZ[0]).to.eql(ValueType.RANDOM, 'orbitalZ.type');
-    expect(positionOverLifetime.orbitalZ[1]).to.eql([0, 90], 'orbitalZ.value');
-    expect(positionOverLifetime.speedOverLifetime[0]).to.eql(ValueType.CONSTANT, 'speedOverLifetime.type');
-    expect(positionOverLifetime.speedOverLifetime[1]).to.eql(4, 'speedOverLifetime.value');
-    expect(positionOverLifetime.forceTarget).to.be.true;
-    expect(positionOverLifetime.forceCurve[0]).to.eql(ValueType.BEZIER_CURVE, 'forceCurve.type');
-    // expect(positionOverLifetime.forceCurve[1]).to.eql([[0, 1, 0, 0], [0.72, 0.82, -0.98, -1.1], [1, 0, -5, 7]], 'forceCurve.value');
-    expect(positionOverLifetime.startSpeed[0]).to.eql(ValueType.RANDOM, 'startSpeed.type');
-    expect(positionOverLifetime.startSpeed[1]).to.eql([0, 1], 'startSpeed.value');
-
-    const emptySpeed = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': ['random', [0, 1]],
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'renderer': {
-          'texture': 0,
-        },
-        'velocityOverLifetime': {
-          'asMovement': true,
-          'speedOverLifetime': 0,
-        },
-      },
-    };
-    const neo2 = getStandardItem(emptySpeed);
-    const positionOverLifetime2 = neo2.content.positionOverLifetime;
-
-    expect(positionOverLifetime2.speedOverLifetime).to.not.exist;
-  });
-
-  it('interaction', () => {
-    const item = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': ['random', [0, 1]],
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'renderer': {
-          'texture': 0,
-        },
-        'interaction': {
-          'radius': 0.5,
-          'behavior': 1,
-          'multiple': true,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-
-    expect(neo.content.interaction, 'interaction').to.be.an('object');
-    expect(neo.content.interaction.behavior).to.eql(ParticleInteractionBehavior.removeParticle, 'ParticleInteractionBehavior');
-    expect(neo.content.interaction.multiple).to.be.true;
-    expect(neo.content.interaction.radius).to.eql(0.5);
-  });
-
-  it('textureSheetAnimation', () => {
-    const item = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': ['random', [0, 1]],
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'shape': {
-          'shape': 'Sphere',
-          'radius': 1,
-          'arc': 360,
-          'arcMode': 0,
-        },
-        'renderer': {
-          'texture': 0,
-        },
-        'textureSheetAnimation': {
-          'animate': true,
-          'col': 2,
-          'row': 3,
-          'total': 4,
-          'animationDuration': 10,
-          'animationDelay': 2,
-          'cycles': ['curve', [[0, 10, 0, -3], [0.5, 0, 0, 0], [1, 10, 3, 0]]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const tsa = neo.content.textureSheetAnimation;
-
-    expect(tsa.row).to.eql(3, 'row');
-    expect(tsa.col).to.eql(2, 'col');
-    expect(tsa.total).to.eql(4, 'total');
-    expect(tsa.animate, 'animate').to.be.true;
-    expect(tsa.animationDuration[0]).to.eql(ValueType.CONSTANT, 'animationDuration.type');
-    expect(tsa.animationDuration[1]).to.eql(10, 'animationDuration.value');
-    expect(tsa.cycles[0]).to.eql(ValueType.BEZIER_CURVE, 'cycles.type');
-    // expect(tsa.cycles[1]).to.eql([[0, 10, 0, -3], [0.5, 0, 0, 0], [1, 10, 3, 0]], 'cycles.value');
-    expect(tsa.animationDelay[0]).to.eql(ValueType.CONSTANT, 'animationDelay.type');
-    expect(tsa.animationDelay[1]).to.eql(2, 'animationDelay.value');
-
-    const randomAnimation = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': ['random', [0, 1]],
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'shape': {
-          'shape': 'Sphere',
-          'radius': 1,
-          'arc': 360,
-          'arcMode': 0,
-        },
-        'renderer': {
-          'texture': 0,
-        },
-        'textureSheetAnimation': {
-          'animate': true,
-          'col': 2,
-          'row': 3,
-          'total': 4,
-          'animationDuration': ['random', [2, 8]],
-          'animationDelay': ['random', [0.5, 1]],
-          'cycles': ['curve', [[0, 10, 0, -3], [0.5, 0, 0, 0], [1, 10, 3, 0]]],
-        },
-      },
-    };
-    const neo2 = getStandardItem(randomAnimation);
-    const tsa2 = neo2.content.textureSheetAnimation;
-
-    expect(tsa2.animationDelay[0]).to.eql(ValueType.CONSTANT, 'animationDelay.type');
-    expect(tsa2.animationDelay[1]).to.eql(0.5, 'animationDelay.value');
-    expect(tsa2.animationDuration[0]).to.eql(ValueType.CONSTANT, 'animationDelay.type');
-    expect(tsa2.animationDuration[1]).to.eql(2, 'animationDelay.value');
-  });
-});
diff --git a/test/cases/particle/trails.test.mjs b/test/cases/particle/trails.test.mjs
deleted file mode 100644
index 4c274b7..0000000
--- a/test/cases/particle/trails.test.mjs
+++ /dev/null
@@ -1,85 +0,0 @@
-import { getStandardItem } from '../../../dist/fallback.mjs';
-import { ValueType, BlendingMode } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('particle trials', () => {
-  it('trails', () => {
-    const item = {
-      'name': 'item_12',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.1,
-      'particle': {
-        'options': {
-          'startLifetime': 1.2,
-          'startSize': 0.2,
-          'sizeAspect': 1,
-          'startSpeed': ['random', [0, 1]],
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 5,
-          'maxCount': 10,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'emission': {
-          'rateOverTime': 5,
-        },
-        'trails': {
-          'lifetime': ['lines', [[0, 0], [1, 1]]],
-          'maxPointPerTrail': 12,
-          'widthOverTrail': ['lines', [[0, 0], [1, 1]]],
-          'minimumVertexDistance': 1,
-          'dieWithParticles': true,
-          'colorOverTrail': {
-            '0%': 'rgb(0,0,0)',
-            '100%': 'rgba(255,255,255,0)',
-          },
-          'sizeAffectsWidth': true,
-          'sizeAffectsLifetime': true,
-          'parentAffectsPosition': true,
-          'inheritParticleColor': true,
-          'transparentOcclusion': true,
-          'colorOverLifetime': ['gradient', { '0.00': 'rgb(0,0,0)', '1.00': 'rgb(255,255,255)' }],
-          'opacityOverLifetime': ['random', [0, 1]],
-          'orderOffset': 1,
-          'blending': 6,
-          'texture': 1,
-          'occlusion': true,
-        },
-        'renderer': {
-          'texture': 0,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const trail = neo.content.trails;
-
-    expect(trail.lifetime[0]).to.eql(ValueType.LINE, 'lifetime.type');
-    expect(trail.lifetime[1]).to.eql([[0, 0], [1, 1]], 'lifetime.value');
-    expect(trail.parentAffectsPosition).to.be.true;
-    expect(trail.opacityOverLifetime[0]).to.eql(ValueType.RANDOM, 'opacityOverLifetime.type');
-    expect(trail.opacityOverLifetime[1]).to.eql([0, 1], 'opacityOverLifetime.value');
-    expect(trail.maxPointPerTrail).to.eql(12, 'maxPointPerTrail');
-    expect(trail.minimumVertexDistance).to.eql(1, 'minimumVertexDistance');
-    expect(trail.dieWithParticles).to.be.true;
-    expect(trail.colorOverTrail[0]).to.eql(ValueType.GRADIENT_COLOR, 'colorOverTrail.type');
-    expect(trail.colorOverTrail[1][0]).to.eql([0, 0, 0, 0, 255], 'colorOverTrail.value[0]');
-    expect(trail.colorOverTrail[1][1]).to.eql([1, 255, 255, 255, 0], 'colorOverTrail.value[1]');
-    expect(trail.colorOverLifetime[0]).to.eql(ValueType.GRADIENT_COLOR, 'colorOverLifetime.type');
-    expect(trail.colorOverLifetime[1][0]).to.eql([0, 0, 0, 0, 255], 'colorOverLifetime.value[0]');
-    expect(trail.colorOverLifetime[1][1]).to.eql([1, 255, 255, 255, 255], 'colorOverLifetime.value[1]');
-    expect(trail.sizeAffectsWidth, 'sizeAffectsWidth').to.be.true;
-    expect(trail.sizeAffectsLifetime, 'sizeAffectsLifetime').to.be.true;
-    expect(trail.transparentOcclusion, 'transparentOcclusion').to.be.true;
-    expect(trail.inheritParticleColor, 'inheritParticleColor').to.be.true;
-    expect(trail.orderOffset).to.eql(1, 'orderOffset');
-    expect(trail.blending).to.eql(BlendingMode.WEAK_LIGHT, 'blending');
-    expect(trail.occlusion).to.be.true;
-    expect(trail.texture).to.eql(1);
-    expect(trail.widthOverTrail[0]).to.eql(ValueType.LINE, 'widthOverTrail.type');
-    expect(trail.widthOverTrail[1]).to.eql([[0, 0], [1, 1]], 'widthOverTrail.value');
-  });
-
-});
diff --git a/test/cases/sprite/base.test.mjs b/test/cases/sprite/base.test.mjs
deleted file mode 100644
index b1f0713..0000000
--- a/test/cases/sprite/base.test.mjs
+++ /dev/null
@@ -1,635 +0,0 @@
-import { getStandardItem } from '../../../dist/fallback.mjs';
-import { ItemType, ItemEndBehavior, ValueType } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('sprite base', () => {
-  it('sprite duration,delay,renderLevel,type', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1 },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.delay).to.eql(0.56, 'delay');
-    expect(neo.duration).to.eql(2, 'duration');
-    expect(neo.renderLevel).to.eql('B+', 'renderLevel');
-    expect(neo.transform?.scale).to.deep.equal([1.2, 1.2, 1], 'transform.scale');
-    expect(neo.type).to.eql(ItemType.sprite, 'type');
-    expect(neo.content).to.be.an('object');
-    expect(neo.content.options.startColor).to.deep.equal([1, 1, 1, 1], 'startColor');
-    expect(neo.parentId).to.eql('5', 'parentId');
-    expect(neo.pn, 'pn').not.exist;
-  });
-
-  it('sprite anchor', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1, anchor: [1, 0] },
-      },
-    };
-    const requires = [];
-    const neo = getStandardItem(item, { requires });
-
-    expect(neo.content.renderer.anchor).to.deep.equals([1, 0]);
-    expect(requires).to.deep.equals(['anchor']);
-  });
-
-  it('sprite delete anchor', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'parentId': '5',
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1, anchor: [0.5, 0.5] },
-      },
-    };
-    const requires = [];
-    const neo = getStandardItem(item, { requires });
-
-    expect(neo.content.renderer.anchor).to.not.exist;
-    expect(requires).to.deep.equals([]);
-  });
-  it('sprite endBehavior', () => {
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1 },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.type).to.eql(ItemType.sprite, 'type');
-    expect(neo.endBehavior).to.eql(ItemEndBehavior.destroy, 'end');
-    expect(neo.parentId).not.exist;
-    const item2 = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'looping': true,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1 },
-      },
-    };
-    const neo2 = getStandardItem(item2);
-
-    expect(neo2.type).to.eql(ItemType.sprite, 'type 2');
-    expect(neo2.endBehavior).to.eql(ItemEndBehavior.loop, 'end 2');
-    const item3 = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'endBehavior': 4,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1 },
-      },
-    };
-    const neo3 = getStandardItem(item3);
-
-    expect(neo3.type).to.eql(ItemType.sprite, 'type 3');
-    expect(neo3.endBehavior).to.eql(ItemEndBehavior.freeze, 'end 3');
-  });
-
-  it('sprite static transform', () => {
-    const t = { 'position': [-2, 1, 2], 'rotation': [20, 10, 30] };
-    const item = {
-      'name': 'item_1',
-      'delay': 0.56,
-      'id': 1,
-      'ro': 0.1,
-      'sprite': {
-        transform: t,
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 0.5,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        }, 'renderer': { 'renderMode': 1 },
-      },
-    };
-    const neo = getStandardItem(item);
-
-    expect(neo.transform.position).to.deep.equal(t.position);
-    const r = neo.transform.rotation;
-
-    expect([+r[0].toFixed(1), +r[1].toFixed(1), +r[2].toFixed(1)]).to.deep.equal([22.2, -1.7, 31.4]);
-    expect(neo.transform?.scale).to.deep.equal([1.2, 2.4, 1]);
-    delete item.sprite.transform;
-    const neo2 = getStandardItem(item);
-
-    expect(neo2.transform?.position).not.exist;
-    expect(neo2.transform?.rotation).not.exist;
-    expect(neo2.transform?.scale).to.deep.equal([1.2, 2.4, 1]);
-  });
-
-  it('colorOverLifetime', () => {
-    const opacityLine = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'colorOverLifetime': {
-          'color': ['gradient', {
-            '0.00': 'rgba(229,12,12,1)',
-            '0.5': 'rgba(44,229,12,1)',
-            '1.00': 'rgba(79,29,201,1)',
-          }],
-          'opacity': ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-        },
-      },
-    };
-
-    const opacityCurve = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'colorOverLifetime': {
-          'color': ['gradient', {
-            '0.00': 'rgba(229,12,12,1)',
-            '0.5': 'rgba(44,229,12,1)',
-            '1.00': 'rgba(79,29,201,1)',
-          }],
-          'opacity': ['curve', [[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]]],
-        },
-      },
-    };
-
-    const gradientColor = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'colorOverLifetime': {
-          'color': { '0.00': 'rgba(229,12,12,1)', '0.5': 'rgba(44,229,12,1)', '1.00': 'rgba(79,29,201,1)' },
-          'opacity': ['lines', [[0, 1], [0.5, 0], [1, 1]]],
-        },
-      },
-    };
-
-    const neo1 = getStandardItem(opacityLine);
-
-    expect(neo1.content.colorOverLifetime.opacity[0]).to.eql(ValueType.LINE, 'opacity.type');
-    expect(neo1.content.colorOverLifetime.opacity[1]).to.eql([[0, 1], [0.5, 0], [1, 1]], 'opacity.value');
-    expect(neo1.content.colorOverLifetime.color[0]).to.eql(ValueType.GRADIENT_COLOR, 'colorGradient.type');
-    expect(neo1.content.colorOverLifetime.color[1][0]).to.eql([0, 229, 12, 12, 255], 'colorGradient.value');
-    expect(neo1.content.colorOverLifetime.color[1][1]).to.eql([0.5, 44, 229, 12, 255], 'colorGradient.value');
-    expect(neo1.content.colorOverLifetime.color[1][2]).to.eql([1, 79, 29, 201, 255], 'colorGradient.value');
-
-    const neo2 = getStandardItem(opacityCurve);
-
-    expect(neo2.content.colorOverLifetime.opacity[0]).to.eql(ValueType.BEZIER_CURVE, 'opacity.type');
-    // expect(neo2.content.colorOverLifetime.opacity[1]).to.eql([[0, 1, 0, -3], [0.5, 0, 0, 0], [1, 1, 3, 0]], 'opacity.value');
-
-    const neo3 = getStandardItem(gradientColor);
-
-    expect(neo3.content.colorOverLifetime.color[0]).to.eql(ValueType.GRADIENT_COLOR, 'colorGradient.type');
-    expect(neo3.content.colorOverLifetime.color[1][0]).to.eql([0, 229, 12, 12, 255], 'colorGradient.value');
-    expect(neo3.content.colorOverLifetime.color[1][1]).to.eql([0.5, 44, 229, 12, 255], 'colorGradient.value');
-    expect(neo3.content.colorOverLifetime.color[1][2]).to.eql([1, 79, 29, 201, 255], 'colorGradient.value');
-
-  });
-
-  it('sizeOverLifetime', () => {
-    const constantSize = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'sizeOverLifetime': {
-          'size': 3,
-        },
-      },
-    };
-    const sizeSeparate = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 1,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'sizeOverLifetime': {
-          'separateAxes': true,
-          'x': ['lines', [[0, 0], [1, 10]]],
-          'y': 2,
-          'z': ['curve', [[0, 0, 1, 0], [0.73, 0.24, 1, 1.1], [1, 1, 5, 1]]],
-        },
-      },
-    };
-
-    const neo1 = getStandardItem(constantSize);
-
-    expect(neo1.content.sizeOverLifetime.size[0]).to.eql(ValueType.CONSTANT, 'size.type');
-    expect(neo1.content.sizeOverLifetime.size[1]).to.eql(3, 'size.value');
-    expect(neo1.content.sizeOverLifetime.separateAxes, 'separateAxes').to.be.undefined;
-    expect(neo1.content.sizeOverLifetime.x, 'x').to.be.undefined;
-    expect(neo1.content.sizeOverLifetime.y, 'y').to.be.undefined;
-    expect(neo1.content.sizeOverLifetime.z, 'z').to.be.undefined;
-    const neo2 = getStandardItem(sizeSeparate);
-
-    expect(neo2.content.sizeOverLifetime.separateAxes, 'separateAxes').to.be.true;
-    expect(neo2.content.sizeOverLifetime.size, 'size').to.be.undefined;
-    expect(neo2.content.sizeOverLifetime.x[0]).to.eql(ValueType.LINE, 'sizeX.type');
-    expect(neo2.content.sizeOverLifetime.x[1]).to.eql([[0, 0], [1, 10]], 'sizeX.value');
-    expect(neo2.content.sizeOverLifetime.y[0]).to.eql(ValueType.CONSTANT, 'sizeY.type');
-    expect(neo2.content.sizeOverLifetime.y[1]).to.eql(2, 'sizeY.value');
-    expect(neo2.content.sizeOverLifetime.z[0]).to.eql(ValueType.BEZIER_CURVE, 'sizeZ.type');
-    // expect(neo2.content.sizeOverLifetime.z[1]).to.eql([[0, 0, 1, 0], [0.73, 0.24, 1, 1.1], [1, 1, 5, 1]], 'sizeZ.value');
-  });
-
-  it('velocityOverLifetime', () => {
-    const item = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravity': [0, -10, 0],
-          'gravityModifier': ['lines', [[0, 0], [0.5, 1], [1, 0]]],
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'velocityOverLifetime': {
-          'asMovement': false,
-          'linearX': 2,
-          'linearY': ['lines', [[0, 0], [0.25, 5], [0.75, 5], [1, 0]]],
-          'linearZ': ['curve', [[0, 1, 0, 0], [0.35, 0.85, -1.3, -1.22], [0.56, 0.16, -1, -1.2], [1, 0, 0, 0]]],
-          'asRotation': true,
-          'orbitalX': 30,
-          'orbitalY': ['lines', [[0, 180], [0.25, 90], [0.75, 90], [1, 0]]],
-          'orbitalZ': ['curve', [[0, 30, 0, -2], [0.2, 15.6, -0.8, -0.7], [0.82, 12.6, -0.57, -0.55], [1, 0, -4.9, 1]]],
-          'speedOverLifetime': 10,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const positionOverLifetime = neo.content.positionOverLifetime;
-
-    expect(positionOverLifetime.asMovement, 'asMovement').to.be.false;
-    expect(positionOverLifetime.linearX[0]).to.eql(ValueType.CONSTANT, 'linearX.type');
-    expect(positionOverLifetime.linearX[1]).to.eql(2, 'linearX.value');
-    expect(positionOverLifetime.linearY[0]).to.eql(ValueType.LINE, 'linearY.type');
-    expect(positionOverLifetime.linearY[1]).to.eql([[0, 0], [0.25, 5], [0.75, 5], [1, 0]], 'linearY.value');
-    expect(positionOverLifetime.linearZ[0]).to.eql(ValueType.BEZIER_CURVE, 'linearZ.type');
-    // expect(positionOverLifetime.linearZ[1]).to.eql([[0, 1, 0, 0], [0.35, 0.85, -1.3, -1.22], [0.56, 0.16, -1, -1.2], [1, 0, 0, 0]], 'linearZ.value');
-    expect(positionOverLifetime.asRotation, 'asRotate').to.be.true;
-    expect(positionOverLifetime.orbitalX[0]).to.eql(ValueType.CONSTANT, 'orbitalX.type');
-    expect(positionOverLifetime.orbitalX[1]).to.eql(30, 'orbitalX.value');
-    expect(positionOverLifetime.orbitalY[0]).to.eql(ValueType.LINE, 'orbitalY.type');
-    expect(positionOverLifetime.orbitalY[1]).to.eql([[0, 180], [0.25, 90], [0.75, 90], [1, 0]], 'orbitalY.value');
-    expect(positionOverLifetime.orbitalZ[0]).to.eql(ValueType.BEZIER_CURVE, 'orbitalZ.type');
-    // expect(positionOverLifetime.orbitalZ[1]).to.eql([[0, 30, 0, -2], [0.2, 15.6, -0.8, -0.7], [0.82, 12.6, -0.57, -0.55], [1, 0, -4.9, 1]], 'orbitalZ.value');
-    expect(positionOverLifetime.speedOverLifetime[0]).to.eql(ValueType.CONSTANT, 'speedOverLifetime.type');
-    expect(positionOverLifetime.speedOverLifetime[1]).to.eql(10, 'speedOverLifetime.value');
-    expect(positionOverLifetime.startSpeed, 'startSpeed').to.be.undefined;
-    expect(positionOverLifetime.gravity).to.eql([0, -10, 0], 'gravity');
-    expect(positionOverLifetime.gravityOverLifetime[0]).to.eql(ValueType.LINE, 'gravityOverLifetime.type');
-    expect(positionOverLifetime.gravityOverLifetime[1]).to.eql([[0, 0], [0.5, 1], [1, 0]], 'gravityOverLifetime.value');
-  });
-
-  it('rotateOverLifetime', () => {
-    const item = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravity': [0, -10, 0],
-          'gravityModifier': ['lines', [[0, 0], [0.5, 1], [1, 0]]],
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'rotationOverLifetime': {
-          'asRotation': true,
-          'angularVelocity': ['curve', [[0, 0, 1, 6], [0.17, 0.54, 0.72, 0.72], [0.78, 0.7, 1, 1], [1, 1, 1, 1]]],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const rot = neo.content.rotationOverLifetime;
-
-    expect(rot.asRotation, 'asRotation').to.be.true;
-    expect(rot.separateAxes, 'separateAxes').to.be.undefined;
-    expect(rot.z[0]).eql(ValueType.BEZIER_CURVE, 'angularVelocity.type');
-    // expect(rot.z[1]).eql([[0, 0, 1, 6], [0.17, 0.54, 0.72, 0.72], [0.78, 0.7, 1, 1], [1, 1, 1, 1]], 'angularVelocity.value');
-
-    const separateItem = {
-      'name': 'null_11',
-      'delay': 0,
-      'id': 12,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 1.2,
-          'sizeAspect': 1,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravity': [0, -10, 0],
-          'gravityModifier': ['lines', [[0, 0], [0.5, 1], [1, 0]]],
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'renderMode': 1,
-        },
-        'rotationOverLifetime': {
-          'asRotation': true,
-          'angularVelocity': ['curve', [[0, 0, 1, 6], [0.17, 0.54, 0.72, 0.72], [0.78, 0.7, 1, 1], [1, 1, 1, 1]]],
-          'separateAxes': true,
-          'x': 10,
-          'y': ['lines', [[0, 1], [0.25, 0], [0.75, 0], [1, 1]]],
-          'z': ['curve', [[0, 1, 0, 0], [0.72, 0.82, -0.98, -1.1], [1, 0, -5, 7]]],
-        },
-      },
-    };
-
-    const neo2 = getStandardItem(separateItem);
-    const rot2 = neo2.content.rotationOverLifetime;
-
-    expect(rot2.asRotation, 'asRotation').to.be.true;
-    expect(rot2.separateAxes, 'separateAxes').to.be.true;
-    expect(rot2.x[0]).eql(ValueType.CONSTANT, 'x.type');
-    expect(rot2.x[1]).eql(10, 'x.value');
-    expect(rot2.y[0]).eql(ValueType.LINE, 'y.type');
-    expect(rot2.y[1]).eql([[0, 1], [0.25, 0], [0.75, 0], [1, 1]], 'y.value');
-    expect(rot2.z[0]).eql(ValueType.BEZIER_CURVE, 'z.type');
-    // expect(rot2.z[1]).eql([[0, 1, 0, 0], [0.72, 0.82, -0.98, -1.1], [1, 0, -5, 7]], 'z.value');
-  });
-
-  it('sprite textureSheetAnimation', () => {
-    const item = {
-      'name': '日历逐帧',
-      'delay': 0,
-      'id': 15,
-      'ro': 0.01,
-      'sprite': {
-        'options': {
-          'startLifetime': 5,
-          'startSize': 2,
-          'startSpeed': 0,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 1,
-          'maxCount': 1,
-          'gravityModifier': 1,
-          'startSizeX': 3.5,
-          'startSizeY': 3.5,
-          'endBehavior': 4,
-          'sizeAspect': 1,
-          'looping': false,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'texture': 0,
-          'occlusion': false,
-          'order': 1,
-          'renderMode': 1,
-        },
-        'textureSheetAnimation': {
-          'col': 8,
-          'row': 8,
-          'animate': true,
-          'cycles': 0,
-          'blend': false,
-          'animationDuration': 2,
-          'animationDelay': 0,
-          'total': 59,
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const tsa = neo.content.textureSheetAnimation;
-
-    expect(tsa.row).to.eql(8, 'row');
-    expect(tsa.col).to.eql(8, 'col');
-    expect(tsa.total).to.eql(59, 'total');
-    expect(tsa.animate, 'animate').to.be.true;
-  });
-
-  it('splits', () => {
-    const item = {
-      'name': 'earth',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.01,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 6,
-          'sizeAspect': 1.1183294663573087,
-          'startColor': ['color', [255, 255, 255]],
-          'duration': 2,
-          'gravityModifier': 0,
-          'endBehavior': 4,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'texture': 1,
-          'order': 0,
-        },
-        'transform': {
-          'position': [0.022863817233533368, -0.021775064031936076, -2.5],
-        },
-        'splits': [[0.001953125, 0.001953125, 0.94140625, 0.841796875, 0]],
-      },
-    };
-
-    const neo = getStandardItem(item);
-    const split = neo.content.splits;
-
-    split.forEach(sp => {
-      expect(sp.length).to.eql(5);
-      expect(sp[0], 'sx').to.be.an('number');
-      expect(sp[1], 'sy').to.be.an('number');
-      expect(sp[2], 'width').to.be.an('number');
-      expect(sp[3], 'height').to.be.an('number');
-      expect(sp[4], 'flip').to.be.oneOf([0, 1]);
-    });
-
-  });
-
-  it('options startRotation', () => {
-    const item = {
-      'name': 'earth',
-      'delay': 0,
-      'id': 12,
-      'ro': 0.01,
-      'sprite': {
-        'options': {
-          'startLifetime': 2,
-          'startSize': 6,
-          'sizeAspect': 1.1183294663573087,
-          'startColor': ['color', [255, 255, 255]],
-          startRotation: 30,
-          'duration': 2,
-          'gravityModifier': 0,
-          'endBehavior': 4,
-          'renderLevel': 'B+',
-        },
-        'renderer': {
-          'texture': 1,
-          'order': 0,
-        },
-        'transform': {
-          rotation: [0, 0, 10],
-        },
-      },
-    };
-
-    const neo = getStandardItem(item);
-
-    expect(neo.transform?.rotation?.[0]).to.closeTo(0, 0.0001);
-    expect(neo.transform?.rotation?.[1]).to.closeTo(0, 0.0001);
-    expect(neo.transform?.rotation?.[2]).to.closeTo(40, 0.0001);
-    // @ts-expect-error
-    delete item.sprite.transform;
-
-    const rr = getStandardItem(item);
-
-    expect(rr.transform?.rotation?.[0]).to.closeTo(0, 0.0001);
-    expect(rr.transform?.rotation?.[1]).to.closeTo(0, 0.0001);
-    expect(rr.transform?.rotation?.[2]).to.closeTo(30, 0.0001);
-  });
-});
diff --git a/test/cases/sprite/filter.test.mjs b/test/cases/sprite/filter.test.mjs
deleted file mode 100644
index 251c921..0000000
--- a/test/cases/sprite/filter.test.mjs
+++ /dev/null
@@ -1,39 +0,0 @@
-/**
- * 主要用于测试 filter 字段被过滤掉
- */
-import { ItemType, ValueType } from '../../../dist/index.mjs';
-import { getStandardJSON, deleteEmptyValue, forEach } from '../../../dist/fallback.mjs';
-
-const { expect } = chai;
-
-describe('filter', () => {
-  it('filter 元素被过滤掉', () => {
-    const json = '{"images":[],"version":"1.5","type":"mars","compositions":[{"id":"28","name":"欢呼粒子","duration":3,"startTime":0,"endBehavior":2,"previewSize":[750,750],"items":[{"id":"557","name":"face","duration":2,"type":"2","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"Cone","radius":0.6,"arc":360,"arcMode":0,"angle":33,"type":2,"alignSpeedDirection":false,"turbulenceX":[0,0],"turbulenceY":[0,0],"turbulenceZ":[0,0]},"splits":[[0.5400390625,0.0009765625,0.3125,0.078125,0]],"options":{"startColor":[8,[1,1,1,1]],"maxCount":100,"startLifetime":[4,[1,1.4]],"startDelay":[0,0],"startSize":[4,[0.2,0.4]],"sizeAspect":[0,1],"start3DSize":false,"startRotationZ":[4,[0,360]]},"renderer":{"renderMode":1,"texture":0},"emission":{"rateOverTime":[0,0],"burstOffsets":[{"index":0,"x":0,"y":0,"z":0},{"index":1,"x":0,"y":0,"z":0},{"index":2,"x":0,"y":0,"z":0}],"bursts":[{"time":0,"count":22,"cycles":1,"interval":0},{"time":0.5,"count":22,"cycles":1,"interval":0},{"time":1,"count":22,"cycles":1,"interval":0}]},"positionOverLifetime":{"asMovement":false,"speedOverLifetime":[6,[[0,1,0,0],[0.2169,0.8442,-1.3,-1.22],[0.4336,0.1332,-0.4662,-0.5119],[1,0,0,0]]],"linearY":[0,0],"linearX":[0,0],"linearZ":[0,0],"startSpeed":[4,[9,16]],"gravity":[0,-7,0],"gravityOverLifetime":[0,1]},"sizeOverLifetime":{"size":[5,[[0,0.8],[0.2547,1.4018],[1,1.6]]]},"rotationOverLifetime":{"asRotation":false,"z":[4,[260,400]]},"colorOverLifetime":{"opacity":[5,[[0,0],[0.1769,1],[0.8198,1],[1,0]]]},"textureSheetAnimation":{"col":4,"animate":false,"total":0,"row":1}}},{"id":"562","name":"filter_447","duration":5,"type":"8","visible":true,"endBehavior":0,"delay":0,"renderLevel":"B+","content":{"options":{},"filter":{"name":"bloom","radius":32,"colorThreshold":[220,220,220],"bloomAddon":[0,0.6],"colorAddon":[0,0.7]},"renderer":{"renderMode":0},"positionOverLifetime":{"path":[2,[0,0,0]]}},"transform":{"position":[0,0,-0.000002098084138424383],"rotation":[0,0,0],"scale":[9,9,1]}}]}],"compositionId":"28","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
-    const result = getStandardJSON(JSON.parse(json));
-    const filterItems = result.items.filter(item => item.type === '8');
-
-    expect(filterItems.length).eq(0);
-  });
-
-  it('过滤逻辑不影响不包含 filter 元素的合成', () => {
-    const json = '{"compositionId":3,"requires":[],"compositions":[{"name":"彩色纸片_满屏落下","id":3,"duration":9,"endBehavior":1,"camera":{"fov":60,"far":20,"near":0.1,"position":[0,0,8],"clipMode":0,"z":8},"items":[{"name":"彩色纸片","delay":0,"id":11,"ro":0.1,"particle":{"options":{"startLifetime":["random",[2,3]],"startSize":["random",[0.15,0.2]],"sizeAspect":1.040983606557377,"startSpeed":["random",[1,3]],"startColor":["colors",["rgba(245, 166 , 35 , 1)","rgba(80, 227 , 194 , 1)","rgba(89, 58 , 245 , 1)","rgba(54, 16 , 242 , 1)","rgba(208, 2 , 27 , 1)"]],"duration":9,"maxCount":100,"gravityModifier":1,"gravity":[0,-1,0],"looping":false,"start3DRotation":true,"startRotationZ":4,"startRotationY":3,"startRotationX":4,"renderLevel":"B+"},"emission":{"rateOverTime":["lines",[[0,55],[0.1974,55],[0.3105,0],[1,0]]],"burstOffsets":[{"index":0,"x":0,"y":0,"z":0}],"bursts":[]},"shape":{"shape":"Edge","radius":0.8,"arc":360,"arcMode":0,"angle":32,"width":10},"renderer":{"texture":0},"textureSheetAnimation":{"col":2,"row":2},"transform":{"rotation":[0,0,180],"position":[0,5,0]},"colorOverLifetime":{"opacity":["curve",[[0,0,0,4.3235],[0.1569,0.9994,0,0],[0.72,0.82,-0.98,-1.1],[1,0,-5,7]]]},"rotationOverLifetime":{"angularVelocity":["random",[300,500]]},"splits":[[0.00390625,0.00390625,0.49609375,0.4765625,0]]}}],"meta":{"previewSize":[0,0]}}],"gltf":[],"images":["https://gw.alipayobjects.com/zos/gltf-asset/mars-cli/MNJVBYCSYDWN/760117553-3d179.png"],"version":"0.1.47","shapes":[],"plugins":[],"type":"mars","_imgs":{"3":[0]},"imageTags":["B+"]}';
-    const result = getStandardJSON(JSON.parse(json));
-    const filterItems = result.items.filter(item => item.type === '8');
-
-    expect(filterItems.length).eq(0);
-  });
-
-  it('particle filter 被过滤掉', () => {
-    const json = '{"images":[],"spines":[],"version":"1.5","shapes":[],"plugins":[],"type":"mars","compositions":[{"id":"25","name":"distortion","duration":5,"startTime":0,"endBehavior":0,"previewSize":[0,0],"items":[{"id":"36","name":"distortion","duration":5,"type":"2","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"shape":{"shape":"None","radius":1,"arc":360,"arcMode":0,"type":0},"options":{"startColor":[8,[1,1,1,1]],"maxCount":1,"startLifetime":[0,5],"startDelay":[0,0],"start3DSize":true,"startSizeX":[0,6],"startSizeY":[0,9]},"renderer":{"texture":0,"order":1},"emission":{"rateOverTime":[0,5]},"positionOverLifetime":{"startSpeed":[0,0],"gravityOverLifetime":[0,1]},"rotationOverLifetime":{"asRotation":true,"z":[0,5]},"filter":{"name":"distortion","center":[0.5,0],"direction":[0.2,1],"strength":[0,0.008],"period":[0,6],"waveMovement":[5,[[0,0],[1,6]]]}},"transform":{"position":[1.723219445898673,3.100635886398397,0],"rotation":[0,0,0],"scale":[1,1,1]}},{"id":"37","name":"virus","duration":5,"type":"1","visible":true,"endBehavior":4,"delay":0,"renderLevel":"B+","content":{"options":{"startColor":[1,1,1,1]},"renderer":{"texture":1,"order":2},"positionOverLifetime":{},"splits":[[0.001953125,0.001953125,0.673828125,0.619140625,0]]},"transform":{"position":[-0.14902922818470277,-0.1669679315773056,0],"rotation":[0,0,0],"scale":[3.5,3.2159420289855074,1]}}]}],"requires":[],"compositionId":"25","bins":[],"textures":[{"source":0,"flipY":true},{"source":1,"flipY":true}]}';
-    const result = getStandardJSON(JSON.parse(json));
-    const filterItems = result.items.filter(item => {
-      if (item.type === '2' && item.content.filter) {
-        return true;
-      }
-
-      return false;
-    });
-
-    expect(filterItems.length).eq(0);
-  });
-});
diff --git a/test/cases/ui/ui.test.mjs b/test/cases/ui/ui.test.mjs
deleted file mode 100644
index 0922148..0000000
--- a/test/cases/ui/ui.test.mjs
+++ /dev/null
@@ -1,117 +0,0 @@
-import { getStandardItem } from '../../../dist/fallback.mjs';
-import { ItemType, InteractType, InteractBehavior, END_BEHAVIOR_PAUSE } from '../../../dist/index.mjs';
-
-const { expect } = chai;
-
-describe('ui element', () => {
-  const items = [
-    {
-      'name': 'click',
-      'delay': 0,
-      'id': 6,
-      'ui': {
-        'options': {
-          'duration': 2,
-          'type': 'click',
-          'width': 2,
-          'height': 1,
-          'showPreview': true,
-          'previewColor': ['color', [237, 21, 21, 1]],
-        },
-        'transform': { 'position': [0.2, 1.5, 0.1] },
-      },
-    },
-    {
-      'name': 'message',
-      'delay': 0,
-      'id': 5,
-      'ui': {
-        'options': {
-          'duration': 2,
-          'type': 'message',
-          'width': 0.6,
-          'height': 0.4,
-          'showPreview': true,
-          'endBehavior': 1,
-        },
-        'transform': { 'position': [-1, -0.02, 0] },
-      },
-    },
-    {
-      'name': 'drag',
-      'delay': 0,
-      'id': 4,
-      'ui': {
-        'options': {
-          'duration': 2,
-          'type': 'drag',
-          'width': 0.6,
-          'height': 0.4,
-          'showPreview': true,
-          'enableInEditor': true,
-          'target': 'camera',
-          'dxRange': [1, 5],
-        },
-      },
-    },
-    {
-      'name': 'orientation',
-      'delay': 0,
-      'id': 3,
-      'ui': {
-        'options': {
-          'duration': 2,
-          'type': 'orientation',
-          'width': 0.6,
-          'height': 0.4,
-          'showPreview': true,
-        },
-      },
-    },
-  ];
-
-  it('load click item', () => {
-    const item = getStandardItem(items[0]);
-
-    expect(item.type).to.eql(ItemType.interact);
-    expect(item.duration).to.eql(2);
-    expect(item.transform?.position).to.eql([0.2, 1.5, 0.1]);
-    expect(item.transform?.scale).to.eql([2, 1, 1]);
-    const content = item.content;
-    const options = content.options;
-
-    expect(options.type).to.eql(InteractType.CLICK);
-    expect(options.showPreview).to.be.true;
-    expect(options.behavior).to.eql(InteractBehavior.NOTIFY, 'endBehavior');
-  });
-
-  it('load message item', () => {
-    const item = getStandardItem(items[1]);
-
-    expect(item.type).to.eql(ItemType.interact);
-    expect(item.duration).to.eql(2);
-    expect(item.endBehavior).to.eql(END_BEHAVIOR_PAUSE);
-    expect(item.transform?.position).to.eql([-1, -0.02, 0]);
-    expect(item.transform?.scale).to.eql([0.6, 0.4, 1]);
-    const options = item.content.options;
-
-    expect(options.type).to.eql(InteractType.MESSAGE, 'type');
-  });
-
-  it('load drag item', () => {
-    const item = getStandardItem(items[2]);
-
-    expect(item.type).to.eql(ItemType.interact);
-    expect(item.duration).to.eql(2);
-    expect(item.transform?.scale).to.eql([0.6, 0.4, 1]);
-    const content = item.content;
-    const options = content.options;
-
-    expect(options.type).to.eql(InteractType.DRAG, 'type');
-    expect(options.enableInEditor).to.be.true;
-    expect(options.dxRange).to.eql([1, 5]);
-    expect(options.dyRange).to.not.exist;
-    expect(options.target).to.eql('camera');
-  });
-
-});
diff --git a/test/index.html b/test/index.html
deleted file mode 100644
index aa81563..0000000
--- a/test/index.html
+++ /dev/null
@@ -1,24 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="utf-8" />
-  <title>spec tests</title>
-  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
-  <link rel="stylesheet" href="../node_modules/mocha/mocha.css">
-</head>
-<body>
-  <div id="mocha"></div>
-
-  <script src="../node_modules/chai/chai.js"></script>
-  <script src="../node_modules/chai-spies/chai-spies.js"></script>
-  <script src="../node_modules/mocha/mocha.js"></script>
-  <script class="mocha-init" type="module">
-    mocha.setup('bdd');
-    mocha.checkLeaks();
-  </script>
-  <script src="./cases/index.mjs" type="module"></script>
-  <script class="mocha-exec" type="module">
-    mocha.run();
-  </script>
-</body>
-</html>
diff --git a/tsconfig.build.json b/tsconfig.build.json
new file mode 100644
index 0000000..6038ce8
--- /dev/null
+++ b/tsconfig.build.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "target": "ESNext"
+  },
+  "include": [
+    "src",
+  ],
+  "exclude": [
+    "**/*.spec.ts"
+  ]
+}
diff --git a/tsconfig.bundle.json b/tsconfig.bundle.json
deleted file mode 100644
index d5af4eb..0000000
--- a/tsconfig.bundle.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "extends": "./tsconfig.json",
-  "compilerOptions": {
-    "removeComments": false,
-    "target": "ES5"
-  },
-  "exclude": [
-    "**/dist/**",
-    "node_modules",
-    "**/*.test.ts"
-  ]
-}
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index fd22020..55fc3f1 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,40 +1,28 @@
 {
   "compilerOptions": {
-    "target": "ES6",
+    "target": "ESNext",
     "module": "ESNext",
     "baseUrl": ".",
-    "lib": [
-      "DOM",
-      "ES2015",
-      "ES2016"
-    ],
-    "allowJs": true,
+    "outDir": "es",
+    "allowJs": false,
     "declaration": true,
-    "declarationDir": ".",
-    "removeComments": true,
-    "noEmit": false,
+    "declarationDir": "es",
     "strict": true,
     "noImplicitAny": true,
     "noImplicitThis": true,
     "moduleResolution": "node",
     "downlevelIteration": true,
     "strictNullChecks": true,
-    // "noUnusedLocals": true,
+    "noUnusedLocals": true,
     "forceConsistentCasingInFileNames": true,
     "allowSyntheticDefaultImports": true,
     "esModuleInterop": true,
-    "outDir": "dist",
+    "noImplicitOverride": true,
     "skipLibCheck": true,
-    "strictPropertyInitialization": false
-  },
-  "include": [
-    "./fallback",
-    "./src",
-    "./test"
-  ],
-  "exclude": [
-    "node_modules",
-    "temp",
-    "dist"
-  ]
-}
\ No newline at end of file
+    "strictPropertyInitialization": false,
+    "lib": [
+      "DOM",
+      "ESNext"
+    ]
+  }
+}

From 6adf3053e8d04f520eaa640e24e02d8e160021fc Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 7 May 2024 17:39:17 +0800
Subject: [PATCH 32/62] feat: add image id

---
 src/image.ts | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/image.ts b/src/image.ts
index 05feb5a..d6a8ac8 100644
--- a/src/image.ts
+++ b/src/image.ts
@@ -84,6 +84,7 @@ export interface TemplateContent {
  * 纹理贴图属性
  */
 export interface Image {
+  id: string,
   /**
    * 纹理贴图地址
    */

From 6bbb2e484d03a03aacf9d846d61762d318fc0cbe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Wed, 8 May 2024 17:40:18 +0800
Subject: [PATCH 33/62] feat: add animation clip data (#44)

* feat: add  AnimationClipData

* perf: opt code

* perf: opt code
---
 src/animation-clip-data.ts | 31 +++++++++++++++++++++++++++++++
 src/components.ts          |  1 +
 src/index.ts               |  1 +
 3 files changed, 33 insertions(+)
 create mode 100644 src/animation-clip-data.ts

diff --git a/src/animation-clip-data.ts b/src/animation-clip-data.ts
new file mode 100644
index 0000000..56bc0db
--- /dev/null
+++ b/src/animation-clip-data.ts
@@ -0,0 +1,31 @@
+import type { EffectsObjectData } from './components';
+import type { FixedNumberExpression, FixedVec3Expression } from './number-expression';
+
+export interface AnimationClipData extends EffectsObjectData {
+  positionCurves: PositionCurveData[],
+  eulerCurves: EulerCurveData[],
+  scaleCurves: ScaleCurveData[],
+  floatCurves: FloatCurveData[],
+}
+
+export interface PositionCurveData {
+  path: string[],
+  keyFrames: FixedVec3Expression,
+}
+
+export interface EulerCurveData {
+  path: string[],
+  keyFrames: FixedVec3Expression,
+}
+
+export interface ScaleCurveData {
+  path: string[],
+  keyFrames: FixedVec3Expression,
+}
+
+export interface FloatCurveData {
+  path: string[],
+  property: string[],
+  className: string,
+  keyFrames: FixedNumberExpression,
+}
\ No newline at end of file
diff --git a/src/components.ts b/src/components.ts
index fb24306..038af5b 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -11,6 +11,7 @@ export enum DataType {
   CameraController = 'CameraController',
   Geometry = 'Geometry',
   Texture = 'Texture',
+  AnimationClip = 'AnimationClip',
   TextComponent = 'TextComponent',
 
   // FIXME: 先完成ECS的场景转换,后面移到spec中
diff --git a/src/index.ts b/src/index.ts
index 4a56262..55d29e8 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -19,6 +19,7 @@ export * from './item/effect-item';
 export * from './item/text-item';
 export * from './item/model';
 export * from './vfx-item-data';
+export * from './animation-clip-data';
 export * from './binary';
 export * from './text';
 export * from './components';

From a245f7c16db874d00173e50d57dc3a1a5971b063 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Thu, 9 May 2024 13:15:57 +0800
Subject: [PATCH 34/62] feat: update geometry data (#45)

* feat: update geometry data

* feat: update geometry data

* feat: update vertex channels
---
 src/components.ts      | 26 +++++++++++++++++++++++++-
 src/item/model/mesh.ts |  4 ++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/src/components.ts b/src/components.ts
index 038af5b..4ccabfd 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -75,6 +75,7 @@ export interface GeometryData extends EffectsObjectData {
   vertexData: VertexData,
   indexFormat: number,
   indexOffset: number,
+  subMeshes: SubMesh[],
   /**
    * 模型绘制模式,默认为 GeometryType.TRIANGLES(三角形)
    * @default GeometryType.TRIANGLES
@@ -84,6 +85,17 @@ export interface GeometryData extends EffectsObjectData {
    * 存放 position, uv, normal, indices 的打包数据
    */
   buffer: string,
+  /**
+   * 所有的骨骼名称
+   */
+  boneNames?: string[],
+  rootBoneName?: string,
+  inverseBindMatrices?: number[],
+}
+
+interface SubMesh {
+  offset: number,
+  count: number,
 }
 
 export enum GeometryType {
@@ -116,9 +128,10 @@ export enum GeometryType {
    */
   TRIANGLE_FAN,
 }
+
 export interface VertexData {
   vertexCount: number,
-  channels: VertexChannel[],  // channel 存放顺序 position, uv, normal
+  channels: Record<string, VertexChannel>, // channel 存放顺序 position, uv, normal
 }
 
 export interface VertexChannel {
@@ -127,6 +140,17 @@ export interface VertexChannel {
   dimension: number,
 }
 
+export enum GeometryBufferSemantic {
+  Positon = 'position',
+  Uv = 'uv',
+  Uv2 = 'uv2',
+  Normal = 'normal',
+  Tangent = 'tangent',
+  Color = 'color',
+  BoneIndices = 'boneIndices',
+  BoneWeights = 'boneWeights'
+}
+
 export interface ShaderData extends EffectsObjectData {
   vertex: string,
   fragment: string,
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index e41b97f..3a2f06f 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -114,6 +114,10 @@ export interface ModelMeshComponentData extends ComponentData {
    * 蒙皮数据
    */
   skin?: SkinData,
+  /**
+   * 骨骼根节点
+   */
+  rootBone: DataPath,
   /**
    * Morph数据
    */

From 9095501550f67c1685fbcc00f5329ac4d83b3b7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Thu, 9 May 2024 13:51:20 +0800
Subject: [PATCH 35/62] perf: vertex channel use array (#46)

* perf: opt vertex channels

* perf: update
---
 src/components.ts | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/components.ts b/src/components.ts
index 4ccabfd..dbe1db8 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -131,10 +131,11 @@ export enum GeometryType {
 
 export interface VertexData {
   vertexCount: number,
-  channels: Record<string, VertexChannel>, // channel 存放顺序 position, uv, normal
+  channels: VertexChannel[], // channel 存放顺序 position, uv, normal
 }
 
 export interface VertexChannel {
+  semantic: string,
   offset: number,
   format: number,
   dimension: number,

From 7816bd2998561dd23e140fb1968b2186844d80ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Thu, 9 May 2024 16:44:48 +0800
Subject: [PATCH 36/62] fix: add several types and update mesh component (#47)

* feat: update geometry data

* feat: update geometry data

* feat: update vertex channels

* fix: add format type and update mesh component

* fix: add RenderType and RenderFace

* chore: update

---------

Co-authored-by: wumaolinmaoan <wumaolin1998@outlook.com>
Co-authored-by: xuezhen.hxz <xuezhen.hxz@alibaba-inc.com>
---
 src/components.ts      | 13 ++++++++++++-
 src/item/model/mesh.ts |  7 ++-----
 src/type.ts            | 11 +++++++++++
 3 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index dbe1db8..2e5e408 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -134,11 +134,22 @@ export interface VertexData {
   channels: VertexChannel[], // channel 存放顺序 position, uv, normal
 }
 
+export enum VertexFormatType {
+  FLOAT,
+  INT,
+  SHORT,
+  BYTE,
+  UNSIGNED_INT,
+  UNSIGNED_SHORT,
+  UNSIGNED_BYTE,
+}
+
 export interface VertexChannel {
   semantic: string,
   offset: number,
-  format: number,
+  format: VertexFormatType,
   dimension: number,
+  normalize?: boolean,
 }
 
 export enum GeometryBufferSemantic {
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index 3a2f06f..d384ff3 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -110,10 +110,6 @@ export interface MorphData {
 
 export interface ModelMeshComponentData extends ComponentData {
   hide?: boolean,
-  /**
-   * 蒙皮数据
-   */
-  skin?: SkinData,
   /**
    * 骨骼根节点
    */
@@ -122,6 +118,7 @@ export interface ModelMeshComponentData extends ComponentData {
    * Morph数据
    */
   morph?: MorphData,
-  primitives: PrimitiveData[],
+  geometry: DataPath,
+  materials: DataPath[],
   interaction?: ModelItemBounding,
 }
diff --git a/src/type.ts b/src/type.ts
index 4fb425b..41fc9a2 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -690,3 +690,14 @@ export interface ShapeGeometry {
    */
   s: ShapeSplits,
 }
+
+export enum RenderType {
+  Opaque = 'Opaque',
+  Transparent = 'Transparent',
+}
+
+export enum RenderFace {
+  Both = 'Both',
+  Back = 'Back',
+  Front = 'Front',
+}

From 81a94ad08407133302f836532bf3af8a4ba68409 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Fri, 10 May 2024 11:01:13 +0800
Subject: [PATCH 37/62] chore: rename (#48)

* feat: update geometry data

* feat: update geometry data

* feat: update vertex channels

* fix: add format type and update mesh component

* fix: add RenderType and RenderFace

* chore: update

* chore: rename

---------

Co-authored-by: wumaolinmaoan <wumaolin1998@outlook.com>
Co-authored-by: xuezhen.hxz <xuezhen.hxz@alibaba-inc.com>
---
 src/components.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components.ts b/src/components.ts
index 2e5e408..8b67b5d 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -152,7 +152,7 @@ export interface VertexChannel {
   normalize?: boolean,
 }
 
-export enum GeometryBufferSemantic {
+export enum VertexBufferSemantic {
   Positon = 'position',
   Uv = 'uv',
   Uv2 = 'uv2',

From 7acdec0e1b3012f2cd24292bc690c7673cd85ccb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Fri, 10 May 2024 11:18:30 +0800
Subject: [PATCH 38/62] fix: add index type (#49)

* feat: update geometry data

* feat: update geometry data

* feat: update vertex channels

* fix: add format type and update mesh component

* fix: add RenderType and RenderFace

* chore: update

* chore: rename

* fix: add IndexFormatType

---------

Co-authored-by: wumaolinmaoan <wumaolin1998@outlook.com>
Co-authored-by: xuezhen.hxz <xuezhen.hxz@alibaba-inc.com>
---
 src/components.ts | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 8b67b5d..423c23c 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -135,13 +135,16 @@ export interface VertexData {
 }
 
 export enum VertexFormatType {
-  FLOAT,
-  INT,
-  SHORT,
-  BYTE,
-  UNSIGNED_INT,
-  UNSIGNED_SHORT,
-  UNSIGNED_BYTE,
+  Float32,
+  Int16,
+  Int8,
+  UInt16,
+  UInt8,
+}
+
+export enum IndexFormatType {
+  UInt16,
+  UInt32,
 }
 
 export interface VertexChannel {

From 49410d86e7451d8f86f58756315a39ae98a3bd6d Mon Sep 17 00:00:00 2001
From: liuxi150 <liuxi150@hotmail.com>
Date: Mon, 13 May 2024 11:41:56 +0800
Subject: [PATCH 39/62] fix: update

---
 src/item/model/mesh.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index d384ff3..4b2cc65 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -113,7 +113,7 @@ export interface ModelMeshComponentData extends ComponentData {
   /**
    * 骨骼根节点
    */
-  rootBone: DataPath,
+  rootBone?: DataPath,
   /**
    * Morph数据
    */

From 749730b8d12acfa92ddbf694861b9ef12dd5f1b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Mon, 13 May 2024 15:54:53 +0800
Subject: [PATCH 40/62] fix: update vertex buffer semantic (#52)

* feat: update vertex semantic

* fix: add blend shape semantic

---------

Co-authored-by: wumaolinmaoan <wumaolin1998@outlook.com>
---
 src/components.ts | 46 ++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 38 insertions(+), 8 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 423c23c..4698ed0 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -155,15 +155,45 @@ export interface VertexChannel {
   normalize?: boolean,
 }
 
+// BINORMAL[n]	Binormal	float4
+// BLENDINDICES[n]	混合索引	uint
+// BLENDWEIGHT[n]	混合权重	FLOAT
+// COLOR[n]	漫射和反射颜色	float4
+// NORMAL[n]	法向矢量	float4
+// POSITION[n]	对象空间中的顶点位置。	float4
+// POSITIONT	变换的顶点位置。	float4
+// PSIZE[n]	点大小	FLOAT
+// TANGENT[n]	正切	float4
+// TEXCOORD[n]	纹理坐标	float4
+// POSITION_BS[n]	Blend Shape 空间中的顶点位置	float4
+// NORMAL_BS[n]	Blend Shape 空间中的法向矢量	float4
+// TANGENT_BS[n]	Blend Shape 空间中的正切矢量	float4
 export enum VertexBufferSemantic {
-  Positon = 'position',
-  Uv = 'uv',
-  Uv2 = 'uv2',
-  Normal = 'normal',
-  Tangent = 'tangent',
-  Color = 'color',
-  BoneIndices = 'boneIndices',
-  BoneWeights = 'boneWeights'
+  Positon = 'POSITION',
+  Uv = 'TEXCOORD0',
+  Uv2 = 'TEXCOORD1',
+  Normal = 'NORMAL',
+  Tangent = 'TANGENT',
+  Color = 'COLOR',
+  Joints = 'JOINTS',
+  Weights = 'WEIGHTS',
+  //
+  PositionBS0 = 'POSITION_BS0',
+  PositionBS1 = 'POSITION_BS1',
+  PositionBS2 = 'POSITION_BS2',
+  PositionBS3 = 'POSITION_BS3',
+  PositionBS4 = 'POSITION_BS4',
+  PositionBS5 = 'POSITION_BS5',
+  PositionBS6 = 'POSITION_BS6',
+  PositionBS7 = 'POSITION_BS7',
+  NormalBS0 = 'NORMAL_BS0',
+  NormalBS1 = 'NORMAL_BS1',
+  NormalBS2 = 'NORMAL_BS2',
+  NormalBS3 = 'NORMAL_BS3',
+  TangentBS0 = 'TANGENT_BS0',
+  TangentBS1 = 'TANGENT_BS1',
+  TangentBS2 = 'TANGENT_BS2',
+  TangentBS3 = 'TANGENT_BS3',
 }
 
 export interface ShaderData extends EffectsObjectData {

From f317961e16e5773dac0a9d24ffbd0e8613985b5b Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 14 May 2024 10:41:11 +0800
Subject: [PATCH 41/62] fix: fix name

---
 src/components.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components.ts b/src/components.ts
index 4698ed0..9abf0c7 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -169,7 +169,7 @@ export interface VertexChannel {
 // NORMAL_BS[n]	Blend Shape 空间中的法向矢量	float4
 // TANGENT_BS[n]	Blend Shape 空间中的正切矢量	float4
 export enum VertexBufferSemantic {
-  Positon = 'POSITION',
+  Position = 'POSITION',
   Uv = 'TEXCOORD0',
   Uv2 = 'TEXCOORD1',
   Normal = 'NORMAL',

From c1c3bf4aa17938ad1309a20902642a7f680cd4cc Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Wed, 15 May 2024 17:57:48 +0800
Subject: [PATCH 42/62] perf: perf subMesh

---
 src/animation-clip-data.ts | 10 +++++-----
 src/components.ts          |  3 ++-
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/src/animation-clip-data.ts b/src/animation-clip-data.ts
index 56bc0db..53153ed 100644
--- a/src/animation-clip-data.ts
+++ b/src/animation-clip-data.ts
@@ -9,23 +9,23 @@ export interface AnimationClipData extends EffectsObjectData {
 }
 
 export interface PositionCurveData {
-  path: string[],
+  path: string,
   keyFrames: FixedVec3Expression,
 }
 
 export interface EulerCurveData {
-  path: string[],
+  path: string,
   keyFrames: FixedVec3Expression,
 }
 
 export interface ScaleCurveData {
-  path: string[],
+  path: string,
   keyFrames: FixedVec3Expression,
 }
 
 export interface FloatCurveData {
-  path: string[],
-  property: string[],
+  path: string,
+  property: string,
   className: string,
   keyFrames: FixedNumberExpression,
 }
\ No newline at end of file
diff --git a/src/components.ts b/src/components.ts
index 9abf0c7..89e4e09 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -95,7 +95,8 @@ export interface GeometryData extends EffectsObjectData {
 
 interface SubMesh {
   offset: number,
-  count: number,
+  indexCount?: number,
+  vertexCount: number,
 }
 
 export enum GeometryType {

From cb21472aefce3b8cc0919250c74eff975c5f8132 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Tue, 21 May 2024 14:21:34 +0800
Subject: [PATCH 43/62] fix: update animation data (#55)

* fix: update animation data and support bezier quaternion curve

* fix: add new value type

* fix: update clip data

* fix: revert

* chore: rename

* chore: update import path
---
 src/animation-clip-data.ts |  8 ++++----
 src/components.ts          |  1 +
 src/item/model/tree.ts     | 13 +++++++++++++
 src/number-expression.ts   | 17 +++++++++++++++++
 4 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/src/animation-clip-data.ts b/src/animation-clip-data.ts
index 53153ed..ce0752b 100644
--- a/src/animation-clip-data.ts
+++ b/src/animation-clip-data.ts
@@ -1,9 +1,9 @@
 import type { EffectsObjectData } from './components';
-import type { FixedNumberExpression, FixedVec3Expression } from './number-expression';
+import type { FixedNumberExpression, FixedVec3Expression, FixedQuatExpression } from './number-expression';
 
 export interface AnimationClipData extends EffectsObjectData {
   positionCurves: PositionCurveData[],
-  eulerCurves: EulerCurveData[],
+  rotationCurves: RotationCurveData[],
   scaleCurves: ScaleCurveData[],
   floatCurves: FloatCurveData[],
 }
@@ -13,9 +13,9 @@ export interface PositionCurveData {
   keyFrames: FixedVec3Expression,
 }
 
-export interface EulerCurveData {
+export interface RotationCurveData {
   path: string,
-  keyFrames: FixedVec3Expression,
+  keyFrames: FixedQuatExpression,
 }
 
 export interface ScaleCurveData {
diff --git a/src/components.ts b/src/components.ts
index 89e4e09..597cf50 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -21,6 +21,7 @@ export enum DataType {
   CameraComponent = 'CameraComponent',
   ModelPluginComponent = 'ModelPluginComponent',
   TreeComponent = 'TreeComponent',
+  AnimationComponent = 'AnimationComponent',
 }
 
 export interface DataPath {
diff --git a/src/item/model/tree.ts b/src/item/model/tree.ts
index c948f20..756c31b 100644
--- a/src/item/model/tree.ts
+++ b/src/item/model/tree.ts
@@ -3,6 +3,7 @@ import type { ModelAnimationTrackDataPointer } from './binary';
 import type { BaseItem, BaseItemTransform } from '../base-item';
 import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
 import type { ComponentData, DataPath } from '../../components';
+import type { AnimationClipData } from '../../animation-clip-data';
 
 export interface TreeNodeOptions {
   name?: string,
@@ -95,3 +96,15 @@ export interface ModelAnimationComponentData extends ComponentData {
    */
   animations: ModelAnimationData[],
 }
+
+export interface AnimationComponentData extends ComponentData {
+  /**
+   * 默认动画索引,-1表示不播放动画
+   */
+  animation?: number,
+  /**
+   * glTF中所有的动画数据
+   */
+  animationClips: AnimationClipData[],
+}
+
diff --git a/src/number-expression.ts b/src/number-expression.ts
index 25660b8..2b6ef12 100644
--- a/src/number-expression.ts
+++ b/src/number-expression.ts
@@ -73,6 +73,11 @@ export enum ValueType {
    * 贝塞尔曲线路径
    */
   BEZIER_CURVE_PATH = 22,
+
+  /**
+   * 贝塞尔曲线四元数
+   */
+  BEZIER_CURVE_QUAT = 23,
 }
 
 export type vec2 = [x: number, y: number];
@@ -100,6 +105,8 @@ export type NumberExpression = FixedNumberExpression | RandomValue;
 
 export type FixedVec3Expression = ConstantVec3 | BezierPath | LinearPath | BezierCurvePath;
 
+export type FixedQuatExpression = BezierCurveQuat;
+
 /**
  * 常数数值
  * [0,5]
@@ -268,11 +275,21 @@ export type BezierValue = [type: ValueType.BEZIER_CURVE, value: BezierKeyframeVa
  */
 export type BezierCurvePathValue = [easing: BezierKeyframeValue[], points: vec3[], controlePoints: vec3[]];
 
+/**
+ * 贝塞尔曲线路径关键帧值
+ */
+export type BezierCurveQuatValue = [easing: BezierKeyframeValue[], points: vec4[], controlePoints: vec4[]];
+
 /**
  * 贝塞尔曲线路径关键帧
  */
 export type BezierCurvePath = [type: ValueType.BEZIER_CURVE_PATH, value: BezierCurvePathValue];
 
+/**
+ * 贝塞尔曲线路径关键帧
+ */
+export type BezierCurveQuat = [type: ValueType.BEZIER_CURVE_QUAT, value: BezierCurveQuatValue];
+
 /*********************************************/
 /*               颜色属性参数                 */
 /*********************************************/

From c9ad8f455df63953fe908f7891cb906b6c147533 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 21 May 2024 15:06:03 +0800
Subject: [PATCH 44/62] feat: add node item type

---
 src/type.ts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/src/type.ts b/src/type.ts
index 41fc9a2..0a77045 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -569,6 +569,10 @@ export enum ItemType {
    * 特效元素
    */
   effect = 'effect',
+  /**
+   * 节点元素
+   */
+  node = 'node',
 }
 
 /**

From cd1da6cfad15879504eb17c4507d97a58eb04f2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=A3=82=E5=85=AE?=
 <151803898+liuxi150@users.noreply.github.com>
Date: Tue, 21 May 2024 19:43:07 +0800
Subject: [PATCH 45/62] chore: export submesh (#58)

---
 src/components.ts | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/components.ts b/src/components.ts
index 597cf50..7d5e42e 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -94,7 +94,7 @@ export interface GeometryData extends EffectsObjectData {
   inverseBindMatrices?: number[],
 }
 
-interface SubMesh {
+export interface SubMesh {
   offset: number,
   indexCount?: number,
   vertexCount: number,

From 751fd32ad1390620275fd8a07b21822a23c1cec1 Mon Sep 17 00:00:00 2001
From: Sruimeng <934274351@qq.com>
Date: Wed, 22 May 2024 18:10:15 +0800
Subject: [PATCH 46/62] =?UTF-8?q?fix:=20=E8=B0=83=E6=95=B4=20animationClip?=
 =?UTF-8?q?s=20=E4=B8=BA=20DataPath=20=E5=BD=A2=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/item/model/tree.ts | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/item/model/tree.ts b/src/item/model/tree.ts
index 756c31b..4dd547e 100644
--- a/src/item/model/tree.ts
+++ b/src/item/model/tree.ts
@@ -3,7 +3,6 @@ import type { ModelAnimationTrackDataPointer } from './binary';
 import type { BaseItem, BaseItemTransform } from '../base-item';
 import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
 import type { ComponentData, DataPath } from '../../components';
-import type { AnimationClipData } from '../../animation-clip-data';
 
 export interface TreeNodeOptions {
   name?: string,
@@ -105,6 +104,6 @@ export interface AnimationComponentData extends ComponentData {
   /**
    * glTF中所有的动画数据
    */
-  animationClips: AnimationClipData[],
+  animationClips: DataPath[],
 }
 

From f08a8c6a6bf897aaf9e4078866d8aedd401b7dbf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Thu, 23 May 2024 13:57:31 +0800
Subject: [PATCH 47/62] feat: add timeline asset data def (#59)

* feat: add timeline asset data def

* perf: opt code
---
 src/components.ts                             |  7 +++
 src/composition.ts                            | 23 ++++++-
 src/index.ts                                  |  1 +
 src/item/null-item.ts                         | 62 +------------------
 src/timeline/index.ts                         |  5 ++
 .../sprite-color-playable-asset-data.ts       |  8 +++
 src/timeline/timeline-asset-data.ts           |  8 +++
 src/timeline/timeline-clip-data.ts            | 10 +++
 src/timeline/track/track-asset-data.ts        | 10 +++
 ...transform-animation-playable-asset-data.ts | 17 +++++
 10 files changed, 89 insertions(+), 62 deletions(-)
 create mode 100644 src/timeline/index.ts
 create mode 100644 src/timeline/sprite-color-playable-asset-data.ts
 create mode 100644 src/timeline/timeline-asset-data.ts
 create mode 100644 src/timeline/timeline-clip-data.ts
 create mode 100644 src/timeline/track/track-asset-data.ts
 create mode 100644 src/timeline/transform-animation-playable-asset-data.ts

diff --git a/src/components.ts b/src/components.ts
index 7d5e42e..ccdf1d2 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -13,6 +13,10 @@ export enum DataType {
   Texture = 'Texture',
   AnimationClip = 'AnimationClip',
   TextComponent = 'TextComponent',
+  TrackAsset = 'TrackAsset',
+  TimelineAsset = 'TimelineAsset',
+  TransformAnimationPlayableAsset = 'TransformAnimationPlayableAsset',
+  SpriteColorPlayableAsset = 'SpriteColorPlayableAsset',
 
   // FIXME: 先完成ECS的场景转换,后面移到spec中
   MeshComponent = 'MeshComponent',
@@ -22,6 +26,9 @@ export enum DataType {
   ModelPluginComponent = 'ModelPluginComponent',
   TreeComponent = 'TreeComponent',
   AnimationComponent = 'AnimationComponent',
+
+  // Non-EffectObject
+  TimelineClip = 'TimelineClip',
 }
 
 export interface DataPath {
diff --git a/src/composition.ts b/src/composition.ts
index 0212e82..c1022a7 100644
--- a/src/composition.ts
+++ b/src/composition.ts
@@ -1,4 +1,4 @@
-import type { Item } from './item';
+import type { DataPath } from './components';
 import {
   CAMERA_CLIP_MODE_NORMAL,
   CAMERA_CLIP_MODE_VERTICAL,
@@ -9,7 +9,7 @@ import {
   END_BEHAVIOR_PAUSE_AND_DESTROY,
   END_BEHAVIOR_RESTART,
 } from './constants';
-import type { DataPath } from './components';
+import type { Item } from './item';
 
 export enum CameraClipMode {
   /**
@@ -174,4 +174,23 @@ export interface CompositionData {
    * 降级图
    */
   fallbackImage?: string,
+  /**
+   * 时间轴资产(TimelineAssetData)
+   */
+  timelineAsset: DataPath,
+  /**
+   * 轨道的场景绑定
+   */
+  sceneBindings: SceneBindingData[],
+}
+
+export interface SceneBindingData {
+  /**
+   * 绑定的轨道资产(TrackAssetData)
+   */
+  key: DataPath,
+  /**
+   * 被绑定的场景对象(VFXItemData)
+   */
+  value: DataPath,
 }
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index 55d29e8..99c185e 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -25,3 +25,4 @@ export * from './text';
 export * from './components';
 export * from './vfx-item-data';
 export * from './buitin-object-guid';
+export * from './timeline';
diff --git a/src/item/null-item.ts b/src/item/null-item.ts
index 2285337..5b465ac 100644
--- a/src/item/null-item.ts
+++ b/src/item/null-item.ts
@@ -1,9 +1,6 @@
-import type {
-  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime, ItemType,
-} from '../type';
 import type { RGBAColorValue } from '../number-expression';
+import type { ColorOverLifetime, ItemType, PositionOverLifetime, RotationOverLifetime, SizeOverLifetime } from '../type';
 import type { BaseItem } from './base-item';
-import type { ComponentData, DataPath, EffectsObjectData } from '../components';
 /**
  * 空节点元素
  */
@@ -47,59 +44,4 @@ export interface NullContent {
    * 空节点元素色彩变化属性
    */
   colorOverLifetime?: ColorOverLifetime,
-}
-
-export interface TimelineComponentData extends ComponentData {
-  /**
-   * 轨道数据
-   */
-  tracks: TrackAssetData[],
-}
-
-export interface PlayableAssetData {
-  dataType: string,
-}
-
-export interface TrackAssetData extends PlayableAssetData {
-  clips: TimelineClipData[],
-}
-
-export interface TimelineClipData {
-  start: number,
-  duration: number,
-  clipAsset: DataPath, // PlayableData
-}
-
-export interface TransformAnimationPlayableAssetData extends PlayableAssetData {
-  animationClip: DataPath, // TransformAnimationClipData
-}
-
-export interface SpriteColorAnimationPlayableAssetData extends PlayableAssetData {
-  animationClip: DataPath, // SpriteColorAnimationClipData
-}
-
-export interface TransformAnimationClipData extends EffectsObjectData {
-  /**
-   * 空节点元素大小变化属性
-   */
-  sizeOverLifetime?: SizeOverLifetime,
-  /**
-   * 空节点元素旋转变化属性
-   */
-  rotationOverLifetime?: RotationOverLifetime,
-  /**
-   * 空节点元素位置变化属性
-   */
-  positionOverLifetime?: PositionOverLifetime,
-}
-
-export interface SpriteColorAnimationClipData extends EffectsObjectData {
-  /**
-   * 空节点元素色彩变化属性
-   */
-  colorOverLifetime?: ColorOverLifetime,
-  /**
-   * 图层初始颜色
-   */
-  startColor?: RGBAColorValue,
-}
+}
\ No newline at end of file
diff --git a/src/timeline/index.ts b/src/timeline/index.ts
new file mode 100644
index 0000000..c9fbd96
--- /dev/null
+++ b/src/timeline/index.ts
@@ -0,0 +1,5 @@
+export * from './track/track-asset-data';
+export * from './sprite-color-playable-asset-data';
+export * from './timeline-asset-data';
+export * from './timeline-clip-data';
+export * from './transform-animation-playable-asset-data';
\ No newline at end of file
diff --git a/src/timeline/sprite-color-playable-asset-data.ts b/src/timeline/sprite-color-playable-asset-data.ts
new file mode 100644
index 0000000..9154eb3
--- /dev/null
+++ b/src/timeline/sprite-color-playable-asset-data.ts
@@ -0,0 +1,8 @@
+import type { EffectsObjectData } from '../components';
+import type { RGBAColorValue } from '../number-expression';
+import type { ColorOverLifetime } from '../type';
+
+export interface SpriteColorPlayableAssetData extends EffectsObjectData {
+  colorOverLifetime?: ColorOverLifetime,
+  startColor?: RGBAColorValue,
+}
\ No newline at end of file
diff --git a/src/timeline/timeline-asset-data.ts b/src/timeline/timeline-asset-data.ts
new file mode 100644
index 0000000..71439a7
--- /dev/null
+++ b/src/timeline/timeline-asset-data.ts
@@ -0,0 +1,8 @@
+import type { EffectsObjectData, DataPath } from '../components';
+
+export interface TimelineAssetData extends EffectsObjectData {
+  /**
+   * 轨道数据(TrackAssetData)
+   */
+  tracks: DataPath[],
+}
\ No newline at end of file
diff --git a/src/timeline/timeline-clip-data.ts b/src/timeline/timeline-clip-data.ts
new file mode 100644
index 0000000..a8606b1
--- /dev/null
+++ b/src/timeline/timeline-clip-data.ts
@@ -0,0 +1,10 @@
+import type { DataPath } from '../components';
+
+export interface TimelineClipData {
+  start?: number,
+  duration?: number,
+  /**
+     * 可播放资产(PlayableAssetData)
+     */
+  asset: DataPath,
+}
\ No newline at end of file
diff --git a/src/timeline/track/track-asset-data.ts b/src/timeline/track/track-asset-data.ts
new file mode 100644
index 0000000..bc8d789
--- /dev/null
+++ b/src/timeline/track/track-asset-data.ts
@@ -0,0 +1,10 @@
+import type { DataPath, EffectsObjectData } from '../../components';
+import type { TimelineClipData } from '../timeline-clip-data';
+
+export interface TrackAssetData extends EffectsObjectData {
+  /**
+   * 子轨道数据(TrackAssetData)
+   */
+  children: DataPath[],
+  clips: TimelineClipData,
+}
\ No newline at end of file
diff --git a/src/timeline/transform-animation-playable-asset-data.ts b/src/timeline/transform-animation-playable-asset-data.ts
new file mode 100644
index 0000000..f3c3f23
--- /dev/null
+++ b/src/timeline/transform-animation-playable-asset-data.ts
@@ -0,0 +1,17 @@
+import type { EffectsObjectData } from '../components';
+import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime } from '../type';
+
+export interface TransformAnimationPlayableAssetData extends EffectsObjectData {
+  /**
+   * 元素大小变化属性
+   */
+  sizeOverLifetime?: SizeOverLifetime,
+  /**
+   * 元素旋转变化属性
+   */
+  rotationOverLifetime?: RotationOverLifetime,
+  /**
+   * 元素位置变化属性
+   */
+  positionOverLifetime?: PositionOverLifetime,
+}
\ No newline at end of file

From 636b514d37d731ed497e8c5ad1b13190e3122ef0 Mon Sep 17 00:00:00 2001
From: liuxi150 <liuxi150@hotmail.com>
Date: Thu, 23 May 2024 16:40:42 +0800
Subject: [PATCH 48/62] fix: add animations into scene

---
 src/scene.ts | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/src/scene.ts b/src/scene.ts
index da75a06..abdfa19 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -6,6 +6,7 @@ import type { FontBase, FontDefine } from './text';
 import type { BinaryFile } from './binary';
 import type { ComponentData, GeometryData, MaterialData, ShaderData } from './components';
 import type { VFXItemData } from './vfx-item-data';
+import type { AnimationClipData } from './animation-clip-data';
 
 /**
  * runtime 2.0 之前的场景信息
@@ -191,4 +192,8 @@ export interface JSONScene {
    * 几何体数据
    */
   geometries: GeometryData[],
+  /**
+   * 动画数据
+   */
+  animations: AnimationClipData[],
 }

From c32cbe9e95816923027d40cb3ca067a2920ded3b Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 28 May 2024 11:29:40 +0800
Subject: [PATCH 49/62] perf: opt format type

---
 src/components.ts | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/src/components.ts b/src/components.ts
index 597cf50..1cd8bf6 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -74,7 +74,7 @@ export interface MaterialData extends EffectsObjectData {
 
 export interface GeometryData extends EffectsObjectData {
   vertexData: VertexData,
-  indexFormat: number,
+  indexFormat: IndexFormatType,
   indexOffset: number,
   subMeshes: SubMesh[],
   /**
@@ -137,14 +137,19 @@ export interface VertexData {
 }
 
 export enum VertexFormatType {
+  Float16,
   Float32,
-  Int16,
   Int8,
-  UInt16,
+  Int16,
+  Int32,
   UInt8,
+  UInt16,
+  UInt32,
 }
 
 export enum IndexFormatType {
+  None = -1,
+  UInt8,
   UInt16,
   UInt32,
 }

From af48e629df2aad71f5783e78d9448cfd2d4da107 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 28 May 2024 15:28:13 +0800
Subject: [PATCH 50/62] perf: rename

---
 src/components.ts                                               | 2 +-
 src/timeline/index.ts                                           | 2 +-
 ...-playable-asset-data.ts => transform-playable-asset-data.ts} | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)
 rename src/timeline/{transform-animation-playable-asset-data.ts => transform-playable-asset-data.ts} (83%)

diff --git a/src/components.ts b/src/components.ts
index 63dc6a6..2df2aa2 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -15,7 +15,7 @@ export enum DataType {
   TextComponent = 'TextComponent',
   TrackAsset = 'TrackAsset',
   TimelineAsset = 'TimelineAsset',
-  TransformAnimationPlayableAsset = 'TransformAnimationPlayableAsset',
+  TransformPlayableAsset = 'TransformPlayableAsset',
   SpriteColorPlayableAsset = 'SpriteColorPlayableAsset',
 
   // FIXME: 先完成ECS的场景转换,后面移到spec中
diff --git a/src/timeline/index.ts b/src/timeline/index.ts
index c9fbd96..ca1682d 100644
--- a/src/timeline/index.ts
+++ b/src/timeline/index.ts
@@ -2,4 +2,4 @@ export * from './track/track-asset-data';
 export * from './sprite-color-playable-asset-data';
 export * from './timeline-asset-data';
 export * from './timeline-clip-data';
-export * from './transform-animation-playable-asset-data';
\ No newline at end of file
+export * from './transform-playable-asset-data';
\ No newline at end of file
diff --git a/src/timeline/transform-animation-playable-asset-data.ts b/src/timeline/transform-playable-asset-data.ts
similarity index 83%
rename from src/timeline/transform-animation-playable-asset-data.ts
rename to src/timeline/transform-playable-asset-data.ts
index f3c3f23..eee2a7a 100644
--- a/src/timeline/transform-animation-playable-asset-data.ts
+++ b/src/timeline/transform-playable-asset-data.ts
@@ -1,7 +1,7 @@
 import type { EffectsObjectData } from '../components';
 import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime } from '../type';
 
-export interface TransformAnimationPlayableAssetData extends EffectsObjectData {
+export interface TransformPlayableAssetData extends EffectsObjectData {
   /**
    * 元素大小变化属性
    */

From c8218cfdbe0d6261da616f34e9a50f39de91eb8f Mon Sep 17 00:00:00 2001
From: Sruimeng <934274351@qq.com>
Date: Tue, 4 Jun 2024 10:30:22 +0800
Subject: [PATCH 51/62] feat: skybox rotation

---
 src/item/model/skybox.ts | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/src/item/model/skybox.ts b/src/item/model/skybox.ts
index c1fb06d..d384d57 100644
--- a/src/item/model/skybox.ts
+++ b/src/item/model/skybox.ts
@@ -2,9 +2,15 @@ import type { BaseItem, ItemEndBehavior } from '../base-item';
 import type { BinaryEnv } from '../../binary';
 import type { SkyboxCubeTexturePointer } from './binary';
 import type { ItemType } from '../../type';
-import type { ComponentData, DataPath } from '../../components';
+import type { ComponentData, DataPath, Vector4Data } from '../../components';
 
 export interface SkyboxOptions<T extends BinaryEnv> {
+  /**
+   * 环境光旋转
+   * UI显示"环境光旋转"
+   * @default { x: 0, y: 0, z: 0, w: 0 }
+   */
+  rotation: Vector4Data,
   // Skybox 是否渲染,UI显示"可见"
   renderable: boolean,
   // Diffuse 强度,UI显示"环境光强度"

From 6a2f9c7366255fb26121893369396915ffa1a279 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Thu, 6 Jun 2024 15:15:36 +0800
Subject: [PATCH 52/62] fix: fix composition type (#68)

* fix: fix json scene composition field type

* chore: composition base interface

---------

Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 src/composition.ts | 56 +++++++++-------------------------------------
 src/scene.ts       |  4 ++--
 2 files changed, 13 insertions(+), 47 deletions(-)

diff --git a/src/composition.ts b/src/composition.ts
index c1022a7..2f9cc37 100644
--- a/src/composition.ts
+++ b/src/composition.ts
@@ -84,10 +84,7 @@ export enum CompositionEndBehavior {
   freeze = END_BEHAVIOR_FREEZE,
 }
 
-/**
- * 合成信息
- */
-export interface Composition {
+interface CompositionBase {
   /**
    * 合成ID
    */
@@ -100,7 +97,6 @@ export interface Composition {
    * 合成持续时间
    */
   duration: number,
-
   /**
    * 合成开始播放的时间,单位妙
    * @default 0
@@ -114,10 +110,6 @@ export interface Composition {
    * 合成相机信息
    */
   camera: CameraOptions,
-  /**
-   * 元素信息
-   */
-  items: Item[],
   /**
    * 合成视窗预览大小
    * 如果没有提供,默认为 player 的 container 大小
@@ -131,49 +123,23 @@ export interface Composition {
 }
 
 /**
- * 合成数据
+ * 合成信息
  */
-export interface CompositionData {
+export interface Composition extends CompositionBase {
   /**
-   * 合成ID
-   */
-  id: string,
-  /**
-   * 合成名称
-   */
-  name: string,
-  /**
-   * 合成持续时间
+   * 元素信息
    */
-  duration: number,
+  items: Item[],
+}
 
-  /**
-   * 合成开始播放的时间,单位妙
-   * @default 0
-   */
-  startTime?: number,
-  /**
-   * 合成结束行为
-   */
-  endBehavior: CompositionEndBehavior,
-  /**
-   * 合成相机信息
-   */
-  camera: CameraOptions,
+/**
+ * 合成数据
+ */
+export interface CompositionData extends CompositionBase {
   /**
    * 元素信息
    */
   items: DataPath[],
-  /**
-   * 合成视窗预览大小
-   * 如果没有提供,默认为 player 的 container 大小
-   * @default [0,0]
-   */
-  previewSize?: [width: number, height: number],
-  /**
-   * 降级图
-   */
-  fallbackImage?: string,
   /**
    * 时间轴资产(TimelineAssetData)
    */
@@ -193,4 +159,4 @@ export interface SceneBindingData {
    * 被绑定的场景对象(VFXItemData)
    */
   value: DataPath,
-}
\ No newline at end of file
+}
diff --git a/src/scene.ts b/src/scene.ts
index abdfa19..be60ec2 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -1,4 +1,4 @@
-import type { Composition } from './composition';
+import type { Composition, CompositionData } from './composition';
 import type { SpineResource } from './item/spine-item';
 import type { PlayerVersion, Shape } from './type';
 import type { TemplateImage, Image, CompressedImage, TextureDefine } from './image';
@@ -129,7 +129,7 @@ export interface JSONScene {
   /**
    * 渲染所需合成列表
    */
-  compositions: Composition[],
+  compositions: CompositionData[],
   /******************************** 以下皆为可复用信息,加载在对应 Manager 中 *******************************/
   /**
    * 贴图信息

From 67a1d0d4221129919ca9ecb1b05b6f43ffcc54ea Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Thu, 6 Jun 2024 16:00:54 +0800
Subject: [PATCH 53/62] =?UTF-8?q?chore:=20=E7=A7=BB=E9=99=A4=E5=BA=9F?=
 =?UTF-8?q?=E5=BC=83=E7=9A=84=20Text=20=E7=B1=BB=E5=9E=8B=EF=BC=8C?=
 =?UTF-8?q?=E8=A7=84=E8=8C=83=E6=B3=A8=E9=87=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/image.ts                           | 11 +++---
 src/item.ts                            |  5 +--
 src/item/camera-item.ts                |  6 +--
 src/item/composition-item.ts           |  4 +-
 src/item/interact-item.ts              |  2 +-
 src/item/null-item.ts                  |  4 +-
 src/item/particle-item.ts              | 36 ++++++++---------
 src/item/plugin-item.ts                |  2 +-
 src/item/spine-item.ts                 |  2 +-
 src/item/sprite-item.ts                |  4 +-
 src/item/text-item.ts                  | 12 ++----
 src/number-expression.ts               | 19 +++++----
 src/scene.ts                           |  9 ++---
 src/text.ts                            | 54 +-------------------------
 src/timeline/timeline-clip-data.ts     |  6 +--
 src/timeline/track/track-asset-data.ts |  2 +-
 src/type.ts                            | 23 ++++++-----
 src/vfx-item-data.ts                   | 11 +++---
 18 files changed, 75 insertions(+), 137 deletions(-)

diff --git a/src/image.ts b/src/image.ts
index d6a8ac8..575fc01 100644
--- a/src/image.ts
+++ b/src/image.ts
@@ -90,8 +90,8 @@ export interface Image {
    */
   url: string,
   /**
-   * webp 地址
-   * 如果运行时支持 webp,则尽量使用 webp
+   * WebP 地址
+   * 如果运行时支持 WebP,则优先使用 WebP
    */
   webp?: string,
   /**
@@ -106,8 +106,8 @@ export interface Image {
    */
   mipmap?: boolean,
   /**
-   * 图片Y轴的方向,如果Y轴向上(与OpenGL相同)则为 1
-   * 如果Y轴向下(与OpenGL相反)则为 -1 ,图片再绘制数据模板的时候需要翻转绘制
+   * 图片 Y 轴的方向,如果 Y 轴向上(与 OpenGL 相同)则为 1
+   * 如果 Y 轴向下(与 OpenGL 相反)则为 -1,图片再绘制数据模板的时候需要翻转绘制
    * @default 1
    */
   oriY?: 1 | -1,
@@ -128,7 +128,8 @@ export interface CompressedImage extends Image {
    * 压缩贴图地址
    */
   compressed: {
-    astc?: string, // 安卓
+    // 安卓
+    astc?: string,
     pvrtc?: string,
   },
 }
diff --git a/src/item.ts b/src/item.ts
index c5cf4c0..50282e7 100644
--- a/src/item.ts
+++ b/src/item.ts
@@ -8,10 +8,9 @@ import type { ModelCameraItem, ModelLightItem, ModelMeshItem, ModelSkyboxItem, M
 import type { CameraItem } from './item/camera-item';
 import type { CompositionItem } from './item/composition-item';
 import type { TextItem } from './item/text-item';
+
 /**
- * Item Interface,
- * 1.0版本
- * 基类,无对应元素
+ * Item 基类,无对应元素
  */
 export type Item =
   | SpriteItem
diff --git a/src/item/camera-item.ts b/src/item/camera-item.ts
index ec9e4bc..2942caf 100644
--- a/src/item/camera-item.ts
+++ b/src/item/camera-item.ts
@@ -55,15 +55,15 @@ export interface CameraContent {
 
 export interface CameraPositionOverLifetime {
   /**
-   * x轴位置变化信息
+   * x 轴位置变化信息
    */
   linearX?: FixedNumberExpression,
   /**
-   * y轴位置变化信息
+   * y 轴位置变化信息
    */
   linearY?: FixedNumberExpression,
   /**
-   * z轴位置变化信息
+   * z 轴位置变化信息
    */
   linearZ?: FixedNumberExpression,
   /**
diff --git a/src/item/composition-item.ts b/src/item/composition-item.ts
index 5773e82..ba5b756 100644
--- a/src/item/composition-item.ts
+++ b/src/item/composition-item.ts
@@ -10,7 +10,7 @@ import type { PositionOverLifetime } from '../type';
  */
 export interface CompositionItem extends BaseItem {
   /**
-   * 元素类型[指定为composition]
+   * 元素类型(指定为 composition)
    */
   type: ItemType.composition,
   /**
@@ -29,7 +29,7 @@ export interface CompositionContent {
    */
   options: {
     /**
-     * 引用的合成id
+     * 引用的合成 ID
      */
     refId: string,
     /**
diff --git a/src/item/interact-item.ts b/src/item/interact-item.ts
index 17542eb..b6325c3 100644
--- a/src/item/interact-item.ts
+++ b/src/item/interact-item.ts
@@ -8,7 +8,7 @@ import type { ComponentData } from '../components';
  */
 export interface InteractItem extends BaseItem {
   /**
-   * 元素类型[指定为interact]
+   * 元素类型(指定为 interact)
    */
   type: ItemType.interact,
   /**
diff --git a/src/item/null-item.ts b/src/item/null-item.ts
index 5b465ac..e435828 100644
--- a/src/item/null-item.ts
+++ b/src/item/null-item.ts
@@ -6,7 +6,7 @@ import type { BaseItem } from './base-item';
  */
 export interface NullItem extends BaseItem {
   /**
-   * 元素类型[指定为null]
+   * 元素类型(指定为 null)
    */
   type: ItemType.null,
   /**
@@ -44,4 +44,4 @@ export interface NullContent {
    * 空节点元素色彩变化属性
    */
   colorOverLifetime?: ColorOverLifetime,
-}
\ No newline at end of file
+}
diff --git a/src/item/particle-item.ts b/src/item/particle-item.ts
index 7a24c2c..f134a01 100644
--- a/src/item/particle-item.ts
+++ b/src/item/particle-item.ts
@@ -28,7 +28,7 @@ export enum ParticleInteractionBehavior {
  */
 export interface ParticleItem extends BaseItem {
   /**
-   * 元素类型[指定为particle]
+   * 元素类型(指定为 particle)
    */
   type: ItemType.particle,
   /**
@@ -65,7 +65,7 @@ export interface ParticleEmission {
      */
     cycles?: number,
     /**
-     * 爆发时间间隔,单位秒
+     * 爆发时间间隔(单位:秒)
      * @default 0
      */
     interval?: number,
@@ -79,15 +79,15 @@ export interface ParticleEmission {
      */
     index: number,
     /**
-     * x方向偏移值
+     * x 方向偏移值
      */
     x: number,
     /**
-     * y方向偏移值
+     * y 方向偏移值
      */
     y: number,
     /**
-     * z方向偏移值
+     * z 方向偏移值
      */
     z: number,
   }[],
@@ -99,15 +99,15 @@ export interface ParticlePositionOverLifetime {
    */
   asMovement?: boolean,
   /**
-   * x轴位置变化信息
+   * x 轴位置变化信息
    */
   linearX?: NumberExpression,
   /**
-   * y轴位置变化信息
+   * y 轴位置变化信息
    */
   linearY?: NumberExpression,
   /**
-   * z轴位置变化信息
+   * z 轴位置变化信息
    */
   linearZ?: NumberExpression,
   /**
@@ -115,15 +115,15 @@ export interface ParticlePositionOverLifetime {
    */
   asRotation?: boolean,
   /**
-   * x轴环绕角度变化信息
+   * x 轴环绕角度变化信息
    */
   orbitalX?: NumberExpression,
   /**
-   * y轴环绕角度变化信息
+   * y 轴环绕角度变化信息
    */
   orbitalY?: NumberExpression,
   /**
-   * z轴环绕角度变化信息
+   * z 轴环绕角度变化信息
    */
   orbitalZ?: NumberExpression,
   /**
@@ -146,7 +146,7 @@ export interface ParticlePositionOverLifetime {
    */
   forceCurve?: FunctionExpression,
   /**
-   * 增加一个初速度,匀速直线运动,direction为运动方向
+   * 增加一个初速度,匀速直线运动,direction 为运动方向
    * @default 0
    */
   startSpeed?: NumberExpression,
@@ -155,7 +155,7 @@ export interface ParticlePositionOverLifetime {
    */
   speedOverLifetime?: FixedNumberExpression,
   /**
-   * 增加一个重力,gravity为重力方向,gravityModifier为重力大小
+   * 增加一个重力,gravity 为重力方向,gravityModifier 为重力大小
    * @default 0
    */
   gravity?: vec3,
@@ -175,15 +175,15 @@ export interface ParticleRotationOverLifetime {
    */
   asRotation?: boolean,
   /**
-   * x轴旋转函数
+   * x 轴旋转函数
    */
   x?: NumberExpression,
   /**
-   * y轴旋转函数
+   * y 轴旋转函数
    */
   y?: NumberExpression,
   /**
-   * z轴旋转函数(不分轴时,变化z)
+   * z 轴旋转函数(不分轴时,变化 z)
    */
   z?: NumberExpression,
 }
@@ -198,11 +198,11 @@ export interface ParticleSizeOverLifetime {
    */
   size?: NumberExpression,
   /**
-   * x轴大小变化信息(分轴模式)
+   * x 轴大小变化信息(分轴模式)
    */
   x?: NumberExpression,
   /**
-   * y轴大小变化信息(分轴模式)
+   * y 轴大小变化信息(分轴模式)
    */
   y?: NumberExpression,
 }
diff --git a/src/item/plugin-item.ts b/src/item/plugin-item.ts
index 7d401c1..46bd60f 100644
--- a/src/item/plugin-item.ts
+++ b/src/item/plugin-item.ts
@@ -6,7 +6,7 @@ import type { BaseItem, ItemEndBehavior } from './base-item';
  */
 export interface PluginItem extends BaseItem {
   /**
-   * 元素类型[指定为plugin]
+   * 元素类型(指定为 plugin)
    */
   type: ItemType.plugin,
   /**
diff --git a/src/item/spine-item.ts b/src/item/spine-item.ts
index 84cd83b..08ac868 100644
--- a/src/item/spine-item.ts
+++ b/src/item/spine-item.ts
@@ -63,7 +63,7 @@ export interface PluginSpineOption {
 	 */
   activeSkin: string,
   /**
-	 * 当前使用的动画列表,1.5之前为 string
+	 * 当前使用的动画列表,1.5 之前为 string
 	 */
   activeAnimation: string[] | string,
   /**
diff --git a/src/item/sprite-item.ts b/src/item/sprite-item.ts
index 6c799d1..1bf18ee 100644
--- a/src/item/sprite-item.ts
+++ b/src/item/sprite-item.ts
@@ -18,7 +18,7 @@ import type { ComponentData } from '../components';
  */
 export interface SpriteItem extends BaseItem {
   /**
-   * 元素类型[指定为sprite]
+   * 元素类型(指定为 sprite)
    */
   type: ItemType.sprite,
   /**
@@ -35,7 +35,7 @@ export interface SpriteContentOptions {
    */
   startColor?: RGBAColorValue,
   /**
-   * FIXME 元素渲染延时
+   * FIXME: 元素渲染延时
    */
 }
 
diff --git a/src/item/text-item.ts b/src/item/text-item.ts
index eb44d2e..42e72d9 100644
--- a/src/item/text-item.ts
+++ b/src/item/text-item.ts
@@ -1,13 +1,7 @@
 import type { BaseItem, ItemEndBehavior } from './base-item';
 import type {
-  SizeOverLifetime,
-  RotationOverLifetime,
-  PositionOverLifetime,
-  ColorOverLifetime,
-  ItemType,
-  TextureSheetAnimation,
-  RendererOptions,
-  InteractBehavior,
+  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime,
+  ItemType, TextureSheetAnimation, RendererOptions, InteractBehavior,
 } from '../type';
 import type { RGBAColorValue } from '../number-expression';
 import type { FontStyle, TextAlignment, TextBaseline, TextOverflow, TextWeight } from '../text';
@@ -18,7 +12,7 @@ import type { ComponentData } from '../components';
  */
 export interface TextItem extends BaseItem {
   /**
-   * 元素类型[指定为text]
+   * 元素类型(指定为 text)
    */
   type: ItemType.text,
   /**
diff --git a/src/number-expression.ts b/src/number-expression.ts
index 2b6ef12..57a3d3c 100644
--- a/src/number-expression.ts
+++ b/src/number-expression.ts
@@ -52,7 +52,7 @@ export enum ValueType {
    */
   SHAPE_SPLITS = 11,
   /**
-   *直线路径
+   * 直线路径
    */
   LINEAR_PATH = 12,
   /**
@@ -63,17 +63,14 @@ export enum ValueType {
    * 二进制指针
    */
   BINARY = 20,
-
   /**
    * 贝塞尔曲线
    */
   BEZIER_CURVE = 21,
-
   /**
    * 贝塞尔曲线路径
    */
   BEZIER_CURVE_PATH = 22,
-
   /**
    * 贝塞尔曲线四元数
    */
@@ -93,18 +90,17 @@ export type mat4 = [
   m11: number, m12: number, m13: number, m14: number,
   m21: number, m22: number, m23: number, m24: number,
   m31: number, m32: number, m33: number, m34: number,
-  m41: number, m42: number, m43: number, m44: number
+  m41: number, m42: number, m43: number, m44: number,
 ];
 
 /*********************************************/
-/*               数值属性参数                 */
+/*               数值属性参数                  */
 /*********************************************/
+
 export type FunctionExpression = LineValue | CurveValue | BezierValue;
 export type FixedNumberExpression = ConstantNumber | LineValue | CurveValue | BezierValue;
 export type NumberExpression = FixedNumberExpression | RandomValue;
-
 export type FixedVec3Expression = ConstantVec3 | BezierPath | LinearPath | BezierCurvePath;
-
 export type FixedQuatExpression = BezierCurveQuat;
 
 /**
@@ -132,6 +128,7 @@ export type RandomValue = [type: ValueType.RANDOM, value: [min: number, max: num
 export type LineValue = [type: ValueType.LINE, value: [time: number, value: number][]];
 
 export type CurveEasingPoint = [time: number, value: number, tanIn: number, tanOut: number];
+
 /**
  * 曲线段数值
  */
@@ -253,7 +250,8 @@ export type HoldKeyframeValue =
   | EaseHoldInKeyframeValue
   | LineHoldOutKeyframeValue
   | LineHoldInKeyframeValue
-  | HoldInOutKeyframeValue;
+  | HoldInOutKeyframeValue
+  ;
 
 /**
  * 贝塞尔关键帧值
@@ -263,7 +261,8 @@ export type BezierKeyframeValue =
   | EaseInKeyframeValue
   | EaseOutKeyframeValue
   | LineKeyframeValue
-  | HoldKeyframeValue;
+  | HoldKeyframeValue
+  ;
 
 /**
  * 贝塞尔关键帧
diff --git a/src/scene.ts b/src/scene.ts
index be60ec2..57d13fb 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -122,7 +122,7 @@ export interface JSONScene {
   type: string,
   /*************************************** 用于加载 json 后复原合成 **************************************/
   /**
-   * 选中合成ID
+   * 选中合成 ID
    * 如果没有设置,选择合成中的第一个
    */
   compositionId?: string,
@@ -136,11 +136,11 @@ export interface JSONScene {
    */
   images: (TemplateImage | Image | CompressedImage)[],
   /**
-   * 根据合成ID,每个合成用到的 image 的数组索引
+   * 根据合成 ID,每个合成用到的 image 的数组索引
    */
   imgUsage?: Record<string, number[]>,
   /**
-   * 根据合成id,每个合成用到的 bin 的数组索引
+   * 根据合成 ID,每个合成用到的 bin 的数组索引
    */
   binUsage?: Record<string, number[]>,
   /**
@@ -159,17 +159,14 @@ export interface JSONScene {
   fonts?: FontBase[] | FontDefine[],
   /**
    * spine 资源
-   * @version 1.5
    */
   spines?: SpineResource[],
   /**
    * 二进制文件地址
-   * @version 1.3
    */
   bins?: BinaryFile[],
   /**
    * textures 配置
-   * 从 v1.3 开始,images 数组会对应创建 textures 数组
    */
   textures?: TextureDefine[],
   /**
diff --git a/src/text.ts b/src/text.ts
index 35c2447..0413036 100644
--- a/src/text.ts
+++ b/src/text.ts
@@ -53,56 +53,6 @@ export interface FontBase {
   letterSpace?: number,
 }
 
-export interface Text {
-  x: number,
-  y: number,
-  /**
-   * 变量名
-   */
-  n?: string,
-  /**
-   * content,
-   * 文字内容,如果包含 $var$ 样式,内容将被替换
-   */
-  t: string,
-  /**
-   * width, if not provide use canvas.measureText() to get width
-   * 文字最大宽度,如果不设置,由系统进行计算
-   */
-  w?: number,
-  /**
-   * font, index to fonts array
-   * 字体,指向字体数组
-   * @default 0
-   */
-  f?: number,
-  /**
-   * textAlignment
-   * 字体排列
-   * @default 0
-   */
-  a?: TextAlignment,
-  /**
-   * index to color array
-   * 字体颜色,指向数组
-   */
-  c?: number,
-
-  /**
-   * 当文字超过最大宽度时,文字的表现行为
-   * 仅当设置文字最大宽度后生效
-   * @default 0
-   */
-  of?: TextOverflow,
-
-  /**
-   * 当文字overflow为ellipsis时的替换符号
-   * @default ".."
-   */
-  et?: string,
-
-}
-
 export enum TextOverflow {
   /**
    * display 模式下,会显示所有文本,存在文本超过边界框的情况。
@@ -136,7 +86,7 @@ export enum TextBaseline {
 export enum TextAlignment {
   /**
    * text alignment starts from(x,y) to right direction
-   * 从(x,y)开始第一个字符,向右边延伸
+   * 从 (x,y) 开始第一个字符,向右边延伸
    */
   left = 0,
   /**
@@ -146,7 +96,7 @@ export enum TextAlignment {
   middle = 1,
   /**
    * text alignment ends with(x,y) from left direction
-   * 从(x,y)结束最后一个字符,向左边延伸
+   * 从 (x,y) 结束最后一个字符,向左边延伸
    */
   right = 2,
 }
diff --git a/src/timeline/timeline-clip-data.ts b/src/timeline/timeline-clip-data.ts
index a8606b1..97ebd4a 100644
--- a/src/timeline/timeline-clip-data.ts
+++ b/src/timeline/timeline-clip-data.ts
@@ -4,7 +4,7 @@ export interface TimelineClipData {
   start?: number,
   duration?: number,
   /**
-     * 可播放资产(PlayableAssetData)
-     */
+   * 可播放资产(PlayableAssetData)
+   */
   asset: DataPath,
-}
\ No newline at end of file
+}
diff --git a/src/timeline/track/track-asset-data.ts b/src/timeline/track/track-asset-data.ts
index bc8d789..bd8afc5 100644
--- a/src/timeline/track/track-asset-data.ts
+++ b/src/timeline/track/track-asset-data.ts
@@ -7,4 +7,4 @@ export interface TrackAssetData extends EffectsObjectData {
    */
   children: DataPath[],
   clips: TimelineClipData,
-}
\ No newline at end of file
+}
diff --git a/src/type.ts b/src/type.ts
index 0a77045..a73277b 100644
--- a/src/type.ts
+++ b/src/type.ts
@@ -7,11 +7,11 @@ import type {
  */
 export interface PlayerVersion {
   /**
-   * Web端版本号
+   * Web 端版本号
    */
   web: string,
   /**
-   * Native端版本号
+   * Native 端版本号
    */
   native: string,
 }
@@ -83,15 +83,15 @@ export interface SizeOverLifetime {
    */
   size?: FixedNumberExpression,
   /**
-   * x轴大小变化信息(分轴模式)
+   * x 轴大小变化信息(分轴模式)
    */
   x?: FixedNumberExpression,
   /**
-   * y轴大小变化信息(分轴模式)
+   * y 轴大小变化信息(分轴模式)
    */
   y?: FixedNumberExpression,
   /**
-   * z轴大小变化信息(分轴模式)
+   * z 轴大小变化信息(分轴模式)
    */
   z?: FixedNumberExpression,
 }
@@ -131,15 +131,15 @@ export interface PositionOverLifetime {
    */
   asMovement?: boolean,
   /**
-   * x轴位置变化信息
+   * x 轴位置变化信息
    */
   linearX?: FixedNumberExpression,
   /**
-   * y轴位置变化信息
+   * y 轴位置变化信息
    */
   linearY?: FixedNumberExpression,
   /**
-   * z轴位置变化信息
+   * z 轴位置变化信息
    */
   linearZ?: FixedNumberExpression,
   /**
@@ -147,15 +147,15 @@ export interface PositionOverLifetime {
    */
   asRotation?: boolean,
   /**
-   * x轴环绕角度变化信息
+   * x 轴环绕角度变化信息
    */
   orbitalX?: FixedNumberExpression,
   /**
-   * y轴环绕角度变化信息
+   * y 轴环绕角度变化信息
    */
   orbitalY?: FixedNumberExpression,
   /**
-   * z轴环绕角度变化信息
+   * z 轴环绕角度变化信息
    */
   orbitalZ?: FixedNumberExpression,
   /**
@@ -448,7 +448,6 @@ export enum InteractBehavior {
    * 清除元素
    */
   REMOVE,
-
   /**
    * 暂停播放器
    */
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index 74ffc7f..cc8227b 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -4,9 +4,9 @@ import type { ItemType, RenderLevel } from './type';
 
 export interface VFXItemData extends EffectsObjectData {
   /**
-   * 元素 id
-   * 非预合成的元素 id 为 int 类型的数字字符串
-   * 预合成元素 id 为 `'{ref元素id}+{合成内id}'` 字符串
+   * 元素 ID
+   * 非预合成的元素 ID 为 int 类型的数字字符串
+   * 预合成元素 ID 为 `'{ref 元素 ID}+{合成内 ID}'` 字符串
    */
   id: string,
   /**
@@ -18,14 +18,13 @@ export interface VFXItemData extends EffectsObjectData {
    */
   duration: number,
   /**
-   * 元素类型,string 类型
+   * 元素类型,String 类型
    * Galacean Effects 内部元素使用 int 数字字符串
    * plugin 模块实现者自由实现命名
-   * 2022.12更新: spine: "spine", 陀螺仪: "5"
    */
   type: ItemType,
   /**
-   * 父节点ID
+   * 父节点 ID
    * 如果父节点无法找到,播放将直接报错
    */
   parentId?: string,

From e198820d0633b77d8d2526939372b58530d4f874 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Wed, 12 Jun 2024 15:03:59 +0800
Subject: [PATCH 54/62] feat: add miscs (#70)

* feat: add miscs

* perf: opt code
---
 src/scene.ts | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/scene.ts b/src/scene.ts
index 57d13fb..eeb8452 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -4,7 +4,7 @@ import type { PlayerVersion, Shape } from './type';
 import type { TemplateImage, Image, CompressedImage, TextureDefine } from './image';
 import type { FontBase, FontDefine } from './text';
 import type { BinaryFile } from './binary';
-import type { ComponentData, GeometryData, MaterialData, ShaderData } from './components';
+import type { ComponentData, EffectsObjectData, GeometryData, MaterialData, ShaderData } from './components';
 import type { VFXItemData } from './vfx-item-data';
 import type { AnimationClipData } from './animation-clip-data';
 
@@ -193,4 +193,8 @@ export interface JSONScene {
    * 动画数据
    */
   animations: AnimationClipData[],
+  /**
+   * 分类外的资产数据
+   */
+  miscs: EffectsObjectData[],
 }

From 0c0bff35d54421e46de9def9242d8f4433ef0435 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E9=99=88=E6=A6=95?=
 <38219632+RGCHN@users.noreply.github.com>
Date: Thu, 13 Jun 2024 09:48:07 +0800
Subject: [PATCH 55/62] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20SpineCompone?=
 =?UTF-8?q?nt=20=E7=B1=BB=E5=9E=8B=20(#71)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* feat: 增加 SpineComponent 和 BinaryAsset 类型

* chore: 根据机器人建议优化代码

---------

Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 src/binary.ts             |  3 +-
 src/buitin-object-guid.ts | 10 +++----
 src/components.ts         |  2 ++
 src/item/spine-item.ts    | 63 ++++++++++++++++++++++++---------------
 src/scene.ts              |  8 ++---
 5 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/src/binary.ts b/src/binary.ts
index 825ddbf..e66f2ed 100644
--- a/src/binary.ts
+++ b/src/binary.ts
@@ -1,3 +1,4 @@
+import type { DataType } from './components';
 import type { RenderLevel } from './type';
 import type { ValueType } from './number-expression';
 
@@ -21,12 +22,12 @@ import type { ValueType } from './number-expression';
 export type BinaryPointerContent = [index: number, start?: number, byteLength?: number, type?: BinaryType];
 export type BinaryPointer = [ValueType.BINARY, BinaryPointerContent];
 export type BinaryType = 'u8' | 'i8' | 'i16' | 'u16' | 'f32' | 'u32' | 'i32' | 'f64' | '';
-
 /**
  * 线上二进制地址
  */
 export interface BinaryFile {
   url: string,
+  dataType: DataType.BinaryAsset,
   renderLevel?: RenderLevel,
 }
 
diff --git a/src/buitin-object-guid.ts b/src/buitin-object-guid.ts
index ba15e3c..b9ffef9 100644
--- a/src/buitin-object-guid.ts
+++ b/src/buitin-object-guid.ts
@@ -1,5 +1,5 @@
-export class BuiltinObjectGUID {
-  static readonly WhiteTexture = 'whitetexture00000000000000000000';
-  static readonly PBRShader = 'pbr00000000000000000000000000000';
-  static readonly UnlitShader = 'unlit000000000000000000000000000';
-}
\ No newline at end of file
+export const BuiltinObjectGUID = {
+  WhiteTexture: 'whitetexture00000000000000000000',
+  PBRShader: 'pbr00000000000000000000000000000',
+  UnlitShader: 'unlit000000000000000000000000000',
+};
diff --git a/src/components.ts b/src/components.ts
index 2df2aa2..a3f2147 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -17,6 +17,7 @@ export enum DataType {
   TimelineAsset = 'TimelineAsset',
   TransformPlayableAsset = 'TransformPlayableAsset',
   SpriteColorPlayableAsset = 'SpriteColorPlayableAsset',
+  BinaryAsset = 'BinaryAsset',
 
   // FIXME: 先完成ECS的场景转换,后面移到spec中
   MeshComponent = 'MeshComponent',
@@ -26,6 +27,7 @@ export enum DataType {
   ModelPluginComponent = 'ModelPluginComponent',
   TreeComponent = 'TreeComponent',
   AnimationComponent = 'AnimationComponent',
+  SpineComponent = 'SpineComponent',
 
   // Non-EffectObject
   TimelineClip = 'TimelineClip',
diff --git a/src/item/spine-item.ts b/src/item/spine-item.ts
index 08ac868..3a43e97 100644
--- a/src/item/spine-item.ts
+++ b/src/item/spine-item.ts
@@ -1,11 +1,8 @@
 import type { BinaryPointer } from '../binary';
+import type { ComponentData, DataPath, DataType } from '../components';
 import type {
-  SizeOverLifetime,
-  RotationOverLifetime,
-  PositionOverLifetime,
-  ColorOverLifetime,
-  RendererOptions,
-  ItemType,
+  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime,
+  RendererOptions, ItemType,
 } from '../type';
 import type { BaseItem, ItemEndBehavior } from './base-item';
 
@@ -14,12 +11,12 @@ import type { BaseItem, ItemEndBehavior } from './base-item';
  */
 export interface SpineItem extends BaseItem {
   /**
-	 * 元素类型 "spine"
-	 */
+   * 元素类型 "spine"
+   */
   type: ItemType.spine,
   /**
-	 * 插件元素渲染信息
-	 */
+   * 插件元素渲染信息
+   */
   content: SpineContent,
   endBehavior: ItemEndBehavior,
 }
@@ -59,16 +56,16 @@ export interface SpineContent {
  */
 export interface PluginSpineOption {
   /**
-	 * 当前使用的皮肤名称
-	 */
+   * 当前使用的皮肤名称
+   */
   activeSkin: string,
   /**
-	 * 当前使用的动画列表,1.5 之前为 string
-	 */
+   * 当前使用的动画列表,1.5 之前为 string
+   */
   activeAnimation: string[] | string,
   /**
-	 * 在 spines 资源数组中的索引
-	 */
+   * 在 spines 资源数组中的索引
+   */
   spine: number,
   /**
    * 默认融合时间
@@ -95,19 +92,37 @@ export type skeletonFileType = 'json' | 'skel';
 
 export interface SpineResource {
   /**
-	 * atlas 文件在 `bins` 中的指针
-	 */
+   * atlas 文件在 `bins` 中的指针
+   */
   atlas: BinaryPointer,
   /**
-	 * 骨骼文件
-	 */
+   * 骨骼文件
+   */
   skeleton: BinaryPointer,
   /**
-	 * skeleton 文件类型, `.skel/.json`
-	 */
+   * skeleton 文件类型, `.skel/.json`
+   */
   skeletonType: skeletonFileType,
   /**
-	 * 图像文件在 `scene.textures` 数组中的索引
-	 */
+   * 图像文件在 `scene.textures` 数组中的索引
+   */
   images: number[],
 }
+
+export interface SpineComponent extends ComponentData {
+  dataType: DataType.SpineComponent,
+  options: PluginSpineOption,
+  resource: {
+    atlas: {
+      bins: DataPath,
+      source: [start: number, length?: number],
+    },
+    skeleton: {
+      bins: DataPath,
+      source: [start: number, length?: number],
+    },
+    images: DataPath[],
+    skeletonType: skeletonFileType,
+  },
+
+}
diff --git a/src/scene.ts b/src/scene.ts
index eeb8452..c8d9af1 100644
--- a/src/scene.ts
+++ b/src/scene.ts
@@ -157,10 +157,10 @@ export interface JSONScene {
    * 数据模板下掉可以不要 FontBase[]
    */
   fonts?: FontBase[] | FontDefine[],
-  /**
-   * spine 资源
-   */
-  spines?: SpineResource[],
+  // /**
+  //  * spine 资源
+  //  */
+  // spines?: SpineResource[],
   /**
    * 二进制文件地址
    */

From 195996c42e487bb1e72d9e6dfd161c81fb382b38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Wed, 26 Jun 2024 11:34:03 +0800
Subject: [PATCH 56/62] feat: add timeline data type (#72)

* feat: add timeline data type

* perf: opt type
---
 src/components.ts                                     | 11 ++++++++++-
 src/timeline/index.ts                                 |  4 ++--
 .../playables/sprite-color-playable-asset-data.ts     |  9 +++++++++
 .../{ => playables}/transform-playable-asset-data.ts  |  5 +++--
 src/timeline/sprite-color-playable-asset-data.ts      |  8 --------
 src/timeline/timeline-asset-data.ts                   |  3 ++-
 6 files changed, 26 insertions(+), 14 deletions(-)
 create mode 100644 src/timeline/playables/sprite-color-playable-asset-data.ts
 rename src/timeline/{ => playables}/transform-playable-asset-data.ts (73%)
 delete mode 100644 src/timeline/sprite-color-playable-asset-data.ts

diff --git a/src/components.ts b/src/components.ts
index a3f2147..0d6d6ab 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -13,11 +13,20 @@ export enum DataType {
   Texture = 'Texture',
   AnimationClip = 'AnimationClip',
   TextComponent = 'TextComponent',
+  BinaryAsset = 'BinaryAsset',
+
+  // Timeline
   TrackAsset = 'TrackAsset',
   TimelineAsset = 'TimelineAsset',
+  ObjectBindingTrack = 'ObjectBindingTrack',
+  TransformTrack = 'TransformTrack',
+  SpriteColorTrack = 'SpriteColorTrack',
+  ActivationTrack = 'ActivationTrack',
+  SubCompositionTrack = 'SubCompositionTrack',
   TransformPlayableAsset = 'TransformPlayableAsset',
   SpriteColorPlayableAsset = 'SpriteColorPlayableAsset',
-  BinaryAsset = 'BinaryAsset',
+  ActivationPlayableAsset = 'ActivationPlayableAsset',
+  SubCompositionPlayableAsset = 'SubCompositionPlayableAsset',
 
   // FIXME: 先完成ECS的场景转换,后面移到spec中
   MeshComponent = 'MeshComponent',
diff --git a/src/timeline/index.ts b/src/timeline/index.ts
index ca1682d..f106736 100644
--- a/src/timeline/index.ts
+++ b/src/timeline/index.ts
@@ -1,5 +1,5 @@
 export * from './track/track-asset-data';
-export * from './sprite-color-playable-asset-data';
+export * from './playables/sprite-color-playable-asset-data';
 export * from './timeline-asset-data';
 export * from './timeline-clip-data';
-export * from './transform-playable-asset-data';
\ No newline at end of file
+export * from './playables/transform-playable-asset-data';
\ No newline at end of file
diff --git a/src/timeline/playables/sprite-color-playable-asset-data.ts b/src/timeline/playables/sprite-color-playable-asset-data.ts
new file mode 100644
index 0000000..ca3f33c
--- /dev/null
+++ b/src/timeline/playables/sprite-color-playable-asset-data.ts
@@ -0,0 +1,9 @@
+import type { DataType, EffectsObjectData } from '../../components';
+import type { RGBAColorValue } from '../../number-expression';
+import type { ColorOverLifetime } from '../../type';
+
+export interface SpriteColorPlayableAssetData extends EffectsObjectData {
+  dataType: DataType.SpriteColorPlayableAsset,
+  colorOverLifetime?: ColorOverLifetime,
+  startColor?: RGBAColorValue,
+}
\ No newline at end of file
diff --git a/src/timeline/transform-playable-asset-data.ts b/src/timeline/playables/transform-playable-asset-data.ts
similarity index 73%
rename from src/timeline/transform-playable-asset-data.ts
rename to src/timeline/playables/transform-playable-asset-data.ts
index eee2a7a..d30c6d1 100644
--- a/src/timeline/transform-playable-asset-data.ts
+++ b/src/timeline/playables/transform-playable-asset-data.ts
@@ -1,7 +1,8 @@
-import type { EffectsObjectData } from '../components';
-import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime } from '../type';
+import type { DataType, EffectsObjectData } from '../../components';
+import type { SizeOverLifetime, RotationOverLifetime, PositionOverLifetime } from '../../type';
 
 export interface TransformPlayableAssetData extends EffectsObjectData {
+  dataType: DataType.TransformPlayableAsset,
   /**
    * 元素大小变化属性
    */
diff --git a/src/timeline/sprite-color-playable-asset-data.ts b/src/timeline/sprite-color-playable-asset-data.ts
deleted file mode 100644
index 9154eb3..0000000
--- a/src/timeline/sprite-color-playable-asset-data.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import type { EffectsObjectData } from '../components';
-import type { RGBAColorValue } from '../number-expression';
-import type { ColorOverLifetime } from '../type';
-
-export interface SpriteColorPlayableAssetData extends EffectsObjectData {
-  colorOverLifetime?: ColorOverLifetime,
-  startColor?: RGBAColorValue,
-}
\ No newline at end of file
diff --git a/src/timeline/timeline-asset-data.ts b/src/timeline/timeline-asset-data.ts
index 71439a7..fa6b3e4 100644
--- a/src/timeline/timeline-asset-data.ts
+++ b/src/timeline/timeline-asset-data.ts
@@ -1,6 +1,7 @@
-import type { EffectsObjectData, DataPath } from '../components';
+import type { EffectsObjectData, DataPath, DataType } from '../components';
 
 export interface TimelineAssetData extends EffectsObjectData {
+  dataType: DataType.TimelineAsset,
   /**
    * 轨道数据(TrackAssetData)
    */

From d1d15580fec05df7a8dc331fa65c6f8e3a5412f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Fri, 12 Jul 2024 10:02:56 +0800
Subject: [PATCH 57/62] perf: unify end behavior (#73)

* perf: unify end behavior

* perf: remove CompositionEndBehavior

* chore: typo

---------

Co-authored-by: wumaolin.wml <wumaolin.wml@antgroup.com>
Co-authored-by: yiiqii <yfj5tzl2005@sina.com>
---
 src/composition.ts           | 44 +++---------------------------------
 src/constants.ts             | 23 +++++++++++++++++++
 src/item/base-item.ts        | 25 ++++++++++++++++----
 src/item/camera-item.ts      |  4 ++--
 src/item/composition-item.ts |  4 ++--
 src/item/effect-item.ts      |  4 ++--
 src/item/interact-item.ts    |  4 ++--
 src/item/model/camera.ts     |  4 ++--
 src/item/model/light.ts      |  4 ++--
 src/item/model/mesh.ts       |  4 ++--
 src/item/model/skybox.ts     |  4 ++--
 src/item/particle-item.ts    |  4 ++--
 src/item/plugin-item.ts      |  4 ++--
 src/item/spine-item.ts       |  4 ++--
 src/item/sprite-item.ts      | 15 ++++--------
 src/item/text-item.ts        |  8 +++----
 src/vfx-item-data.ts         |  4 ++--
 17 files changed, 79 insertions(+), 84 deletions(-)

diff --git a/src/composition.ts b/src/composition.ts
index 2f9cc37..2400bd9 100644
--- a/src/composition.ts
+++ b/src/composition.ts
@@ -1,15 +1,7 @@
 import type { DataPath } from './components';
-import {
-  CAMERA_CLIP_MODE_NORMAL,
-  CAMERA_CLIP_MODE_VERTICAL,
-  END_BEHAVIOR_DESTROY,
-  END_BEHAVIOR_FORWARD,
-  END_BEHAVIOR_FREEZE,
-  END_BEHAVIOR_PAUSE,
-  END_BEHAVIOR_PAUSE_AND_DESTROY,
-  END_BEHAVIOR_RESTART,
-} from './constants';
+import { CAMERA_CLIP_MODE_NORMAL, CAMERA_CLIP_MODE_VERTICAL } from './constants';
 import type { Item } from './item';
+import type { EndBehavior } from './item/base-item';
 
 export enum CameraClipMode {
   /**
@@ -54,36 +46,6 @@ export interface CameraOptions {
   clipMode: CameraClipMode,
 }
 
-/**
- * 结束行为
- */
-export enum CompositionEndBehavior {
-  /**
-   * 销毁
-   */
-  destroy = END_BEHAVIOR_DESTROY,
-  /**
-   * 暂停
-   */
-  pause = END_BEHAVIOR_PAUSE,
-  /**
-   * 重播
-   */
-  restart = END_BEHAVIOR_RESTART,
-  /**
-   * 无限播放
-   */
-  forward = END_BEHAVIOR_FORWARD,
-  /**
-   * 销毁并保留最后一帧
-   */
-  pause_destroy = END_BEHAVIOR_PAUSE_AND_DESTROY,
-  /**
-   * 冻结
-   */
-  freeze = END_BEHAVIOR_FREEZE,
-}
-
 interface CompositionBase {
   /**
    * 合成ID
@@ -105,7 +67,7 @@ interface CompositionBase {
   /**
    * 合成结束行为
    */
-  endBehavior: CompositionEndBehavior,
+  endBehavior: EndBehavior,
   /**
    * 合成相机信息
    */
diff --git a/src/constants.ts b/src/constants.ts
index 09e3a0a..b89722c 100644
--- a/src/constants.ts
+++ b/src/constants.ts
@@ -1,9 +1,32 @@
+/**
+ * 销毁
+ */
 export const END_BEHAVIOR_DESTROY = 0;
+/**
+ * 暂停
+ * @deprecated since 2.0 - use `END_BEHAVIOR_FREEZE` instead
+ */
 export const END_BEHAVIOR_PAUSE = 1;
+/**
+ * 无限播放
+ */
 export const END_BEHAVIOR_FORWARD = 2;
+/**
+ * 销毁并保留最后一帧
+ * @deprecated since 2.0
+ */
 export const END_BEHAVIOR_PAUSE_AND_DESTROY = 3;
+/**
+ * 冻结
+ */
 export const END_BEHAVIOR_FREEZE = 4;
+/**
+ * 重播
+ */
 export const END_BEHAVIOR_RESTART = 5;
+/**
+ *
+ */
 export const END_BEHAVIOR_DESTROY_CHILDREN = 6;
 
 export const CAMERA_CLIP_MODE_VERTICAL = 1;
diff --git a/src/item/base-item.ts b/src/item/base-item.ts
index 8dbf2f4..f8ac9b8 100644
--- a/src/item/base-item.ts
+++ b/src/item/base-item.ts
@@ -1,7 +1,8 @@
 /* eslint-disable @typescript-eslint/no-redundant-type-constituents */
 import type { BinaryEnv } from '../binary';
 import {
-  END_BEHAVIOR_DESTROY, END_BEHAVIOR_DESTROY_CHILDREN, END_BEHAVIOR_FREEZE, END_BEHAVIOR_RESTART,
+  END_BEHAVIOR_DESTROY, END_BEHAVIOR_DESTROY_CHILDREN, END_BEHAVIOR_FORWARD,
+  END_BEHAVIOR_FREEZE, END_BEHAVIOR_RESTART,
 } from '../constants';
 import type { vec3, vec4 } from '../number-expression';
 import type { ItemType, RenderLevel } from '../type';
@@ -17,9 +18,25 @@ import type { SpineContent } from './spine-item';
 import type { SpriteContent } from './sprite-item';
 import type { TextContent } from './text-item';
 
-export enum ItemEndBehavior {
+/**
+ * 结束行为
+ */
+export enum EndBehavior {
+  /**
+   * 销毁
+   */
   destroy = END_BEHAVIOR_DESTROY,
-  loop = END_BEHAVIOR_RESTART,
+  /**
+   * 重播
+   */
+  restart = END_BEHAVIOR_RESTART,
+  /**
+   * 无限播放
+   */
+  forward = END_BEHAVIOR_FORWARD,
+  /**
+   * 冻结
+   */
   freeze = END_BEHAVIOR_FREEZE,
 }
 
@@ -64,7 +81,7 @@ export interface BaseItem {
    * 元素结束行为
    * @default destroy
    */
-  endBehavior: ItemEndBehavior | ParentItemEndBehavior,
+  endBehavior: EndBehavior | ParentItemEndBehavior,
   /**
    * 元素播放延时(单位秒)
    * @default 0
diff --git a/src/item/camera-item.ts b/src/item/camera-item.ts
index 2942caf..4167aee 100644
--- a/src/item/camera-item.ts
+++ b/src/item/camera-item.ts
@@ -1,4 +1,4 @@
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 import type { ItemType, RotationOverLifetime } from '../type';
 import type { FixedNumberExpression, FixedVec3Expression } from '../number-expression';
 import type { CameraClipMode } from '../composition';
@@ -12,7 +12,7 @@ export interface CameraItem extends BaseItem {
    * 相机元素渲染信息
    */
   content: CameraContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 export interface CameraContent {
diff --git a/src/item/composition-item.ts b/src/item/composition-item.ts
index ba5b756..4989449 100644
--- a/src/item/composition-item.ts
+++ b/src/item/composition-item.ts
@@ -1,4 +1,4 @@
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 import type {
   SizeOverLifetime, RotationOverLifetime, ColorOverLifetime, ItemType,
 } from '../type';
@@ -17,7 +17,7 @@ export interface CompositionItem extends BaseItem {
    * 预合成元素渲染信息
    */
   content: CompositionContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/effect-item.ts b/src/item/effect-item.ts
index 3af5587..426362b 100644
--- a/src/item/effect-item.ts
+++ b/src/item/effect-item.ts
@@ -1,5 +1,5 @@
 import type { ItemType, PositionOverLifetime, RotationOverLifetime, SizeOverLifetime } from '../type';
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 
 /**
  * 特效元素
@@ -7,7 +7,7 @@ import type { BaseItem, ItemEndBehavior } from './base-item';
 export interface EffectItem extends BaseItem {
   type: ItemType.effect,
   content: EffectContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/interact-item.ts b/src/item/interact-item.ts
index b6325c3..8b1bca1 100644
--- a/src/item/interact-item.ts
+++ b/src/item/interact-item.ts
@@ -1,6 +1,6 @@
 import type { InteractBehavior, InteractType, ItemType } from '../type';
 import type { RGBAColor } from '../number-expression';
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 import type { ComponentData } from '../components';
 
 /**
@@ -15,7 +15,7 @@ export interface InteractItem extends BaseItem {
    * 交互元素渲染信息
    */
   content: InteractContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/model/camera.ts b/src/item/model/camera.ts
index b555e99..ff35d6b 100644
--- a/src/item/model/camera.ts
+++ b/src/item/model/camera.ts
@@ -1,4 +1,4 @@
-import type { BaseItem, ItemEndBehavior } from '../base-item';
+import type { BaseItem, EndBehavior } from '../base-item';
 import type { CameraClipMode, CameraOptions } from '../../composition';
 import type { RotationOverLifetime, PositionOverLifetime } from '../../type';
 import type { ComponentData } from '../../components';
@@ -34,7 +34,7 @@ export interface ModelCameraItem extends BaseItem {
   type: 'camera',
   pluginName: 'model',
   content: ModelCameraContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 export enum CameraType {
diff --git a/src/item/model/light.ts b/src/item/model/light.ts
index ff0dc5d..2419d11 100644
--- a/src/item/model/light.ts
+++ b/src/item/model/light.ts
@@ -1,5 +1,5 @@
 import type { RGBAColorValue } from '../../number-expression';
-import type { BaseItem, ItemEndBehavior } from '../base-item';
+import type { BaseItem, EndBehavior } from '../base-item';
 import type { RotationOverLifetime, PositionOverLifetime, ItemType } from '../../type';
 import type { ColorData, ComponentData } from '../../components';
 
@@ -85,7 +85,7 @@ export interface ModelLightItem extends BaseItem {
   type: ItemType.light,
   pluginName: 'model',
   content: ModelLightContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 export enum LightType {
diff --git a/src/item/model/mesh.ts b/src/item/model/mesh.ts
index 4b2cc65..1348c53 100644
--- a/src/item/model/mesh.ts
+++ b/src/item/model/mesh.ts
@@ -1,5 +1,5 @@
 import type { BinaryEnv } from '../../binary';
-import type { BaseItem, ItemEndBehavior } from '../base-item';
+import type { BaseItem, EndBehavior } from '../base-item';
 import type { MaterialOptions } from './material';
 import type { GeometryPointer } from './binary';
 import type { vec3 } from '../../number-expression';
@@ -88,7 +88,7 @@ export interface ModelMeshItem<T extends BinaryEnv> extends BaseItem {
   type: ItemType.mesh,
   pluginName: 'model',
   content: ModelMeshItemContent<T>,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 export interface PrimitiveData {
diff --git a/src/item/model/skybox.ts b/src/item/model/skybox.ts
index d384d57..86ae0db 100644
--- a/src/item/model/skybox.ts
+++ b/src/item/model/skybox.ts
@@ -1,4 +1,4 @@
-import type { BaseItem, ItemEndBehavior } from '../base-item';
+import type { BaseItem, EndBehavior } from '../base-item';
 import type { BinaryEnv } from '../../binary';
 import type { SkyboxCubeTexturePointer } from './binary';
 import type { ItemType } from '../../type';
@@ -40,7 +40,7 @@ export interface ModelSkyboxItem<T extends BinaryEnv> extends BaseItem {
   type: ItemType.skybox,
   pluginName: 'model',
   content: SkyboxContent<T>,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/particle-item.ts b/src/item/particle-item.ts
index f134a01..1a8e3ef 100644
--- a/src/item/particle-item.ts
+++ b/src/item/particle-item.ts
@@ -5,7 +5,7 @@ import type {
   FixedNumberExpression, NumberExpression, GradientColor, vec3, FixedVec3Expression,
   ColorExpression, FunctionExpression,
 } from '../number-expression';
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 import type { ParticleShape } from './particle-shape';
 import type { ComponentData } from '../components';
 
@@ -35,7 +35,7 @@ export interface ParticleItem extends BaseItem {
    * 粒子元素渲染信息
    */
   content: ParticleContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/plugin-item.ts b/src/item/plugin-item.ts
index 46bd60f..12d175c 100644
--- a/src/item/plugin-item.ts
+++ b/src/item/plugin-item.ts
@@ -1,5 +1,5 @@
 import type { ItemType, PluginGyroscopeTarget, PluginType, RendererOptions } from '../type';
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 
 /**
  * 插件元素
@@ -13,7 +13,7 @@ export interface PluginItem extends BaseItem {
    * 插件元素渲染信息
    */
   content: PluginContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/spine-item.ts b/src/item/spine-item.ts
index 3a43e97..a242a7c 100644
--- a/src/item/spine-item.ts
+++ b/src/item/spine-item.ts
@@ -4,7 +4,7 @@ import type {
   SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime,
   RendererOptions, ItemType,
 } from '../type';
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 
 /**
  * 插件元素
@@ -18,7 +18,7 @@ export interface SpineItem extends BaseItem {
    * 插件元素渲染信息
    */
   content: SpineContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 /**
diff --git a/src/item/sprite-item.ts b/src/item/sprite-item.ts
index 1bf18ee..65cc614 100644
--- a/src/item/sprite-item.ts
+++ b/src/item/sprite-item.ts
@@ -1,14 +1,7 @@
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 import type {
-  SizeOverLifetime,
-  RotationOverLifetime,
-  PositionOverLifetime,
-  ColorOverLifetime,
-  ItemType,
-  TextureSheetAnimation,
-  RendererOptions,
-  SplitParameter,
-  InteractBehavior,
+  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime, ItemType,
+  TextureSheetAnimation, RendererOptions, SplitParameter, InteractBehavior,
 } from '../type';
 import type { RGBAColorValue } from '../number-expression';
 import type { ComponentData } from '../components';
@@ -25,7 +18,7 @@ export interface SpriteItem extends BaseItem {
    * 图层元素渲染信息
    */
   content: SpriteContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 export interface SpriteContentOptions {
diff --git a/src/item/text-item.ts b/src/item/text-item.ts
index 42e72d9..55c2213 100644
--- a/src/item/text-item.ts
+++ b/src/item/text-item.ts
@@ -1,7 +1,7 @@
-import type { BaseItem, ItemEndBehavior } from './base-item';
+import type { BaseItem, EndBehavior } from './base-item';
 import type {
-  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime,
-  ItemType, TextureSheetAnimation, RendererOptions, InteractBehavior,
+  SizeOverLifetime, RotationOverLifetime, PositionOverLifetime, ColorOverLifetime, ItemType,
+  TextureSheetAnimation, RendererOptions, InteractBehavior,
 } from '../type';
 import type { RGBAColorValue } from '../number-expression';
 import type { FontStyle, TextAlignment, TextBaseline, TextOverflow, TextWeight } from '../text';
@@ -19,7 +19,7 @@ export interface TextItem extends BaseItem {
    * 文本元素渲染信息
    */
   content: TextContent,
-  endBehavior: ItemEndBehavior,
+  endBehavior: EndBehavior,
 }
 
 export interface TextContentOptions {
diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index cc8227b..1d1d51f 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -1,5 +1,5 @@
 import type { DataPath, EffectsObjectData } from './components';
-import type { ItemEndBehavior, ParentItemEndBehavior, BaseContent, TransformData } from './item/base-item';
+import type { EndBehavior, ParentItemEndBehavior, BaseContent, TransformData } from './item/base-item';
 import type { ItemType, RenderLevel } from './type';
 
 export interface VFXItemData extends EffectsObjectData {
@@ -38,7 +38,7 @@ export interface VFXItemData extends EffectsObjectData {
    * 元素结束行为
    * @default destroy
    */
-  endBehavior: ItemEndBehavior | ParentItemEndBehavior,
+  endBehavior: EndBehavior | ParentItemEndBehavior,
   /**
    * 元素播放延时(单位秒)
    * @default 0

From 05ba4d13682ccc34b389b85b4c1712a1388d87b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E8=8C=82=E5=AE=89?=
 <151805118+wumaolinmaoan@users.noreply.github.com>
Date: Mon, 15 Jul 2024 16:16:37 +0800
Subject: [PATCH 58/62] feat: geometry buffer support binary asset (#74)

* feat: geometry buffer support binary asset

* feat: add BinaryDataSegment
---
 src/binary.ts                      | 10 ++++++++--
 src/components.ts                  |  7 ++++++-
 src/timeline/timeline-clip-data.ts |  2 ++
 3 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/src/binary.ts b/src/binary.ts
index e66f2ed..3c4151d 100644
--- a/src/binary.ts
+++ b/src/binary.ts
@@ -1,4 +1,4 @@
-import type { DataType } from './components';
+import type { DataPath, DataType, EffectsObjectData } from './components';
 import type { RenderLevel } from './type';
 import type { ValueType } from './number-expression';
 
@@ -25,12 +25,18 @@ export type BinaryType = 'u8' | 'i8' | 'i16' | 'u16' | 'f32' | 'u32' | 'i32' | '
 /**
  * 线上二进制地址
  */
-export interface BinaryFile {
+export interface BinaryFile extends EffectsObjectData {
   url: string,
   dataType: DataType.BinaryAsset,
   renderLevel?: RenderLevel,
 }
 
+export interface BinaryDataSegment {
+  buffer: DataPath,
+  offset: number,
+  length: number,
+}
+
 export type BinaryEnv = 'studio' | 'runtime' | 'json';
 
 /**
diff --git a/src/components.ts b/src/components.ts
index 0d6d6ab..6c83099 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -1,3 +1,4 @@
+import type { BinaryDataSegment } from './binary';
 import type { Vector2Data } from './item/base-item';
 
 export enum DataType {
@@ -103,7 +104,11 @@ export interface GeometryData extends EffectsObjectData {
   /**
    * 存放 position, uv, normal, indices 的打包数据
    */
-  buffer: string,
+  buffer?: string,
+  /**
+   * 存放 position, uv, normal, indices 的打包数据二进制资产引用
+   */
+  bufferAsset?: BinaryDataSegment,
   /**
    * 所有的骨骼名称
    */
diff --git a/src/timeline/timeline-clip-data.ts b/src/timeline/timeline-clip-data.ts
index 97ebd4a..c5d5194 100644
--- a/src/timeline/timeline-clip-data.ts
+++ b/src/timeline/timeline-clip-data.ts
@@ -1,8 +1,10 @@
+import type { EndBehavior } from '../item/base-item';
 import type { DataPath } from '../components';
 
 export interface TimelineClipData {
   start?: number,
   duration?: number,
+  endBehavior?: EndBehavior,
   /**
    * 可播放资产(PlayableAssetData)
    */

From adba20c1504055b7b89a7706ffef789221da415b Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Tue, 16 Jul 2024 17:33:24 +0800
Subject: [PATCH 59/62] feat: add binaryData

---
 src/binary.ts     | 8 +-------
 src/components.ts | 5 ++---
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/src/binary.ts b/src/binary.ts
index 3c4151d..c1922bd 100644
--- a/src/binary.ts
+++ b/src/binary.ts
@@ -1,4 +1,4 @@
-import type { DataPath, DataType, EffectsObjectData } from './components';
+import type { DataType, EffectsObjectData } from './components';
 import type { RenderLevel } from './type';
 import type { ValueType } from './number-expression';
 
@@ -31,12 +31,6 @@ export interface BinaryFile extends EffectsObjectData {
   renderLevel?: RenderLevel,
 }
 
-export interface BinaryDataSegment {
-  buffer: DataPath,
-  offset: number,
-  length: number,
-}
-
 export type BinaryEnv = 'studio' | 'runtime' | 'json';
 
 /**
diff --git a/src/components.ts b/src/components.ts
index 6c83099..6989576 100644
--- a/src/components.ts
+++ b/src/components.ts
@@ -1,4 +1,3 @@
-import type { BinaryDataSegment } from './binary';
 import type { Vector2Data } from './item/base-item';
 
 export enum DataType {
@@ -106,9 +105,9 @@ export interface GeometryData extends EffectsObjectData {
    */
   buffer?: string,
   /**
-   * 存放 position, uv, normal, indices 的打包数据二进制资产引用
+   * 存放 position, uv, normal, indices 的二进制数据,用于序列化二进制数据
    */
-  bufferAsset?: BinaryDataSegment,
+  binaryData?: Uint8Array,
   /**
    * 所有的骨骼名称
    */

From 1ed83bb14372aded3c01f4f6d069e07dcc439e7d Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Tue, 30 Jul 2024 15:50:33 +0800
Subject: [PATCH 60/62] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20Image=20?=
 =?UTF-8?q?=E7=9A=84=20avif=20=E5=AD=97=E6=AE=B5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/image.ts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/image.ts b/src/image.ts
index 575fc01..1fa409f 100644
--- a/src/image.ts
+++ b/src/image.ts
@@ -94,6 +94,12 @@ export interface Image {
    * 如果运行时支持 WebP,则优先使用 WebP
    */
   webp?: string,
+  /**
+   * AVIF 地址
+   * 如果运行时支持 AVIF,则优先使用 AVIF
+   * @since 2.0.0
+   */
+  avif?: string,
   /**
    * 纹理贴图渲染等级
    * 如果没有设置,按照 B+ 处理

From dd5b11d0de4c7bc5e1aec7a203cfaa42efb87718 Mon Sep 17 00:00:00 2001
From: yiiqii <yfj5tzl2005@sina.com>
Date: Wed, 31 Jul 2024 18:25:05 +0800
Subject: [PATCH 61/62] =?UTF-8?q?chore:=20=E5=AE=8C=E5=96=84=20TemplateCon?=
 =?UTF-8?q?tent=20=E7=B1=BB=E5=9E=8B=EF=BC=8C=E5=A2=9E=E5=8A=A0=20Template?=
 =?UTF-8?q?Variable=20=E7=B1=BB=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 src/image.ts | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/image.ts b/src/image.ts
index 1fa409f..745e484 100644
--- a/src/image.ts
+++ b/src/image.ts
@@ -66,7 +66,6 @@ export enum BackgroundType {
 }
 
 export interface TemplateContent {
-  variables: Record<string, number | string>,
   /**
    * 当 template 宽高和 image 不相同时,会对 template 进行缩放,使其和 image 相同。
    */
@@ -76,10 +75,12 @@ export interface TemplateContent {
   background?: {
     type: BackgroundType,
     name: string,
-    url: string,
+    url: string | HTMLImageElement,
   },
 }
 
+export type TemplateVariables = Record<string, string | string[] | HTMLImageElement | HTMLImageElement[]>;
+
 /**
  * 纹理贴图属性
  */

From b3dbd94d499499e1712edc0b8277d177b1aff422 Mon Sep 17 00:00:00 2001
From: wumaolinmaoan <wumaolin1998@outlook.com>
Date: Mon, 19 Aug 2024 12:17:55 +0800
Subject: [PATCH 62/62] perf: opt item endbehavior type

---
 src/vfx-item-data.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/vfx-item-data.ts b/src/vfx-item-data.ts
index 1d1d51f..ee0b0c1 100644
--- a/src/vfx-item-data.ts
+++ b/src/vfx-item-data.ts
@@ -1,5 +1,5 @@
 import type { DataPath, EffectsObjectData } from './components';
-import type { EndBehavior, ParentItemEndBehavior, BaseContent, TransformData } from './item/base-item';
+import type { EndBehavior, BaseContent, TransformData } from './item/base-item';
 import type { ItemType, RenderLevel } from './type';
 
 export interface VFXItemData extends EffectsObjectData {
@@ -38,7 +38,7 @@ export interface VFXItemData extends EffectsObjectData {
    * 元素结束行为
    * @default destroy
    */
-  endBehavior: EndBehavior | ParentItemEndBehavior,
+  endBehavior: EndBehavior,
   /**
    * 元素播放延时(单位秒)
    * @default 0