Browse Source

'init:代码迁移,网页端和桌面端代码托管'

韩洋 1 year ago
commit
69ac37eba3
100 changed files with 16785 additions and 0 deletions
  1. 18 0
      .editorconfig
  2. 32 0
      .gitignore
  3. 4 0
      .npmrc
  4. 1 0
      .prettierignore
  5. 8 0
      .prettierrc
  6. 33 0
      .vscode/settings.json
  7. 50 0
      README.md
  8. 48 0
      docs/.vitepress/config.js
  9. 7 0
      docs/3rd-libs.md
  10. 48 0
      docs/about.md
  11. 72 0
      docs/api-request.md
  12. 36 0
      docs/config.md
  13. 27 0
      docs/dev-env.md
  14. 78 0
      docs/dir-structure.md
  15. 34 0
      docs/event-bus.md
  16. 57 0
      docs/git-commit.md
  17. 11 0
      docs/i18n.md
  18. 14 0
      docs/index.md
  19. 75 0
      docs/storage.md
  20. 27 0
      docs/theme.md
  21. 308 0
      docs/vue-sfc.md
  22. 587 0
      electron.main copy.js
  23. 595 0
      electron.main.js
  24. 13 0
      eslint.config.js
  25. 60 0
      floating-icon.html
  26. 6136 0
      package-lock.json
  27. 84 0
      package.json
  28. 26 0
      preload.js
  29. 49 0
      public/config.js
  30. BIN
      public/logo.png
  31. BIN
      public/tray-icon.ico
  32. BIN
      public/tray-icon.png
  33. 1 0
      src/3rd-libs/README.md
  34. 14 0
      src/3rd-libs/clipboard.js
  35. 29 0
      src/3rd-libs/docx-preview.js
  36. 25 0
      src/3rd-libs/docx-preview/docx-preview.d.ts
  37. 3903 0
      src/3rd-libs/docx-preview/docx-preview.js
  38. 0 0
      src/3rd-libs/docx-preview/docx-preview.js.map
  39. 0 0
      src/3rd-libs/docx-preview/docx-preview.min.js
  40. 0 0
      src/3rd-libs/docx-preview/docx-preview.min.js.map
  41. 0 0
      src/3rd-libs/docx-preview/docx-preview.min.mjs
  42. 0 0
      src/3rd-libs/docx-preview/docx-preview.min.mjs.map
  43. 3894 0
      src/3rd-libs/docx-preview/docx-preview.mjs
  44. 0 0
      src/3rd-libs/docx-preview/docx-preview.mjs.map
  45. 14 0
      src/3rd-libs/filesize.js
  46. 4 0
      src/3rd-libs/highlight.js
  47. 7 0
      src/3rd-libs/js-cookie.js
  48. 6 0
      src/3rd-libs/jsencrypt.js
  49. 8 0
      src/3rd-libs/marked.js
  50. 3 0
      src/3rd-libs/microsoft-feat-event-source.js
  51. 7 0
      src/3rd-libs/mitt.js
  52. 49 0
      src/3rd-libs/screenfull.js
  53. 11 0
      src/App.vue
  54. BIN
      src/assets/Green.png
  55. BIN
      src/assets/agent/agent_bg.png
  56. 31 0
      src/assets/agent/agent_icon_1.svg
  57. 39 0
      src/assets/agent/agent_icon_2.svg
  58. 36 0
      src/assets/agent/agent_icon_3.svg
  59. 32 0
      src/assets/agent/agent_icon_4.svg
  60. BIN
      src/assets/agent/icon_1.png
  61. 0 0
      src/assets/agent/icon_1.svg
  62. 0 0
      src/assets/agent/icon_10.svg
  63. 0 0
      src/assets/agent/icon_11.svg
  64. 0 0
      src/assets/agent/icon_12.svg
  65. BIN
      src/assets/agent/icon_13.png
  66. BIN
      src/assets/agent/icon_13.svg
  67. BIN
      src/assets/agent/icon_14.png
  68. BIN
      src/assets/agent/icon_15.png
  69. BIN
      src/assets/agent/icon_16.png
  70. BIN
      src/assets/agent/icon_17.png
  71. BIN
      src/assets/agent/icon_18.png
  72. 0 0
      src/assets/agent/icon_2.svg
  73. 0 0
      src/assets/agent/icon_3.svg
  74. BIN
      src/assets/agent/icon_4.png
  75. 0 0
      src/assets/agent/icon_4.svg
  76. 0 0
      src/assets/agent/icon_5.svg
  77. 0 0
      src/assets/agent/icon_6.svg
  78. BIN
      src/assets/agent/icon_7.png
  79. 0 0
      src/assets/agent/icon_7.svg
  80. 2 0
      src/assets/agent/icon_8.svg
  81. 0 0
      src/assets/agent/icon_9.svg
  82. 0 0
      src/assets/agent_center.svg
  83. 64 0
      src/assets/ai-editor/document.svg
  84. 13 0
      src/assets/ai-editor/rewrite.svg
  85. 14 0
      src/assets/ai-editor/shorten.svg
  86. 12 0
      src/assets/ai-editor/submit-ing.svg
  87. 13 0
      src/assets/ai-editor/submit-normal.svg
  88. 14 0
      src/assets/ai-editor/winden.svg
  89. BIN
      src/assets/android_link.png
  90. 0 0
      src/assets/android_link.svg
  91. 1 0
      src/assets/bg/bg-aside.svg
  92. 1 0
      src/assets/bg/bg-chat.svg
  93. 0 0
      src/assets/bg/bg-green.svg
  94. 0 0
      src/assets/bg/bg-left-footer.svg
  95. 0 0
      src/assets/bg/bg-right-footer.svg
  96. 0 0
      src/assets/bg/vg-chat.svg
  97. BIN
      src/assets/chat-aside/aside-btn-expond.png
  98. BIN
      src/assets/chat-aside/aside-menu-bg-black-bottom.png
  99. BIN
      src/assets/chat-aside/aside-menu-bg-black-middle.png
  100. BIN
      src/assets/chat-aside/aside-menu-bg-black-top.png

+ 18 - 0
.editorconfig

@@ -0,0 +1,18 @@
+# https://editorconfig.org
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 2
+indent_style = space
+insert_final_newline = true
+max_line_length = 80
+trim_trailing_whitespace = true
+
+[*.md]
+max_line_length = 0
+trim_trailing_whitespace = false
+
+[COMMIT_EDITMSG]
+max_line_length = 0

+ 32 - 0
.gitignore

@@ -0,0 +1,32 @@
+.DS_Store
+node_modules
+dist
+dist_electron
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+
+# Editor directories and files
+.idea
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
+
+*.backup.*
+
+example.*
+
+no-use.*
+
+dist
+
+docs/.vitepress/cache/

+ 4 - 0
.npmrc

@@ -0,0 +1,4 @@
+registry=https://registry.npmmirror.com
+
+electron_mirror=https://npmmirror.com/mirrors/electron/
+electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/

+ 1 - 0
.prettierignore

@@ -0,0 +1 @@
+docs

+ 8 - 0
.prettierrc

@@ -0,0 +1,8 @@
+{
+  "tabWidth": 2,
+  "trailingComma": "none",
+  "endOfLine": "auto",
+  "semi": true,
+  "printWidth": 120,
+  "singleQuote": true
+}

+ 33 - 0
.vscode/settings.json

@@ -0,0 +1,33 @@
+{
+  "editor.wordWrap": "off",
+  "editor.detectIndentation": false,
+  // 重新设定tabsize
+  "editor.tabSize": 2,
+  //失去焦点后自动保存
+  "files.autoSave": "onFocusChange",
+  //每120行就显示一条线
+  "editor.rulers": [],
+  // 在使用搜索功能时,将这些文件夹/文件排除在外
+  "search.exclude": {
+    "**/node_modules": true,
+    "**/bower_components": true,
+    "**/target": true,
+    "**/logs": true
+  },
+
+  "editor.codeActionsOnSave": {
+    "source.fixAll.eslint": "explicit"
+  },
+
+  "editor.defaultFormatter": "esbenp.prettier-vscode",
+  // #值设置为true时,每次保存的时候自动格式化;
+  "editor.formatOnSave": true,
+  "[vue]": {
+    "editor.defaultFormatter": "octref.vetur"
+  },
+  "[javascript]": {
+    "editor.defaultFormatter": "vscode.typescript-language-features"
+  },
+  "typescript.updateImportsOnPaste.enabled": false,
+  "javascript.updateImportsOnPaste.enabled": false
+}

+ 50 - 0
README.md

@@ -0,0 +1,50 @@
+# 大模型——知识问答(四川电力)
+
+## 项目须知
+
+启动项目之前,请先查看`项目开发规范`。
+
+### 将项目下载到本地
+
+```bash
+$ git clone xxxx@xxx.git
+
+# 进入项目目录
+$ cd xxxx
+
+# 安装项目所需依赖
+$ npm install
+```
+
+### 查看项目开发规范
+
+项目规范约定了一些开发过程中需要遵守的一些规则,有助于项目的`可持续性`、`可维护性`。
+
+```bash
+$ npm run doc # localhost:5174
+```
+
+### 启动项目
+
+```bash
+$ npm start # localhost:5173
+```
+
+### 构建项目
+
+```bash
+$ npm run build
+```
+
+## 兼容与支持程度
+
+注意:由于 `Vue3` 不再支持 `IE 浏览器`环境,`ArcoVue` 也不再支持 `IE 浏览器`环境。[参考](https://arco.design/vue/docs/start#Vue-%E7%89%88%E6%9C%AC),此项目也不支持`IE 浏览器`环境。
+
+### 技术相关资源
+
+- [vuejs](https://cn.vuejs.org/)
+- [vue-router](https://router.vuejs.org/zh/)
+- [pinia](https://pinia.vuejs.org/zh/)
+- [vue-i18n](https://www.npmjs.com/package/vue-i18n)
+- [axios](https://github.com/axios/axios)
+- [arco.design](https://arco.design/)

+ 48 - 0
docs/.vitepress/config.js

@@ -0,0 +1,48 @@
+export default {
+  // 站点级选项
+  title: "前端开发规范",
+  description: "前端开发规范",
+  base: "/",
+
+  // @see https://vitepress.dev/zh/reference/site-config#head
+  head: [["script", {}, `console.log('自定义脚本');`]],
+
+  themeConfig: {
+    // aside: 'right',
+    // @see https://vitepress.dev/zh/reference/default-theme-config#outline
+    outline: {
+      level: "deep",
+      label: "大纲"
+    },
+    // @see https://vitepress.dev/zh/reference/default-theme-config#docfooter
+    docFooter: {
+      prev: "上一页",
+      next: "下一页"
+    },
+    // @see https://vitepress.dev/zh/reference/default-theme-config#lightmodeswitchtitle
+    // @see https://vitepress.dev/zh/reference/default-theme-config#darkmodeswitchtitle
+    lightModeSwitchTitle: "浅色模式",
+    darkModeSwitchTitle: "深色模式",
+
+    // @see https://vitepress.dev/zh/reference/default-theme-config#sociallinks
+    socialLinks: [{ icon: "github", link: "https://github.com" }],
+
+    nav: [{ text: "首页", link: "/" }],
+    sidebar: [
+      { text: "首页", link: "/" },
+      { text: "通用规范"},
+      { text: "开发环境", link: "/dev-env" },
+      { text: "vue单文件组件", link: "/vue-sfc" },
+      { text: "git提交规范", link: "/git-commit" },
+      { text: "项目开发" },
+      { text: '目录结构', link: '/dir-structure'},
+      { text: '关于此项目', link: '/about'},
+      { text: '第三方依赖项', link: '/3rd-libs'},
+      { text: '配置文件', link: '/config'},
+      { text: '本地存储', link: '/storage'},
+      { text: '事件总线', link: '/event-bus'},
+      { text: '主题', link: '/theme'},
+      { text: '多语言', link: '/i18n'},
+    ]
+  }
+};

+ 7 - 0
docs/3rd-libs.md

@@ -0,0 +1,7 @@
+# 第三方依赖项
+
+项目中有一个目录`3rd-libs`,意为`第三方组件`。
+
+项目中引入的任意非`vue核心`第三方依赖项,都应该在`3rd-libs`目录中引入,然后导出`关键接口`,在`具体使用`时,应从`3rd-libs`中导入,而非`node_modules`中直接导入。
+
+即,在项目中,除了`vue`、`vue-router`、`pinia`、`i18n`、`arco-design`几个有限的`依赖项`可以直接从`node_modules`中引入之外,其他的第三方依赖,全部需要通过`相对路径`从`3rd-libs`中引入。

+ 48 - 0
docs/about.md

@@ -0,0 +1,48 @@
+# 关于项目
+
+## 通用组件库
+
+此项目中的`通用组件`使用 字节跳动出品的企业级设计系统[arco.design](https://arco.design/vue/docs/start)。
+
+UI层面的组件库,不要使用除此之外的组件库。
+
+## 使用第三方库或者组件
+
+每当有需要引入`第三方组件`或者`第三方库`时,应该和小组成员讨论、确认。
+
+在相应的`第三方依赖`安装到项目后,应该在`package.json`文件中移除版本号中的`^`或者`~`字符,已确保版本不会变化。
+
+引入`第三方依赖`后,第一时间在项目中进行测试使用,查看各个位置,是否存在`警告`、`报错`等问题,若发现相关情况,请`立即解决`,若无法解决,请考虑更换`其他第三方依赖`,或者移除该`第三方依赖`。
+
+## 关于别名
+
+不允许在`vite.config.mjs`中配置`resolve.alias`。
+
+即,如下代码是`不被允许`的:
+
+```vue
+<template>
+  <div>hello</div>
+</template>
+
+<script>
+import Alert from '@components/Alert'
+</script>
+```
+
+切记:任意需要引入的依赖,都要在组件中`明确`具体位置。`不允许使用别名引入`。
+
+> 别名方式容易造成`风格不统一`的问题。  
+> 随着项目开发进程的推进,`明确`具体位置,会使得开发者`越来越`了解整个`项目结构`
+
+
+## 相关资源
+
+### 技术相关资源
+
+- [vuejs](https://cn.vuejs.org/)
+- [vue-router](https://router.vuejs.org/zh/)
+- [pinia](https://pinia.vuejs.org/zh/)
+- [vue-i18n](https://www.npmjs.com/package/vue-i18n)
+- [axios](https://github.com/axios/axios)
+- [arco.design](https://arco.design/)

+ 72 - 0
docs/api-request.md

@@ -0,0 +1,72 @@
+# 网络请求
+
+* ajax
+* WebSocket
+* @microsoft/fetch-event-source (SSE)
+
+## API请求
+
+请注意`src/components/ApiGet.vue`组件,此组件可用于`get`相关的网络请求。
+
+此组件封装了一些默认的`loading`效果、错误处理内容提示。
+
+相关使用示例:
+
+* src/components/ApiGetExample1.vue
+* src/components/ApiGetExample2.vue
+* src/components/ApiGetExample3.vue
+
+### 示例1
+
+```vue
+<template>
+  <ApiGet :url="url">
+    <template v-slot="slotProps">
+      <div class="result">{{ slotProps.data[0].id }}</div>
+    </template>
+  </ApiGet>
+</template>
+
+<script setup>
+import ApiGet from './ApiGet.vue';
+
+/**
+ * 使用默认的Loading、错误处理组件
+ * 使用 slot 数据
+ */
+const url = '/api/agent/list';
+</script>
+```
+一般常用的`API`接口请求通过`Promise`统一封装暴露,在组件中引入调用。
+### 示例2
+```js
+export const getAgentIcons = ({ username }) => {
+  return new Promise((resolve, reject) => {
+    ajax
+      .post(
+        `/iaserverapi/v1/user/getInfo`,
+        { username },
+        {
+          headers: {
+            'Content-Type': 'application/json'
+          }
+        }
+      )
+      .then((res) => {
+        resolve({ code: 200, data: res.data });
+      })
+      .catch((err) => {
+        reject(err);
+      });
+  });
+}
+
+```
+```js
+import { getAgentIcons } from '../../modules/conversation-dialog/api-dialog';
+const getAgentIconsFun = async () => {
+  const username = await getUserName();
+  const res = await getAgentIcons({ username });
+};
+
+```

+ 36 - 0
docs/config.md

@@ -0,0 +1,36 @@
+# 配置文件
+
+配置文件位于`src/config/config.js`,配置字段请在此文件中配置。
+
+## 配置项的获取
+
+获取配置项的方法位于`src/config/index.js`,方法为`getConfigField`。
+
+系统里所有对配置文件的字段的获取,请通过此方法,不允许直接读`src/config/config.js`文件中的`key`
+
+```js
+export const getConfigField = (key) => {
+  if (!key) {
+    return null;
+  }
+
+  if (!config) {
+    return null;
+  }
+
+  if (key in config) {
+    return config[key];
+  } else {
+    return null;
+  }
+};
+```
+
+当在开发过程中需要用到某个配置项时,需要使用`getWindowConfig`方法进行读取。
+
+## 关于 public/config.js
+
+在`项目根目录`下的`public`下,也存在一个为`config.js`的文件。
+
+> 可能存在的特殊情况:`在项目已经 build 后,部署时希望动态调整某些关键配置项`  
+> 如需开启,则调整`getConfigField`文件配置项获取的策略,然后`build`即可。

+ 27 - 0
docs/dev-env.md

@@ -0,0 +1,27 @@
+# 开发环境
+
+## 必备软件
+
+- Chrome 浏览器
+- [git](https://git-scm.com/)
+- [Node.js](https://nodejs.org/zh-cn) 和 NPM
+- [nvm](https://github.com/nvm-sh/nvm)
+- [vscode](https://code.visualstudio.com/)
+
+## 浏览器
+
+* [Vue DevTools 文档](https://devtools.vuejs.org/)
+* [Vue DevTools Chrome应用商店](https://chromewebstore.google.com/detail/vuejs-devtools-beta/ljjemllljcmogpfapbkkighbhhppjdbg)
+
+请在浏览器安装`Vue DevTools`插件,有助于`vue`项目的开发。
+
+### vscode
+
+参考:[工具链](https://cn.vuejs.org/guide/scaling-up/tooling.html)
+
+在开发`vue`项目过程中,`vscode`编辑器有许多有用的插件,这里`重点推荐`几个。请在编辑器安装下面几个插件。
+
+* [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar)
+* [Prettier - Code formatter](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
+* [eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint)
+* [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig)

+ 78 - 0
docs/dir-structure.md

@@ -0,0 +1,78 @@
+# 项目目录结构
+
+```
+|- project/
+  |- docs/
+  |- node_modules/
+  |- src/
+    |- 3rd-libs/
+    |- assets/
+    |- config/
+    |- utils/
+    |- base/
+    |- components/
+    |- modules/
+    |- views/
+      |- Home.vue
+      |- Login.vue
+      |- routes.js
+    |- i18n.js
+    |- router.js
+    |- App.vue
+    |- index.js
+    |- index.html
+```
+
+## 目录说明
+
+### 3rd-libs
+
+此目录用于保存`第三方依赖`,所有引入的`第三方依赖`,应在此目录中进行`引入`,并公开`核心接口`,在项目的具体位置,引入此目录中公开的`核心接口`。
+
+> 此目录的设置,可以有助于随时`替换`第三方依赖项
+
+### assets
+
+此目录中保存一些`静态资源文件`
+
+>存放项目使用的第三方字体文件。
+>存放项目使用的图片资源,尽量使用`svg`矢量图。
+
+### config
+
+此目录进行配置。
+
+### utils
+
+此目录保存一些业务无关的`工具函数`。
+
+### base
+
+此目录中提供`系统`一些`基础`的能力,例如:网络、存储等。
+
+### components
+
+此目录保存一些`业务无关`的`通用组件`。
+
+### modules
+
+此目录保存`业务模块`。
+
+### views
+
+此目录保存`路由组件`。
+
+## 目录层级关系
+
+以上目录层级,由低到高,基本顺序如下:
+
+1. config
+2. utils
+3. base
+4. components
+5. modules
+6. views
+
+基本原则是:`高层能引用低层`,但是`低层不能引用高层`
+
+例如:`views`目录能引用其他任意目录的功能,但是其他目录不能引入`views`目录的功能

+ 34 - 0
docs/event-bus.md

@@ -0,0 +1,34 @@
+# 事件总线
+
+项目中对`事件总线`进行了简单封装,位于`src/base/bus.js`中。
+
+在任何时候都不允许直接使用`mitt`或者其他类似的第三方库实现`事件总线`。
+
+必须先在`src/base/bus.js`中进行定义,然后在`具体位置`引入`src/base/bus.js`中定义好的`事件总线定义`
+
+```js
+/**
+ * 事件总线 定义
+ */
+import EventBus from './event-bus/EventBus';
+
+/**
+ * 定义event bus
+ * 任意 event bus 的定义,必须添加 bus_ 前缀
+ * @example
+ * import { bus_themeChange } from './base/bus.js';
+ * 
+ * bus_themeChange.emit('light');
+ * 
+ * bus_themeChange.on((value) => {
+ *  console.log(value); // light
+ * });
+ * 
+ * setTimeout(() => {
+ *  bus_themeChange.off();
+ * }, 1000);
+ */
+export const bus_themeChange = new EventBus('theme_change');
+```
+
+> 事件总线中的`前缀`定义,不符合前面约定的`命名规范`,`事件总线定义`按照此文档进行命名。

+ 57 - 0
docs/git-commit.md

@@ -0,0 +1,57 @@
+# git提交规范
+
+## 书写格式
+
+```
+<type>(<scope>): <subject>
+// 空一行
+<body>
+// 空一行
+<footer>
+```
+
+### type值参考
+
+* feat 增加新功能
+* fix 修复问题/BUG
+* style 代码风格相关无影响运行结果的
+* perf 优化/性能提升
+* refactor 重构
+* revert 撤销修改
+* test 测试相关
+* docs 文档/注释
+* chore 依赖更新/脚手架配置修改等
+* workflow 工作流改进
+* ci 持续集成
+* mod 不确定分类的修改
+* wip 开发中
+* types 类型修改
+
+## 操作示例
+
+### 操作1
+
+```bash
+$ git commit -m 'feat(home): add home page'
+```
+
+### 操作2
+
+```bash
+$ git commit
+```
+
+输入提交信息:
+
+```
+feature(登录模块): 支持扫码登录
+
+1. 登录时增加扫码登录选项
+2. 支持多种登录方式切换
+3. 支持多种二维码展示样式
+```
+
+## 参考
+
+* [vuejs](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md)
+* [angular](https://github.com/conventional-changelog/conventional-changelog/tree/master/packages/conventional-changelog-angular)

+ 11 - 0
docs/i18n.md

@@ -0,0 +1,11 @@
+# 多语言
+
+项目支持多语言,在开发过程中,应时刻注意`多语言`的设置。
+
+<s>
+多语言的定义按照`就近原则`,在哪个文件中使用的,就在该文件`同目录`下,创建一个多语言配置文件。
+
+查看示例:`src/views/common/Header.vue`与`src/views/common/header-i18n.js`
+
+所有`-i18n.js`文件,都需要在`src/i18n.js`中进行注册。
+</s>

+ 14 - 0
docs/index.md

@@ -0,0 +1,14 @@
+# 前端开发规范
+
+为了提高前端项目的`可维护性`、`可持续性`、`代码可读性`,特制定此规范。
+
+请前端成员遵守规范进行开发。
+
+现阶段前端开发规范主要包括:
+
+- vue 组件规范
+- git 提交规范
+
+## 相关链接
+
+- [vue](https://cn.vuejs.org/)

+ 75 - 0
docs/storage.md

@@ -0,0 +1,75 @@
+# 本地存储
+
+项目中使用`localStorage`或者`sessionStorage`要注意,不能在项目中直接使用`localStorage`或者`sessionStorage`。
+
+项目中关于`本地存储`已经做了简单封装。位于`src/base/storage.js`文件中。
+
+此文件中定义一些`localStorage`、`sessionStorage`、`cookie`
+
+每当项目里有需要用到具体功能时,请先在`src/base/storage/js`中进行定义,然后在`具体位置`引入。
+
+例如:
+
+```js
+// 数据存储
+import { MyLocalStorage, MySessionStorage } from './storage/storage';
+
+import { MyCookie } from './storage/cookie';
+
+/**
+ * 本地存储定义
+ * 应确保每个 storage 定义使用的 key 不重复,并做好注释
+ * 任意localStorage的定义,必须添加 localST_ 前缀
+ */
+export const localST_Theme = new MyLocalStorage('theme'); // 主题
+export const localST_Locale = new MyLocalStorage('locale'); // 多语言
+export const localST_Authorization = new MyLocalStorage('token'); // 用户身份token
+
+/**
+ * session storage定义
+ * 任意 sessionStorage的定义,必须添加 sessionST_ 前缀
+ */
+export const sessionST_Expire = new MySessionStorage('expire');
+
+/**
+ * cookie定义
+ * 任意 cookie 的定义,必须添加 kuky_ 前缀
+ */
+export const kuky_UserName = new MyCookie('user_name');
+```
+
+每当有需要用到`本地存储`的场景时,应现在`src/base/storage.js`中定义好相应的`Storage`,然后再引入定义好的`Storage`,而非直接使用`localStorage`。
+
+## 示例
+
+> src/base/storage.js
+
+```js
+import { MyLocalStorage, MySessionStorage } from "./storage/storage";
+
+export const localST_Expire = new MyLocalStorage("expire");
+```
+
+> src/App.vue
+
+```vue
+<template>
+  <div>过期时间:{{expire_value}}</div>
+</template>
+
+<script>
+import {ref, onMounted} from 'vue';
+
+import {localST_Expire} from './base/storage';
+
+const expire_value = ref(0);
+
+onMounted(() => {
+  const expire = localST_Expire.getItem();
+
+  expire_value.value = expire;
+});
+</script>
+```
+
+> 此页描述的`前缀`不符合前面约定的`命名规范`,`本地存储相关定义`的命名,按照此页文档描述进行。

+ 27 - 0
docs/theme.md

@@ -0,0 +1,27 @@
+# 主题
+
+所有与主题有关的定义位于`src/theme`目录下。
+
+此目录下有两个`css`主题定义,`css`文件中,定义了一些关键的`颜色`、`字号`等变量,当在项目中使用到`颜色`、`字号`等`css属性`时,应使用`css变量`,否则将会引起`主题切换`功能的异常。
+
+内置的一些可以`直接使用`的变量: [设计变量](https://arco.design/vue/docs/token)
+
+如果没有找到可以直接使用的变量,则需要再`/src/theme`目录对应的`样式表`中进行定义
+
+例如:
+
+**theme-dark.css**
+
+```css
+html body[dmx-theme="dark"] {
+  --custom-color: black;
+}
+```
+
+**theme-light.css**
+
+```css
+html body[dmx-theme="dark"] {
+  --custom-color: white;
+}
+```

+ 308 - 0
docs/vue-sfc.md

@@ -0,0 +1,308 @@
+# vue 单文件组件
+
+## 基本原则
+
+### 总体原则
+
+1. 使用`setup`语法,`组合式 API`,而非`选项式 API`
+2. 不要使用`mixins`,vue3中已不推荐使用,参考:[mixins](https://cn.vuejs.org/api/options-composition.html#mixins),[app.mixin()](https://cn.vuejs.org/api/application.html#app-mixin)
+3. 不要在 `updated` 钩子中更改组件的状态,这可能会导致无限的更新循环!
+4. 慎用`provide`和`inject`。
+5. 慎用`watch`,能在`数据变化`源头进行操作的,就不要用`watch`。
+6. 适时进行`组件拆分`,组件中代码长度不宜超过`300`行(概数,`少于`或者`略超`都可接受),宽度不宜超过`3/4 屏幕宽度`,代码应适时`空格`、`换行`、`空行`。
+7. 每次提交代码之前,应移除`console.log`等无用代码。
+
+### 组件拆分原则
+
+1. 通常`v-for`遍历的`每一项`,应拆分为`独立组件`。除非`场景极其简单`,或者`确定后续不再更改`。
+2. 通常`v-if`对应的`每一项`,应拆分为`独立组件`。除非`场景极其简单`,或者`确定后续不再更改`。
+3. 通常`modal`组件中的内容,应拆分为`独立组件`。
+4. 通常`drawer`组件中的内容,应拆分为`独立组件`。
+5. 通常`popover`组件中的内容,应拆分为`独立组件`。
+6. 通常`表单`应拆分为`独立组件`。
+7. `过于复杂`的组件应设法拆分为`多个独立组件`
+
+### 模板-template
+
+1. `v-if`和`v-for`不要用在同一个节点上。
+2. `v-for`必须加独立的唯一的`key`,如果API不返回,客户端应设法构造一个`唯一的可逆的key`
+3. 任意节点的`key`都不能用`随机数`
+4. 不要在模板里写`函数`,例如:`<button @click="() => {status = 1}">按钮</button>`,这是糟糕的做法。
+5. 不要在模板里写过多`js表达式`,请使用`计算属性`或者其他定义好的值。例如:绑定的样式对象直接在模板里书写,这是糟糕的做法。
+6. 模板中的字符串使用`双引号`包裹,例如:`<div title="标题"></div>`
+7. 不要使用`v-else`,当在模板中存在条件判断时,应写完整的`v-if`,例如:`<div v-if="open">开</div><div v-if="!open">关</div>`。使用`v-else`不利于后续扩展
+8. 请使用缩写指令,`@`代替`v-on`,`:`代替`v-bind`,`#`代替`v-slot`
+9. 当节点上有`多个属性`时,应对每一个属性进行`换行`。
+10. 在模板中使用`自定义组件`时,应写成`大写驼峰`(参考下方组件命名),而非`小写中横线`。
+
+### 脚本-script
+
+1. `js`中的字符串使用`单引号`包裹,例如:`const user_name = ref('zhangsan')`
+2. 代码不宜写成一坨,要进行合理的`空行`。通常做`相似事情的代码`可连续书写,当代码进行到下一类事情时,需`空行`。例如声明多个变量,可连续书写,当将要声明一个函数时,需`空行`后再进行函数声明。
+3. `关键词`与`操作符`之间要进行合理的`空格`
+4. `注释`要清晰,必要时添加`文档`进行说明。请参考[jsdoc](https://jsdoc.nodejs.cn/)进行注释。
+
+### 样式-style
+
+1. 在样式中不要直接使用`元素选择器`。
+2. 在样式中不要使用 `deep`
+
+## 命名规范
+
+为了`统一风格`,特对于项目中的`命名`进行一些规定。下方给出了一个项目的`src`目录中关键文件的`命名示例`。
+
+```
+src/
+  |- index.js
+  |- App.vue
+  |- assets/
+    |- images/
+      |- site-logo.png
+      |- man.svg
+      |- woman.svg
+    |- audio/
+      |- response-media.mp3
+    |- video/
+      |- movie.mp4
+  |- store/
+    |- index.js
+    |- use-counter.js
+  |- routes/
+    |- index.js
+  |- components/
+    |- account/
+      |- Login.vue
+      |- Register.vue
+    |- product/
+      |- ProductCreateForm.vue
+      |- ProductDetail.vue
+    |- shop-online/
+      |- ShopOnlineConfirmForm.vue
+      |- ShopOnlineStatus.vue
+  |- views/
+    |- Index.vue
+    |- About.vue
+    |- Login.vue
+    |- ProductDetail.vue
+```
+
+### 文件夹名称
+
+`文件夹名称`一律`小写`,用`中横线`分隔。例如:`shop-online`
+
+### 文件名称
+
+除了`组件名`之外,其他类型的文件一律使用`小写英文字母`,使用`中横线`分隔。例如:`response-media.mp3`、`site-logo.png`
+
+### 第三方组件名在模板中的使用
+
+对于`第三方组件`,使用`小写`、`中横线`的方式进行书写。
+
+```vue
+<template>
+  <a-space>
+    <a-button type="primary">Primary</a-button>
+    <a-button>Secondary</a-button>
+    <a-button type="dashed">Dashed</a-button>
+    <a-button type="outline">Outline</a-button>
+    <a-button type="text">Text</a-button>
+  </a-space>
+</template>
+```
+
+### 自定义组件名称
+
+`组件名`使用`驼峰`形式命名,例如:`Index.vue`、`ProductDetail.vue`。
+
+### 项目内自定义组件
+
+对于`项目内`的`自定义组件`,使用`大写`、`驼峰`方式进行书写。
+
+```vue
+<template>
+  <ViewContainer>
+    <ProductDetail :id="product_id"/>
+
+    <PriceHistory />
+  </ViewContainer>
+</template>
+```
+
+### props命名
+
+`props`命名使用`小写`、`下划线`形式命名。例如下方的`props.user_age`、`props.user_name`。
+
+```vue
+<script>
+const props = defineProps({
+  foo: String,
+  user_age: Number,
+  user_name: String
+});
+</script>
+```
+
+### emit命名
+
+`emit`命名使用`小写`、`驼峰`形式,例如:`priceChange`,`messageFinished`。
+
+> 无需加`on`前缀,例如:`onPriceChange`,这是错误做法。
+
+```vue
+<script>
+const emit = defineEmits(['change', 'delete'])
+</script>
+```
+
+### 变量命名
+
+同`props`命名,使用`小写`、`下划线`形式。
+
+```js
+const my_name = ref('张三');
+const user_age = 18;
+const theme_color = 'dark';
+```
+
+### 常量命名
+
+`常量`使用`大写`字母加`下划线`的形式命名。
+
+```js
+const PROJECT_TITLE = '小数智能'; // 项目名称
+
+const EXPIRE_VALUE = 3600; // 过期时间
+```
+
+### 函数命名
+
+`函数`名称同`emit`命名
+
+```js
+function handleClick(){
+
+}
+
+/**
+ * 获取产品的ID
+ * @params {string} id - 产品ID
+ **/
+function getProductInfo(id){
+
+}
+```
+
+### 类命名
+
+`类`使用`大写`、`驼峰`形式命名。
+
+```js
+class Human{
+
+}
+
+class Animals{
+
+}
+
+class ProductOrder{
+
+}
+```
+
+## 关键顺序约定
+
+### 单文件组件顺序
+
+`单文件组件`中区块顺序按照`template`,`script`,`style`顺序进行书写。
+
+```vue
+<template>
+  <div class="container">组件模板</div>
+</template>
+
+<script>
+import { ref } from "vue";
+
+const status = ref(1);
+</script>
+
+<style scoped>
+.container {
+  font-weight: bold;
+}
+</style>
+
+<style>
+
+</style>
+```
+
+### 模板中元素属性的顺序
+
+在模板中为元素绑定属性,需要遵循一定的顺序,大致顺序如下:
+
+1. `v-`开头的指令,`v-if`、`v-show`、`v-for`
+2. `key`、`class`、`style`、`id`、`title`等
+3. 自定义属性,例如: `:age="18"`、`:price="300"`
+4. 事件 `@click`、`@input`、`@change` 等
+
+```vue
+<template>
+  <div 
+    v-if="is_show" 
+    class="news-title"
+    :class="{'disabled': disabled}"
+    title="标题"
+    :age="18"
+    @click="handleTitleClick"
+  >这是新闻的标题</div>
+</template>
+```
+
+### `script`标签内的顺序
+
+在`单文件组件`中,各项顺序大致如下:
+
+1. `import`
+2. `defineProps`
+3. `defineEmits`
+4. `defineExpose`
+5. `ref`、`reactive`、`let`、`const`、`var`等
+6. `computed`
+7. `watch`
+8. `事件处理`方法
+9. `生命周期钩子`:`onCreated`、`onMounted`、`onUpdated`、`onBeforeUnmount`
+
+### css属性规则的顺序
+
+样式的定义应遵循一定的顺序。
+
+建议遵循以下顺序:
+
+1. 布局定位属性:display / position / float / clear / visibility / overflow
+2. 自身属性:width / height / margin / padding / border / background
+3. 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
+4. 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background:linear-gradient …
+
+> 参考:https://guide.aotu.io/docs/css/code.html#%E5%B1%9E%E6%80%A7%E4%B9%A6%E5%86%99%E9%A1%BA%E5%BA%8F
+
+```css
+.title{
+  display: block;
+  position: relative;
+  float: left;
+  width: 100px;
+  height: 100px;
+  margin: 0 10px;
+  padding: 20px 0;
+  font-family: Arial, 'Helvetica Neue', Helvetica, sans-serif;
+  color: #333;
+  background: rgba(0,0,0,.5);
+  -webkit-border-radius: 10px;
+  -moz-border-radius: 10px;
+  -o-border-radius: 10px;
+  -ms-border-radius: 10px;
+  border-radius: 10px;
+}
+```

+ 587 - 0
electron.main copy.js

@@ -0,0 +1,587 @@
+const { app, Tray, Menu, screen, BrowserWindow, ipcMain } = require('electron');
+const path = require('path');
+const Store = require('electron-store');
+
+
+// 初始化存储实例
+const store = new Store({
+  username: {
+    type: 'string',
+    default: ''
+  },
+  password: {
+    type: 'string',
+    default: ''
+  },
+  token: {
+    type: 'string',
+    default: ''
+  },
+
+  // name: 'auth-data', // 存储文件名称(可选)
+  // encryptionKey: 'your-encryption-key', // 可选加密(生产环境建议设置)
+});
+// store.set('username', '');
+// store.set('password', '');
+// if(store.get())
+store.delete('token');
+// console.log(store.get('username'))
+
+let tray = null;
+let win = null;
+let floatingWindow = null;
+let tooltipWindow = null;
+let smart_win = null;
+let isFloatingWindowVisible = true; // 新增:跟踪悬浮球可见状态
+// 新增:记录登录状态
+let isLoggedIn = false;
+
+// 尝试获取单实例锁
+const gotTheLock = app.requestSingleInstanceLock();
+let iconPath;
+if (app.isPackaged) {
+  iconPath = path.join(path.dirname(app.getPath('exe')), 'resources/tray-icon.png');
+} else {
+  iconPath = path.join(__dirname, '/tray-icon.png');
+}
+function createWindow(w = 1200, h = 800) {
+  win = new BrowserWindow({
+    width: w,
+    height: h,
+    // frame: false,
+    icon: iconPath, // 使用平台特定图标
+    backgroundColor: '#fff',
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: true,  //启用nodejs集成
+      contextIsolation: true,
+      contentSecurityPolicy:
+        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'"
+    }
+  });
+  // 禁用默认菜单栏(保留窗口控制按钮)
+  Menu.setApplicationMenu(null);
+  // 初始设置为登录页模式(固定大小,禁止调整)
+  setLoginWindowMode();
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const { width, height } = primaryDisplay.workAreaSize;
+  // win.setPosition(width - 660 - 900, 100);
+  win.center();
+  if (process.env.NODE_ENV === 'development') {
+    win.loadURL(' http://localhost:5173/');
+  } else {
+    // win.loadFile(path.join(__dirname, 'dist', 'index.html'));
+    win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html')
+  }
+  // 设置窗口标题
+  win.setTitle('智库问答助手');
+  win.on('close', (e) => {
+    if (!app.isQuitting) {
+      e.preventDefault();
+      win.hide();
+    }
+    return false;
+  });
+
+  win.on('closed', function () {
+    win = null;
+  });
+}
+// 设置登录窗口模式(固定大小,禁止调整)
+function setLoginWindowMode() {
+  if (win && !win.isDestroyed()) {
+    win.setResizable(false);       // 禁止调整大小
+    win.setMaximizable(false);     // 禁用最大化按钮
+    win.setMinimumSize(1080, 608);  // 设置最小尺寸(可选)
+    win.setSize(1080, 608);         // 设置为固定尺寸
+    win.center();                  // 窗口居中
+    win.setTitle('智库问答助手');
+    isLoggedIn = false;
+  }
+}
+
+// 设置主窗口模式(可调整大小,有最小限制)
+function setMainWindowMode() {
+  if (win && !win.isDestroyed()) {
+    win.setResizable(true);        // 允许调整大小
+    win.setMaximizable(true);      // 启用最大化按钮
+    win.setMinimumSize(1200, 800); // 设置最小尺寸
+    win.setTitle('智库问答助手');
+    isLoggedIn = true;
+  }
+}
+
+
+// 创建快捷对话窗口
+function createSmartWindow() {
+  smart_win = new BrowserWindow({
+    width: 520,
+    height: 110,
+    // maxHeight: 500,
+    frame: false,
+    icon: iconPath, // 使用平台特定图标
+    resizable: false, // 禁止调整窗口大小
+    maximizable: false, // 禁止最大化
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: true,
+      contextIsolation: true,
+      contentSecurityPolicy:
+        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'"
+    }
+  });
+  // 禁用默认菜单栏(保留窗口控制按钮)
+  Menu.setApplicationMenu(null);
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const { width, height } = primaryDisplay.workAreaSize;
+  smart_win.setPosition(width - 660, 100);
+  if (process.env.NODE_ENV === 'development') {
+    smart_win.loadURL('http://localhost:5173/#/smart');
+  } else {
+    // smart_win.loadFile(path.join(__dirname, 'dist', 'index.html'), {
+    //   hash: '/smart'
+    // });
+    smart_win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/smart')
+  }
+
+}
+
+// 新增:设置悬浮窗事件监听
+function setupFloatingWindowEvents() {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    // 移除旧的事件监听器(如果存在)
+    floatingWindow.removeAllListeners('closed');
+
+    // 添加关闭事件处理
+    floatingWindow.on('closed', () => {
+      floatingWindow = null;
+    });
+  }
+}
+
+// 新增:切换悬浮球可见性
+function toggleFloatingWindow() {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    if (isFloatingWindowVisible) {
+      smart_win?.close()
+      // smart_win?.destroy()
+      floatingWindow?.hide();
+      hideTooltip(); // 隐藏可能显示的工具提示
+    } else {
+      floatingWindow?.show();
+      // 重新设置悬浮窗事件监听
+      setupFloatingWindowEvents();
+    }
+    isFloatingWindowVisible = !isFloatingWindowVisible;
+    updateTrayMenu(); // 更新托盘菜单文本
+  }
+}
+
+// 新增:更新托盘菜单
+function updateTrayMenu(show_float_item = true) {
+  if (!tray) return;
+  const menu_list = [
+    {
+      label: '打开',
+      click: () => {
+        if (win && !win.isDestroyed()) {
+          if (win.isMinimized()) win.restore();
+          win.show();
+          win.focus();
+
+        } else {
+
+          createWindow();
+
+        }
+      }
+    },
+    // {
+    //   label: isFloatingWindowVisible ? '隐藏悬浮球' : '显示悬浮球',
+    //   click: toggleFloatingWindow
+    // },
+    {
+      label: '退出',
+      click: () => {
+        app.isQuitting = true;
+        if (floatingWindow) floatingWindow.destroy();
+        app.quit();
+      }
+    }
+  ]
+  const float_item = {
+    label: isFloatingWindowVisible ? '隐藏悬浮球' : '显示悬浮球',
+    click: toggleFloatingWindow
+  }
+
+  if (show_float_item) {
+    menu_list.splice(1, 0, float_item)
+  }
+
+  const contextMenu = Menu.buildFromTemplate(menu_list);
+
+
+
+  tray.setContextMenu(contextMenu);
+}
+
+// 创建系统托盘
+function createTray() {
+  let iconPath;
+  if (app.isPackaged) {
+    iconPath = path.join(path.dirname(app.getPath('exe')), 'resources/tray-icon.png');
+  } else {
+    iconPath = path.join(__dirname, '/tray-icon.png');
+  }
+  tray = new Tray(iconPath);
+
+  updateTrayMenu(); // 使用函数设置菜单
+
+  tray.setToolTip('智库问答助手');
+
+  tray.on('click', () => {
+    if (win && !win.isDestroyed()) {
+      if (win.isMinimized()) win.restore();
+      win.show();
+      win.focus();
+    } else {
+      createWindow();
+    }
+  });
+}
+
+// 创建悬浮窗
+function createFloatingWindow() {
+  floatingWindow = new BrowserWindow({
+    width: 42,
+    height: 42,
+    frame: false,
+    transparent: false,
+    alwaysOnTop: true,
+    skipTaskbar: true,
+    resizable: false,
+    backgroundColor: '#00000000', // 强制有颜色背景,否则 tooltip 不触发
+    hasShadow: false,
+    transparent: true,
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: true,
+      contextIsolation: true
+    },
+    type: 'desktop'
+  });
+  floatingWindow.setAlwaysOnTop(true, 'screen-saver'); // 在macOS有效
+
+  if (process.env.NODE_ENV === 'development') {
+    floatingWindow.loadURL('http://localhost:5173/#/floating');
+  } else {
+    // floatingWindow.loadFile(path.join(__dirname, 'dist', 'index.html'), {
+    //   hash: '/floating'
+    // });
+    floatingWindow.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/floating')
+  }
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const { width, height } = primaryDisplay.workAreaSize;
+  floatingWindow.setPosition(width - 50, height - 200);
+
+  // 设置悬浮窗事件监听
+  setupFloatingWindowEvents();
+}
+// 提示窗口
+function showTooltip(adsorbedPosition, x, y) {
+  if (tooltipWindow) return;
+
+  let tooltipX;
+  if (adsorbedPosition === 0) {
+    // 悬浮球吸附在左侧,tooltip 显示在右侧
+    tooltipX = x + 50;
+  } else {
+    // 悬浮球吸附在右侧,tooltip 显示在左侧
+    tooltipX = x - 125;
+  }
+
+  tooltipWindow = new BrowserWindow({
+    width: 120,
+    height: 40,
+    x: tooltipX,
+    y: y + 5,
+    frame: false,
+    alwaysOnTop: true,
+    skipTaskbar: true,
+    resizable: false,
+    transparent: true,
+    hasShadow: false,
+    focusable: false,
+    webPreferences: {
+      nodeIntegration: true,
+      contextIsolation: false
+    }
+  });
+
+  if (process.env.NODE_ENV === 'development') {
+    tooltipWindow.loadURL(' http://localhost:5173/#/tips');
+  } else {
+    // tooltipWindow.loadFile(path.join(__dirname, 'dist', 'index.html'), {
+    //   hash: '/tips'
+    // });
+    tooltipWindow.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/tips')
+  }
+
+  tooltipWindow.once('ready-to-show', () => {
+    tooltipWindow?.showInactive();
+  });
+}
+
+function hideTooltip() {
+  if (tooltipWindow) {
+    tooltipWindow.close();
+    tooltipWindow = null;
+  }
+}
+
+// 监听打开窗口事件
+ipcMain.on('open-window', () => {
+  if (win && !win.isDestroyed()) {
+    if (win.isMinimized()) win.restore();
+    win.show();
+    win.focus();
+  } else {
+    createWindow();
+  }
+});
+// 监听窗口大小变化时间
+ipcMain.on('resize-main-window', (event, width, height) => {
+  if (win && !win.isDestroyed()) {
+    // 1. 先退出全屏状态(如果是全屏)
+    if (win.isFullScreen()) {
+      win.setFullScreen(false);
+
+      // 等待全屏状态变更完成后再调整大小
+      win.once('leave-full-screen', () => {
+        adjustWindowSize(width, height);
+      });
+    }
+    // 2. 再恢复窗口(如果是最大化)
+    else if (win.isMaximized()) {
+      win.unmaximize();
+
+      // 等待窗口恢复后再调整大小
+      win.once('unmaximize', () => {
+        adjustWindowSize(width, height);
+      });
+    }
+    // 3. 直接调整大小(普通状态)
+    else {
+      adjustWindowSize(width, height);
+    }
+  } else {
+    createWindow(width, height);
+  }
+});
+
+// 提取调整窗口大小的公共逻辑
+function adjustWindowSize(width, height) {
+  win.setSize(width, height);
+  win.center();
+}
+ipcMain.on('open-smart-window', () => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    if (smart_win.isMinimized()) smart_win.restore();
+    smart_win.show();
+    smart_win.focus();
+  } else {
+    createSmartWindow();
+  }
+});
+
+ipcMain.on('toggle-smart-window', () => {
+
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.hide();
+    smart_win.close();
+    smart_win.destroy()
+    smart_win = null
+  } else {
+
+    createSmartWindow();
+    smart_win.focus();
+  }
+});
+
+ipcMain.on('close-smart-window', () => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.close();
+  }
+});
+
+ipcMain.on('resize-smart-window', (event, height) => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    // 获取当前窗口宽度
+    const [width] = smart_win.getSize();
+
+    // 设置新的窗口大小(保持宽度不变,修改高度)
+    smart_win.setSize(width, height);
+  }
+});
+
+ipcMain.on('set-float-window-position', (event, x, y) => {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    floatingWindow.setBounds({ x, y, width: 50, height: 50 });
+  }
+});
+
+ipcMain.handle('get-float-window-position', () => {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    const [x, y] = floatingWindow.getPosition();
+    return { x, y };
+  }
+  return { x: 0, y: 0 };
+});
+
+ipcMain.handle('get-smart-window-position', () => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    const [x, y] = smart_win.getPosition();
+    return { x, y };
+  }
+  return { x: 0, y: 0 };
+});
+
+ipcMain.on('set-smart-window-position', (event, x, y) => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.setBounds({ x, y });
+  }
+});
+
+ipcMain.on('show-tooltip', (event, adsorbedPosition) => {
+  if (!floatingWindow) return;
+  const [x, y] = floatingWindow.getPosition();
+  showTooltip(adsorbedPosition, x, y);
+});
+
+ipcMain.on('hide-tooltip', hideTooltip);
+
+ipcMain.on('hide-tray-float-window', (event) => {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+
+    if (isFloatingWindowVisible) {
+
+      if (smart_win) {
+        smart_win?.close()
+        // smart_win?.destroy()
+        floatingWindow?.hide();
+        hideTooltip(); // 隐藏可能显示的工具提示
+      } else {
+        floatingWindow?.close()
+      }
+    }
+    updateTrayMenu(false); // 更新托盘菜单文本
+  }
+})
+ipcMain.on('show-tray-float-window', (event) => {
+  createFloatingWindow();
+  floatingWindow.focus();
+  isFloatingWindowVisible = true;
+  updateTrayMenu(); // 更新托盘菜单文本
+
+})
+
+// 新增:监听登录状态变化
+ipcMain.on('set-login-state', (event, loggedIn) => {
+  if (loggedIn) {
+    setLoginWindowMode();
+  } else {
+    setMainWindowMode();
+  }
+});
+// 封装存储操作
+// 保存认证信息
+ipcMain.handle('save-auth', (event, username, password, token) => {
+  console.log('Saving auth:', username, password, token);
+  try {
+    console.log('Saving auth:', username, password, token);
+    store.set('username', username);
+    store.set('password', password);
+    store.set('token', token);
+    return { success: true, message: '认证信息保存成功' };
+  } catch (error) {
+    console.error('Failed to save auth:', error);
+    return new Error('保存认证信息失败: ' + error.message);
+  }
+
+});
+
+// 获取用户名
+ipcMain.handle('get-username', () => {
+
+  return store.get('username') || '';
+
+});
+// 获取密码
+ipcMain.handle('get-password', () => {
+
+  return store.get('password') || '';
+
+});
+
+// 获取 Token
+ipcMain.handle('get-token', () => {
+
+  return store.get('token') || '';
+});
+
+// 删除认证信息
+ipcMain.handle('clear-auth', () => {
+
+  // store.delete('username');n
+  store.delete('token');
+  // store.delete('password')
+});
+
+ipcMain.on('logout', () => {
+  updateTrayMenu(false)
+
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.destroy();
+    smart_win = null;
+  }
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    floatingWindow.destroy();
+    floatingWindow = null;
+  }
+});
+
+// 显示主窗口
+function showMainWindow() {
+  if (win && !win.isDestroyed()) {
+    if (win.isMinimized()) win.restore();
+    win.show();
+    win.focus();
+  } else {
+    createWindow();
+  }
+}
+
+
+
+if (!gotTheLock) {
+  // 如果没有获取到锁,说明已经有一个实例在运行,直接退出当前实例
+  app.quit();
+} else {
+  app.whenReady().then(() => {
+
+    createWindow();
+    createTray();
+    createFloatingWindow();
+
+    app.on('activate', function () {
+      if (BrowserWindow.getAllWindows().length === 0) createWindow();
+    });
+  });
+
+  app.on('window-all-closed', function () {
+    if (process.platform !== 'darwin') app.quit();
+  });
+
+  // 再次启动时,如果有主窗口,则显示主窗口
+  app.on('second-instance', showMainWindow);
+}

+ 595 - 0
electron.main.js

@@ -0,0 +1,595 @@
+const { app, Tray, Menu, screen, BrowserWindow, ipcMain } = require('electron');
+const path = require('path');
+const Store = require('electron-store');
+
+
+// 初始化存储实例
+const store = new Store({
+  username: {
+    type: 'string',
+    default: ''
+  },
+  password: {
+    type: 'string',
+    default: ''
+  },
+  token: {
+    type: 'string',
+    default: ''
+  },
+
+  // name: 'auth-data', // 存储文件名称(可选)
+  // encryptionKey: 'your-encryption-key', // 可选加密(生产环境建议设置)
+});
+// store.set('username', '');
+// store.set('password', '');
+// if(store.get())
+if (store.get('token')) {
+  store.delete('token');
+}
+
+// console.log(store.get('username'))
+
+let tray = null;
+let win = null;
+let floatingWindow = null;
+let tooltipWindow = null;
+let smart_win = null;
+let isFloatingWindowVisible = true; // 新增:跟踪悬浮球可见状态
+// 新增:记录登录状态
+let isLoggedIn = false;
+
+// 尝试获取单实例锁
+const gotTheLock = app.requestSingleInstanceLock();
+let iconPath;
+if (app.isPackaged) {
+  iconPath = path.join(path.dirname(app.getPath('exe')), 'resources/tray-icon.png');
+} else {
+  iconPath = path.join(__dirname, '/tray-icon.png');
+}
+function createWindow(w = 1200, h = 800) {
+  win = new BrowserWindow({
+    width: w,
+    height: h,
+    // frame: false,
+    icon: iconPath, // 使用平台特定图标
+    backgroundColor: '#fff',
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: true,  //启用nodejs集成
+      contextIsolation: true,
+      contentSecurityPolicy:
+        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'"
+    }
+  });
+  // 禁用默认菜单栏(保留窗口控制按钮)
+  Menu.setApplicationMenu(null);
+  // 初始设置为登录页模式(固定大小,禁止调整)
+  setLoginWindowMode();
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const { width, height } = primaryDisplay.workAreaSize;
+  // win.setPosition(width - 660 - 900, 100);
+  win.center();
+  if (process.env.NODE_ENV === 'development') {
+    win.loadURL(' http://localhost:5173/');
+  } else {
+    if (isLoggedIn) {
+      win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/conversation?id=znwd')
+    } else {
+      win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/login')
+    }
+    // win.loadFile(path.join(__dirname, 'dist', 'index.html'));
+
+  }
+  // 设置窗口标题
+  win.setTitle('智库问答助手');
+  win.on('close', (e) => {
+    if (!app.isQuitting) {
+      e.preventDefault();
+      win.hide();
+    }
+    return false;
+  });
+
+  win.on('closed', function () {
+    win = null;
+  });
+}
+// 设置登录窗口模式(固定大小,禁止调整)
+function setLoginWindowMode() {
+  if (win && !win.isDestroyed()) {
+    win.setResizable(false);       // 禁止调整大小
+    win.setMaximizable(false);     // 禁用最大化按钮
+    win.setMinimumSize(1080, 608);  // 设置最小尺寸(可选)
+    win.setSize(1080, 608);         // 设置为固定尺寸
+    win.center();                  // 窗口居中
+    win.setTitle('智库问答助手');
+    isLoggedIn = false;
+  }
+}
+
+// 设置主窗口模式(可调整大小,有最小限制)
+function setMainWindowMode() {
+  if (win && !win.isDestroyed()) {
+    win.setResizable(true);        // 允许调整大小
+    win.setMaximizable(true);      // 启用最大化按钮
+    win.setMinimumSize(1200, 800); // 设置最小尺寸
+    win.setTitle('智库问答助手');
+    isLoggedIn = true;
+  }
+}
+
+
+// 创建快捷对话窗口
+function createSmartWindow() {
+  smart_win = new BrowserWindow({
+    width: 520,
+    height: 110,
+    // maxHeight: 500,
+    frame: false,
+    icon: iconPath, // 使用平台特定图标
+    resizable: false, // 禁止调整窗口大小
+    maximizable: false, // 禁止最大化
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: true,
+      contextIsolation: true,
+      contentSecurityPolicy:
+        "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'"
+    }
+  });
+  // 禁用默认菜单栏(保留窗口控制按钮)
+  Menu.setApplicationMenu(null);
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const { width, height } = primaryDisplay.workAreaSize;
+  smart_win.setPosition(width - 660, 100);
+  if (process.env.NODE_ENV === 'development') {
+    smart_win.loadURL('http://localhost:5173/#/smart');
+  } else {
+    // smart_win.loadFile(path.join(__dirname, 'dist', 'index.html'), {
+    //   hash: '/smart'
+    // });
+    smart_win.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/smart')
+  }
+
+}
+
+// 新增:设置悬浮窗事件监听
+function setupFloatingWindowEvents() {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    // 移除旧的事件监听器(如果存在)
+    floatingWindow.removeAllListeners('closed');
+
+    // 添加关闭事件处理
+    floatingWindow.on('closed', () => {
+      floatingWindow = null;
+    });
+  }
+}
+
+// 新增:切换悬浮球可见性
+function toggleFloatingWindow() {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    if (isFloatingWindowVisible) {
+      smart_win?.close()
+      // smart_win?.destroy()
+      floatingWindow?.hide();
+      hideTooltip(); // 隐藏可能显示的工具提示
+    } else {
+      floatingWindow?.show();
+      // 重新设置悬浮窗事件监听
+      setupFloatingWindowEvents();
+    }
+    isFloatingWindowVisible = !isFloatingWindowVisible;
+    updateTrayMenu(); // 更新托盘菜单文本
+  }
+}
+
+// 新增:更新托盘菜单
+function updateTrayMenu(show_float_item = true) {
+  if (!tray) return;
+  const menu_list = [
+    {
+      label: '打开',
+      click: () => {
+        if (win && !win.isDestroyed()) {
+          if (win.isMinimized()) win.restore();
+          win.show();
+          win.focus();
+
+        } else {
+
+          createWindow();
+
+        }
+      }
+    },
+    // {
+    //   label: isFloatingWindowVisible ? '隐藏悬浮球' : '显示悬浮球',
+    //   click: toggleFloatingWindow
+    // },
+    {
+      label: '退出',
+      click: () => {
+        app.isQuitting = true;
+        if (floatingWindow) floatingWindow.destroy();
+        app.quit();
+      }
+    }
+  ]
+  const float_item = {
+    label: isFloatingWindowVisible ? '隐藏悬浮球' : '显示悬浮球',
+    click: toggleFloatingWindow
+  }
+
+  if (show_float_item) {
+    menu_list.splice(1, 0, float_item)
+  }
+
+  const contextMenu = Menu.buildFromTemplate(menu_list);
+
+
+
+  tray.setContextMenu(contextMenu);
+}
+
+// 创建系统托盘
+function createTray() {
+  let iconPath;
+  if (app.isPackaged) {
+    iconPath = path.join(path.dirname(app.getPath('exe')), 'resources/tray-icon.png');
+  } else {
+    iconPath = path.join(__dirname, '/tray-icon.png');
+  }
+  tray = new Tray(iconPath);
+
+  updateTrayMenu(); // 使用函数设置菜单
+
+  tray.setToolTip('智库问答助手');
+
+  tray.on('click', () => {
+    if (win && !win.isDestroyed()) {
+      if (win.isMinimized()) win.restore();
+      win.show();
+      win.focus();
+    } else {
+      createWindow();
+    }
+  });
+}
+
+// 创建悬浮窗
+function createFloatingWindow() {
+  floatingWindow = new BrowserWindow({
+    width: 42,
+    height: 42,
+    frame: false,
+    transparent: false,
+    alwaysOnTop: true,
+    skipTaskbar: true,
+    resizable: false,
+    backgroundColor: '#00000000', // 强制有颜色背景,否则 tooltip 不触发
+    hasShadow: false,
+    transparent: true,
+    webPreferences: {
+      preload: path.join(__dirname, 'preload.js'),
+      nodeIntegration: true,
+      contextIsolation: true
+    },
+    type: 'desktop'
+  });
+  floatingWindow.setAlwaysOnTop(true, 'screen-saver'); // 在macOS有效
+
+  if (process.env.NODE_ENV === 'development') {
+    floatingWindow.loadURL('http://localhost:5173/#/floating');
+  } else {
+    // floatingWindow.loadFile(path.join(__dirname, 'dist', 'index.html'), {
+    //   hash: '/floating'
+    // });
+    floatingWindow.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/floating')
+  }
+  const primaryDisplay = screen.getPrimaryDisplay();
+  const { width, height } = primaryDisplay.workAreaSize;
+  floatingWindow.setPosition(width - 50, height - 200);
+
+  // 设置悬浮窗事件监听
+  setupFloatingWindowEvents();
+}
+// 提示窗口
+function showTooltip(adsorbedPosition, x, y) {
+  if (tooltipWindow) return;
+
+  let tooltipX;
+  if (adsorbedPosition === 0) {
+    // 悬浮球吸附在左侧,tooltip 显示在右侧
+    tooltipX = x + 50;
+  } else {
+    // 悬浮球吸附在右侧,tooltip 显示在左侧
+    tooltipX = x - 125;
+  }
+
+  tooltipWindow = new BrowserWindow({
+    width: 120,
+    height: 40,
+    x: tooltipX,
+    y: y + 5,
+    frame: false,
+    alwaysOnTop: true,
+    skipTaskbar: true,
+    resizable: false,
+    transparent: true,
+    hasShadow: false,
+    focusable: false,
+    webPreferences: {
+      nodeIntegration: true,
+      contextIsolation: false
+    }
+  });
+
+  if (process.env.NODE_ENV === 'development') {
+    tooltipWindow.loadURL(' http://localhost:5173/#/tips');
+  } else {
+    // tooltipWindow.loadFile(path.join(__dirname, 'dist', 'index.html'), {
+    //   hash: '/tips'
+    // });
+    tooltipWindow.loadURL('http://25.214.216.111:9000/pdwyzz/ai-znwd/dist/index.html#/tips')
+  }
+
+  tooltipWindow.once('ready-to-show', () => {
+    tooltipWindow?.showInactive();
+  });
+}
+
+function hideTooltip() {
+  if (tooltipWindow) {
+    tooltipWindow.close();
+    tooltipWindow = null;
+  }
+}
+
+// 监听打开窗口事件
+ipcMain.on('open-window', () => {
+  if (win && !win.isDestroyed()) {
+    if (win.isMinimized()) win.restore();
+    win.show();
+    win.focus();
+  } else {
+    createWindow();
+  }
+});
+// 监听窗口大小变化时间
+ipcMain.on('resize-main-window', (event, width, height) => {
+  if (win && !win.isDestroyed()) {
+    // 1. 先退出全屏状态(如果是全屏)
+    if (win.isFullScreen()) {
+      win.setFullScreen(false);
+
+      // 等待全屏状态变更完成后再调整大小
+      win.once('leave-full-screen', () => {
+        adjustWindowSize(width, height);
+      });
+    }
+    // 2. 再恢复窗口(如果是最大化)
+    else if (win.isMaximized()) {
+      win.unmaximize();
+
+      // 等待窗口恢复后再调整大小
+      win.once('unmaximize', () => {
+        adjustWindowSize(width, height);
+      });
+    }
+    // 3. 直接调整大小(普通状态)
+    else {
+      adjustWindowSize(width, height);
+    }
+  } else {
+    createWindow(width, height);
+  }
+});
+
+// 提取调整窗口大小的公共逻辑
+function adjustWindowSize(width, height) {
+  win.setSize(width, height);
+  win.center();
+}
+ipcMain.on('open-smart-window', () => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    if (smart_win.isMinimized()) smart_win.restore();
+    smart_win.show();
+    smart_win.focus();
+  } else {
+    createSmartWindow();
+  }
+});
+
+ipcMain.on('toggle-smart-window', () => {
+
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.hide();
+    smart_win.close();
+    smart_win.destroy()
+    smart_win = null
+  } else {
+
+    createSmartWindow();
+    smart_win.focus();
+  }
+});
+
+ipcMain.on('close-smart-window', () => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.close();
+  }
+});
+
+ipcMain.on('resize-smart-window', (event, height) => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    // 获取当前窗口宽度
+    const [width] = smart_win.getSize();
+
+    // 设置新的窗口大小(保持宽度不变,修改高度)
+    smart_win.setSize(width, height);
+  }
+});
+
+ipcMain.on('set-float-window-position', (event, x, y) => {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    floatingWindow.setBounds({ x, y, width: 50, height: 50 });
+  }
+});
+
+ipcMain.handle('get-float-window-position', () => {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    const [x, y] = floatingWindow.getPosition();
+    return { x, y };
+  }
+  return { x: 0, y: 0 };
+});
+
+ipcMain.handle('get-smart-window-position', () => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    const [x, y] = smart_win.getPosition();
+    return { x, y };
+  }
+  return { x: 0, y: 0 };
+});
+
+ipcMain.on('set-smart-window-position', (event, x, y) => {
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.setBounds({ x, y });
+  }
+});
+
+ipcMain.on('show-tooltip', (event, adsorbedPosition) => {
+  if (!floatingWindow) return;
+  const [x, y] = floatingWindow.getPosition();
+  showTooltip(adsorbedPosition, x, y);
+});
+
+ipcMain.on('hide-tooltip', hideTooltip);
+
+ipcMain.on('hide-tray-float-window', (event) => {
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+
+    if (isFloatingWindowVisible) {
+
+      if (smart_win) {
+        smart_win?.close()
+        // smart_win?.destroy()
+        floatingWindow?.hide();
+        hideTooltip(); // 隐藏可能显示的工具提示
+      } else {
+        floatingWindow?.close()
+      }
+    }
+    updateTrayMenu(false); // 更新托盘菜单文本
+  }
+})
+ipcMain.on('show-tray-float-window', (event) => {
+  createFloatingWindow();
+  floatingWindow.focus();
+  isFloatingWindowVisible = true;
+  updateTrayMenu(); // 更新托盘菜单文本
+
+})
+
+// 新增:监听登录状态变化
+ipcMain.on('set-login-state', (event, loggedIn) => {
+  if (loggedIn) {
+    setLoginWindowMode();
+  } else {
+    setMainWindowMode();
+  }
+});
+// 封装存储操作
+// 保存认证信息
+ipcMain.handle('save-auth', (event, username, password, token) => {
+  console.log('Saving auth:', username, password, token);
+  try {
+    console.log('Saving auth:', username, password, token);
+    store.set('username', username);
+    store.set('password', password);
+    store.set('token', token);
+    return { success: true, message: '认证信息保存成功' };
+  } catch (error) {
+    console.error('Failed to save auth:', error);
+    return new Error('保存认证信息失败: ' + error.message);
+  }
+
+});
+
+// 获取用户名
+ipcMain.handle('get-username', () => {
+
+  return store.get('username') || '';
+
+});
+// 获取密码
+ipcMain.handle('get-password', () => {
+
+  return store.get('password') || '';
+
+});
+
+// 获取 Token
+ipcMain.handle('get-token', () => {
+
+  return store.get('token') || '';
+});
+
+// 删除认证信息
+ipcMain.handle('clear-auth', () => {
+
+  // store.delete('username');n
+  store.delete('token');
+  // store.delete('password')
+});
+
+ipcMain.on('logout', () => {
+  updateTrayMenu(false)
+
+  if (smart_win && !smart_win.isDestroyed()) {
+    smart_win.destroy();
+    smart_win = null;
+  }
+  if (floatingWindow && !floatingWindow.isDestroyed()) {
+    floatingWindow.destroy();
+    floatingWindow = null;
+  }
+});
+
+// 显示主窗口
+function showMainWindow() {
+  if (win && !win.isDestroyed()) {
+    if (win.isMinimized()) win.restore();
+    win.show();
+    win.focus();
+  } else {
+    createWindow();
+  }
+}
+
+
+
+if (!gotTheLock) {
+  // 如果没有获取到锁,说明已经有一个实例在运行,直接退出当前实例
+  app.quit();
+} else {
+  app.whenReady().then(() => {
+
+    createWindow();
+    createTray();
+    createFloatingWindow();
+
+    app.on('activate', function () {
+      if (BrowserWindow.getAllWindows().length === 0) createWindow();
+    });
+  });
+
+  app.on('window-all-closed', function () {
+    if (process.platform !== 'darwin') app.quit();
+  });
+
+  // 再次启动时,如果有主窗口,则显示主窗口
+  app.on('second-instance', showMainWindow);
+}

+ 13 - 0
eslint.config.js

@@ -0,0 +1,13 @@
+import pluginVue from "eslint-plugin-vue";
+
+// eslint.config.js
+export default [
+  ...pluginVue.configs["flat/recommended"],
+
+  {
+    rules: {
+      // "no-unused-vars": "error",
+      // "no-undef": "error"
+    }
+  }
+];

+ 60 - 0
floating-icon.html

@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    <!-- 引入 Arco Design 的 CSS CDN -->
+    <link rel="stylesheet" href="https://unpkg.com/@arco-design/web-vue@2.43.0/dist/css/arco.css" />
+    <!-- 引入 Arco Design 的 JavaScript CDN -->
+    <script src="https://unpkg.com/@arco-design/web-vue@2.43.0/dist/arco.min.js"></script>
+    <style>
+      body {
+        background-color: transparent;
+        margin: 0;
+        padding: 0;
+        overflow: hidden;
+      }
+
+      img {
+        width: 100%;
+        height: 100%;
+        overflow: hidden;
+      }
+
+      #prompt {
+        display: none;
+        position: absolute;
+        left: -80px;
+        top: 50%;
+        transform: translateY(-50%);
+      }
+    </style>
+  </head>
+
+  <body>
+    <!-- 替换为你的图标路径 -->
+    <img src="./tray-icon.png" alt="Floating Icon" id="icon" @click="openWindow()" />
+    <div id="prompt">
+      <!-- 使用 Arco Design 的按钮组件 -->
+      问一问
+    </div>
+
+    <script>
+      const icon = document.getElementById('icon');
+      const prompt = document.getElementById('prompt');
+
+      icon.addEventListener('mouseenter', () => {
+        prompt.style.display = 'block';
+      });
+
+      icon.addEventListener('mouseleave', () => {
+        prompt.style.display = 'none';
+      });
+
+      function openWindow() {
+        // 发送消息到主进程打开窗口
+        window.electronAPI.openWindow();
+      }
+    </script>
+  </body>
+</html>

+ 6136 - 0
package-lock.json

@@ -0,0 +1,6136 @@
+{
+  "name": "SmartChat",
+  "version": "1.0.0",
+  "lockfileVersion": 3,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "SmartChat",
+      "version": "1.0.0",
+      "license": "ISC",
+      "dependencies": {
+        "@arco-design/web-vue": "2.56.3",
+        "@microsoft/fetch-event-source": "2.0.1",
+        "@wangeditor/editor": "^5.1.23",
+        "@wangeditor/editor-for-vue": "^5.1.12",
+        "axios": "1.7.8",
+        "clipboard": "2.0.11",
+        "dayjs": "1.11.13",
+        "docx-preview": "0.3.3",
+        "echarts": "^5.6.0",
+        "electron-store": "^8.2.0",
+        "filesize": "10.1.6",
+        "highlight.js": "11.10.0",
+        "js-cookie": "3.0.5",
+        "jsencrypt": "^3.3.1",
+        "marked": "13.0.0",
+        "md5": "2.3.0",
+        "mitt": "3.0.1",
+        "pinia": "2.2.8",
+        "postcss-pxtorem": "^6.1.0",
+        "screenfull": "6.0.2",
+        "vue": "3.5.13",
+        "vue-i18n": "10.0.5",
+        "vue-router": "4.5.0",
+        "wujie-vue3": "1.0.23"
+      },
+      "devDependencies": {
+        "@vitejs/plugin-vue": "5.2.1",
+        "concurrently": "8.2.1",
+        "cross-env": "7.0.3",
+        "electron": "25.3.1",
+        "electron-builder": "23.6.0",
+        "eslint": "9.16.0",
+        "eslint-plugin-vue": "9.32.0",
+        "vite": "5.4.11",
+        "vitepress": "1.5.0",
+        "wait-on": "7.0.1"
+      }
+    },
+    "node_modules/@algolia/autocomplete-core": {
+      "version": "1.17.9",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/autocomplete-plugin-algolia-insights": "1.17.9",
+        "@algolia/autocomplete-shared": "1.17.9"
+      }
+    },
+    "node_modules/@algolia/autocomplete-plugin-algolia-insights": {
+      "version": "1.17.9",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/autocomplete-shared": "1.17.9"
+      },
+      "peerDependencies": {
+        "search-insights": ">= 1 < 3"
+      }
+    },
+    "node_modules/@algolia/autocomplete-preset-algolia": {
+      "version": "1.17.9",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/autocomplete-shared": "1.17.9"
+      },
+      "peerDependencies": {
+        "@algolia/client-search": ">= 4.9.1 < 6",
+        "algoliasearch": ">= 4.9.1 < 6"
+      }
+    },
+    "node_modules/@algolia/autocomplete-shared": {
+      "version": "1.17.9",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "@algolia/client-search": ">= 4.9.1 < 6",
+        "algoliasearch": ">= 4.9.1 < 6"
+      }
+    },
+    "node_modules/@algolia/client-abtesting": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/client-analytics": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/client-common": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/client-insights": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/client-personalization": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/client-query-suggestions": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/client-search": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/ingestion": {
+      "version": "1.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/monitoring": {
+      "version": "1.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/recommend": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/requester-browser-xhr": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/requester-fetch": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@algolia/requester-node-http": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-common": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/@arco-design/color": {
+      "version": "0.4.0",
+      "license": "MIT",
+      "dependencies": {
+        "color": "^3.1.3"
+      }
+    },
+    "node_modules/@arco-design/web-vue": {
+      "version": "2.56.3",
+      "license": "MIT",
+      "dependencies": {
+        "@arco-design/color": "^0.4.0",
+        "b-tween": "^0.3.3",
+        "b-validate": "^1.4.4",
+        "compute-scroll-into-view": "^1.0.17",
+        "dayjs": "^1.10.3",
+        "number-precision": "^1.5.0",
+        "resize-observer-polyfill": "^1.5.1",
+        "scroll-into-view-if-needed": "^2.2.28"
+      },
+      "peerDependencies": {
+        "vue": "^3.1.0"
+      }
+    },
+    "node_modules/@babel/helper-string-parser": {
+      "version": "7.27.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/helper-validator-identifier": {
+      "version": "7.27.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/parser": {
+      "version": "7.27.1",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/types": "^7.27.1"
+      },
+      "bin": {
+        "parser": "bin/babel-parser.js"
+      },
+      "engines": {
+        "node": ">=6.0.0"
+      }
+    },
+    "node_modules/@babel/runtime": {
+      "version": "7.27.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@babel/types": {
+      "version": "7.27.1",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/helper-string-parser": "^7.27.1",
+        "@babel/helper-validator-identifier": "^7.27.1"
+      },
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
+    "node_modules/@docsearch/css": {
+      "version": "3.9.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@docsearch/js": {
+      "version": "3.9.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@docsearch/react": "3.9.0",
+        "preact": "^10.0.0"
+      }
+    },
+    "node_modules/@docsearch/react": {
+      "version": "3.9.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/autocomplete-core": "1.17.9",
+        "@algolia/autocomplete-preset-algolia": "1.17.9",
+        "@docsearch/css": "3.9.0",
+        "algoliasearch": "^5.14.2"
+      },
+      "peerDependencies": {
+        "@types/react": ">= 16.8.0 < 20.0.0",
+        "react": ">= 16.8.0 < 20.0.0",
+        "react-dom": ">= 16.8.0 < 20.0.0",
+        "search-insights": ">= 1 < 3"
+      },
+      "peerDependenciesMeta": {
+        "@types/react": {
+          "optional": true
+        },
+        "react": {
+          "optional": true
+        },
+        "react-dom": {
+          "optional": true
+        },
+        "search-insights": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@esbuild/win32-x64": {
+      "version": "0.21.5",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils": {
+      "version": "4.7.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "eslint-visitor-keys": "^3.4.3"
+      },
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      },
+      "peerDependencies": {
+        "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+      }
+    },
+    "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint-community/regexpp": {
+      "version": "4.12.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+      }
+    },
+    "node_modules/@eslint/config-array": {
+      "version": "0.19.2",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/object-schema": "^2.1.6",
+        "debug": "^4.3.1",
+        "minimatch": "^3.1.2"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/core": {
+      "version": "0.9.1",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@types/json-schema": "^7.0.15"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/eslintrc": {
+      "version": "3.3.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ajv": "^6.12.4",
+        "debug": "^4.3.2",
+        "espree": "^10.0.1",
+        "globals": "^14.0.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": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/@eslint/js": {
+      "version": "9.16.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/object-schema": {
+      "version": "2.1.6",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/plugin-kit": {
+      "version": "0.2.8",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@eslint/core": "^0.13.0",
+        "levn": "^0.4.1"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
+      "version": "0.13.0",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@types/json-schema": "^7.0.15"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      }
+    },
+    "node_modules/@hapi/hoek": {
+      "version": "9.3.0",
+      "dev": true,
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/@hapi/topo": {
+      "version": "5.1.0",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "@hapi/hoek": "^9.0.0"
+      }
+    },
+    "node_modules/@humanfs/core": {
+      "version": "0.19.1",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/@humanfs/node": {
+      "version": "0.16.6",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@humanfs/core": "^0.19.1",
+        "@humanwhocodes/retry": "^0.3.0"
+      },
+      "engines": {
+        "node": ">=18.18.0"
+      }
+    },
+    "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+      "version": "0.3.1",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/module-importer": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=12.22"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@humanwhocodes/retry": {
+      "version": "0.4.2",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=18.18"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/nzakas"
+      }
+    },
+    "node_modules/@iconify-json/simple-icons": {
+      "version": "1.2.33",
+      "dev": true,
+      "license": "CC0-1.0",
+      "dependencies": {
+        "@iconify/types": "*"
+      }
+    },
+    "node_modules/@iconify/types": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@intlify/core-base": {
+      "version": "10.0.5",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/message-compiler": "10.0.5",
+        "@intlify/shared": "10.0.5"
+      },
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      }
+    },
+    "node_modules/@intlify/message-compiler": {
+      "version": "10.0.5",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/shared": "10.0.5",
+        "source-map-js": "^1.0.2"
+      },
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      }
+    },
+    "node_modules/@intlify/shared": {
+      "version": "10.0.5",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      }
+    },
+    "node_modules/@jridgewell/sourcemap-codec": {
+      "version": "1.5.0",
+      "license": "MIT"
+    },
+    "node_modules/@microsoft/fetch-event-source": {
+      "version": "2.0.1",
+      "license": "MIT"
+    },
+    "node_modules/@rollup/rollup-win32-x64-msvc": {
+      "version": "4.40.1",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "os": [
+        "win32"
+      ]
+    },
+    "node_modules/@shikijs/core": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/engine-javascript": "1.29.2",
+        "@shikijs/engine-oniguruma": "1.29.2",
+        "@shikijs/types": "1.29.2",
+        "@shikijs/vscode-textmate": "^10.0.1",
+        "@types/hast": "^3.0.4",
+        "hast-util-to-html": "^9.0.4"
+      }
+    },
+    "node_modules/@shikijs/engine-javascript": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/types": "1.29.2",
+        "@shikijs/vscode-textmate": "^10.0.1",
+        "oniguruma-to-es": "^2.2.0"
+      }
+    },
+    "node_modules/@shikijs/engine-oniguruma": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/types": "1.29.2",
+        "@shikijs/vscode-textmate": "^10.0.1"
+      }
+    },
+    "node_modules/@shikijs/langs": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/types": "1.29.2"
+      }
+    },
+    "node_modules/@shikijs/themes": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/types": "1.29.2"
+      }
+    },
+    "node_modules/@shikijs/transformers": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/core": "1.29.2",
+        "@shikijs/types": "1.29.2"
+      }
+    },
+    "node_modules/@shikijs/types": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/vscode-textmate": "^10.0.1",
+        "@types/hast": "^3.0.4"
+      }
+    },
+    "node_modules/@shikijs/vscode-textmate": {
+      "version": "10.0.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@sideway/address": {
+      "version": "4.1.5",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "@hapi/hoek": "^9.0.0"
+      }
+    },
+    "node_modules/@sideway/formula": {
+      "version": "3.0.1",
+      "dev": true,
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/@sideway/pinpoint": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "BSD-3-Clause"
+    },
+    "node_modules/@transloadit/prettier-bytes": {
+      "version": "0.0.7",
+      "resolved": "https://registry.npmmirror.com/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz",
+      "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA=="
+    },
+    "node_modules/@types/cacheable-request": {
+      "version": "6.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/http-cache-semantics": "*",
+        "@types/keyv": "^3.1.4",
+        "@types/node": "*",
+        "@types/responselike": "^1.0.0"
+      }
+    },
+    "node_modules/@types/debug": {
+      "version": "4.1.12",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/ms": "*"
+      }
+    },
+    "node_modules/@types/estree": {
+      "version": "1.0.7",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/event-emitter": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmmirror.com/@types/event-emitter/-/event-emitter-0.3.5.tgz",
+      "integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ=="
+    },
+    "node_modules/@types/fs-extra": {
+      "version": "9.0.13",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/glob": {
+      "version": "7.2.0",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@types/minimatch": "*",
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/hast": {
+      "version": "3.0.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "*"
+      }
+    },
+    "node_modules/@types/http-cache-semantics": {
+      "version": "4.0.4",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/json-schema": {
+      "version": "7.0.15",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/keyv": {
+      "version": "3.1.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/linkify-it": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/markdown-it": {
+      "version": "14.1.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/linkify-it": "^5",
+        "@types/mdurl": "^2"
+      }
+    },
+    "node_modules/@types/mdast": {
+      "version": "4.0.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "*"
+      }
+    },
+    "node_modules/@types/mdurl": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/minimatch": {
+      "version": "5.1.2",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/@types/ms": {
+      "version": "2.1.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/node": {
+      "version": "22.15.14",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "undici-types": "~6.21.0"
+      }
+    },
+    "node_modules/@types/responselike": {
+      "version": "1.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@types/unist": {
+      "version": "3.0.3",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/web-bluetooth": {
+      "version": "0.0.20",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/yargs": {
+      "version": "17.0.33",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/yargs-parser": "*"
+      }
+    },
+    "node_modules/@types/yargs-parser": {
+      "version": "21.0.3",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/@types/yauzl": {
+      "version": "2.10.3",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "@types/node": "*"
+      }
+    },
+    "node_modules/@ungap/structured-clone": {
+      "version": "1.3.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/@uppy/companion-client": {
+      "version": "2.2.2",
+      "resolved": "https://registry.npmmirror.com/@uppy/companion-client/-/companion-client-2.2.2.tgz",
+      "integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==",
+      "dependencies": {
+        "@uppy/utils": "^4.1.2",
+        "namespace-emitter": "^2.0.1"
+      }
+    },
+    "node_modules/@uppy/core": {
+      "version": "2.3.4",
+      "resolved": "https://registry.npmmirror.com/@uppy/core/-/core-2.3.4.tgz",
+      "integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==",
+      "dependencies": {
+        "@transloadit/prettier-bytes": "0.0.7",
+        "@uppy/store-default": "^2.1.1",
+        "@uppy/utils": "^4.1.3",
+        "lodash.throttle": "^4.1.1",
+        "mime-match": "^1.0.2",
+        "namespace-emitter": "^2.0.1",
+        "nanoid": "^3.1.25",
+        "preact": "^10.5.13"
+      }
+    },
+    "node_modules/@uppy/store-default": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/@uppy/store-default/-/store-default-2.1.1.tgz",
+      "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ=="
+    },
+    "node_modules/@uppy/utils": {
+      "version": "4.1.3",
+      "resolved": "https://registry.npmmirror.com/@uppy/utils/-/utils-4.1.3.tgz",
+      "integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==",
+      "dependencies": {
+        "lodash.throttle": "^4.1.1"
+      }
+    },
+    "node_modules/@uppy/xhr-upload": {
+      "version": "2.1.3",
+      "resolved": "https://registry.npmmirror.com/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz",
+      "integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==",
+      "dependencies": {
+        "@uppy/companion-client": "^2.2.2",
+        "@uppy/utils": "^4.1.2",
+        "nanoid": "^3.1.25"
+      },
+      "peerDependencies": {
+        "@uppy/core": "^2.3.3"
+      }
+    },
+    "node_modules/@vitejs/plugin-vue": {
+      "version": "5.2.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "peerDependencies": {
+        "vite": "^5.0.0 || ^6.0.0",
+        "vue": "^3.2.25"
+      }
+    },
+    "node_modules/@vue/compiler-core": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.25.3",
+        "@vue/shared": "3.5.13",
+        "entities": "^4.5.0",
+        "estree-walker": "^2.0.2",
+        "source-map-js": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/compiler-dom": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-core": "3.5.13",
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/compiler-sfc": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/parser": "^7.25.3",
+        "@vue/compiler-core": "3.5.13",
+        "@vue/compiler-dom": "3.5.13",
+        "@vue/compiler-ssr": "3.5.13",
+        "@vue/shared": "3.5.13",
+        "estree-walker": "^2.0.2",
+        "magic-string": "^0.30.11",
+        "postcss": "^8.4.48",
+        "source-map-js": "^1.2.0"
+      }
+    },
+    "node_modules/@vue/compiler-ssr": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.13",
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/devtools-api": {
+      "version": "6.6.4",
+      "license": "MIT"
+    },
+    "node_modules/@vue/devtools-kit": {
+      "version": "7.7.6",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-shared": "^7.7.6",
+        "birpc": "^2.3.0",
+        "hookable": "^5.5.3",
+        "mitt": "^3.0.1",
+        "perfect-debounce": "^1.0.0",
+        "speakingurl": "^14.0.1",
+        "superjson": "^2.2.2"
+      }
+    },
+    "node_modules/@vue/devtools-shared": {
+      "version": "7.7.6",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "rfdc": "^1.4.1"
+      }
+    },
+    "node_modules/@vue/reactivity": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/runtime-core": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.13",
+        "@vue/shared": "3.5.13"
+      }
+    },
+    "node_modules/@vue/runtime-dom": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/reactivity": "3.5.13",
+        "@vue/runtime-core": "3.5.13",
+        "@vue/shared": "3.5.13",
+        "csstype": "^3.1.3"
+      }
+    },
+    "node_modules/@vue/server-renderer": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-ssr": "3.5.13",
+        "@vue/shared": "3.5.13"
+      },
+      "peerDependencies": {
+        "vue": "3.5.13"
+      }
+    },
+    "node_modules/@vue/shared": {
+      "version": "3.5.13",
+      "license": "MIT"
+    },
+    "node_modules/@vueuse/core": {
+      "version": "11.3.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/web-bluetooth": "^0.0.20",
+        "@vueuse/metadata": "11.3.0",
+        "@vueuse/shared": "11.3.0",
+        "vue-demi": ">=0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/core/node_modules/vue-demi": {
+      "version": "0.14.10",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vueuse/integrations": {
+      "version": "11.3.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vueuse/core": "11.3.0",
+        "@vueuse/shared": "11.3.0",
+        "vue-demi": ">=0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "async-validator": "^4",
+        "axios": "^1",
+        "change-case": "^5",
+        "drauu": "^0.4",
+        "focus-trap": "^7",
+        "fuse.js": "^7",
+        "idb-keyval": "^6",
+        "jwt-decode": "^4",
+        "nprogress": "^0.2",
+        "qrcode": "^1.5",
+        "sortablejs": "^1",
+        "universal-cookie": "^7"
+      },
+      "peerDependenciesMeta": {
+        "async-validator": {
+          "optional": true
+        },
+        "axios": {
+          "optional": true
+        },
+        "change-case": {
+          "optional": true
+        },
+        "drauu": {
+          "optional": true
+        },
+        "focus-trap": {
+          "optional": true
+        },
+        "fuse.js": {
+          "optional": true
+        },
+        "idb-keyval": {
+          "optional": true
+        },
+        "jwt-decode": {
+          "optional": true
+        },
+        "nprogress": {
+          "optional": true
+        },
+        "qrcode": {
+          "optional": true
+        },
+        "sortablejs": {
+          "optional": true
+        },
+        "universal-cookie": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vueuse/integrations/node_modules/vue-demi": {
+      "version": "0.14.10",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@vueuse/metadata": {
+      "version": "11.3.0",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/shared": {
+      "version": "11.3.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "vue-demi": ">=0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/@vueuse/shared/node_modules/vue-demi": {
+      "version": "0.14.10",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/@wangeditor/basic-modules": {
+      "version": "1.1.7",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/basic-modules/-/basic-modules-1.1.7.tgz",
+      "integrity": "sha512-cY9CPkLJaqF05STqfpZKWG4LpxTMeGSIIF1fHvfm/mz+JXatCagjdkbxdikOuKYlxDdeqvOeBmsUBItufDLXZg==",
+      "dependencies": {
+        "is-url": "^1.2.4"
+      },
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "lodash.throttle": "^4.1.1",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/code-highlight": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/code-highlight/-/code-highlight-1.0.3.tgz",
+      "integrity": "sha512-iazHwO14XpCuIWJNTQTikqUhGKyqj+dUNWJ9288Oym9M2xMVHvnsOmDU2sgUDWVy+pOLojReMPgXCsvvNlOOhw==",
+      "dependencies": {
+        "prismjs": "^1.23.0"
+      },
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/core": {
+      "version": "1.1.19",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/core/-/core-1.1.19.tgz",
+      "integrity": "sha512-KevkB47+7GhVszyYF2pKGKtCSj/YzmClsD03C3zTt+9SR2XWT5T0e3yQqg8baZpcMvkjs1D8Dv4fk8ok/UaS2Q==",
+      "dependencies": {
+        "@types/event-emitter": "^0.3.3",
+        "event-emitter": "^0.3.5",
+        "html-void-elements": "^2.0.0",
+        "i18next": "^20.4.0",
+        "scroll-into-view-if-needed": "^2.2.28",
+        "slate-history": "^0.66.0"
+      },
+      "peerDependencies": {
+        "@uppy/core": "^2.1.1",
+        "@uppy/xhr-upload": "^2.0.3",
+        "dom7": "^3.0.0",
+        "is-hotkey": "^0.2.0",
+        "lodash.camelcase": "^4.3.0",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.debounce": "^4.0.8",
+        "lodash.foreach": "^4.5.0",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "lodash.toarray": "^4.4.0",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/core/node_modules/html-void-elements": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/html-void-elements/-/html-void-elements-2.0.1.tgz",
+      "integrity": "sha512-0quDb7s97CfemeJAnW9wC0hw78MtW7NU3hqtCD75g2vFlDLt36llsYD7uB7SUzojLMP24N5IatXf7ylGXiGG9A==",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/@wangeditor/editor": {
+      "version": "5.1.23",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/editor/-/editor-5.1.23.tgz",
+      "integrity": "sha512-0RxfeVTuK1tktUaPROnCoFfaHVJpRAIE2zdS0mpP+vq1axVQpLjM8+fCvKzqYIkH0Pg+C+44hJpe3VVroSkEuQ==",
+      "dependencies": {
+        "@uppy/core": "^2.1.1",
+        "@uppy/xhr-upload": "^2.0.3",
+        "@wangeditor/basic-modules": "^1.1.7",
+        "@wangeditor/code-highlight": "^1.0.3",
+        "@wangeditor/core": "^1.1.19",
+        "@wangeditor/list-module": "^1.0.5",
+        "@wangeditor/table-module": "^1.1.4",
+        "@wangeditor/upload-image-module": "^1.0.2",
+        "@wangeditor/video-module": "^1.1.4",
+        "dom7": "^3.0.0",
+        "is-hotkey": "^0.2.0",
+        "lodash.camelcase": "^4.3.0",
+        "lodash.clonedeep": "^4.5.0",
+        "lodash.debounce": "^4.0.8",
+        "lodash.foreach": "^4.5.0",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "lodash.toarray": "^4.4.0",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/editor-for-vue": {
+      "version": "5.1.12",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/editor-for-vue/-/editor-for-vue-5.1.12.tgz",
+      "integrity": "sha512-0Ds3D8I+xnpNWezAeO7HmPRgTfUxHLMd9JKcIw+QzvSmhC5xUHbpCcLU+KLmeBKTR/zffnS5GQo6qi3GhTMJWQ==",
+      "peerDependencies": {
+        "@wangeditor/editor": ">=5.1.0",
+        "vue": "^3.0.5"
+      }
+    },
+    "node_modules/@wangeditor/list-module": {
+      "version": "1.0.5",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/list-module/-/list-module-1.0.5.tgz",
+      "integrity": "sha512-uDuYTP6DVhcYf7mF1pTlmNn5jOb4QtcVhYwSSAkyg09zqxI1qBqsfUnveeDeDqIuptSJhkh81cyxi+MF8sEPOQ==",
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/table-module": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/table-module/-/table-module-1.1.4.tgz",
+      "integrity": "sha512-5saanU9xuEocxaemGdNi9t8MCDSucnykEC6jtuiT72kt+/Hhh4nERYx1J20OPsTCCdVr7hIyQenFD1iSRkIQ6w==",
+      "peerDependencies": {
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "lodash.isequal": "^4.5.0",
+        "lodash.throttle": "^4.1.1",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/upload-image-module": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/upload-image-module/-/upload-image-module-1.0.2.tgz",
+      "integrity": "sha512-z81lk/v71OwPDYeQDxj6cVr81aDP90aFuywb8nPD6eQeECtOymrqRODjpO6VGvCVxVck8nUxBHtbxKtjgcwyiA==",
+      "peerDependencies": {
+        "@uppy/core": "^2.0.3",
+        "@uppy/xhr-upload": "^2.0.3",
+        "@wangeditor/basic-modules": "1.x",
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "lodash.foreach": "^4.5.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/@wangeditor/video-module": {
+      "version": "1.1.4",
+      "resolved": "https://registry.npmmirror.com/@wangeditor/video-module/-/video-module-1.1.4.tgz",
+      "integrity": "sha512-ZdodDPqKQrgx3IwWu4ZiQmXI8EXZ3hm2/fM6E3t5dB8tCaIGWQZhmqd6P5knfkRAd3z2+YRSRbxOGfoRSp/rLg==",
+      "peerDependencies": {
+        "@uppy/core": "^2.1.4",
+        "@uppy/xhr-upload": "^2.0.7",
+        "@wangeditor/core": "1.x",
+        "dom7": "^3.0.0",
+        "nanoid": "^3.2.0",
+        "slate": "^0.72.0",
+        "snabbdom": "^3.1.0"
+      }
+    },
+    "node_modules/acorn": {
+      "version": "8.14.1",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "acorn": "bin/acorn"
+      },
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/acorn-jsx": {
+      "version": "5.3.2",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+      }
+    },
+    "node_modules/ajv": {
+      "version": "6.12.6",
+      "dev": true,
+      "license": "MIT",
+      "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/ajv-formats": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz",
+      "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+      "dependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependencies": {
+        "ajv": "^8.0.0"
+      },
+      "peerDependenciesMeta": {
+        "ajv": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/ajv-formats/node_modules/ajv": {
+      "version": "8.17.1",
+      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz",
+      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/ajv-formats/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+    },
+    "node_modules/algoliasearch": {
+      "version": "5.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@algolia/client-abtesting": "5.24.0",
+        "@algolia/client-analytics": "5.24.0",
+        "@algolia/client-common": "5.24.0",
+        "@algolia/client-insights": "5.24.0",
+        "@algolia/client-personalization": "5.24.0",
+        "@algolia/client-query-suggestions": "5.24.0",
+        "@algolia/client-search": "5.24.0",
+        "@algolia/ingestion": "1.24.0",
+        "@algolia/monitoring": "1.24.0",
+        "@algolia/recommend": "5.24.0",
+        "@algolia/requester-browser-xhr": "5.24.0",
+        "@algolia/requester-fetch": "5.24.0",
+        "@algolia/requester-node-http": "5.24.0"
+      },
+      "engines": {
+        "node": ">= 14.0.0"
+      }
+    },
+    "node_modules/ansi-regex": {
+      "version": "5.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/ansi-styles": {
+      "version": "4.3.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+      }
+    },
+    "node_modules/ansi-styles/node_modules/color-convert": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "~1.1.4"
+      },
+      "engines": {
+        "node": ">=7.0.0"
+      }
+    },
+    "node_modules/ansi-styles/node_modules/color-name": {
+      "version": "1.1.4",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/app-builder-lib": {
+      "version": "23.6.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@develar/schema-utils": "~2.6.5",
+        "@electron/universal": "1.2.1",
+        "@malept/flatpak-bundler": "^0.4.0",
+        "7zip-bin": "~5.1.1",
+        "async-exit-hook": "^2.0.1",
+        "bluebird-lst": "^1.0.9",
+        "builder-util": "23.6.0",
+        "builder-util-runtime": "9.1.1",
+        "chromium-pickle-js": "^0.2.0",
+        "debug": "^4.3.4",
+        "ejs": "^3.1.7",
+        "electron-osx-sign": "^0.6.0",
+        "electron-publish": "23.6.0",
+        "form-data": "^4.0.0",
+        "fs-extra": "^10.1.0",
+        "hosted-git-info": "^4.1.0",
+        "is-ci": "^3.0.0",
+        "isbinaryfile": "^4.0.10",
+        "js-yaml": "^4.1.0",
+        "lazy-val": "^1.0.5",
+        "minimatch": "^3.1.2",
+        "read-config-file": "6.2.0",
+        "sanitize-filename": "^1.6.3",
+        "semver": "^7.3.7",
+        "tar": "^6.1.11",
+        "temp-file": "^3.4.0"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@develar/schema-utils": {
+      "version": "2.6.5",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ajv": "^6.12.0",
+        "ajv-keywords": "^3.4.1"
+      },
+      "engines": {
+        "node": ">= 8.9.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/webpack"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@electron/universal": {
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@malept/cross-spawn-promise": "^1.1.0",
+        "asar": "^3.1.0",
+        "debug": "^4.3.1",
+        "dir-compare": "^2.4.0",
+        "fs-extra": "^9.0.1",
+        "minimatch": "^3.0.4",
+        "plist": "^3.0.4"
+      },
+      "engines": {
+        "node": ">=8.6"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@electron/universal/node_modules/fs-extra": {
+      "version": "9.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "at-least-node": "^1.0.0",
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@malept/cross-spawn-promise": {
+      "version": "1.1.1",
+      "dev": true,
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/malept"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund"
+        }
+      ],
+      "license": "Apache-2.0",
+      "dependencies": {
+        "cross-spawn": "^7.0.1"
+      },
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@malept/flatpak-bundler": {
+      "version": "0.4.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.1.1",
+        "fs-extra": "^9.0.0",
+        "lodash": "^4.17.15",
+        "tmp-promise": "^3.0.2"
+      },
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@malept/flatpak-bundler/node_modules/fs-extra": {
+      "version": "9.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "at-least-node": "^1.0.0",
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/@xmldom/xmldom": {
+      "version": "0.8.10",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/7zip-bin": {
+      "version": "5.1.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/app-builder-lib/node_modules/ajv-keywords": {
+      "version": "3.5.2",
+      "dev": true,
+      "license": "MIT",
+      "peerDependencies": {
+        "ajv": "^6.9.1"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/asar": {
+      "version": "3.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "chromium-pickle-js": "^0.2.0",
+        "commander": "^5.0.0",
+        "glob": "^7.1.6",
+        "minimatch": "^3.0.4"
+      },
+      "bin": {
+        "asar": "bin/asar.js"
+      },
+      "engines": {
+        "node": ">=10.12.0"
+      },
+      "optionalDependencies": {
+        "@types/glob": "^7.1.1"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/async": {
+      "version": "3.2.6",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/app-builder-lib/node_modules/bluebird": {
+      "version": "3.7.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/app-builder-lib/node_modules/buffer-equal": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/chromium-pickle-js": {
+      "version": "0.2.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/app-builder-lib/node_modules/colors": {
+      "version": "1.0.3",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.1.90"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/commander": {
+      "version": "5.1.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/dir-compare": {
+      "version": "2.4.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "buffer-equal": "1.0.0",
+        "colors": "1.0.3",
+        "commander": "2.9.0",
+        "minimatch": "3.0.4"
+      },
+      "bin": {
+        "dircompare": "src/cli/dircompare.js"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/dir-compare/node_modules/commander": {
+      "version": "2.9.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "graceful-readlink": ">= 1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.6.x"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/dir-compare/node_modules/minimatch": {
+      "version": "3.0.4",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/ejs": {
+      "version": "3.1.10",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "jake": "^10.8.5"
+      },
+      "bin": {
+        "ejs": "bin/cli.js"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/electron-osx-sign": {
+      "version": "0.6.0",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "bluebird": "^3.5.0",
+        "compare-version": "^0.1.2",
+        "debug": "^2.6.8",
+        "isbinaryfile": "^3.0.2",
+        "minimist": "^1.2.0",
+        "plist": "^3.0.1"
+      },
+      "bin": {
+        "electron-osx-flat": "bin/electron-osx-flat.js",
+        "electron-osx-sign": "bin/electron-osx-sign.js"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/electron-osx-sign/node_modules/debug": {
+      "version": "2.6.9",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "2.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/electron-osx-sign/node_modules/isbinaryfile": {
+      "version": "3.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "buffer-alloc": "^1.2.0"
+      },
+      "engines": {
+        "node": ">=0.6.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/electron-publish": {
+      "version": "23.6.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/fs-extra": "^9.0.11",
+        "builder-util": "23.6.0",
+        "builder-util-runtime": "9.1.1",
+        "chalk": "^4.1.1",
+        "fs-extra": "^10.0.0",
+        "lazy-val": "^1.0.5",
+        "mime": "^2.5.2"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/filelist": {
+      "version": "1.0.4",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "minimatch": "^5.0.1"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/filelist/node_modules/brace-expansion": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/filelist/node_modules/minimatch": {
+      "version": "5.1.6",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^2.0.1"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/fs-extra": {
+      "version": "10.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/fs-minipass": {
+      "version": "2.1.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "minipass": "^3.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/fs-minipass/node_modules/minipass": {
+      "version": "3.3.6",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/hosted-git-info": {
+      "version": "4.1.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "lru-cache": "^6.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/isbinaryfile": {
+      "version": "4.0.10",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 8.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/gjtorikian/"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/jake": {
+      "version": "10.9.2",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "async": "^3.2.3",
+        "chalk": "^4.0.2",
+        "filelist": "^1.0.4",
+        "minimatch": "^3.1.2"
+      },
+      "bin": {
+        "jake": "bin/cli.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/lru-cache": {
+      "version": "6.0.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/mime": {
+      "version": "2.6.0",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "mime": "cli.js"
+      },
+      "engines": {
+        "node": ">=4.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/minizlib": {
+      "version": "2.1.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "minipass": "^3.0.0",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/minizlib/node_modules/minipass": {
+      "version": "3.3.6",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/mkdirp": {
+      "version": "1.0.4",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "mkdirp": "bin/cmd.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/ms": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/app-builder-lib/node_modules/plist": {
+      "version": "3.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@xmldom/xmldom": "^0.8.8",
+        "base64-js": "^1.5.1",
+        "xmlbuilder": "^15.1.1"
+      },
+      "engines": {
+        "node": ">=10.4.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/tar": {
+      "version": "6.2.1",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "chownr": "^2.0.0",
+        "fs-minipass": "^2.0.0",
+        "minipass": "^5.0.0",
+        "minizlib": "^2.1.1",
+        "mkdirp": "^1.0.3",
+        "yallist": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/temp-file": {
+      "version": "3.4.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "async-exit-hook": "^2.0.1",
+        "fs-extra": "^10.0.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/tmp": {
+      "version": "0.2.3",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=14.14"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/tmp-promise": {
+      "version": "3.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "tmp": "^0.2.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/xmlbuilder": {
+      "version": "15.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/app-builder-lib/node_modules/yallist": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/argparse": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "Python-2.0"
+    },
+    "node_modules/async-exit-hook": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/asynckit": {
+      "version": "0.4.0",
+      "license": "MIT"
+    },
+    "node_modules/at-least-node": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "ISC",
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/atomically": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmmirror.com/atomically/-/atomically-1.7.0.tgz",
+      "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==",
+      "engines": {
+        "node": ">=10.12.0"
+      }
+    },
+    "node_modules/axios": {
+      "version": "1.7.8",
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.15.6",
+        "form-data": "^4.0.0",
+        "proxy-from-env": "^1.1.0"
+      }
+    },
+    "node_modules/b-tween": {
+      "version": "0.3.3",
+      "license": "MIT"
+    },
+    "node_modules/b-validate": {
+      "version": "1.5.3",
+      "license": "MIT"
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "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"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/birpc": {
+      "version": "2.3.0",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      }
+    },
+    "node_modules/bluebird-lst": {
+      "version": "1.0.9",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "bluebird": "^3.5.5"
+      }
+    },
+    "node_modules/bluebird-lst/node_modules/bluebird": {
+      "version": "3.7.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/boolbase": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/buffer-alloc": {
+      "version": "1.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "buffer-alloc-unsafe": "^1.1.0",
+        "buffer-fill": "^1.0.0"
+      }
+    },
+    "node_modules/buffer-alloc-unsafe": {
+      "version": "1.1.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/buffer-crc32": {
+      "version": "0.2.13",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/buffer-fill": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/buffer-from": {
+      "version": "1.1.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/builder-util": {
+      "version": "23.6.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/debug": "^4.1.6",
+        "@types/fs-extra": "^9.0.11",
+        "7zip-bin": "~5.1.1",
+        "app-builder-bin": "4.0.0",
+        "bluebird-lst": "^1.0.9",
+        "builder-util-runtime": "9.1.1",
+        "chalk": "^4.1.1",
+        "cross-spawn": "^7.0.3",
+        "debug": "^4.3.4",
+        "fs-extra": "^10.0.0",
+        "http-proxy-agent": "^5.0.0",
+        "https-proxy-agent": "^5.0.0",
+        "is-ci": "^3.0.0",
+        "js-yaml": "^4.1.0",
+        "source-map-support": "^0.5.19",
+        "stat-mode": "^1.0.0",
+        "temp-file": "^3.4.0"
+      }
+    },
+    "node_modules/builder-util-runtime": {
+      "version": "9.1.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.3.4",
+        "sax": "^1.2.4"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/builder-util-runtime/node_modules/sax": {
+      "version": "1.4.1",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/builder-util/node_modules/@tootallnate/once": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10"
+      }
+    },
+    "node_modules/builder-util/node_modules/7zip-bin": {
+      "version": "5.1.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/builder-util/node_modules/agent-base": {
+      "version": "6.0.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6.0.0"
+      }
+    },
+    "node_modules/builder-util/node_modules/app-builder-bin": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/builder-util/node_modules/fs-extra": {
+      "version": "10.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/builder-util/node_modules/http-proxy-agent": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@tootallnate/once": "2",
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/builder-util/node_modules/https-proxy-agent": {
+      "version": "5.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "agent-base": "6",
+        "debug": "4"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/builder-util/node_modules/stat-mode": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/builder-util/node_modules/temp-file": {
+      "version": "3.4.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "async-exit-hook": "^2.0.1",
+        "fs-extra": "^10.0.0"
+      }
+    },
+    "node_modules/call-bind-apply-helpers": {
+      "version": "1.0.2",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/callsites": {
+      "version": "3.1.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/ccount": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/chalk": {
+      "version": "4.1.2",
+      "dev": true,
+      "license": "MIT",
+      "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/character-entities-html4": {
+      "version": "2.1.0",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/character-entities-legacy": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/charenc": {
+      "version": "0.0.2",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/chownr": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "ISC",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/ci-info": {
+      "version": "3.9.0",
+      "dev": true,
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/sibiraj-s"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/clipboard": {
+      "version": "2.0.11",
+      "license": "MIT",
+      "dependencies": {
+        "good-listener": "^1.2.2",
+        "select": "^1.1.2",
+        "tiny-emitter": "^2.0.0"
+      }
+    },
+    "node_modules/color": {
+      "version": "3.2.1",
+      "license": "MIT",
+      "dependencies": {
+        "color-convert": "^1.9.3",
+        "color-string": "^1.6.0"
+      }
+    },
+    "node_modules/color-convert": {
+      "version": "1.9.3",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "1.1.3"
+      }
+    },
+    "node_modules/color-name": {
+      "version": "1.1.3",
+      "license": "MIT"
+    },
+    "node_modules/color-string": {
+      "version": "1.9.1",
+      "license": "MIT",
+      "dependencies": {
+        "color-name": "^1.0.0",
+        "simple-swizzle": "^0.2.2"
+      }
+    },
+    "node_modules/combined-stream": {
+      "version": "1.0.8",
+      "license": "MIT",
+      "dependencies": {
+        "delayed-stream": "~1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.8"
+      }
+    },
+    "node_modules/comma-separated-tokens": {
+      "version": "2.0.3",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/compare-version": {
+      "version": "0.1.2",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/compute-scroll-into-view": {
+      "version": "1.0.20",
+      "license": "MIT"
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/concurrently": {
+      "version": "8.2.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "chalk": "^4.1.2",
+        "date-fns": "^2.30.0",
+        "lodash": "^4.17.21",
+        "rxjs": "^7.8.1",
+        "shell-quote": "^1.8.1",
+        "spawn-command": "0.0.2",
+        "supports-color": "^8.1.1",
+        "tree-kill": "^1.2.2",
+        "yargs": "^17.7.2"
+      },
+      "bin": {
+        "conc": "dist/bin/concurrently.js",
+        "concurrently": "dist/bin/concurrently.js"
+      },
+      "engines": {
+        "node": "^14.13.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/open-cli-tools/concurrently?sponsor=1"
+      }
+    },
+    "node_modules/concurrently/node_modules/supports-color": {
+      "version": "8.1.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/chalk/supports-color?sponsor=1"
+      }
+    },
+    "node_modules/conf": {
+      "version": "10.2.0",
+      "resolved": "https://registry.npmmirror.com/conf/-/conf-10.2.0.tgz",
+      "integrity": "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==",
+      "dependencies": {
+        "ajv": "^8.6.3",
+        "ajv-formats": "^2.1.1",
+        "atomically": "^1.7.0",
+        "debounce-fn": "^4.0.0",
+        "dot-prop": "^6.0.1",
+        "env-paths": "^2.2.1",
+        "json-schema-typed": "^7.0.3",
+        "onetime": "^5.1.2",
+        "pkg-up": "^3.1.0",
+        "semver": "^7.3.5"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/conf/node_modules/ajv": {
+      "version": "8.17.1",
+      "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.17.1.tgz",
+      "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+      "dependencies": {
+        "fast-deep-equal": "^3.1.3",
+        "fast-uri": "^3.0.1",
+        "json-schema-traverse": "^1.0.0",
+        "require-from-string": "^2.0.2"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/epoberezkin"
+      }
+    },
+    "node_modules/conf/node_modules/json-schema-traverse": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+      "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+    },
+    "node_modules/copy-anything": {
+      "version": "3.0.5",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-what": "^4.1.8"
+      },
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/core-util-is": {
+      "version": "1.0.3",
+      "license": "MIT"
+    },
+    "node_modules/cross-env": {
+      "version": "7.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "cross-spawn": "^7.0.1"
+      },
+      "bin": {
+        "cross-env": "src/bin/cross-env.js",
+        "cross-env-shell": "src/bin/cross-env-shell.js"
+      },
+      "engines": {
+        "node": ">=10.14",
+        "npm": ">=6",
+        "yarn": ">=1"
+      }
+    },
+    "node_modules/cross-spawn": {
+      "version": "7.0.6",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "path-key": "^3.1.0",
+        "shebang-command": "^2.0.0",
+        "which": "^2.0.1"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/crypt": {
+      "version": "0.0.2",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/cssesc": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "cssesc": "bin/cssesc"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/csstype": {
+      "version": "3.1.3",
+      "license": "MIT"
+    },
+    "node_modules/d": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/d/-/d-1.0.2.tgz",
+      "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
+      "dependencies": {
+        "es5-ext": "^0.10.64",
+        "type": "^2.7.2"
+      },
+      "engines": {
+        "node": ">=0.12"
+      }
+    },
+    "node_modules/date-fns": {
+      "version": "2.30.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime": "^7.21.0"
+      },
+      "engines": {
+        "node": ">=0.11"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/date-fns"
+      }
+    },
+    "node_modules/dayjs": {
+      "version": "1.11.13",
+      "license": "MIT"
+    },
+    "node_modules/debounce-fn": {
+      "version": "4.0.0",
+      "resolved": "https://registry.npmmirror.com/debounce-fn/-/debounce-fn-4.0.0.tgz",
+      "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==",
+      "dependencies": {
+        "mimic-fn": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/debug": {
+      "version": "4.4.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ms": "^2.1.3"
+      },
+      "engines": {
+        "node": ">=6.0"
+      },
+      "peerDependenciesMeta": {
+        "supports-color": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/deep-is": {
+      "version": "0.1.4",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/delayed-stream": {
+      "version": "1.0.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/delegate": {
+      "version": "3.2.0",
+      "license": "MIT"
+    },
+    "node_modules/dequal": {
+      "version": "2.0.3",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/detect-node": {
+      "version": "2.1.0",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/devlop": {
+      "version": "1.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "dequal": "^2.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/dmg-builder": {
+      "version": "23.6.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "app-builder-lib": "23.6.0",
+        "builder-util": "23.6.0",
+        "builder-util-runtime": "9.1.1",
+        "fs-extra": "^10.0.0",
+        "iconv-lite": "^0.6.2",
+        "js-yaml": "^4.1.0"
+      },
+      "optionalDependencies": {
+        "dmg-license": "^1.0.11"
+      }
+    },
+    "node_modules/dmg-builder/node_modules/fs-extra": {
+      "version": "10.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/dmg-builder/node_modules/iconv-lite": {
+      "version": "0.6.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "safer-buffer": ">= 2.1.2 < 3.0.0"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/docx-preview": {
+      "version": "0.3.3",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "jszip": ">=3.0.0"
+      }
+    },
+    "node_modules/dom7": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/dom7/-/dom7-3.0.0.tgz",
+      "integrity": "sha512-oNlcUdHsC4zb7Msx7JN3K0Nro1dzJ48knvBOnDPKJ2GV9wl1i5vydJZUSyOfrkKFDZEud/jBsTk92S/VGSAe/g==",
+      "dependencies": {
+        "ssr-window": "^3.0.0-alpha.1"
+      }
+    },
+    "node_modules/dot-prop": {
+      "version": "6.0.1",
+      "resolved": "https://registry.npmmirror.com/dot-prop/-/dot-prop-6.0.1.tgz",
+      "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==",
+      "dependencies": {
+        "is-obj": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/dunder-proto": {
+      "version": "1.0.1",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.2.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/echarts": {
+      "version": "5.6.0",
+      "resolved": "https://registry.npmmirror.com/echarts/-/echarts-5.6.0.tgz",
+      "integrity": "sha512-oTbVTsXfKuEhxftHqL5xprgLoc0k7uScAwtryCgWF6hPYFLRwOUHiFmHGCBKP5NPFNkDVopOieyUqYGH8Fa3kA==",
+      "dependencies": {
+        "tslib": "2.3.0",
+        "zrender": "5.6.1"
+      }
+    },
+    "node_modules/echarts/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+    },
+    "node_modules/electron": {
+      "version": "25.3.1",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "dependencies": {
+        "@electron/get": "^2.0.0",
+        "@types/node": "^18.11.18",
+        "extract-zip": "^2.0.1"
+      },
+      "bin": {
+        "electron": "cli.js"
+      },
+      "engines": {
+        "node": ">= 12.20.55"
+      }
+    },
+    "node_modules/electron-builder": {
+      "version": "23.6.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/yargs": "^17.0.1",
+        "app-builder-lib": "23.6.0",
+        "builder-util": "23.6.0",
+        "builder-util-runtime": "9.1.1",
+        "chalk": "^4.1.1",
+        "dmg-builder": "23.6.0",
+        "fs-extra": "^10.0.0",
+        "is-ci": "^3.0.0",
+        "lazy-val": "^1.0.5",
+        "read-config-file": "6.2.0",
+        "simple-update-notifier": "^1.0.7",
+        "yargs": "^17.5.1"
+      },
+      "bin": {
+        "electron-builder": "cli.js",
+        "install-app-deps": "install-app-deps.js"
+      },
+      "engines": {
+        "node": ">=14.0.0"
+      }
+    },
+    "node_modules/electron-builder/node_modules/fs-extra": {
+      "version": "10.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^6.0.1",
+        "universalify": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/electron-store": {
+      "version": "8.2.0",
+      "resolved": "https://registry.npmmirror.com/electron-store/-/electron-store-8.2.0.tgz",
+      "integrity": "sha512-ukLL5Bevdil6oieAOXz3CMy+OgaItMiVBg701MNlG6W5RaC0AHN7rvlqTCmeb6O7jP0Qa1KKYTE0xV0xbhF4Hw==",
+      "dependencies": {
+        "conf": "^10.2.0",
+        "type-fest": "^2.17.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron-store/node_modules/type-fest": {
+      "version": "2.19.0",
+      "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-2.19.0.tgz",
+      "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
+      "engines": {
+        "node": ">=12.20"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/@electron/get": {
+      "version": "2.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.1.1",
+        "env-paths": "^2.2.0",
+        "fs-extra": "^8.1.0",
+        "got": "^11.8.5",
+        "progress": "^2.0.3",
+        "semver": "^6.2.0",
+        "sumchecker": "^3.0.1"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "global-agent": "^3.0.0"
+      }
+    },
+    "node_modules/electron/node_modules/@electron/get/node_modules/semver": {
+      "version": "6.3.1",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/electron/node_modules/@sindresorhus/is": {
+      "version": "4.6.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/is?sponsor=1"
+      }
+    },
+    "node_modules/electron/node_modules/@szmarczak/http-timer": {
+      "version": "4.0.6",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "defer-to-connect": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/electron/node_modules/@types/node": {
+      "version": "18.19.97",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "undici-types": "~5.26.4"
+      }
+    },
+    "node_modules/electron/node_modules/boolean": {
+      "version": "3.2.0",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/electron/node_modules/cacheable-lookup": {
+      "version": "5.0.4",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.6.0"
+      }
+    },
+    "node_modules/electron/node_modules/cacheable-request": {
+      "version": "7.0.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "clone-response": "^1.0.2",
+        "get-stream": "^5.1.0",
+        "http-cache-semantics": "^4.0.0",
+        "keyv": "^4.0.0",
+        "lowercase-keys": "^2.0.0",
+        "normalize-url": "^6.0.1",
+        "responselike": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/electron/node_modules/clone-response": {
+      "version": "1.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "mimic-response": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/decompress-response": {
+      "version": "6.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "mimic-response": "^3.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/decompress-response/node_modules/mimic-response": {
+      "version": "3.1.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/defer-to-connect": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/electron/node_modules/define-data-property": {
+      "version": "1.1.4",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "es-define-property": "^1.0.0",
+        "es-errors": "^1.3.0",
+        "gopd": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/electron/node_modules/define-properties": {
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "define-data-property": "^1.0.1",
+        "has-property-descriptors": "^1.0.0",
+        "object-keys": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/electron/node_modules/es6-error": {
+      "version": "4.1.1",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/electron/node_modules/extract-zip": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "debug": "^4.1.1",
+        "get-stream": "^5.1.0",
+        "yauzl": "^2.10.0"
+      },
+      "bin": {
+        "extract-zip": "cli.js"
+      },
+      "engines": {
+        "node": ">= 10.17.0"
+      },
+      "optionalDependencies": {
+        "@types/yauzl": "^2.9.1"
+      }
+    },
+    "node_modules/electron/node_modules/fs-extra": {
+      "version": "8.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "graceful-fs": "^4.2.0",
+        "jsonfile": "^4.0.0",
+        "universalify": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=6 <7 || >=8"
+      }
+    },
+    "node_modules/electron/node_modules/get-stream": {
+      "version": "5.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "pump": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/global-agent": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "optional": true,
+      "dependencies": {
+        "boolean": "^3.0.1",
+        "es6-error": "^4.1.1",
+        "matcher": "^3.0.0",
+        "roarr": "^2.15.3",
+        "semver": "^7.3.2",
+        "serialize-error": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=10.0"
+      }
+    },
+    "node_modules/electron/node_modules/globalthis": {
+      "version": "1.0.4",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "define-properties": "^1.2.1",
+        "gopd": "^1.0.1"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/electron/node_modules/got": {
+      "version": "11.8.6",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@sindresorhus/is": "^4.0.0",
+        "@szmarczak/http-timer": "^4.0.5",
+        "@types/cacheable-request": "^6.0.1",
+        "@types/responselike": "^1.0.0",
+        "cacheable-lookup": "^5.0.3",
+        "cacheable-request": "^7.0.2",
+        "decompress-response": "^6.0.0",
+        "http2-wrapper": "^1.0.0-beta.5.2",
+        "lowercase-keys": "^2.0.0",
+        "p-cancelable": "^2.0.0",
+        "responselike": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=10.19.0"
+      },
+      "funding": {
+        "url": "https://github.com/sindresorhus/got?sponsor=1"
+      }
+    },
+    "node_modules/electron/node_modules/has-property-descriptors": {
+      "version": "1.0.2",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "es-define-property": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/electron/node_modules/http2-wrapper": {
+      "version": "1.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "quick-lru": "^5.1.1",
+        "resolve-alpn": "^1.0.0"
+      },
+      "engines": {
+        "node": ">=10.19.0"
+      }
+    },
+    "node_modules/electron/node_modules/json-stringify-safe": {
+      "version": "5.0.1",
+      "dev": true,
+      "license": "ISC",
+      "optional": true
+    },
+    "node_modules/electron/node_modules/jsonfile": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/electron/node_modules/object-keys": {
+      "version": "1.1.1",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/electron/node_modules/pump": {
+      "version": "3.0.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "end-of-stream": "^1.1.0",
+        "once": "^1.3.1"
+      }
+    },
+    "node_modules/electron/node_modules/responselike": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "lowercase-keys": "^2.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/roarr": {
+      "version": "2.15.4",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "optional": true,
+      "dependencies": {
+        "boolean": "^3.0.1",
+        "detect-node": "^2.0.4",
+        "globalthis": "^1.0.1",
+        "json-stringify-safe": "^5.0.1",
+        "semver-compare": "^1.0.0",
+        "sprintf-js": "^1.1.2"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/electron/node_modules/semver-compare": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "MIT",
+      "optional": true
+    },
+    "node_modules/electron/node_modules/serialize-error": {
+      "version": "7.0.1",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "type-fest": "^0.13.1"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/sprintf-js": {
+      "version": "1.1.3",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "optional": true
+    },
+    "node_modules/electron/node_modules/sumchecker": {
+      "version": "3.0.1",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "debug": "^4.1.0"
+      },
+      "engines": {
+        "node": ">= 8.0"
+      }
+    },
+    "node_modules/electron/node_modules/type-fest": {
+      "version": "0.13.1",
+      "dev": true,
+      "license": "(MIT OR CC0-1.0)",
+      "optional": true,
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/electron/node_modules/undici-types": {
+      "version": "5.26.5",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/electron/node_modules/universalify": {
+      "version": "0.1.2",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4.0.0"
+      }
+    },
+    "node_modules/emoji-regex-xs": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/end-of-stream": {
+      "version": "1.4.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "once": "^1.4.0"
+      }
+    },
+    "node_modules/entities": {
+      "version": "4.5.0",
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.12"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/entities?sponsor=1"
+      }
+    },
+    "node_modules/env-paths": {
+      "version": "2.2.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/es-define-property": {
+      "version": "1.0.1",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-errors": {
+      "version": "1.3.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-object-atoms": {
+      "version": "1.1.1",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es-set-tostringtag": {
+      "version": "2.1.0",
+      "license": "MIT",
+      "dependencies": {
+        "es-errors": "^1.3.0",
+        "get-intrinsic": "^1.2.6",
+        "has-tostringtag": "^1.0.2",
+        "hasown": "^2.0.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/es5-ext": {
+      "version": "0.10.64",
+      "resolved": "https://registry.npmmirror.com/es5-ext/-/es5-ext-0.10.64.tgz",
+      "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
+      "hasInstallScript": true,
+      "dependencies": {
+        "es6-iterator": "^2.0.3",
+        "es6-symbol": "^3.1.3",
+        "esniff": "^2.0.1",
+        "next-tick": "^1.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/es6-iterator": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmmirror.com/es6-iterator/-/es6-iterator-2.0.3.tgz",
+      "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+      "dependencies": {
+        "d": "1",
+        "es5-ext": "^0.10.35",
+        "es6-symbol": "^3.1.1"
+      }
+    },
+    "node_modules/es6-symbol": {
+      "version": "3.1.4",
+      "resolved": "https://registry.npmmirror.com/es6-symbol/-/es6-symbol-3.1.4.tgz",
+      "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
+      "dependencies": {
+        "d": "^1.0.2",
+        "ext": "^1.7.0"
+      },
+      "engines": {
+        "node": ">=0.12"
+      }
+    },
+    "node_modules/esbuild": {
+      "version": "0.21.5",
+      "dev": true,
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "esbuild": "bin/esbuild"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "optionalDependencies": {
+        "@esbuild/aix-ppc64": "0.21.5",
+        "@esbuild/android-arm": "0.21.5",
+        "@esbuild/android-arm64": "0.21.5",
+        "@esbuild/android-x64": "0.21.5",
+        "@esbuild/darwin-arm64": "0.21.5",
+        "@esbuild/darwin-x64": "0.21.5",
+        "@esbuild/freebsd-arm64": "0.21.5",
+        "@esbuild/freebsd-x64": "0.21.5",
+        "@esbuild/linux-arm": "0.21.5",
+        "@esbuild/linux-arm64": "0.21.5",
+        "@esbuild/linux-ia32": "0.21.5",
+        "@esbuild/linux-loong64": "0.21.5",
+        "@esbuild/linux-mips64el": "0.21.5",
+        "@esbuild/linux-ppc64": "0.21.5",
+        "@esbuild/linux-riscv64": "0.21.5",
+        "@esbuild/linux-s390x": "0.21.5",
+        "@esbuild/linux-x64": "0.21.5",
+        "@esbuild/netbsd-x64": "0.21.5",
+        "@esbuild/openbsd-x64": "0.21.5",
+        "@esbuild/sunos-x64": "0.21.5",
+        "@esbuild/win32-arm64": "0.21.5",
+        "@esbuild/win32-ia32": "0.21.5",
+        "@esbuild/win32-x64": "0.21.5"
+      }
+    },
+    "node_modules/escalade": {
+      "version": "3.2.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/escape-string-regexp": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint": {
+      "version": "9.16.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.2.0",
+        "@eslint-community/regexpp": "^4.12.1",
+        "@eslint/config-array": "^0.19.0",
+        "@eslint/core": "^0.9.0",
+        "@eslint/eslintrc": "^3.2.0",
+        "@eslint/js": "9.16.0",
+        "@eslint/plugin-kit": "^0.2.3",
+        "@humanfs/node": "^0.16.6",
+        "@humanwhocodes/module-importer": "^1.0.1",
+        "@humanwhocodes/retry": "^0.4.1",
+        "@types/estree": "^1.0.6",
+        "@types/json-schema": "^7.0.15",
+        "ajv": "^6.12.4",
+        "chalk": "^4.0.0",
+        "cross-spawn": "^7.0.5",
+        "debug": "^4.3.2",
+        "escape-string-regexp": "^4.0.0",
+        "eslint-scope": "^8.2.0",
+        "eslint-visitor-keys": "^4.2.0",
+        "espree": "^10.3.0",
+        "esquery": "^1.5.0",
+        "esutils": "^2.0.2",
+        "fast-deep-equal": "^3.1.3",
+        "file-entry-cache": "^8.0.0",
+        "find-up": "^5.0.0",
+        "glob-parent": "^6.0.2",
+        "ignore": "^5.2.0",
+        "imurmurhash": "^0.1.4",
+        "is-glob": "^4.0.0",
+        "json-stable-stringify-without-jsonify": "^1.0.1",
+        "lodash.merge": "^4.6.2",
+        "minimatch": "^3.1.2",
+        "natural-compare": "^1.4.0",
+        "optionator": "^0.9.3"
+      },
+      "bin": {
+        "eslint": "bin/eslint.js"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://eslint.org/donate"
+      },
+      "peerDependencies": {
+        "jiti": "*"
+      },
+      "peerDependenciesMeta": {
+        "jiti": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/eslint-plugin-vue": {
+      "version": "9.32.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@eslint-community/eslint-utils": "^4.4.0",
+        "globals": "^13.24.0",
+        "natural-compare": "^1.4.0",
+        "nth-check": "^2.1.1",
+        "postcss-selector-parser": "^6.0.15",
+        "semver": "^7.6.3",
+        "vue-eslint-parser": "^9.4.3",
+        "xml-name-validator": "^4.0.0"
+      },
+      "engines": {
+        "node": "^14.17.0 || >=16.0.0"
+      },
+      "peerDependencies": {
+        "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0"
+      }
+    },
+    "node_modules/eslint-plugin-vue/node_modules/globals": {
+      "version": "13.24.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "type-fest": "^0.20.2"
+      },
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/eslint-scope": {
+      "version": "8.3.0",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "esrecurse": "^4.3.0",
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/eslint-visitor-keys": {
+      "version": "4.2.0",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esniff": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/esniff/-/esniff-2.0.1.tgz",
+      "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
+      "dependencies": {
+        "d": "^1.0.1",
+        "es5-ext": "^0.10.62",
+        "event-emitter": "^0.3.5",
+        "type": "^2.7.2"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/espree": {
+      "version": "10.3.0",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "acorn": "^8.14.0",
+        "acorn-jsx": "^5.3.2",
+        "eslint-visitor-keys": "^4.2.0"
+      },
+      "engines": {
+        "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/esquery": {
+      "version": "1.6.0",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "estraverse": "^5.1.0"
+      },
+      "engines": {
+        "node": ">=0.10"
+      }
+    },
+    "node_modules/esrecurse": {
+      "version": "4.3.0",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "estraverse": "^5.2.0"
+      },
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estraverse": {
+      "version": "5.3.0",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=4.0"
+      }
+    },
+    "node_modules/estree-walker": {
+      "version": "2.0.2",
+      "license": "MIT"
+    },
+    "node_modules/esutils": {
+      "version": "2.0.3",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/event-emitter": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmmirror.com/event-emitter/-/event-emitter-0.3.5.tgz",
+      "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
+      "dependencies": {
+        "d": "1",
+        "es5-ext": "~0.10.14"
+      }
+    },
+    "node_modules/ext": {
+      "version": "1.7.0",
+      "resolved": "https://registry.npmmirror.com/ext/-/ext-1.7.0.tgz",
+      "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
+      "dependencies": {
+        "type": "^2.7.2"
+      }
+    },
+    "node_modules/fast-deep-equal": {
+      "version": "3.1.3",
+      "license": "MIT"
+    },
+    "node_modules/fast-json-stable-stringify": {
+      "version": "2.1.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-levenshtein": {
+      "version": "2.0.6",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/fast-uri": {
+      "version": "3.0.6",
+      "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.0.6.tgz",
+      "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/fastify"
+        },
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/fastify"
+        }
+      ]
+    },
+    "node_modules/file-entry-cache": {
+      "version": "8.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "flat-cache": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=16.0.0"
+      }
+    },
+    "node_modules/filesize": {
+      "version": "10.1.6",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">= 10.4.0"
+      }
+    },
+    "node_modules/find-up": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "locate-path": "^6.0.0",
+        "path-exists": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/flat-cache": {
+      "version": "4.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "flatted": "^3.2.9",
+        "keyv": "^4.5.4"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/flatted": {
+      "version": "3.3.3",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/focus-trap": {
+      "version": "7.6.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "tabbable": "^6.2.0"
+      }
+    },
+    "node_modules/follow-redirects": {
+      "version": "1.15.9",
+      "funding": [
+        {
+          "type": "individual",
+          "url": "https://github.com/sponsors/RubenVerborgh"
+        }
+      ],
+      "license": "MIT",
+      "engines": {
+        "node": ">=4.0"
+      },
+      "peerDependenciesMeta": {
+        "debug": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/form-data": {
+      "version": "4.0.2",
+      "license": "MIT",
+      "dependencies": {
+        "asynckit": "^0.4.0",
+        "combined-stream": "^1.0.8",
+        "es-set-tostringtag": "^2.1.0",
+        "mime-types": "^2.1.12"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.2",
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-caller-file": {
+      "version": "2.0.5",
+      "dev": true,
+      "license": "ISC",
+      "engines": {
+        "node": "6.* || 8.* || >= 10.*"
+      }
+    },
+    "node_modules/get-intrinsic": {
+      "version": "1.3.0",
+      "license": "MIT",
+      "dependencies": {
+        "call-bind-apply-helpers": "^1.0.2",
+        "es-define-property": "^1.0.1",
+        "es-errors": "^1.3.0",
+        "es-object-atoms": "^1.1.1",
+        "function-bind": "^1.1.2",
+        "get-proto": "^1.0.1",
+        "gopd": "^1.2.0",
+        "has-symbols": "^1.1.0",
+        "hasown": "^2.0.2",
+        "math-intrinsics": "^1.1.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/get-proto": {
+      "version": "1.0.1",
+      "license": "MIT",
+      "dependencies": {
+        "dunder-proto": "^1.0.1",
+        "es-object-atoms": "^1.0.0"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/glob": {
+      "version": "7.2.3",
+      "dev": true,
+      "license": "ISC",
+      "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",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "is-glob": "^4.0.3"
+      },
+      "engines": {
+        "node": ">=10.13.0"
+      }
+    },
+    "node_modules/globals": {
+      "version": "14.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=18"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/good-listener": {
+      "version": "1.2.2",
+      "license": "MIT",
+      "dependencies": {
+        "delegate": "^3.1.2"
+      }
+    },
+    "node_modules/gopd": {
+      "version": "1.2.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/graceful-fs": {
+      "version": "4.2.11",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/graceful-readlink": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/has-flag": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/has-symbols": {
+      "version": "1.1.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/has-tostringtag": {
+      "version": "1.0.2",
+      "license": "MIT",
+      "dependencies": {
+        "has-symbols": "^1.0.3"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/hasown": {
+      "version": "2.0.2",
+      "license": "MIT",
+      "dependencies": {
+        "function-bind": "^1.1.2"
+      },
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/hast-util-to-html": {
+      "version": "9.0.5",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/hast": "^3.0.0",
+        "@types/unist": "^3.0.0",
+        "ccount": "^2.0.0",
+        "comma-separated-tokens": "^2.0.0",
+        "hast-util-whitespace": "^3.0.0",
+        "html-void-elements": "^3.0.0",
+        "mdast-util-to-hast": "^13.0.0",
+        "property-information": "^7.0.0",
+        "space-separated-tokens": "^2.0.0",
+        "stringify-entities": "^4.0.0",
+        "zwitch": "^2.0.4"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/hast-util-whitespace": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/hast": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/highlight.js": {
+      "version": "11.10.0",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/hookable": {
+      "version": "5.5.3",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/html-void-elements": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/http-cache-semantics": {
+      "version": "4.1.1",
+      "dev": true,
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/i18next": {
+      "version": "20.6.1",
+      "resolved": "https://registry.npmmirror.com/i18next/-/i18next-20.6.1.tgz",
+      "integrity": "sha512-yCMYTMEJ9ihCwEQQ3phLo7I/Pwycf8uAx+sRHwwk5U9Aui/IZYgQRyMqXafQOw5QQ7DM1Z+WyEXWIqSuJHhG2A==",
+      "dependencies": {
+        "@babel/runtime": "^7.12.0"
+      }
+    },
+    "node_modules/ignore": {
+      "version": "5.3.2",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 4"
+      }
+    },
+    "node_modules/immediate": {
+      "version": "3.0.6",
+      "license": "MIT"
+    },
+    "node_modules/immer": {
+      "version": "9.0.21",
+      "resolved": "https://registry.npmmirror.com/immer/-/immer-9.0.21.tgz",
+      "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/immer"
+      }
+    },
+    "node_modules/import-fresh": {
+      "version": "3.3.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "parent-module": "^1.0.0",
+        "resolve-from": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/imurmurhash": {
+      "version": "0.1.4",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.8.19"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "license": "ISC"
+    },
+    "node_modules/is-arrayish": {
+      "version": "0.3.2",
+      "license": "MIT"
+    },
+    "node_modules/is-buffer": {
+      "version": "1.1.6",
+      "license": "MIT"
+    },
+    "node_modules/is-ci": {
+      "version": "3.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ci-info": "^3.2.0"
+      },
+      "bin": {
+        "is-ci": "bin.js"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-fullwidth-code-point": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-hotkey": {
+      "version": "0.2.0",
+      "resolved": "https://registry.npmmirror.com/is-hotkey/-/is-hotkey-0.2.0.tgz",
+      "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw=="
+    },
+    "node_modules/is-obj": {
+      "version": "2.0.0",
+      "resolved": "https://registry.npmmirror.com/is-obj/-/is-obj-2.0.0.tgz",
+      "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-plain-object": {
+      "version": "5.0.0",
+      "resolved": "https://registry.npmmirror.com/is-plain-object/-/is-plain-object-5.0.0.tgz",
+      "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-url": {
+      "version": "1.2.4",
+      "resolved": "https://registry.npmmirror.com/is-url/-/is-url-1.2.4.tgz",
+      "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
+    },
+    "node_modules/is-what": {
+      "version": "4.1.16",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=12.13"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mesqueeb"
+      }
+    },
+    "node_modules/isarray": {
+      "version": "1.0.0",
+      "license": "MIT"
+    },
+    "node_modules/isexe": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/joi": {
+      "version": "17.13.3",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "@hapi/hoek": "^9.3.0",
+        "@hapi/topo": "^5.1.0",
+        "@sideway/address": "^4.1.5",
+        "@sideway/formula": "^3.0.1",
+        "@sideway/pinpoint": "^2.0.0"
+      }
+    },
+    "node_modules/js-cookie": {
+      "version": "3.0.5",
+      "license": "MIT",
+      "engines": {
+        "node": ">=14"
+      }
+    },
+    "node_modules/js-yaml": {
+      "version": "4.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "argparse": "^2.0.1"
+      },
+      "bin": {
+        "js-yaml": "bin/js-yaml.js"
+      }
+    },
+    "node_modules/jsencrypt": {
+      "version": "3.3.1",
+      "resolved": "https://registry.npmmirror.com/jsencrypt/-/jsencrypt-3.3.1.tgz",
+      "integrity": "sha512-dVvV54GdFuJgmEKn+oBiaifDMen4p6o6j/lJh0OVMcouME8sST0bJ7bldIgKBQk4za0zyGn0/pm4vOznR25mLw=="
+    },
+    "node_modules/json-buffer": {
+      "version": "3.0.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-schema-traverse": {
+      "version": "0.4.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json-schema-typed": {
+      "version": "7.0.3",
+      "resolved": "https://registry.npmmirror.com/json-schema-typed/-/json-schema-typed-7.0.3.tgz",
+      "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A=="
+    },
+    "node_modules/json-stable-stringify-without-jsonify": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/json5": {
+      "version": "2.2.3",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "json5": "lib/cli.js"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/jsonfile": {
+      "version": "6.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "universalify": "^2.0.0"
+      },
+      "optionalDependencies": {
+        "graceful-fs": "^4.1.6"
+      }
+    },
+    "node_modules/jszip": {
+      "version": "3.10.1",
+      "license": "(MIT OR GPL-3.0-or-later)",
+      "dependencies": {
+        "lie": "~3.3.0",
+        "pako": "~1.0.2",
+        "readable-stream": "~2.3.6",
+        "setimmediate": "^1.0.5"
+      }
+    },
+    "node_modules/keyv": {
+      "version": "4.5.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "json-buffer": "3.0.1"
+      }
+    },
+    "node_modules/lazy-val": {
+      "version": "1.0.5",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/levn": {
+      "version": "0.4.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1",
+        "type-check": "~0.4.0"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/lie": {
+      "version": "3.3.0",
+      "license": "MIT",
+      "dependencies": {
+        "immediate": "~3.0.5"
+      }
+    },
+    "node_modules/locate-path": {
+      "version": "6.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-locate": "^5.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/lodash": {
+      "version": "4.17.21",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/lodash.camelcase": {
+      "version": "4.3.0",
+      "resolved": "https://registry.npmmirror.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+      "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="
+    },
+    "node_modules/lodash.clonedeep": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
+      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
+    },
+    "node_modules/lodash.debounce": {
+      "version": "4.0.8",
+      "resolved": "https://registry.npmmirror.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+      "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
+    },
+    "node_modules/lodash.foreach": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
+      "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ=="
+    },
+    "node_modules/lodash.isequal": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmmirror.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+      "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+      "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
+    },
+    "node_modules/lodash.merge": {
+      "version": "4.6.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/lodash.throttle": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmmirror.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz",
+      "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ=="
+    },
+    "node_modules/lodash.toarray": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmmirror.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
+      "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw=="
+    },
+    "node_modules/lowercase-keys": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/magic-string": {
+      "version": "0.30.17",
+      "license": "MIT",
+      "dependencies": {
+        "@jridgewell/sourcemap-codec": "^1.5.0"
+      }
+    },
+    "node_modules/mark.js": {
+      "version": "8.11.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/marked": {
+      "version": "13.0.0",
+      "license": "MIT",
+      "bin": {
+        "marked": "bin/marked.js"
+      },
+      "engines": {
+        "node": ">= 18"
+      }
+    },
+    "node_modules/matcher": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "optional": true,
+      "dependencies": {
+        "escape-string-regexp": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/math-intrinsics": {
+      "version": "1.1.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      }
+    },
+    "node_modules/md5": {
+      "version": "2.3.0",
+      "license": "BSD-3-Clause",
+      "dependencies": {
+        "charenc": "0.0.2",
+        "crypt": "0.0.2",
+        "is-buffer": "~1.1.6"
+      }
+    },
+    "node_modules/mdast-util-to-hast": {
+      "version": "13.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/hast": "^3.0.0",
+        "@types/mdast": "^4.0.0",
+        "@ungap/structured-clone": "^1.0.0",
+        "devlop": "^1.0.0",
+        "micromark-util-sanitize-uri": "^2.0.0",
+        "trim-lines": "^3.0.0",
+        "unist-util-position": "^5.0.0",
+        "unist-util-visit": "^5.0.0",
+        "vfile": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/micromark-util-character": {
+      "version": "2.1.1",
+      "dev": true,
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "micromark-util-symbol": "^2.0.0",
+        "micromark-util-types": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-encode": {
+      "version": "2.0.1",
+      "dev": true,
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/micromark-util-sanitize-uri": {
+      "version": "2.0.1",
+      "dev": true,
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "micromark-util-character": "^2.0.0",
+        "micromark-util-encode": "^2.0.0",
+        "micromark-util-symbol": "^2.0.0"
+      }
+    },
+    "node_modules/micromark-util-symbol": {
+      "version": "2.0.1",
+      "dev": true,
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/micromark-util-types": {
+      "version": "2.0.2",
+      "dev": true,
+      "funding": [
+        {
+          "type": "GitHub Sponsors",
+          "url": "https://github.com/sponsors/unifiedjs"
+        },
+        {
+          "type": "OpenCollective",
+          "url": "https://opencollective.com/unified"
+        }
+      ],
+      "license": "MIT"
+    },
+    "node_modules/mime-db": {
+      "version": "1.52.0",
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mime-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmmirror.com/mime-match/-/mime-match-1.0.2.tgz",
+      "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==",
+      "dependencies": {
+        "wildcard": "^1.1.0"
+      }
+    },
+    "node_modules/mime-types": {
+      "version": "2.1.35",
+      "license": "MIT",
+      "dependencies": {
+        "mime-db": "1.52.0"
+      },
+      "engines": {
+        "node": ">= 0.6"
+      }
+    },
+    "node_modules/mimic-fn": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-3.1.0.tgz",
+      "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/mimic-response": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.1.2",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/minimist": {
+      "version": "1.2.8",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/minipass": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "ISC",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/minisearch": {
+      "version": "7.1.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/mitt": {
+      "version": "3.0.1",
+      "license": "MIT"
+    },
+    "node_modules/ms": {
+      "version": "2.1.3",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/namespace-emitter": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmmirror.com/namespace-emitter/-/namespace-emitter-2.0.1.tgz",
+      "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g=="
+    },
+    "node_modules/nanoid": {
+      "version": "3.3.11",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "bin": {
+        "nanoid": "bin/nanoid.cjs"
+      },
+      "engines": {
+        "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+      }
+    },
+    "node_modules/natural-compare": {
+      "version": "1.4.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/next-tick": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmmirror.com/next-tick/-/next-tick-1.1.0.tgz",
+      "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
+    },
+    "node_modules/normalize-url": {
+      "version": "6.1.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/nth-check": {
+      "version": "2.1.1",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "boolbase": "^1.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/fb55/nth-check?sponsor=1"
+      }
+    },
+    "node_modules/number-precision": {
+      "version": "1.6.0",
+      "license": "MIT"
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/onetime": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz",
+      "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+      "dependencies": {
+        "mimic-fn": "^2.1.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/onetime/node_modules/mimic-fn": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz",
+      "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/oniguruma-to-es": {
+      "version": "2.3.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex-xs": "^1.0.0",
+        "regex": "^5.1.1",
+        "regex-recursion": "^5.1.1"
+      }
+    },
+    "node_modules/optionator": {
+      "version": "0.9.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "deep-is": "^0.1.3",
+        "fast-levenshtein": "^2.0.6",
+        "levn": "^0.4.1",
+        "prelude-ls": "^1.2.1",
+        "type-check": "^0.4.0",
+        "word-wrap": "^1.2.5"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/p-cancelable": {
+      "version": "2.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/p-limit": {
+      "version": "3.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "yocto-queue": "^0.1.0"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-locate": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "p-limit": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/p-try": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmmirror.com/p-try/-/p-try-2.2.0.tgz",
+      "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pako": {
+      "version": "1.0.11",
+      "license": "(MIT AND Zlib)"
+    },
+    "node_modules/parent-module": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "callsites": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/path-exists": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-key": {
+      "version": "3.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pend": {
+      "version": "1.2.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/perfect-debounce": {
+      "version": "1.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/picocolors": {
+      "version": "1.1.1",
+      "license": "ISC"
+    },
+    "node_modules/pinia": {
+      "version": "2.2.8",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.3",
+        "vue-demi": "^0.14.10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.4.0",
+        "typescript": ">=4.4.4",
+        "vue": "^2.6.14 || ^3.5.11"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        },
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinia/node_modules/vue-demi": {
+      "version": "0.14.10",
+      "hasInstallScript": true,
+      "license": "MIT",
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pkg-up": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmmirror.com/pkg-up/-/pkg-up-3.1.0.tgz",
+      "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
+      "dependencies": {
+        "find-up": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/pkg-up/node_modules/find-up": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/find-up/-/find-up-3.0.0.tgz",
+      "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+      "dependencies": {
+        "locate-path": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-up/node_modules/locate-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-3.0.0.tgz",
+      "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+      "dependencies": {
+        "p-locate": "^3.0.0",
+        "path-exists": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-up/node_modules/p-limit": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-2.3.0.tgz",
+      "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+      "dependencies": {
+        "p-try": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/pkg-up/node_modules/p-locate": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-3.0.0.tgz",
+      "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+      "dependencies": {
+        "p-limit": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/pkg-up/node_modules/path-exists": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz",
+      "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/postcss": {
+      "version": "8.5.3",
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "tidelift",
+          "url": "https://tidelift.com/funding/github/npm/postcss"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
+      "license": "MIT",
+      "dependencies": {
+        "nanoid": "^3.3.8",
+        "picocolors": "^1.1.1",
+        "source-map-js": "^1.2.1"
+      },
+      "engines": {
+        "node": "^10 || ^12 || >=14"
+      }
+    },
+    "node_modules/postcss-pxtorem": {
+      "version": "6.1.0",
+      "resolved": "https://registry.npmmirror.com/postcss-pxtorem/-/postcss-pxtorem-6.1.0.tgz",
+      "integrity": "sha512-ROODSNci9ADal3zUcPHOF/K83TiCgNSPXQFSbwyPHNV8ioHIE4SaC+FPOufd8jsr5jV2uIz29v1Uqy1c4ov42g==",
+      "peerDependencies": {
+        "postcss": "^8.0.0"
+      }
+    },
+    "node_modules/postcss-selector-parser": {
+      "version": "6.1.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "cssesc": "^3.0.0",
+        "util-deprecate": "^1.0.2"
+      },
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/preact": {
+      "version": "10.26.5",
+      "license": "MIT",
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/preact"
+      }
+    },
+    "node_modules/prelude-ls": {
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/prismjs": {
+      "version": "1.30.0",
+      "resolved": "https://registry.npmmirror.com/prismjs/-/prismjs-1.30.0.tgz",
+      "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/process-nextick-args": {
+      "version": "2.0.1",
+      "license": "MIT"
+    },
+    "node_modules/progress": {
+      "version": "2.0.3",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.4.0"
+      }
+    },
+    "node_modules/property-information": {
+      "version": "7.0.0",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/proxy-from-env": {
+      "version": "1.1.0",
+      "license": "MIT"
+    },
+    "node_modules/punycode": {
+      "version": "2.3.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=6"
+      }
+    },
+    "node_modules/quick-lru": {
+      "version": "5.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/read-config-file": {
+      "version": "6.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "dotenv": "^9.0.2",
+        "dotenv-expand": "^5.1.0",
+        "js-yaml": "^4.1.0",
+        "json5": "^2.2.0",
+        "lazy-val": "^1.0.4"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/read-config-file/node_modules/dotenv": {
+      "version": "9.0.2",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/read-config-file/node_modules/dotenv-expand": {
+      "version": "5.1.0",
+      "dev": true,
+      "license": "BSD-2-Clause"
+    },
+    "node_modules/readable-stream": {
+      "version": "2.3.8",
+      "license": "MIT",
+      "dependencies": {
+        "core-util-is": "~1.0.0",
+        "inherits": "~2.0.3",
+        "isarray": "~1.0.0",
+        "process-nextick-args": "~2.0.0",
+        "safe-buffer": "~5.1.1",
+        "string_decoder": "~1.1.1",
+        "util-deprecate": "~1.0.1"
+      }
+    },
+    "node_modules/regex": {
+      "version": "5.1.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "regex-utilities": "^2.3.0"
+      }
+    },
+    "node_modules/regex-recursion": {
+      "version": "5.1.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "regex": "^5.1.1",
+        "regex-utilities": "^2.3.0"
+      }
+    },
+    "node_modules/regex-utilities": {
+      "version": "2.3.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/require-directory": {
+      "version": "2.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/require-from-string": {
+      "version": "2.0.2",
+      "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz",
+      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/resize-observer-polyfill": {
+      "version": "1.5.1",
+      "license": "MIT"
+    },
+    "node_modules/resolve-alpn": {
+      "version": "1.2.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/resolve-from": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=4"
+      }
+    },
+    "node_modules/rfdc": {
+      "version": "1.4.1",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/rollup": {
+      "version": "4.40.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/estree": "1.0.7"
+      },
+      "bin": {
+        "rollup": "dist/bin/rollup"
+      },
+      "engines": {
+        "node": ">=18.0.0",
+        "npm": ">=8.0.0"
+      },
+      "optionalDependencies": {
+        "@rollup/rollup-android-arm-eabi": "4.40.1",
+        "@rollup/rollup-android-arm64": "4.40.1",
+        "@rollup/rollup-darwin-arm64": "4.40.1",
+        "@rollup/rollup-darwin-x64": "4.40.1",
+        "@rollup/rollup-freebsd-arm64": "4.40.1",
+        "@rollup/rollup-freebsd-x64": "4.40.1",
+        "@rollup/rollup-linux-arm-gnueabihf": "4.40.1",
+        "@rollup/rollup-linux-arm-musleabihf": "4.40.1",
+        "@rollup/rollup-linux-arm64-gnu": "4.40.1",
+        "@rollup/rollup-linux-arm64-musl": "4.40.1",
+        "@rollup/rollup-linux-loongarch64-gnu": "4.40.1",
+        "@rollup/rollup-linux-powerpc64le-gnu": "4.40.1",
+        "@rollup/rollup-linux-riscv64-gnu": "4.40.1",
+        "@rollup/rollup-linux-riscv64-musl": "4.40.1",
+        "@rollup/rollup-linux-s390x-gnu": "4.40.1",
+        "@rollup/rollup-linux-x64-gnu": "4.40.1",
+        "@rollup/rollup-linux-x64-musl": "4.40.1",
+        "@rollup/rollup-win32-arm64-msvc": "4.40.1",
+        "@rollup/rollup-win32-ia32-msvc": "4.40.1",
+        "@rollup/rollup-win32-x64-msvc": "4.40.1",
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/rxjs": {
+      "version": "7.8.2",
+      "dev": true,
+      "license": "Apache-2.0",
+      "dependencies": {
+        "tslib": "^2.1.0"
+      }
+    },
+    "node_modules/safe-buffer": {
+      "version": "5.1.2",
+      "license": "MIT"
+    },
+    "node_modules/safer-buffer": {
+      "version": "2.1.2",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/sanitize-filename": {
+      "version": "1.6.3",
+      "dev": true,
+      "license": "WTFPL OR ISC",
+      "dependencies": {
+        "truncate-utf8-bytes": "^1.0.0"
+      }
+    },
+    "node_modules/sanitize-filename/node_modules/truncate-utf8-bytes": {
+      "version": "1.0.2",
+      "dev": true,
+      "license": "WTFPL",
+      "dependencies": {
+        "utf8-byte-length": "^1.0.1"
+      }
+    },
+    "node_modules/screenfull": {
+      "version": "6.0.2",
+      "license": "MIT",
+      "engines": {
+        "node": "^14.13.1 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/scroll-into-view-if-needed": {
+      "version": "2.2.31",
+      "license": "MIT",
+      "dependencies": {
+        "compute-scroll-into-view": "^1.0.20"
+      }
+    },
+    "node_modules/search-insights": {
+      "version": "2.17.3",
+      "dev": true,
+      "license": "MIT",
+      "peer": true
+    },
+    "node_modules/select": {
+      "version": "1.1.2",
+      "license": "MIT"
+    },
+    "node_modules/semver": {
+      "version": "7.7.1",
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      },
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/setimmediate": {
+      "version": "1.0.5",
+      "license": "MIT"
+    },
+    "node_modules/shebang-command": {
+      "version": "2.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "shebang-regex": "^3.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shebang-regex": {
+      "version": "3.0.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/shell-quote": {
+      "version": "1.8.2",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 0.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/shiki": {
+      "version": "1.29.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@shikijs/core": "1.29.2",
+        "@shikijs/engine-javascript": "1.29.2",
+        "@shikijs/engine-oniguruma": "1.29.2",
+        "@shikijs/langs": "1.29.2",
+        "@shikijs/themes": "1.29.2",
+        "@shikijs/types": "1.29.2",
+        "@shikijs/vscode-textmate": "^10.0.1",
+        "@types/hast": "^3.0.4"
+      }
+    },
+    "node_modules/simple-swizzle": {
+      "version": "0.2.2",
+      "license": "MIT",
+      "dependencies": {
+        "is-arrayish": "^0.3.1"
+      }
+    },
+    "node_modules/simple-update-notifier": {
+      "version": "1.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "semver": "~7.0.0"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/simple-update-notifier/node_modules/semver": {
+      "version": "7.0.0",
+      "dev": true,
+      "license": "ISC",
+      "bin": {
+        "semver": "bin/semver.js"
+      }
+    },
+    "node_modules/slate": {
+      "version": "0.72.8",
+      "resolved": "https://registry.npmmirror.com/slate/-/slate-0.72.8.tgz",
+      "integrity": "sha512-/nJwTswQgnRurpK+bGJFH1oM7naD5qDmHd89JyiKNT2oOKD8marW0QSBtuFnwEbL5aGCS8AmrhXQgNOsn4osAw==",
+      "dependencies": {
+        "immer": "^9.0.6",
+        "is-plain-object": "^5.0.0",
+        "tiny-warning": "^1.0.3"
+      }
+    },
+    "node_modules/slate-history": {
+      "version": "0.66.0",
+      "resolved": "https://registry.npmmirror.com/slate-history/-/slate-history-0.66.0.tgz",
+      "integrity": "sha512-6MWpxGQZiMvSINlCbMW43E2YBSVMCMCIwQfBzGssjWw4kb0qfvj0pIdblWNRQZD0hR6WHP+dHHgGSeVdMWzfng==",
+      "dependencies": {
+        "is-plain-object": "^5.0.0"
+      },
+      "peerDependencies": {
+        "slate": ">=0.65.3"
+      }
+    },
+    "node_modules/snabbdom": {
+      "version": "3.6.2",
+      "resolved": "https://registry.npmmirror.com/snabbdom/-/snabbdom-3.6.2.tgz",
+      "integrity": "sha512-ig5qOnCDbugFntKi6c7Xlib8bA6xiJVk8O+WdFrV3wxbMqeHO0hXFQC4nAhPVWfZfi8255lcZkNhtIBINCc4+Q==",
+      "engines": {
+        "node": ">=12.17.0"
+      }
+    },
+    "node_modules/source-map-js": {
+      "version": "1.2.1",
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/source-map-support": {
+      "version": "0.5.21",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "buffer-from": "^1.0.0",
+        "source-map": "^0.6.0"
+      }
+    },
+    "node_modules/source-map-support/node_modules/source-map": {
+      "version": "0.6.1",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/space-separated-tokens": {
+      "version": "2.0.2",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/spawn-command": {
+      "version": "0.0.2",
+      "dev": true
+    },
+    "node_modules/speakingurl": {
+      "version": "14.0.1",
+      "dev": true,
+      "license": "BSD-3-Clause",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/ssr-window": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmmirror.com/ssr-window/-/ssr-window-3.0.0.tgz",
+      "integrity": "sha512-q+8UfWDg9Itrg0yWK7oe5p/XRCJpJF9OBtXfOPgSJl+u3Xd5KI328RUEvUqSMVM9CiQUEf1QdBzJMkYGErj9QA=="
+    },
+    "node_modules/string_decoder": {
+      "version": "1.1.1",
+      "license": "MIT",
+      "dependencies": {
+        "safe-buffer": "~5.1.0"
+      }
+    },
+    "node_modules/string-width": {
+      "version": "4.2.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "emoji-regex": "^8.0.0",
+        "is-fullwidth-code-point": "^3.0.0",
+        "strip-ansi": "^6.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/string-width/node_modules/emoji-regex": {
+      "version": "8.0.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/stringify-entities": {
+      "version": "4.0.4",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "character-entities-html4": "^2.0.0",
+        "character-entities-legacy": "^3.0.0"
+      },
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/strip-ansi": {
+      "version": "6.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "ansi-regex": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/strip-json-comments": {
+      "version": "3.1.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=8"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/superjson": {
+      "version": "2.2.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "copy-anything": "^3.0.2"
+      },
+      "engines": {
+        "node": ">=16"
+      }
+    },
+    "node_modules/supports-color": {
+      "version": "7.2.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "has-flag": "^4.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/tabbable": {
+      "version": "6.2.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/tiny-emitter": {
+      "version": "2.1.0",
+      "license": "MIT"
+    },
+    "node_modules/tiny-warning": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmmirror.com/tiny-warning/-/tiny-warning-1.0.3.tgz",
+      "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+    },
+    "node_modules/tree-kill": {
+      "version": "1.2.2",
+      "dev": true,
+      "license": "MIT",
+      "bin": {
+        "tree-kill": "cli.js"
+      }
+    },
+    "node_modules/trim-lines": {
+      "version": "3.0.1",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    },
+    "node_modules/tslib": {
+      "version": "2.8.1",
+      "dev": true,
+      "license": "0BSD"
+    },
+    "node_modules/type": {
+      "version": "2.7.3",
+      "resolved": "https://registry.npmmirror.com/type/-/type-2.7.3.tgz",
+      "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ=="
+    },
+    "node_modules/type-check": {
+      "version": "0.4.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "prelude-ls": "^1.2.1"
+      },
+      "engines": {
+        "node": ">= 0.8.0"
+      }
+    },
+    "node_modules/type-fest": {
+      "version": "0.20.2",
+      "dev": true,
+      "license": "(MIT OR CC0-1.0)",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/undici-types": {
+      "version": "6.21.0",
+      "dev": true,
+      "license": "MIT"
+    },
+    "node_modules/unist-util-is": {
+      "version": "6.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-position": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-stringify-position": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-visit": {
+      "version": "5.0.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "unist-util-is": "^6.0.0",
+        "unist-util-visit-parents": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/unist-util-visit-parents": {
+      "version": "6.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "unist-util-is": "^6.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/universalify": {
+      "version": "2.0.1",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">= 10.0.0"
+      }
+    },
+    "node_modules/uri-js": {
+      "version": "4.4.1",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "dependencies": {
+        "punycode": "^2.1.0"
+      }
+    },
+    "node_modules/utf8-byte-length": {
+      "version": "1.0.5",
+      "dev": true,
+      "license": "(WTFPL OR MIT)"
+    },
+    "node_modules/util-deprecate": {
+      "version": "1.0.2",
+      "license": "MIT"
+    },
+    "node_modules/vfile": {
+      "version": "6.0.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "vfile-message": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/vfile-message": {
+      "version": "4.0.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@types/unist": "^3.0.0",
+        "unist-util-stringify-position": "^4.0.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/unified"
+      }
+    },
+    "node_modules/vite": {
+      "version": "5.4.11",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "esbuild": "^0.21.3",
+        "postcss": "^8.4.43",
+        "rollup": "^4.20.0"
+      },
+      "bin": {
+        "vite": "bin/vite.js"
+      },
+      "engines": {
+        "node": "^18.0.0 || >=20.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/vitejs/vite?sponsor=1"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.3"
+      },
+      "peerDependencies": {
+        "@types/node": "^18.0.0 || >=20.0.0",
+        "less": "*",
+        "lightningcss": "^1.21.0",
+        "sass": "*",
+        "sass-embedded": "*",
+        "stylus": "*",
+        "sugarss": "*",
+        "terser": "^5.4.0"
+      },
+      "peerDependenciesMeta": {
+        "@types/node": {
+          "optional": true
+        },
+        "less": {
+          "optional": true
+        },
+        "lightningcss": {
+          "optional": true
+        },
+        "sass": {
+          "optional": true
+        },
+        "sass-embedded": {
+          "optional": true
+        },
+        "stylus": {
+          "optional": true
+        },
+        "sugarss": {
+          "optional": true
+        },
+        "terser": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vitepress": {
+      "version": "1.5.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@docsearch/css": "^3.6.2",
+        "@docsearch/js": "^3.6.2",
+        "@iconify-json/simple-icons": "^1.2.10",
+        "@shikijs/core": "^1.22.2",
+        "@shikijs/transformers": "^1.22.2",
+        "@shikijs/types": "^1.22.2",
+        "@types/markdown-it": "^14.1.2",
+        "@vitejs/plugin-vue": "^5.1.4",
+        "@vue/devtools-api": "^7.5.4",
+        "@vue/shared": "^3.5.12",
+        "@vueuse/core": "^11.1.0",
+        "@vueuse/integrations": "^11.1.0",
+        "focus-trap": "^7.6.0",
+        "mark.js": "8.11.1",
+        "minisearch": "^7.1.0",
+        "shiki": "^1.22.2",
+        "vite": "^5.4.10",
+        "vue": "^3.5.12"
+      },
+      "bin": {
+        "vitepress": "bin/vitepress.js"
+      },
+      "peerDependencies": {
+        "markdown-it-mathjax3": "^4",
+        "postcss": "^8"
+      },
+      "peerDependenciesMeta": {
+        "markdown-it-mathjax3": {
+          "optional": true
+        },
+        "postcss": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vitepress/node_modules/@vue/devtools-api": {
+      "version": "7.7.6",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-kit": "^7.7.6"
+      }
+    },
+    "node_modules/vue": {
+      "version": "3.5.13",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/compiler-dom": "3.5.13",
+        "@vue/compiler-sfc": "3.5.13",
+        "@vue/runtime-dom": "3.5.13",
+        "@vue/server-renderer": "3.5.13",
+        "@vue/shared": "3.5.13"
+      },
+      "peerDependencies": {
+        "typescript": "*"
+      },
+      "peerDependenciesMeta": {
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/vue-eslint-parser": {
+      "version": "9.4.3",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "debug": "^4.3.4",
+        "eslint-scope": "^7.1.1",
+        "eslint-visitor-keys": "^3.3.0",
+        "espree": "^9.3.1",
+        "esquery": "^1.4.0",
+        "lodash": "^4.17.21",
+        "semver": "^7.3.6"
+      },
+      "engines": {
+        "node": "^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/mysticatea"
+      },
+      "peerDependencies": {
+        "eslint": ">=6.0.0"
+      }
+    },
+    "node_modules/vue-eslint-parser/node_modules/eslint-scope": {
+      "version": "7.2.2",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "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/vue-eslint-parser/node_modules/eslint-visitor-keys": {
+      "version": "3.4.3",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+      },
+      "funding": {
+        "url": "https://opencollective.com/eslint"
+      }
+    },
+    "node_modules/vue-eslint-parser/node_modules/espree": {
+      "version": "9.6.1",
+      "dev": true,
+      "license": "BSD-2-Clause",
+      "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/vue-i18n": {
+      "version": "10.0.5",
+      "license": "MIT",
+      "dependencies": {
+        "@intlify/core-base": "10.0.5",
+        "@intlify/shared": "10.0.5",
+        "@vue/devtools-api": "^6.5.0"
+      },
+      "engines": {
+        "node": ">= 16"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/kazupon"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/vue-router": {
+      "version": "4.5.0",
+      "license": "MIT",
+      "dependencies": {
+        "@vue/devtools-api": "^6.6.4"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "vue": "^3.2.0"
+      }
+    },
+    "node_modules/wait-on": {
+      "version": "7.0.1",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "axios": "^0.27.2",
+        "joi": "^17.7.0",
+        "lodash": "^4.17.21",
+        "minimist": "^1.2.7",
+        "rxjs": "^7.8.0"
+      },
+      "bin": {
+        "wait-on": "bin/wait-on"
+      },
+      "engines": {
+        "node": ">=12.0.0"
+      }
+    },
+    "node_modules/wait-on/node_modules/axios": {
+      "version": "0.27.2",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "follow-redirects": "^1.14.9",
+        "form-data": "^4.0.0"
+      }
+    },
+    "node_modules/which": {
+      "version": "2.0.2",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "isexe": "^2.0.0"
+      },
+      "bin": {
+        "node-which": "bin/node-which"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/wildcard": {
+      "version": "1.1.2",
+      "resolved": "https://registry.npmmirror.com/wildcard/-/wildcard-1.1.2.tgz",
+      "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng=="
+    },
+    "node_modules/word-wrap": {
+      "version": "1.2.5",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/wrap-ansi": {
+      "version": "7.0.0",
+      "dev": true,
+      "license": "MIT",
+      "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",
+      "dev": true,
+      "license": "ISC"
+    },
+    "node_modules/wujie": {
+      "version": "1.0.23",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime": "^7.18.6"
+      }
+    },
+    "node_modules/wujie-vue3": {
+      "version": "1.0.23",
+      "license": "MIT",
+      "dependencies": {
+        "wujie": "1.0.23"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/xml-name-validator": {
+      "version": "4.0.0",
+      "dev": true,
+      "license": "Apache-2.0",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs": {
+      "version": "17.7.2",
+      "dev": true,
+      "license": "MIT",
+      "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/node_modules/cliui": {
+      "version": "8.0.1",
+      "dev": true,
+      "license": "ISC",
+      "dependencies": {
+        "string-width": "^4.2.0",
+        "strip-ansi": "^6.0.1",
+        "wrap-ansi": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yargs/node_modules/y18n": {
+      "version": "5.0.8",
+      "dev": true,
+      "license": "ISC",
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/yargs/node_modules/yargs-parser": {
+      "version": "21.1.1",
+      "dev": true,
+      "license": "ISC",
+      "engines": {
+        "node": ">=12"
+      }
+    },
+    "node_modules/yauzl": {
+      "version": "2.10.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "buffer-crc32": "~0.2.3",
+        "fd-slicer": "~1.1.0"
+      }
+    },
+    "node_modules/yauzl/node_modules/fd-slicer": {
+      "version": "1.1.0",
+      "dev": true,
+      "license": "MIT",
+      "dependencies": {
+        "pend": "~1.2.0"
+      }
+    },
+    "node_modules/yocto-queue": {
+      "version": "0.1.0",
+      "dev": true,
+      "license": "MIT",
+      "engines": {
+        "node": ">=10"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
+    },
+    "node_modules/zrender": {
+      "version": "5.6.1",
+      "resolved": "https://registry.npmmirror.com/zrender/-/zrender-5.6.1.tgz",
+      "integrity": "sha512-OFXkDJKcrlx5su2XbzJvj/34Q3m6PvyCZkVPHGYpcCJ52ek4U/ymZyfuV1nKE23AyBJ51E/6Yr0mhZ7xGTO4ag==",
+      "dependencies": {
+        "tslib": "2.3.0"
+      }
+    },
+    "node_modules/zrender/node_modules/tslib": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
+      "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg=="
+    },
+    "node_modules/zwitch": {
+      "version": "2.0.4",
+      "dev": true,
+      "license": "MIT",
+      "funding": {
+        "type": "github",
+        "url": "https://github.com/sponsors/wooorm"
+      }
+    }
+  }
+}

+ 84 - 0
package.json

@@ -0,0 +1,84 @@
+{
+  "name": "SmartChat",
+  "version": "1.0.0",
+  "main": "electron.main.js",
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "description": "Smart Chat App",
+  "scripts": {
+    "dev": "cross-env NODE_ENV=development vite",
+    "electron:serve": "cross-env NODE_ENV=development concurrently \"npm run dev\" \"wait-on http://localhost:5173 && electron .\"",
+    "build": "cross-env NODE_ENV=production vite build",
+    "electron:build": "cross-env NODE_ENV=production vite build && electron-builder",
+    "doc": "vitepress dev docs --port 5174 --host",
+    "doc-build": "vitepress build docs"
+  },
+  "devDependencies": {
+    "@vitejs/plugin-vue": "5.2.1",
+    "concurrently": "8.2.1",
+    "cross-env": "7.0.3",
+    "electron": "25.3.1",
+    "electron-builder": "23.6.0",
+    "eslint": "9.16.0",
+    "eslint-plugin-vue": "9.32.0",
+    "vite": "5.4.11",
+    "vitepress": "1.5.0",
+    "wait-on": "7.0.1"
+  },
+  "dependencies": {
+    "@arco-design/web-vue": "2.56.3",
+    "@microsoft/fetch-event-source": "2.0.1",
+    "@wangeditor/editor": "^5.1.23",
+    "@wangeditor/editor-for-vue": "^5.1.12",
+    "axios": "1.7.8",
+    "clipboard": "2.0.11",
+    "dayjs": "1.11.13",
+    "docx-preview": "0.3.3",
+    "echarts": "^5.6.0",
+    "electron-store": "^8.2.0",
+    "filesize": "10.1.6",
+    "highlight.js": "11.10.0",
+    "js-cookie": "3.0.5",
+    "jsencrypt": "^3.3.1",
+    "katex": "^0.16.22",
+    "marked": "13.0.0",
+    "md5": "2.3.0",
+    "mitt": "3.0.1",
+    "pinia": "2.2.8",
+    "postcss-pxtorem": "^6.1.0",
+    "screenfull": "6.0.2",
+    "vue": "3.5.13",
+    "vue-i18n": "10.0.5",
+    "vue-router": "4.5.0",
+    "wujie-vue3": "1.0.23"
+  },
+  "build": {
+    "appId": "com.example.damoxing_desk",
+    "productName": "智库问答助手",
+    "directories": {
+      "output": "dist_electron"
+    },
+    "icon": "tray-icon.png",
+    "files": [
+      "dist/**/*",
+      "electron.main.js",
+      "preload.js",
+      "public/logo.png"
+    ],
+    "extraResources": [
+      {
+        "from": "tray-icon.png",
+        "to": "tray-icon.png"
+      }
+    ],
+    "nsis": {
+      "oneClick": false,
+      "allowToChangeInstallationDirectory": true,
+      "createDesktopShortcut": true,
+      "createStartMenuShortcut": true,
+      "shortcutName": "智库问答助手"
+    }
+
+  }
+}

+ 26 - 0
preload.js

@@ -0,0 +1,26 @@
+
+const { contextBridge, ipcRenderer } = require('electron');
+
+contextBridge.exposeInMainWorld('electronAPI', {
+  openWindow: () => ipcRenderer.send('open-window'),
+  resizeMainWindow: (width, height) => ipcRenderer.send('resize-main-window', width, height),
+  openSmartWindow: () => ipcRenderer.send('open-smart-window'),
+  toggleSmartWindow: () => ipcRenderer.send('toggle-smart-window'),
+  closeSmartWindow: () => ipcRenderer.send('close-smart-window'),
+  resizeSmartWindow: (height) => ipcRenderer.send('resize-smart-window', height),
+  setFloatWindowPosition: (x, y) => ipcRenderer.send('set-float-window-position', x, y),
+  getWindowPosition: () => ipcRenderer.invoke('get-float-window-position'),
+  showTooltip: (adsorbedPosition) => ipcRenderer.send('show-tooltip', adsorbedPosition),
+  hideTooltip: () => ipcRenderer.send('hide-tooltip'),
+  getSmartWindowPosition: () => ipcRenderer.invoke('get-smart-window-position'),
+  setSmartWindowPosition: (x, y) => ipcRenderer.send('set-smart-window-position', x, y),
+  hideTrayFloatWindow: () => ipcRenderer.send('hide-tray-float-window'),
+  showTrayFloatWindow: () => ipcRenderer.send('show-tray-float-window'),
+  setLoginStateWindow: (is_login) => ipcRenderer.send('set-login-state', is_login),
+  saveAuth: (username, password, token) => ipcRenderer.invoke('save-auth', username, password, token),
+  getUsername: () => ipcRenderer.invoke('get-username'),
+  getPassword: () => ipcRenderer.invoke('get-password'),
+  getToken: () => ipcRenderer.invoke('get-token'),
+  clearAuth: () => ipcRenderer.invoke('clear-auth'),
+  toLayout: () => ipcRenderer.send('logout'),
+});

+ 49 - 0
public/config.js

@@ -0,0 +1,49 @@
+window.DMX_VERSION = "1.0.1";
+
+window.API_BASE_URL = 'http://25.214.216.111:9000'
+// window.API_BASE_URL_SSE = 'http://25.214.216.111:9000/smart/'
+
+
+// 百度千帆
+
+window.API_KEY_BD = 'private-x|eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1YThjMWQ1ZC02YmE4LTQzY2MtYTY5OC1lZTJkZDQ4ZTk4NDUiLCJzdWIiOiJwcm9qLTR0dDJ1b3lreXI5dnFqeWsifQ.yijxBW6YLFglO7_VQmDkjCe-KZP4uiFajaiftuWiq_M'
+// 应用ID(每次打包前需要修改,尤其桌面端)
+// 线上平台
+window.APP_ID = '920b7a5f-0c16-4cf0-add1-99631a784684'
+// 本地调试
+// window.APP_ID = '120ddab6-7db0-4d2a-ad0d-4ee56508fde2'
+
+
+// 阿里百炼智能体参数(报告)
+window.APP_ID_AL = "52159216-feb2-4918-86a3-2b384c735580"
+// window.APP_VERSION_AL = "1750039714487"
+window.APP_VERSION_AL = "1750227083021"
+
+
+// 阿里百炼智能体参数(问数)
+window.APP_ID_AL_WS = "c16b35ec-85a7-4bb8-a841-645569e99e53"
+// window.APP_VERSION_AL = "1750039714487"
+window.APP_VERSION_AL_WS = "1754962461212"
+
+
+
+// 手机端i国网下载链接
+// 苹果手机连接
+window.iPhone_LINK = 'https://apps.apple.com/cn/app/i%E5%9B%BD%E7%BD%91/id1586964186'
+// 安卓手机链接
+window.Android_LINK = 'https://url.cloud.huawei.com/vQNLcor8qI'
+
+
+// 智能体开关控制
+window.AGENT = {
+  znwd: true,
+  bgsc: true,
+  znws: true,
+  bgcl: true,
+}
+
+
+// 表格处理(智能报表),自定义问题
+window.bgcl_question = "数据处理,并标注表格中的异常值"
+window.bgcl_content = '表格解析完成,请配置表格数据校验规则'
+window.bgcl_error_content = '表格合并失败,请稍候重试!'

BIN
public/logo.png


BIN
public/tray-icon.ico


BIN
public/tray-icon.png


+ 1 - 0
src/3rd-libs/README.md

@@ -0,0 +1 @@
+# 第三方依赖项

+ 14 - 0
src/3rd-libs/clipboard.js

@@ -0,0 +1,14 @@
+/**
+ * https://www.npmjs.com/package/clipboard
+ * https://github.com/zenorocha/clipboard.js
+ */
+
+import Clipboard from 'clipboard';
+
+/**
+ * 在剪贴板复制一个字符串
+ * @param {string} str
+ */
+export default function copyText(str) {
+  Clipboard.copy(str);
+}

+ 29 - 0
src/3rd-libs/docx-preview.js

@@ -0,0 +1,29 @@
+/**
+ * 使用此组件,依赖 jszip 库
+ * 在使用时,需要先安装 jszip
+ * @see https://www.npmjs.com/package/docx-preview
+ * @see https://www.npmjs.com/package/jszip
+ */
+
+/**
+ * 渲染blob数据
+ * @param {Element} ele
+ * @param {Blob} blob
+ * @returns
+ */
+export const renderDocxByBlob = (ele, blob) => {
+  return new Promise((resolve, reject) => {
+    import('./docx-preview/docx-preview.min.mjs')
+      .then((res) => {
+        const renderAsync = res.renderAsync;
+
+        renderAsync(blob, ele);
+
+        resolve();
+      })
+      .catch((err) => {
+        console.log('docx-preview.mjs 加载失败');
+        reject(err);
+      });
+  });
+};

+ 25 - 0
src/3rd-libs/docx-preview/docx-preview.d.ts

@@ -0,0 +1,25 @@
+export interface Options {
+    inWrapper: boolean;
+    ignoreWidth: boolean;
+    ignoreHeight: boolean;
+    ignoreFonts: boolean;
+    breakPages: boolean;
+    debug: boolean;
+    experimental: boolean;
+    className: string;
+    trimXmlDeclaration: boolean;
+    renderHeaders: boolean;
+    renderFooters: boolean;
+    renderFootnotes: boolean;
+    renderEndnotes: boolean;
+    ignoreLastRenderedPageBreak: boolean;
+    useBase64URL: boolean;
+    renderChanges: boolean;
+    renderComments: boolean;
+}
+//stub
+export type WordDocument = any;
+export declare const defaultOptions: Options;
+export declare function parseAsync(data: Blob | any, userOptions?: Partial<Options>): Promise<WordDocument>;
+export declare function renderDocument(document: WordDocument, bodyContainer: HTMLElement, styleContainer?: HTMLElement, userOptions?: Partial<Options>): Promise<any>;
+export declare function renderAsync(data: Blob | any, bodyContainer: HTMLElement, styleContainer?: HTMLElement, userOptions?: Partial<Options>): Promise<any>;

+ 3903 - 0
src/3rd-libs/docx-preview/docx-preview.js

@@ -0,0 +1,3903 @@
+(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('jszip')) :
+    typeof define === 'function' && define.amd ? define(['exports', 'jszip'], factory) :
+    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.docx = {}, global.JSZip));
+})(this, (function (exports, JSZip) { 'use strict';
+
+    var RelationshipTypes;
+    (function (RelationshipTypes) {
+        RelationshipTypes["OfficeDocument"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
+        RelationshipTypes["FontTable"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
+        RelationshipTypes["Image"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
+        RelationshipTypes["Numbering"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering";
+        RelationshipTypes["Styles"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
+        RelationshipTypes["StylesWithEffects"] = "http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects";
+        RelationshipTypes["Theme"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
+        RelationshipTypes["Settings"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
+        RelationshipTypes["WebSettings"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings";
+        RelationshipTypes["Hyperlink"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
+        RelationshipTypes["Footnotes"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes";
+        RelationshipTypes["Endnotes"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes";
+        RelationshipTypes["Footer"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
+        RelationshipTypes["Header"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
+        RelationshipTypes["ExtendedProperties"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
+        RelationshipTypes["CoreProperties"] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+        RelationshipTypes["CustomProperties"] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/custom-properties";
+        RelationshipTypes["Comments"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
+        RelationshipTypes["CommentsExtended"] = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
+    })(RelationshipTypes || (RelationshipTypes = {}));
+    function parseRelationships(root, xml) {
+        return xml.elements(root).map(e => ({
+            id: xml.attr(e, "Id"),
+            type: xml.attr(e, "Type"),
+            target: xml.attr(e, "Target"),
+            targetMode: xml.attr(e, "TargetMode")
+        }));
+    }
+
+    const ns$1 = {
+        wordml: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+        drawingml: "http://schemas.openxmlformats.org/drawingml/2006/main",
+        picture: "http://schemas.openxmlformats.org/drawingml/2006/picture",
+        compatibility: "http://schemas.openxmlformats.org/markup-compatibility/2006",
+        math: "http://schemas.openxmlformats.org/officeDocument/2006/math"
+    };
+    const LengthUsage = {
+        Dxa: { mul: 0.05, unit: "pt" },
+        Emu: { mul: 1 / 12700, unit: "pt" },
+        FontSize: { mul: 0.5, unit: "pt" },
+        Border: { mul: 0.125, unit: "pt" },
+        Point: { mul: 1, unit: "pt" },
+        Percent: { mul: 0.02, unit: "%" },
+        LineHeight: { mul: 1 / 240, unit: "" },
+        VmlEmu: { mul: 1 / 12700, unit: "" },
+    };
+    function convertLength(val, usage = LengthUsage.Dxa) {
+        if (val == null || /.+(p[xt]|[%])$/.test(val)) {
+            return val;
+        }
+        return `${(parseInt(val) * usage.mul).toFixed(2)}${usage.unit}`;
+    }
+    function convertBoolean(v, defaultValue = false) {
+        switch (v) {
+            case "1": return true;
+            case "0": return false;
+            case "on": return true;
+            case "off": return false;
+            case "true": return true;
+            case "false": return false;
+            default: return defaultValue;
+        }
+    }
+    function parseCommonProperty(elem, props, xml) {
+        if (elem.namespaceURI != ns$1.wordml)
+            return false;
+        switch (elem.localName) {
+            case "color":
+                props.color = xml.attr(elem, "val");
+                break;
+            case "sz":
+                props.fontSize = xml.lengthAttr(elem, "val", LengthUsage.FontSize);
+                break;
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    function parseXmlString(xmlString, trimXmlDeclaration = false) {
+        if (trimXmlDeclaration)
+            xmlString = xmlString.replace(/<[?].*[?]>/, "");
+        xmlString = removeUTF8BOM(xmlString);
+        const result = new DOMParser().parseFromString(xmlString, "application/xml");
+        const errorText = hasXmlParserError(result);
+        if (errorText)
+            throw new Error(errorText);
+        return result;
+    }
+    function hasXmlParserError(doc) {
+        return doc.getElementsByTagName("parsererror")[0]?.textContent;
+    }
+    function removeUTF8BOM(data) {
+        return data.charCodeAt(0) === 0xFEFF ? data.substring(1) : data;
+    }
+    function serializeXmlString(elem) {
+        return new XMLSerializer().serializeToString(elem);
+    }
+    class XmlParser {
+        elements(elem, localName = null) {
+            const result = [];
+            for (let i = 0, l = elem.childNodes.length; i < l; i++) {
+                let c = elem.childNodes.item(i);
+                if (c.nodeType == 1 && (localName == null || c.localName == localName))
+                    result.push(c);
+            }
+            return result;
+        }
+        element(elem, localName) {
+            for (let i = 0, l = elem.childNodes.length; i < l; i++) {
+                let c = elem.childNodes.item(i);
+                if (c.nodeType == 1 && c.localName == localName)
+                    return c;
+            }
+            return null;
+        }
+        elementAttr(elem, localName, attrLocalName) {
+            var el = this.element(elem, localName);
+            return el ? this.attr(el, attrLocalName) : undefined;
+        }
+        attrs(elem) {
+            return Array.from(elem.attributes);
+        }
+        attr(elem, localName) {
+            for (let i = 0, l = elem.attributes.length; i < l; i++) {
+                let a = elem.attributes.item(i);
+                if (a.localName == localName)
+                    return a.value;
+            }
+            return null;
+        }
+        intAttr(node, attrName, defaultValue = null) {
+            var val = this.attr(node, attrName);
+            return val ? parseInt(val) : defaultValue;
+        }
+        hexAttr(node, attrName, defaultValue = null) {
+            var val = this.attr(node, attrName);
+            return val ? parseInt(val, 16) : defaultValue;
+        }
+        floatAttr(node, attrName, defaultValue = null) {
+            var val = this.attr(node, attrName);
+            return val ? parseFloat(val) : defaultValue;
+        }
+        boolAttr(node, attrName, defaultValue = null) {
+            return convertBoolean(this.attr(node, attrName), defaultValue);
+        }
+        lengthAttr(node, attrName, usage = LengthUsage.Dxa) {
+            return convertLength(this.attr(node, attrName), usage);
+        }
+    }
+    const globalXmlParser = new XmlParser();
+
+    class Part {
+        constructor(_package, path) {
+            this._package = _package;
+            this.path = path;
+        }
+        async load() {
+            this.rels = await this._package.loadRelationships(this.path);
+            const xmlText = await this._package.load(this.path);
+            const xmlDoc = this._package.parseXmlDocument(xmlText);
+            if (this._package.options.keepOrigin) {
+                this._xmlDocument = xmlDoc;
+            }
+            this.parseXml(xmlDoc.firstElementChild);
+        }
+        save() {
+            this._package.update(this.path, serializeXmlString(this._xmlDocument));
+        }
+        parseXml(root) {
+        }
+    }
+
+    const embedFontTypeMap = {
+        embedRegular: 'regular',
+        embedBold: 'bold',
+        embedItalic: 'italic',
+        embedBoldItalic: 'boldItalic',
+    };
+    function parseFonts(root, xml) {
+        return xml.elements(root).map(el => parseFont(el, xml));
+    }
+    function parseFont(elem, xml) {
+        let result = {
+            name: xml.attr(elem, "name"),
+            embedFontRefs: []
+        };
+        for (let el of xml.elements(elem)) {
+            switch (el.localName) {
+                case "family":
+                    result.family = xml.attr(el, "val");
+                    break;
+                case "altName":
+                    result.altName = xml.attr(el, "val");
+                    break;
+                case "embedRegular":
+                case "embedBold":
+                case "embedItalic":
+                case "embedBoldItalic":
+                    result.embedFontRefs.push(parseEmbedFontRef(el, xml));
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseEmbedFontRef(elem, xml) {
+        return {
+            id: xml.attr(elem, "id"),
+            key: xml.attr(elem, "fontKey"),
+            type: embedFontTypeMap[elem.localName]
+        };
+    }
+
+    class FontTablePart extends Part {
+        parseXml(root) {
+            this.fonts = parseFonts(root, this._package.xmlParser);
+        }
+    }
+
+    function escapeClassName(className) {
+        return className?.replace(/[ .]+/g, '-').replace(/[&]+/g, 'and').toLowerCase();
+    }
+    function encloseFontFamily(fontFamily) {
+        return /^[^"'].*\s.*[^"']$/.test(fontFamily) ? `'${fontFamily}'` : fontFamily;
+    }
+    function splitPath(path) {
+        let si = path.lastIndexOf('/') + 1;
+        let folder = si == 0 ? "" : path.substring(0, si);
+        let fileName = si == 0 ? path : path.substring(si);
+        return [folder, fileName];
+    }
+    function resolvePath(path, base) {
+        try {
+            const prefix = "http://docx/";
+            const url = new URL(path, prefix + base).toString();
+            return url.substring(prefix.length);
+        }
+        catch {
+            return `${base}${path}`;
+        }
+    }
+    function keyBy(array, by) {
+        return array.reduce((a, x) => {
+            a[by(x)] = x;
+            return a;
+        }, {});
+    }
+    function blobToBase64(blob) {
+        return new Promise((resolve, reject) => {
+            const reader = new FileReader();
+            reader.onloadend = () => resolve(reader.result);
+            reader.onerror = () => reject();
+            reader.readAsDataURL(blob);
+        });
+    }
+    function isObject(item) {
+        return item && typeof item === 'object' && !Array.isArray(item);
+    }
+    function isString(item) {
+        return typeof item === 'string' || item instanceof String;
+    }
+    function mergeDeep(target, ...sources) {
+        if (!sources.length)
+            return target;
+        const source = sources.shift();
+        if (isObject(target) && isObject(source)) {
+            for (const key in source) {
+                if (isObject(source[key])) {
+                    const val = target[key] ?? (target[key] = {});
+                    mergeDeep(val, source[key]);
+                }
+                else {
+                    target[key] = source[key];
+                }
+            }
+        }
+        return mergeDeep(target, ...sources);
+    }
+    function asArray(val) {
+        return Array.isArray(val) ? val : [val];
+    }
+
+    class OpenXmlPackage {
+        constructor(_zip, options) {
+            this._zip = _zip;
+            this.options = options;
+            this.xmlParser = new XmlParser();
+        }
+        get(path) {
+            const p = normalizePath(path);
+            return this._zip.files[p] ?? this._zip.files[p.replace(/\//g, '\\')];
+        }
+        update(path, content) {
+            this._zip.file(path, content);
+        }
+        static async load(input, options) {
+            const zip = await JSZip.loadAsync(input);
+            return new OpenXmlPackage(zip, options);
+        }
+        save(type = "blob") {
+            return this._zip.generateAsync({ type });
+        }
+        load(path, type = "string") {
+            return this.get(path)?.async(type) ?? Promise.resolve(null);
+        }
+        async loadRelationships(path = null) {
+            let relsPath = `_rels/.rels`;
+            if (path != null) {
+                const [f, fn] = splitPath(path);
+                relsPath = `${f}_rels/${fn}.rels`;
+            }
+            const txt = await this.load(relsPath);
+            return txt ? parseRelationships(this.parseXmlDocument(txt).firstElementChild, this.xmlParser) : null;
+        }
+        parseXmlDocument(txt) {
+            return parseXmlString(txt, this.options.trimXmlDeclaration);
+        }
+    }
+    function normalizePath(path) {
+        return path.startsWith('/') ? path.substr(1) : path;
+    }
+
+    class DocumentPart extends Part {
+        constructor(pkg, path, parser) {
+            super(pkg, path);
+            this._documentParser = parser;
+        }
+        parseXml(root) {
+            this.body = this._documentParser.parseDocumentFile(root);
+        }
+    }
+
+    function parseBorder(elem, xml) {
+        return {
+            type: xml.attr(elem, "val"),
+            color: xml.attr(elem, "color"),
+            size: xml.lengthAttr(elem, "sz", LengthUsage.Border),
+            offset: xml.lengthAttr(elem, "space", LengthUsage.Point),
+            frame: xml.boolAttr(elem, 'frame'),
+            shadow: xml.boolAttr(elem, 'shadow')
+        };
+    }
+    function parseBorders(elem, xml) {
+        var result = {};
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "left":
+                    result.left = parseBorder(e, xml);
+                    break;
+                case "top":
+                    result.top = parseBorder(e, xml);
+                    break;
+                case "right":
+                    result.right = parseBorder(e, xml);
+                    break;
+                case "bottom":
+                    result.bottom = parseBorder(e, xml);
+                    break;
+            }
+        }
+        return result;
+    }
+
+    var SectionType;
+    (function (SectionType) {
+        SectionType["Continuous"] = "continuous";
+        SectionType["NextPage"] = "nextPage";
+        SectionType["NextColumn"] = "nextColumn";
+        SectionType["EvenPage"] = "evenPage";
+        SectionType["OddPage"] = "oddPage";
+    })(SectionType || (SectionType = {}));
+    function parseSectionProperties(elem, xml = globalXmlParser) {
+        var section = {};
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "pgSz":
+                    section.pageSize = {
+                        width: xml.lengthAttr(e, "w"),
+                        height: xml.lengthAttr(e, "h"),
+                        orientation: xml.attr(e, "orient")
+                    };
+                    break;
+                case "type":
+                    section.type = xml.attr(e, "val");
+                    break;
+                case "pgMar":
+                    section.pageMargins = {
+                        left: xml.lengthAttr(e, "left"),
+                        right: xml.lengthAttr(e, "right"),
+                        top: xml.lengthAttr(e, "top"),
+                        bottom: xml.lengthAttr(e, "bottom"),
+                        header: xml.lengthAttr(e, "header"),
+                        footer: xml.lengthAttr(e, "footer"),
+                        gutter: xml.lengthAttr(e, "gutter"),
+                    };
+                    break;
+                case "cols":
+                    section.columns = parseColumns(e, xml);
+                    break;
+                case "headerReference":
+                    (section.headerRefs ?? (section.headerRefs = [])).push(parseFooterHeaderReference(e, xml));
+                    break;
+                case "footerReference":
+                    (section.footerRefs ?? (section.footerRefs = [])).push(parseFooterHeaderReference(e, xml));
+                    break;
+                case "titlePg":
+                    section.titlePage = xml.boolAttr(e, "val", true);
+                    break;
+                case "pgBorders":
+                    section.pageBorders = parseBorders(e, xml);
+                    break;
+                case "pgNumType":
+                    section.pageNumber = parsePageNumber(e, xml);
+                    break;
+            }
+        }
+        return section;
+    }
+    function parseColumns(elem, xml) {
+        return {
+            numberOfColumns: xml.intAttr(elem, "num"),
+            space: xml.lengthAttr(elem, "space"),
+            separator: xml.boolAttr(elem, "sep"),
+            equalWidth: xml.boolAttr(elem, "equalWidth", true),
+            columns: xml.elements(elem, "col")
+                .map(e => ({
+                width: xml.lengthAttr(e, "w"),
+                space: xml.lengthAttr(e, "space")
+            }))
+        };
+    }
+    function parsePageNumber(elem, xml) {
+        return {
+            chapSep: xml.attr(elem, "chapSep"),
+            chapStyle: xml.attr(elem, "chapStyle"),
+            format: xml.attr(elem, "fmt"),
+            start: xml.intAttr(elem, "start")
+        };
+    }
+    function parseFooterHeaderReference(elem, xml) {
+        return {
+            id: xml.attr(elem, "id"),
+            type: xml.attr(elem, "type"),
+        };
+    }
+
+    function parseLineSpacing(elem, xml) {
+        return {
+            before: xml.lengthAttr(elem, "before"),
+            after: xml.lengthAttr(elem, "after"),
+            line: xml.intAttr(elem, "line"),
+            lineRule: xml.attr(elem, "lineRule")
+        };
+    }
+
+    function parseRunProperties(elem, xml) {
+        let result = {};
+        for (let el of xml.elements(elem)) {
+            parseRunProperty(el, result, xml);
+        }
+        return result;
+    }
+    function parseRunProperty(elem, props, xml) {
+        if (parseCommonProperty(elem, props, xml))
+            return true;
+        return false;
+    }
+
+    function parseParagraphProperties(elem, xml) {
+        let result = {};
+        for (let el of xml.elements(elem)) {
+            parseParagraphProperty(el, result, xml);
+        }
+        return result;
+    }
+    function parseParagraphProperty(elem, props, xml) {
+        if (elem.namespaceURI != ns$1.wordml)
+            return false;
+        if (parseCommonProperty(elem, props, xml))
+            return true;
+        switch (elem.localName) {
+            case "tabs":
+                props.tabs = parseTabs(elem, xml);
+                break;
+            case "sectPr":
+                props.sectionProps = parseSectionProperties(elem, xml);
+                break;
+            case "numPr":
+                props.numbering = parseNumbering$1(elem, xml);
+                break;
+            case "spacing":
+                props.lineSpacing = parseLineSpacing(elem, xml);
+                return false;
+            case "textAlignment":
+                props.textAlignment = xml.attr(elem, "val");
+                return false;
+            case "keepLines":
+                props.keepLines = xml.boolAttr(elem, "val", true);
+                break;
+            case "keepNext":
+                props.keepNext = xml.boolAttr(elem, "val", true);
+                break;
+            case "pageBreakBefore":
+                props.pageBreakBefore = xml.boolAttr(elem, "val", true);
+                break;
+            case "outlineLvl":
+                props.outlineLevel = xml.intAttr(elem, "val");
+                break;
+            case "pStyle":
+                props.styleName = xml.attr(elem, "val");
+                break;
+            case "rPr":
+                props.runProps = parseRunProperties(elem, xml);
+                break;
+            default:
+                return false;
+        }
+        return true;
+    }
+    function parseTabs(elem, xml) {
+        return xml.elements(elem, "tab")
+            .map(e => ({
+            position: xml.lengthAttr(e, "pos"),
+            leader: xml.attr(e, "leader"),
+            style: xml.attr(e, "val")
+        }));
+    }
+    function parseNumbering$1(elem, xml) {
+        var result = {};
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "numId":
+                    result.id = xml.attr(e, "val");
+                    break;
+                case "ilvl":
+                    result.level = xml.intAttr(e, "val");
+                    break;
+            }
+        }
+        return result;
+    }
+
+    function parseNumberingPart(elem, xml) {
+        let result = {
+            numberings: [],
+            abstractNumberings: [],
+            bulletPictures: []
+        };
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "num":
+                    result.numberings.push(parseNumbering(e, xml));
+                    break;
+                case "abstractNum":
+                    result.abstractNumberings.push(parseAbstractNumbering(e, xml));
+                    break;
+                case "numPicBullet":
+                    result.bulletPictures.push(parseNumberingBulletPicture(e, xml));
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseNumbering(elem, xml) {
+        let result = {
+            id: xml.attr(elem, 'numId'),
+            overrides: []
+        };
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "abstractNumId":
+                    result.abstractId = xml.attr(e, "val");
+                    break;
+                case "lvlOverride":
+                    result.overrides.push(parseNumberingLevelOverrride(e, xml));
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseAbstractNumbering(elem, xml) {
+        let result = {
+            id: xml.attr(elem, 'abstractNumId'),
+            levels: []
+        };
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "name":
+                    result.name = xml.attr(e, "val");
+                    break;
+                case "multiLevelType":
+                    result.multiLevelType = xml.attr(e, "val");
+                    break;
+                case "numStyleLink":
+                    result.numberingStyleLink = xml.attr(e, "val");
+                    break;
+                case "styleLink":
+                    result.styleLink = xml.attr(e, "val");
+                    break;
+                case "lvl":
+                    result.levels.push(parseNumberingLevel(e, xml));
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseNumberingLevel(elem, xml) {
+        let result = {
+            level: xml.intAttr(elem, 'ilvl')
+        };
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "start":
+                    result.start = xml.attr(e, "val");
+                    break;
+                case "lvlRestart":
+                    result.restart = xml.intAttr(e, "val");
+                    break;
+                case "numFmt":
+                    result.format = xml.attr(e, "val");
+                    break;
+                case "lvlText":
+                    result.text = xml.attr(e, "val");
+                    break;
+                case "lvlJc":
+                    result.justification = xml.attr(e, "val");
+                    break;
+                case "lvlPicBulletId":
+                    result.bulletPictureId = xml.attr(e, "val");
+                    break;
+                case "pStyle":
+                    result.paragraphStyle = xml.attr(e, "val");
+                    break;
+                case "pPr":
+                    result.paragraphProps = parseParagraphProperties(e, xml);
+                    break;
+                case "rPr":
+                    result.runProps = parseRunProperties(e, xml);
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseNumberingLevelOverrride(elem, xml) {
+        let result = {
+            level: xml.intAttr(elem, 'ilvl')
+        };
+        for (let e of xml.elements(elem)) {
+            switch (e.localName) {
+                case "startOverride":
+                    result.start = xml.intAttr(e, "val");
+                    break;
+                case "lvl":
+                    result.numberingLevel = parseNumberingLevel(e, xml);
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseNumberingBulletPicture(elem, xml) {
+        var pict = xml.element(elem, "pict");
+        var shape = pict && xml.element(pict, "shape");
+        var imagedata = shape && xml.element(shape, "imagedata");
+        return imagedata ? {
+            id: xml.attr(elem, "numPicBulletId"),
+            referenceId: xml.attr(imagedata, "id"),
+            style: xml.attr(shape, "style")
+        } : null;
+    }
+
+    class NumberingPart extends Part {
+        constructor(pkg, path, parser) {
+            super(pkg, path);
+            this._documentParser = parser;
+        }
+        parseXml(root) {
+            Object.assign(this, parseNumberingPart(root, this._package.xmlParser));
+            this.domNumberings = this._documentParser.parseNumberingFile(root);
+        }
+    }
+
+    class StylesPart extends Part {
+        constructor(pkg, path, parser) {
+            super(pkg, path);
+            this._documentParser = parser;
+        }
+        parseXml(root) {
+            this.styles = this._documentParser.parseStylesFile(root);
+        }
+    }
+
+    var DomType;
+    (function (DomType) {
+        DomType["Document"] = "document";
+        DomType["Paragraph"] = "paragraph";
+        DomType["Run"] = "run";
+        DomType["Break"] = "break";
+        DomType["NoBreakHyphen"] = "noBreakHyphen";
+        DomType["Table"] = "table";
+        DomType["Row"] = "row";
+        DomType["Cell"] = "cell";
+        DomType["Hyperlink"] = "hyperlink";
+        DomType["SmartTag"] = "smartTag";
+        DomType["Drawing"] = "drawing";
+        DomType["Image"] = "image";
+        DomType["Text"] = "text";
+        DomType["Tab"] = "tab";
+        DomType["Symbol"] = "symbol";
+        DomType["BookmarkStart"] = "bookmarkStart";
+        DomType["BookmarkEnd"] = "bookmarkEnd";
+        DomType["Footer"] = "footer";
+        DomType["Header"] = "header";
+        DomType["FootnoteReference"] = "footnoteReference";
+        DomType["EndnoteReference"] = "endnoteReference";
+        DomType["Footnote"] = "footnote";
+        DomType["Endnote"] = "endnote";
+        DomType["SimpleField"] = "simpleField";
+        DomType["ComplexField"] = "complexField";
+        DomType["Instruction"] = "instruction";
+        DomType["VmlPicture"] = "vmlPicture";
+        DomType["MmlMath"] = "mmlMath";
+        DomType["MmlMathParagraph"] = "mmlMathParagraph";
+        DomType["MmlFraction"] = "mmlFraction";
+        DomType["MmlFunction"] = "mmlFunction";
+        DomType["MmlFunctionName"] = "mmlFunctionName";
+        DomType["MmlNumerator"] = "mmlNumerator";
+        DomType["MmlDenominator"] = "mmlDenominator";
+        DomType["MmlRadical"] = "mmlRadical";
+        DomType["MmlBase"] = "mmlBase";
+        DomType["MmlDegree"] = "mmlDegree";
+        DomType["MmlSuperscript"] = "mmlSuperscript";
+        DomType["MmlSubscript"] = "mmlSubscript";
+        DomType["MmlPreSubSuper"] = "mmlPreSubSuper";
+        DomType["MmlSubArgument"] = "mmlSubArgument";
+        DomType["MmlSuperArgument"] = "mmlSuperArgument";
+        DomType["MmlNary"] = "mmlNary";
+        DomType["MmlDelimiter"] = "mmlDelimiter";
+        DomType["MmlRun"] = "mmlRun";
+        DomType["MmlEquationArray"] = "mmlEquationArray";
+        DomType["MmlLimit"] = "mmlLimit";
+        DomType["MmlLimitLower"] = "mmlLimitLower";
+        DomType["MmlMatrix"] = "mmlMatrix";
+        DomType["MmlMatrixRow"] = "mmlMatrixRow";
+        DomType["MmlBox"] = "mmlBox";
+        DomType["MmlBar"] = "mmlBar";
+        DomType["MmlGroupChar"] = "mmlGroupChar";
+        DomType["VmlElement"] = "vmlElement";
+        DomType["Inserted"] = "inserted";
+        DomType["Deleted"] = "deleted";
+        DomType["DeletedText"] = "deletedText";
+        DomType["Comment"] = "comment";
+        DomType["CommentReference"] = "commentReference";
+        DomType["CommentRangeStart"] = "commentRangeStart";
+        DomType["CommentRangeEnd"] = "commentRangeEnd";
+    })(DomType || (DomType = {}));
+    class OpenXmlElementBase {
+        constructor() {
+            this.children = [];
+            this.cssStyle = {};
+        }
+    }
+
+    class WmlHeader extends OpenXmlElementBase {
+        constructor() {
+            super(...arguments);
+            this.type = DomType.Header;
+        }
+    }
+    class WmlFooter extends OpenXmlElementBase {
+        constructor() {
+            super(...arguments);
+            this.type = DomType.Footer;
+        }
+    }
+
+    class BaseHeaderFooterPart extends Part {
+        constructor(pkg, path, parser) {
+            super(pkg, path);
+            this._documentParser = parser;
+        }
+        parseXml(root) {
+            this.rootElement = this.createRootElement();
+            this.rootElement.children = this._documentParser.parseBodyElements(root);
+        }
+    }
+    class HeaderPart extends BaseHeaderFooterPart {
+        createRootElement() {
+            return new WmlHeader();
+        }
+    }
+    class FooterPart extends BaseHeaderFooterPart {
+        createRootElement() {
+            return new WmlFooter();
+        }
+    }
+
+    function parseExtendedProps(root, xmlParser) {
+        const result = {};
+        for (let el of xmlParser.elements(root)) {
+            switch (el.localName) {
+                case "Template":
+                    result.template = el.textContent;
+                    break;
+                case "Pages":
+                    result.pages = safeParseToInt(el.textContent);
+                    break;
+                case "Words":
+                    result.words = safeParseToInt(el.textContent);
+                    break;
+                case "Characters":
+                    result.characters = safeParseToInt(el.textContent);
+                    break;
+                case "Application":
+                    result.application = el.textContent;
+                    break;
+                case "Lines":
+                    result.lines = safeParseToInt(el.textContent);
+                    break;
+                case "Paragraphs":
+                    result.paragraphs = safeParseToInt(el.textContent);
+                    break;
+                case "Company":
+                    result.company = el.textContent;
+                    break;
+                case "AppVersion":
+                    result.appVersion = el.textContent;
+                    break;
+            }
+        }
+        return result;
+    }
+    function safeParseToInt(value) {
+        if (typeof value === 'undefined')
+            return;
+        return parseInt(value);
+    }
+
+    class ExtendedPropsPart extends Part {
+        parseXml(root) {
+            this.props = parseExtendedProps(root, this._package.xmlParser);
+        }
+    }
+
+    function parseCoreProps(root, xmlParser) {
+        const result = {};
+        for (let el of xmlParser.elements(root)) {
+            switch (el.localName) {
+                case "title":
+                    result.title = el.textContent;
+                    break;
+                case "description":
+                    result.description = el.textContent;
+                    break;
+                case "subject":
+                    result.subject = el.textContent;
+                    break;
+                case "creator":
+                    result.creator = el.textContent;
+                    break;
+                case "keywords":
+                    result.keywords = el.textContent;
+                    break;
+                case "language":
+                    result.language = el.textContent;
+                    break;
+                case "lastModifiedBy":
+                    result.lastModifiedBy = el.textContent;
+                    break;
+                case "revision":
+                    el.textContent && (result.revision = parseInt(el.textContent));
+                    break;
+            }
+        }
+        return result;
+    }
+
+    class CorePropsPart extends Part {
+        parseXml(root) {
+            this.props = parseCoreProps(root, this._package.xmlParser);
+        }
+    }
+
+    class DmlTheme {
+    }
+    function parseTheme(elem, xml) {
+        var result = new DmlTheme();
+        var themeElements = xml.element(elem, "themeElements");
+        for (let el of xml.elements(themeElements)) {
+            switch (el.localName) {
+                case "clrScheme":
+                    result.colorScheme = parseColorScheme(el, xml);
+                    break;
+                case "fontScheme":
+                    result.fontScheme = parseFontScheme(el, xml);
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseColorScheme(elem, xml) {
+        var result = {
+            name: xml.attr(elem, "name"),
+            colors: {}
+        };
+        for (let el of xml.elements(elem)) {
+            var srgbClr = xml.element(el, "srgbClr");
+            var sysClr = xml.element(el, "sysClr");
+            if (srgbClr) {
+                result.colors[el.localName] = xml.attr(srgbClr, "val");
+            }
+            else if (sysClr) {
+                result.colors[el.localName] = xml.attr(sysClr, "lastClr");
+            }
+        }
+        return result;
+    }
+    function parseFontScheme(elem, xml) {
+        var result = {
+            name: xml.attr(elem, "name"),
+        };
+        for (let el of xml.elements(elem)) {
+            switch (el.localName) {
+                case "majorFont":
+                    result.majorFont = parseFontInfo(el, xml);
+                    break;
+                case "minorFont":
+                    result.minorFont = parseFontInfo(el, xml);
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseFontInfo(elem, xml) {
+        return {
+            latinTypeface: xml.elementAttr(elem, "latin", "typeface"),
+            eaTypeface: xml.elementAttr(elem, "ea", "typeface"),
+            csTypeface: xml.elementAttr(elem, "cs", "typeface"),
+        };
+    }
+
+    class ThemePart extends Part {
+        constructor(pkg, path) {
+            super(pkg, path);
+        }
+        parseXml(root) {
+            this.theme = parseTheme(root, this._package.xmlParser);
+        }
+    }
+
+    class WmlBaseNote {
+    }
+    class WmlFootnote extends WmlBaseNote {
+        constructor() {
+            super(...arguments);
+            this.type = DomType.Footnote;
+        }
+    }
+    class WmlEndnote extends WmlBaseNote {
+        constructor() {
+            super(...arguments);
+            this.type = DomType.Endnote;
+        }
+    }
+
+    class BaseNotePart extends Part {
+        constructor(pkg, path, parser) {
+            super(pkg, path);
+            this._documentParser = parser;
+        }
+    }
+    class FootnotesPart extends BaseNotePart {
+        constructor(pkg, path, parser) {
+            super(pkg, path, parser);
+        }
+        parseXml(root) {
+            this.notes = this._documentParser.parseNotes(root, "footnote", WmlFootnote);
+        }
+    }
+    class EndnotesPart extends BaseNotePart {
+        constructor(pkg, path, parser) {
+            super(pkg, path, parser);
+        }
+        parseXml(root) {
+            this.notes = this._documentParser.parseNotes(root, "endnote", WmlEndnote);
+        }
+    }
+
+    function parseSettings(elem, xml) {
+        var result = {};
+        for (let el of xml.elements(elem)) {
+            switch (el.localName) {
+                case "defaultTabStop":
+                    result.defaultTabStop = xml.lengthAttr(el, "val");
+                    break;
+                case "footnotePr":
+                    result.footnoteProps = parseNoteProperties(el, xml);
+                    break;
+                case "endnotePr":
+                    result.endnoteProps = parseNoteProperties(el, xml);
+                    break;
+                case "autoHyphenation":
+                    result.autoHyphenation = xml.boolAttr(el, "val");
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseNoteProperties(elem, xml) {
+        var result = {
+            defaultNoteIds: []
+        };
+        for (let el of xml.elements(elem)) {
+            switch (el.localName) {
+                case "numFmt":
+                    result.nummeringFormat = xml.attr(el, "val");
+                    break;
+                case "footnote":
+                case "endnote":
+                    result.defaultNoteIds.push(xml.attr(el, "id"));
+                    break;
+            }
+        }
+        return result;
+    }
+
+    class SettingsPart extends Part {
+        constructor(pkg, path) {
+            super(pkg, path);
+        }
+        parseXml(root) {
+            this.settings = parseSettings(root, this._package.xmlParser);
+        }
+    }
+
+    function parseCustomProps(root, xml) {
+        return xml.elements(root, "property").map(e => {
+            const firstChild = e.firstChild;
+            return {
+                formatId: xml.attr(e, "fmtid"),
+                name: xml.attr(e, "name"),
+                type: firstChild.nodeName,
+                value: firstChild.textContent
+            };
+        });
+    }
+
+    class CustomPropsPart extends Part {
+        parseXml(root) {
+            this.props = parseCustomProps(root, this._package.xmlParser);
+        }
+    }
+
+    class CommentsPart extends Part {
+        constructor(pkg, path, parser) {
+            super(pkg, path);
+            this._documentParser = parser;
+        }
+        parseXml(root) {
+            this.comments = this._documentParser.parseComments(root);
+            this.commentMap = keyBy(this.comments, x => x.id);
+        }
+    }
+
+    class CommentsExtendedPart extends Part {
+        constructor(pkg, path) {
+            super(pkg, path);
+            this.comments = [];
+        }
+        parseXml(root) {
+            const xml = this._package.xmlParser;
+            for (let el of xml.elements(root, "commentEx")) {
+                this.comments.push({
+                    paraId: xml.attr(el, 'paraId'),
+                    paraIdParent: xml.attr(el, 'paraIdParent'),
+                    done: xml.boolAttr(el, 'done')
+                });
+            }
+            this.commentMap = keyBy(this.comments, x => x.paraId);
+        }
+    }
+
+    const topLevelRels = [
+        { type: RelationshipTypes.OfficeDocument, target: "word/document.xml" },
+        { type: RelationshipTypes.ExtendedProperties, target: "docProps/app.xml" },
+        { type: RelationshipTypes.CoreProperties, target: "docProps/core.xml" },
+        { type: RelationshipTypes.CustomProperties, target: "docProps/custom.xml" },
+    ];
+    class WordDocument {
+        constructor() {
+            this.parts = [];
+            this.partsMap = {};
+        }
+        static async load(blob, parser, options) {
+            var d = new WordDocument();
+            d._options = options;
+            d._parser = parser;
+            d._package = await OpenXmlPackage.load(blob, options);
+            d.rels = await d._package.loadRelationships();
+            await Promise.all(topLevelRels.map(rel => {
+                const r = d.rels.find(x => x.type === rel.type) ?? rel;
+                return d.loadRelationshipPart(r.target, r.type);
+            }));
+            return d;
+        }
+        save(type = "blob") {
+            return this._package.save(type);
+        }
+        async loadRelationshipPart(path, type) {
+            if (this.partsMap[path])
+                return this.partsMap[path];
+            if (!this._package.get(path))
+                return null;
+            let part = null;
+            switch (type) {
+                case RelationshipTypes.OfficeDocument:
+                    this.documentPart = part = new DocumentPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.FontTable:
+                    this.fontTablePart = part = new FontTablePart(this._package, path);
+                    break;
+                case RelationshipTypes.Numbering:
+                    this.numberingPart = part = new NumberingPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.Styles:
+                    this.stylesPart = part = new StylesPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.Theme:
+                    this.themePart = part = new ThemePart(this._package, path);
+                    break;
+                case RelationshipTypes.Footnotes:
+                    this.footnotesPart = part = new FootnotesPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.Endnotes:
+                    this.endnotesPart = part = new EndnotesPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.Footer:
+                    part = new FooterPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.Header:
+                    part = new HeaderPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.CoreProperties:
+                    this.corePropsPart = part = new CorePropsPart(this._package, path);
+                    break;
+                case RelationshipTypes.ExtendedProperties:
+                    this.extendedPropsPart = part = new ExtendedPropsPart(this._package, path);
+                    break;
+                case RelationshipTypes.CustomProperties:
+                    part = new CustomPropsPart(this._package, path);
+                    break;
+                case RelationshipTypes.Settings:
+                    this.settingsPart = part = new SettingsPart(this._package, path);
+                    break;
+                case RelationshipTypes.Comments:
+                    this.commentsPart = part = new CommentsPart(this._package, path, this._parser);
+                    break;
+                case RelationshipTypes.CommentsExtended:
+                    this.commentsExtendedPart = part = new CommentsExtendedPart(this._package, path);
+                    break;
+            }
+            if (part == null)
+                return Promise.resolve(null);
+            this.partsMap[path] = part;
+            this.parts.push(part);
+            await part.load();
+            if (part.rels?.length > 0) {
+                const [folder] = splitPath(part.path);
+                await Promise.all(part.rels.map(rel => this.loadRelationshipPart(resolvePath(rel.target, folder), rel.type)));
+            }
+            return part;
+        }
+        async loadDocumentImage(id, part) {
+            const x = await this.loadResource(part ?? this.documentPart, id, "blob");
+            return this.blobToURL(x);
+        }
+        async loadNumberingImage(id) {
+            const x = await this.loadResource(this.numberingPart, id, "blob");
+            return this.blobToURL(x);
+        }
+        async loadFont(id, key) {
+            const x = await this.loadResource(this.fontTablePart, id, "uint8array");
+            return x ? this.blobToURL(new Blob([deobfuscate(x, key)])) : x;
+        }
+        blobToURL(blob) {
+            if (!blob)
+                return null;
+            if (this._options.useBase64URL) {
+                return blobToBase64(blob);
+            }
+            return URL.createObjectURL(blob);
+        }
+        findPartByRelId(id, basePart = null) {
+            var rel = (basePart.rels ?? this.rels).find(r => r.id == id);
+            const folder = basePart ? splitPath(basePart.path)[0] : '';
+            return rel ? this.partsMap[resolvePath(rel.target, folder)] : null;
+        }
+        getPathById(part, id) {
+            const rel = part.rels.find(x => x.id == id);
+            const [folder] = splitPath(part.path);
+            return rel ? resolvePath(rel.target, folder) : null;
+        }
+        loadResource(part, id, outputType) {
+            const path = this.getPathById(part, id);
+            return path ? this._package.load(path, outputType) : Promise.resolve(null);
+        }
+    }
+    function deobfuscate(data, guidKey) {
+        const len = 16;
+        const trimmed = guidKey.replace(/{|}|-/g, "");
+        const numbers = new Array(len);
+        for (let i = 0; i < len; i++)
+            numbers[len - i - 1] = parseInt(trimmed.substr(i * 2, 2), 16);
+        for (let i = 0; i < 32; i++)
+            data[i] = data[i] ^ numbers[i % len];
+        return data;
+    }
+
+    function parseBookmarkStart(elem, xml) {
+        return {
+            type: DomType.BookmarkStart,
+            id: xml.attr(elem, "id"),
+            name: xml.attr(elem, "name"),
+            colFirst: xml.intAttr(elem, "colFirst"),
+            colLast: xml.intAttr(elem, "colLast")
+        };
+    }
+    function parseBookmarkEnd(elem, xml) {
+        return {
+            type: DomType.BookmarkEnd,
+            id: xml.attr(elem, "id")
+        };
+    }
+
+    class VmlElement extends OpenXmlElementBase {
+        constructor() {
+            super(...arguments);
+            this.type = DomType.VmlElement;
+            this.attrs = {};
+        }
+    }
+    function parseVmlElement(elem, parser) {
+        var result = new VmlElement();
+        switch (elem.localName) {
+            case "rect":
+                result.tagName = "rect";
+                Object.assign(result.attrs, { width: '100%', height: '100%' });
+                break;
+            case "oval":
+                result.tagName = "ellipse";
+                Object.assign(result.attrs, { cx: "50%", cy: "50%", rx: "50%", ry: "50%" });
+                break;
+            case "line":
+                result.tagName = "line";
+                break;
+            case "shape":
+                result.tagName = "g";
+                break;
+            case "textbox":
+                result.tagName = "foreignObject";
+                Object.assign(result.attrs, { width: '100%', height: '100%' });
+                break;
+            default:
+                return null;
+        }
+        for (const at of globalXmlParser.attrs(elem)) {
+            switch (at.localName) {
+                case "style":
+                    result.cssStyleText = at.value;
+                    break;
+                case "fillcolor":
+                    result.attrs.fill = at.value;
+                    break;
+                case "from":
+                    const [x1, y1] = parsePoint(at.value);
+                    Object.assign(result.attrs, { x1, y1 });
+                    break;
+                case "to":
+                    const [x2, y2] = parsePoint(at.value);
+                    Object.assign(result.attrs, { x2, y2 });
+                    break;
+            }
+        }
+        for (const el of globalXmlParser.elements(elem)) {
+            switch (el.localName) {
+                case "stroke":
+                    Object.assign(result.attrs, parseStroke(el));
+                    break;
+                case "fill":
+                    Object.assign(result.attrs, parseFill());
+                    break;
+                case "imagedata":
+                    result.tagName = "image";
+                    Object.assign(result.attrs, { width: '100%', height: '100%' });
+                    result.imageHref = {
+                        id: globalXmlParser.attr(el, "id"),
+                        title: globalXmlParser.attr(el, "title"),
+                    };
+                    break;
+                case "txbxContent":
+                    result.children.push(...parser.parseBodyElements(el));
+                    break;
+                default:
+                    const child = parseVmlElement(el, parser);
+                    child && result.children.push(child);
+                    break;
+            }
+        }
+        return result;
+    }
+    function parseStroke(el) {
+        return {
+            'stroke': globalXmlParser.attr(el, "color"),
+            'stroke-width': globalXmlParser.lengthAttr(el, "weight", LengthUsage.Emu) ?? '1px'
+        };
+    }
+    function parseFill(el) {
+        return {};
+    }
+    function parsePoint(val) {
+        return val.split(",");
+    }
+
+    class WmlComment extends OpenXmlElementBase {
+        constructor() {
+            super(...arguments);
+            this.type = DomType.Comment;
+        }
+    }
+    class WmlCommentReference extends OpenXmlElementBase {
+        constructor(id) {
+            super();
+            this.id = id;
+            this.type = DomType.CommentReference;
+        }
+    }
+    class WmlCommentRangeStart extends OpenXmlElementBase {
+        constructor(id) {
+            super();
+            this.id = id;
+            this.type = DomType.CommentRangeStart;
+        }
+    }
+    class WmlCommentRangeEnd extends OpenXmlElementBase {
+        constructor(id) {
+            super();
+            this.id = id;
+            this.type = DomType.CommentRangeEnd;
+        }
+    }
+
+    var autos = {
+        shd: "inherit",
+        color: "black",
+        borderColor: "black",
+        highlight: "transparent"
+    };
+    const supportedNamespaceURIs = [];
+    const mmlTagMap = {
+        "oMath": DomType.MmlMath,
+        "oMathPara": DomType.MmlMathParagraph,
+        "f": DomType.MmlFraction,
+        "func": DomType.MmlFunction,
+        "fName": DomType.MmlFunctionName,
+        "num": DomType.MmlNumerator,
+        "den": DomType.MmlDenominator,
+        "rad": DomType.MmlRadical,
+        "deg": DomType.MmlDegree,
+        "e": DomType.MmlBase,
+        "sSup": DomType.MmlSuperscript,
+        "sSub": DomType.MmlSubscript,
+        "sPre": DomType.MmlPreSubSuper,
+        "sup": DomType.MmlSuperArgument,
+        "sub": DomType.MmlSubArgument,
+        "d": DomType.MmlDelimiter,
+        "nary": DomType.MmlNary,
+        "eqArr": DomType.MmlEquationArray,
+        "lim": DomType.MmlLimit,
+        "limLow": DomType.MmlLimitLower,
+        "m": DomType.MmlMatrix,
+        "mr": DomType.MmlMatrixRow,
+        "box": DomType.MmlBox,
+        "bar": DomType.MmlBar,
+        "groupChr": DomType.MmlGroupChar
+    };
+    class DocumentParser {
+        constructor(options) {
+            this.options = {
+                ignoreWidth: false,
+                debug: false,
+                ...options
+            };
+        }
+        parseNotes(xmlDoc, elemName, elemClass) {
+            var result = [];
+            for (let el of globalXmlParser.elements(xmlDoc, elemName)) {
+                const node = new elemClass();
+                node.id = globalXmlParser.attr(el, "id");
+                node.noteType = globalXmlParser.attr(el, "type");
+                node.children = this.parseBodyElements(el);
+                result.push(node);
+            }
+            return result;
+        }
+        parseComments(xmlDoc) {
+            var result = [];
+            for (let el of globalXmlParser.elements(xmlDoc, "comment")) {
+                const item = new WmlComment();
+                item.id = globalXmlParser.attr(el, "id");
+                item.author = globalXmlParser.attr(el, "author");
+                item.initials = globalXmlParser.attr(el, "initials");
+                item.date = globalXmlParser.attr(el, "date");
+                item.children = this.parseBodyElements(el);
+                result.push(item);
+            }
+            return result;
+        }
+        parseDocumentFile(xmlDoc) {
+            var xbody = globalXmlParser.element(xmlDoc, "body");
+            var background = globalXmlParser.element(xmlDoc, "background");
+            var sectPr = globalXmlParser.element(xbody, "sectPr");
+            return {
+                type: DomType.Document,
+                children: this.parseBodyElements(xbody),
+                props: sectPr ? parseSectionProperties(sectPr, globalXmlParser) : {},
+                cssStyle: background ? this.parseBackground(background) : {},
+            };
+        }
+        parseBackground(elem) {
+            var result = {};
+            var color = xmlUtil.colorAttr(elem, "color");
+            if (color) {
+                result["background-color"] = color;
+            }
+            return result;
+        }
+        parseBodyElements(element) {
+            var children = [];
+            for (let elem of globalXmlParser.elements(element)) {
+                switch (elem.localName) {
+                    case "p":
+                        children.push(this.parseParagraph(elem));
+                        break;
+                    case "tbl":
+                        children.push(this.parseTable(elem));
+                        break;
+                    case "sdt":
+                        children.push(...this.parseSdt(elem, e => this.parseBodyElements(e)));
+                        break;
+                }
+            }
+            return children;
+        }
+        parseStylesFile(xstyles) {
+            var result = [];
+            xmlUtil.foreach(xstyles, n => {
+                switch (n.localName) {
+                    case "style":
+                        result.push(this.parseStyle(n));
+                        break;
+                    case "docDefaults":
+                        result.push(this.parseDefaultStyles(n));
+                        break;
+                }
+            });
+            return result;
+        }
+        parseDefaultStyles(node) {
+            var result = {
+                id: null,
+                name: null,
+                target: null,
+                basedOn: null,
+                styles: []
+            };
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "rPrDefault":
+                        var rPr = globalXmlParser.element(c, "rPr");
+                        if (rPr)
+                            result.styles.push({
+                                target: "span",
+                                values: this.parseDefaultProperties(rPr, {})
+                            });
+                        break;
+                    case "pPrDefault":
+                        var pPr = globalXmlParser.element(c, "pPr");
+                        if (pPr)
+                            result.styles.push({
+                                target: "p",
+                                values: this.parseDefaultProperties(pPr, {})
+                            });
+                        break;
+                }
+            });
+            return result;
+        }
+        parseStyle(node) {
+            var result = {
+                id: globalXmlParser.attr(node, "styleId"),
+                isDefault: globalXmlParser.boolAttr(node, "default"),
+                name: null,
+                target: null,
+                basedOn: null,
+                styles: [],
+                linked: null
+            };
+            switch (globalXmlParser.attr(node, "type")) {
+                case "paragraph":
+                    result.target = "p";
+                    break;
+                case "table":
+                    result.target = "table";
+                    break;
+                case "character":
+                    result.target = "span";
+                    break;
+            }
+            xmlUtil.foreach(node, n => {
+                switch (n.localName) {
+                    case "basedOn":
+                        result.basedOn = globalXmlParser.attr(n, "val");
+                        break;
+                    case "name":
+                        result.name = globalXmlParser.attr(n, "val");
+                        break;
+                    case "link":
+                        result.linked = globalXmlParser.attr(n, "val");
+                        break;
+                    case "next":
+                        result.next = globalXmlParser.attr(n, "val");
+                        break;
+                    case "aliases":
+                        result.aliases = globalXmlParser.attr(n, "val").split(",");
+                        break;
+                    case "pPr":
+                        result.styles.push({
+                            target: "p",
+                            values: this.parseDefaultProperties(n, {})
+                        });
+                        result.paragraphProps = parseParagraphProperties(n, globalXmlParser);
+                        break;
+                    case "rPr":
+                        result.styles.push({
+                            target: "span",
+                            values: this.parseDefaultProperties(n, {})
+                        });
+                        result.runProps = parseRunProperties(n, globalXmlParser);
+                        break;
+                    case "tblPr":
+                    case "tcPr":
+                        result.styles.push({
+                            target: "td",
+                            values: this.parseDefaultProperties(n, {})
+                        });
+                        break;
+                    case "tblStylePr":
+                        for (let s of this.parseTableStyle(n))
+                            result.styles.push(s);
+                        break;
+                    case "rsid":
+                    case "qFormat":
+                    case "hidden":
+                    case "semiHidden":
+                    case "unhideWhenUsed":
+                    case "autoRedefine":
+                    case "uiPriority":
+                        break;
+                    default:
+                        this.options.debug && console.warn(`DOCX: Unknown style element: ${n.localName}`);
+                }
+            });
+            return result;
+        }
+        parseTableStyle(node) {
+            var result = [];
+            var type = globalXmlParser.attr(node, "type");
+            var selector = "";
+            var modificator = "";
+            switch (type) {
+                case "firstRow":
+                    modificator = ".first-row";
+                    selector = "tr.first-row td";
+                    break;
+                case "lastRow":
+                    modificator = ".last-row";
+                    selector = "tr.last-row td";
+                    break;
+                case "firstCol":
+                    modificator = ".first-col";
+                    selector = "td.first-col";
+                    break;
+                case "lastCol":
+                    modificator = ".last-col";
+                    selector = "td.last-col";
+                    break;
+                case "band1Vert":
+                    modificator = ":not(.no-vband)";
+                    selector = "td.odd-col";
+                    break;
+                case "band2Vert":
+                    modificator = ":not(.no-vband)";
+                    selector = "td.even-col";
+                    break;
+                case "band1Horz":
+                    modificator = ":not(.no-hband)";
+                    selector = "tr.odd-row";
+                    break;
+                case "band2Horz":
+                    modificator = ":not(.no-hband)";
+                    selector = "tr.even-row";
+                    break;
+                default: return [];
+            }
+            xmlUtil.foreach(node, n => {
+                switch (n.localName) {
+                    case "pPr":
+                        result.push({
+                            target: `${selector} p`,
+                            mod: modificator,
+                            values: this.parseDefaultProperties(n, {})
+                        });
+                        break;
+                    case "rPr":
+                        result.push({
+                            target: `${selector} span`,
+                            mod: modificator,
+                            values: this.parseDefaultProperties(n, {})
+                        });
+                        break;
+                    case "tblPr":
+                    case "tcPr":
+                        result.push({
+                            target: selector,
+                            mod: modificator,
+                            values: this.parseDefaultProperties(n, {})
+                        });
+                        break;
+                }
+            });
+            return result;
+        }
+        parseNumberingFile(xnums) {
+            var result = [];
+            var mapping = {};
+            var bullets = [];
+            xmlUtil.foreach(xnums, n => {
+                switch (n.localName) {
+                    case "abstractNum":
+                        this.parseAbstractNumbering(n, bullets)
+                            .forEach(x => result.push(x));
+                        break;
+                    case "numPicBullet":
+                        bullets.push(this.parseNumberingPicBullet(n));
+                        break;
+                    case "num":
+                        var numId = globalXmlParser.attr(n, "numId");
+                        var abstractNumId = globalXmlParser.elementAttr(n, "abstractNumId", "val");
+                        mapping[abstractNumId] = numId;
+                        break;
+                }
+            });
+            result.forEach(x => x.id = mapping[x.id]);
+            return result;
+        }
+        parseNumberingPicBullet(elem) {
+            var pict = globalXmlParser.element(elem, "pict");
+            var shape = pict && globalXmlParser.element(pict, "shape");
+            var imagedata = shape && globalXmlParser.element(shape, "imagedata");
+            return imagedata ? {
+                id: globalXmlParser.intAttr(elem, "numPicBulletId"),
+                src: globalXmlParser.attr(imagedata, "id"),
+                style: globalXmlParser.attr(shape, "style")
+            } : null;
+        }
+        parseAbstractNumbering(node, bullets) {
+            var result = [];
+            var id = globalXmlParser.attr(node, "abstractNumId");
+            xmlUtil.foreach(node, n => {
+                switch (n.localName) {
+                    case "lvl":
+                        result.push(this.parseNumberingLevel(id, n, bullets));
+                        break;
+                }
+            });
+            return result;
+        }
+        parseNumberingLevel(id, node, bullets) {
+            var result = {
+                id: id,
+                level: globalXmlParser.intAttr(node, "ilvl"),
+                start: 1,
+                pStyleName: undefined,
+                pStyle: {},
+                rStyle: {},
+                suff: "tab"
+            };
+            xmlUtil.foreach(node, n => {
+                switch (n.localName) {
+                    case "start":
+                        result.start = globalXmlParser.intAttr(n, "val");
+                        break;
+                    case "pPr":
+                        this.parseDefaultProperties(n, result.pStyle);
+                        break;
+                    case "rPr":
+                        this.parseDefaultProperties(n, result.rStyle);
+                        break;
+                    case "lvlPicBulletId":
+                        var id = globalXmlParser.intAttr(n, "val");
+                        result.bullet = bullets.find(x => x?.id == id);
+                        break;
+                    case "lvlText":
+                        result.levelText = globalXmlParser.attr(n, "val");
+                        break;
+                    case "pStyle":
+                        result.pStyleName = globalXmlParser.attr(n, "val");
+                        break;
+                    case "numFmt":
+                        result.format = globalXmlParser.attr(n, "val");
+                        break;
+                    case "suff":
+                        result.suff = globalXmlParser.attr(n, "val");
+                        break;
+                }
+            });
+            return result;
+        }
+        parseSdt(node, parser) {
+            const sdtContent = globalXmlParser.element(node, "sdtContent");
+            return sdtContent ? parser(sdtContent) : [];
+        }
+        parseInserted(node, parentParser) {
+            return {
+                type: DomType.Inserted,
+                children: parentParser(node)?.children ?? []
+            };
+        }
+        parseDeleted(node, parentParser) {
+            return {
+                type: DomType.Deleted,
+                children: parentParser(node)?.children ?? []
+            };
+        }
+        parseParagraph(node) {
+            var result = { type: DomType.Paragraph, children: [] };
+            for (let el of globalXmlParser.elements(node)) {
+                switch (el.localName) {
+                    case "pPr":
+                        this.parseParagraphProperties(el, result);
+                        break;
+                    case "r":
+                        result.children.push(this.parseRun(el, result));
+                        break;
+                    case "hyperlink":
+                        result.children.push(this.parseHyperlink(el, result));
+                        break;
+                    case "smartTag":
+                        result.children.push(this.parseSmartTag(el, result));
+                        break;
+                    case "bookmarkStart":
+                        result.children.push(parseBookmarkStart(el, globalXmlParser));
+                        break;
+                    case "bookmarkEnd":
+                        result.children.push(parseBookmarkEnd(el, globalXmlParser));
+                        break;
+                    case "commentRangeStart":
+                        result.children.push(new WmlCommentRangeStart(globalXmlParser.attr(el, "id")));
+                        break;
+                    case "commentRangeEnd":
+                        result.children.push(new WmlCommentRangeEnd(globalXmlParser.attr(el, "id")));
+                        break;
+                    case "oMath":
+                    case "oMathPara":
+                        result.children.push(this.parseMathElement(el));
+                        break;
+                    case "sdt":
+                        result.children.push(...this.parseSdt(el, e => this.parseParagraph(e).children));
+                        break;
+                    case "ins":
+                        result.children.push(this.parseInserted(el, e => this.parseParagraph(e)));
+                        break;
+                    case "del":
+                        result.children.push(this.parseDeleted(el, e => this.parseParagraph(e)));
+                        break;
+                }
+            }
+            return result;
+        }
+        parseParagraphProperties(elem, paragraph) {
+            this.parseDefaultProperties(elem, paragraph.cssStyle = {}, null, c => {
+                if (parseParagraphProperty(c, paragraph, globalXmlParser))
+                    return true;
+                switch (c.localName) {
+                    case "pStyle":
+                        paragraph.styleName = globalXmlParser.attr(c, "val");
+                        break;
+                    case "cnfStyle":
+                        paragraph.className = values.classNameOfCnfStyle(c);
+                        break;
+                    case "framePr":
+                        this.parseFrame(c, paragraph);
+                        break;
+                    case "rPr":
+                        break;
+                    default:
+                        return false;
+                }
+                return true;
+            });
+        }
+        parseFrame(node, paragraph) {
+            var dropCap = globalXmlParser.attr(node, "dropCap");
+            if (dropCap == "drop")
+                paragraph.cssStyle["float"] = "left";
+        }
+        parseHyperlink(node, parent) {
+            var result = { type: DomType.Hyperlink, parent: parent, children: [] };
+            var anchor = globalXmlParser.attr(node, "anchor");
+            var relId = globalXmlParser.attr(node, "id");
+            if (anchor)
+                result.href = "#" + anchor;
+            if (relId)
+                result.id = relId;
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "r":
+                        result.children.push(this.parseRun(c, result));
+                        break;
+                }
+            });
+            return result;
+        }
+        parseSmartTag(node, parent) {
+            var result = { type: DomType.SmartTag, parent, children: [] };
+            var uri = globalXmlParser.attr(node, "uri");
+            var element = globalXmlParser.attr(node, "element");
+            if (uri)
+                result.uri = uri;
+            if (element)
+                result.element = element;
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "r":
+                        result.children.push(this.parseRun(c, result));
+                        break;
+                }
+            });
+            return result;
+        }
+        parseRun(node, parent) {
+            var result = { type: DomType.Run, parent: parent, children: [] };
+            xmlUtil.foreach(node, c => {
+                c = this.checkAlternateContent(c);
+                switch (c.localName) {
+                    case "t":
+                        result.children.push({
+                            type: DomType.Text,
+                            text: c.textContent
+                        });
+                        break;
+                    case "delText":
+                        result.children.push({
+                            type: DomType.DeletedText,
+                            text: c.textContent
+                        });
+                        break;
+                    case "commentReference":
+                        result.children.push(new WmlCommentReference(globalXmlParser.attr(c, "id")));
+                        break;
+                    case "fldSimple":
+                        result.children.push({
+                            type: DomType.SimpleField,
+                            instruction: globalXmlParser.attr(c, "instr"),
+                            lock: globalXmlParser.boolAttr(c, "lock", false),
+                            dirty: globalXmlParser.boolAttr(c, "dirty", false)
+                        });
+                        break;
+                    case "instrText":
+                        result.fieldRun = true;
+                        result.children.push({
+                            type: DomType.Instruction,
+                            text: c.textContent
+                        });
+                        break;
+                    case "fldChar":
+                        result.fieldRun = true;
+                        result.children.push({
+                            type: DomType.ComplexField,
+                            charType: globalXmlParser.attr(c, "fldCharType"),
+                            lock: globalXmlParser.boolAttr(c, "lock", false),
+                            dirty: globalXmlParser.boolAttr(c, "dirty", false)
+                        });
+                        break;
+                    case "noBreakHyphen":
+                        result.children.push({ type: DomType.NoBreakHyphen });
+                        break;
+                    case "br":
+                        result.children.push({
+                            type: DomType.Break,
+                            break: globalXmlParser.attr(c, "type") || "textWrapping"
+                        });
+                        break;
+                    case "lastRenderedPageBreak":
+                        result.children.push({
+                            type: DomType.Break,
+                            break: "lastRenderedPageBreak"
+                        });
+                        break;
+                    case "sym":
+                        result.children.push({
+                            type: DomType.Symbol,
+                            font: globalXmlParser.attr(c, "font"),
+                            char: globalXmlParser.attr(c, "char")
+                        });
+                        break;
+                    case "tab":
+                        result.children.push({ type: DomType.Tab });
+                        break;
+                    case "footnoteReference":
+                        result.children.push({
+                            type: DomType.FootnoteReference,
+                            id: globalXmlParser.attr(c, "id")
+                        });
+                        break;
+                    case "endnoteReference":
+                        result.children.push({
+                            type: DomType.EndnoteReference,
+                            id: globalXmlParser.attr(c, "id")
+                        });
+                        break;
+                    case "drawing":
+                        let d = this.parseDrawing(c);
+                        if (d)
+                            result.children = [d];
+                        break;
+                    case "pict":
+                        result.children.push(this.parseVmlPicture(c));
+                        break;
+                    case "rPr":
+                        this.parseRunProperties(c, result);
+                        break;
+                }
+            });
+            return result;
+        }
+        parseMathElement(elem) {
+            const propsTag = `${elem.localName}Pr`;
+            const result = { type: mmlTagMap[elem.localName], children: [] };
+            for (const el of globalXmlParser.elements(elem)) {
+                const childType = mmlTagMap[el.localName];
+                if (childType) {
+                    result.children.push(this.parseMathElement(el));
+                }
+                else if (el.localName == "r") {
+                    var run = this.parseRun(el);
+                    run.type = DomType.MmlRun;
+                    result.children.push(run);
+                }
+                else if (el.localName == propsTag) {
+                    result.props = this.parseMathProperies(el);
+                }
+            }
+            return result;
+        }
+        parseMathProperies(elem) {
+            const result = {};
+            for (const el of globalXmlParser.elements(elem)) {
+                switch (el.localName) {
+                    case "chr":
+                        result.char = globalXmlParser.attr(el, "val");
+                        break;
+                    case "vertJc":
+                        result.verticalJustification = globalXmlParser.attr(el, "val");
+                        break;
+                    case "pos":
+                        result.position = globalXmlParser.attr(el, "val");
+                        break;
+                    case "degHide":
+                        result.hideDegree = globalXmlParser.boolAttr(el, "val");
+                        break;
+                    case "begChr":
+                        result.beginChar = globalXmlParser.attr(el, "val");
+                        break;
+                    case "endChr":
+                        result.endChar = globalXmlParser.attr(el, "val");
+                        break;
+                }
+            }
+            return result;
+        }
+        parseRunProperties(elem, run) {
+            this.parseDefaultProperties(elem, run.cssStyle = {}, null, c => {
+                switch (c.localName) {
+                    case "rStyle":
+                        run.styleName = globalXmlParser.attr(c, "val");
+                        break;
+                    case "vertAlign":
+                        run.verticalAlign = values.valueOfVertAlign(c, true);
+                        break;
+                    default:
+                        return false;
+                }
+                return true;
+            });
+        }
+        parseVmlPicture(elem) {
+            const result = { type: DomType.VmlPicture, children: [] };
+            for (const el of globalXmlParser.elements(elem)) {
+                const child = parseVmlElement(el, this);
+                child && result.children.push(child);
+            }
+            return result;
+        }
+        checkAlternateContent(elem) {
+            if (elem.localName != 'AlternateContent')
+                return elem;
+            var choice = globalXmlParser.element(elem, "Choice");
+            if (choice) {
+                var requires = globalXmlParser.attr(choice, "Requires");
+                var namespaceURI = elem.lookupNamespaceURI(requires);
+                if (supportedNamespaceURIs.includes(namespaceURI))
+                    return choice.firstElementChild;
+            }
+            return globalXmlParser.element(elem, "Fallback")?.firstElementChild;
+        }
+        parseDrawing(node) {
+            for (var n of globalXmlParser.elements(node)) {
+                switch (n.localName) {
+                    case "inline":
+                    case "anchor":
+                        return this.parseDrawingWrapper(n);
+                }
+            }
+        }
+        parseDrawingWrapper(node) {
+            var result = { type: DomType.Drawing, children: [], cssStyle: {} };
+            var isAnchor = node.localName == "anchor";
+            let wrapType = null;
+            let simplePos = globalXmlParser.boolAttr(node, "simplePos");
+            globalXmlParser.boolAttr(node, "behindDoc");
+            let posX = { relative: "page", align: "left", offset: "0" };
+            let posY = { relative: "page", align: "top", offset: "0" };
+            for (var n of globalXmlParser.elements(node)) {
+                switch (n.localName) {
+                    case "simplePos":
+                        if (simplePos) {
+                            posX.offset = globalXmlParser.lengthAttr(n, "x", LengthUsage.Emu);
+                            posY.offset = globalXmlParser.lengthAttr(n, "y", LengthUsage.Emu);
+                        }
+                        break;
+                    case "extent":
+                        result.cssStyle["width"] = globalXmlParser.lengthAttr(n, "cx", LengthUsage.Emu);
+                        result.cssStyle["height"] = globalXmlParser.lengthAttr(n, "cy", LengthUsage.Emu);
+                        break;
+                    case "positionH":
+                    case "positionV":
+                        if (!simplePos) {
+                            let pos = n.localName == "positionH" ? posX : posY;
+                            var alignNode = globalXmlParser.element(n, "align");
+                            var offsetNode = globalXmlParser.element(n, "posOffset");
+                            pos.relative = globalXmlParser.attr(n, "relativeFrom") ?? pos.relative;
+                            if (alignNode)
+                                pos.align = alignNode.textContent;
+                            if (offsetNode)
+                                pos.offset = xmlUtil.sizeValue(offsetNode, LengthUsage.Emu);
+                        }
+                        break;
+                    case "wrapTopAndBottom":
+                        wrapType = "wrapTopAndBottom";
+                        break;
+                    case "wrapNone":
+                        wrapType = "wrapNone";
+                        break;
+                    case "graphic":
+                        var g = this.parseGraphic(n);
+                        if (g)
+                            result.children.push(g);
+                        break;
+                }
+            }
+            if (wrapType == "wrapTopAndBottom") {
+                result.cssStyle['display'] = 'block';
+                if (posX.align) {
+                    result.cssStyle['text-align'] = posX.align;
+                    result.cssStyle['width'] = "100%";
+                }
+            }
+            else if (wrapType == "wrapNone") {
+                result.cssStyle['display'] = 'block';
+                result.cssStyle['position'] = 'relative';
+                result.cssStyle["width"] = "0px";
+                result.cssStyle["height"] = "0px";
+                if (posX.offset)
+                    result.cssStyle["left"] = posX.offset;
+                if (posY.offset)
+                    result.cssStyle["top"] = posY.offset;
+            }
+            else if (isAnchor && (posX.align == 'left' || posX.align == 'right')) {
+                result.cssStyle["float"] = posX.align;
+            }
+            return result;
+        }
+        parseGraphic(elem) {
+            var graphicData = globalXmlParser.element(elem, "graphicData");
+            for (let n of globalXmlParser.elements(graphicData)) {
+                switch (n.localName) {
+                    case "pic":
+                        return this.parsePicture(n);
+                }
+            }
+            return null;
+        }
+        parsePicture(elem) {
+            var result = { type: DomType.Image, src: "", cssStyle: {} };
+            var blipFill = globalXmlParser.element(elem, "blipFill");
+            var blip = globalXmlParser.element(blipFill, "blip");
+            result.src = globalXmlParser.attr(blip, "embed");
+            var spPr = globalXmlParser.element(elem, "spPr");
+            var xfrm = globalXmlParser.element(spPr, "xfrm");
+            result.cssStyle["position"] = "relative";
+            for (var n of globalXmlParser.elements(xfrm)) {
+                switch (n.localName) {
+                    case "ext":
+                        result.cssStyle["width"] = globalXmlParser.lengthAttr(n, "cx", LengthUsage.Emu);
+                        result.cssStyle["height"] = globalXmlParser.lengthAttr(n, "cy", LengthUsage.Emu);
+                        break;
+                    case "off":
+                        result.cssStyle["left"] = globalXmlParser.lengthAttr(n, "x", LengthUsage.Emu);
+                        result.cssStyle["top"] = globalXmlParser.lengthAttr(n, "y", LengthUsage.Emu);
+                        break;
+                }
+            }
+            return result;
+        }
+        parseTable(node) {
+            var result = { type: DomType.Table, children: [] };
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "tr":
+                        result.children.push(this.parseTableRow(c));
+                        break;
+                    case "tblGrid":
+                        result.columns = this.parseTableColumns(c);
+                        break;
+                    case "tblPr":
+                        this.parseTableProperties(c, result);
+                        break;
+                }
+            });
+            return result;
+        }
+        parseTableColumns(node) {
+            var result = [];
+            xmlUtil.foreach(node, n => {
+                switch (n.localName) {
+                    case "gridCol":
+                        result.push({ width: globalXmlParser.lengthAttr(n, "w") });
+                        break;
+                }
+            });
+            return result;
+        }
+        parseTableProperties(elem, table) {
+            table.cssStyle = {};
+            table.cellStyle = {};
+            this.parseDefaultProperties(elem, table.cssStyle, table.cellStyle, c => {
+                switch (c.localName) {
+                    case "tblStyle":
+                        table.styleName = globalXmlParser.attr(c, "val");
+                        break;
+                    case "tblLook":
+                        table.className = values.classNameOftblLook(c);
+                        break;
+                    case "tblpPr":
+                        this.parseTablePosition(c, table);
+                        break;
+                    case "tblStyleColBandSize":
+                        table.colBandSize = globalXmlParser.intAttr(c, "val");
+                        break;
+                    case "tblStyleRowBandSize":
+                        table.rowBandSize = globalXmlParser.intAttr(c, "val");
+                        break;
+                    default:
+                        return false;
+                }
+                return true;
+            });
+            switch (table.cssStyle["text-align"]) {
+                case "center":
+                    delete table.cssStyle["text-align"];
+                    table.cssStyle["margin-left"] = "auto";
+                    table.cssStyle["margin-right"] = "auto";
+                    break;
+                case "right":
+                    delete table.cssStyle["text-align"];
+                    table.cssStyle["margin-left"] = "auto";
+                    break;
+            }
+        }
+        parseTablePosition(node, table) {
+            var topFromText = globalXmlParser.lengthAttr(node, "topFromText");
+            var bottomFromText = globalXmlParser.lengthAttr(node, "bottomFromText");
+            var rightFromText = globalXmlParser.lengthAttr(node, "rightFromText");
+            var leftFromText = globalXmlParser.lengthAttr(node, "leftFromText");
+            table.cssStyle["float"] = 'left';
+            table.cssStyle["margin-bottom"] = values.addSize(table.cssStyle["margin-bottom"], bottomFromText);
+            table.cssStyle["margin-left"] = values.addSize(table.cssStyle["margin-left"], leftFromText);
+            table.cssStyle["margin-right"] = values.addSize(table.cssStyle["margin-right"], rightFromText);
+            table.cssStyle["margin-top"] = values.addSize(table.cssStyle["margin-top"], topFromText);
+        }
+        parseTableRow(node) {
+            var result = { type: DomType.Row, children: [] };
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "tc":
+                        result.children.push(this.parseTableCell(c));
+                        break;
+                    case "trPr":
+                        this.parseTableRowProperties(c, result);
+                        break;
+                }
+            });
+            return result;
+        }
+        parseTableRowProperties(elem, row) {
+            row.cssStyle = this.parseDefaultProperties(elem, {}, null, c => {
+                switch (c.localName) {
+                    case "cnfStyle":
+                        row.className = values.classNameOfCnfStyle(c);
+                        break;
+                    case "tblHeader":
+                        row.isHeader = globalXmlParser.boolAttr(c, "val");
+                        break;
+                    default:
+                        return false;
+                }
+                return true;
+            });
+        }
+        parseTableCell(node) {
+            var result = { type: DomType.Cell, children: [] };
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "tbl":
+                        result.children.push(this.parseTable(c));
+                        break;
+                    case "p":
+                        result.children.push(this.parseParagraph(c));
+                        break;
+                    case "tcPr":
+                        this.parseTableCellProperties(c, result);
+                        break;
+                }
+            });
+            return result;
+        }
+        parseTableCellProperties(elem, cell) {
+            cell.cssStyle = this.parseDefaultProperties(elem, {}, null, c => {
+                switch (c.localName) {
+                    case "gridSpan":
+                        cell.span = globalXmlParser.intAttr(c, "val", null);
+                        break;
+                    case "vMerge":
+                        cell.verticalMerge = globalXmlParser.attr(c, "val") ?? "continue";
+                        break;
+                    case "cnfStyle":
+                        cell.className = values.classNameOfCnfStyle(c);
+                        break;
+                    default:
+                        return false;
+                }
+                return true;
+            });
+            this.parseTableCellVerticalText(elem, cell);
+        }
+        parseTableCellVerticalText(elem, cell) {
+            const directionMap = {
+                "btLr": {
+                    writingMode: "vertical-rl",
+                    transform: "rotate(180deg)"
+                },
+                "lrTb": {
+                    writingMode: "vertical-lr",
+                    transform: "none"
+                },
+                "tbRl": {
+                    writingMode: "vertical-rl",
+                    transform: "none"
+                }
+            };
+            xmlUtil.foreach(elem, c => {
+                if (c.localName === "textDirection") {
+                    const direction = globalXmlParser.attr(c, "val");
+                    const style = directionMap[direction] || { writingMode: "horizontal-tb" };
+                    cell.cssStyle["writing-mode"] = style.writingMode;
+                    cell.cssStyle["transform"] = style.transform;
+                }
+            });
+        }
+        parseDefaultProperties(elem, style = null, childStyle = null, handler = null) {
+            style = style || {};
+            xmlUtil.foreach(elem, c => {
+                if (handler?.(c))
+                    return;
+                switch (c.localName) {
+                    case "jc":
+                        style["text-align"] = values.valueOfJc(c);
+                        break;
+                    case "textAlignment":
+                        style["vertical-align"] = values.valueOfTextAlignment(c);
+                        break;
+                    case "color":
+                        style["color"] = xmlUtil.colorAttr(c, "val", null, autos.color);
+                        break;
+                    case "sz":
+                        style["font-size"] = style["min-height"] = globalXmlParser.lengthAttr(c, "val", LengthUsage.FontSize);
+                        break;
+                    case "shd":
+                        style["background-color"] = xmlUtil.colorAttr(c, "fill", null, autos.shd);
+                        break;
+                    case "highlight":
+                        style["background-color"] = xmlUtil.colorAttr(c, "val", null, autos.highlight);
+                        break;
+                    case "vertAlign":
+                        break;
+                    case "position":
+                        style.verticalAlign = globalXmlParser.lengthAttr(c, "val", LengthUsage.FontSize);
+                        break;
+                    case "tcW":
+                        if (this.options.ignoreWidth)
+                            break;
+                    case "tblW":
+                        style["width"] = values.valueOfSize(c, "w");
+                        break;
+                    case "trHeight":
+                        this.parseTrHeight(c, style);
+                        break;
+                    case "strike":
+                        style["text-decoration"] = globalXmlParser.boolAttr(c, "val", true) ? "line-through" : "none";
+                        break;
+                    case "b":
+                        style["font-weight"] = globalXmlParser.boolAttr(c, "val", true) ? "bold" : "normal";
+                        break;
+                    case "i":
+                        style["font-style"] = globalXmlParser.boolAttr(c, "val", true) ? "italic" : "normal";
+                        break;
+                    case "caps":
+                        style["text-transform"] = globalXmlParser.boolAttr(c, "val", true) ? "uppercase" : "none";
+                        break;
+                    case "smallCaps":
+                        style["font-variant"] = globalXmlParser.boolAttr(c, "val", true) ? "small-caps" : "none";
+                        break;
+                    case "u":
+                        this.parseUnderline(c, style);
+                        break;
+                    case "ind":
+                    case "tblInd":
+                        this.parseIndentation(c, style);
+                        break;
+                    case "rFonts":
+                        this.parseFont(c, style);
+                        break;
+                    case "tblBorders":
+                        this.parseBorderProperties(c, childStyle || style);
+                        break;
+                    case "tblCellSpacing":
+                        style["border-spacing"] = values.valueOfMargin(c);
+                        style["border-collapse"] = "separate";
+                        break;
+                    case "pBdr":
+                        this.parseBorderProperties(c, style);
+                        break;
+                    case "bdr":
+                        style["border"] = values.valueOfBorder(c);
+                        break;
+                    case "tcBorders":
+                        this.parseBorderProperties(c, style);
+                        break;
+                    case "vanish":
+                        if (globalXmlParser.boolAttr(c, "val", true))
+                            style["display"] = "none";
+                        break;
+                    case "kern":
+                        break;
+                    case "noWrap":
+                        break;
+                    case "tblCellMar":
+                    case "tcMar":
+                        this.parseMarginProperties(c, childStyle || style);
+                        break;
+                    case "tblLayout":
+                        style["table-layout"] = values.valueOfTblLayout(c);
+                        break;
+                    case "vAlign":
+                        style["vertical-align"] = values.valueOfTextAlignment(c);
+                        break;
+                    case "spacing":
+                        if (elem.localName == "pPr")
+                            this.parseSpacing(c, style);
+                        break;
+                    case "wordWrap":
+                        if (globalXmlParser.boolAttr(c, "val"))
+                            style["overflow-wrap"] = "break-word";
+                        break;
+                    case "suppressAutoHyphens":
+                        style["hyphens"] = globalXmlParser.boolAttr(c, "val", true) ? "none" : "auto";
+                        break;
+                    case "lang":
+                        style["$lang"] = globalXmlParser.attr(c, "val");
+                        break;
+                    case "bCs":
+                    case "iCs":
+                    case "szCs":
+                    case "tabs":
+                    case "outlineLvl":
+                    case "contextualSpacing":
+                    case "tblStyleColBandSize":
+                    case "tblStyleRowBandSize":
+                    case "webHidden":
+                    case "pageBreakBefore":
+                    case "suppressLineNumbers":
+                    case "keepLines":
+                    case "keepNext":
+                    case "widowControl":
+                    case "bidi":
+                    case "rtl":
+                    case "noProof":
+                        break;
+                    default:
+                        if (this.options.debug)
+                            console.warn(`DOCX: Unknown document element: ${elem.localName}.${c.localName}`);
+                        break;
+                }
+            });
+            return style;
+        }
+        parseUnderline(node, style) {
+            var val = globalXmlParser.attr(node, "val");
+            if (val == null)
+                return;
+            switch (val) {
+                case "dash":
+                case "dashDotDotHeavy":
+                case "dashDotHeavy":
+                case "dashedHeavy":
+                case "dashLong":
+                case "dashLongHeavy":
+                case "dotDash":
+                case "dotDotDash":
+                    style["text-decoration"] = "underline dashed";
+                    break;
+                case "dotted":
+                case "dottedHeavy":
+                    style["text-decoration"] = "underline dotted";
+                    break;
+                case "double":
+                    style["text-decoration"] = "underline double";
+                    break;
+                case "single":
+                case "thick":
+                    style["text-decoration"] = "underline";
+                    break;
+                case "wave":
+                case "wavyDouble":
+                case "wavyHeavy":
+                    style["text-decoration"] = "underline wavy";
+                    break;
+                case "words":
+                    style["text-decoration"] = "underline";
+                    break;
+                case "none":
+                    style["text-decoration"] = "none";
+                    break;
+            }
+            var col = xmlUtil.colorAttr(node, "color");
+            if (col)
+                style["text-decoration-color"] = col;
+        }
+        parseFont(node, style) {
+            var ascii = globalXmlParser.attr(node, "ascii");
+            var asciiTheme = values.themeValue(node, "asciiTheme");
+            var eastAsia = globalXmlParser.attr(node, "eastAsia");
+            var fonts = [ascii, asciiTheme, eastAsia].filter(x => x).map(x => encloseFontFamily(x));
+            if (fonts.length > 0)
+                style["font-family"] = [...new Set(fonts)].join(', ');
+        }
+        parseIndentation(node, style) {
+            var firstLine = globalXmlParser.lengthAttr(node, "firstLine");
+            var hanging = globalXmlParser.lengthAttr(node, "hanging");
+            var left = globalXmlParser.lengthAttr(node, "left");
+            var start = globalXmlParser.lengthAttr(node, "start");
+            var right = globalXmlParser.lengthAttr(node, "right");
+            var end = globalXmlParser.lengthAttr(node, "end");
+            if (firstLine)
+                style["text-indent"] = firstLine;
+            if (hanging)
+                style["text-indent"] = `-${hanging}`;
+            if (left || start)
+                style["margin-left"] = left || start;
+            if (right || end)
+                style["margin-right"] = right || end;
+        }
+        parseSpacing(node, style) {
+            var before = globalXmlParser.lengthAttr(node, "before");
+            var after = globalXmlParser.lengthAttr(node, "after");
+            var line = globalXmlParser.intAttr(node, "line", null);
+            var lineRule = globalXmlParser.attr(node, "lineRule");
+            if (before)
+                style["margin-top"] = before;
+            if (after)
+                style["margin-bottom"] = after;
+            if (line !== null) {
+                switch (lineRule) {
+                    case "auto":
+                        style["line-height"] = `${(line / 240).toFixed(2)}`;
+                        break;
+                    case "atLeast":
+                        style["line-height"] = `calc(100% + ${line / 20}pt)`;
+                        break;
+                    default:
+                        style["line-height"] = style["min-height"] = `${line / 20}pt`;
+                        break;
+                }
+            }
+        }
+        parseMarginProperties(node, output) {
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "left":
+                        output["padding-left"] = values.valueOfMargin(c);
+                        break;
+                    case "right":
+                        output["padding-right"] = values.valueOfMargin(c);
+                        break;
+                    case "top":
+                        output["padding-top"] = values.valueOfMargin(c);
+                        break;
+                    case "bottom":
+                        output["padding-bottom"] = values.valueOfMargin(c);
+                        break;
+                }
+            });
+        }
+        parseTrHeight(node, output) {
+            switch (globalXmlParser.attr(node, "hRule")) {
+                case "exact":
+                    output["height"] = globalXmlParser.lengthAttr(node, "val");
+                    break;
+                case "atLeast":
+                default:
+                    output["height"] = globalXmlParser.lengthAttr(node, "val");
+                    break;
+            }
+        }
+        parseBorderProperties(node, output) {
+            xmlUtil.foreach(node, c => {
+                switch (c.localName) {
+                    case "start":
+                    case "left":
+                        output["border-left"] = values.valueOfBorder(c);
+                        break;
+                    case "end":
+                    case "right":
+                        output["border-right"] = values.valueOfBorder(c);
+                        break;
+                    case "top":
+                        output["border-top"] = values.valueOfBorder(c);
+                        break;
+                    case "bottom":
+                        output["border-bottom"] = values.valueOfBorder(c);
+                        break;
+                }
+            });
+        }
+    }
+    const knownColors = ['black', 'blue', 'cyan', 'darkBlue', 'darkCyan', 'darkGray', 'darkGreen', 'darkMagenta', 'darkRed', 'darkYellow', 'green', 'lightGray', 'magenta', 'none', 'red', 'white', 'yellow'];
+    class xmlUtil {
+        static foreach(node, cb) {
+            for (var i = 0; i < node.childNodes.length; i++) {
+                let n = node.childNodes[i];
+                if (n.nodeType == Node.ELEMENT_NODE)
+                    cb(n);
+            }
+        }
+        static colorAttr(node, attrName, defValue = null, autoColor = 'black') {
+            var v = globalXmlParser.attr(node, attrName);
+            if (v) {
+                if (v == "auto") {
+                    return autoColor;
+                }
+                else if (knownColors.includes(v)) {
+                    return v;
+                }
+                return `#${v}`;
+            }
+            var themeColor = globalXmlParser.attr(node, "themeColor");
+            return themeColor ? `var(--docx-${themeColor}-color)` : defValue;
+        }
+        static sizeValue(node, type = LengthUsage.Dxa) {
+            return convertLength(node.textContent, type);
+        }
+    }
+    class values {
+        static themeValue(c, attr) {
+            var val = globalXmlParser.attr(c, attr);
+            return val ? `var(--docx-${val}-font)` : null;
+        }
+        static valueOfSize(c, attr) {
+            var type = LengthUsage.Dxa;
+            switch (globalXmlParser.attr(c, "type")) {
+                case "dxa": break;
+                case "pct":
+                    type = LengthUsage.Percent;
+                    break;
+                case "auto": return "auto";
+            }
+            return globalXmlParser.lengthAttr(c, attr, type);
+        }
+        static valueOfMargin(c) {
+            return globalXmlParser.lengthAttr(c, "w");
+        }
+        static valueOfBorder(c) {
+            var type = globalXmlParser.attr(c, "val");
+            if (type == "nil")
+                return "none";
+            var color = xmlUtil.colorAttr(c, "color");
+            var size = globalXmlParser.lengthAttr(c, "sz", LengthUsage.Border);
+            return `${size} solid ${color == "auto" ? autos.borderColor : color}`;
+        }
+        static valueOfTblLayout(c) {
+            var type = globalXmlParser.attr(c, "val");
+            return type == "fixed" ? "fixed" : "auto";
+        }
+        static classNameOfCnfStyle(c) {
+            const val = globalXmlParser.attr(c, "val");
+            const classes = [
+                'first-row', 'last-row', 'first-col', 'last-col',
+                'odd-col', 'even-col', 'odd-row', 'even-row',
+                'ne-cell', 'nw-cell', 'se-cell', 'sw-cell'
+            ];
+            return classes.filter((_, i) => val[i] == '1').join(' ');
+        }
+        static valueOfJc(c) {
+            var type = globalXmlParser.attr(c, "val");
+            switch (type) {
+                case "start":
+                case "left": return "left";
+                case "center": return "center";
+                case "end":
+                case "right": return "right";
+                case "both": return "justify";
+            }
+            return type;
+        }
+        static valueOfVertAlign(c, asTagName = false) {
+            var type = globalXmlParser.attr(c, "val");
+            switch (type) {
+                case "subscript": return "sub";
+                case "superscript": return asTagName ? "sup" : "super";
+            }
+            return asTagName ? null : type;
+        }
+        static valueOfTextAlignment(c) {
+            var type = globalXmlParser.attr(c, "val");
+            switch (type) {
+                case "auto":
+                case "baseline": return "baseline";
+                case "top": return "top";
+                case "center": return "middle";
+                case "bottom": return "bottom";
+            }
+            return type;
+        }
+        static addSize(a, b) {
+            if (a == null)
+                return b;
+            if (b == null)
+                return a;
+            return `calc(${a} + ${b})`;
+        }
+        static classNameOftblLook(c) {
+            const val = globalXmlParser.hexAttr(c, "val", 0);
+            let className = "";
+            if (globalXmlParser.boolAttr(c, "firstRow") || (val & 0x0020))
+                className += " first-row";
+            if (globalXmlParser.boolAttr(c, "lastRow") || (val & 0x0040))
+                className += " last-row";
+            if (globalXmlParser.boolAttr(c, "firstColumn") || (val & 0x0080))
+                className += " first-col";
+            if (globalXmlParser.boolAttr(c, "lastColumn") || (val & 0x0100))
+                className += " last-col";
+            if (globalXmlParser.boolAttr(c, "noHBand") || (val & 0x0200))
+                className += " no-hband";
+            if (globalXmlParser.boolAttr(c, "noVBand") || (val & 0x0400))
+                className += " no-vband";
+            return className.trim();
+        }
+    }
+
+    const defaultTab = { pos: 0, leader: "none", style: "left" };
+    const maxTabs = 50;
+    function computePixelToPoint(container = document.body) {
+        const temp = document.createElement("div");
+        temp.style.width = '100pt';
+        container.appendChild(temp);
+        const result = 100 / temp.offsetWidth;
+        container.removeChild(temp);
+        return result;
+    }
+    function updateTabStop(elem, tabs, defaultTabSize, pixelToPoint = 72 / 96) {
+        const p = elem.closest("p");
+        const ebb = elem.getBoundingClientRect();
+        const pbb = p.getBoundingClientRect();
+        const pcs = getComputedStyle(p);
+        const tabStops = tabs?.length > 0 ? tabs.map(t => ({
+            pos: lengthToPoint(t.position),
+            leader: t.leader,
+            style: t.style
+        })).sort((a, b) => a.pos - b.pos) : [defaultTab];
+        const lastTab = tabStops[tabStops.length - 1];
+        const pWidthPt = pbb.width * pixelToPoint;
+        const size = lengthToPoint(defaultTabSize);
+        let pos = lastTab.pos + size;
+        if (pos < pWidthPt) {
+            for (; pos < pWidthPt && tabStops.length < maxTabs; pos += size) {
+                tabStops.push({ ...defaultTab, pos: pos });
+            }
+        }
+        const marginLeft = parseFloat(pcs.marginLeft);
+        const pOffset = pbb.left + marginLeft;
+        const left = (ebb.left - pOffset) * pixelToPoint;
+        const tab = tabStops.find(t => t.style != "clear" && t.pos > left);
+        if (tab == null)
+            return;
+        let width = 1;
+        if (tab.style == "right" || tab.style == "center") {
+            const tabStops = Array.from(p.querySelectorAll(`.${elem.className}`));
+            const nextIdx = tabStops.indexOf(elem) + 1;
+            const range = document.createRange();
+            range.setStart(elem, 1);
+            if (nextIdx < tabStops.length) {
+                range.setEndBefore(tabStops[nextIdx]);
+            }
+            else {
+                range.setEndAfter(p);
+            }
+            const mul = tab.style == "center" ? 0.5 : 1;
+            const nextBB = range.getBoundingClientRect();
+            const offset = nextBB.left + mul * nextBB.width - (pbb.left - marginLeft);
+            width = tab.pos - offset * pixelToPoint;
+        }
+        else {
+            width = tab.pos - left;
+        }
+        elem.innerHTML = "&nbsp;";
+        elem.style.textDecoration = "inherit";
+        elem.style.wordSpacing = `${width.toFixed(0)}pt`;
+        switch (tab.leader) {
+            case "dot":
+            case "middleDot":
+                elem.style.textDecoration = "underline";
+                elem.style.textDecorationStyle = "dotted";
+                break;
+            case "hyphen":
+            case "heavy":
+            case "underscore":
+                elem.style.textDecoration = "underline";
+                break;
+        }
+    }
+    function lengthToPoint(length) {
+        return parseFloat(length);
+    }
+
+    const ns = {
+        svg: "http://www.w3.org/2000/svg",
+        mathML: "http://www.w3.org/1998/Math/MathML"
+    };
+    class HtmlRenderer {
+        constructor(htmlDocument) {
+            this.htmlDocument = htmlDocument;
+            this.className = "docx";
+            this.styleMap = {};
+            this.currentPart = null;
+            this.tableVerticalMerges = [];
+            this.currentVerticalMerge = null;
+            this.tableCellPositions = [];
+            this.currentCellPosition = null;
+            this.footnoteMap = {};
+            this.endnoteMap = {};
+            this.currentEndnoteIds = [];
+            this.usedHederFooterParts = [];
+            this.currentTabs = [];
+            this.commentMap = {};
+            this.tasks = [];
+            this.postRenderTasks = [];
+        }
+        async render(document, bodyContainer, styleContainer = null, options) {
+            this.document = document;
+            this.options = options;
+            this.className = options.className;
+            this.rootSelector = options.inWrapper ? `.${this.className}-wrapper` : ':root';
+            this.styleMap = null;
+            this.tasks = [];
+            if (this.options.renderComments && globalThis.Highlight) {
+                this.commentHighlight = new Highlight();
+            }
+            styleContainer = styleContainer || bodyContainer;
+            removeAllElements(styleContainer);
+            removeAllElements(bodyContainer);
+            styleContainer.appendChild(this.createComment("docxjs library predefined styles"));
+            styleContainer.appendChild(this.renderDefaultStyle());
+            if (document.themePart) {
+                styleContainer.appendChild(this.createComment("docxjs document theme values"));
+                this.renderTheme(document.themePart, styleContainer);
+            }
+            if (document.stylesPart != null) {
+                this.styleMap = this.processStyles(document.stylesPart.styles);
+                styleContainer.appendChild(this.createComment("docxjs document styles"));
+                styleContainer.appendChild(this.renderStyles(document.stylesPart.styles));
+            }
+            if (document.numberingPart) {
+                this.prodessNumberings(document.numberingPart.domNumberings);
+                styleContainer.appendChild(this.createComment("docxjs document numbering styles"));
+                styleContainer.appendChild(this.renderNumbering(document.numberingPart.domNumberings, styleContainer));
+            }
+            if (document.footnotesPart) {
+                this.footnoteMap = keyBy(document.footnotesPart.notes, x => x.id);
+            }
+            if (document.endnotesPart) {
+                this.endnoteMap = keyBy(document.endnotesPart.notes, x => x.id);
+            }
+            if (document.settingsPart) {
+                this.defaultTabSize = document.settingsPart.settings?.defaultTabStop;
+            }
+            if (!options.ignoreFonts && document.fontTablePart)
+                this.renderFontTable(document.fontTablePart, styleContainer);
+            var sectionElements = this.renderSections(document.documentPart.body);
+            if (this.options.inWrapper) {
+                bodyContainer.appendChild(this.renderWrapper(sectionElements));
+            }
+            else {
+                appendChildren(bodyContainer, sectionElements);
+            }
+            if (this.commentHighlight && options.renderComments) {
+                CSS.highlights.set(`${this.className}-comments`, this.commentHighlight);
+            }
+            this.postRenderTasks.forEach(t => t());
+            await Promise.allSettled(this.tasks);
+            this.refreshTabStops();
+        }
+        renderTheme(themePart, styleContainer) {
+            const variables = {};
+            const fontScheme = themePart.theme?.fontScheme;
+            if (fontScheme) {
+                if (fontScheme.majorFont) {
+                    variables['--docx-majorHAnsi-font'] = fontScheme.majorFont.latinTypeface;
+                }
+                if (fontScheme.minorFont) {
+                    variables['--docx-minorHAnsi-font'] = fontScheme.minorFont.latinTypeface;
+                }
+            }
+            const colorScheme = themePart.theme?.colorScheme;
+            if (colorScheme) {
+                for (let [k, v] of Object.entries(colorScheme.colors)) {
+                    variables[`--docx-${k}-color`] = `#${v}`;
+                }
+            }
+            const cssText = this.styleToString(`.${this.className}`, variables);
+            styleContainer.appendChild(this.createStyleElement(cssText));
+        }
+        renderFontTable(fontsPart, styleContainer) {
+            for (let f of fontsPart.fonts) {
+                for (let ref of f.embedFontRefs) {
+                    this.tasks.push(this.document.loadFont(ref.id, ref.key).then(fontData => {
+                        const cssValues = {
+                            'font-family': encloseFontFamily(f.name),
+                            'src': `url(${fontData})`
+                        };
+                        if (ref.type == "bold" || ref.type == "boldItalic") {
+                            cssValues['font-weight'] = 'bold';
+                        }
+                        if (ref.type == "italic" || ref.type == "boldItalic") {
+                            cssValues['font-style'] = 'italic';
+                        }
+                        const cssText = this.styleToString("@font-face", cssValues);
+                        styleContainer.appendChild(this.createComment(`docxjs ${f.name} font`));
+                        styleContainer.appendChild(this.createStyleElement(cssText));
+                    }));
+                }
+            }
+        }
+        processStyleName(className) {
+            return className ? `${this.className}_${escapeClassName(className)}` : this.className;
+        }
+        processStyles(styles) {
+            const stylesMap = keyBy(styles.filter(x => x.id != null), x => x.id);
+            for (const style of styles.filter(x => x.basedOn)) {
+                var baseStyle = stylesMap[style.basedOn];
+                if (baseStyle) {
+                    style.paragraphProps = mergeDeep(style.paragraphProps, baseStyle.paragraphProps);
+                    style.runProps = mergeDeep(style.runProps, baseStyle.runProps);
+                    for (const baseValues of baseStyle.styles) {
+                        const styleValues = style.styles.find(x => x.target == baseValues.target);
+                        if (styleValues) {
+                            this.copyStyleProperties(baseValues.values, styleValues.values);
+                        }
+                        else {
+                            style.styles.push({ ...baseValues, values: { ...baseValues.values } });
+                        }
+                    }
+                }
+                else if (this.options.debug)
+                    console.warn(`Can't find base style ${style.basedOn}`);
+            }
+            for (let style of styles) {
+                style.cssName = this.processStyleName(style.id);
+            }
+            return stylesMap;
+        }
+        prodessNumberings(numberings) {
+            for (let num of numberings.filter(n => n.pStyleName)) {
+                const style = this.findStyle(num.pStyleName);
+                if (style?.paragraphProps?.numbering) {
+                    style.paragraphProps.numbering.level = num.level;
+                }
+            }
+        }
+        processElement(element) {
+            if (element.children) {
+                for (var e of element.children) {
+                    e.parent = element;
+                    if (e.type == DomType.Table) {
+                        this.processTable(e);
+                    }
+                    else {
+                        this.processElement(e);
+                    }
+                }
+            }
+        }
+        processTable(table) {
+            for (var r of table.children) {
+                for (var c of r.children) {
+                    c.cssStyle = this.copyStyleProperties(table.cellStyle, c.cssStyle, [
+                        "border-left", "border-right", "border-top", "border-bottom",
+                        "padding-left", "padding-right", "padding-top", "padding-bottom"
+                    ]);
+                    this.processElement(c);
+                }
+            }
+        }
+        copyStyleProperties(input, output, attrs = null) {
+            if (!input)
+                return output;
+            if (output == null)
+                output = {};
+            if (attrs == null)
+                attrs = Object.getOwnPropertyNames(input);
+            for (var key of attrs) {
+                if (input.hasOwnProperty(key) && !output.hasOwnProperty(key))
+                    output[key] = input[key];
+            }
+            return output;
+        }
+        createPageElement(className, props) {
+            var elem = this.createElement("section", { className });
+            if (props) {
+                if (props.pageMargins) {
+                    elem.style.paddingLeft = props.pageMargins.left;
+                    elem.style.paddingRight = props.pageMargins.right;
+                    elem.style.paddingTop = props.pageMargins.top;
+                    elem.style.paddingBottom = props.pageMargins.bottom;
+                }
+                if (props.pageSize) {
+                    if (!this.options.ignoreWidth)
+                        elem.style.width = props.pageSize.width;
+                    if (!this.options.ignoreHeight)
+                        elem.style.minHeight = props.pageSize.height;
+                }
+            }
+            return elem;
+        }
+        createSectionContent(props) {
+            var elem = this.createElement("article");
+            if (props.columns && props.columns.numberOfColumns) {
+                elem.style.columnCount = `${props.columns.numberOfColumns}`;
+                elem.style.columnGap = props.columns.space;
+                if (props.columns.separator) {
+                    elem.style.columnRule = "1px solid black";
+                }
+            }
+            return elem;
+        }
+        renderSections(document) {
+            const result = [];
+            this.processElement(document);
+            const sections = this.splitBySection(document.children, document.props);
+            const pages = this.groupByPageBreaks(sections);
+            let prevProps = null;
+            for (let i = 0, l = pages.length; i < l; i++) {
+                this.currentFootnoteIds = [];
+                const section = pages[i][0];
+                let props = section.sectProps;
+                const pageElement = this.createPageElement(this.className, props);
+                this.renderStyleValues(document.cssStyle, pageElement);
+                this.options.renderHeaders && this.renderHeaderFooter(props.headerRefs, props, result.length, prevProps != props, pageElement);
+                for (const sect of pages[i]) {
+                    var contentElement = this.createSectionContent(sect.sectProps);
+                    this.renderElements(sect.elements, contentElement);
+                    pageElement.appendChild(contentElement);
+                    props = sect.sectProps;
+                }
+                if (this.options.renderFootnotes) {
+                    this.renderNotes(this.currentFootnoteIds, this.footnoteMap, pageElement);
+                }
+                if (this.options.renderEndnotes && i == l - 1) {
+                    this.renderNotes(this.currentEndnoteIds, this.endnoteMap, pageElement);
+                }
+                this.options.renderFooters && this.renderHeaderFooter(props.footerRefs, props, result.length, prevProps != props, pageElement);
+                result.push(pageElement);
+                prevProps = props;
+            }
+            return result;
+        }
+        renderHeaderFooter(refs, props, page, firstOfSection, into) {
+            if (!refs)
+                return;
+            var ref = (props.titlePage && firstOfSection ? refs.find(x => x.type == "first") : null)
+                ?? (page % 2 == 1 ? refs.find(x => x.type == "even") : null)
+                ?? refs.find(x => x.type == "default");
+            var part = ref && this.document.findPartByRelId(ref.id, this.document.documentPart);
+            if (part) {
+                this.currentPart = part;
+                if (!this.usedHederFooterParts.includes(part.path)) {
+                    this.processElement(part.rootElement);
+                    this.usedHederFooterParts.push(part.path);
+                }
+                const [el] = this.renderElements([part.rootElement], into);
+                if (props?.pageMargins) {
+                    if (part.rootElement.type === DomType.Header) {
+                        el.style.marginTop = `calc(${props.pageMargins.header} - ${props.pageMargins.top})`;
+                        el.style.minHeight = `calc(${props.pageMargins.top} - ${props.pageMargins.header})`;
+                    }
+                    else if (part.rootElement.type === DomType.Footer) {
+                        el.style.marginBottom = `calc(${props.pageMargins.footer} - ${props.pageMargins.bottom})`;
+                        el.style.minHeight = `calc(${props.pageMargins.bottom} - ${props.pageMargins.footer})`;
+                    }
+                }
+                this.currentPart = null;
+            }
+        }
+        isPageBreakElement(elem) {
+            if (elem.type != DomType.Break)
+                return false;
+            if (elem.break == "lastRenderedPageBreak")
+                return !this.options.ignoreLastRenderedPageBreak;
+            return elem.break == "page";
+        }
+        isPageBreakSection(prev, next) {
+            if (!prev)
+                return false;
+            if (!next)
+                return false;
+            return prev.pageSize?.orientation != next.pageSize?.orientation
+                || prev.pageSize?.width != next.pageSize?.width
+                || prev.pageSize?.height != next.pageSize?.height;
+        }
+        splitBySection(elements, defaultProps) {
+            var current = { sectProps: null, elements: [], pageBreak: false };
+            var result = [current];
+            for (let elem of elements) {
+                if (elem.type == DomType.Paragraph) {
+                    const s = this.findStyle(elem.styleName);
+                    if (s?.paragraphProps?.pageBreakBefore) {
+                        current.sectProps = sectProps;
+                        current.pageBreak = true;
+                        current = { sectProps: null, elements: [], pageBreak: false };
+                        result.push(current);
+                    }
+                }
+                current.elements.push(elem);
+                if (elem.type == DomType.Paragraph) {
+                    const p = elem;
+                    var sectProps = p.sectionProps;
+                    var pBreakIndex = -1;
+                    var rBreakIndex = -1;
+                    if (this.options.breakPages && p.children) {
+                        pBreakIndex = p.children.findIndex(r => {
+                            rBreakIndex = r.children?.findIndex(this.isPageBreakElement.bind(this)) ?? -1;
+                            return rBreakIndex != -1;
+                        });
+                    }
+                    if (sectProps || pBreakIndex != -1) {
+                        current.sectProps = sectProps;
+                        current.pageBreak = pBreakIndex != -1;
+                        current = { sectProps: null, elements: [], pageBreak: false };
+                        result.push(current);
+                    }
+                    if (pBreakIndex != -1) {
+                        let breakRun = p.children[pBreakIndex];
+                        let splitRun = rBreakIndex < breakRun.children.length - 1;
+                        if (pBreakIndex < p.children.length - 1 || splitRun) {
+                            var children = elem.children;
+                            var newParagraph = { ...elem, children: children.slice(pBreakIndex) };
+                            elem.children = children.slice(0, pBreakIndex);
+                            current.elements.push(newParagraph);
+                            if (splitRun) {
+                                let runChildren = breakRun.children;
+                                let newRun = { ...breakRun, children: runChildren.slice(0, rBreakIndex) };
+                                elem.children.push(newRun);
+                                breakRun.children = runChildren.slice(rBreakIndex);
+                            }
+                        }
+                    }
+                }
+            }
+            let currentSectProps = null;
+            for (let i = result.length - 1; i >= 0; i--) {
+                if (result[i].sectProps == null) {
+                    result[i].sectProps = currentSectProps ?? defaultProps;
+                }
+                else {
+                    currentSectProps = result[i].sectProps;
+                }
+            }
+            return result;
+        }
+        groupByPageBreaks(sections) {
+            let current = [];
+            let prev;
+            const result = [current];
+            for (let s of sections) {
+                current.push(s);
+                if (this.options.ignoreLastRenderedPageBreak || s.pageBreak || this.isPageBreakSection(prev, s.sectProps))
+                    result.push(current = []);
+                prev = s.sectProps;
+            }
+            return result.filter(x => x.length > 0);
+        }
+        renderWrapper(children) {
+            return this.createElement("div", { className: `${this.className}-wrapper` }, children);
+        }
+        renderDefaultStyle() {
+            var c = this.className;
+            var styleText = `
+.${c}-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; } 
+.${c}-wrapper>section.${c} { background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); margin-bottom: 30px; }
+.${c} { color: black; hyphens: auto; text-underline-position: from-font; }
+section.${c} { box-sizing: border-box; display: flex; flex-flow: column nowrap; position: relative; overflow: hidden; }
+section.${c}>article { margin-bottom: auto; z-index: 1; }
+section.${c}>footer { z-index: 1; }
+.${c} table { border-collapse: collapse; }
+.${c} table td, .${c} table th { vertical-align: top; }
+.${c} p { margin: 0pt; min-height: 1em; }
+.${c} span { white-space: pre-wrap; overflow-wrap: break-word; }
+.${c} a { color: inherit; text-decoration: inherit; }
+.${c} svg { fill: transparent; }
+`;
+            if (this.options.renderComments) {
+                styleText += `
+.${c}-comment-ref { cursor: default; }
+.${c}-comment-popover { display: none; z-index: 1000; padding: 0.5rem; background: white; position: absolute; box-shadow: 0 0 0.25rem rgba(0, 0, 0, 0.25); width: 30ch; }
+.${c}-comment-ref:hover~.${c}-comment-popover { display: block; }
+.${c}-comment-author,.${c}-comment-date { font-size: 0.875rem; color: #888; }
+`;
+            }
+            return this.createStyleElement(styleText);
+        }
+        renderNumbering(numberings, styleContainer) {
+            var styleText = "";
+            var resetCounters = [];
+            for (var num of numberings) {
+                var selector = `p.${this.numberingClass(num.id, num.level)}`;
+                var listStyleType = "none";
+                if (num.bullet) {
+                    let valiable = `--${this.className}-${num.bullet.src}`.toLowerCase();
+                    styleText += this.styleToString(`${selector}:before`, {
+                        "content": "' '",
+                        "display": "inline-block",
+                        "background": `var(${valiable})`
+                    }, num.bullet.style);
+                    this.tasks.push(this.document.loadNumberingImage(num.bullet.src).then(data => {
+                        var text = `${this.rootSelector} { ${valiable}: url(${data}) }`;
+                        styleContainer.appendChild(this.createStyleElement(text));
+                    }));
+                }
+                else if (num.levelText) {
+                    let counter = this.numberingCounter(num.id, num.level);
+                    const counterReset = counter + " " + (num.start - 1);
+                    if (num.level > 0) {
+                        styleText += this.styleToString(`p.${this.numberingClass(num.id, num.level - 1)}`, {
+                            "counter-reset": counterReset
+                        });
+                    }
+                    resetCounters.push(counterReset);
+                    styleText += this.styleToString(`${selector}:before`, {
+                        "content": this.levelTextToContent(num.levelText, num.suff, num.id, this.numFormatToCssValue(num.format)),
+                        "counter-increment": counter,
+                        ...num.rStyle,
+                    });
+                }
+                else {
+                    listStyleType = this.numFormatToCssValue(num.format);
+                }
+                styleText += this.styleToString(selector, {
+                    "display": "list-item",
+                    "list-style-position": "inside",
+                    "list-style-type": listStyleType,
+                    ...num.pStyle
+                });
+            }
+            if (resetCounters.length > 0) {
+                styleText += this.styleToString(this.rootSelector, {
+                    "counter-reset": resetCounters.join(" ")
+                });
+            }
+            return this.createStyleElement(styleText);
+        }
+        renderStyles(styles) {
+            var styleText = "";
+            const stylesMap = this.styleMap;
+            const defautStyles = keyBy(styles.filter(s => s.isDefault), s => s.target);
+            for (const style of styles) {
+                var subStyles = style.styles;
+                if (style.linked) {
+                    var linkedStyle = style.linked && stylesMap[style.linked];
+                    if (linkedStyle)
+                        subStyles = subStyles.concat(linkedStyle.styles);
+                    else if (this.options.debug)
+                        console.warn(`Can't find linked style ${style.linked}`);
+                }
+                for (const subStyle of subStyles) {
+                    var selector = `${style.target ?? ''}.${style.cssName}`;
+                    if (style.target != subStyle.target)
+                        selector += ` ${subStyle.target}`;
+                    if (defautStyles[style.target] == style)
+                        selector = `.${this.className} ${style.target}, ` + selector;
+                    styleText += this.styleToString(selector, subStyle.values);
+                }
+            }
+            return this.createStyleElement(styleText);
+        }
+        renderNotes(noteIds, notesMap, into) {
+            var notes = noteIds.map(id => notesMap[id]).filter(x => x);
+            if (notes.length > 0) {
+                var result = this.createElement("ol", null, this.renderElements(notes));
+                into.appendChild(result);
+            }
+        }
+        renderElement(elem) {
+            switch (elem.type) {
+                case DomType.Paragraph:
+                    return this.renderParagraph(elem);
+                case DomType.BookmarkStart:
+                    return this.renderBookmarkStart(elem);
+                case DomType.BookmarkEnd:
+                    return null;
+                case DomType.Run:
+                    return this.renderRun(elem);
+                case DomType.Table:
+                    return this.renderTable(elem);
+                case DomType.Row:
+                    return this.renderTableRow(elem);
+                case DomType.Cell:
+                    return this.renderTableCell(elem);
+                case DomType.Hyperlink:
+                    return this.renderHyperlink(elem);
+                case DomType.SmartTag:
+                    return this.renderSmartTag(elem);
+                case DomType.Drawing:
+                    return this.renderDrawing(elem);
+                case DomType.Image:
+                    return this.renderImage(elem);
+                case DomType.Text:
+                    return this.renderText(elem);
+                case DomType.Text:
+                    return this.renderText(elem);
+                case DomType.DeletedText:
+                    return this.renderDeletedText(elem);
+                case DomType.Tab:
+                    return this.renderTab(elem);
+                case DomType.Symbol:
+                    return this.renderSymbol(elem);
+                case DomType.Break:
+                    return this.renderBreak(elem);
+                case DomType.Footer:
+                    return this.renderContainer(elem, "footer");
+                case DomType.Header:
+                    return this.renderContainer(elem, "header");
+                case DomType.Footnote:
+                case DomType.Endnote:
+                    return this.renderContainer(elem, "li");
+                case DomType.FootnoteReference:
+                    return this.renderFootnoteReference(elem);
+                case DomType.EndnoteReference:
+                    return this.renderEndnoteReference(elem);
+                case DomType.NoBreakHyphen:
+                    return this.createElement("wbr");
+                case DomType.VmlPicture:
+                    return this.renderVmlPicture(elem);
+                case DomType.VmlElement:
+                    return this.renderVmlElement(elem);
+                case DomType.MmlMath:
+                    return this.renderContainerNS(elem, ns.mathML, "math", { xmlns: ns.mathML });
+                case DomType.MmlMathParagraph:
+                    return this.renderContainer(elem, "span");
+                case DomType.MmlFraction:
+                    return this.renderContainerNS(elem, ns.mathML, "mfrac");
+                case DomType.MmlBase:
+                    return this.renderContainerNS(elem, ns.mathML, elem.parent.type == DomType.MmlMatrixRow ? "mtd" : "mrow");
+                case DomType.MmlNumerator:
+                case DomType.MmlDenominator:
+                case DomType.MmlFunction:
+                case DomType.MmlLimit:
+                case DomType.MmlBox:
+                    return this.renderContainerNS(elem, ns.mathML, "mrow");
+                case DomType.MmlGroupChar:
+                    return this.renderMmlGroupChar(elem);
+                case DomType.MmlLimitLower:
+                    return this.renderContainerNS(elem, ns.mathML, "munder");
+                case DomType.MmlMatrix:
+                    return this.renderContainerNS(elem, ns.mathML, "mtable");
+                case DomType.MmlMatrixRow:
+                    return this.renderContainerNS(elem, ns.mathML, "mtr");
+                case DomType.MmlRadical:
+                    return this.renderMmlRadical(elem);
+                case DomType.MmlSuperscript:
+                    return this.renderContainerNS(elem, ns.mathML, "msup");
+                case DomType.MmlSubscript:
+                    return this.renderContainerNS(elem, ns.mathML, "msub");
+                case DomType.MmlDegree:
+                case DomType.MmlSuperArgument:
+                case DomType.MmlSubArgument:
+                    return this.renderContainerNS(elem, ns.mathML, "mn");
+                case DomType.MmlFunctionName:
+                    return this.renderContainerNS(elem, ns.mathML, "ms");
+                case DomType.MmlDelimiter:
+                    return this.renderMmlDelimiter(elem);
+                case DomType.MmlRun:
+                    return this.renderMmlRun(elem);
+                case DomType.MmlNary:
+                    return this.renderMmlNary(elem);
+                case DomType.MmlPreSubSuper:
+                    return this.renderMmlPreSubSuper(elem);
+                case DomType.MmlBar:
+                    return this.renderMmlBar(elem);
+                case DomType.MmlEquationArray:
+                    return this.renderMllList(elem);
+                case DomType.Inserted:
+                    return this.renderInserted(elem);
+                case DomType.Deleted:
+                    return this.renderDeleted(elem);
+                case DomType.CommentRangeStart:
+                    return this.renderCommentRangeStart(elem);
+                case DomType.CommentRangeEnd:
+                    return this.renderCommentRangeEnd(elem);
+                case DomType.CommentReference:
+                    return this.renderCommentReference(elem);
+            }
+            return null;
+        }
+        renderElements(elems, into) {
+            if (elems == null)
+                return null;
+            var result = elems.flatMap(e => this.renderElement(e)).filter(e => e != null);
+            if (into)
+                appendChildren(into, result);
+            return result;
+        }
+        renderContainer(elem, tagName, props) {
+            return this.createElement(tagName, props, this.renderElements(elem.children));
+        }
+        renderContainerNS(elem, ns, tagName, props) {
+            return this.createElementNS(ns, tagName, props, this.renderElements(elem.children));
+        }
+        renderParagraph(elem) {
+            var result = this.renderContainer(elem, "p");
+            const style = this.findStyle(elem.styleName);
+            elem.tabs ?? (elem.tabs = style?.paragraphProps?.tabs);
+            this.renderClass(elem, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            this.renderCommonProperties(result.style, elem);
+            const numbering = elem.numbering ?? style?.paragraphProps?.numbering;
+            if (numbering) {
+                result.classList.add(this.numberingClass(numbering.id, numbering.level));
+            }
+            return result;
+        }
+        renderRunProperties(style, props) {
+            this.renderCommonProperties(style, props);
+        }
+        renderCommonProperties(style, props) {
+            if (props == null)
+                return;
+            if (props.color) {
+                style["color"] = props.color;
+            }
+            if (props.fontSize) {
+                style["font-size"] = props.fontSize;
+            }
+        }
+        renderHyperlink(elem) {
+            var result = this.renderContainer(elem, "a");
+            this.renderStyleValues(elem.cssStyle, result);
+            if (elem.href) {
+                result.href = elem.href;
+            }
+            else if (elem.id) {
+                const rel = this.document.documentPart.rels
+                    .find(it => it.id == elem.id && it.targetMode === "External");
+                result.href = rel?.target;
+            }
+            return result;
+        }
+        renderSmartTag(elem) {
+            return this.renderContainer(elem, "span");
+        }
+        renderCommentRangeStart(commentStart) {
+            if (!this.options.renderComments)
+                return null;
+            const rng = new Range();
+            this.commentHighlight?.add(rng);
+            const result = this.htmlDocument.createComment(`start of comment #${commentStart.id}`);
+            this.later(() => rng.setStart(result, 0));
+            this.commentMap[commentStart.id] = rng;
+            return result;
+        }
+        renderCommentRangeEnd(commentEnd) {
+            if (!this.options.renderComments)
+                return null;
+            const rng = this.commentMap[commentEnd.id];
+            const result = this.htmlDocument.createComment(`end of comment #${commentEnd.id}`);
+            this.later(() => rng?.setEnd(result, 0));
+            return result;
+        }
+        renderCommentReference(commentRef) {
+            if (!this.options.renderComments)
+                return null;
+            var comment = this.document.commentsPart?.commentMap[commentRef.id];
+            if (!comment)
+                return null;
+            const frg = new DocumentFragment();
+            const commentRefEl = this.createElement("span", { className: `${this.className}-comment-ref` }, ['💬']);
+            const commentsContainerEl = this.createElement("div", { className: `${this.className}-comment-popover` });
+            this.renderCommentContent(comment, commentsContainerEl);
+            frg.appendChild(this.htmlDocument.createComment(`comment #${comment.id} by ${comment.author} on ${comment.date}`));
+            frg.appendChild(commentRefEl);
+            frg.appendChild(commentsContainerEl);
+            return frg;
+        }
+        renderCommentContent(comment, container) {
+            container.appendChild(this.createElement('div', { className: `${this.className}-comment-author` }, [comment.author]));
+            container.appendChild(this.createElement('div', { className: `${this.className}-comment-date` }, [new Date(comment.date).toLocaleString()]));
+            this.renderElements(comment.children, container);
+        }
+        renderDrawing(elem) {
+            var result = this.renderContainer(elem, "div");
+            result.style.display = "inline-block";
+            result.style.position = "relative";
+            result.style.textIndent = "0px";
+            this.renderStyleValues(elem.cssStyle, result);
+            return result;
+        }
+        renderImage(elem) {
+            let result = this.createElement("img");
+            this.renderStyleValues(elem.cssStyle, result);
+            if (this.document) {
+                this.tasks.push(this.document.loadDocumentImage(elem.src, this.currentPart).then(x => {
+                    result.src = x;
+                }));
+            }
+            return result;
+        }
+        renderText(elem) {
+            return this.htmlDocument.createTextNode(elem.text);
+        }
+        renderDeletedText(elem) {
+            return this.options.renderEndnotes ? this.htmlDocument.createTextNode(elem.text) : null;
+        }
+        renderBreak(elem) {
+            if (elem.break == "textWrapping") {
+                return this.createElement("br");
+            }
+            return null;
+        }
+        renderInserted(elem) {
+            if (this.options.renderChanges)
+                return this.renderContainer(elem, "ins");
+            return this.renderElements(elem.children);
+        }
+        renderDeleted(elem) {
+            if (this.options.renderChanges)
+                return this.renderContainer(elem, "del");
+            return null;
+        }
+        renderSymbol(elem) {
+            var span = this.createElement("span");
+            span.style.fontFamily = elem.font;
+            span.innerHTML = `&#x${elem.char};`;
+            return span;
+        }
+        renderFootnoteReference(elem) {
+            var result = this.createElement("sup");
+            this.currentFootnoteIds.push(elem.id);
+            result.textContent = `${this.currentFootnoteIds.length}`;
+            return result;
+        }
+        renderEndnoteReference(elem) {
+            var result = this.createElement("sup");
+            this.currentEndnoteIds.push(elem.id);
+            result.textContent = `${this.currentEndnoteIds.length}`;
+            return result;
+        }
+        renderTab(elem) {
+            var tabSpan = this.createElement("span");
+            tabSpan.innerHTML = "&emsp;";
+            if (this.options.experimental) {
+                tabSpan.className = this.tabStopClass();
+                var stops = findParent(elem, DomType.Paragraph)?.tabs;
+                this.currentTabs.push({ stops, span: tabSpan });
+            }
+            return tabSpan;
+        }
+        renderBookmarkStart(elem) {
+            return this.createElement("span", { id: elem.name });
+        }
+        renderRun(elem) {
+            if (elem.fieldRun)
+                return null;
+            const result = this.createElement("span");
+            if (elem.id)
+                result.id = elem.id;
+            this.renderClass(elem, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            if (elem.verticalAlign) {
+                const wrapper = this.createElement(elem.verticalAlign);
+                this.renderElements(elem.children, wrapper);
+                result.appendChild(wrapper);
+            }
+            else {
+                this.renderElements(elem.children, result);
+            }
+            return result;
+        }
+        renderTable(elem) {
+            let result = this.createElement("table");
+            this.tableCellPositions.push(this.currentCellPosition);
+            this.tableVerticalMerges.push(this.currentVerticalMerge);
+            this.currentVerticalMerge = {};
+            this.currentCellPosition = { col: 0, row: 0 };
+            if (elem.columns)
+                result.appendChild(this.renderTableColumns(elem.columns));
+            this.renderClass(elem, result);
+            this.renderElements(elem.children, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            this.currentVerticalMerge = this.tableVerticalMerges.pop();
+            this.currentCellPosition = this.tableCellPositions.pop();
+            return result;
+        }
+        renderTableColumns(columns) {
+            let result = this.createElement("colgroup");
+            for (let col of columns) {
+                let colElem = this.createElement("col");
+                if (col.width)
+                    colElem.style.width = col.width;
+                result.appendChild(colElem);
+            }
+            return result;
+        }
+        renderTableRow(elem) {
+            let result = this.renderContainer(elem, "tr");
+            this.currentCellPosition.col = 0;
+            this.renderClass(elem, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            this.currentCellPosition.row++;
+            return result;
+        }
+        renderTableCell(elem) {
+            let result = this.renderContainer(elem, "td");
+            const key = this.currentCellPosition.col;
+            if (elem.verticalMerge) {
+                if (elem.verticalMerge == "restart") {
+                    this.currentVerticalMerge[key] = result;
+                    result.rowSpan = 1;
+                }
+                else if (this.currentVerticalMerge[key]) {
+                    this.currentVerticalMerge[key].rowSpan += 1;
+                    result.style.display = "none";
+                }
+            }
+            else {
+                this.currentVerticalMerge[key] = null;
+            }
+            this.renderClass(elem, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            if (elem.span)
+                result.colSpan = elem.span;
+            this.currentCellPosition.col += result.colSpan;
+            return result;
+        }
+        renderVmlPicture(elem) {
+            return this.renderContainer(elem, "div");
+        }
+        renderVmlElement(elem) {
+            var container = this.createSvgElement("svg");
+            container.setAttribute("style", elem.cssStyleText);
+            const result = this.renderVmlChildElement(elem);
+            if (elem.imageHref?.id) {
+                this.tasks.push(this.document?.loadDocumentImage(elem.imageHref.id, this.currentPart)
+                    .then(x => result.setAttribute("href", x)));
+            }
+            container.appendChild(result);
+            requestAnimationFrame(() => {
+                const bb = container.firstElementChild.getBBox();
+                container.setAttribute("width", `${Math.ceil(bb.x + bb.width)}`);
+                container.setAttribute("height", `${Math.ceil(bb.y + bb.height)}`);
+            });
+            return container;
+        }
+        renderVmlChildElement(elem) {
+            const result = this.createSvgElement(elem.tagName);
+            Object.entries(elem.attrs).forEach(([k, v]) => result.setAttribute(k, v));
+            for (let child of elem.children) {
+                if (child.type == DomType.VmlElement) {
+                    result.appendChild(this.renderVmlChildElement(child));
+                }
+                else {
+                    result.appendChild(...asArray(this.renderElement(child)));
+                }
+            }
+            return result;
+        }
+        renderMmlRadical(elem) {
+            const base = elem.children.find(el => el.type == DomType.MmlBase);
+            if (elem.props?.hideDegree) {
+                return this.createElementNS(ns.mathML, "msqrt", null, this.renderElements([base]));
+            }
+            const degree = elem.children.find(el => el.type == DomType.MmlDegree);
+            return this.createElementNS(ns.mathML, "mroot", null, this.renderElements([base, degree]));
+        }
+        renderMmlDelimiter(elem) {
+            const children = [];
+            children.push(this.createElementNS(ns.mathML, "mo", null, [elem.props.beginChar ?? '(']));
+            children.push(...this.renderElements(elem.children));
+            children.push(this.createElementNS(ns.mathML, "mo", null, [elem.props.endChar ?? ')']));
+            return this.createElementNS(ns.mathML, "mrow", null, children);
+        }
+        renderMmlNary(elem) {
+            const children = [];
+            const grouped = keyBy(elem.children, x => x.type);
+            const sup = grouped[DomType.MmlSuperArgument];
+            const sub = grouped[DomType.MmlSubArgument];
+            const supElem = sup ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sup))) : null;
+            const subElem = sub ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sub))) : null;
+            const charElem = this.createElementNS(ns.mathML, "mo", null, [elem.props?.char ?? '\u222B']);
+            if (supElem || subElem) {
+                children.push(this.createElementNS(ns.mathML, "munderover", null, [charElem, subElem, supElem]));
+            }
+            else if (supElem) {
+                children.push(this.createElementNS(ns.mathML, "mover", null, [charElem, supElem]));
+            }
+            else if (subElem) {
+                children.push(this.createElementNS(ns.mathML, "munder", null, [charElem, subElem]));
+            }
+            else {
+                children.push(charElem);
+            }
+            children.push(...this.renderElements(grouped[DomType.MmlBase].children));
+            return this.createElementNS(ns.mathML, "mrow", null, children);
+        }
+        renderMmlPreSubSuper(elem) {
+            const children = [];
+            const grouped = keyBy(elem.children, x => x.type);
+            const sup = grouped[DomType.MmlSuperArgument];
+            const sub = grouped[DomType.MmlSubArgument];
+            const supElem = sup ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sup))) : null;
+            const subElem = sub ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sub))) : null;
+            const stubElem = this.createElementNS(ns.mathML, "mo", null);
+            children.push(this.createElementNS(ns.mathML, "msubsup", null, [stubElem, subElem, supElem]));
+            children.push(...this.renderElements(grouped[DomType.MmlBase].children));
+            return this.createElementNS(ns.mathML, "mrow", null, children);
+        }
+        renderMmlGroupChar(elem) {
+            const tagName = elem.props.verticalJustification === "bot" ? "mover" : "munder";
+            const result = this.renderContainerNS(elem, ns.mathML, tagName);
+            if (elem.props.char) {
+                result.appendChild(this.createElementNS(ns.mathML, "mo", null, [elem.props.char]));
+            }
+            return result;
+        }
+        renderMmlBar(elem) {
+            const result = this.renderContainerNS(elem, ns.mathML, "mrow");
+            switch (elem.props.position) {
+                case "top":
+                    result.style.textDecoration = "overline";
+                    break;
+                case "bottom":
+                    result.style.textDecoration = "underline";
+                    break;
+            }
+            return result;
+        }
+        renderMmlRun(elem) {
+            const result = this.createElementNS(ns.mathML, "ms", null, this.renderElements(elem.children));
+            this.renderClass(elem, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            return result;
+        }
+        renderMllList(elem) {
+            const result = this.createElementNS(ns.mathML, "mtable");
+            this.renderClass(elem, result);
+            this.renderStyleValues(elem.cssStyle, result);
+            for (let child of this.renderElements(elem.children)) {
+                result.appendChild(this.createElementNS(ns.mathML, "mtr", null, [
+                    this.createElementNS(ns.mathML, "mtd", null, [child])
+                ]));
+            }
+            return result;
+        }
+        renderStyleValues(style, ouput) {
+            for (let k in style) {
+                if (k.startsWith("$")) {
+                    ouput.setAttribute(k.slice(1), style[k]);
+                }
+                else {
+                    ouput.style[k] = style[k];
+                }
+            }
+        }
+        renderClass(input, ouput) {
+            if (input.className)
+                ouput.className = input.className;
+            if (input.styleName)
+                ouput.classList.add(this.processStyleName(input.styleName));
+        }
+        findStyle(styleName) {
+            return styleName && this.styleMap?.[styleName];
+        }
+        numberingClass(id, lvl) {
+            return `${this.className}-num-${id}-${lvl}`;
+        }
+        tabStopClass() {
+            return `${this.className}-tab-stop`;
+        }
+        styleToString(selectors, values, cssText = null) {
+            let result = `${selectors} {\r\n`;
+            for (const key in values) {
+                if (key.startsWith('$'))
+                    continue;
+                result += `  ${key}: ${values[key]};\r\n`;
+            }
+            if (cssText)
+                result += cssText;
+            return result + "}\r\n";
+        }
+        numberingCounter(id, lvl) {
+            return `${this.className}-num-${id}-${lvl}`;
+        }
+        levelTextToContent(text, suff, id, numformat) {
+            const suffMap = {
+                "tab": "\\9",
+                "space": "\\a0",
+            };
+            var result = text.replace(/%\d*/g, s => {
+                let lvl = parseInt(s.substring(1), 10) - 1;
+                return `"counter(${this.numberingCounter(id, lvl)}, ${numformat})"`;
+            });
+            return `"${result}${suffMap[suff] ?? ""}"`;
+        }
+        numFormatToCssValue(format) {
+            var mapping = {
+                none: "none",
+                bullet: "disc",
+                decimal: "decimal",
+                lowerLetter: "lower-alpha",
+                upperLetter: "upper-alpha",
+                lowerRoman: "lower-roman",
+                upperRoman: "upper-roman",
+                decimalZero: "decimal-leading-zero",
+                aiueo: "katakana",
+                aiueoFullWidth: "katakana",
+                chineseCounting: "simp-chinese-informal",
+                chineseCountingThousand: "simp-chinese-informal",
+                chineseLegalSimplified: "simp-chinese-formal",
+                chosung: "hangul-consonant",
+                ideographDigital: "cjk-ideographic",
+                ideographTraditional: "cjk-heavenly-stem",
+                ideographLegalTraditional: "trad-chinese-formal",
+                ideographZodiac: "cjk-earthly-branch",
+                iroha: "katakana-iroha",
+                irohaFullWidth: "katakana-iroha",
+                japaneseCounting: "japanese-informal",
+                japaneseDigitalTenThousand: "cjk-decimal",
+                japaneseLegal: "japanese-formal",
+                thaiNumbers: "thai",
+                koreanCounting: "korean-hangul-formal",
+                koreanDigital: "korean-hangul-formal",
+                koreanDigital2: "korean-hanja-informal",
+                hebrew1: "hebrew",
+                hebrew2: "hebrew",
+                hindiNumbers: "devanagari",
+                ganada: "hangul",
+                taiwaneseCounting: "cjk-ideographic",
+                taiwaneseCountingThousand: "cjk-ideographic",
+                taiwaneseDigital: "cjk-decimal",
+            };
+            return mapping[format] ?? format;
+        }
+        refreshTabStops() {
+            if (!this.options.experimental)
+                return;
+            setTimeout(() => {
+                const pixelToPoint = computePixelToPoint();
+                for (let tab of this.currentTabs) {
+                    updateTabStop(tab.span, tab.stops, this.defaultTabSize, pixelToPoint);
+                }
+            }, 500);
+        }
+        createElementNS(ns, tagName, props, children) {
+            var result = ns ? this.htmlDocument.createElementNS(ns, tagName) : this.htmlDocument.createElement(tagName);
+            Object.assign(result, props);
+            children && appendChildren(result, children);
+            return result;
+        }
+        createElement(tagName, props, children) {
+            return this.createElementNS(undefined, tagName, props, children);
+        }
+        createSvgElement(tagName, props, children) {
+            return this.createElementNS(ns.svg, tagName, props, children);
+        }
+        createStyleElement(cssText) {
+            return this.createElement("style", { innerHTML: cssText });
+        }
+        createComment(text) {
+            return this.htmlDocument.createComment(text);
+        }
+        later(func) {
+            this.postRenderTasks.push(func);
+        }
+    }
+    function removeAllElements(elem) {
+        elem.innerHTML = '';
+    }
+    function appendChildren(elem, children) {
+        children.forEach(c => elem.appendChild(isString(c) ? document.createTextNode(c) : c));
+    }
+    function findParent(elem, type) {
+        var parent = elem.parent;
+        while (parent != null && parent.type != type)
+            parent = parent.parent;
+        return parent;
+    }
+
+    const defaultOptions = {
+        ignoreHeight: false,
+        ignoreWidth: false,
+        ignoreFonts: false,
+        breakPages: true,
+        debug: false,
+        experimental: false,
+        className: "docx",
+        inWrapper: true,
+        trimXmlDeclaration: true,
+        ignoreLastRenderedPageBreak: true,
+        renderHeaders: true,
+        renderFooters: true,
+        renderFootnotes: true,
+        renderEndnotes: true,
+        useBase64URL: false,
+        renderChanges: false,
+        renderComments: false
+    };
+    function parseAsync(data, userOptions) {
+        const ops = { ...defaultOptions, ...userOptions };
+        return WordDocument.load(data, new DocumentParser(ops), ops);
+    }
+    async function renderDocument(document, bodyContainer, styleContainer, userOptions) {
+        const ops = { ...defaultOptions, ...userOptions };
+        const renderer = new HtmlRenderer(window.document);
+        return await renderer.render(document, bodyContainer, styleContainer, ops);
+    }
+    async function renderAsync(data, bodyContainer, styleContainer, userOptions) {
+        const doc = await parseAsync(data, userOptions);
+        await renderDocument(doc, bodyContainer, styleContainer, userOptions);
+        return doc;
+    }
+
+    exports.defaultOptions = defaultOptions;
+    exports.parseAsync = parseAsync;
+    exports.renderAsync = renderAsync;
+    exports.renderDocument = renderDocument;
+
+}));
+//# sourceMappingURL=docx-preview.js.map

File diff suppressed because it is too large
+ 0 - 0
src/3rd-libs/docx-preview/docx-preview.js.map


File diff suppressed because it is too large
+ 0 - 0
src/3rd-libs/docx-preview/docx-preview.min.js


File diff suppressed because it is too large
+ 0 - 0
src/3rd-libs/docx-preview/docx-preview.min.js.map


File diff suppressed because it is too large
+ 0 - 0
src/3rd-libs/docx-preview/docx-preview.min.mjs


File diff suppressed because it is too large
+ 0 - 0
src/3rd-libs/docx-preview/docx-preview.min.mjs.map


+ 3894 - 0
src/3rd-libs/docx-preview/docx-preview.mjs

@@ -0,0 +1,3894 @@
+import JSZip from 'jszip';
+
+var RelationshipTypes;
+(function (RelationshipTypes) {
+    RelationshipTypes["OfficeDocument"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument";
+    RelationshipTypes["FontTable"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable";
+    RelationshipTypes["Image"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image";
+    RelationshipTypes["Numbering"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering";
+    RelationshipTypes["Styles"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles";
+    RelationshipTypes["StylesWithEffects"] = "http://schemas.microsoft.com/office/2007/relationships/stylesWithEffects";
+    RelationshipTypes["Theme"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme";
+    RelationshipTypes["Settings"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings";
+    RelationshipTypes["WebSettings"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/webSettings";
+    RelationshipTypes["Hyperlink"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink";
+    RelationshipTypes["Footnotes"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes";
+    RelationshipTypes["Endnotes"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes";
+    RelationshipTypes["Footer"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer";
+    RelationshipTypes["Header"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header";
+    RelationshipTypes["ExtendedProperties"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
+    RelationshipTypes["CoreProperties"] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+    RelationshipTypes["CustomProperties"] = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/custom-properties";
+    RelationshipTypes["Comments"] = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments";
+    RelationshipTypes["CommentsExtended"] = "http://schemas.microsoft.com/office/2011/relationships/commentsExtended";
+})(RelationshipTypes || (RelationshipTypes = {}));
+function parseRelationships(root, xml) {
+    return xml.elements(root).map(e => ({
+        id: xml.attr(e, "Id"),
+        type: xml.attr(e, "Type"),
+        target: xml.attr(e, "Target"),
+        targetMode: xml.attr(e, "TargetMode")
+    }));
+}
+
+const ns$1 = {
+    wordml: "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+    drawingml: "http://schemas.openxmlformats.org/drawingml/2006/main",
+    picture: "http://schemas.openxmlformats.org/drawingml/2006/picture",
+    compatibility: "http://schemas.openxmlformats.org/markup-compatibility/2006",
+    math: "http://schemas.openxmlformats.org/officeDocument/2006/math"
+};
+const LengthUsage = {
+    Dxa: { mul: 0.05, unit: "pt" },
+    Emu: { mul: 1 / 12700, unit: "pt" },
+    FontSize: { mul: 0.5, unit: "pt" },
+    Border: { mul: 0.125, unit: "pt" },
+    Point: { mul: 1, unit: "pt" },
+    Percent: { mul: 0.02, unit: "%" },
+    LineHeight: { mul: 1 / 240, unit: "" },
+    VmlEmu: { mul: 1 / 12700, unit: "" },
+};
+function convertLength(val, usage = LengthUsage.Dxa) {
+    if (val == null || /.+(p[xt]|[%])$/.test(val)) {
+        return val;
+    }
+    return `${(parseInt(val) * usage.mul).toFixed(2)}${usage.unit}`;
+}
+function convertBoolean(v, defaultValue = false) {
+    switch (v) {
+        case "1": return true;
+        case "0": return false;
+        case "on": return true;
+        case "off": return false;
+        case "true": return true;
+        case "false": return false;
+        default: return defaultValue;
+    }
+}
+function parseCommonProperty(elem, props, xml) {
+    if (elem.namespaceURI != ns$1.wordml)
+        return false;
+    switch (elem.localName) {
+        case "color":
+            props.color = xml.attr(elem, "val");
+            break;
+        case "sz":
+            props.fontSize = xml.lengthAttr(elem, "val", LengthUsage.FontSize);
+            break;
+        default:
+            return false;
+    }
+    return true;
+}
+
+function parseXmlString(xmlString, trimXmlDeclaration = false) {
+    if (trimXmlDeclaration)
+        xmlString = xmlString.replace(/<[?].*[?]>/, "");
+    xmlString = removeUTF8BOM(xmlString);
+    const result = new DOMParser().parseFromString(xmlString, "application/xml");
+    const errorText = hasXmlParserError(result);
+    if (errorText)
+        throw new Error(errorText);
+    return result;
+}
+function hasXmlParserError(doc) {
+    return doc.getElementsByTagName("parsererror")[0]?.textContent;
+}
+function removeUTF8BOM(data) {
+    return data.charCodeAt(0) === 0xFEFF ? data.substring(1) : data;
+}
+function serializeXmlString(elem) {
+    return new XMLSerializer().serializeToString(elem);
+}
+class XmlParser {
+    elements(elem, localName = null) {
+        const result = [];
+        for (let i = 0, l = elem.childNodes.length; i < l; i++) {
+            let c = elem.childNodes.item(i);
+            if (c.nodeType == 1 && (localName == null || c.localName == localName))
+                result.push(c);
+        }
+        return result;
+    }
+    element(elem, localName) {
+        for (let i = 0, l = elem.childNodes.length; i < l; i++) {
+            let c = elem.childNodes.item(i);
+            if (c.nodeType == 1 && c.localName == localName)
+                return c;
+        }
+        return null;
+    }
+    elementAttr(elem, localName, attrLocalName) {
+        var el = this.element(elem, localName);
+        return el ? this.attr(el, attrLocalName) : undefined;
+    }
+    attrs(elem) {
+        return Array.from(elem.attributes);
+    }
+    attr(elem, localName) {
+        for (let i = 0, l = elem.attributes.length; i < l; i++) {
+            let a = elem.attributes.item(i);
+            if (a.localName == localName)
+                return a.value;
+        }
+        return null;
+    }
+    intAttr(node, attrName, defaultValue = null) {
+        var val = this.attr(node, attrName);
+        return val ? parseInt(val) : defaultValue;
+    }
+    hexAttr(node, attrName, defaultValue = null) {
+        var val = this.attr(node, attrName);
+        return val ? parseInt(val, 16) : defaultValue;
+    }
+    floatAttr(node, attrName, defaultValue = null) {
+        var val = this.attr(node, attrName);
+        return val ? parseFloat(val) : defaultValue;
+    }
+    boolAttr(node, attrName, defaultValue = null) {
+        return convertBoolean(this.attr(node, attrName), defaultValue);
+    }
+    lengthAttr(node, attrName, usage = LengthUsage.Dxa) {
+        return convertLength(this.attr(node, attrName), usage);
+    }
+}
+const globalXmlParser = new XmlParser();
+
+class Part {
+    constructor(_package, path) {
+        this._package = _package;
+        this.path = path;
+    }
+    async load() {
+        this.rels = await this._package.loadRelationships(this.path);
+        const xmlText = await this._package.load(this.path);
+        const xmlDoc = this._package.parseXmlDocument(xmlText);
+        if (this._package.options.keepOrigin) {
+            this._xmlDocument = xmlDoc;
+        }
+        this.parseXml(xmlDoc.firstElementChild);
+    }
+    save() {
+        this._package.update(this.path, serializeXmlString(this._xmlDocument));
+    }
+    parseXml(root) {
+    }
+}
+
+const embedFontTypeMap = {
+    embedRegular: 'regular',
+    embedBold: 'bold',
+    embedItalic: 'italic',
+    embedBoldItalic: 'boldItalic',
+};
+function parseFonts(root, xml) {
+    return xml.elements(root).map(el => parseFont(el, xml));
+}
+function parseFont(elem, xml) {
+    let result = {
+        name: xml.attr(elem, "name"),
+        embedFontRefs: []
+    };
+    for (let el of xml.elements(elem)) {
+        switch (el.localName) {
+            case "family":
+                result.family = xml.attr(el, "val");
+                break;
+            case "altName":
+                result.altName = xml.attr(el, "val");
+                break;
+            case "embedRegular":
+            case "embedBold":
+            case "embedItalic":
+            case "embedBoldItalic":
+                result.embedFontRefs.push(parseEmbedFontRef(el, xml));
+                break;
+        }
+    }
+    return result;
+}
+function parseEmbedFontRef(elem, xml) {
+    return {
+        id: xml.attr(elem, "id"),
+        key: xml.attr(elem, "fontKey"),
+        type: embedFontTypeMap[elem.localName]
+    };
+}
+
+class FontTablePart extends Part {
+    parseXml(root) {
+        this.fonts = parseFonts(root, this._package.xmlParser);
+    }
+}
+
+function escapeClassName(className) {
+    return className?.replace(/[ .]+/g, '-').replace(/[&]+/g, 'and').toLowerCase();
+}
+function encloseFontFamily(fontFamily) {
+    return /^[^"'].*\s.*[^"']$/.test(fontFamily) ? `'${fontFamily}'` : fontFamily;
+}
+function splitPath(path) {
+    let si = path.lastIndexOf('/') + 1;
+    let folder = si == 0 ? "" : path.substring(0, si);
+    let fileName = si == 0 ? path : path.substring(si);
+    return [folder, fileName];
+}
+function resolvePath(path, base) {
+    try {
+        const prefix = "http://docx/";
+        const url = new URL(path, prefix + base).toString();
+        return url.substring(prefix.length);
+    }
+    catch {
+        return `${base}${path}`;
+    }
+}
+function keyBy(array, by) {
+    return array.reduce((a, x) => {
+        a[by(x)] = x;
+        return a;
+    }, {});
+}
+function blobToBase64(blob) {
+    return new Promise((resolve, reject) => {
+        const reader = new FileReader();
+        reader.onloadend = () => resolve(reader.result);
+        reader.onerror = () => reject();
+        reader.readAsDataURL(blob);
+    });
+}
+function isObject(item) {
+    return item && typeof item === 'object' && !Array.isArray(item);
+}
+function isString(item) {
+    return typeof item === 'string' || item instanceof String;
+}
+function mergeDeep(target, ...sources) {
+    if (!sources.length)
+        return target;
+    const source = sources.shift();
+    if (isObject(target) && isObject(source)) {
+        for (const key in source) {
+            if (isObject(source[key])) {
+                const val = target[key] ?? (target[key] = {});
+                mergeDeep(val, source[key]);
+            }
+            else {
+                target[key] = source[key];
+            }
+        }
+    }
+    return mergeDeep(target, ...sources);
+}
+function asArray(val) {
+    return Array.isArray(val) ? val : [val];
+}
+
+class OpenXmlPackage {
+    constructor(_zip, options) {
+        this._zip = _zip;
+        this.options = options;
+        this.xmlParser = new XmlParser();
+    }
+    get(path) {
+        const p = normalizePath(path);
+        return this._zip.files[p] ?? this._zip.files[p.replace(/\//g, '\\')];
+    }
+    update(path, content) {
+        this._zip.file(path, content);
+    }
+    static async load(input, options) {
+        const zip = await JSZip.loadAsync(input);
+        return new OpenXmlPackage(zip, options);
+    }
+    save(type = "blob") {
+        return this._zip.generateAsync({ type });
+    }
+    load(path, type = "string") {
+        return this.get(path)?.async(type) ?? Promise.resolve(null);
+    }
+    async loadRelationships(path = null) {
+        let relsPath = `_rels/.rels`;
+        if (path != null) {
+            const [f, fn] = splitPath(path);
+            relsPath = `${f}_rels/${fn}.rels`;
+        }
+        const txt = await this.load(relsPath);
+        return txt ? parseRelationships(this.parseXmlDocument(txt).firstElementChild, this.xmlParser) : null;
+    }
+    parseXmlDocument(txt) {
+        return parseXmlString(txt, this.options.trimXmlDeclaration);
+    }
+}
+function normalizePath(path) {
+    return path.startsWith('/') ? path.substr(1) : path;
+}
+
+class DocumentPart extends Part {
+    constructor(pkg, path, parser) {
+        super(pkg, path);
+        this._documentParser = parser;
+    }
+    parseXml(root) {
+        this.body = this._documentParser.parseDocumentFile(root);
+    }
+}
+
+function parseBorder(elem, xml) {
+    return {
+        type: xml.attr(elem, "val"),
+        color: xml.attr(elem, "color"),
+        size: xml.lengthAttr(elem, "sz", LengthUsage.Border),
+        offset: xml.lengthAttr(elem, "space", LengthUsage.Point),
+        frame: xml.boolAttr(elem, 'frame'),
+        shadow: xml.boolAttr(elem, 'shadow')
+    };
+}
+function parseBorders(elem, xml) {
+    var result = {};
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "left":
+                result.left = parseBorder(e, xml);
+                break;
+            case "top":
+                result.top = parseBorder(e, xml);
+                break;
+            case "right":
+                result.right = parseBorder(e, xml);
+                break;
+            case "bottom":
+                result.bottom = parseBorder(e, xml);
+                break;
+        }
+    }
+    return result;
+}
+
+var SectionType;
+(function (SectionType) {
+    SectionType["Continuous"] = "continuous";
+    SectionType["NextPage"] = "nextPage";
+    SectionType["NextColumn"] = "nextColumn";
+    SectionType["EvenPage"] = "evenPage";
+    SectionType["OddPage"] = "oddPage";
+})(SectionType || (SectionType = {}));
+function parseSectionProperties(elem, xml = globalXmlParser) {
+    var section = {};
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "pgSz":
+                section.pageSize = {
+                    width: xml.lengthAttr(e, "w"),
+                    height: xml.lengthAttr(e, "h"),
+                    orientation: xml.attr(e, "orient")
+                };
+                break;
+            case "type":
+                section.type = xml.attr(e, "val");
+                break;
+            case "pgMar":
+                section.pageMargins = {
+                    left: xml.lengthAttr(e, "left"),
+                    right: xml.lengthAttr(e, "right"),
+                    top: xml.lengthAttr(e, "top"),
+                    bottom: xml.lengthAttr(e, "bottom"),
+                    header: xml.lengthAttr(e, "header"),
+                    footer: xml.lengthAttr(e, "footer"),
+                    gutter: xml.lengthAttr(e, "gutter"),
+                };
+                break;
+            case "cols":
+                section.columns = parseColumns(e, xml);
+                break;
+            case "headerReference":
+                (section.headerRefs ?? (section.headerRefs = [])).push(parseFooterHeaderReference(e, xml));
+                break;
+            case "footerReference":
+                (section.footerRefs ?? (section.footerRefs = [])).push(parseFooterHeaderReference(e, xml));
+                break;
+            case "titlePg":
+                section.titlePage = xml.boolAttr(e, "val", true);
+                break;
+            case "pgBorders":
+                section.pageBorders = parseBorders(e, xml);
+                break;
+            case "pgNumType":
+                section.pageNumber = parsePageNumber(e, xml);
+                break;
+        }
+    }
+    return section;
+}
+function parseColumns(elem, xml) {
+    return {
+        numberOfColumns: xml.intAttr(elem, "num"),
+        space: xml.lengthAttr(elem, "space"),
+        separator: xml.boolAttr(elem, "sep"),
+        equalWidth: xml.boolAttr(elem, "equalWidth", true),
+        columns: xml.elements(elem, "col")
+            .map(e => ({
+            width: xml.lengthAttr(e, "w"),
+            space: xml.lengthAttr(e, "space")
+        }))
+    };
+}
+function parsePageNumber(elem, xml) {
+    return {
+        chapSep: xml.attr(elem, "chapSep"),
+        chapStyle: xml.attr(elem, "chapStyle"),
+        format: xml.attr(elem, "fmt"),
+        start: xml.intAttr(elem, "start")
+    };
+}
+function parseFooterHeaderReference(elem, xml) {
+    return {
+        id: xml.attr(elem, "id"),
+        type: xml.attr(elem, "type"),
+    };
+}
+
+function parseLineSpacing(elem, xml) {
+    return {
+        before: xml.lengthAttr(elem, "before"),
+        after: xml.lengthAttr(elem, "after"),
+        line: xml.intAttr(elem, "line"),
+        lineRule: xml.attr(elem, "lineRule")
+    };
+}
+
+function parseRunProperties(elem, xml) {
+    let result = {};
+    for (let el of xml.elements(elem)) {
+        parseRunProperty(el, result, xml);
+    }
+    return result;
+}
+function parseRunProperty(elem, props, xml) {
+    if (parseCommonProperty(elem, props, xml))
+        return true;
+    return false;
+}
+
+function parseParagraphProperties(elem, xml) {
+    let result = {};
+    for (let el of xml.elements(elem)) {
+        parseParagraphProperty(el, result, xml);
+    }
+    return result;
+}
+function parseParagraphProperty(elem, props, xml) {
+    if (elem.namespaceURI != ns$1.wordml)
+        return false;
+    if (parseCommonProperty(elem, props, xml))
+        return true;
+    switch (elem.localName) {
+        case "tabs":
+            props.tabs = parseTabs(elem, xml);
+            break;
+        case "sectPr":
+            props.sectionProps = parseSectionProperties(elem, xml);
+            break;
+        case "numPr":
+            props.numbering = parseNumbering$1(elem, xml);
+            break;
+        case "spacing":
+            props.lineSpacing = parseLineSpacing(elem, xml);
+            return false;
+        case "textAlignment":
+            props.textAlignment = xml.attr(elem, "val");
+            return false;
+        case "keepLines":
+            props.keepLines = xml.boolAttr(elem, "val", true);
+            break;
+        case "keepNext":
+            props.keepNext = xml.boolAttr(elem, "val", true);
+            break;
+        case "pageBreakBefore":
+            props.pageBreakBefore = xml.boolAttr(elem, "val", true);
+            break;
+        case "outlineLvl":
+            props.outlineLevel = xml.intAttr(elem, "val");
+            break;
+        case "pStyle":
+            props.styleName = xml.attr(elem, "val");
+            break;
+        case "rPr":
+            props.runProps = parseRunProperties(elem, xml);
+            break;
+        default:
+            return false;
+    }
+    return true;
+}
+function parseTabs(elem, xml) {
+    return xml.elements(elem, "tab")
+        .map(e => ({
+        position: xml.lengthAttr(e, "pos"),
+        leader: xml.attr(e, "leader"),
+        style: xml.attr(e, "val")
+    }));
+}
+function parseNumbering$1(elem, xml) {
+    var result = {};
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "numId":
+                result.id = xml.attr(e, "val");
+                break;
+            case "ilvl":
+                result.level = xml.intAttr(e, "val");
+                break;
+        }
+    }
+    return result;
+}
+
+function parseNumberingPart(elem, xml) {
+    let result = {
+        numberings: [],
+        abstractNumberings: [],
+        bulletPictures: []
+    };
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "num":
+                result.numberings.push(parseNumbering(e, xml));
+                break;
+            case "abstractNum":
+                result.abstractNumberings.push(parseAbstractNumbering(e, xml));
+                break;
+            case "numPicBullet":
+                result.bulletPictures.push(parseNumberingBulletPicture(e, xml));
+                break;
+        }
+    }
+    return result;
+}
+function parseNumbering(elem, xml) {
+    let result = {
+        id: xml.attr(elem, 'numId'),
+        overrides: []
+    };
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "abstractNumId":
+                result.abstractId = xml.attr(e, "val");
+                break;
+            case "lvlOverride":
+                result.overrides.push(parseNumberingLevelOverrride(e, xml));
+                break;
+        }
+    }
+    return result;
+}
+function parseAbstractNumbering(elem, xml) {
+    let result = {
+        id: xml.attr(elem, 'abstractNumId'),
+        levels: []
+    };
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "name":
+                result.name = xml.attr(e, "val");
+                break;
+            case "multiLevelType":
+                result.multiLevelType = xml.attr(e, "val");
+                break;
+            case "numStyleLink":
+                result.numberingStyleLink = xml.attr(e, "val");
+                break;
+            case "styleLink":
+                result.styleLink = xml.attr(e, "val");
+                break;
+            case "lvl":
+                result.levels.push(parseNumberingLevel(e, xml));
+                break;
+        }
+    }
+    return result;
+}
+function parseNumberingLevel(elem, xml) {
+    let result = {
+        level: xml.intAttr(elem, 'ilvl')
+    };
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "start":
+                result.start = xml.attr(e, "val");
+                break;
+            case "lvlRestart":
+                result.restart = xml.intAttr(e, "val");
+                break;
+            case "numFmt":
+                result.format = xml.attr(e, "val");
+                break;
+            case "lvlText":
+                result.text = xml.attr(e, "val");
+                break;
+            case "lvlJc":
+                result.justification = xml.attr(e, "val");
+                break;
+            case "lvlPicBulletId":
+                result.bulletPictureId = xml.attr(e, "val");
+                break;
+            case "pStyle":
+                result.paragraphStyle = xml.attr(e, "val");
+                break;
+            case "pPr":
+                result.paragraphProps = parseParagraphProperties(e, xml);
+                break;
+            case "rPr":
+                result.runProps = parseRunProperties(e, xml);
+                break;
+        }
+    }
+    return result;
+}
+function parseNumberingLevelOverrride(elem, xml) {
+    let result = {
+        level: xml.intAttr(elem, 'ilvl')
+    };
+    for (let e of xml.elements(elem)) {
+        switch (e.localName) {
+            case "startOverride":
+                result.start = xml.intAttr(e, "val");
+                break;
+            case "lvl":
+                result.numberingLevel = parseNumberingLevel(e, xml);
+                break;
+        }
+    }
+    return result;
+}
+function parseNumberingBulletPicture(elem, xml) {
+    var pict = xml.element(elem, "pict");
+    var shape = pict && xml.element(pict, "shape");
+    var imagedata = shape && xml.element(shape, "imagedata");
+    return imagedata ? {
+        id: xml.attr(elem, "numPicBulletId"),
+        referenceId: xml.attr(imagedata, "id"),
+        style: xml.attr(shape, "style")
+    } : null;
+}
+
+class NumberingPart extends Part {
+    constructor(pkg, path, parser) {
+        super(pkg, path);
+        this._documentParser = parser;
+    }
+    parseXml(root) {
+        Object.assign(this, parseNumberingPart(root, this._package.xmlParser));
+        this.domNumberings = this._documentParser.parseNumberingFile(root);
+    }
+}
+
+class StylesPart extends Part {
+    constructor(pkg, path, parser) {
+        super(pkg, path);
+        this._documentParser = parser;
+    }
+    parseXml(root) {
+        this.styles = this._documentParser.parseStylesFile(root);
+    }
+}
+
+var DomType;
+(function (DomType) {
+    DomType["Document"] = "document";
+    DomType["Paragraph"] = "paragraph";
+    DomType["Run"] = "run";
+    DomType["Break"] = "break";
+    DomType["NoBreakHyphen"] = "noBreakHyphen";
+    DomType["Table"] = "table";
+    DomType["Row"] = "row";
+    DomType["Cell"] = "cell";
+    DomType["Hyperlink"] = "hyperlink";
+    DomType["SmartTag"] = "smartTag";
+    DomType["Drawing"] = "drawing";
+    DomType["Image"] = "image";
+    DomType["Text"] = "text";
+    DomType["Tab"] = "tab";
+    DomType["Symbol"] = "symbol";
+    DomType["BookmarkStart"] = "bookmarkStart";
+    DomType["BookmarkEnd"] = "bookmarkEnd";
+    DomType["Footer"] = "footer";
+    DomType["Header"] = "header";
+    DomType["FootnoteReference"] = "footnoteReference";
+    DomType["EndnoteReference"] = "endnoteReference";
+    DomType["Footnote"] = "footnote";
+    DomType["Endnote"] = "endnote";
+    DomType["SimpleField"] = "simpleField";
+    DomType["ComplexField"] = "complexField";
+    DomType["Instruction"] = "instruction";
+    DomType["VmlPicture"] = "vmlPicture";
+    DomType["MmlMath"] = "mmlMath";
+    DomType["MmlMathParagraph"] = "mmlMathParagraph";
+    DomType["MmlFraction"] = "mmlFraction";
+    DomType["MmlFunction"] = "mmlFunction";
+    DomType["MmlFunctionName"] = "mmlFunctionName";
+    DomType["MmlNumerator"] = "mmlNumerator";
+    DomType["MmlDenominator"] = "mmlDenominator";
+    DomType["MmlRadical"] = "mmlRadical";
+    DomType["MmlBase"] = "mmlBase";
+    DomType["MmlDegree"] = "mmlDegree";
+    DomType["MmlSuperscript"] = "mmlSuperscript";
+    DomType["MmlSubscript"] = "mmlSubscript";
+    DomType["MmlPreSubSuper"] = "mmlPreSubSuper";
+    DomType["MmlSubArgument"] = "mmlSubArgument";
+    DomType["MmlSuperArgument"] = "mmlSuperArgument";
+    DomType["MmlNary"] = "mmlNary";
+    DomType["MmlDelimiter"] = "mmlDelimiter";
+    DomType["MmlRun"] = "mmlRun";
+    DomType["MmlEquationArray"] = "mmlEquationArray";
+    DomType["MmlLimit"] = "mmlLimit";
+    DomType["MmlLimitLower"] = "mmlLimitLower";
+    DomType["MmlMatrix"] = "mmlMatrix";
+    DomType["MmlMatrixRow"] = "mmlMatrixRow";
+    DomType["MmlBox"] = "mmlBox";
+    DomType["MmlBar"] = "mmlBar";
+    DomType["MmlGroupChar"] = "mmlGroupChar";
+    DomType["VmlElement"] = "vmlElement";
+    DomType["Inserted"] = "inserted";
+    DomType["Deleted"] = "deleted";
+    DomType["DeletedText"] = "deletedText";
+    DomType["Comment"] = "comment";
+    DomType["CommentReference"] = "commentReference";
+    DomType["CommentRangeStart"] = "commentRangeStart";
+    DomType["CommentRangeEnd"] = "commentRangeEnd";
+})(DomType || (DomType = {}));
+class OpenXmlElementBase {
+    constructor() {
+        this.children = [];
+        this.cssStyle = {};
+    }
+}
+
+class WmlHeader extends OpenXmlElementBase {
+    constructor() {
+        super(...arguments);
+        this.type = DomType.Header;
+    }
+}
+class WmlFooter extends OpenXmlElementBase {
+    constructor() {
+        super(...arguments);
+        this.type = DomType.Footer;
+    }
+}
+
+class BaseHeaderFooterPart extends Part {
+    constructor(pkg, path, parser) {
+        super(pkg, path);
+        this._documentParser = parser;
+    }
+    parseXml(root) {
+        this.rootElement = this.createRootElement();
+        this.rootElement.children = this._documentParser.parseBodyElements(root);
+    }
+}
+class HeaderPart extends BaseHeaderFooterPart {
+    createRootElement() {
+        return new WmlHeader();
+    }
+}
+class FooterPart extends BaseHeaderFooterPart {
+    createRootElement() {
+        return new WmlFooter();
+    }
+}
+
+function parseExtendedProps(root, xmlParser) {
+    const result = {};
+    for (let el of xmlParser.elements(root)) {
+        switch (el.localName) {
+            case "Template":
+                result.template = el.textContent;
+                break;
+            case "Pages":
+                result.pages = safeParseToInt(el.textContent);
+                break;
+            case "Words":
+                result.words = safeParseToInt(el.textContent);
+                break;
+            case "Characters":
+                result.characters = safeParseToInt(el.textContent);
+                break;
+            case "Application":
+                result.application = el.textContent;
+                break;
+            case "Lines":
+                result.lines = safeParseToInt(el.textContent);
+                break;
+            case "Paragraphs":
+                result.paragraphs = safeParseToInt(el.textContent);
+                break;
+            case "Company":
+                result.company = el.textContent;
+                break;
+            case "AppVersion":
+                result.appVersion = el.textContent;
+                break;
+        }
+    }
+    return result;
+}
+function safeParseToInt(value) {
+    if (typeof value === 'undefined')
+        return;
+    return parseInt(value);
+}
+
+class ExtendedPropsPart extends Part {
+    parseXml(root) {
+        this.props = parseExtendedProps(root, this._package.xmlParser);
+    }
+}
+
+function parseCoreProps(root, xmlParser) {
+    const result = {};
+    for (let el of xmlParser.elements(root)) {
+        switch (el.localName) {
+            case "title":
+                result.title = el.textContent;
+                break;
+            case "description":
+                result.description = el.textContent;
+                break;
+            case "subject":
+                result.subject = el.textContent;
+                break;
+            case "creator":
+                result.creator = el.textContent;
+                break;
+            case "keywords":
+                result.keywords = el.textContent;
+                break;
+            case "language":
+                result.language = el.textContent;
+                break;
+            case "lastModifiedBy":
+                result.lastModifiedBy = el.textContent;
+                break;
+            case "revision":
+                el.textContent && (result.revision = parseInt(el.textContent));
+                break;
+        }
+    }
+    return result;
+}
+
+class CorePropsPart extends Part {
+    parseXml(root) {
+        this.props = parseCoreProps(root, this._package.xmlParser);
+    }
+}
+
+class DmlTheme {
+}
+function parseTheme(elem, xml) {
+    var result = new DmlTheme();
+    var themeElements = xml.element(elem, "themeElements");
+    for (let el of xml.elements(themeElements)) {
+        switch (el.localName) {
+            case "clrScheme":
+                result.colorScheme = parseColorScheme(el, xml);
+                break;
+            case "fontScheme":
+                result.fontScheme = parseFontScheme(el, xml);
+                break;
+        }
+    }
+    return result;
+}
+function parseColorScheme(elem, xml) {
+    var result = {
+        name: xml.attr(elem, "name"),
+        colors: {}
+    };
+    for (let el of xml.elements(elem)) {
+        var srgbClr = xml.element(el, "srgbClr");
+        var sysClr = xml.element(el, "sysClr");
+        if (srgbClr) {
+            result.colors[el.localName] = xml.attr(srgbClr, "val");
+        }
+        else if (sysClr) {
+            result.colors[el.localName] = xml.attr(sysClr, "lastClr");
+        }
+    }
+    return result;
+}
+function parseFontScheme(elem, xml) {
+    var result = {
+        name: xml.attr(elem, "name"),
+    };
+    for (let el of xml.elements(elem)) {
+        switch (el.localName) {
+            case "majorFont":
+                result.majorFont = parseFontInfo(el, xml);
+                break;
+            case "minorFont":
+                result.minorFont = parseFontInfo(el, xml);
+                break;
+        }
+    }
+    return result;
+}
+function parseFontInfo(elem, xml) {
+    return {
+        latinTypeface: xml.elementAttr(elem, "latin", "typeface"),
+        eaTypeface: xml.elementAttr(elem, "ea", "typeface"),
+        csTypeface: xml.elementAttr(elem, "cs", "typeface"),
+    };
+}
+
+class ThemePart extends Part {
+    constructor(pkg, path) {
+        super(pkg, path);
+    }
+    parseXml(root) {
+        this.theme = parseTheme(root, this._package.xmlParser);
+    }
+}
+
+class WmlBaseNote {
+}
+class WmlFootnote extends WmlBaseNote {
+    constructor() {
+        super(...arguments);
+        this.type = DomType.Footnote;
+    }
+}
+class WmlEndnote extends WmlBaseNote {
+    constructor() {
+        super(...arguments);
+        this.type = DomType.Endnote;
+    }
+}
+
+class BaseNotePart extends Part {
+    constructor(pkg, path, parser) {
+        super(pkg, path);
+        this._documentParser = parser;
+    }
+}
+class FootnotesPart extends BaseNotePart {
+    constructor(pkg, path, parser) {
+        super(pkg, path, parser);
+    }
+    parseXml(root) {
+        this.notes = this._documentParser.parseNotes(root, "footnote", WmlFootnote);
+    }
+}
+class EndnotesPart extends BaseNotePart {
+    constructor(pkg, path, parser) {
+        super(pkg, path, parser);
+    }
+    parseXml(root) {
+        this.notes = this._documentParser.parseNotes(root, "endnote", WmlEndnote);
+    }
+}
+
+function parseSettings(elem, xml) {
+    var result = {};
+    for (let el of xml.elements(elem)) {
+        switch (el.localName) {
+            case "defaultTabStop":
+                result.defaultTabStop = xml.lengthAttr(el, "val");
+                break;
+            case "footnotePr":
+                result.footnoteProps = parseNoteProperties(el, xml);
+                break;
+            case "endnotePr":
+                result.endnoteProps = parseNoteProperties(el, xml);
+                break;
+            case "autoHyphenation":
+                result.autoHyphenation = xml.boolAttr(el, "val");
+                break;
+        }
+    }
+    return result;
+}
+function parseNoteProperties(elem, xml) {
+    var result = {
+        defaultNoteIds: []
+    };
+    for (let el of xml.elements(elem)) {
+        switch (el.localName) {
+            case "numFmt":
+                result.nummeringFormat = xml.attr(el, "val");
+                break;
+            case "footnote":
+            case "endnote":
+                result.defaultNoteIds.push(xml.attr(el, "id"));
+                break;
+        }
+    }
+    return result;
+}
+
+class SettingsPart extends Part {
+    constructor(pkg, path) {
+        super(pkg, path);
+    }
+    parseXml(root) {
+        this.settings = parseSettings(root, this._package.xmlParser);
+    }
+}
+
+function parseCustomProps(root, xml) {
+    return xml.elements(root, "property").map(e => {
+        const firstChild = e.firstChild;
+        return {
+            formatId: xml.attr(e, "fmtid"),
+            name: xml.attr(e, "name"),
+            type: firstChild.nodeName,
+            value: firstChild.textContent
+        };
+    });
+}
+
+class CustomPropsPart extends Part {
+    parseXml(root) {
+        this.props = parseCustomProps(root, this._package.xmlParser);
+    }
+}
+
+class CommentsPart extends Part {
+    constructor(pkg, path, parser) {
+        super(pkg, path);
+        this._documentParser = parser;
+    }
+    parseXml(root) {
+        this.comments = this._documentParser.parseComments(root);
+        this.commentMap = keyBy(this.comments, x => x.id);
+    }
+}
+
+class CommentsExtendedPart extends Part {
+    constructor(pkg, path) {
+        super(pkg, path);
+        this.comments = [];
+    }
+    parseXml(root) {
+        const xml = this._package.xmlParser;
+        for (let el of xml.elements(root, "commentEx")) {
+            this.comments.push({
+                paraId: xml.attr(el, 'paraId'),
+                paraIdParent: xml.attr(el, 'paraIdParent'),
+                done: xml.boolAttr(el, 'done')
+            });
+        }
+        this.commentMap = keyBy(this.comments, x => x.paraId);
+    }
+}
+
+const topLevelRels = [
+    { type: RelationshipTypes.OfficeDocument, target: "word/document.xml" },
+    { type: RelationshipTypes.ExtendedProperties, target: "docProps/app.xml" },
+    { type: RelationshipTypes.CoreProperties, target: "docProps/core.xml" },
+    { type: RelationshipTypes.CustomProperties, target: "docProps/custom.xml" },
+];
+class WordDocument {
+    constructor() {
+        this.parts = [];
+        this.partsMap = {};
+    }
+    static async load(blob, parser, options) {
+        var d = new WordDocument();
+        d._options = options;
+        d._parser = parser;
+        d._package = await OpenXmlPackage.load(blob, options);
+        d.rels = await d._package.loadRelationships();
+        await Promise.all(topLevelRels.map(rel => {
+            const r = d.rels.find(x => x.type === rel.type) ?? rel;
+            return d.loadRelationshipPart(r.target, r.type);
+        }));
+        return d;
+    }
+    save(type = "blob") {
+        return this._package.save(type);
+    }
+    async loadRelationshipPart(path, type) {
+        if (this.partsMap[path])
+            return this.partsMap[path];
+        if (!this._package.get(path))
+            return null;
+        let part = null;
+        switch (type) {
+            case RelationshipTypes.OfficeDocument:
+                this.documentPart = part = new DocumentPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.FontTable:
+                this.fontTablePart = part = new FontTablePart(this._package, path);
+                break;
+            case RelationshipTypes.Numbering:
+                this.numberingPart = part = new NumberingPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.Styles:
+                this.stylesPart = part = new StylesPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.Theme:
+                this.themePart = part = new ThemePart(this._package, path);
+                break;
+            case RelationshipTypes.Footnotes:
+                this.footnotesPart = part = new FootnotesPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.Endnotes:
+                this.endnotesPart = part = new EndnotesPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.Footer:
+                part = new FooterPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.Header:
+                part = new HeaderPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.CoreProperties:
+                this.corePropsPart = part = new CorePropsPart(this._package, path);
+                break;
+            case RelationshipTypes.ExtendedProperties:
+                this.extendedPropsPart = part = new ExtendedPropsPart(this._package, path);
+                break;
+            case RelationshipTypes.CustomProperties:
+                part = new CustomPropsPart(this._package, path);
+                break;
+            case RelationshipTypes.Settings:
+                this.settingsPart = part = new SettingsPart(this._package, path);
+                break;
+            case RelationshipTypes.Comments:
+                this.commentsPart = part = new CommentsPart(this._package, path, this._parser);
+                break;
+            case RelationshipTypes.CommentsExtended:
+                this.commentsExtendedPart = part = new CommentsExtendedPart(this._package, path);
+                break;
+        }
+        if (part == null)
+            return Promise.resolve(null);
+        this.partsMap[path] = part;
+        this.parts.push(part);
+        await part.load();
+        if (part.rels?.length > 0) {
+            const [folder] = splitPath(part.path);
+            await Promise.all(part.rels.map(rel => this.loadRelationshipPart(resolvePath(rel.target, folder), rel.type)));
+        }
+        return part;
+    }
+    async loadDocumentImage(id, part) {
+        const x = await this.loadResource(part ?? this.documentPart, id, "blob");
+        return this.blobToURL(x);
+    }
+    async loadNumberingImage(id) {
+        const x = await this.loadResource(this.numberingPart, id, "blob");
+        return this.blobToURL(x);
+    }
+    async loadFont(id, key) {
+        const x = await this.loadResource(this.fontTablePart, id, "uint8array");
+        return x ? this.blobToURL(new Blob([deobfuscate(x, key)])) : x;
+    }
+    blobToURL(blob) {
+        if (!blob)
+            return null;
+        if (this._options.useBase64URL) {
+            return blobToBase64(blob);
+        }
+        return URL.createObjectURL(blob);
+    }
+    findPartByRelId(id, basePart = null) {
+        var rel = (basePart.rels ?? this.rels).find(r => r.id == id);
+        const folder = basePart ? splitPath(basePart.path)[0] : '';
+        return rel ? this.partsMap[resolvePath(rel.target, folder)] : null;
+    }
+    getPathById(part, id) {
+        const rel = part.rels.find(x => x.id == id);
+        const [folder] = splitPath(part.path);
+        return rel ? resolvePath(rel.target, folder) : null;
+    }
+    loadResource(part, id, outputType) {
+        const path = this.getPathById(part, id);
+        return path ? this._package.load(path, outputType) : Promise.resolve(null);
+    }
+}
+function deobfuscate(data, guidKey) {
+    const len = 16;
+    const trimmed = guidKey.replace(/{|}|-/g, "");
+    const numbers = new Array(len);
+    for (let i = 0; i < len; i++)
+        numbers[len - i - 1] = parseInt(trimmed.substr(i * 2, 2), 16);
+    for (let i = 0; i < 32; i++)
+        data[i] = data[i] ^ numbers[i % len];
+    return data;
+}
+
+function parseBookmarkStart(elem, xml) {
+    return {
+        type: DomType.BookmarkStart,
+        id: xml.attr(elem, "id"),
+        name: xml.attr(elem, "name"),
+        colFirst: xml.intAttr(elem, "colFirst"),
+        colLast: xml.intAttr(elem, "colLast")
+    };
+}
+function parseBookmarkEnd(elem, xml) {
+    return {
+        type: DomType.BookmarkEnd,
+        id: xml.attr(elem, "id")
+    };
+}
+
+class VmlElement extends OpenXmlElementBase {
+    constructor() {
+        super(...arguments);
+        this.type = DomType.VmlElement;
+        this.attrs = {};
+    }
+}
+function parseVmlElement(elem, parser) {
+    var result = new VmlElement();
+    switch (elem.localName) {
+        case "rect":
+            result.tagName = "rect";
+            Object.assign(result.attrs, { width: '100%', height: '100%' });
+            break;
+        case "oval":
+            result.tagName = "ellipse";
+            Object.assign(result.attrs, { cx: "50%", cy: "50%", rx: "50%", ry: "50%" });
+            break;
+        case "line":
+            result.tagName = "line";
+            break;
+        case "shape":
+            result.tagName = "g";
+            break;
+        case "textbox":
+            result.tagName = "foreignObject";
+            Object.assign(result.attrs, { width: '100%', height: '100%' });
+            break;
+        default:
+            return null;
+    }
+    for (const at of globalXmlParser.attrs(elem)) {
+        switch (at.localName) {
+            case "style":
+                result.cssStyleText = at.value;
+                break;
+            case "fillcolor":
+                result.attrs.fill = at.value;
+                break;
+            case "from":
+                const [x1, y1] = parsePoint(at.value);
+                Object.assign(result.attrs, { x1, y1 });
+                break;
+            case "to":
+                const [x2, y2] = parsePoint(at.value);
+                Object.assign(result.attrs, { x2, y2 });
+                break;
+        }
+    }
+    for (const el of globalXmlParser.elements(elem)) {
+        switch (el.localName) {
+            case "stroke":
+                Object.assign(result.attrs, parseStroke(el));
+                break;
+            case "fill":
+                Object.assign(result.attrs, parseFill());
+                break;
+            case "imagedata":
+                result.tagName = "image";
+                Object.assign(result.attrs, { width: '100%', height: '100%' });
+                result.imageHref = {
+                    id: globalXmlParser.attr(el, "id"),
+                    title: globalXmlParser.attr(el, "title"),
+                };
+                break;
+            case "txbxContent":
+                result.children.push(...parser.parseBodyElements(el));
+                break;
+            default:
+                const child = parseVmlElement(el, parser);
+                child && result.children.push(child);
+                break;
+        }
+    }
+    return result;
+}
+function parseStroke(el) {
+    return {
+        'stroke': globalXmlParser.attr(el, "color"),
+        'stroke-width': globalXmlParser.lengthAttr(el, "weight", LengthUsage.Emu) ?? '1px'
+    };
+}
+function parseFill(el) {
+    return {};
+}
+function parsePoint(val) {
+    return val.split(",");
+}
+
+class WmlComment extends OpenXmlElementBase {
+    constructor() {
+        super(...arguments);
+        this.type = DomType.Comment;
+    }
+}
+class WmlCommentReference extends OpenXmlElementBase {
+    constructor(id) {
+        super();
+        this.id = id;
+        this.type = DomType.CommentReference;
+    }
+}
+class WmlCommentRangeStart extends OpenXmlElementBase {
+    constructor(id) {
+        super();
+        this.id = id;
+        this.type = DomType.CommentRangeStart;
+    }
+}
+class WmlCommentRangeEnd extends OpenXmlElementBase {
+    constructor(id) {
+        super();
+        this.id = id;
+        this.type = DomType.CommentRangeEnd;
+    }
+}
+
+var autos = {
+    shd: "inherit",
+    color: "black",
+    borderColor: "black",
+    highlight: "transparent"
+};
+const supportedNamespaceURIs = [];
+const mmlTagMap = {
+    "oMath": DomType.MmlMath,
+    "oMathPara": DomType.MmlMathParagraph,
+    "f": DomType.MmlFraction,
+    "func": DomType.MmlFunction,
+    "fName": DomType.MmlFunctionName,
+    "num": DomType.MmlNumerator,
+    "den": DomType.MmlDenominator,
+    "rad": DomType.MmlRadical,
+    "deg": DomType.MmlDegree,
+    "e": DomType.MmlBase,
+    "sSup": DomType.MmlSuperscript,
+    "sSub": DomType.MmlSubscript,
+    "sPre": DomType.MmlPreSubSuper,
+    "sup": DomType.MmlSuperArgument,
+    "sub": DomType.MmlSubArgument,
+    "d": DomType.MmlDelimiter,
+    "nary": DomType.MmlNary,
+    "eqArr": DomType.MmlEquationArray,
+    "lim": DomType.MmlLimit,
+    "limLow": DomType.MmlLimitLower,
+    "m": DomType.MmlMatrix,
+    "mr": DomType.MmlMatrixRow,
+    "box": DomType.MmlBox,
+    "bar": DomType.MmlBar,
+    "groupChr": DomType.MmlGroupChar
+};
+class DocumentParser {
+    constructor(options) {
+        this.options = {
+            ignoreWidth: false,
+            debug: false,
+            ...options
+        };
+    }
+    parseNotes(xmlDoc, elemName, elemClass) {
+        var result = [];
+        for (let el of globalXmlParser.elements(xmlDoc, elemName)) {
+            const node = new elemClass();
+            node.id = globalXmlParser.attr(el, "id");
+            node.noteType = globalXmlParser.attr(el, "type");
+            node.children = this.parseBodyElements(el);
+            result.push(node);
+        }
+        return result;
+    }
+    parseComments(xmlDoc) {
+        var result = [];
+        for (let el of globalXmlParser.elements(xmlDoc, "comment")) {
+            const item = new WmlComment();
+            item.id = globalXmlParser.attr(el, "id");
+            item.author = globalXmlParser.attr(el, "author");
+            item.initials = globalXmlParser.attr(el, "initials");
+            item.date = globalXmlParser.attr(el, "date");
+            item.children = this.parseBodyElements(el);
+            result.push(item);
+        }
+        return result;
+    }
+    parseDocumentFile(xmlDoc) {
+        var xbody = globalXmlParser.element(xmlDoc, "body");
+        var background = globalXmlParser.element(xmlDoc, "background");
+        var sectPr = globalXmlParser.element(xbody, "sectPr");
+        return {
+            type: DomType.Document,
+            children: this.parseBodyElements(xbody),
+            props: sectPr ? parseSectionProperties(sectPr, globalXmlParser) : {},
+            cssStyle: background ? this.parseBackground(background) : {},
+        };
+    }
+    parseBackground(elem) {
+        var result = {};
+        var color = xmlUtil.colorAttr(elem, "color");
+        if (color) {
+            result["background-color"] = color;
+        }
+        return result;
+    }
+    parseBodyElements(element) {
+        var children = [];
+        for (let elem of globalXmlParser.elements(element)) {
+            switch (elem.localName) {
+                case "p":
+                    children.push(this.parseParagraph(elem));
+                    break;
+                case "tbl":
+                    children.push(this.parseTable(elem));
+                    break;
+                case "sdt":
+                    children.push(...this.parseSdt(elem, e => this.parseBodyElements(e)));
+                    break;
+            }
+        }
+        return children;
+    }
+    parseStylesFile(xstyles) {
+        var result = [];
+        xmlUtil.foreach(xstyles, n => {
+            switch (n.localName) {
+                case "style":
+                    result.push(this.parseStyle(n));
+                    break;
+                case "docDefaults":
+                    result.push(this.parseDefaultStyles(n));
+                    break;
+            }
+        });
+        return result;
+    }
+    parseDefaultStyles(node) {
+        var result = {
+            id: null,
+            name: null,
+            target: null,
+            basedOn: null,
+            styles: []
+        };
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "rPrDefault":
+                    var rPr = globalXmlParser.element(c, "rPr");
+                    if (rPr)
+                        result.styles.push({
+                            target: "span",
+                            values: this.parseDefaultProperties(rPr, {})
+                        });
+                    break;
+                case "pPrDefault":
+                    var pPr = globalXmlParser.element(c, "pPr");
+                    if (pPr)
+                        result.styles.push({
+                            target: "p",
+                            values: this.parseDefaultProperties(pPr, {})
+                        });
+                    break;
+            }
+        });
+        return result;
+    }
+    parseStyle(node) {
+        var result = {
+            id: globalXmlParser.attr(node, "styleId"),
+            isDefault: globalXmlParser.boolAttr(node, "default"),
+            name: null,
+            target: null,
+            basedOn: null,
+            styles: [],
+            linked: null
+        };
+        switch (globalXmlParser.attr(node, "type")) {
+            case "paragraph":
+                result.target = "p";
+                break;
+            case "table":
+                result.target = "table";
+                break;
+            case "character":
+                result.target = "span";
+                break;
+        }
+        xmlUtil.foreach(node, n => {
+            switch (n.localName) {
+                case "basedOn":
+                    result.basedOn = globalXmlParser.attr(n, "val");
+                    break;
+                case "name":
+                    result.name = globalXmlParser.attr(n, "val");
+                    break;
+                case "link":
+                    result.linked = globalXmlParser.attr(n, "val");
+                    break;
+                case "next":
+                    result.next = globalXmlParser.attr(n, "val");
+                    break;
+                case "aliases":
+                    result.aliases = globalXmlParser.attr(n, "val").split(",");
+                    break;
+                case "pPr":
+                    result.styles.push({
+                        target: "p",
+                        values: this.parseDefaultProperties(n, {})
+                    });
+                    result.paragraphProps = parseParagraphProperties(n, globalXmlParser);
+                    break;
+                case "rPr":
+                    result.styles.push({
+                        target: "span",
+                        values: this.parseDefaultProperties(n, {})
+                    });
+                    result.runProps = parseRunProperties(n, globalXmlParser);
+                    break;
+                case "tblPr":
+                case "tcPr":
+                    result.styles.push({
+                        target: "td",
+                        values: this.parseDefaultProperties(n, {})
+                    });
+                    break;
+                case "tblStylePr":
+                    for (let s of this.parseTableStyle(n))
+                        result.styles.push(s);
+                    break;
+                case "rsid":
+                case "qFormat":
+                case "hidden":
+                case "semiHidden":
+                case "unhideWhenUsed":
+                case "autoRedefine":
+                case "uiPriority":
+                    break;
+                default:
+                    this.options.debug && console.warn(`DOCX: Unknown style element: ${n.localName}`);
+            }
+        });
+        return result;
+    }
+    parseTableStyle(node) {
+        var result = [];
+        var type = globalXmlParser.attr(node, "type");
+        var selector = "";
+        var modificator = "";
+        switch (type) {
+            case "firstRow":
+                modificator = ".first-row";
+                selector = "tr.first-row td";
+                break;
+            case "lastRow":
+                modificator = ".last-row";
+                selector = "tr.last-row td";
+                break;
+            case "firstCol":
+                modificator = ".first-col";
+                selector = "td.first-col";
+                break;
+            case "lastCol":
+                modificator = ".last-col";
+                selector = "td.last-col";
+                break;
+            case "band1Vert":
+                modificator = ":not(.no-vband)";
+                selector = "td.odd-col";
+                break;
+            case "band2Vert":
+                modificator = ":not(.no-vband)";
+                selector = "td.even-col";
+                break;
+            case "band1Horz":
+                modificator = ":not(.no-hband)";
+                selector = "tr.odd-row";
+                break;
+            case "band2Horz":
+                modificator = ":not(.no-hband)";
+                selector = "tr.even-row";
+                break;
+            default: return [];
+        }
+        xmlUtil.foreach(node, n => {
+            switch (n.localName) {
+                case "pPr":
+                    result.push({
+                        target: `${selector} p`,
+                        mod: modificator,
+                        values: this.parseDefaultProperties(n, {})
+                    });
+                    break;
+                case "rPr":
+                    result.push({
+                        target: `${selector} span`,
+                        mod: modificator,
+                        values: this.parseDefaultProperties(n, {})
+                    });
+                    break;
+                case "tblPr":
+                case "tcPr":
+                    result.push({
+                        target: selector,
+                        mod: modificator,
+                        values: this.parseDefaultProperties(n, {})
+                    });
+                    break;
+            }
+        });
+        return result;
+    }
+    parseNumberingFile(xnums) {
+        var result = [];
+        var mapping = {};
+        var bullets = [];
+        xmlUtil.foreach(xnums, n => {
+            switch (n.localName) {
+                case "abstractNum":
+                    this.parseAbstractNumbering(n, bullets)
+                        .forEach(x => result.push(x));
+                    break;
+                case "numPicBullet":
+                    bullets.push(this.parseNumberingPicBullet(n));
+                    break;
+                case "num":
+                    var numId = globalXmlParser.attr(n, "numId");
+                    var abstractNumId = globalXmlParser.elementAttr(n, "abstractNumId", "val");
+                    mapping[abstractNumId] = numId;
+                    break;
+            }
+        });
+        result.forEach(x => x.id = mapping[x.id]);
+        return result;
+    }
+    parseNumberingPicBullet(elem) {
+        var pict = globalXmlParser.element(elem, "pict");
+        var shape = pict && globalXmlParser.element(pict, "shape");
+        var imagedata = shape && globalXmlParser.element(shape, "imagedata");
+        return imagedata ? {
+            id: globalXmlParser.intAttr(elem, "numPicBulletId"),
+            src: globalXmlParser.attr(imagedata, "id"),
+            style: globalXmlParser.attr(shape, "style")
+        } : null;
+    }
+    parseAbstractNumbering(node, bullets) {
+        var result = [];
+        var id = globalXmlParser.attr(node, "abstractNumId");
+        xmlUtil.foreach(node, n => {
+            switch (n.localName) {
+                case "lvl":
+                    result.push(this.parseNumberingLevel(id, n, bullets));
+                    break;
+            }
+        });
+        return result;
+    }
+    parseNumberingLevel(id, node, bullets) {
+        var result = {
+            id: id,
+            level: globalXmlParser.intAttr(node, "ilvl"),
+            start: 1,
+            pStyleName: undefined,
+            pStyle: {},
+            rStyle: {},
+            suff: "tab"
+        };
+        xmlUtil.foreach(node, n => {
+            switch (n.localName) {
+                case "start":
+                    result.start = globalXmlParser.intAttr(n, "val");
+                    break;
+                case "pPr":
+                    this.parseDefaultProperties(n, result.pStyle);
+                    break;
+                case "rPr":
+                    this.parseDefaultProperties(n, result.rStyle);
+                    break;
+                case "lvlPicBulletId":
+                    var id = globalXmlParser.intAttr(n, "val");
+                    result.bullet = bullets.find(x => x?.id == id);
+                    break;
+                case "lvlText":
+                    result.levelText = globalXmlParser.attr(n, "val");
+                    break;
+                case "pStyle":
+                    result.pStyleName = globalXmlParser.attr(n, "val");
+                    break;
+                case "numFmt":
+                    result.format = globalXmlParser.attr(n, "val");
+                    break;
+                case "suff":
+                    result.suff = globalXmlParser.attr(n, "val");
+                    break;
+            }
+        });
+        return result;
+    }
+    parseSdt(node, parser) {
+        const sdtContent = globalXmlParser.element(node, "sdtContent");
+        return sdtContent ? parser(sdtContent) : [];
+    }
+    parseInserted(node, parentParser) {
+        return {
+            type: DomType.Inserted,
+            children: parentParser(node)?.children ?? []
+        };
+    }
+    parseDeleted(node, parentParser) {
+        return {
+            type: DomType.Deleted,
+            children: parentParser(node)?.children ?? []
+        };
+    }
+    parseParagraph(node) {
+        var result = { type: DomType.Paragraph, children: [] };
+        for (let el of globalXmlParser.elements(node)) {
+            switch (el.localName) {
+                case "pPr":
+                    this.parseParagraphProperties(el, result);
+                    break;
+                case "r":
+                    result.children.push(this.parseRun(el, result));
+                    break;
+                case "hyperlink":
+                    result.children.push(this.parseHyperlink(el, result));
+                    break;
+                case "smartTag":
+                    result.children.push(this.parseSmartTag(el, result));
+                    break;
+                case "bookmarkStart":
+                    result.children.push(parseBookmarkStart(el, globalXmlParser));
+                    break;
+                case "bookmarkEnd":
+                    result.children.push(parseBookmarkEnd(el, globalXmlParser));
+                    break;
+                case "commentRangeStart":
+                    result.children.push(new WmlCommentRangeStart(globalXmlParser.attr(el, "id")));
+                    break;
+                case "commentRangeEnd":
+                    result.children.push(new WmlCommentRangeEnd(globalXmlParser.attr(el, "id")));
+                    break;
+                case "oMath":
+                case "oMathPara":
+                    result.children.push(this.parseMathElement(el));
+                    break;
+                case "sdt":
+                    result.children.push(...this.parseSdt(el, e => this.parseParagraph(e).children));
+                    break;
+                case "ins":
+                    result.children.push(this.parseInserted(el, e => this.parseParagraph(e)));
+                    break;
+                case "del":
+                    result.children.push(this.parseDeleted(el, e => this.parseParagraph(e)));
+                    break;
+            }
+        }
+        return result;
+    }
+    parseParagraphProperties(elem, paragraph) {
+        this.parseDefaultProperties(elem, paragraph.cssStyle = {}, null, c => {
+            if (parseParagraphProperty(c, paragraph, globalXmlParser))
+                return true;
+            switch (c.localName) {
+                case "pStyle":
+                    paragraph.styleName = globalXmlParser.attr(c, "val");
+                    break;
+                case "cnfStyle":
+                    paragraph.className = values.classNameOfCnfStyle(c);
+                    break;
+                case "framePr":
+                    this.parseFrame(c, paragraph);
+                    break;
+                case "rPr":
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        });
+    }
+    parseFrame(node, paragraph) {
+        var dropCap = globalXmlParser.attr(node, "dropCap");
+        if (dropCap == "drop")
+            paragraph.cssStyle["float"] = "left";
+    }
+    parseHyperlink(node, parent) {
+        var result = { type: DomType.Hyperlink, parent: parent, children: [] };
+        var anchor = globalXmlParser.attr(node, "anchor");
+        var relId = globalXmlParser.attr(node, "id");
+        if (anchor)
+            result.href = "#" + anchor;
+        if (relId)
+            result.id = relId;
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "r":
+                    result.children.push(this.parseRun(c, result));
+                    break;
+            }
+        });
+        return result;
+    }
+    parseSmartTag(node, parent) {
+        var result = { type: DomType.SmartTag, parent, children: [] };
+        var uri = globalXmlParser.attr(node, "uri");
+        var element = globalXmlParser.attr(node, "element");
+        if (uri)
+            result.uri = uri;
+        if (element)
+            result.element = element;
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "r":
+                    result.children.push(this.parseRun(c, result));
+                    break;
+            }
+        });
+        return result;
+    }
+    parseRun(node, parent) {
+        var result = { type: DomType.Run, parent: parent, children: [] };
+        xmlUtil.foreach(node, c => {
+            c = this.checkAlternateContent(c);
+            switch (c.localName) {
+                case "t":
+                    result.children.push({
+                        type: DomType.Text,
+                        text: c.textContent
+                    });
+                    break;
+                case "delText":
+                    result.children.push({
+                        type: DomType.DeletedText,
+                        text: c.textContent
+                    });
+                    break;
+                case "commentReference":
+                    result.children.push(new WmlCommentReference(globalXmlParser.attr(c, "id")));
+                    break;
+                case "fldSimple":
+                    result.children.push({
+                        type: DomType.SimpleField,
+                        instruction: globalXmlParser.attr(c, "instr"),
+                        lock: globalXmlParser.boolAttr(c, "lock", false),
+                        dirty: globalXmlParser.boolAttr(c, "dirty", false)
+                    });
+                    break;
+                case "instrText":
+                    result.fieldRun = true;
+                    result.children.push({
+                        type: DomType.Instruction,
+                        text: c.textContent
+                    });
+                    break;
+                case "fldChar":
+                    result.fieldRun = true;
+                    result.children.push({
+                        type: DomType.ComplexField,
+                        charType: globalXmlParser.attr(c, "fldCharType"),
+                        lock: globalXmlParser.boolAttr(c, "lock", false),
+                        dirty: globalXmlParser.boolAttr(c, "dirty", false)
+                    });
+                    break;
+                case "noBreakHyphen":
+                    result.children.push({ type: DomType.NoBreakHyphen });
+                    break;
+                case "br":
+                    result.children.push({
+                        type: DomType.Break,
+                        break: globalXmlParser.attr(c, "type") || "textWrapping"
+                    });
+                    break;
+                case "lastRenderedPageBreak":
+                    result.children.push({
+                        type: DomType.Break,
+                        break: "lastRenderedPageBreak"
+                    });
+                    break;
+                case "sym":
+                    result.children.push({
+                        type: DomType.Symbol,
+                        font: globalXmlParser.attr(c, "font"),
+                        char: globalXmlParser.attr(c, "char")
+                    });
+                    break;
+                case "tab":
+                    result.children.push({ type: DomType.Tab });
+                    break;
+                case "footnoteReference":
+                    result.children.push({
+                        type: DomType.FootnoteReference,
+                        id: globalXmlParser.attr(c, "id")
+                    });
+                    break;
+                case "endnoteReference":
+                    result.children.push({
+                        type: DomType.EndnoteReference,
+                        id: globalXmlParser.attr(c, "id")
+                    });
+                    break;
+                case "drawing":
+                    let d = this.parseDrawing(c);
+                    if (d)
+                        result.children = [d];
+                    break;
+                case "pict":
+                    result.children.push(this.parseVmlPicture(c));
+                    break;
+                case "rPr":
+                    this.parseRunProperties(c, result);
+                    break;
+            }
+        });
+        return result;
+    }
+    parseMathElement(elem) {
+        const propsTag = `${elem.localName}Pr`;
+        const result = { type: mmlTagMap[elem.localName], children: [] };
+        for (const el of globalXmlParser.elements(elem)) {
+            const childType = mmlTagMap[el.localName];
+            if (childType) {
+                result.children.push(this.parseMathElement(el));
+            }
+            else if (el.localName == "r") {
+                var run = this.parseRun(el);
+                run.type = DomType.MmlRun;
+                result.children.push(run);
+            }
+            else if (el.localName == propsTag) {
+                result.props = this.parseMathProperies(el);
+            }
+        }
+        return result;
+    }
+    parseMathProperies(elem) {
+        const result = {};
+        for (const el of globalXmlParser.elements(elem)) {
+            switch (el.localName) {
+                case "chr":
+                    result.char = globalXmlParser.attr(el, "val");
+                    break;
+                case "vertJc":
+                    result.verticalJustification = globalXmlParser.attr(el, "val");
+                    break;
+                case "pos":
+                    result.position = globalXmlParser.attr(el, "val");
+                    break;
+                case "degHide":
+                    result.hideDegree = globalXmlParser.boolAttr(el, "val");
+                    break;
+                case "begChr":
+                    result.beginChar = globalXmlParser.attr(el, "val");
+                    break;
+                case "endChr":
+                    result.endChar = globalXmlParser.attr(el, "val");
+                    break;
+            }
+        }
+        return result;
+    }
+    parseRunProperties(elem, run) {
+        this.parseDefaultProperties(elem, run.cssStyle = {}, null, c => {
+            switch (c.localName) {
+                case "rStyle":
+                    run.styleName = globalXmlParser.attr(c, "val");
+                    break;
+                case "vertAlign":
+                    run.verticalAlign = values.valueOfVertAlign(c, true);
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        });
+    }
+    parseVmlPicture(elem) {
+        const result = { type: DomType.VmlPicture, children: [] };
+        for (const el of globalXmlParser.elements(elem)) {
+            const child = parseVmlElement(el, this);
+            child && result.children.push(child);
+        }
+        return result;
+    }
+    checkAlternateContent(elem) {
+        if (elem.localName != 'AlternateContent')
+            return elem;
+        var choice = globalXmlParser.element(elem, "Choice");
+        if (choice) {
+            var requires = globalXmlParser.attr(choice, "Requires");
+            var namespaceURI = elem.lookupNamespaceURI(requires);
+            if (supportedNamespaceURIs.includes(namespaceURI))
+                return choice.firstElementChild;
+        }
+        return globalXmlParser.element(elem, "Fallback")?.firstElementChild;
+    }
+    parseDrawing(node) {
+        for (var n of globalXmlParser.elements(node)) {
+            switch (n.localName) {
+                case "inline":
+                case "anchor":
+                    return this.parseDrawingWrapper(n);
+            }
+        }
+    }
+    parseDrawingWrapper(node) {
+        var result = { type: DomType.Drawing, children: [], cssStyle: {} };
+        var isAnchor = node.localName == "anchor";
+        let wrapType = null;
+        let simplePos = globalXmlParser.boolAttr(node, "simplePos");
+        globalXmlParser.boolAttr(node, "behindDoc");
+        let posX = { relative: "page", align: "left", offset: "0" };
+        let posY = { relative: "page", align: "top", offset: "0" };
+        for (var n of globalXmlParser.elements(node)) {
+            switch (n.localName) {
+                case "simplePos":
+                    if (simplePos) {
+                        posX.offset = globalXmlParser.lengthAttr(n, "x", LengthUsage.Emu);
+                        posY.offset = globalXmlParser.lengthAttr(n, "y", LengthUsage.Emu);
+                    }
+                    break;
+                case "extent":
+                    result.cssStyle["width"] = globalXmlParser.lengthAttr(n, "cx", LengthUsage.Emu);
+                    result.cssStyle["height"] = globalXmlParser.lengthAttr(n, "cy", LengthUsage.Emu);
+                    break;
+                case "positionH":
+                case "positionV":
+                    if (!simplePos) {
+                        let pos = n.localName == "positionH" ? posX : posY;
+                        var alignNode = globalXmlParser.element(n, "align");
+                        var offsetNode = globalXmlParser.element(n, "posOffset");
+                        pos.relative = globalXmlParser.attr(n, "relativeFrom") ?? pos.relative;
+                        if (alignNode)
+                            pos.align = alignNode.textContent;
+                        if (offsetNode)
+                            pos.offset = xmlUtil.sizeValue(offsetNode, LengthUsage.Emu);
+                    }
+                    break;
+                case "wrapTopAndBottom":
+                    wrapType = "wrapTopAndBottom";
+                    break;
+                case "wrapNone":
+                    wrapType = "wrapNone";
+                    break;
+                case "graphic":
+                    var g = this.parseGraphic(n);
+                    if (g)
+                        result.children.push(g);
+                    break;
+            }
+        }
+        if (wrapType == "wrapTopAndBottom") {
+            result.cssStyle['display'] = 'block';
+            if (posX.align) {
+                result.cssStyle['text-align'] = posX.align;
+                result.cssStyle['width'] = "100%";
+            }
+        }
+        else if (wrapType == "wrapNone") {
+            result.cssStyle['display'] = 'block';
+            result.cssStyle['position'] = 'relative';
+            result.cssStyle["width"] = "0px";
+            result.cssStyle["height"] = "0px";
+            if (posX.offset)
+                result.cssStyle["left"] = posX.offset;
+            if (posY.offset)
+                result.cssStyle["top"] = posY.offset;
+        }
+        else if (isAnchor && (posX.align == 'left' || posX.align == 'right')) {
+            result.cssStyle["float"] = posX.align;
+        }
+        return result;
+    }
+    parseGraphic(elem) {
+        var graphicData = globalXmlParser.element(elem, "graphicData");
+        for (let n of globalXmlParser.elements(graphicData)) {
+            switch (n.localName) {
+                case "pic":
+                    return this.parsePicture(n);
+            }
+        }
+        return null;
+    }
+    parsePicture(elem) {
+        var result = { type: DomType.Image, src: "", cssStyle: {} };
+        var blipFill = globalXmlParser.element(elem, "blipFill");
+        var blip = globalXmlParser.element(blipFill, "blip");
+        result.src = globalXmlParser.attr(blip, "embed");
+        var spPr = globalXmlParser.element(elem, "spPr");
+        var xfrm = globalXmlParser.element(spPr, "xfrm");
+        result.cssStyle["position"] = "relative";
+        for (var n of globalXmlParser.elements(xfrm)) {
+            switch (n.localName) {
+                case "ext":
+                    result.cssStyle["width"] = globalXmlParser.lengthAttr(n, "cx", LengthUsage.Emu);
+                    result.cssStyle["height"] = globalXmlParser.lengthAttr(n, "cy", LengthUsage.Emu);
+                    break;
+                case "off":
+                    result.cssStyle["left"] = globalXmlParser.lengthAttr(n, "x", LengthUsage.Emu);
+                    result.cssStyle["top"] = globalXmlParser.lengthAttr(n, "y", LengthUsage.Emu);
+                    break;
+            }
+        }
+        return result;
+    }
+    parseTable(node) {
+        var result = { type: DomType.Table, children: [] };
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "tr":
+                    result.children.push(this.parseTableRow(c));
+                    break;
+                case "tblGrid":
+                    result.columns = this.parseTableColumns(c);
+                    break;
+                case "tblPr":
+                    this.parseTableProperties(c, result);
+                    break;
+            }
+        });
+        return result;
+    }
+    parseTableColumns(node) {
+        var result = [];
+        xmlUtil.foreach(node, n => {
+            switch (n.localName) {
+                case "gridCol":
+                    result.push({ width: globalXmlParser.lengthAttr(n, "w") });
+                    break;
+            }
+        });
+        return result;
+    }
+    parseTableProperties(elem, table) {
+        table.cssStyle = {};
+        table.cellStyle = {};
+        this.parseDefaultProperties(elem, table.cssStyle, table.cellStyle, c => {
+            switch (c.localName) {
+                case "tblStyle":
+                    table.styleName = globalXmlParser.attr(c, "val");
+                    break;
+                case "tblLook":
+                    table.className = values.classNameOftblLook(c);
+                    break;
+                case "tblpPr":
+                    this.parseTablePosition(c, table);
+                    break;
+                case "tblStyleColBandSize":
+                    table.colBandSize = globalXmlParser.intAttr(c, "val");
+                    break;
+                case "tblStyleRowBandSize":
+                    table.rowBandSize = globalXmlParser.intAttr(c, "val");
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        });
+        switch (table.cssStyle["text-align"]) {
+            case "center":
+                delete table.cssStyle["text-align"];
+                table.cssStyle["margin-left"] = "auto";
+                table.cssStyle["margin-right"] = "auto";
+                break;
+            case "right":
+                delete table.cssStyle["text-align"];
+                table.cssStyle["margin-left"] = "auto";
+                break;
+        }
+    }
+    parseTablePosition(node, table) {
+        var topFromText = globalXmlParser.lengthAttr(node, "topFromText");
+        var bottomFromText = globalXmlParser.lengthAttr(node, "bottomFromText");
+        var rightFromText = globalXmlParser.lengthAttr(node, "rightFromText");
+        var leftFromText = globalXmlParser.lengthAttr(node, "leftFromText");
+        table.cssStyle["float"] = 'left';
+        table.cssStyle["margin-bottom"] = values.addSize(table.cssStyle["margin-bottom"], bottomFromText);
+        table.cssStyle["margin-left"] = values.addSize(table.cssStyle["margin-left"], leftFromText);
+        table.cssStyle["margin-right"] = values.addSize(table.cssStyle["margin-right"], rightFromText);
+        table.cssStyle["margin-top"] = values.addSize(table.cssStyle["margin-top"], topFromText);
+    }
+    parseTableRow(node) {
+        var result = { type: DomType.Row, children: [] };
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "tc":
+                    result.children.push(this.parseTableCell(c));
+                    break;
+                case "trPr":
+                    this.parseTableRowProperties(c, result);
+                    break;
+            }
+        });
+        return result;
+    }
+    parseTableRowProperties(elem, row) {
+        row.cssStyle = this.parseDefaultProperties(elem, {}, null, c => {
+            switch (c.localName) {
+                case "cnfStyle":
+                    row.className = values.classNameOfCnfStyle(c);
+                    break;
+                case "tblHeader":
+                    row.isHeader = globalXmlParser.boolAttr(c, "val");
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        });
+    }
+    parseTableCell(node) {
+        var result = { type: DomType.Cell, children: [] };
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "tbl":
+                    result.children.push(this.parseTable(c));
+                    break;
+                case "p":
+                    result.children.push(this.parseParagraph(c));
+                    break;
+                case "tcPr":
+                    this.parseTableCellProperties(c, result);
+                    break;
+            }
+        });
+        return result;
+    }
+    parseTableCellProperties(elem, cell) {
+        cell.cssStyle = this.parseDefaultProperties(elem, {}, null, c => {
+            switch (c.localName) {
+                case "gridSpan":
+                    cell.span = globalXmlParser.intAttr(c, "val", null);
+                    break;
+                case "vMerge":
+                    cell.verticalMerge = globalXmlParser.attr(c, "val") ?? "continue";
+                    break;
+                case "cnfStyle":
+                    cell.className = values.classNameOfCnfStyle(c);
+                    break;
+                default:
+                    return false;
+            }
+            return true;
+        });
+        this.parseTableCellVerticalText(elem, cell);
+    }
+    parseTableCellVerticalText(elem, cell) {
+        const directionMap = {
+            "btLr": {
+                writingMode: "vertical-rl",
+                transform: "rotate(180deg)"
+            },
+            "lrTb": {
+                writingMode: "vertical-lr",
+                transform: "none"
+            },
+            "tbRl": {
+                writingMode: "vertical-rl",
+                transform: "none"
+            }
+        };
+        xmlUtil.foreach(elem, c => {
+            if (c.localName === "textDirection") {
+                const direction = globalXmlParser.attr(c, "val");
+                const style = directionMap[direction] || { writingMode: "horizontal-tb" };
+                cell.cssStyle["writing-mode"] = style.writingMode;
+                cell.cssStyle["transform"] = style.transform;
+            }
+        });
+    }
+    parseDefaultProperties(elem, style = null, childStyle = null, handler = null) {
+        style = style || {};
+        xmlUtil.foreach(elem, c => {
+            if (handler?.(c))
+                return;
+            switch (c.localName) {
+                case "jc":
+                    style["text-align"] = values.valueOfJc(c);
+                    break;
+                case "textAlignment":
+                    style["vertical-align"] = values.valueOfTextAlignment(c);
+                    break;
+                case "color":
+                    style["color"] = xmlUtil.colorAttr(c, "val", null, autos.color);
+                    break;
+                case "sz":
+                    style["font-size"] = style["min-height"] = globalXmlParser.lengthAttr(c, "val", LengthUsage.FontSize);
+                    break;
+                case "shd":
+                    style["background-color"] = xmlUtil.colorAttr(c, "fill", null, autos.shd);
+                    break;
+                case "highlight":
+                    style["background-color"] = xmlUtil.colorAttr(c, "val", null, autos.highlight);
+                    break;
+                case "vertAlign":
+                    break;
+                case "position":
+                    style.verticalAlign = globalXmlParser.lengthAttr(c, "val", LengthUsage.FontSize);
+                    break;
+                case "tcW":
+                    if (this.options.ignoreWidth)
+                        break;
+                case "tblW":
+                    style["width"] = values.valueOfSize(c, "w");
+                    break;
+                case "trHeight":
+                    this.parseTrHeight(c, style);
+                    break;
+                case "strike":
+                    style["text-decoration"] = globalXmlParser.boolAttr(c, "val", true) ? "line-through" : "none";
+                    break;
+                case "b":
+                    style["font-weight"] = globalXmlParser.boolAttr(c, "val", true) ? "bold" : "normal";
+                    break;
+                case "i":
+                    style["font-style"] = globalXmlParser.boolAttr(c, "val", true) ? "italic" : "normal";
+                    break;
+                case "caps":
+                    style["text-transform"] = globalXmlParser.boolAttr(c, "val", true) ? "uppercase" : "none";
+                    break;
+                case "smallCaps":
+                    style["font-variant"] = globalXmlParser.boolAttr(c, "val", true) ? "small-caps" : "none";
+                    break;
+                case "u":
+                    this.parseUnderline(c, style);
+                    break;
+                case "ind":
+                case "tblInd":
+                    this.parseIndentation(c, style);
+                    break;
+                case "rFonts":
+                    this.parseFont(c, style);
+                    break;
+                case "tblBorders":
+                    this.parseBorderProperties(c, childStyle || style);
+                    break;
+                case "tblCellSpacing":
+                    style["border-spacing"] = values.valueOfMargin(c);
+                    style["border-collapse"] = "separate";
+                    break;
+                case "pBdr":
+                    this.parseBorderProperties(c, style);
+                    break;
+                case "bdr":
+                    style["border"] = values.valueOfBorder(c);
+                    break;
+                case "tcBorders":
+                    this.parseBorderProperties(c, style);
+                    break;
+                case "vanish":
+                    if (globalXmlParser.boolAttr(c, "val", true))
+                        style["display"] = "none";
+                    break;
+                case "kern":
+                    break;
+                case "noWrap":
+                    break;
+                case "tblCellMar":
+                case "tcMar":
+                    this.parseMarginProperties(c, childStyle || style);
+                    break;
+                case "tblLayout":
+                    style["table-layout"] = values.valueOfTblLayout(c);
+                    break;
+                case "vAlign":
+                    style["vertical-align"] = values.valueOfTextAlignment(c);
+                    break;
+                case "spacing":
+                    if (elem.localName == "pPr")
+                        this.parseSpacing(c, style);
+                    break;
+                case "wordWrap":
+                    if (globalXmlParser.boolAttr(c, "val"))
+                        style["overflow-wrap"] = "break-word";
+                    break;
+                case "suppressAutoHyphens":
+                    style["hyphens"] = globalXmlParser.boolAttr(c, "val", true) ? "none" : "auto";
+                    break;
+                case "lang":
+                    style["$lang"] = globalXmlParser.attr(c, "val");
+                    break;
+                case "bCs":
+                case "iCs":
+                case "szCs":
+                case "tabs":
+                case "outlineLvl":
+                case "contextualSpacing":
+                case "tblStyleColBandSize":
+                case "tblStyleRowBandSize":
+                case "webHidden":
+                case "pageBreakBefore":
+                case "suppressLineNumbers":
+                case "keepLines":
+                case "keepNext":
+                case "widowControl":
+                case "bidi":
+                case "rtl":
+                case "noProof":
+                    break;
+                default:
+                    if (this.options.debug)
+                        console.warn(`DOCX: Unknown document element: ${elem.localName}.${c.localName}`);
+                    break;
+            }
+        });
+        return style;
+    }
+    parseUnderline(node, style) {
+        var val = globalXmlParser.attr(node, "val");
+        if (val == null)
+            return;
+        switch (val) {
+            case "dash":
+            case "dashDotDotHeavy":
+            case "dashDotHeavy":
+            case "dashedHeavy":
+            case "dashLong":
+            case "dashLongHeavy":
+            case "dotDash":
+            case "dotDotDash":
+                style["text-decoration"] = "underline dashed";
+                break;
+            case "dotted":
+            case "dottedHeavy":
+                style["text-decoration"] = "underline dotted";
+                break;
+            case "double":
+                style["text-decoration"] = "underline double";
+                break;
+            case "single":
+            case "thick":
+                style["text-decoration"] = "underline";
+                break;
+            case "wave":
+            case "wavyDouble":
+            case "wavyHeavy":
+                style["text-decoration"] = "underline wavy";
+                break;
+            case "words":
+                style["text-decoration"] = "underline";
+                break;
+            case "none":
+                style["text-decoration"] = "none";
+                break;
+        }
+        var col = xmlUtil.colorAttr(node, "color");
+        if (col)
+            style["text-decoration-color"] = col;
+    }
+    parseFont(node, style) {
+        var ascii = globalXmlParser.attr(node, "ascii");
+        var asciiTheme = values.themeValue(node, "asciiTheme");
+        var eastAsia = globalXmlParser.attr(node, "eastAsia");
+        var fonts = [ascii, asciiTheme, eastAsia].filter(x => x).map(x => encloseFontFamily(x));
+        if (fonts.length > 0)
+            style["font-family"] = [...new Set(fonts)].join(', ');
+    }
+    parseIndentation(node, style) {
+        var firstLine = globalXmlParser.lengthAttr(node, "firstLine");
+        var hanging = globalXmlParser.lengthAttr(node, "hanging");
+        var left = globalXmlParser.lengthAttr(node, "left");
+        var start = globalXmlParser.lengthAttr(node, "start");
+        var right = globalXmlParser.lengthAttr(node, "right");
+        var end = globalXmlParser.lengthAttr(node, "end");
+        if (firstLine)
+            style["text-indent"] = firstLine;
+        if (hanging)
+            style["text-indent"] = `-${hanging}`;
+        if (left || start)
+            style["margin-left"] = left || start;
+        if (right || end)
+            style["margin-right"] = right || end;
+    }
+    parseSpacing(node, style) {
+        var before = globalXmlParser.lengthAttr(node, "before");
+        var after = globalXmlParser.lengthAttr(node, "after");
+        var line = globalXmlParser.intAttr(node, "line", null);
+        var lineRule = globalXmlParser.attr(node, "lineRule");
+        if (before)
+            style["margin-top"] = before;
+        if (after)
+            style["margin-bottom"] = after;
+        if (line !== null) {
+            switch (lineRule) {
+                case "auto":
+                    style["line-height"] = `${(line / 240).toFixed(2)}`;
+                    break;
+                case "atLeast":
+                    style["line-height"] = `calc(100% + ${line / 20}pt)`;
+                    break;
+                default:
+                    style["line-height"] = style["min-height"] = `${line / 20}pt`;
+                    break;
+            }
+        }
+    }
+    parseMarginProperties(node, output) {
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "left":
+                    output["padding-left"] = values.valueOfMargin(c);
+                    break;
+                case "right":
+                    output["padding-right"] = values.valueOfMargin(c);
+                    break;
+                case "top":
+                    output["padding-top"] = values.valueOfMargin(c);
+                    break;
+                case "bottom":
+                    output["padding-bottom"] = values.valueOfMargin(c);
+                    break;
+            }
+        });
+    }
+    parseTrHeight(node, output) {
+        switch (globalXmlParser.attr(node, "hRule")) {
+            case "exact":
+                output["height"] = globalXmlParser.lengthAttr(node, "val");
+                break;
+            case "atLeast":
+            default:
+                output["height"] = globalXmlParser.lengthAttr(node, "val");
+                break;
+        }
+    }
+    parseBorderProperties(node, output) {
+        xmlUtil.foreach(node, c => {
+            switch (c.localName) {
+                case "start":
+                case "left":
+                    output["border-left"] = values.valueOfBorder(c);
+                    break;
+                case "end":
+                case "right":
+                    output["border-right"] = values.valueOfBorder(c);
+                    break;
+                case "top":
+                    output["border-top"] = values.valueOfBorder(c);
+                    break;
+                case "bottom":
+                    output["border-bottom"] = values.valueOfBorder(c);
+                    break;
+            }
+        });
+    }
+}
+const knownColors = ['black', 'blue', 'cyan', 'darkBlue', 'darkCyan', 'darkGray', 'darkGreen', 'darkMagenta', 'darkRed', 'darkYellow', 'green', 'lightGray', 'magenta', 'none', 'red', 'white', 'yellow'];
+class xmlUtil {
+    static foreach(node, cb) {
+        for (var i = 0; i < node.childNodes.length; i++) {
+            let n = node.childNodes[i];
+            if (n.nodeType == Node.ELEMENT_NODE)
+                cb(n);
+        }
+    }
+    static colorAttr(node, attrName, defValue = null, autoColor = 'black') {
+        var v = globalXmlParser.attr(node, attrName);
+        if (v) {
+            if (v == "auto") {
+                return autoColor;
+            }
+            else if (knownColors.includes(v)) {
+                return v;
+            }
+            return `#${v}`;
+        }
+        var themeColor = globalXmlParser.attr(node, "themeColor");
+        return themeColor ? `var(--docx-${themeColor}-color)` : defValue;
+    }
+    static sizeValue(node, type = LengthUsage.Dxa) {
+        return convertLength(node.textContent, type);
+    }
+}
+class values {
+    static themeValue(c, attr) {
+        var val = globalXmlParser.attr(c, attr);
+        return val ? `var(--docx-${val}-font)` : null;
+    }
+    static valueOfSize(c, attr) {
+        var type = LengthUsage.Dxa;
+        switch (globalXmlParser.attr(c, "type")) {
+            case "dxa": break;
+            case "pct":
+                type = LengthUsage.Percent;
+                break;
+            case "auto": return "auto";
+        }
+        return globalXmlParser.lengthAttr(c, attr, type);
+    }
+    static valueOfMargin(c) {
+        return globalXmlParser.lengthAttr(c, "w");
+    }
+    static valueOfBorder(c) {
+        var type = globalXmlParser.attr(c, "val");
+        if (type == "nil")
+            return "none";
+        var color = xmlUtil.colorAttr(c, "color");
+        var size = globalXmlParser.lengthAttr(c, "sz", LengthUsage.Border);
+        return `${size} solid ${color == "auto" ? autos.borderColor : color}`;
+    }
+    static valueOfTblLayout(c) {
+        var type = globalXmlParser.attr(c, "val");
+        return type == "fixed" ? "fixed" : "auto";
+    }
+    static classNameOfCnfStyle(c) {
+        const val = globalXmlParser.attr(c, "val");
+        const classes = [
+            'first-row', 'last-row', 'first-col', 'last-col',
+            'odd-col', 'even-col', 'odd-row', 'even-row',
+            'ne-cell', 'nw-cell', 'se-cell', 'sw-cell'
+        ];
+        return classes.filter((_, i) => val[i] == '1').join(' ');
+    }
+    static valueOfJc(c) {
+        var type = globalXmlParser.attr(c, "val");
+        switch (type) {
+            case "start":
+            case "left": return "left";
+            case "center": return "center";
+            case "end":
+            case "right": return "right";
+            case "both": return "justify";
+        }
+        return type;
+    }
+    static valueOfVertAlign(c, asTagName = false) {
+        var type = globalXmlParser.attr(c, "val");
+        switch (type) {
+            case "subscript": return "sub";
+            case "superscript": return asTagName ? "sup" : "super";
+        }
+        return asTagName ? null : type;
+    }
+    static valueOfTextAlignment(c) {
+        var type = globalXmlParser.attr(c, "val");
+        switch (type) {
+            case "auto":
+            case "baseline": return "baseline";
+            case "top": return "top";
+            case "center": return "middle";
+            case "bottom": return "bottom";
+        }
+        return type;
+    }
+    static addSize(a, b) {
+        if (a == null)
+            return b;
+        if (b == null)
+            return a;
+        return `calc(${a} + ${b})`;
+    }
+    static classNameOftblLook(c) {
+        const val = globalXmlParser.hexAttr(c, "val", 0);
+        let className = "";
+        if (globalXmlParser.boolAttr(c, "firstRow") || (val & 0x0020))
+            className += " first-row";
+        if (globalXmlParser.boolAttr(c, "lastRow") || (val & 0x0040))
+            className += " last-row";
+        if (globalXmlParser.boolAttr(c, "firstColumn") || (val & 0x0080))
+            className += " first-col";
+        if (globalXmlParser.boolAttr(c, "lastColumn") || (val & 0x0100))
+            className += " last-col";
+        if (globalXmlParser.boolAttr(c, "noHBand") || (val & 0x0200))
+            className += " no-hband";
+        if (globalXmlParser.boolAttr(c, "noVBand") || (val & 0x0400))
+            className += " no-vband";
+        return className.trim();
+    }
+}
+
+const defaultTab = { pos: 0, leader: "none", style: "left" };
+const maxTabs = 50;
+function computePixelToPoint(container = document.body) {
+    const temp = document.createElement("div");
+    temp.style.width = '100pt';
+    container.appendChild(temp);
+    const result = 100 / temp.offsetWidth;
+    container.removeChild(temp);
+    return result;
+}
+function updateTabStop(elem, tabs, defaultTabSize, pixelToPoint = 72 / 96) {
+    const p = elem.closest("p");
+    const ebb = elem.getBoundingClientRect();
+    const pbb = p.getBoundingClientRect();
+    const pcs = getComputedStyle(p);
+    const tabStops = tabs?.length > 0 ? tabs.map(t => ({
+        pos: lengthToPoint(t.position),
+        leader: t.leader,
+        style: t.style
+    })).sort((a, b) => a.pos - b.pos) : [defaultTab];
+    const lastTab = tabStops[tabStops.length - 1];
+    const pWidthPt = pbb.width * pixelToPoint;
+    const size = lengthToPoint(defaultTabSize);
+    let pos = lastTab.pos + size;
+    if (pos < pWidthPt) {
+        for (; pos < pWidthPt && tabStops.length < maxTabs; pos += size) {
+            tabStops.push({ ...defaultTab, pos: pos });
+        }
+    }
+    const marginLeft = parseFloat(pcs.marginLeft);
+    const pOffset = pbb.left + marginLeft;
+    const left = (ebb.left - pOffset) * pixelToPoint;
+    const tab = tabStops.find(t => t.style != "clear" && t.pos > left);
+    if (tab == null)
+        return;
+    let width = 1;
+    if (tab.style == "right" || tab.style == "center") {
+        const tabStops = Array.from(p.querySelectorAll(`.${elem.className}`));
+        const nextIdx = tabStops.indexOf(elem) + 1;
+        const range = document.createRange();
+        range.setStart(elem, 1);
+        if (nextIdx < tabStops.length) {
+            range.setEndBefore(tabStops[nextIdx]);
+        }
+        else {
+            range.setEndAfter(p);
+        }
+        const mul = tab.style == "center" ? 0.5 : 1;
+        const nextBB = range.getBoundingClientRect();
+        const offset = nextBB.left + mul * nextBB.width - (pbb.left - marginLeft);
+        width = tab.pos - offset * pixelToPoint;
+    }
+    else {
+        width = tab.pos - left;
+    }
+    elem.innerHTML = "&nbsp;";
+    elem.style.textDecoration = "inherit";
+    elem.style.wordSpacing = `${width.toFixed(0)}pt`;
+    switch (tab.leader) {
+        case "dot":
+        case "middleDot":
+            elem.style.textDecoration = "underline";
+            elem.style.textDecorationStyle = "dotted";
+            break;
+        case "hyphen":
+        case "heavy":
+        case "underscore":
+            elem.style.textDecoration = "underline";
+            break;
+    }
+}
+function lengthToPoint(length) {
+    return parseFloat(length);
+}
+
+const ns = {
+    svg: "http://www.w3.org/2000/svg",
+    mathML: "http://www.w3.org/1998/Math/MathML"
+};
+class HtmlRenderer {
+    constructor(htmlDocument) {
+        this.htmlDocument = htmlDocument;
+        this.className = "docx";
+        this.styleMap = {};
+        this.currentPart = null;
+        this.tableVerticalMerges = [];
+        this.currentVerticalMerge = null;
+        this.tableCellPositions = [];
+        this.currentCellPosition = null;
+        this.footnoteMap = {};
+        this.endnoteMap = {};
+        this.currentEndnoteIds = [];
+        this.usedHederFooterParts = [];
+        this.currentTabs = [];
+        this.commentMap = {};
+        this.tasks = [];
+        this.postRenderTasks = [];
+    }
+    async render(document, bodyContainer, styleContainer = null, options) {
+        this.document = document;
+        this.options = options;
+        this.className = options.className;
+        this.rootSelector = options.inWrapper ? `.${this.className}-wrapper` : ':root';
+        this.styleMap = null;
+        this.tasks = [];
+        if (this.options.renderComments && globalThis.Highlight) {
+            this.commentHighlight = new Highlight();
+        }
+        styleContainer = styleContainer || bodyContainer;
+        removeAllElements(styleContainer);
+        removeAllElements(bodyContainer);
+        styleContainer.appendChild(this.createComment("docxjs library predefined styles"));
+        styleContainer.appendChild(this.renderDefaultStyle());
+        if (document.themePart) {
+            styleContainer.appendChild(this.createComment("docxjs document theme values"));
+            this.renderTheme(document.themePart, styleContainer);
+        }
+        if (document.stylesPart != null) {
+            this.styleMap = this.processStyles(document.stylesPart.styles);
+            styleContainer.appendChild(this.createComment("docxjs document styles"));
+            styleContainer.appendChild(this.renderStyles(document.stylesPart.styles));
+        }
+        if (document.numberingPart) {
+            this.prodessNumberings(document.numberingPart.domNumberings);
+            styleContainer.appendChild(this.createComment("docxjs document numbering styles"));
+            styleContainer.appendChild(this.renderNumbering(document.numberingPart.domNumberings, styleContainer));
+        }
+        if (document.footnotesPart) {
+            this.footnoteMap = keyBy(document.footnotesPart.notes, x => x.id);
+        }
+        if (document.endnotesPart) {
+            this.endnoteMap = keyBy(document.endnotesPart.notes, x => x.id);
+        }
+        if (document.settingsPart) {
+            this.defaultTabSize = document.settingsPart.settings?.defaultTabStop;
+        }
+        if (!options.ignoreFonts && document.fontTablePart)
+            this.renderFontTable(document.fontTablePart, styleContainer);
+        var sectionElements = this.renderSections(document.documentPart.body);
+        if (this.options.inWrapper) {
+            bodyContainer.appendChild(this.renderWrapper(sectionElements));
+        }
+        else {
+            appendChildren(bodyContainer, sectionElements);
+        }
+        if (this.commentHighlight && options.renderComments) {
+            CSS.highlights.set(`${this.className}-comments`, this.commentHighlight);
+        }
+        this.postRenderTasks.forEach(t => t());
+        await Promise.allSettled(this.tasks);
+        this.refreshTabStops();
+    }
+    renderTheme(themePart, styleContainer) {
+        const variables = {};
+        const fontScheme = themePart.theme?.fontScheme;
+        if (fontScheme) {
+            if (fontScheme.majorFont) {
+                variables['--docx-majorHAnsi-font'] = fontScheme.majorFont.latinTypeface;
+            }
+            if (fontScheme.minorFont) {
+                variables['--docx-minorHAnsi-font'] = fontScheme.minorFont.latinTypeface;
+            }
+        }
+        const colorScheme = themePart.theme?.colorScheme;
+        if (colorScheme) {
+            for (let [k, v] of Object.entries(colorScheme.colors)) {
+                variables[`--docx-${k}-color`] = `#${v}`;
+            }
+        }
+        const cssText = this.styleToString(`.${this.className}`, variables);
+        styleContainer.appendChild(this.createStyleElement(cssText));
+    }
+    renderFontTable(fontsPart, styleContainer) {
+        for (let f of fontsPart.fonts) {
+            for (let ref of f.embedFontRefs) {
+                this.tasks.push(this.document.loadFont(ref.id, ref.key).then(fontData => {
+                    const cssValues = {
+                        'font-family': encloseFontFamily(f.name),
+                        'src': `url(${fontData})`
+                    };
+                    if (ref.type == "bold" || ref.type == "boldItalic") {
+                        cssValues['font-weight'] = 'bold';
+                    }
+                    if (ref.type == "italic" || ref.type == "boldItalic") {
+                        cssValues['font-style'] = 'italic';
+                    }
+                    const cssText = this.styleToString("@font-face", cssValues);
+                    styleContainer.appendChild(this.createComment(`docxjs ${f.name} font`));
+                    styleContainer.appendChild(this.createStyleElement(cssText));
+                }));
+            }
+        }
+    }
+    processStyleName(className) {
+        return className ? `${this.className}_${escapeClassName(className)}` : this.className;
+    }
+    processStyles(styles) {
+        const stylesMap = keyBy(styles.filter(x => x.id != null), x => x.id);
+        for (const style of styles.filter(x => x.basedOn)) {
+            var baseStyle = stylesMap[style.basedOn];
+            if (baseStyle) {
+                style.paragraphProps = mergeDeep(style.paragraphProps, baseStyle.paragraphProps);
+                style.runProps = mergeDeep(style.runProps, baseStyle.runProps);
+                for (const baseValues of baseStyle.styles) {
+                    const styleValues = style.styles.find(x => x.target == baseValues.target);
+                    if (styleValues) {
+                        this.copyStyleProperties(baseValues.values, styleValues.values);
+                    }
+                    else {
+                        style.styles.push({ ...baseValues, values: { ...baseValues.values } });
+                    }
+                }
+            }
+            else if (this.options.debug)
+                console.warn(`Can't find base style ${style.basedOn}`);
+        }
+        for (let style of styles) {
+            style.cssName = this.processStyleName(style.id);
+        }
+        return stylesMap;
+    }
+    prodessNumberings(numberings) {
+        for (let num of numberings.filter(n => n.pStyleName)) {
+            const style = this.findStyle(num.pStyleName);
+            if (style?.paragraphProps?.numbering) {
+                style.paragraphProps.numbering.level = num.level;
+            }
+        }
+    }
+    processElement(element) {
+        if (element.children) {
+            for (var e of element.children) {
+                e.parent = element;
+                if (e.type == DomType.Table) {
+                    this.processTable(e);
+                }
+                else {
+                    this.processElement(e);
+                }
+            }
+        }
+    }
+    processTable(table) {
+        for (var r of table.children) {
+            for (var c of r.children) {
+                c.cssStyle = this.copyStyleProperties(table.cellStyle, c.cssStyle, [
+                    "border-left", "border-right", "border-top", "border-bottom",
+                    "padding-left", "padding-right", "padding-top", "padding-bottom"
+                ]);
+                this.processElement(c);
+            }
+        }
+    }
+    copyStyleProperties(input, output, attrs = null) {
+        if (!input)
+            return output;
+        if (output == null)
+            output = {};
+        if (attrs == null)
+            attrs = Object.getOwnPropertyNames(input);
+        for (var key of attrs) {
+            if (input.hasOwnProperty(key) && !output.hasOwnProperty(key))
+                output[key] = input[key];
+        }
+        return output;
+    }
+    createPageElement(className, props) {
+        var elem = this.createElement("section", { className });
+        if (props) {
+            if (props.pageMargins) {
+                elem.style.paddingLeft = props.pageMargins.left;
+                elem.style.paddingRight = props.pageMargins.right;
+                elem.style.paddingTop = props.pageMargins.top;
+                elem.style.paddingBottom = props.pageMargins.bottom;
+            }
+            if (props.pageSize) {
+                if (!this.options.ignoreWidth)
+                    elem.style.width = props.pageSize.width;
+                if (!this.options.ignoreHeight)
+                    elem.style.minHeight = props.pageSize.height;
+            }
+        }
+        return elem;
+    }
+    createSectionContent(props) {
+        var elem = this.createElement("article");
+        if (props.columns && props.columns.numberOfColumns) {
+            elem.style.columnCount = `${props.columns.numberOfColumns}`;
+            elem.style.columnGap = props.columns.space;
+            if (props.columns.separator) {
+                elem.style.columnRule = "1px solid black";
+            }
+        }
+        return elem;
+    }
+    renderSections(document) {
+        const result = [];
+        this.processElement(document);
+        const sections = this.splitBySection(document.children, document.props);
+        const pages = this.groupByPageBreaks(sections);
+        let prevProps = null;
+        for (let i = 0, l = pages.length; i < l; i++) {
+            this.currentFootnoteIds = [];
+            const section = pages[i][0];
+            let props = section.sectProps;
+            const pageElement = this.createPageElement(this.className, props);
+            this.renderStyleValues(document.cssStyle, pageElement);
+            this.options.renderHeaders && this.renderHeaderFooter(props.headerRefs, props, result.length, prevProps != props, pageElement);
+            for (const sect of pages[i]) {
+                var contentElement = this.createSectionContent(sect.sectProps);
+                this.renderElements(sect.elements, contentElement);
+                pageElement.appendChild(contentElement);
+                props = sect.sectProps;
+            }
+            if (this.options.renderFootnotes) {
+                this.renderNotes(this.currentFootnoteIds, this.footnoteMap, pageElement);
+            }
+            if (this.options.renderEndnotes && i == l - 1) {
+                this.renderNotes(this.currentEndnoteIds, this.endnoteMap, pageElement);
+            }
+            this.options.renderFooters && this.renderHeaderFooter(props.footerRefs, props, result.length, prevProps != props, pageElement);
+            result.push(pageElement);
+            prevProps = props;
+        }
+        return result;
+    }
+    renderHeaderFooter(refs, props, page, firstOfSection, into) {
+        if (!refs)
+            return;
+        var ref = (props.titlePage && firstOfSection ? refs.find(x => x.type == "first") : null)
+            ?? (page % 2 == 1 ? refs.find(x => x.type == "even") : null)
+            ?? refs.find(x => x.type == "default");
+        var part = ref && this.document.findPartByRelId(ref.id, this.document.documentPart);
+        if (part) {
+            this.currentPart = part;
+            if (!this.usedHederFooterParts.includes(part.path)) {
+                this.processElement(part.rootElement);
+                this.usedHederFooterParts.push(part.path);
+            }
+            const [el] = this.renderElements([part.rootElement], into);
+            if (props?.pageMargins) {
+                if (part.rootElement.type === DomType.Header) {
+                    el.style.marginTop = `calc(${props.pageMargins.header} - ${props.pageMargins.top})`;
+                    el.style.minHeight = `calc(${props.pageMargins.top} - ${props.pageMargins.header})`;
+                }
+                else if (part.rootElement.type === DomType.Footer) {
+                    el.style.marginBottom = `calc(${props.pageMargins.footer} - ${props.pageMargins.bottom})`;
+                    el.style.minHeight = `calc(${props.pageMargins.bottom} - ${props.pageMargins.footer})`;
+                }
+            }
+            this.currentPart = null;
+        }
+    }
+    isPageBreakElement(elem) {
+        if (elem.type != DomType.Break)
+            return false;
+        if (elem.break == "lastRenderedPageBreak")
+            return !this.options.ignoreLastRenderedPageBreak;
+        return elem.break == "page";
+    }
+    isPageBreakSection(prev, next) {
+        if (!prev)
+            return false;
+        if (!next)
+            return false;
+        return prev.pageSize?.orientation != next.pageSize?.orientation
+            || prev.pageSize?.width != next.pageSize?.width
+            || prev.pageSize?.height != next.pageSize?.height;
+    }
+    splitBySection(elements, defaultProps) {
+        var current = { sectProps: null, elements: [], pageBreak: false };
+        var result = [current];
+        for (let elem of elements) {
+            if (elem.type == DomType.Paragraph) {
+                const s = this.findStyle(elem.styleName);
+                if (s?.paragraphProps?.pageBreakBefore) {
+                    current.sectProps = sectProps;
+                    current.pageBreak = true;
+                    current = { sectProps: null, elements: [], pageBreak: false };
+                    result.push(current);
+                }
+            }
+            current.elements.push(elem);
+            if (elem.type == DomType.Paragraph) {
+                const p = elem;
+                var sectProps = p.sectionProps;
+                var pBreakIndex = -1;
+                var rBreakIndex = -1;
+                if (this.options.breakPages && p.children) {
+                    pBreakIndex = p.children.findIndex(r => {
+                        rBreakIndex = r.children?.findIndex(this.isPageBreakElement.bind(this)) ?? -1;
+                        return rBreakIndex != -1;
+                    });
+                }
+                if (sectProps || pBreakIndex != -1) {
+                    current.sectProps = sectProps;
+                    current.pageBreak = pBreakIndex != -1;
+                    current = { sectProps: null, elements: [], pageBreak: false };
+                    result.push(current);
+                }
+                if (pBreakIndex != -1) {
+                    let breakRun = p.children[pBreakIndex];
+                    let splitRun = rBreakIndex < breakRun.children.length - 1;
+                    if (pBreakIndex < p.children.length - 1 || splitRun) {
+                        var children = elem.children;
+                        var newParagraph = { ...elem, children: children.slice(pBreakIndex) };
+                        elem.children = children.slice(0, pBreakIndex);
+                        current.elements.push(newParagraph);
+                        if (splitRun) {
+                            let runChildren = breakRun.children;
+                            let newRun = { ...breakRun, children: runChildren.slice(0, rBreakIndex) };
+                            elem.children.push(newRun);
+                            breakRun.children = runChildren.slice(rBreakIndex);
+                        }
+                    }
+                }
+            }
+        }
+        let currentSectProps = null;
+        for (let i = result.length - 1; i >= 0; i--) {
+            if (result[i].sectProps == null) {
+                result[i].sectProps = currentSectProps ?? defaultProps;
+            }
+            else {
+                currentSectProps = result[i].sectProps;
+            }
+        }
+        return result;
+    }
+    groupByPageBreaks(sections) {
+        let current = [];
+        let prev;
+        const result = [current];
+        for (let s of sections) {
+            current.push(s);
+            if (this.options.ignoreLastRenderedPageBreak || s.pageBreak || this.isPageBreakSection(prev, s.sectProps))
+                result.push(current = []);
+            prev = s.sectProps;
+        }
+        return result.filter(x => x.length > 0);
+    }
+    renderWrapper(children) {
+        return this.createElement("div", { className: `${this.className}-wrapper` }, children);
+    }
+    renderDefaultStyle() {
+        var c = this.className;
+        var styleText = `
+.${c}-wrapper { background: gray; padding: 30px; padding-bottom: 0px; display: flex; flex-flow: column; align-items: center; } 
+.${c}-wrapper>section.${c} { background: white; box-shadow: 0 0 10px rgba(0, 0, 0, 0.5); margin-bottom: 30px; }
+.${c} { color: black; hyphens: auto; text-underline-position: from-font; }
+section.${c} { box-sizing: border-box; display: flex; flex-flow: column nowrap; position: relative; overflow: hidden; }
+section.${c}>article { margin-bottom: auto; z-index: 1; }
+section.${c}>footer { z-index: 1; }
+.${c} table { border-collapse: collapse; }
+.${c} table td, .${c} table th { vertical-align: top; }
+.${c} p { margin: 0pt; min-height: 1em; }
+.${c} span { white-space: pre-wrap; overflow-wrap: break-word; }
+.${c} a { color: inherit; text-decoration: inherit; }
+.${c} svg { fill: transparent; }
+`;
+        if (this.options.renderComments) {
+            styleText += `
+.${c}-comment-ref { cursor: default; }
+.${c}-comment-popover { display: none; z-index: 1000; padding: 0.5rem; background: white; position: absolute; box-shadow: 0 0 0.25rem rgba(0, 0, 0, 0.25); width: 30ch; }
+.${c}-comment-ref:hover~.${c}-comment-popover { display: block; }
+.${c}-comment-author,.${c}-comment-date { font-size: 0.875rem; color: #888; }
+`;
+        }
+        return this.createStyleElement(styleText);
+    }
+    renderNumbering(numberings, styleContainer) {
+        var styleText = "";
+        var resetCounters = [];
+        for (var num of numberings) {
+            var selector = `p.${this.numberingClass(num.id, num.level)}`;
+            var listStyleType = "none";
+            if (num.bullet) {
+                let valiable = `--${this.className}-${num.bullet.src}`.toLowerCase();
+                styleText += this.styleToString(`${selector}:before`, {
+                    "content": "' '",
+                    "display": "inline-block",
+                    "background": `var(${valiable})`
+                }, num.bullet.style);
+                this.tasks.push(this.document.loadNumberingImage(num.bullet.src).then(data => {
+                    var text = `${this.rootSelector} { ${valiable}: url(${data}) }`;
+                    styleContainer.appendChild(this.createStyleElement(text));
+                }));
+            }
+            else if (num.levelText) {
+                let counter = this.numberingCounter(num.id, num.level);
+                const counterReset = counter + " " + (num.start - 1);
+                if (num.level > 0) {
+                    styleText += this.styleToString(`p.${this.numberingClass(num.id, num.level - 1)}`, {
+                        "counter-reset": counterReset
+                    });
+                }
+                resetCounters.push(counterReset);
+                styleText += this.styleToString(`${selector}:before`, {
+                    "content": this.levelTextToContent(num.levelText, num.suff, num.id, this.numFormatToCssValue(num.format)),
+                    "counter-increment": counter,
+                    ...num.rStyle,
+                });
+            }
+            else {
+                listStyleType = this.numFormatToCssValue(num.format);
+            }
+            styleText += this.styleToString(selector, {
+                "display": "list-item",
+                "list-style-position": "inside",
+                "list-style-type": listStyleType,
+                ...num.pStyle
+            });
+        }
+        if (resetCounters.length > 0) {
+            styleText += this.styleToString(this.rootSelector, {
+                "counter-reset": resetCounters.join(" ")
+            });
+        }
+        return this.createStyleElement(styleText);
+    }
+    renderStyles(styles) {
+        var styleText = "";
+        const stylesMap = this.styleMap;
+        const defautStyles = keyBy(styles.filter(s => s.isDefault), s => s.target);
+        for (const style of styles) {
+            var subStyles = style.styles;
+            if (style.linked) {
+                var linkedStyle = style.linked && stylesMap[style.linked];
+                if (linkedStyle)
+                    subStyles = subStyles.concat(linkedStyle.styles);
+                else if (this.options.debug)
+                    console.warn(`Can't find linked style ${style.linked}`);
+            }
+            for (const subStyle of subStyles) {
+                var selector = `${style.target ?? ''}.${style.cssName}`;
+                if (style.target != subStyle.target)
+                    selector += ` ${subStyle.target}`;
+                if (defautStyles[style.target] == style)
+                    selector = `.${this.className} ${style.target}, ` + selector;
+                styleText += this.styleToString(selector, subStyle.values);
+            }
+        }
+        return this.createStyleElement(styleText);
+    }
+    renderNotes(noteIds, notesMap, into) {
+        var notes = noteIds.map(id => notesMap[id]).filter(x => x);
+        if (notes.length > 0) {
+            var result = this.createElement("ol", null, this.renderElements(notes));
+            into.appendChild(result);
+        }
+    }
+    renderElement(elem) {
+        switch (elem.type) {
+            case DomType.Paragraph:
+                return this.renderParagraph(elem);
+            case DomType.BookmarkStart:
+                return this.renderBookmarkStart(elem);
+            case DomType.BookmarkEnd:
+                return null;
+            case DomType.Run:
+                return this.renderRun(elem);
+            case DomType.Table:
+                return this.renderTable(elem);
+            case DomType.Row:
+                return this.renderTableRow(elem);
+            case DomType.Cell:
+                return this.renderTableCell(elem);
+            case DomType.Hyperlink:
+                return this.renderHyperlink(elem);
+            case DomType.SmartTag:
+                return this.renderSmartTag(elem);
+            case DomType.Drawing:
+                return this.renderDrawing(elem);
+            case DomType.Image:
+                return this.renderImage(elem);
+            case DomType.Text:
+                return this.renderText(elem);
+            case DomType.Text:
+                return this.renderText(elem);
+            case DomType.DeletedText:
+                return this.renderDeletedText(elem);
+            case DomType.Tab:
+                return this.renderTab(elem);
+            case DomType.Symbol:
+                return this.renderSymbol(elem);
+            case DomType.Break:
+                return this.renderBreak(elem);
+            case DomType.Footer:
+                return this.renderContainer(elem, "footer");
+            case DomType.Header:
+                return this.renderContainer(elem, "header");
+            case DomType.Footnote:
+            case DomType.Endnote:
+                return this.renderContainer(elem, "li");
+            case DomType.FootnoteReference:
+                return this.renderFootnoteReference(elem);
+            case DomType.EndnoteReference:
+                return this.renderEndnoteReference(elem);
+            case DomType.NoBreakHyphen:
+                return this.createElement("wbr");
+            case DomType.VmlPicture:
+                return this.renderVmlPicture(elem);
+            case DomType.VmlElement:
+                return this.renderVmlElement(elem);
+            case DomType.MmlMath:
+                return this.renderContainerNS(elem, ns.mathML, "math", { xmlns: ns.mathML });
+            case DomType.MmlMathParagraph:
+                return this.renderContainer(elem, "span");
+            case DomType.MmlFraction:
+                return this.renderContainerNS(elem, ns.mathML, "mfrac");
+            case DomType.MmlBase:
+                return this.renderContainerNS(elem, ns.mathML, elem.parent.type == DomType.MmlMatrixRow ? "mtd" : "mrow");
+            case DomType.MmlNumerator:
+            case DomType.MmlDenominator:
+            case DomType.MmlFunction:
+            case DomType.MmlLimit:
+            case DomType.MmlBox:
+                return this.renderContainerNS(elem, ns.mathML, "mrow");
+            case DomType.MmlGroupChar:
+                return this.renderMmlGroupChar(elem);
+            case DomType.MmlLimitLower:
+                return this.renderContainerNS(elem, ns.mathML, "munder");
+            case DomType.MmlMatrix:
+                return this.renderContainerNS(elem, ns.mathML, "mtable");
+            case DomType.MmlMatrixRow:
+                return this.renderContainerNS(elem, ns.mathML, "mtr");
+            case DomType.MmlRadical:
+                return this.renderMmlRadical(elem);
+            case DomType.MmlSuperscript:
+                return this.renderContainerNS(elem, ns.mathML, "msup");
+            case DomType.MmlSubscript:
+                return this.renderContainerNS(elem, ns.mathML, "msub");
+            case DomType.MmlDegree:
+            case DomType.MmlSuperArgument:
+            case DomType.MmlSubArgument:
+                return this.renderContainerNS(elem, ns.mathML, "mn");
+            case DomType.MmlFunctionName:
+                return this.renderContainerNS(elem, ns.mathML, "ms");
+            case DomType.MmlDelimiter:
+                return this.renderMmlDelimiter(elem);
+            case DomType.MmlRun:
+                return this.renderMmlRun(elem);
+            case DomType.MmlNary:
+                return this.renderMmlNary(elem);
+            case DomType.MmlPreSubSuper:
+                return this.renderMmlPreSubSuper(elem);
+            case DomType.MmlBar:
+                return this.renderMmlBar(elem);
+            case DomType.MmlEquationArray:
+                return this.renderMllList(elem);
+            case DomType.Inserted:
+                return this.renderInserted(elem);
+            case DomType.Deleted:
+                return this.renderDeleted(elem);
+            case DomType.CommentRangeStart:
+                return this.renderCommentRangeStart(elem);
+            case DomType.CommentRangeEnd:
+                return this.renderCommentRangeEnd(elem);
+            case DomType.CommentReference:
+                return this.renderCommentReference(elem);
+        }
+        return null;
+    }
+    renderElements(elems, into) {
+        if (elems == null)
+            return null;
+        var result = elems.flatMap(e => this.renderElement(e)).filter(e => e != null);
+        if (into)
+            appendChildren(into, result);
+        return result;
+    }
+    renderContainer(elem, tagName, props) {
+        return this.createElement(tagName, props, this.renderElements(elem.children));
+    }
+    renderContainerNS(elem, ns, tagName, props) {
+        return this.createElementNS(ns, tagName, props, this.renderElements(elem.children));
+    }
+    renderParagraph(elem) {
+        var result = this.renderContainer(elem, "p");
+        const style = this.findStyle(elem.styleName);
+        elem.tabs ?? (elem.tabs = style?.paragraphProps?.tabs);
+        this.renderClass(elem, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        this.renderCommonProperties(result.style, elem);
+        const numbering = elem.numbering ?? style?.paragraphProps?.numbering;
+        if (numbering) {
+            result.classList.add(this.numberingClass(numbering.id, numbering.level));
+        }
+        return result;
+    }
+    renderRunProperties(style, props) {
+        this.renderCommonProperties(style, props);
+    }
+    renderCommonProperties(style, props) {
+        if (props == null)
+            return;
+        if (props.color) {
+            style["color"] = props.color;
+        }
+        if (props.fontSize) {
+            style["font-size"] = props.fontSize;
+        }
+    }
+    renderHyperlink(elem) {
+        var result = this.renderContainer(elem, "a");
+        this.renderStyleValues(elem.cssStyle, result);
+        if (elem.href) {
+            result.href = elem.href;
+        }
+        else if (elem.id) {
+            const rel = this.document.documentPart.rels
+                .find(it => it.id == elem.id && it.targetMode === "External");
+            result.href = rel?.target;
+        }
+        return result;
+    }
+    renderSmartTag(elem) {
+        return this.renderContainer(elem, "span");
+    }
+    renderCommentRangeStart(commentStart) {
+        if (!this.options.renderComments)
+            return null;
+        const rng = new Range();
+        this.commentHighlight?.add(rng);
+        const result = this.htmlDocument.createComment(`start of comment #${commentStart.id}`);
+        this.later(() => rng.setStart(result, 0));
+        this.commentMap[commentStart.id] = rng;
+        return result;
+    }
+    renderCommentRangeEnd(commentEnd) {
+        if (!this.options.renderComments)
+            return null;
+        const rng = this.commentMap[commentEnd.id];
+        const result = this.htmlDocument.createComment(`end of comment #${commentEnd.id}`);
+        this.later(() => rng?.setEnd(result, 0));
+        return result;
+    }
+    renderCommentReference(commentRef) {
+        if (!this.options.renderComments)
+            return null;
+        var comment = this.document.commentsPart?.commentMap[commentRef.id];
+        if (!comment)
+            return null;
+        const frg = new DocumentFragment();
+        const commentRefEl = this.createElement("span", { className: `${this.className}-comment-ref` }, ['💬']);
+        const commentsContainerEl = this.createElement("div", { className: `${this.className}-comment-popover` });
+        this.renderCommentContent(comment, commentsContainerEl);
+        frg.appendChild(this.htmlDocument.createComment(`comment #${comment.id} by ${comment.author} on ${comment.date}`));
+        frg.appendChild(commentRefEl);
+        frg.appendChild(commentsContainerEl);
+        return frg;
+    }
+    renderCommentContent(comment, container) {
+        container.appendChild(this.createElement('div', { className: `${this.className}-comment-author` }, [comment.author]));
+        container.appendChild(this.createElement('div', { className: `${this.className}-comment-date` }, [new Date(comment.date).toLocaleString()]));
+        this.renderElements(comment.children, container);
+    }
+    renderDrawing(elem) {
+        var result = this.renderContainer(elem, "div");
+        result.style.display = "inline-block";
+        result.style.position = "relative";
+        result.style.textIndent = "0px";
+        this.renderStyleValues(elem.cssStyle, result);
+        return result;
+    }
+    renderImage(elem) {
+        let result = this.createElement("img");
+        this.renderStyleValues(elem.cssStyle, result);
+        if (this.document) {
+            this.tasks.push(this.document.loadDocumentImage(elem.src, this.currentPart).then(x => {
+                result.src = x;
+            }));
+        }
+        return result;
+    }
+    renderText(elem) {
+        return this.htmlDocument.createTextNode(elem.text);
+    }
+    renderDeletedText(elem) {
+        return this.options.renderEndnotes ? this.htmlDocument.createTextNode(elem.text) : null;
+    }
+    renderBreak(elem) {
+        if (elem.break == "textWrapping") {
+            return this.createElement("br");
+        }
+        return null;
+    }
+    renderInserted(elem) {
+        if (this.options.renderChanges)
+            return this.renderContainer(elem, "ins");
+        return this.renderElements(elem.children);
+    }
+    renderDeleted(elem) {
+        if (this.options.renderChanges)
+            return this.renderContainer(elem, "del");
+        return null;
+    }
+    renderSymbol(elem) {
+        var span = this.createElement("span");
+        span.style.fontFamily = elem.font;
+        span.innerHTML = `&#x${elem.char};`;
+        return span;
+    }
+    renderFootnoteReference(elem) {
+        var result = this.createElement("sup");
+        this.currentFootnoteIds.push(elem.id);
+        result.textContent = `${this.currentFootnoteIds.length}`;
+        return result;
+    }
+    renderEndnoteReference(elem) {
+        var result = this.createElement("sup");
+        this.currentEndnoteIds.push(elem.id);
+        result.textContent = `${this.currentEndnoteIds.length}`;
+        return result;
+    }
+    renderTab(elem) {
+        var tabSpan = this.createElement("span");
+        tabSpan.innerHTML = "&emsp;";
+        if (this.options.experimental) {
+            tabSpan.className = this.tabStopClass();
+            var stops = findParent(elem, DomType.Paragraph)?.tabs;
+            this.currentTabs.push({ stops, span: tabSpan });
+        }
+        return tabSpan;
+    }
+    renderBookmarkStart(elem) {
+        return this.createElement("span", { id: elem.name });
+    }
+    renderRun(elem) {
+        if (elem.fieldRun)
+            return null;
+        const result = this.createElement("span");
+        if (elem.id)
+            result.id = elem.id;
+        this.renderClass(elem, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        if (elem.verticalAlign) {
+            const wrapper = this.createElement(elem.verticalAlign);
+            this.renderElements(elem.children, wrapper);
+            result.appendChild(wrapper);
+        }
+        else {
+            this.renderElements(elem.children, result);
+        }
+        return result;
+    }
+    renderTable(elem) {
+        let result = this.createElement("table");
+        this.tableCellPositions.push(this.currentCellPosition);
+        this.tableVerticalMerges.push(this.currentVerticalMerge);
+        this.currentVerticalMerge = {};
+        this.currentCellPosition = { col: 0, row: 0 };
+        if (elem.columns)
+            result.appendChild(this.renderTableColumns(elem.columns));
+        this.renderClass(elem, result);
+        this.renderElements(elem.children, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        this.currentVerticalMerge = this.tableVerticalMerges.pop();
+        this.currentCellPosition = this.tableCellPositions.pop();
+        return result;
+    }
+    renderTableColumns(columns) {
+        let result = this.createElement("colgroup");
+        for (let col of columns) {
+            let colElem = this.createElement("col");
+            if (col.width)
+                colElem.style.width = col.width;
+            result.appendChild(colElem);
+        }
+        return result;
+    }
+    renderTableRow(elem) {
+        let result = this.renderContainer(elem, "tr");
+        this.currentCellPosition.col = 0;
+        this.renderClass(elem, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        this.currentCellPosition.row++;
+        return result;
+    }
+    renderTableCell(elem) {
+        let result = this.renderContainer(elem, "td");
+        const key = this.currentCellPosition.col;
+        if (elem.verticalMerge) {
+            if (elem.verticalMerge == "restart") {
+                this.currentVerticalMerge[key] = result;
+                result.rowSpan = 1;
+            }
+            else if (this.currentVerticalMerge[key]) {
+                this.currentVerticalMerge[key].rowSpan += 1;
+                result.style.display = "none";
+            }
+        }
+        else {
+            this.currentVerticalMerge[key] = null;
+        }
+        this.renderClass(elem, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        if (elem.span)
+            result.colSpan = elem.span;
+        this.currentCellPosition.col += result.colSpan;
+        return result;
+    }
+    renderVmlPicture(elem) {
+        return this.renderContainer(elem, "div");
+    }
+    renderVmlElement(elem) {
+        var container = this.createSvgElement("svg");
+        container.setAttribute("style", elem.cssStyleText);
+        const result = this.renderVmlChildElement(elem);
+        if (elem.imageHref?.id) {
+            this.tasks.push(this.document?.loadDocumentImage(elem.imageHref.id, this.currentPart)
+                .then(x => result.setAttribute("href", x)));
+        }
+        container.appendChild(result);
+        requestAnimationFrame(() => {
+            const bb = container.firstElementChild.getBBox();
+            container.setAttribute("width", `${Math.ceil(bb.x + bb.width)}`);
+            container.setAttribute("height", `${Math.ceil(bb.y + bb.height)}`);
+        });
+        return container;
+    }
+    renderVmlChildElement(elem) {
+        const result = this.createSvgElement(elem.tagName);
+        Object.entries(elem.attrs).forEach(([k, v]) => result.setAttribute(k, v));
+        for (let child of elem.children) {
+            if (child.type == DomType.VmlElement) {
+                result.appendChild(this.renderVmlChildElement(child));
+            }
+            else {
+                result.appendChild(...asArray(this.renderElement(child)));
+            }
+        }
+        return result;
+    }
+    renderMmlRadical(elem) {
+        const base = elem.children.find(el => el.type == DomType.MmlBase);
+        if (elem.props?.hideDegree) {
+            return this.createElementNS(ns.mathML, "msqrt", null, this.renderElements([base]));
+        }
+        const degree = elem.children.find(el => el.type == DomType.MmlDegree);
+        return this.createElementNS(ns.mathML, "mroot", null, this.renderElements([base, degree]));
+    }
+    renderMmlDelimiter(elem) {
+        const children = [];
+        children.push(this.createElementNS(ns.mathML, "mo", null, [elem.props.beginChar ?? '(']));
+        children.push(...this.renderElements(elem.children));
+        children.push(this.createElementNS(ns.mathML, "mo", null, [elem.props.endChar ?? ')']));
+        return this.createElementNS(ns.mathML, "mrow", null, children);
+    }
+    renderMmlNary(elem) {
+        const children = [];
+        const grouped = keyBy(elem.children, x => x.type);
+        const sup = grouped[DomType.MmlSuperArgument];
+        const sub = grouped[DomType.MmlSubArgument];
+        const supElem = sup ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sup))) : null;
+        const subElem = sub ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sub))) : null;
+        const charElem = this.createElementNS(ns.mathML, "mo", null, [elem.props?.char ?? '\u222B']);
+        if (supElem || subElem) {
+            children.push(this.createElementNS(ns.mathML, "munderover", null, [charElem, subElem, supElem]));
+        }
+        else if (supElem) {
+            children.push(this.createElementNS(ns.mathML, "mover", null, [charElem, supElem]));
+        }
+        else if (subElem) {
+            children.push(this.createElementNS(ns.mathML, "munder", null, [charElem, subElem]));
+        }
+        else {
+            children.push(charElem);
+        }
+        children.push(...this.renderElements(grouped[DomType.MmlBase].children));
+        return this.createElementNS(ns.mathML, "mrow", null, children);
+    }
+    renderMmlPreSubSuper(elem) {
+        const children = [];
+        const grouped = keyBy(elem.children, x => x.type);
+        const sup = grouped[DomType.MmlSuperArgument];
+        const sub = grouped[DomType.MmlSubArgument];
+        const supElem = sup ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sup))) : null;
+        const subElem = sub ? this.createElementNS(ns.mathML, "mo", null, asArray(this.renderElement(sub))) : null;
+        const stubElem = this.createElementNS(ns.mathML, "mo", null);
+        children.push(this.createElementNS(ns.mathML, "msubsup", null, [stubElem, subElem, supElem]));
+        children.push(...this.renderElements(grouped[DomType.MmlBase].children));
+        return this.createElementNS(ns.mathML, "mrow", null, children);
+    }
+    renderMmlGroupChar(elem) {
+        const tagName = elem.props.verticalJustification === "bot" ? "mover" : "munder";
+        const result = this.renderContainerNS(elem, ns.mathML, tagName);
+        if (elem.props.char) {
+            result.appendChild(this.createElementNS(ns.mathML, "mo", null, [elem.props.char]));
+        }
+        return result;
+    }
+    renderMmlBar(elem) {
+        const result = this.renderContainerNS(elem, ns.mathML, "mrow");
+        switch (elem.props.position) {
+            case "top":
+                result.style.textDecoration = "overline";
+                break;
+            case "bottom":
+                result.style.textDecoration = "underline";
+                break;
+        }
+        return result;
+    }
+    renderMmlRun(elem) {
+        const result = this.createElementNS(ns.mathML, "ms", null, this.renderElements(elem.children));
+        this.renderClass(elem, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        return result;
+    }
+    renderMllList(elem) {
+        const result = this.createElementNS(ns.mathML, "mtable");
+        this.renderClass(elem, result);
+        this.renderStyleValues(elem.cssStyle, result);
+        for (let child of this.renderElements(elem.children)) {
+            result.appendChild(this.createElementNS(ns.mathML, "mtr", null, [
+                this.createElementNS(ns.mathML, "mtd", null, [child])
+            ]));
+        }
+        return result;
+    }
+    renderStyleValues(style, ouput) {
+        for (let k in style) {
+            if (k.startsWith("$")) {
+                ouput.setAttribute(k.slice(1), style[k]);
+            }
+            else {
+                ouput.style[k] = style[k];
+            }
+        }
+    }
+    renderClass(input, ouput) {
+        if (input.className)
+            ouput.className = input.className;
+        if (input.styleName)
+            ouput.classList.add(this.processStyleName(input.styleName));
+    }
+    findStyle(styleName) {
+        return styleName && this.styleMap?.[styleName];
+    }
+    numberingClass(id, lvl) {
+        return `${this.className}-num-${id}-${lvl}`;
+    }
+    tabStopClass() {
+        return `${this.className}-tab-stop`;
+    }
+    styleToString(selectors, values, cssText = null) {
+        let result = `${selectors} {\r\n`;
+        for (const key in values) {
+            if (key.startsWith('$'))
+                continue;
+            result += `  ${key}: ${values[key]};\r\n`;
+        }
+        if (cssText)
+            result += cssText;
+        return result + "}\r\n";
+    }
+    numberingCounter(id, lvl) {
+        return `${this.className}-num-${id}-${lvl}`;
+    }
+    levelTextToContent(text, suff, id, numformat) {
+        const suffMap = {
+            "tab": "\\9",
+            "space": "\\a0",
+        };
+        var result = text.replace(/%\d*/g, s => {
+            let lvl = parseInt(s.substring(1), 10) - 1;
+            return `"counter(${this.numberingCounter(id, lvl)}, ${numformat})"`;
+        });
+        return `"${result}${suffMap[suff] ?? ""}"`;
+    }
+    numFormatToCssValue(format) {
+        var mapping = {
+            none: "none",
+            bullet: "disc",
+            decimal: "decimal",
+            lowerLetter: "lower-alpha",
+            upperLetter: "upper-alpha",
+            lowerRoman: "lower-roman",
+            upperRoman: "upper-roman",
+            decimalZero: "decimal-leading-zero",
+            aiueo: "katakana",
+            aiueoFullWidth: "katakana",
+            chineseCounting: "simp-chinese-informal",
+            chineseCountingThousand: "simp-chinese-informal",
+            chineseLegalSimplified: "simp-chinese-formal",
+            chosung: "hangul-consonant",
+            ideographDigital: "cjk-ideographic",
+            ideographTraditional: "cjk-heavenly-stem",
+            ideographLegalTraditional: "trad-chinese-formal",
+            ideographZodiac: "cjk-earthly-branch",
+            iroha: "katakana-iroha",
+            irohaFullWidth: "katakana-iroha",
+            japaneseCounting: "japanese-informal",
+            japaneseDigitalTenThousand: "cjk-decimal",
+            japaneseLegal: "japanese-formal",
+            thaiNumbers: "thai",
+            koreanCounting: "korean-hangul-formal",
+            koreanDigital: "korean-hangul-formal",
+            koreanDigital2: "korean-hanja-informal",
+            hebrew1: "hebrew",
+            hebrew2: "hebrew",
+            hindiNumbers: "devanagari",
+            ganada: "hangul",
+            taiwaneseCounting: "cjk-ideographic",
+            taiwaneseCountingThousand: "cjk-ideographic",
+            taiwaneseDigital: "cjk-decimal",
+        };
+        return mapping[format] ?? format;
+    }
+    refreshTabStops() {
+        if (!this.options.experimental)
+            return;
+        setTimeout(() => {
+            const pixelToPoint = computePixelToPoint();
+            for (let tab of this.currentTabs) {
+                updateTabStop(tab.span, tab.stops, this.defaultTabSize, pixelToPoint);
+            }
+        }, 500);
+    }
+    createElementNS(ns, tagName, props, children) {
+        var result = ns ? this.htmlDocument.createElementNS(ns, tagName) : this.htmlDocument.createElement(tagName);
+        Object.assign(result, props);
+        children && appendChildren(result, children);
+        return result;
+    }
+    createElement(tagName, props, children) {
+        return this.createElementNS(undefined, tagName, props, children);
+    }
+    createSvgElement(tagName, props, children) {
+        return this.createElementNS(ns.svg, tagName, props, children);
+    }
+    createStyleElement(cssText) {
+        return this.createElement("style", { innerHTML: cssText });
+    }
+    createComment(text) {
+        return this.htmlDocument.createComment(text);
+    }
+    later(func) {
+        this.postRenderTasks.push(func);
+    }
+}
+function removeAllElements(elem) {
+    elem.innerHTML = '';
+}
+function appendChildren(elem, children) {
+    children.forEach(c => elem.appendChild(isString(c) ? document.createTextNode(c) : c));
+}
+function findParent(elem, type) {
+    var parent = elem.parent;
+    while (parent != null && parent.type != type)
+        parent = parent.parent;
+    return parent;
+}
+
+const defaultOptions = {
+    ignoreHeight: false,
+    ignoreWidth: false,
+    ignoreFonts: false,
+    breakPages: true,
+    debug: false,
+    experimental: false,
+    className: "docx",
+    inWrapper: true,
+    trimXmlDeclaration: true,
+    ignoreLastRenderedPageBreak: true,
+    renderHeaders: true,
+    renderFooters: true,
+    renderFootnotes: true,
+    renderEndnotes: true,
+    useBase64URL: false,
+    renderChanges: false,
+    renderComments: false
+};
+function parseAsync(data, userOptions) {
+    const ops = { ...defaultOptions, ...userOptions };
+    return WordDocument.load(data, new DocumentParser(ops), ops);
+}
+async function renderDocument(document, bodyContainer, styleContainer, userOptions) {
+    const ops = { ...defaultOptions, ...userOptions };
+    const renderer = new HtmlRenderer(window.document);
+    return await renderer.render(document, bodyContainer, styleContainer, ops);
+}
+async function renderAsync(data, bodyContainer, styleContainer, userOptions) {
+    const doc = await parseAsync(data, userOptions);
+    await renderDocument(doc, bodyContainer, styleContainer, userOptions);
+    return doc;
+}
+
+export { defaultOptions, parseAsync, renderAsync, renderDocument };
+//# sourceMappingURL=docx-preview.mjs.map

File diff suppressed because it is too large
+ 0 - 0
src/3rd-libs/docx-preview/docx-preview.mjs.map


+ 14 - 0
src/3rd-libs/filesize.js

@@ -0,0 +1,14 @@
+/**
+ * https://www.npmjs.com/package/filesize
+ * https://github.com/avoidwork/filesize.js
+ */
+
+import { filesize } from 'filesize';
+
+/**
+ * 获取一个文件的尺寸 B/Kb/Mb/Gb/Tb/
+ * @param {number} value
+ */
+export default function getFileSize(value) {
+  return filesize(value, { standard: 'jedec' });
+}

+ 4 - 0
src/3rd-libs/highlight.js

@@ -0,0 +1,4 @@
+import hljs from 'highlight.js';
+import 'highlight.js/styles/monokai.css';
+
+export default hljs;

+ 7 - 0
src/3rd-libs/js-cookie.js

@@ -0,0 +1,7 @@
+/**
+ * @see https://www.npmjs.com/package/js-cookie
+ */
+
+import Cookies from 'js-cookie';
+
+export default Cookies;

+ 6 - 0
src/3rd-libs/jsencrypt.js

@@ -0,0 +1,6 @@
+/**
+ * @see https://www.npmjs.com/package/jsdecrypt
+ * */
+import JSEncrypt from 'jsencrypt/bin/jsencrypt.min';
+
+export default JSEncrypt;

+ 8 - 0
src/3rd-libs/marked.js

@@ -0,0 +1,8 @@
+import { Marked } from 'marked';
+
+const marked = new Marked();
+marked.setOptions({
+  breaks: true,
+  // pedantic: true  // 宽松模式(效果有限)
+});
+export default marked;

+ 3 - 0
src/3rd-libs/microsoft-feat-event-source.js

@@ -0,0 +1,3 @@
+import { fetchEventSource } from '@microsoft/fetch-event-source';
+
+export default fetchEventSource;

+ 7 - 0
src/3rd-libs/mitt.js

@@ -0,0 +1,7 @@
+/**
+ * 事件总线。
+ * @see https://www.npmjs.com/package/mitt
+ */
+import mitt from 'mitt';
+
+export default mitt;

+ 49 - 0
src/3rd-libs/screenfull.js

@@ -0,0 +1,49 @@
+import screenfull from 'screenfull';
+
+/**
+ * 申请全屏
+ * @see https://www.npmjs.com/package/screenfull#screenfull-1
+ */
+export const requestScreenFull = () => {
+  if (screenfull.isEnabled) {
+    screenfull.request();
+  }
+};
+
+/**
+ * 将一个DOM元素全屏
+ * @param {DOMElement} element
+ */
+export const requestElementScreenFull = (element) => {
+  if (screenfull.isEnabled) {
+    screenfull.request(element);
+  }
+};
+
+/**
+ * 全屏切换方法
+ */
+export const toggleScreenFull = () => {
+  if (screenfull.isEnabled) {
+    screenfull.toggle();
+  }
+};
+
+/**
+ * 监听全屏事件
+ * @param {function} fn - 事件发生时的回调函数
+ * @returns
+ */
+export const onScreenFullChange = (fn) => {
+  if (screenfull.isEnabled) {
+    screenfull.on('change', () => {
+      if (typeof fn === 'function') {
+        fn(screenfull.isFullscreen);
+      }
+    });
+  }
+
+  return () => {
+    screenfull.off('change', fn);
+  };
+};

+ 11 - 0
src/App.vue

@@ -0,0 +1,11 @@
+<template>
+  <router-view />
+</template>
+<script setup>
+import { onMounted } from 'vue';
+// import DevicePixelRatio from './utils/devicePixelRatio'
+
+onMounted(() => {
+  // new DevicePixelRatio().init()
+})
+</script>

BIN
src/assets/Green.png


BIN
src/assets/agent/agent_bg.png


+ 31 - 0
src/assets/agent/agent_icon_1.svg

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="93px" height="92px" viewBox="0 0 93 92" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>智库问答- icon</title>
+    <defs>
+        <filter x="-37.5%" y="-277.7%" width="175.0%" height="655.4%" filterUnits="objectBoundingBox" id="filter-1">
+            <feGaussianBlur stdDeviation="6" in="SourceGraphic"></feGaussianBlur>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.7416036%" id="linearGradient-2">
+            <stop stop-color="#255FDE" offset="0%"></stop>
+            <stop stop-color="#84A8EB" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.7416036%" id="linearGradient-3">
+            <stop stop-color="#96B3F0" stop-opacity="0.6" offset="0%"></stop>
+            <stop stop-color="#DEE8FA" stop-opacity="0.6" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="首页" transform="translate(-482.000000, -508.000000)">
+            <g id="智库问答--icon" transform="translate(482.000000, 508.000000)">
+                <rect id="矩形" x="0" y="0" width="92" height="92"></rect>
+                <g id="编组-7" transform="translate(10.000000, 7.000000)">
+                    <ellipse id="椭圆形" fill="#2660DE" opacity="0.6" filter="url(#filter-1)" cx="40.8911995" cy="61.2409333" rx="24" ry="3.24093329"></ellipse>
+                    <path d="M18,0 L63,0 C67.418278,-8.11624501e-16 71,3.581722 71,8 L71,38 C71,42.418278 67.418278,46 63,46 L38.4111226,46 C38.0625261,46 37.7199834,46.0911139 37.4174554,46.2643084 L26.5705417,52.4740651 C25.6119457,53.0228523 24.3899701,52.6906367 23.8411828,51.7320407 C23.6679884,51.4295127 23.5768745,51.08697 23.5768745,50.7383735 L23.5768745,48 C23.5768745,46.8954305 22.681444,46 21.5768745,46 L16.7884372,46 C13.0392869,46 10,42.9607131 10,39.2115628 L10,8 C10,3.581722 13.581722,8.11624501e-16 18,0 Z" id="矩形" fill="url(#linearGradient-2)"></path>
+                    <path d="M53,8.5 C55.0710678,8.5 56.9460678,9.33946609 58.3033009,10.6966991 C59.6605339,12.0539322 60.5,13.9289322 60.5,16 L60.5,16 L60.5,46 C60.5,48.0710678 59.6605339,49.9460678 58.3033009,51.3033009 C56.9460678,52.6605339 55.0710678,53.5 53,53.5 L53,53.5 L28.4111226,53.5 C27.975377,53.5 27.5471986,53.6138924 27.1690386,53.8303855 L27.1690386,53.8303855 L16.3221249,60.0401422 C15.9626514,60.2459374 15.5537942,60.2865446 15.1833566,60.1858346 C14.812919,60.0851246 14.480901,59.8430974 14.2751057,59.4836239 C14.1452099,59.2567279 14.0768745,58.9998208 14.0768745,58.7383735 L14.0768745,58.7383735 L14.0768745,56 C14.0768745,55.3096441 13.7970524,54.6846441 13.3446414,54.232233 C12.8922304,53.779822 12.2672304,53.5 11.5768745,53.5 L11.5768745,53.5 L6.78843723,53.5 C5.05193324,53.5 3.47982393,52.7961427 2.34184062,51.6581594 C1.20385731,50.5201761 0.5,48.9480668 0.5,47.2115628 L0.5,47.2115628 L0.5,16 C0.5,13.9289322 1.33946609,12.0539322 2.69669914,10.6966991 C4.05393219,9.33946609 5.92893219,8.5 8,8.5 L8,8.5 Z" id="矩形备份-8" stroke="#FFFFFF" fill="url(#linearGradient-3)"></path>
+                    <rect id="矩形" fill="#FFFFFF" x="12" y="20" width="37" height="5" rx="2.5"></rect>
+                    <rect id="矩形备份-7" fill="#FFFFFF" x="12" y="34" width="37" height="5" rx="2.5"></rect>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 39 - 0
src/assets/agent/agent_icon_2.svg

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="92px" height="92px" viewBox="0 0 92 92" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>报告自动生成- icon</title>
+    <defs>
+        <filter x="-46.3%" y="-277.7%" width="192.6%" height="655.4%" filterUnits="objectBoundingBox" id="filter-1">
+            <feGaussianBlur stdDeviation="6" in="SourceGraphic"></feGaussianBlur>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
+            <stop stop-color="#0A817E" offset="0%"></stop>
+            <stop stop-color="#7FB8B4" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="1.53987612%" x2="50%" y2="99.3499542%" id="linearGradient-3">
+            <stop stop-color="#92E3E3" stop-opacity="0.6" offset="0%"></stop>
+            <stop stop-color="#E5F1F0" stop-opacity="0.6" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="首页" transform="translate(-914.000000, -508.000000)">
+            <g id="报告自动生成--icon" transform="translate(914.000000, 508.000000)">
+                <rect id="矩形备份-9" x="0" y="0" width="92" height="92"></rect>
+                <g id="编组-4" transform="translate(5.661699, 5.247486)">
+                    <ellipse id="椭圆形" fill="#0E8380" opacity="0.6" filter="url(#filter-1)" cx="40.3369809" cy="63.3103712" rx="19.4455998" ry="3.24093329"></ellipse>
+                    <g id="编组-3" transform="translate(29.712420, 31.681635) rotate(-15.000000) translate(-29.712420, -31.681635) translate(6.040847, 5.225172)">
+                        <rect id="矩形" fill="url(#linearGradient-2)" x="0" y="0" width="47.3431452" height="52.912927" rx="8"></rect>
+                        <rect id="矩形" fill="#FFFFFF" x="8.35467268" y="9.74711813" width="18.1017908" height="8.35467268" rx="2"></rect>
+                        <rect id="矩形" fill="#FFFFFF" x="8.35467268" y="23.6715726" width="30.6337998" height="4.17733634" rx="2"></rect>
+                        <rect id="矩形备份-6" fill="#FFFFFF" x="8.35467268" y="33.4186907" width="15.3168999" height="4.17733634" rx="2"></rect>
+                    </g>
+                    <g id="编组-2" transform="translate(56.657757, 38.163502) rotate(-345.000000) translate(-56.657757, -38.163502) translate(37.019613, 18.525357)">
+                        <rect id="蒙版" stroke="#FFFFFF" fill="url(#linearGradient-3)" x="0.5" y="0.5" width="38.2762883" height="38.2762883" rx="8"></rect>
+                        <g id="A" transform="translate(9.428541, 8.926429)" fill="#FFFFFF" fill-rule="nonzero">
+                            <path d="M0,21.4792202 L4.89558849,4.93743113 C5.3047165,3.5612733 5.84402159,2.46871557 6.51350378,1.65975792 C7.41544506,0.553252641 8.63353071,0 10.1677607,0 C11.6926924,0 12.8689354,0.432373913 13.6964897,1.29712174 C14.3473752,1.98520065 14.8401885,2.8685452 15.1749296,3.9471554 L20.502892,21.4931677 L17.0299531,21.4931677 L14.9796639,14.9378213 L5.56507068,14.9378213 L3.37530603,21.4931677 L0,21.4792202 Z M6.29034305,11.8554137 L14.1009686,11.8554137 L12.0506794,5.00716886 C11.9298006,4.60733922 11.7019907,4.21215876 11.3672496,3.82162748 C11.069702,3.47758803 10.6931183,3.3055683 10.2374984,3.3055683 C9.7353868,3.3055683 9.30766207,3.52407985 8.95432425,3.96110294 C8.68467171,4.27724731 8.49405525,4.62593595 8.38247488,5.00716886 L6.29034305,11.8554137 Z" id="形状"></path>
+                        </g>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 36 - 0
src/assets/agent/agent_icon_3.svg

@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="92px" height="92px" viewBox="0 0 92 92" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>智能问数- icon</title>
+    <defs>
+        <filter x="-32.7%" y="-292.8%" width="165.4%" height="685.6%" filterUnits="objectBoundingBox" id="filter-1">
+            <feGaussianBlur stdDeviation="6" in="SourceGraphic"></feGaussianBlur>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
+            <stop stop-color="#6F35CA" offset="0%"></stop>
+            <stop stop-color="#A7A3DF" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-3">
+            <stop stop-color="#CAB5EC" stop-opacity="0.6" offset="0%"></stop>
+            <stop stop-color="#E0DEF9" stop-opacity="0.6" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="首页" transform="translate(-1346.000000, -508.000000)">
+            <g id="智能问数--icon" transform="translate(1346.000000, 508.000000)">
+                <rect id="矩形" x="0" y="0" width="92" height="92"></rect>
+                <g id="编组-11" transform="translate(8.774005, 7.161974)">
+                    <ellipse id="椭圆形" fill="#7036CA" opacity="0.6" filter="url(#filter-1)" cx="37.2053668" cy="58.8811176" rx="27.5061379" ry="3.07398476"></ellipse>
+                    <g id="编组-13" transform="translate(26.772004, 29.249482) rotate(-7.000000) translate(-26.772004, -29.249482) translate(3.059816, 2.691832)">
+                        <rect id="矩形" fill="url(#linearGradient-2)" x="0" y="0" width="47.4243757" height="53.1153007" rx="8"></rect>
+                        <rect id="矩形" fill="#FFFFFF" x="6.63941259" y="12.3303377" width="32.2485755" height="4.74243757" rx="2.37121878"></rect>
+                        <rect id="矩形备份-7" fill="#FFFFFF" x="6.63941259" y="25.6091629" width="19.9182378" height="4.74243757" rx="2.37121878"></rect>
+                    </g>
+                    <g id="编组-14" transform="translate(54.278142, 35.888895) rotate(7.000000) translate(-54.278142, -35.888895) translate(37.205367, 15.970657)" stroke="#FFFFFF">
+                        <rect id="矩形" fill="url(#linearGradient-3)" x="0.5" y="0.5" width="33.1455505" height="38.8364756" rx="8"></rect>
+                        <polyline id="路径-9" stroke-width="5" stroke-linecap="round" stroke-linejoin="round" points="8.41080021 24.4036021 13.2788252 19.1653028 19.4811838 21.4709174 23.8622896 15.9383599"></polyline>
+                    </g>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 32 - 0
src/assets/agent/agent_icon_4.svg

@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="84px" height="81px" viewBox="0 0 84 81" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>智库问答- icon备份 4</title>
+    <defs>
+        <filter x="-43.1%" y="-319.4%" width="186.2%" height="738.7%" filterUnits="objectBoundingBox" id="filter-1">
+            <feGaussianBlur stdDeviation="6" in="SourceGraphic"></feGaussianBlur>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="98.6697349%" id="linearGradient-2">
+            <stop stop-color="#E5612C" offset="0%"></stop>
+            <stop stop-color="#EFC781" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="99.7416036%" id="linearGradient-3">
+            <stop stop-color="#EFC781" stop-opacity="0.6" offset="0%"></stop>
+            <stop stop-color="#FDF5E7" stop-opacity="0.6" offset="100%"></stop>
+        </linearGradient>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="首页" transform="translate(-1430.000000, -561.000000)">
+            <g id="智库问答--icon备份-4" transform="translate(1430.000000, 561.000000)">
+                <rect id="矩形" x="0" y="0" width="80" height="80"></rect>
+                <g id="编组-7" transform="translate(12.173913, 5.217391)">
+                    <ellipse id="椭圆形" fill="#E5612C" opacity="0.6" filter="url(#filter-1)" cx="32.0793039" cy="54.1225507" rx="20.8695652" ry="2.81820287"></ellipse>
+                    <path d="M18.4347826,9.56521739 L45.9130435,9.56521739 C50.3313215,9.56521739 53.9130435,13.1469394 53.9130435,17.5652174 L53.9130435,45.0434783 C53.9130435,49.4617563 50.3313215,53.0434783 45.9130435,53.0434783 L18.4347826,53.0434783 C14.0165046,53.0434783 10.4347826,49.4617563 10.4347826,45.0434783 L10.4347826,17.5652174 C10.4347826,13.1469394 14.0165046,9.56521739 18.4347826,9.56521739 Z" id="矩形" fill="url(#linearGradient-2)"></path>
+                    <path d="M35.4782609,0.5 C37.5493287,0.5 39.4243287,1.33946609 40.7815617,2.69669914 C42.1387948,4.05393219 42.9782609,5.92893219 42.9782609,8 L42.9782609,8 L42.9782609,35.4782609 C42.9782609,37.5493287 42.1387948,39.4243287 40.7815617,40.7815617 C39.4243287,42.1387948 37.5493287,42.9782609 35.4782609,42.9782609 L35.4782609,42.9782609 L8,42.9782609 C5.92893219,42.9782609 4.05393219,42.1387948 2.69669914,40.7815617 C1.33946609,39.4243287 0.5,37.5493287 0.5,35.4782609 L0.5,35.4782609 L0.5,8 C0.5,5.92893219 1.33946609,4.05393219 2.69669914,2.69669914 C4.05393219,1.33946609 5.92893219,0.5 8,0.5 L8,0.5 Z" id="矩形备份-8" stroke="#FFFFFF" fill="url(#linearGradient-3)"></path>
+                    <path d="M10.6521739,29.5652174 L18.9130435,29.5652174 C19.9936006,29.5652174 20.8695652,30.441182 20.8695652,31.5217391 C20.8695652,32.6022962 19.9936006,33.4782609 18.9130435,33.4782609 L10.6521739,33.4782609 C9.57161679,33.4782609 8.69565217,32.6022962 8.69565217,31.5217391 C8.69565217,30.441182 9.57161679,29.5652174 10.6521739,29.5652174 Z" id="矩形备份-7" fill="#FFFFFF" transform="translate(14.782609, 31.521739) rotate(-270.000000) translate(-14.782609, -31.521739) "></path>
+                    <path d="M15.8695652,25.2173913 L32.826087,25.2173913 C33.9066441,25.2173913 34.7826087,26.0933559 34.7826087,27.173913 C34.7826087,28.2544702 33.9066441,29.1304348 32.826087,29.1304348 L15.8695652,29.1304348 C14.7890081,29.1304348 13.9130435,28.2544702 13.9130435,27.173913 C13.9130435,26.0933559 14.7890081,25.2173913 15.8695652,25.2173913 Z" id="矩形备份-11" fill="#FFFFFF" transform="translate(24.347826, 27.173913) rotate(-270.000000) translate(-24.347826, -27.173913) "></path>
+                    <rect id="矩形备份-12" fill="#FFFFFF" transform="translate(33.913043, 29.782609) rotate(-270.000000) translate(-33.913043, -29.782609) " x="26.0869565" y="27.826087" width="15.6521739" height="3.91304348" rx="1.95652174"></rect>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

BIN
src/assets/agent/icon_1.png


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_1.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_10.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_11.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_12.svg


BIN
src/assets/agent/icon_13.png


BIN
src/assets/agent/icon_13.svg


BIN
src/assets/agent/icon_14.png


BIN
src/assets/agent/icon_15.png


BIN
src/assets/agent/icon_16.png


BIN
src/assets/agent/icon_17.png


BIN
src/assets/agent/icon_18.png


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_2.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_3.svg


BIN
src/assets/agent/icon_4.png


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_4.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_5.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_6.svg


BIN
src/assets/agent/icon_7.png


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_7.svg


File diff suppressed because it is too large
+ 2 - 0
src/assets/agent/icon_8.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent/icon_9.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/agent_center.svg


+ 64 - 0
src/assets/ai-editor/document.svg

@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="34px" height="31px" viewBox="0 0 34 31" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>文档- icon</title>
+    <defs>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
+            <stop stop-color="#1EA6A3" offset="0%"></stop>
+            <stop stop-color="#0A817E" offset="100%"></stop>
+        </linearGradient>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-2">
+            <stop stop-color="#53C0BD" offset="0%"></stop>
+            <stop stop-color="#0A817E" offset="100%"></stop>
+        </linearGradient>
+        <path d="M0,8 C5,9.02532895 10,9.53799342 15,9.53799342 C20,9.53799342 25,9.02532895 30,8 L30,22 C30,26.418278 26.418278,30 22,30 L8,30 C3.581722,30 5.41083001e-16,26.418278 0,22 L0,8 L0,8 Z" id="path-3"></path>
+        <filter x="-11.7%" y="-20.5%" width="123.3%" height="131.8%" filterUnits="objectBoundingBox" id="filter-4">
+            <feOffset dx="0" dy="-1" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feGaussianBlur stdDeviation="1" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0.381079632   0 0 0 0 0.371391167  0 0 0 0.3 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="98.7682849%" id="linearGradient-5">
+            <stop stop-color="#AAEAE8" offset="0%"></stop>
+            <stop stop-color="#EAFCFB" offset="100%"></stop>
+        </linearGradient>
+        <circle id="path-6" cx="15" cy="15" r="3"></circle>
+        <filter x="0.0%" y="0.0%" width="100.0%" height="100.0%" filterUnits="objectBoundingBox" id="filter-7">
+            <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetInner1"></feOffset>
+            <feComposite in="shadowOffsetInner1" in2="SourceAlpha" operator="arithmetic" k2="-1" k3="1" result="shadowInnerInner1"></feComposite>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0   0 0 0 0 0  0 0 0 0.5 0" type="matrix" in="shadowInnerInner1"></feColorMatrix>
+        </filter>
+        <linearGradient x1="50%" y1="0%" x2="50%" y2="98.7682849%" id="linearGradient-8">
+            <stop stop-color="#FFFFFF" offset="0%"></stop>
+            <stop stop-color="#BEEEED" offset="100%"></stop>
+        </linearGradient>
+        <circle id="path-9" cx="15" cy="15" r="3"></circle>
+        <filter x="-25.0%" y="-25.0%" width="150.0%" height="150.0%" filterUnits="objectBoundingBox" id="filter-10">
+            <feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter1"></feOffset>
+            <feMorphology radius="1" operator="erode" in="SourceAlpha" result="shadowInner"></feMorphology>
+            <feOffset dx="0" dy="0" in="shadowInner" result="shadowInner"></feOffset>
+            <feComposite in="shadowOffsetOuter1" in2="shadowInner" operator="out" result="shadowOffsetOuter1"></feComposite>
+            <feGaussianBlur stdDeviation="0.5" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
+            <feColorMatrix values="0 0 0 0 0   0 0 0 0 0.380392157   0 0 0 0 0.37254902  0 0 0 0.5 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
+        </filter>
+    </defs>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板" transform="translate(-128.000000, -402.000000)">
+            <g id="文档--icon" transform="translate(130.000000, 402.000000)">
+                <rect id="矩形" fill="url(#linearGradient-1)" x="0" y="0" width="30" height="30" rx="8"></rect>
+                <rect id="矩形" fill="#FFFFFF" opacity="0.5" x="5" y="3" width="20" height="18" rx="4"></rect>
+                <rect id="矩形" fill="#FFFFFF" x="3" y="5" width="24" height="18" rx="4"></rect>
+                <g id="矩形">
+                    <use fill="black" fill-opacity="1" filter="url(#filter-4)" xlink:href="#path-3"></use>
+                    <use fill="url(#linearGradient-2)" fill-rule="evenodd" xlink:href="#path-3"></use>
+                </g>
+                <g id="椭圆形">
+                    <use fill="black" fill-opacity="1" filter="url(#filter-7)" xlink:href="#path-6"></use>
+                    <circle stroke="url(#linearGradient-5)" stroke-width="1.6" stroke-linejoin="square" cx="15" cy="15" r="2.2"></circle>
+                </g>
+                <g id="椭圆形">
+                    <use fill="black" fill-opacity="1" filter="url(#filter-10)" xlink:href="#path-9"></use>
+                    <circle stroke="url(#linearGradient-8)" stroke-width="0.8" stroke-linejoin="square" cx="15" cy="15" r="2.6"></circle>
+                </g>
+            </g>
+        </g>
+    </g>
+</svg>

+ 13 - 0
src/assets/ai-editor/rewrite.svg

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>改写- icon</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板" transform="translate(-176.000000, -458.000000)">
+            <g id="改写--icon" transform="translate(176.000000, 458.000000)">
+                <rect id="矩形" x="0" y="0" width="24" height="24"></rect>
+                <path d="M9,5.5 C9.41421356,5.5 9.78921356,5.66789322 10.0606602,5.93933983 C10.3321068,6.21078644 10.5,6.58578644 10.5,7 L10.5,7 L10.5,16.9001807 C10.1174549,17.8157299 9.77327242,18.5073816 9.46309356,18.9726499 C9.28750349,19.236035 9.15816091,19.5 9,19.5 C8.8539769,19.5 8.73587184,19.262132 8.57573967,19.0299364 C8.28446284,18.6075779 7.96271768,17.9801438 7.60599699,17.1502847 L7.60599699,17.1502847 L7.5,7 C7.5,6.58578644 7.66789322,6.21078644 7.93933983,5.93933983 C8.21078644,5.66789322 8.58578644,5.5 9,5.5 Z" id="矩形" stroke="#2C2C2C" transform="translate(9.000000, 12.500000) rotate(-345.000000) translate(-9.000000, -12.500000) "></path>
+                <line x1="11.1137985" y1="19.158502" x2="18.3429152" y2="19.158502" id="路径-42" stroke="#2C2C2C"></line>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/ai-editor/shorten.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>缩写- icon</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板" transform="translate(-368.000000, -458.000000)">
+            <g id="缩写--icon" transform="translate(368.000000, 458.000000)">
+                <rect id="矩形" x="0" y="0" width="24" height="24"></rect>
+                <path d="M12,5 C12.4142136,5 12.7892136,5.16789322 13.0606602,5.43933983 C13.3321068,5.71078644 13.5,6.08578644 13.5,6.5 L13.5,6.5 L13.5,16.4001807 C13.1174549,17.3157299 12.7732724,18.0073816 12.4630936,18.4726499 C12.2875035,18.736035 12.1581609,19 12,19 C11.8539769,19 11.7358718,18.762132 11.5757397,18.5299364 C11.2844628,18.1075779 10.9627177,17.4801438 10.605997,16.6502847 L10.605997,16.6502847 L10.5,6.5 C10.5,6.08578644 10.6678932,5.71078644 10.9393398,5.43933983 C11.2107864,5.16789322 11.5857864,5 12,5 Z" id="矩形" stroke="#2C2C2C"></path>
+                <path d="M8,9 L5,12 L8,15" id="路径-3" stroke="#2C2C2C" transform="translate(6.500000, 12.000000) scale(-1, 1) translate(-6.500000, -12.000000) "></path>
+                <path d="M19,9 L16,12 L19,15" id="路径-3备份" stroke="#2C2C2C"></path>
+            </g>
+        </g>
+    </g>
+</svg>

+ 12 - 0
src/assets/ai-editor/submit-ing.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="48px" height="48px" viewBox="0 0 48 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>暂停- icon</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="方案一#0A817E" transform="translate(-1567.000000, -952.000000)">
+            <g id="暂停--icon" transform="translate(1567.000000, 952.000000)">
+                <circle id="椭圆形" fill="#0A817E" cx="24" cy="24" r="24"></circle>
+                <rect id="矩形" fill="#FFFFFF" x="15" y="15" width="18" height="18" rx="4"></rect>
+            </g>
+        </g>
+    </g>
+</svg>

+ 13 - 0
src/assets/ai-editor/submit-normal.svg

@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="30px" height="30px" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>发送-不可点击- icon备份 2</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板" transform="translate(-712.000000, -535.000000)">
+            <g id="发送-不可点击--icon备份-2" transform="translate(727.000000, 550.000000) rotate(-270.000000) translate(-727.000000, -550.000000) translate(712.000000, 535.000000)">
+                <circle id="椭圆形" fill="#0A817E" cx="15" cy="15" r="15"></circle>
+                <line x1="15" y1="21.875" x2="15" y2="9.375" id="路径-20" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round"></line>
+                <polyline id="路径-21" stroke="#FFFFFF" stroke-width="3" stroke-linecap="round" stroke-linejoin="round" points="8.75 13.75 15 8.125 21.25 13.75"></polyline>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/assets/ai-editor/winden.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>扩写- icon</title>
+    <g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="画板" transform="translate(-272.000000, -458.000000)">
+            <g id="扩写--icon" transform="translate(272.000000, 458.000000)">
+                <rect id="矩形" x="0" y="0" width="24" height="24"></rect>
+                <path d="M12,5 C12.4142136,5 12.7892136,5.16789322 13.0606602,5.43933983 C13.3321068,5.71078644 13.5,6.08578644 13.5,6.5 L13.5,6.5 L13.5,16.4001807 C13.1174549,17.3157299 12.7732724,18.0073816 12.4630936,18.4726499 C12.2875035,18.736035 12.1581609,19 12,19 C11.8539769,19 11.7358718,18.762132 11.5757397,18.5299364 C11.2844628,18.1075779 10.9627177,17.4801438 10.605997,16.6502847 L10.605997,16.6502847 L10.5,6.5 C10.5,6.08578644 10.6678932,5.71078644 10.9393398,5.43933983 C11.2107864,5.16789322 11.5857864,5 12,5 Z" id="矩形" stroke="#2C2C2C"></path>
+                <path d="M8,9 L5,12 L8,15" id="路径-3" stroke="#2C2C2C"></path>
+                <path d="M19,9 L16,12 L19,15" id="路径-3备份" stroke="#2C2C2C" transform="translate(17.500000, 12.000000) scale(-1, 1) translate(-17.500000, -12.000000) "></path>
+            </g>
+        </g>
+    </g>
+</svg>

BIN
src/assets/android_link.png


File diff suppressed because it is too large
+ 0 - 0
src/assets/android_link.svg


+ 1 - 0
src/assets/bg/bg-aside.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="26" height="934" viewBox="0 0 26 934"><defs><linearGradient x1="1" y1="0.44493260979652405" x2="0" y2="0.44493260979652405" id="master_svg0_0_1822"><stop offset="0%" stop-color="#0A817E" stop-opacity="0"/><stop offset="100%" stop-color="#0A817E" stop-opacity="0.05999999865889549"/></linearGradient></defs><g><path d="M0 0C0 0 0 0 0 0L26 0C26 0 26 0 26 0L26 934C26 934 26 934 26 934L0 934C0 934 0 934 0 934Z" fill="url(#master_svg0_0_1822)" fill-opacity="1"/></g></svg>

+ 1 - 0
src/assets/bg/bg-chat.svg

@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" fill="none" version="1.1" width="1458" height="934" viewBox="0 0 1458 934"><defs><linearGradient x1="0.5" y1="0.013911900110542774" x2="0.5" y2="0.9853787422180176" id="master_svg0_0_1813"><stop offset="0%" stop-color="#0A817E" stop-opacity="0"/><stop offset="100%" stop-color="#0A817E" stop-opacity="0.05999999865889549"/></linearGradient></defs><g><path d="M0 0C0 0 0 0 0 0L1438 0C1449.0456949966158 0 1458 8.954305003384134 1458 20L1458 914C1458 925.0456949966159 1449.0456949966158 934 1438 934L0 934C0 934 0 934 0 934Z" fill="url(#master_svg0_0_1813)" fill-opacity="1"/></g></svg>

File diff suppressed because it is too large
+ 0 - 0
src/assets/bg/bg-green.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/bg/bg-left-footer.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/bg/bg-right-footer.svg


File diff suppressed because it is too large
+ 0 - 0
src/assets/bg/vg-chat.svg


BIN
src/assets/chat-aside/aside-btn-expond.png


BIN
src/assets/chat-aside/aside-menu-bg-black-bottom.png


BIN
src/assets/chat-aside/aside-menu-bg-black-middle.png


BIN
src/assets/chat-aside/aside-menu-bg-black-top.png


Some files were not shown because too many files changed in this diff