diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..c519a2c --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,53 @@ +# Copilot Instructions + +## Build, test, and lint commands + +### Root project (Gradle / Java 21) + +```bash +./gradlew build +./gradlew test +./gradlew test --tests "run.halo.migrate.SomeTest" +./gradlew haloServer +./gradlew pnpmInstall +``` + +- `./gradlew build` also builds `ui/` and copies the frontend bundle into `build/resources/main/console/`. +- `./gradlew haloServer` starts a Halo Docker environment with the plugin loaded. + +### Frontend (`ui/`, pnpm / Node 24) + +```bash +cd ui +pnpm install +pnpm build +pnpm dev +pnpm lint +pnpm prettier +pnpm type-check +``` + +## High-level architecture + +- This repository is a Halo plugin with a **minimal Java backend** and a **browser-heavy Vue 3 frontend**. The root Gradle project packages the plugin; the `ui/` subproject contains the migration UI and most of the logic. +- The Java side is intentionally small: `MigratePlugin` is the plugin entry point, and `MigrationController` only exposes `POST /migrations/rss-parse` so the frontend can fetch remote RSS/Atom content without browser CORS issues. +- The frontend is registered through `ui/src/index.ts`, which adds the `/migrate` routes to Halo Console. The main user flow is: + 1. `SelectProviderView.vue` lets the user choose a source platform. + 2. A provider parser component in `ui/src/modules//` reads export files and converts them into a shared `MigrateData` shape. + 3. Attachment handling runs before import: most providers use `MigrateAttachmentHandler.vue`, Halo uses `HaloMigrateAttachmentHandler.vue`, and local media URL rewriting happens in `use-attachment-preprocessor.ts`. + 4. `use-migrate-task.ts` turns `MigrateData` into `MigrateTaskGroup[]`, and `MigrateView.vue` executes those tasks with `fastq` at concurrency `9`. +- `use-migrate-task.ts` maps each migrated content type directly to Halo APIs: tags/categories/comments/attachments use generated core clients, post/page imports use console draft APIs, and plugin resources without generated clients (moments, photos, links) go through `axiosInstance`. + +## Key conventions + +- **UnoCSS compile-class mode is enabled.** Inline utility classes in Vue templates use the `:uno:` prefix, for example `class=":uno: flex items-center gap-2"`. +- **New migration providers are registered centrally.** Add the provider entry in `ui/src/modules/index.ts`, then implement its parser UI under `ui/src/modules//`. +- **Provider parser components are write-only.** They should emit `update:data` with a `MigrateData` payload and expose `reset()` for `MigrateView.vue` to call. The shared extension docs in `docs/extend/provider.md` describe this contract. +- **Attachment handling is shared unless the provider is Typecho.** Most providers feed attachments through `MigrateAttachmentHandler.vue`; Typecho owns its own remote attachment migration flow inside `TypechoMigrateDataParser.vue`. +- **Attachment migration behavior depends on the selected strategy.** Local upload mode removes `LOCAL` attachments from the final attachment task list and rewrites referenced URLs after uploading files; manual mode only creates Halo attachment records with the selected storage policy. +- **Provider-specific attachment paths matter.** `providerItems` can set `options.attachmentFolderPath`; `use-migrate-task.ts` uses that to build local attachment annotations such as `migrate-from-1.x/...` and `migrate-from-wp/...`. +- **Keep API client usage consistent with existing code.** + - `coreApiClient`: tags, categories, comments, replies, attachments, menus, storage policies. + - `consoleApiClient`: draft post/page creation, current user lookup, plugin listing, console attachment upload. + - `axiosInstance`: moments, photos, and links endpoints that do not have generated client methods. +- **Do not change task queue concurrency casually.** Import execution in `MigrateView.vue` uses `fastq.promise(asyncWorker, 9)`, which is tuned for current Halo API behavior. diff --git a/.gitignore b/.gitignore index f3d1286..c50a68c 100755 --- a/.gitignore +++ b/.gitignore @@ -74,4 +74,4 @@ application-local.properties /workplace/ node_modules /docs/.vitepress/cache/ -/src/main/resources/console/ +/src/main/resources/console/ \ No newline at end of file diff --git a/README.md b/README.md index c18972e..ac2e27a 100644 --- a/README.md +++ b/README.md @@ -2,16 +2,23 @@ 支持从其他平台迁移数据到 Halo 的插件。 -![Screenshot](./docs/img/screenshot.png) +![Screenshot](./images/preview.png) 目前已支持以下平台: 1. Halo 1.5 / 1.6 -2. [WordPress](https://wordpress.org/) -3. RSS / Atom 订阅链接 -4. [Hugo](https://gohugo.io/) -5. [Ghost](https://ghost.org/) -6. [Typecho](https://github.com/typecho/typecho) +2. WordPress +3. Ghost +4. Typecho +5. RSS / Atom 订阅文件或订阅链接 +6. Markdown(适用于 Markdown + Front Matter 静态博客内容导入) + +## 功能概览 + +1. 每个 Provider 拥有独立的导入 UI 和数据转换逻辑,最终统一汇总为 Halo 导入任务。 +2. 大多数平台支持统一的附件处理流程:本地上传或手动迁移;Markdown 仅支持本地目录上传;RSS / Atom 会保留原始远程资源链接。 +3. 对包含邮箱的来源用户,导入时会优先匹配现有 Halo 用户;若不存在,则自动创建 `guest` 用户,并尽量保留文章、页面、评论的归属关系。 +4. Markdown 导入支持 YAML / TOML / JSON Front Matter,支持常见标题、摘要、分类、标签、发布时间、页面类型以及 `cover` / `thumbnail` / `feature_image` 等封面字段。 ## 使用方式 @@ -21,8 +28,18 @@ 2. 安装,插件安装和更新方式可参考: 3. 启动插件之后,即可在 Console 的左侧菜单栏看到 **迁移** 的菜单。 -> **Warning** -> 详细的迁移文档请查阅 +> [!NOTE] +> 详细的迁移文档请查阅 + +> [!TIP] +> 建议先在本地环境测试导入,确认无误后再考虑在生产环境执行。这样做的原因是: +> 1. 导入失败的因素较多,在本地更容易快速重试并定位原因。 +> 2. 导入过程会频繁请求后端并上传附件,在线上环境可能因为服务器性能或网络波动导致导入变慢,甚至出现部分数据导入失败。 +> 3. 本地验证通过后,可以利用 Halo 自身的备份恢复能力,更快地在生产环境完成数据恢复或回滚。 + +## 添加迁移平台 + +如果你想为此插件添加一个迁移平台,请查阅:[扩展一个新的迁移平台](./docs/provider.md) ## 开发环境 @@ -49,7 +66,7 @@ git clone git@github.com:{your_github_id}/plugin-migrate.git cd path/to/plugin-migrate ``` -### 运行方式 1(推荐) +### 运行方式(推荐) > 此方式需要本地安装 Docker @@ -70,29 +87,3 @@ cd path/to/plugin-migrate ``` 执行此命令后,会自动创建一个 Halo 的 Docker 容器并加载当前的插件,更多文档可查阅: - -### 运行方式 2 - -> 此方式需要使用源码运行 Halo - -编译插件: - -```bash -# macOS / Linux -./gradlew build - -# Windows -./gradlew.bat build -``` - -修改 Halo 配置文件: - -```yaml -halo: - plugin: - runtime-mode: development - fixedPluginPath: - - "/path/to/plugin-migrate" -``` - -最后重启 Halo 项目即可。 diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts deleted file mode 100644 index cd5fc32..0000000 --- a/docs/.vitepress/config.mts +++ /dev/null @@ -1,49 +0,0 @@ -import { defineConfig } from "vitepress"; - -// https://vitepress.dev/reference/site-config -export default defineConfig({ - lang: "zh-CN", - title: "Halo 迁移插件", - description: "多平台迁移至 Halo 2.x 的迁移插件使用文档", - head: [["link", { rel: "icon", href: "/logo.svg" }]], - lastUpdated: true, - themeConfig: { - logo: "/logo.svg", - // https://vitepress.dev/reference/default-theme-config - nav: [ - { text: "首页", link: "/" }, - { - text: "Release", - link: "https://github.com/halo-sigs/plugin-migrate/releases", - }, - ], - - sidebar: [ - { - items: [{ text: "介绍", link: "/" }], - }, - { - text: "迁移", - items: [ - { text: "Halo 1.x", link: "/provider/halo" }, - { text: "WordPress", link: "/provider/wordpress" }, - { text: "RSS", link: "/provider/rss" }, - { text: "Atom", link: "/provider/atom" }, - { text: "HUGO", link: "/provider/hugo" }, - { text: "Ghost", link: "/provider/ghost" }, - ], - }, - { - text: "扩展", - items: [ - { text: "扩展 Provider", link: "/extend/provider" }, - { text: "扩展迁移步骤", link: "/extend/steps" }, - ], - }, - ], - - socialLinks: [ - { icon: "github", link: "https://github.com/halo-sigs/plugin-migrate" }, - ], - }, -}); diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css deleted file mode 100644 index a2ccd55..0000000 --- a/docs/.vitepress/theme/custom.css +++ /dev/null @@ -1,13 +0,0 @@ -p > img { - border-radius: 0.4rem; - box-shadow: 2px 2px 0.4rem 2px rgba(0, 0, 0, 0.3); - overflow: hidden; -} - -.medium-zoom-overlay { - z-index: 20; -} - -.medium-zoom-image { - z-index: 21; -} diff --git a/docs/.vitepress/theme/index.ts b/docs/.vitepress/theme/index.ts deleted file mode 100644 index fe6ff99..0000000 --- a/docs/.vitepress/theme/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import DefaultTheme from "vitepress/theme"; -import { onMounted, watch, nextTick } from "vue"; -import "./custom.css"; -import mediumZoom from "medium-zoom"; -import { useRoute } from "vitepress/client"; - -export default { - ...DefaultTheme, - - setup() { - const route = useRoute(); - const initZoom = () => { - mediumZoom("[data-zoomable]", { background: "var(--vp-c-bg)" }); - }; - onMounted(() => { - initZoom(); - }); - watch( - () => route.path, - () => nextTick(() => initZoom()) - ); - }, -}; diff --git a/docs/extend/provider.md b/docs/extend/provider.md deleted file mode 100644 index 8eb2aa5..0000000 --- a/docs/extend/provider.md +++ /dev/null @@ -1,86 +0,0 @@ -# 扩展可迁移平台 - -若您使用的平台不在当前支持的平台内,则可通过扩展迁移平台的方式来支持。 - -迁移插件并不强行置顶目标平台的导入方式,由扩展点决定如何进行导入及处理数据,迁移插件只关心最终数据。 - -## 扩展方式 - -每个平台都应当有至少一种导入数据的方式,例如从文件中导入、远程导入等,因此需要对导入数据进行自定义扩展。 - -以 Halo 1.x 平台迁移为例。 - -1. 前往 `ui/src/modules` 中新建一个名为 **halo** 的文件夹。 -2. 在新建的文件夹中,创建一个 `vue` 文件,用于展示导入数据的界面以及处理、转换导入的数据,如 `HaloMigrateDataParser.vue` 文件。 -3. 编写 `HaloMigrateDataParser.vue` 文件,此 vue 模板接收一个 [MigrateData](#migratedata) 类型的数据,用户最终解析完成导入数据后,需要更新此数据以进行下一步操作。后续操作将基于 **MigrateData** 进行。例如 - - ```ts - defineProps<{ - data: MigrateData; - }>(); - - const emit = defineEmits<{ - (event: "update:data", value: MigrateData): void; - }>(); - - /** - * 必要操作:处理数据处理完成之后,触发 update:data 事件来更新 data。 - */ - const handleDataChange = (data: MigrateData) => { - emit("update:data", data); - }; - ``` - -4. 在 **ui/src/modules** 目录下的 **index.ts** 文件中,为 `providerItems` 新增一个 [Provider](#provider) 对象,例如 - - ```json - { - name: "Halo", - icon: "https://halo.run/logo", - description: "Halo 1.5 / 1.6 数据迁移", - importComponent: defineAsyncComponent( - () => import("./halo/HaloMigrateDataParser.vue") // 扩展文件 - ), - options: { - attachmentFolderPath: "migrate-from-1.x", // 附件迁移文件夹 - } - } - ``` - -## MigrateData - -```ts -interface MigrateData { - tags?: MigrateTag[]; - - categories?: MigrateCategory[]; - - posts?: MigratePost[]; - - pages?: MigrateSinglePage[]; - - comments?: (MigrateComment | MigrateReply)[]; - - menuItems?: MigrateMenu[]; - - moments?: MigrateMoment[]; - - photos?: MigratePhoto[]; - - links?: MigrateLink[]; - - attachments?: MigrateAttachment[]; -} -``` - -## Provider - -```ts -interface Provider { - name: string; - icon: string; - description: string; - importComponent?: string | Component; - options?: MigrationOption; -} -``` diff --git a/docs/extend/steps.md b/docs/extend/steps.md deleted file mode 100644 index 480e642..0000000 --- a/docs/extend/steps.md +++ /dev/null @@ -1,49 +0,0 @@ -# 扩展迁移步骤 - -若目前迁移插件的步骤不符合目标 Provider,或者想对迁移增加一些新的功能,例如筛选、进度条等,可以对迁移步骤进行扩展。扩展迁移步骤前,需要注意如下问题: - -1. `选择渠道` 步骤建议保持首位。 -2. 若新增所有 Provider 都会具有的步骤,则需要测试当前所有已拥有的 Provider。 - -## 扩展方式 - -1. 在 `ui/src/view/MigrateView.vue` 文件中,找到 **stepItems** 属性,为其新增 [Step](#step) 字段,以 设置附件存储策略 为例如下所示: - - ```ts - { - key: "attachmentPolicy", // step item slot - name: "设置附件存储策略", // 步骤名称,将会展示在步骤条上 - next: { // 下一步按钮设置 - disabled: computed(() => { // 是否禁止下一步 - return policyMap.value.size === 0; - }), - disabledMessage: "未设置附件存储策略", // 无法进行下一步时,出现的提示 - }, - visible: computed(() => { // 在步骤条中展示当前步骤的条件 - return migrateData.value ? .attachments != undefined; - }), - } - ``` - -2. 设置完上述步骤属性之后,还需要增加目标步骤的界面,在 **MigrateView.vue** 文件中,找到 `Steps` 组件,新建例如 attachmentPolicy 的 slot content,如下所示 - - ```vue - - ``` - -在其中编写页面模板及代码逻辑即可。 - -## Step - -```ts -interface Step { - key: string; - name: string; - description?: string; - next?: StepButtonItem; - prev?: StepButtonItem; - visible?: ComputedRef; -} -``` diff --git a/docs/img/ghost-1.png b/docs/img/ghost-1.png deleted file mode 100644 index 32d26fa..0000000 Binary files a/docs/img/ghost-1.png and /dev/null differ diff --git a/docs/img/ghost-2.png b/docs/img/ghost-2.png deleted file mode 100644 index 0709e00..0000000 Binary files a/docs/img/ghost-2.png and /dev/null differ diff --git a/docs/img/ghost-3.png b/docs/img/ghost-3.png deleted file mode 100644 index 28b3a6c..0000000 Binary files a/docs/img/ghost-3.png and /dev/null differ diff --git a/docs/img/ghost-4.png b/docs/img/ghost-4.png deleted file mode 100644 index 5b3fb21..0000000 Binary files a/docs/img/ghost-4.png and /dev/null differ diff --git a/docs/img/halo-provider-data-export.png b/docs/img/halo-provider-data-export.png deleted file mode 100644 index 04dc176..0000000 Binary files a/docs/img/halo-provider-data-export.png and /dev/null differ diff --git a/docs/img/halo-provider-migrate-plugin.png b/docs/img/halo-provider-migrate-plugin.png deleted file mode 100644 index c081591..0000000 Binary files a/docs/img/halo-provider-migrate-plugin.png and /dev/null differ diff --git a/docs/img/screenshot.png b/docs/img/screenshot.png deleted file mode 100644 index 625dd21..0000000 Binary files a/docs/img/screenshot.png and /dev/null differ diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 03d27f3..0000000 --- a/docs/index.md +++ /dev/null @@ -1,98 +0,0 @@ -# plugin-migrate - -支持从其他平台迁移数据到 Halo 的插件。 - -![Screenshot](/img/screenshot.png) - -目前已支持以下平台: - -1. Halo 1.5 / 1.6 -2. [WordPress](https://wordpress.org/) -3. RSS / Atom 订阅链接 -4. [Hugo](https://gohugo.io/) -5. [Ghost](https://ghost.org/) -6. [Typecho](https://github.com/typecho/typecho) - -## 使用方式 - -1. 下载,目前提供以下两个下载方式: - - GitHub Releases:访问 [Releases](https://github.com/halo-sigs/plugin-migrate/releases) 下载 Assets 中的 JAR 文件。 - - Halo 应用市场: -2. 安装,插件安装和更新方式可参考: -3. 启动插件之后,即可在 Console 的左侧菜单栏看到 **迁移** 的菜单。 - -> **Warning** -> 详细的迁移文档请查阅 - -## 开发环境 - -插件开发的详细文档请查阅: - -所需环境: - -1. Java 17 -2. Node 20 -3. pnpm 10 -4. Docker (可选) - -克隆项目: - -```bash -git clone git@github.com:halo-sigs/plugin-migrate.git - -# 或者当你 fork 之后 - -git clone git@github.com:{your_github_id}/plugin-migrate.git -``` - -```bash -cd path/to/plugin-migrate -``` - -### 运行方式 1(推荐) - -> 此方式需要本地安装 Docker - -```bash -# macOS / Linux -./gradlew pnpmInstall - -# Windows -./gradlew.bat pnpmInstall -``` - -```bash -# macOS / Linux -./gradlew haloServer - -# Windows -./gradlew.bat haloServer -``` - -执行此命令后,会自动创建一个 Halo 的 Docker 容器并加载当前的插件,更多文档可查阅: - -### 运行方式 2 - -> 此方式需要使用源码运行 Halo - -编译插件: - -```bash -# macOS / Linux -./gradlew build - -# Windows -./gradlew.bat build -``` - -修改 Halo 配置文件: - -```yaml -halo: - plugin: - runtime-mode: development - fixedPluginPath: - - "/path/to/plugin-migrate" -``` - -最后重启 Halo 项目即可。 diff --git a/docs/package.json b/docs/package.json deleted file mode 100644 index c2cca98..0000000 --- a/docs/package.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "scripts": { - "docs:dev": "vitepress dev", - "docs:build": "vitepress build", - "docs:preview": "vitepress preview" - }, - "dependencies": { - "medium-zoom": "^1.1.0", - "vitepress": "1.2.3", - "vue": "^3.4.30" - } -} diff --git a/docs/pnpm-lock.yaml b/docs/pnpm-lock.yaml deleted file mode 100644 index acd237c..0000000 --- a/docs/pnpm-lock.yaml +++ /dev/null @@ -1,1202 +0,0 @@ -lockfileVersion: '9.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -importers: - - .: - dependencies: - medium-zoom: - specifier: ^1.1.0 - version: 1.1.0 - vitepress: - specifier: 1.2.3 - version: 1.2.3(@algolia/client-search@4.19.1)(postcss@8.4.38)(search-insights@2.7.0) - vue: - specifier: ^3.4.30 - version: 3.4.30 - -packages: - - '@algolia/autocomplete-core@1.9.3': - resolution: {integrity: sha512-009HdfugtGCdC4JdXUbVJClA0q0zh24yyePn+KUGk3rP7j8FEe/m5Yo/z65gn6nP/cM39PxpzqKrL7A6fP6PPw==} - - '@algolia/autocomplete-plugin-algolia-insights@1.9.3': - resolution: {integrity: sha512-a/yTUkcO/Vyy+JffmAnTWbr4/90cLzw+CC3bRbhnULr/EM0fGNvM13oQQ14f2moLMcVDyAx/leczLlAOovhSZg==} - peerDependencies: - search-insights: '>= 1 < 3' - - '@algolia/autocomplete-preset-algolia@1.9.3': - resolution: {integrity: sha512-d4qlt6YmrLMYy95n5TB52wtNDr6EgAIPH81dvvvW8UmuWRgxEtY0NJiPwl/h95JtG2vmRM804M0DSwMCNZlzRA==} - peerDependencies: - '@algolia/client-search': '>= 4.9.1 < 6' - algoliasearch: '>= 4.9.1 < 6' - - '@algolia/autocomplete-shared@1.9.3': - resolution: {integrity: sha512-Wnm9E4Ye6Rl6sTTqjoymD+l8DjSTHsHboVRYrKgEt8Q7UHm9nYbqhN/i0fhUYA3OAEH7WA8x3jfpnmJm3rKvaQ==} - peerDependencies: - '@algolia/client-search': '>= 4.9.1 < 6' - algoliasearch: '>= 4.9.1 < 6' - - '@algolia/cache-browser-local-storage@4.19.1': - resolution: {integrity: sha512-FYAZWcGsFTTaSAwj9Std8UML3Bu8dyWDncM7Ls8g+58UOe4XYdlgzXWbrIgjaguP63pCCbMoExKr61B+ztK3tw==} - - '@algolia/cache-common@4.19.1': - resolution: {integrity: sha512-XGghi3l0qA38HiqdoUY+wvGyBsGvKZ6U3vTiMBT4hArhP3fOGLXpIINgMiiGjTe4FVlTa5a/7Zf2bwlIHfRqqg==} - - '@algolia/cache-in-memory@4.19.1': - resolution: {integrity: sha512-+PDWL+XALGvIginigzu8oU6eWw+o76Z8zHbBovWYcrtWOEtinbl7a7UTt3x3lthv+wNuFr/YD1Gf+B+A9V8n5w==} - - '@algolia/client-account@4.19.1': - resolution: {integrity: sha512-Oy0ritA2k7AMxQ2JwNpfaEcgXEDgeyKu0V7E7xt/ZJRdXfEpZcwp9TOg4TJHC7Ia62gIeT2Y/ynzsxccPw92GA==} - - '@algolia/client-analytics@4.19.1': - resolution: {integrity: sha512-5QCq2zmgdZLIQhHqwl55ZvKVpLM3DNWjFI4T+bHr3rGu23ew2bLO4YtyxaZeChmDb85jUdPDouDlCumGfk6wOg==} - - '@algolia/client-common@4.19.1': - resolution: {integrity: sha512-3kAIVqTcPrjfS389KQvKzliC559x+BDRxtWamVJt8IVp7LGnjq+aVAXg4Xogkur1MUrScTZ59/AaUd5EdpyXgA==} - - '@algolia/client-personalization@4.19.1': - resolution: {integrity: sha512-8CWz4/H5FA+krm9HMw2HUQenizC/DxUtsI5oYC0Jxxyce1vsr8cb1aEiSJArQT6IzMynrERif1RVWLac1m36xw==} - - '@algolia/client-search@4.19.1': - resolution: {integrity: sha512-mBecfMFS4N+yK/p0ZbK53vrZbL6OtWMk8YmnOv1i0LXx4pelY8TFhqKoTit3NPVPwoSNN0vdSN9dTu1xr1XOVw==} - - '@algolia/logger-common@4.19.1': - resolution: {integrity: sha512-i6pLPZW/+/YXKis8gpmSiNk1lOmYCmRI6+x6d2Qk1OdfvX051nRVdalRbEcVTpSQX6FQAoyeaui0cUfLYW5Elw==} - - '@algolia/logger-console@4.19.1': - resolution: {integrity: sha512-jj72k9GKb9W0c7TyC3cuZtTr0CngLBLmc8trzZlXdfvQiigpUdvTi1KoWIb2ZMcRBG7Tl8hSb81zEY3zI2RlXg==} - - '@algolia/requester-browser-xhr@4.19.1': - resolution: {integrity: sha512-09K/+t7lptsweRTueHnSnmPqIxbHMowejAkn9XIcJMLdseS3zl8ObnS5GWea86mu3vy4+8H+ZBKkUN82Zsq/zg==} - - '@algolia/requester-common@4.19.1': - resolution: {integrity: sha512-BisRkcWVxrDzF1YPhAckmi2CFYK+jdMT60q10d7z3PX+w6fPPukxHRnZwooiTUrzFe50UBmLItGizWHP5bDzVQ==} - - '@algolia/requester-node-http@4.19.1': - resolution: {integrity: sha512-6DK52DHviBHTG2BK/Vv2GIlEw7i+vxm7ypZW0Z7vybGCNDeWzADx+/TmxjkES2h15+FZOqVf/Ja677gePsVItA==} - - '@algolia/transporter@4.19.1': - resolution: {integrity: sha512-nkpvPWbpuzxo1flEYqNIbGz7xhfhGOKGAZS7tzC+TELgEmi7z99qRyTfNSUlW7LZmB3ACdnqAo+9A9KFBENviQ==} - - '@babel/helper-string-parser@7.22.5': - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} - engines: {node: '>=6.9.0'} - - '@babel/helper-validator-identifier@7.22.5': - resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} - engines: {node: '>=6.9.0'} - - '@babel/parser@7.24.7': - resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} - engines: {node: '>=6.0.0'} - hasBin: true - - '@babel/types@7.22.10': - resolution: {integrity: sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==} - engines: {node: '>=6.9.0'} - - '@docsearch/css@3.6.0': - resolution: {integrity: sha512-+sbxb71sWre+PwDK7X2T8+bhS6clcVMLwBPznX45Qu6opJcgRjAp7gYSDzVFp187J+feSj5dNBN1mJoi6ckkUQ==} - - '@docsearch/js@3.6.0': - resolution: {integrity: sha512-QujhqINEElrkIfKwyyyTfbsfMAYCkylInLYMRqHy7PHc8xTBQCow73tlo/Kc7oIwBrCLf0P3YhjlOeV4v8hevQ==} - - '@docsearch/react@3.6.0': - resolution: {integrity: sha512-HUFut4ztcVNmqy9gp/wxNbC7pTOHhgVVkHVGCACTuLhUKUhKAF9KYHJtMiLUJxEqiFLQiuri1fWF8zqwM/cu1w==} - peerDependencies: - '@types/react': '>= 16.8.0 < 19.0.0' - react: '>= 16.8.0 < 19.0.0' - react-dom: '>= 16.8.0 < 19.0.0' - search-insights: '>= 1 < 3' - peerDependenciesMeta: - '@types/react': - optional: true - react: - optional: true - react-dom: - optional: true - search-insights: - optional: true - - '@esbuild/aix-ppc64@0.21.5': - resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [aix] - - '@esbuild/android-arm64@0.21.5': - resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [android] - - '@esbuild/android-arm@0.21.5': - resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} - engines: {node: '>=12'} - cpu: [arm] - os: [android] - - '@esbuild/android-x64@0.21.5': - resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} - engines: {node: '>=12'} - cpu: [x64] - os: [android] - - '@esbuild/darwin-arm64@0.21.5': - resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} - engines: {node: '>=12'} - cpu: [arm64] - os: [darwin] - - '@esbuild/darwin-x64@0.21.5': - resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} - engines: {node: '>=12'} - cpu: [x64] - os: [darwin] - - '@esbuild/freebsd-arm64@0.21.5': - resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} - engines: {node: '>=12'} - cpu: [arm64] - os: [freebsd] - - '@esbuild/freebsd-x64@0.21.5': - resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [freebsd] - - '@esbuild/linux-arm64@0.21.5': - resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} - engines: {node: '>=12'} - cpu: [arm64] - os: [linux] - - '@esbuild/linux-arm@0.21.5': - resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} - engines: {node: '>=12'} - cpu: [arm] - os: [linux] - - '@esbuild/linux-ia32@0.21.5': - resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} - engines: {node: '>=12'} - cpu: [ia32] - os: [linux] - - '@esbuild/linux-loong64@0.21.5': - resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} - engines: {node: '>=12'} - cpu: [loong64] - os: [linux] - - '@esbuild/linux-mips64el@0.21.5': - resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} - engines: {node: '>=12'} - cpu: [mips64el] - os: [linux] - - '@esbuild/linux-ppc64@0.21.5': - resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} - engines: {node: '>=12'} - cpu: [ppc64] - os: [linux] - - '@esbuild/linux-riscv64@0.21.5': - resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} - engines: {node: '>=12'} - cpu: [riscv64] - os: [linux] - - '@esbuild/linux-s390x@0.21.5': - resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} - engines: {node: '>=12'} - cpu: [s390x] - os: [linux] - - '@esbuild/linux-x64@0.21.5': - resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} - engines: {node: '>=12'} - cpu: [x64] - os: [linux] - - '@esbuild/netbsd-x64@0.21.5': - resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} - engines: {node: '>=12'} - cpu: [x64] - os: [netbsd] - - '@esbuild/openbsd-x64@0.21.5': - resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} - engines: {node: '>=12'} - cpu: [x64] - os: [openbsd] - - '@esbuild/sunos-x64@0.21.5': - resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} - engines: {node: '>=12'} - cpu: [x64] - os: [sunos] - - '@esbuild/win32-arm64@0.21.5': - resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} - engines: {node: '>=12'} - cpu: [arm64] - os: [win32] - - '@esbuild/win32-ia32@0.21.5': - resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} - engines: {node: '>=12'} - cpu: [ia32] - os: [win32] - - '@esbuild/win32-x64@0.21.5': - resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} - engines: {node: '>=12'} - cpu: [x64] - os: [win32] - - '@jridgewell/sourcemap-codec@1.4.15': - resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - - '@rollup/rollup-android-arm-eabi@4.18.0': - resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} - cpu: [arm] - os: [android] - - '@rollup/rollup-android-arm64@4.18.0': - resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} - cpu: [arm64] - os: [android] - - '@rollup/rollup-darwin-arm64@4.18.0': - resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} - cpu: [arm64] - os: [darwin] - - '@rollup/rollup-darwin-x64@4.18.0': - resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} - cpu: [x64] - os: [darwin] - - '@rollup/rollup-linux-arm-gnueabihf@4.18.0': - resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm-musleabihf@4.18.0': - resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} - cpu: [arm] - os: [linux] - - '@rollup/rollup-linux-arm64-gnu@4.18.0': - resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-arm64-musl@4.18.0': - resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} - cpu: [arm64] - os: [linux] - - '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': - resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} - cpu: [ppc64] - os: [linux] - - '@rollup/rollup-linux-riscv64-gnu@4.18.0': - resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} - cpu: [riscv64] - os: [linux] - - '@rollup/rollup-linux-s390x-gnu@4.18.0': - resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} - cpu: [s390x] - os: [linux] - - '@rollup/rollup-linux-x64-gnu@4.18.0': - resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-linux-x64-musl@4.18.0': - resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} - cpu: [x64] - os: [linux] - - '@rollup/rollup-win32-arm64-msvc@4.18.0': - resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} - cpu: [arm64] - os: [win32] - - '@rollup/rollup-win32-ia32-msvc@4.18.0': - resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} - cpu: [ia32] - os: [win32] - - '@rollup/rollup-win32-x64-msvc@4.18.0': - resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} - cpu: [x64] - os: [win32] - - '@shikijs/core@1.9.0': - resolution: {integrity: sha512-cbSoY8P/jgGByG8UOl3jnP/CWg/Qk+1q+eAKWtcrU3pNoILF8wTsLB0jT44qUBV8Ce1SvA9uqcM9Xf+u3fJFBw==} - - '@shikijs/transformers@1.9.0': - resolution: {integrity: sha512-wo8dNbZtFtVhKtw8BnXIT/FDTGMwEdWcQSIRa78ou14JGkMYxSCBN942W5+IRUifP5BwVUWgkXBYX/M3FUFkeg==} - - '@types/estree@1.0.5': - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} - - '@types/linkify-it@5.0.0': - resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} - - '@types/markdown-it@14.1.1': - resolution: {integrity: sha512-4NpsnpYl2Gt1ljyBGrKMxFYAYvpqbnnkgP/i/g+NLpjEUa3obn1XJCur9YbEXKDAkaXqsR1LbDnGEJ0MmKFxfg==} - - '@types/mdurl@2.0.0': - resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} - - '@types/web-bluetooth@0.0.20': - resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} - - '@vitejs/plugin-vue@5.0.5': - resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==} - engines: {node: ^18.0.0 || >=20.0.0} - peerDependencies: - vite: ^5.0.0 - vue: ^3.2.25 - - '@vue/compiler-core@3.4.30': - resolution: {integrity: sha512-ZL8y4Xxdh8O6PSwfdZ1IpQ24PjTAieOz3jXb/MDTfDtANcKBMxg1KLm6OX2jofsaQGYfIVzd3BAG22i56/cF1w==} - - '@vue/compiler-dom@3.4.30': - resolution: {integrity: sha512-+16Sd8lYr5j/owCbr9dowcNfrHd+pz+w2/b5Lt26Oz/kB90C9yNbxQ3bYOvt7rI2bxk0nqda39hVcwDFw85c2Q==} - - '@vue/compiler-sfc@3.4.30': - resolution: {integrity: sha512-8vElKklHn/UY8+FgUFlQrYAPbtiSB2zcgeRKW7HkpSRn/JjMRmZvuOtwDx036D1aqKNSTtXkWRfqx53Qb+HmMg==} - - '@vue/compiler-ssr@3.4.30': - resolution: {integrity: sha512-ZJ56YZGXJDd6jky4mmM0rNaNP6kIbQu9LTKZDhcpddGe/3QIalB1WHHmZ6iZfFNyj5mSypTa4+qDJa5VIuxMSg==} - - '@vue/devtools-api@7.3.4': - resolution: {integrity: sha512-E5dJlLW+NgGb+WS33y99ioOJL2OXpVhje6VwXGJ/q5fNizJDpe67Ml0GBSrlYOKNSjZs2mwcZd7B3e12th3Q0g==} - - '@vue/devtools-kit@7.3.4': - resolution: {integrity: sha512-DalQZWaFLRyA4qfKT0WT7e+q2AwvYoTwd0pWqswHqcpviXw+oU6FlSJHMrEACB3lBHjN1KBS9Kh527sWIe1vcg==} - - '@vue/devtools-shared@7.3.4': - resolution: {integrity: sha512-5S5cHh7oWLZdboujnLteR3rT8UGfKHfA34aGLyFRB/B5TqBxmeLW1Rq32xW6TCDEy4isoYsYHGwJVp6DQcpiDA==} - - '@vue/reactivity@3.4.30': - resolution: {integrity: sha512-bVJurnCe3LS0JII8PPoAA63Zd2MBzcKrEzwdQl92eHCcxtIbxD2fhNwJpa+KkM3Y/A4T5FUnmdhgKwOf6BfbcA==} - - '@vue/runtime-core@3.4.30': - resolution: {integrity: sha512-qaFEbnNpGz+tlnkaualomogzN8vBLkgzK55uuWjYXbYn039eOBZrWxyXWq/7qh9Bz2FPifZqGjVDl/FXiq9L2g==} - - '@vue/runtime-dom@3.4.30': - resolution: {integrity: sha512-tV6B4YiZRj5QsaJgw2THCy5C1H+2UeywO9tqgWEc21tn85qHEERndHN/CxlyXvSBFrpmlexCIdnqPuR9RM9thw==} - - '@vue/server-renderer@3.4.30': - resolution: {integrity: sha512-TBD3eqR1DeDc0cMrXS/vEs/PWzq1uXxnvjoqQuDGFIEHFIwuDTX/KWAQKIBjyMWLFHEeTDGYVsYci85z2UbTDg==} - peerDependencies: - vue: 3.4.30 - - '@vue/shared@3.4.30': - resolution: {integrity: sha512-CLg+f8RQCHQnKvuHY9adMsMaQOcqclh6Z5V9TaoMgy0ut0tz848joZ7/CYFFyF/yZ5i2yaw7Fn498C+CNZVHIg==} - - '@vueuse/core@10.11.0': - resolution: {integrity: sha512-x3sD4Mkm7PJ+pcq3HX8PLPBadXCAlSDR/waK87dz0gQE+qJnaaFhc/dZVfJz+IUYzTMVGum2QlR7ImiJQN4s6g==} - - '@vueuse/integrations@10.11.0': - resolution: {integrity: sha512-Pp6MtWEIr+NDOccWd8j59Kpjy5YDXogXI61Kb1JxvSfVBO8NzFQkmrKmSZz47i+ZqHnIzxaT38L358yDHTncZg==} - peerDependencies: - async-validator: ^4 - axios: ^1 - change-case: ^4 - drauu: ^0.3 - focus-trap: ^7 - fuse.js: ^6 - idb-keyval: ^6 - jwt-decode: ^3 - nprogress: ^0.2 - qrcode: ^1.5 - sortablejs: ^1 - universal-cookie: ^6 - 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 - - '@vueuse/metadata@10.11.0': - resolution: {integrity: sha512-kQX7l6l8dVWNqlqyN3ePW3KmjCQO3ZMgXuBMddIu83CmucrsBfXlH+JoviYyRBws/yLTQO8g3Pbw+bdIoVm4oQ==} - - '@vueuse/shared@10.11.0': - resolution: {integrity: sha512-fyNoIXEq3PfX1L3NkNhtVQUSRtqYwJtJg+Bp9rIzculIZWHTkKSysujrOk2J+NrRulLTQH9+3gGSfYLWSEWU1A==} - - algoliasearch@4.19.1: - resolution: {integrity: sha512-IJF5b93b2MgAzcE/tuzW0yOPnuUyRgGAtaPv5UUywXM8kzqfdwZTO4sPJBzoGz1eOy6H9uEchsJsBFTELZSu+g==} - - birpc@0.2.17: - resolution: {integrity: sha512-+hkTxhot+dWsLpp3gia5AkVHIsKlZybNT5gIYiDlNzJrmYPcTM9k5/w2uaj3IPpd7LlEYpmCj4Jj1nC41VhDFg==} - - copy-anything@3.0.5: - resolution: {integrity: sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==} - engines: {node: '>=12.13'} - - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - - entities@4.5.0: - resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} - engines: {node: '>=0.12'} - - esbuild@0.21.5: - resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} - engines: {node: '>=12'} - hasBin: true - - estree-walker@2.0.2: - resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} - - focus-trap@7.5.4: - resolution: {integrity: sha512-N7kHdlgsO/v+iD/dMoJKtsSqs5Dz/dXZVebRgJw23LDk+jMi/974zyiOYDziY2JPp8xivq9BmUGwIJMiuSBi7w==} - - fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - - hookable@5.5.3: - resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} - - is-what@4.1.16: - resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} - engines: {node: '>=12.13'} - - magic-string@0.30.10: - resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - - mark.js@8.11.1: - resolution: {integrity: sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ==} - - medium-zoom@1.1.0: - resolution: {integrity: sha512-ewyDsp7k4InCUp3jRmwHBRFGyjBimKps/AJLjRSox+2q/2H4p/PNpQf+pwONWlJiOudkBXtbdmVbFjqyybfTmQ==} - - minisearch@6.3.0: - resolution: {integrity: sha512-ihFnidEeU8iXzcVHy74dhkxh/dn8Dc08ERl0xwoMMGqp4+LvRSCgicb+zGqWthVokQKvCSxITlh3P08OzdTYCQ==} - - mitt@3.0.1: - resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} - - nanoid@3.3.7: - resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - - perfect-debounce@1.0.0: - resolution: {integrity: sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==} - - picocolors@1.0.0: - resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} - - postcss@8.4.38: - resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==} - engines: {node: ^10 || ^12 || >=14} - - preact@10.16.0: - resolution: {integrity: sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA==} - - rfdc@1.4.1: - resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} - - rollup@4.18.0: - resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - - search-insights@2.7.0: - resolution: {integrity: sha512-GLbVaGgzYEKMvuJbHRhLi1qoBFnjXZGZ6l4LxOYPCp4lI2jDRB3jPU9/XNhMwv6kvnA9slTreq6pvK+b3o3aqg==} - engines: {node: '>=8.16.0'} - - shiki@1.9.0: - resolution: {integrity: sha512-i6//Lqgn7+7nZA0qVjoYH0085YdNk4MC+tJV4bo+HgjgRMJ0JmkLZzFAuvVioJqLkcGDK5GAMpghZEZkCnwxpQ==} - - source-map-js@1.2.0: - resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} - engines: {node: '>=0.10.0'} - - speakingurl@14.0.1: - resolution: {integrity: sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==} - engines: {node: '>=0.10.0'} - - superjson@2.2.1: - resolution: {integrity: sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==} - engines: {node: '>=16'} - - tabbable@6.2.0: - resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} - - to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - - vite@5.3.1: - resolution: {integrity: sha512-XBmSKRLXLxiaPYamLv3/hnP/KXDai1NDexN0FpkTaZXTfycHvkRHoenpgl/fvuK/kPbB6xAgoyiryAhQNxYmAQ==} - engines: {node: ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@types/node': ^18.0.0 || >=20.0.0 - less: '*' - lightningcss: ^1.21.0 - sass: '*' - stylus: '*' - sugarss: '*' - terser: ^5.4.0 - peerDependenciesMeta: - '@types/node': - optional: true - less: - optional: true - lightningcss: - optional: true - sass: - optional: true - stylus: - optional: true - sugarss: - optional: true - terser: - optional: true - - vitepress@1.2.3: - resolution: {integrity: sha512-GvEsrEeNLiDE1+fuwDAYJCYLNZDAna+EtnXlPajhv/MYeTjbNK6Bvyg6NoTdO1sbwuQJ0vuJR99bOlH53bo6lg==} - hasBin: true - peerDependencies: - markdown-it-mathjax3: ^4 - postcss: ^8 - peerDependenciesMeta: - markdown-it-mathjax3: - optional: true - postcss: - optional: true - - vue-demi@0.14.8: - resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==} - engines: {node: '>=12'} - hasBin: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - - vue@3.4.30: - resolution: {integrity: sha512-NcxtKCwkdf1zPsr7Y8+QlDBCGqxvjLXF2EX+yi76rV5rrz90Y6gK1cq0olIhdWGgrlhs9ElHuhi9t3+W5sG5Xw==} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - -snapshots: - - '@algolia/autocomplete-core@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.7.0)': - dependencies: - '@algolia/autocomplete-plugin-algolia-insights': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.7.0) - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) - transitivePeerDependencies: - - '@algolia/client-search' - - algoliasearch - - search-insights - - '@algolia/autocomplete-plugin-algolia-insights@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.7.0)': - dependencies: - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) - search-insights: 2.7.0 - transitivePeerDependencies: - - '@algolia/client-search' - - algoliasearch - - '@algolia/autocomplete-preset-algolia@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)': - dependencies: - '@algolia/autocomplete-shared': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) - '@algolia/client-search': 4.19.1 - algoliasearch: 4.19.1 - - '@algolia/autocomplete-shared@1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)': - dependencies: - '@algolia/client-search': 4.19.1 - algoliasearch: 4.19.1 - - '@algolia/cache-browser-local-storage@4.19.1': - dependencies: - '@algolia/cache-common': 4.19.1 - - '@algolia/cache-common@4.19.1': {} - - '@algolia/cache-in-memory@4.19.1': - dependencies: - '@algolia/cache-common': 4.19.1 - - '@algolia/client-account@4.19.1': - dependencies: - '@algolia/client-common': 4.19.1 - '@algolia/client-search': 4.19.1 - '@algolia/transporter': 4.19.1 - - '@algolia/client-analytics@4.19.1': - dependencies: - '@algolia/client-common': 4.19.1 - '@algolia/client-search': 4.19.1 - '@algolia/requester-common': 4.19.1 - '@algolia/transporter': 4.19.1 - - '@algolia/client-common@4.19.1': - dependencies: - '@algolia/requester-common': 4.19.1 - '@algolia/transporter': 4.19.1 - - '@algolia/client-personalization@4.19.1': - dependencies: - '@algolia/client-common': 4.19.1 - '@algolia/requester-common': 4.19.1 - '@algolia/transporter': 4.19.1 - - '@algolia/client-search@4.19.1': - dependencies: - '@algolia/client-common': 4.19.1 - '@algolia/requester-common': 4.19.1 - '@algolia/transporter': 4.19.1 - - '@algolia/logger-common@4.19.1': {} - - '@algolia/logger-console@4.19.1': - dependencies: - '@algolia/logger-common': 4.19.1 - - '@algolia/requester-browser-xhr@4.19.1': - dependencies: - '@algolia/requester-common': 4.19.1 - - '@algolia/requester-common@4.19.1': {} - - '@algolia/requester-node-http@4.19.1': - dependencies: - '@algolia/requester-common': 4.19.1 - - '@algolia/transporter@4.19.1': - dependencies: - '@algolia/cache-common': 4.19.1 - '@algolia/logger-common': 4.19.1 - '@algolia/requester-common': 4.19.1 - - '@babel/helper-string-parser@7.22.5': {} - - '@babel/helper-validator-identifier@7.22.5': {} - - '@babel/parser@7.24.7': - dependencies: - '@babel/types': 7.22.10 - - '@babel/types@7.22.10': - dependencies: - '@babel/helper-string-parser': 7.22.5 - '@babel/helper-validator-identifier': 7.22.5 - to-fast-properties: 2.0.0 - - '@docsearch/css@3.6.0': {} - - '@docsearch/js@3.6.0(@algolia/client-search@4.19.1)(search-insights@2.7.0)': - dependencies: - '@docsearch/react': 3.6.0(@algolia/client-search@4.19.1)(search-insights@2.7.0) - preact: 10.16.0 - transitivePeerDependencies: - - '@algolia/client-search' - - '@types/react' - - react - - react-dom - - search-insights - - '@docsearch/react@3.6.0(@algolia/client-search@4.19.1)(search-insights@2.7.0)': - dependencies: - '@algolia/autocomplete-core': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1)(search-insights@2.7.0) - '@algolia/autocomplete-preset-algolia': 1.9.3(@algolia/client-search@4.19.1)(algoliasearch@4.19.1) - '@docsearch/css': 3.6.0 - algoliasearch: 4.19.1 - optionalDependencies: - search-insights: 2.7.0 - transitivePeerDependencies: - - '@algolia/client-search' - - '@esbuild/aix-ppc64@0.21.5': - optional: true - - '@esbuild/android-arm64@0.21.5': - optional: true - - '@esbuild/android-arm@0.21.5': - optional: true - - '@esbuild/android-x64@0.21.5': - optional: true - - '@esbuild/darwin-arm64@0.21.5': - optional: true - - '@esbuild/darwin-x64@0.21.5': - optional: true - - '@esbuild/freebsd-arm64@0.21.5': - optional: true - - '@esbuild/freebsd-x64@0.21.5': - optional: true - - '@esbuild/linux-arm64@0.21.5': - optional: true - - '@esbuild/linux-arm@0.21.5': - optional: true - - '@esbuild/linux-ia32@0.21.5': - optional: true - - '@esbuild/linux-loong64@0.21.5': - optional: true - - '@esbuild/linux-mips64el@0.21.5': - optional: true - - '@esbuild/linux-ppc64@0.21.5': - optional: true - - '@esbuild/linux-riscv64@0.21.5': - optional: true - - '@esbuild/linux-s390x@0.21.5': - optional: true - - '@esbuild/linux-x64@0.21.5': - optional: true - - '@esbuild/netbsd-x64@0.21.5': - optional: true - - '@esbuild/openbsd-x64@0.21.5': - optional: true - - '@esbuild/sunos-x64@0.21.5': - optional: true - - '@esbuild/win32-arm64@0.21.5': - optional: true - - '@esbuild/win32-ia32@0.21.5': - optional: true - - '@esbuild/win32-x64@0.21.5': - optional: true - - '@jridgewell/sourcemap-codec@1.4.15': {} - - '@rollup/rollup-android-arm-eabi@4.18.0': - optional: true - - '@rollup/rollup-android-arm64@4.18.0': - optional: true - - '@rollup/rollup-darwin-arm64@4.18.0': - optional: true - - '@rollup/rollup-darwin-x64@4.18.0': - optional: true - - '@rollup/rollup-linux-arm-gnueabihf@4.18.0': - optional: true - - '@rollup/rollup-linux-arm-musleabihf@4.18.0': - optional: true - - '@rollup/rollup-linux-arm64-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-arm64-musl@4.18.0': - optional: true - - '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-riscv64-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-s390x-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-x64-gnu@4.18.0': - optional: true - - '@rollup/rollup-linux-x64-musl@4.18.0': - optional: true - - '@rollup/rollup-win32-arm64-msvc@4.18.0': - optional: true - - '@rollup/rollup-win32-ia32-msvc@4.18.0': - optional: true - - '@rollup/rollup-win32-x64-msvc@4.18.0': - optional: true - - '@shikijs/core@1.9.0': {} - - '@shikijs/transformers@1.9.0': - dependencies: - shiki: 1.9.0 - - '@types/estree@1.0.5': {} - - '@types/linkify-it@5.0.0': {} - - '@types/markdown-it@14.1.1': - dependencies: - '@types/linkify-it': 5.0.0 - '@types/mdurl': 2.0.0 - - '@types/mdurl@2.0.0': {} - - '@types/web-bluetooth@0.0.20': {} - - '@vitejs/plugin-vue@5.0.5(vite@5.3.1)(vue@3.4.30)': - dependencies: - vite: 5.3.1 - vue: 3.4.30 - - '@vue/compiler-core@3.4.30': - dependencies: - '@babel/parser': 7.24.7 - '@vue/shared': 3.4.30 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.2.0 - - '@vue/compiler-dom@3.4.30': - dependencies: - '@vue/compiler-core': 3.4.30 - '@vue/shared': 3.4.30 - - '@vue/compiler-sfc@3.4.30': - dependencies: - '@babel/parser': 7.24.7 - '@vue/compiler-core': 3.4.30 - '@vue/compiler-dom': 3.4.30 - '@vue/compiler-ssr': 3.4.30 - '@vue/shared': 3.4.30 - estree-walker: 2.0.2 - magic-string: 0.30.10 - postcss: 8.4.38 - source-map-js: 1.2.0 - - '@vue/compiler-ssr@3.4.30': - dependencies: - '@vue/compiler-dom': 3.4.30 - '@vue/shared': 3.4.30 - - '@vue/devtools-api@7.3.4': - dependencies: - '@vue/devtools-kit': 7.3.4 - - '@vue/devtools-kit@7.3.4': - dependencies: - '@vue/devtools-shared': 7.3.4 - birpc: 0.2.17 - hookable: 5.5.3 - mitt: 3.0.1 - perfect-debounce: 1.0.0 - speakingurl: 14.0.1 - superjson: 2.2.1 - - '@vue/devtools-shared@7.3.4': - dependencies: - rfdc: 1.4.1 - - '@vue/reactivity@3.4.30': - dependencies: - '@vue/shared': 3.4.30 - - '@vue/runtime-core@3.4.30': - dependencies: - '@vue/reactivity': 3.4.30 - '@vue/shared': 3.4.30 - - '@vue/runtime-dom@3.4.30': - dependencies: - '@vue/reactivity': 3.4.30 - '@vue/runtime-core': 3.4.30 - '@vue/shared': 3.4.30 - csstype: 3.1.3 - - '@vue/server-renderer@3.4.30(vue@3.4.30)': - dependencies: - '@vue/compiler-ssr': 3.4.30 - '@vue/shared': 3.4.30 - vue: 3.4.30 - - '@vue/shared@3.4.30': {} - - '@vueuse/core@10.11.0(vue@3.4.30)': - dependencies: - '@types/web-bluetooth': 0.0.20 - '@vueuse/metadata': 10.11.0 - '@vueuse/shared': 10.11.0(vue@3.4.30) - vue-demi: 0.14.8(vue@3.4.30) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - - '@vueuse/integrations@10.11.0(focus-trap@7.5.4)(vue@3.4.30)': - dependencies: - '@vueuse/core': 10.11.0(vue@3.4.30) - '@vueuse/shared': 10.11.0(vue@3.4.30) - vue-demi: 0.14.8(vue@3.4.30) - optionalDependencies: - focus-trap: 7.5.4 - transitivePeerDependencies: - - '@vue/composition-api' - - vue - - '@vueuse/metadata@10.11.0': {} - - '@vueuse/shared@10.11.0(vue@3.4.30)': - dependencies: - vue-demi: 0.14.8(vue@3.4.30) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - - algoliasearch@4.19.1: - dependencies: - '@algolia/cache-browser-local-storage': 4.19.1 - '@algolia/cache-common': 4.19.1 - '@algolia/cache-in-memory': 4.19.1 - '@algolia/client-account': 4.19.1 - '@algolia/client-analytics': 4.19.1 - '@algolia/client-common': 4.19.1 - '@algolia/client-personalization': 4.19.1 - '@algolia/client-search': 4.19.1 - '@algolia/logger-common': 4.19.1 - '@algolia/logger-console': 4.19.1 - '@algolia/requester-browser-xhr': 4.19.1 - '@algolia/requester-common': 4.19.1 - '@algolia/requester-node-http': 4.19.1 - '@algolia/transporter': 4.19.1 - - birpc@0.2.17: {} - - copy-anything@3.0.5: - dependencies: - is-what: 4.1.16 - - csstype@3.1.3: {} - - entities@4.5.0: {} - - esbuild@0.21.5: - 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 - - estree-walker@2.0.2: {} - - focus-trap@7.5.4: - dependencies: - tabbable: 6.2.0 - - fsevents@2.3.3: - optional: true - - hookable@5.5.3: {} - - is-what@4.1.16: {} - - magic-string@0.30.10: - dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 - - mark.js@8.11.1: {} - - medium-zoom@1.1.0: {} - - minisearch@6.3.0: {} - - mitt@3.0.1: {} - - nanoid@3.3.7: {} - - perfect-debounce@1.0.0: {} - - picocolors@1.0.0: {} - - postcss@8.4.38: - dependencies: - nanoid: 3.3.7 - picocolors: 1.0.0 - source-map-js: 1.2.0 - - preact@10.16.0: {} - - rfdc@1.4.1: {} - - rollup@4.18.0: - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.18.0 - '@rollup/rollup-android-arm64': 4.18.0 - '@rollup/rollup-darwin-arm64': 4.18.0 - '@rollup/rollup-darwin-x64': 4.18.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 - '@rollup/rollup-linux-arm-musleabihf': 4.18.0 - '@rollup/rollup-linux-arm64-gnu': 4.18.0 - '@rollup/rollup-linux-arm64-musl': 4.18.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 - '@rollup/rollup-linux-riscv64-gnu': 4.18.0 - '@rollup/rollup-linux-s390x-gnu': 4.18.0 - '@rollup/rollup-linux-x64-gnu': 4.18.0 - '@rollup/rollup-linux-x64-musl': 4.18.0 - '@rollup/rollup-win32-arm64-msvc': 4.18.0 - '@rollup/rollup-win32-ia32-msvc': 4.18.0 - '@rollup/rollup-win32-x64-msvc': 4.18.0 - fsevents: 2.3.3 - - search-insights@2.7.0: {} - - shiki@1.9.0: - dependencies: - '@shikijs/core': 1.9.0 - - source-map-js@1.2.0: {} - - speakingurl@14.0.1: {} - - superjson@2.2.1: - dependencies: - copy-anything: 3.0.5 - - tabbable@6.2.0: {} - - to-fast-properties@2.0.0: {} - - vite@5.3.1: - dependencies: - esbuild: 0.21.5 - postcss: 8.4.38 - rollup: 4.18.0 - optionalDependencies: - fsevents: 2.3.3 - - vitepress@1.2.3(@algolia/client-search@4.19.1)(postcss@8.4.38)(search-insights@2.7.0): - dependencies: - '@docsearch/css': 3.6.0 - '@docsearch/js': 3.6.0(@algolia/client-search@4.19.1)(search-insights@2.7.0) - '@shikijs/core': 1.9.0 - '@shikijs/transformers': 1.9.0 - '@types/markdown-it': 14.1.1 - '@vitejs/plugin-vue': 5.0.5(vite@5.3.1)(vue@3.4.30) - '@vue/devtools-api': 7.3.4 - '@vue/shared': 3.4.30 - '@vueuse/core': 10.11.0(vue@3.4.30) - '@vueuse/integrations': 10.11.0(focus-trap@7.5.4)(vue@3.4.30) - focus-trap: 7.5.4 - mark.js: 8.11.1 - minisearch: 6.3.0 - shiki: 1.9.0 - vite: 5.3.1 - vue: 3.4.30 - optionalDependencies: - postcss: 8.4.38 - transitivePeerDependencies: - - '@algolia/client-search' - - '@types/node' - - '@types/react' - - '@vue/composition-api' - - async-validator - - axios - - change-case - - drauu - - fuse.js - - idb-keyval - - jwt-decode - - less - - lightningcss - - nprogress - - qrcode - - react - - react-dom - - sass - - search-insights - - sortablejs - - stylus - - sugarss - - terser - - typescript - - universal-cookie - - vue-demi@0.14.8(vue@3.4.30): - dependencies: - vue: 3.4.30 - - vue@3.4.30: - dependencies: - '@vue/compiler-dom': 3.4.30 - '@vue/compiler-sfc': 3.4.30 - '@vue/runtime-dom': 3.4.30 - '@vue/server-renderer': 3.4.30(vue@3.4.30) - '@vue/shared': 3.4.30 diff --git a/docs/pnpm-workspace.yaml b/docs/pnpm-workspace.yaml deleted file mode 100644 index 4e768fe..0000000 --- a/docs/pnpm-workspace.yaml +++ /dev/null @@ -1,3 +0,0 @@ -onlyBuiltDependencies: - - esbuild - - vue-demi diff --git a/docs/provider.md b/docs/provider.md new file mode 100644 index 0000000..43df80e --- /dev/null +++ b/docs/provider.md @@ -0,0 +1,419 @@ +# 扩展一个新的迁移平台 + +本文档基于当前插件的真实实现,说明如何为 plugin-migrate 新增一个来源平台。目标读者是准备扩展 WordPress、Ghost、Typecho、Markdown 之外的新平台开发者。 + +## 先理解当前架构 + +当前迁移插件的核心原则很简单:**每个 Provider 只负责来源平台自己的读取、解析和转换;真正的导入流程全部走共享链路。** + +在当前实现中,一次迁移大致会经过以下阶段: + +1. 在 `ui/src/modules/index.ts` 注册 Provider,让它出现在平台选择页。 +2. `MigrateView.vue` 根据当前 Provider 渲染对应的解析组件。 +3. Provider 组件读取用户选择的文件、目录或链接,并产出统一的 `MigrateData`。 +4. `useMigratePreparation.ts` 根据解析结果决定是否进入统一附件处理,并生成最终要执行的任务分组。 +5. `useMigrateTaskRunner.ts` 负责用户归属预处理、本地附件上传预处理,以及按统一队列执行导入任务。 + +这意味着新增平台时,**不要在 Provider 内直接调用 Halo API,也不要在 Provider 内自己执行导入**。Provider 的职责应该停留在“把来源平台数据转换成当前插件认得的结构”这一层。 + +如果你发现自己正在考虑在 Provider 组件里直接创建文章、上传附件或运行任务,通常说明实现已经偏离当前架构了。 + +## 什么时候应该新增 Provider + +如果你的来源平台有独立的数据格式、文件结构、导出方式或媒体路径规则,就应该新增一个单独的 Provider。 + +典型例子包括: + +- 自定义导出文件格式,例如 XML、JSON、SQL dump、压缩包目录 +- 特定的附件路径约定,例如 `/wp-content/uploads/`、`content/images/`、`usr/uploads/` +- 特定的用户、评论、分类或页面模型 +- 需要自己的导入提示、文件选择方式或预解析逻辑 + +如果只是想增强所有平台都会复用的能力,例如统一附件处理、统一用户匹配、统一任务执行顺序,那么应该优先修改共享流程,而不是新增 Provider。 + +## 当前扩展点在哪里 + +新增一个平台时,通常会同时接触以下几处代码: + +| 位置 | 作用 | +| --- | --- | +| `ui/src/modules/index.ts` | 注册 Provider、配置附件处理选项 | +| `ui/src/modules//` | 存放该平台自己的组件和解析逻辑 | +| `ui/src/views/MigrateView.vue` | 承载共享迁移页面,一般不需要为单个平台加分支 | +| `ui/src/composables/use-migrate-preparation.ts` | 把解析结果转换成准备状态与任务分组 | +| `ui/src/composables/use-migrate-task.ts` | 把统一数据结构映射为真正的导入任务 | +| `ui/src/components/MigrateAttachmentHandler.vue` | 统一附件处理 UI | +| `ui/src/composables/use-migrate-task-runner.ts` | 执行用户预处理、附件预处理与任务队列 | + +如果你的新平台只是“新增一种来源格式”,大部分改动应该集中在 `ui/src/modules//` 和 `ui/src/modules/index.ts`,而不是扩散到整个迁移视图。 + +## 推荐的目录结构 + +建议每个新平台都使用独立目录,至少拆成“界面组件”和“解析逻辑”两层。例如新增 `demo` 平台时,可以这样组织: + +```text +ui/src/modules/demo/ +├── DemoMigrateDataParser.vue +└── use-demo-data-parser.ts +``` + +如果该平台还有额外的格式归一化、Front Matter 解析、附件路径处理等逻辑,可以继续在该目录下拆分多个辅助文件。原则是:**Provider 内部复杂度在自己的目录里消化,不要把平台特有逻辑塞回共享 composable。** + +## 第一步:注册 Provider + +所有平台入口都通过 `ui/src/modules/index.ts` 统一注册。新增 Provider 时,需要提供: + +- `name`:显示在平台选择页和迁移页面顶部的名称 +- `icon`:平台图标 +- `description`:平台简介 +- `importComponent`:解析组件 +- `options`:附件目录前缀、本地附件策略、自定义附件提示文案 + +一个最小示例如下: + +```ts +{ + name: 'Demo', + icon: demoIcon, + description: 'Demo 平台数据迁移', + importComponent: defineAsyncComponent(() => import('./demo/DemoMigrateDataParser.vue')), + options: { + attachmentFolderPath: 'migrate-from-demo', + localAttachmentStrategies: ['upload', 'manual'] + } +} +``` + +其中 `attachmentFolderPath` 很重要。共享任务生成逻辑会用它拼出本地附件记录里的相对路径标记,例如: + +```text +migrate-from-demo/path/to/file.jpg +``` + +如果你的 Provider 支持“手动迁移本地附件”,这个目录前缀应该从一开始就设计清楚,并和文档里的手动迁移说明保持一致。 + +## 第二步:实现 Provider 组件 + +Provider 组件的职责是展示来源平台自己的上传或输入界面,并在解析成功后通过 `v-model:data` 把统一结果交给外层。 + +当前 `MigrateView.vue` 通过下面的方式和 Provider 组件交互: + +- 传入 `v-model:data` +- 在切换平台时调用组件暴露的 `reset()` + +因此,一个 Provider 组件至少要满足以下约定: + +```ts +defineProps<{ + data: MigrateData +}>() + +const emit = defineEmits<{ + (event: 'update:data', value: MigrateData): void +}>() + +function reset() { + emit('update:data', {} as MigrateData) +} + +defineExpose({ + reset +}) +``` + +比较推荐的实现方式是: + +1. 在组件内处理文件选择、目录选择或 URL 输入 +2. 调用 `use-xxx-data-parser.ts` 之类的解析 composable +3. 解析前先清空旧数据 +4. 成功后 `emit('update:data', data)` +5. 失败时显示错误,但不要伪造成功结果 + +像 Markdown、WordPress、Ghost 这些现有 Provider 都遵循了这个模式,可以直接作为参考。 + +## 第三步:输出统一的 `MigrateData` + +不论来源平台原始格式多复杂,最终都必须收敛到 `MigrateData`: + +```ts +interface MigrateData { + sourceProvider?: string + tags?: MigrateTag[] + categories?: MigrateCategory[] + users?: MigrateSourceUser[] + posts?: MigratePost[] + pages?: MigrateSinglePage[] + comments?: (MigrateComment | MigrateReply)[] + menuItems?: MigrateMenu[] + moments?: MigrateMoment[] + photos?: MigratePhoto[] + links?: MigrateLink[] + attachments?: MigrateAttachment[] +} +``` + +这里有两个重要原则: + +1. **只输出当前平台确实能稳定提供的数据。** 不要为了“看起来完整”而伪造字段。 +2. **尽量在 Provider 内完成归一化。** 例如页面和文章的区分、评论层级的整理、附件路径的标准化,都应该在这里收敛。 + +共享流程不会替你理解来源平台的原始语义;共享流程只负责消费已经被归一化后的结果。 + +## 如何构造文章和页面 + +文章和页面最终都要包装成 Halo 已有的请求结构: + +- 文章使用 `MigratePost` +- 页面使用 `MigrateSinglePage` + +这两个结构内部直接持有 `PostRequest` 或 `SinglePageRequest`,因此最稳妥的做法是:**在 Provider 内就直接按 Halo 当前 API 所需结构去组装数据**。 + +同时,如果来源平台包含作者归属信息,应该额外填写: + +```ts +ownerRef?: { + sourceId: string +} +``` + +这里只需要保存来源平台用户 ID,不要在 Provider 内自行做 Halo 用户匹配。真正的匹配发生在导入执行前,由 `useUserPreprocessor()` 统一处理。 + +如果来源平台还带有访问量、点赞数、已审核评论数等统计数据,也可以通过 `counter` 附带到文章或页面上,后续共享任务生成器会自动追加对应的统计任务。 + +## 如何处理来源用户 + +如果平台有作者、评论者或其他可识别用户,建议尽量输出 `users` 列表,并为文章、页面、评论保留 `ownerRef`。 + +来源用户结构如下: + +```ts +interface MigrateSourceUser { + id: string + provider: string + displayName: string + email?: string + username?: string + slug?: string + avatar?: string + bio?: string + website?: string + role?: string +} +``` + +其中最有价值的是: + +- `id`:来源平台内的稳定主键 +- `provider`:来源平台标识 +- `displayName` +- `email` + +如果你能拿到邮箱,导入时共享用户预处理会优先尝试匹配已有 Halo 用户;匹配不到时再创建 `guest` 用户。 +如果你拿不到邮箱,也仍然建议输出稳定的来源用户 ID,这样至少能保留来源归属链路。 + +## 如何处理评论和回复 + +评论导入最容易出错的地方是层级语义。当前插件使用的是: + +- 顶级评论:`MigrateComment` +- 非顶级回复:`MigrateReply` + +并且评论、回复还需要显式说明它们属于哪种内容: + +```ts +refType: 'Post' | 'SinglePage' | 'Moment' +``` + +如果你的来源平台支持多级回复,需要在 Provider 内提前整理好: + +- 根评论是谁 +- 直接父回复是谁 +- 是否需要映射为 Halo 的 `quoteReply` + +不要把“如何从来源平台的父子关系推导 Halo 的 Comment / Reply 结构”留到共享流程里处理。 +WordPress、Typecho、Halo 1.x 这些 Provider 的评论逻辑都可以作为参考样例。 + +## 如何处理附件 + +附件是新增 Provider 时最需要提前设计好的部分,因为它直接影响后续“上传到 Halo”和“手动迁移”两种路径。 + +统一附件结构如下: + +```ts +interface MigrateAttachment { + id: number | string + name: string + path: string + url?: string + fileKey?: string + mediaType?: string + suffix?: string + width?: number + height?: number + size?: number + tags?: string[] + type: AttachmentType +} +``` + +你需要先回答三个问题: + +1. 这个平台的本地附件路径规则是什么? +2. 这个平台是否存在远程云存储附件? +3. 文章正文、封面、摘要或其他字段里引用附件的方式是什么? + +### 本地附件 + +如果附件来自本地目录,请把它们标记为 `type: 'LOCAL'`,并让 `path` 尽量保持来源平台中的相对路径语义,例如: + +- WordPress:`wp-content/uploads/...` +- Ghost:`content/images/...` +- Typecho:`usr/uploads/...` +- Halo 1.x:`upload/...` + +这很重要,因为共享任务生成器会根据 `attachmentFolderPath` 和 `item.path` 组合出最终的本地路径标记。 +如果你的 `path` 设计错了,后续无论是自动上传还是手动迁移,都会变得很难解释。 + +### 远程附件 + +如果来源平台能区分云存储类型,也可以直接输出对应的 `type`,例如 `MINIO`、`ALIOSS`、`TENCENTCOS` 等。共享附件处理器会为这些远程类型要求用户选择存储策略。 + +### 本地附件策略配置 + +是否允许 `upload` 或 `manual`,由 Provider 注册时的 `localAttachmentStrategies` 决定: + +```ts +options: { + localAttachmentStrategies: ['upload', 'manual'] +} +``` + +如果某个平台只适合自动上传,不适合保留原始路径,例如 Markdown,就应该明确限制为: + +```ts +options: { + localAttachmentStrategies: ['upload'] +} +``` + +### 自定义附件处理提示 + +如果默认的共享附件说明不够准确,可以通过 `attachmentHandlerDescriptions` 自定义提示文案。Ghost、Typecho、Halo 1.x 都已经这样做了。 + +如果你的平台对目录选择有强约束,例如“必须保留 `content/images` 这一层级”,就应该把这个要求明确写进这里,而不是只写在外部文档里。 + +## 共享流程会帮你做什么 + +当 Provider 成功输出 `MigrateData` 后,共享链路会自动接手后续流程: + +### 1. 数据准备 + +`useMigratePreparation.ts` 会维护以下状态流转: + +```text +parsedData + -> attachment handler result + -> preparedData + -> taskGroups +``` + +其中: + +- `parsedData`:Provider 刚解析出来的原始统一结果 +- `preparedData`:应用附件策略后的结果 +- `taskGroups`:最终要执行的导入任务列表 + +如果 `attachments` 为空,通常会直接跳过附件处理步骤。 + +### 2. 用户预处理 + +在真正执行导入前,`useMigrateTaskRunner.ts` 会调用 `useUserPreprocessor()`,统一处理来源用户与 Halo 用户的匹配关系。 + +### 3. 本地附件上传预处理 + +如果用户为本地附件选择了 **上传到 Halo**,任务执行前还会先调用 `useAttachmentPreprocessor()`,根据用户选择的目录上传文件并回写引用。 + +### 4. 任务执行 + +`useMigrateTask.ts` 会把 `MigrateData` 映射成任务分组,例如: + +- 标签 +- 分类 +- 文章 +- 页面 +- 评论 / 回复 +- 附件 +- 菜单 +- 瞬间 +- 图库 +- 链接 + +`useMigrateTaskRunner.ts` 再用 `fastq` 按固定并发执行这些任务。 +所以新增 Provider 时,只要你的输出结构符合当前约定,通常不需要自己关心“导入顺序怎么排”。 + +## 不建议的扩展方式 + +下面这些做法在当前架构下都不推荐: + +- 在 Provider 组件里直接请求 Halo API +- 在 Provider 组件里自己实现导入按钮和执行逻辑 +- 把某个平台专属的解析分支塞进 `MigrateView.vue` +- 把来源平台原始结构一路传到共享 composable 再解释 +- 为了兼容单个平台,在共享流程里引入大量 `if provider === 'xxx'` + +当前代码的维护重点是“平台特有逻辑留在平台目录,共享链路只消费统一结果”。 +只要能守住这个边界,后续再扩展平台时成本会低很多。 + +## 推荐开发步骤 + +如果你要新增一个全新的 Provider,建议按下面的顺序推进: + +1. 先读懂来源平台的导出格式、内容模型、附件路径和用户模型。 +2. 先设计 `MigrateData` 映射,再写 UI,不要一开始就堆组件。 +3. 实现 `use-xxx-data-parser.ts`,先保证能稳定输出统一结构。 +4. 再实现 `XXXMigrateDataParser.vue`,负责选择文件、调用 parser、展示错误。 +5. 注册到 `ui/src/modules/index.ts`。 +6. 如果有本地附件,再补齐 `attachmentFolderPath`、附件策略和说明文案。 +7. 最后补测试与文档。 + +## 测试建议 + +新增 Provider 后,至少应该补三类验证: + +1. **解析测试**:给定来源样例,断言输出的 `MigrateData` 结构正确。 +2. **边界测试**:空文件、坏数据、缺字段、异常评论层级、异常附件路径等。 +3. **类型与基础质量检查**:确保不会破坏现有前端构建链路。 + +当前前端常用命令: + +```bash +cd ui +pnpm test:unit +pnpm type-check +pnpm lint +``` + +如果只是改文档,则使用: + +```bash +cd docs +pnpm docs:build +``` + +## 一个最小可用的新增 Provider 清单 + +在提交前,可以用下面这份清单快速自查: + +- 已在 `ui/src/modules/index.ts` 注册 Provider +- 已创建 `ui/src/modules//` 目录 +- 解析组件支持 `v-model:data` +- 解析组件暴露了 `reset()` +- 解析逻辑最终输出 `MigrateData` +- 文章 / 页面 / 评论 / 附件路径都已完成归一化 +- 如有用户归属,已输出 `users` 与 `ownerRef` +- 如有本地附件,已配置 `attachmentFolderPath` +- 如有特殊附件说明,已配置 `attachmentHandlerDescriptions` +- 已补对应测试 +- 已补该平台的迁移文档 + +如果以上几点都满足,这个平台通常就已经接入到了当前插件的正确扩展链路中。 diff --git a/docs/provider/atom.md b/docs/provider/atom.md deleted file mode 100644 index 8c0209c..0000000 --- a/docs/provider/atom.md +++ /dev/null @@ -1,16 +0,0 @@ -# Atom Feed 数据迁移指引 - -本指引提供了从 `Atom Feed` 文件迁移至 `Halo 2.x` 的方案。 - -## 注意事项 - -1. 目标 Atom 文件需要符合 [标准 Atom Feed 规范](https://datatracker.ietf.org/doc/html/rfc4287) -2. Atom 迁移目前仅能导入文章,并且不支持分类标签等。 -3. 通过 Atom 迁移的文章内的图片及资源,将保持源站链接,迁移插件并不会将其下载至 Halo。 - -## 迁移 - -1. 点击左侧菜单的迁移进入迁移页面。 -2. 在选择渠道步骤中,选择 **Atom Feed**,点击下一步。 -3. 在导入数据步骤中,点击 **选择文件** 按钮,选择在 Atom 文件(XML 格式)或者输入 Atom 地址链接并解析,之后点击下一步。 -4. 在待迁移数据步骤中,可以再次审查待迁移的数据,审查结束后点击 **执行导入** 后,耐心等待即可,数据迁移完成后会有弹窗进行提示。 \ No newline at end of file diff --git a/docs/provider/ghost.md b/docs/provider/ghost.md deleted file mode 100644 index be4b23a..0000000 --- a/docs/provider/ghost.md +++ /dev/null @@ -1,63 +0,0 @@ -# Ghost 数据迁移 - -此插件提供了从 Ghost 迁移数据到 Halo 的功能,支持从 Ghost 导入的 JSON 文件解析数据并转换为 Halo 的数据格式。 - -注意事项: - -- 目前仅支持根据 Ghost 导出的 JSON 文件自动迁移数据,图片相关的数据迁移请参阅下面的文档手动迁移。 -- 由于平台之间的差异性,目前仅支持迁移**文章**、**标签**、**页面**数据,其他和 Ghost 平台相关的数据(包括主题模板、网站设置,用户等)无法迁移。 -- 迁移完成后,不建议立即删除 Ghost 的数据文件,可以先检查数据是否完整。 - -## 导出 Ghost 数据 - -进入 Ghost 的设置页面,找到 `Import/Export` 选项,然后点击 `Export content` 按钮即可导入 Ghost 的数据为 JSON 文件。 - -![Export Content](../img/ghost-1.png){data-zoomable} - -## 图片迁移 - -Ghost 平台目前没有将上传的图片信息持久化到数据库,所以目前只能手动复制 Ghost 平台的图片到 Halo 的附件目录下,并设置映射规则,让图片可以在 Halo 正常访问。 - -1. 进入 Ghost 所在的服务器,找到 Ghost 的附件存储目录,例如 `/ghost_path/content/images`,将该目录下的所有文件复制到 Halo 工作目录下的 `attachments/migrate-from-ghost` 目录中。 -2. 最终在 Halo 的附件目录下会得到如下所示的目录结构: - - ```shell - {halo-work-dir}/attachments - ├── migrate-from-ghost - │ ├── 2021 - │ ├── 2022 - └── upload - └── local - ``` - -3. 配置映射规则,将 Ghost 平台的图片路径映射到 Halo 的附件目录中。在 Halo 的 Docker 容器添加以下启动参数: - - ```shell - - --halo.attachment.resource-mappings[0].pathPattern=/content/images/** - - --halo.attachment.resource-mappings[0].locations[0]=migrate-from-ghost - ``` - - 如果你的 Halo 是通过配置文件配置的,也可以在配置文件中添加以下配置: - - ```yaml - halo: - attachment: - resource-mappings: - - pathPattern: /content/images/** - locations: - - migrate-from-ghost - ``` - -## 迁移数据 - -进入迁移页面,选择 Ghost。 - -![Ghost 2](../img/ghost-2.png){data-zoomable} - -然后选择从 Ghost 平台导出的 JSON 文件。 - -![Ghost 3](../img/ghost-3.png){data-zoomable} - -点击**执行导入**按钮即可开始迁移数据。 - -![Ghost 4](../img/ghost-4.png){data-zoomable} diff --git a/docs/provider/halo.md b/docs/provider/halo.md deleted file mode 100644 index c2e3684..0000000 --- a/docs/provider/halo.md +++ /dev/null @@ -1,71 +0,0 @@ -# Halo 1.x 数据迁移指引 - -本指引提供了从 `Halo 1.5 / 1.6` 文件迁移至 `Halo 2.x` 的方案。 - -## 前置需求 - -由于 Halo 2.0 的底层架构变动,无法兼容 1.x 的数据,导致无法平滑升级,所以需要进行数据迁移。为此,我们提供了从 Halo 1.5 / 1.6 版本迁移的方案。在进行迁移之前,**有几点注意事项和要求,如果你目前无法满足,建议先暂缓迁移。** - -- Halo 版本必须为 1.5.x 或 1.6.x。如果不满足,需要先升级到 1.5.x 或 1.6.x 版本。 -- Halo 2.0 不兼容 1.x 的主题,建议在升级前先查询你正在使用的主题是否已经支持 2.0。你可以访问 [halo-sigs/awesome-halo](https://github.com/halo-sigs/awesome-halo) 或 [应用市场](https://halo.run/store/apps?type=THEME) 查阅目前支持的主题。 -- Halo 2.0 目前没有内置 Markdown 编辑器,如果需要重新编辑迁移后的文章,需要额外安装 Markdown 编辑器插件。目前社区已经提供了以下插件: - - StackEdit: - - ByteMD: -- Halo 2.0 不再内置友情链接、日志、图库等模块,需要安装额外的插件,目前官方已提供: - - 链接管理: - - 图库: - - 瞬间(原日志): -- Halo 2.0 不再内置外部云存储的支持。需要安装额外的插件,目前官方已提供: - - S3(兼容国内主流的云存储): - - 阿里云 OSS: -- 在迁移过程中不会保留旧版本的用户数据,迁移完成之后,关于文章等数据的关联都将改为 Halo 2.0 的新用户。 -- 为了防止直接升级 2.0 导致 1.x 的数据受到破坏,我们已经将工作目录由 `~/.halo` 变更为 `~/.halo2`。 -- 目前 Halo 2.0 仅提供 Docker 部署方式,没有提供可执行 JAR 包,但可以自编译,请参考 [构建](https://docs.halo.run/developer-guide/core/build) 文档 -- 可以考虑先在本地运行一个 Halo 2.0,模拟一下导入,检查导入后是否满足要求。 - -如果遇到了迁移过程中的问题,也可以向我们提交 Issue: ,以上暂不支持的功能我们也会陆续完善。 - -## 备份数据 - -在进行迁移操作之前,我们强烈建议先**完整备份所有数据**,可以参考 [备份迁移](https://docs.halo.run/user-guide/backup-migration) 进行整站备份。 - -## 导出数据文件 - -在 Halo 1.5.x / 1.6.x 后台的小工具中提供了数据导出的功能,将最新的数据进行备份,然后下载即可。这个数据文件包含了数据库所有的数据,后续我们在 2.0 的导入插件中就是通过这个文件进行数据导入。 - -![halo-data-export.png](../img/halo-provider-data-export.png){data-zoomable} - -## 移动附件 - -- 本地存储的附件,只需要将 1.x 工作目录的 `upload` 目录里面的所有文件夹移动到 2.0 工作目录下的 `attachments/migrate-from-1.x` 文件夹即可。 -- 云存储的附件迁移会在迁移过程中进行。 - -## 安装插件 - -在迁移过程中,需要提前安装必要的插件: - -- 链接管理: -- 图库: -- 瞬间(原日志): -- S3(如果需要迁移存在云存储的附件,需要安装): - -## 配置存储策略(可选) - -> 如果在 Halo 1.x 中未使用云存储,可以跳过此步骤。 - -1. 安装 S3 插件。 -2. 进入附件管理页面。 -3. 点击页面右上角的 **存储策略** 按钮。 -4. 创建存储策略,选择 **S3 Object Storage**。 -5. 填写相关配置,点击 **保存** 即可。 - -## 迁移 - -1. 点击左侧菜单的迁移进入迁移页面。 -2. 在选择渠道步骤中,选择 **Halo**,点击下一步。 - - ![halo-provider-migrate-plugin](../img/halo-provider-migrate-plugin.png){data-zoomable} - -3. 在导入数据步骤中,点击 **选择文件** 按钮,选择在 Halo 1.5.x / 1.6.x 导出的数据文件(JSON 格式),之后点击下一步。 -4. 如果存在需要迁移的附件,则会出现 **设置附件存储策略** 步骤,此时选择之前创建的存储策略即可。完成之后点击下一步。 -5. 在待迁移数据步骤中,可以再次审查待迁移的数据,审查结束后点击 **执行导入** 后,耐心等待即可,数据迁移完成后会有弹窗进行提示。 diff --git a/docs/provider/hugo.md b/docs/provider/hugo.md deleted file mode 100644 index 766fdc9..0000000 --- a/docs/provider/hugo.md +++ /dev/null @@ -1,23 +0,0 @@ -# HUGO 数据迁移指引 - -本指引提供了从 [`HUGO`](https://gohugo.io/) 文件迁移至 `Halo 2.x` 的方案。 - -## 注意事项 - -HUGO 是一个十分强大与灵活的静态站点生成器,但没有提供统一的导出格式。本插件无意实现一个完整的 HUGO 解析器,仅支持其基础功能。注意: - -1. 不支持本地附件文件(包括图片)迁移,引用的在线资源(例如外部图床)不受影响。 -2. 不支持 HUGO 的模板属性文件 `_index.md`。 -3. 仅支持下列 matter: `title`, `slug`, `draft`, `categories`, `tags`, `date`。 -4. 仅处理文档内容,不解析 HUGO 配置文件。 -5. 本插件使用独立的 markdown 解析器,渲染效果可能和 HUGO 以及 Halo 中安装的 markdown 编辑器不同。 - -## 迁移 - -1. 请先手动将 HUGO 项目根目录下的 `content` 文件夹打包为 `zip` 压缩包。注意不要上传整个 HUGO 目录。 -2. 点击左侧菜单的迁移进入迁移页面。 -3. 在选择渠道步骤中,选择 **HUGO**,点击下一步。 -4. 在导入数据步骤中,点击 **选择文件** 按钮,选择刚才打包的文件,之后点击下一步。 -5. 按提示配置内容类别映射。确认后将显示解析出的内容。点击下一步进入最终确认。 -6. 在待迁移数据步骤中,可以再次审查待迁移的数据,审查结束后点击 **执行导入** 后,耐心等待即可,数据迁移完成后会有弹窗进行提示。 - diff --git a/docs/provider/rss.md b/docs/provider/rss.md deleted file mode 100644 index d839090..0000000 --- a/docs/provider/rss.md +++ /dev/null @@ -1,16 +0,0 @@ -# RSS 数据迁移指引 - -本指引提供了从 `RSS` 文件迁移至 `Halo 2.x` 的方案。 - -## 注意事项 - -1. 由于需要导入内容,因此除了需要符合[标准 RSS 规范](https://www.rssboard.org/rss-specification)之外,item 字段中还需要具有额外的 `content:encoded` 或者包含全文的 `description` 字段,否则迁移完成后的文章可能不正确。 -2. RSS 迁移目前仅能导入文章,并且不支持分类标签等。 -3. 通过 RSS 迁移的文章内的图片及资源,将保持源站链接,迁移插件并不会将其下载至 Halo。 - -## 迁移 - -1. 点击左侧菜单的迁移进入迁移页面。 -2. 在选择渠道步骤中,选择 **RSS**,点击下一步。 -3. 在导入数据步骤中,点击 **选择文件** 按钮,选择在 RSS 文件(XML 格式)或者输入 RSS 地址链接并解析,之后点击下一步。 -4. 在待迁移数据步骤中,可以再次审查待迁移的数据,审查结束后点击 **执行导入** 后,耐心等待即可,数据迁移完成后会有弹窗进行提示。 diff --git a/docs/provider/wordpress.md b/docs/provider/wordpress.md deleted file mode 100644 index 08ea0d1..0000000 --- a/docs/provider/wordpress.md +++ /dev/null @@ -1,72 +0,0 @@ -# WordPress 数据迁移指引 - -本指引提供了从 `Wordpress` 迁移至 `Halo 2.x` 的方案。 - -## 导出 WordPress WXR 文件 - -在 WordPress 管理后台的 **工具-导出** 菜单中,选择导出 **所有内容** 来导出你的 WordPress 数据,下载导出的文件后会得到一个 XML 文件。(有关详细信息可以查看 [WordPress 支持页面](https://wordpress.com/zh-cn/support/export/) ) - -## 附件迁移 - -在 WordPress 部署服务器后台,找到附件存储目录,例如 **/wordpress_path/blog.halo.run/wp-content**,打包该目录下的 **upload** 目录。 - -```cmd -tar -czvf upload.tgz uploads/ -``` - -通过上述命令可以将 **uploads** 目录打包为 upload.tgz 文件。将得到的 upload.tgz 文件拷贝到新的 Halo 服务器上,并在 Halo 工作目录下的 attachments 目录中创建与上一步配置的路由规则对应的 migrate-from-wp 子目录。 - -``` -mkdir -p {halo-work-dir}/attachments/migrate-from-wp -``` - -将 upload.tgz 中的文件解压到上述目录中。 - -``` -cd {halo-work-dir}/attachments/migrate-from-wp -tar --strip-components 1 -zxvf /path/to/upload.tgz -``` - -将会得到如下所示的目录 - -``` -{halo-work-dir}/attachments -├── migrate-from-wp -│ ├── 2011 -│ ├── 2015 -│ ├── 2016 -│ ├── 2017 -│ ├── 2018 -│ ├── 2019 -│ ├── 2020 -│ ├── 2021 -│ ├── 2022 -│ ├── elementor -│ ├── wpforms -│ └── wp-import-export-lite -└── upload - └── local -``` - -## 修改 Halo 配置 - -在 Halo 配置文件中增加如下配置,通过该配置,用户在 **{halo-work-dir}/attachments/migrate-from-wp/** \*/ 上传文件后,可以通过 **{HALO_EXTERNAL_URL}/wp-content/uploads/{文件名}** 访问到该文件,与 WordPress 中的附件链接规则一致。 - -```yaml -halo: - attachment: - resource-mappings: - - pathPattern: /wp-content/uploads/** - locations: - - migrate-from-wp -``` - -同时,修改 Halo 的 **HALO_EXTERNAL_URL** 配置,与原本的 WordPress 域名保持一致,例如 https://blog.halo.run。 - -## 迁移 - -1. 点击左侧菜单的迁移进入迁移页面。 -2. 在选择渠道步骤中,选择 **WordPress**,点击下一步。 -3. 在导入数据步骤中,点击 **选择文件** 按钮,选择在 WordPress 导出的 WXR 数据文件(XML 格式),之后点击下一步。 -4. 如果存在需要迁移的附件,则会出现 **设置附件存储策略** 步骤,选择本地至本地即可,完成之后点击下一步。 -5. 在待迁移数据步骤中,可以再次审查待迁移的数据,审查结束后点击 **执行导入** 后,耐心等待即可,数据迁移完成后会有弹窗进行提示。 diff --git a/docs/public/logo.svg b/docs/public/logo.svg deleted file mode 100644 index 70033d9..0000000 --- a/docs/public/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/images/preview.png b/images/preview.png new file mode 100644 index 0000000..f149270 Binary files /dev/null and b/images/preview.png differ diff --git a/ui/package.json b/ui/package.json index 2035a94..b5086fd 100644 --- a/ui/package.json +++ b/ui/package.json @@ -6,7 +6,7 @@ "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore", "prettier": "prettier --write .", "type-check": "vue-tsc --noEmit -p tsconfig.json --composite false", - "test:unit": "echo 'No tests'" + "test:unit": "rstest" }, "prettier": { "plugins": [ @@ -23,6 +23,7 @@ "@halo-dev/components": "2.22.0", "@halo-dev/ui-shared": "2.22.0", "@tanstack/vue-query": "^4.41.0", + "@tanstack/vue-virtual": "^3.13.23", "@vueuse/core": "^10.11.1", "@zip.js/zip.js": "^2.8.10", "axios": "^1.13.2", @@ -42,6 +43,7 @@ "@halo-dev/ui-plugin-bundler-kit": "2.22.0", "@iconify/json": "^2.2.408", "@rsbuild/core": "^1.6.6", + "@rstest/core": "^0.7.9", "@rushstack/eslint-patch": "^1.15.0", "@types/markdown-it": "^14.1.2", "@types/node": "^20.19.25", @@ -53,6 +55,7 @@ "@vue/tsconfig": "^0.7.0", "eslint": "^8.57.1", "eslint-plugin-vue": "^8.7.1", + "jsdom": "^26.1.0", "prettier": "^3.6.2", "prettier-plugin-organize-imports": "^4.3.0", "typescript": "~5.9.3", diff --git a/ui/pnpm-lock.yaml b/ui/pnpm-lock.yaml index e0c6ae6..3844501 100644 --- a/ui/pnpm-lock.yaml +++ b/ui/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: '@tanstack/vue-query': specifier: ^4.41.0 version: 4.41.0(vue@3.5.24(typescript@5.9.3)) + '@tanstack/vue-virtual': + specifier: ^3.13.23 + version: 3.13.23(vue@3.5.24(typescript@5.9.3)) '@vueuse/core': specifier: ^10.11.1 version: 10.11.1(vue@3.5.24(typescript@5.9.3)) @@ -72,6 +75,9 @@ importers: '@rsbuild/core': specifier: ^1.6.6 version: 1.6.6 + '@rstest/core': + specifier: ^0.7.9 + version: 0.7.9(jsdom@26.1.0) '@rushstack/eslint-patch': specifier: ^1.15.0 version: 1.15.0 @@ -105,6 +111,9 @@ importers: eslint-plugin-vue: specifier: ^8.7.1 version: 8.7.1(eslint@8.57.1) + jsdom: + specifier: ^26.1.0 + version: 26.1.0 prettier: specifier: ^3.6.2 version: 3.6.2 @@ -136,6 +145,9 @@ packages: '@antfu/utils@9.3.0': resolution: {integrity: sha512-9hFT4RauhcUzqOE4f1+frMKLZrgNog5b06I7VmZQV1BkvwvqrbC8EBZf3L1eEL2AKb6rNKjER0sEvJiSP1FXEA==} + '@asamuzakjp/css-color@3.2.0': + resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -174,6 +186,34 @@ packages: resolution: {integrity: sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==} engines: {node: '>=6.9.0'} + '@csstools/color-helpers@5.1.0': + resolution: {integrity: sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==} + engines: {node: '>=18'} + + '@csstools/css-calc@2.1.4': + resolution: {integrity: sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-color-parser@3.1.0': + resolution: {integrity: sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + '@emnapi/core@1.7.1': resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} @@ -418,21 +458,39 @@ packages: '@module-federation/error-codes@0.21.4': resolution: {integrity: sha512-ClpL5MereWNXh+EgDjz7w4RrC1JlisQTvXDa1gLxpviHafzNDfdViVmuhi9xXVuj+EYo8KU70Y999KHhk9424Q==} + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + '@module-federation/runtime-core@0.21.4': resolution: {integrity: sha512-SGpmoOLGNxZofpTOk6Lxb2ewaoz5wMi93AFYuuJB04HTVcngEK+baNeUZ2D/xewrqNIJoMY6f5maUjVfIIBPUA==} + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + '@module-federation/runtime-tools@0.21.4': resolution: {integrity: sha512-RzFKaL0DIjSmkn76KZRfzfB6dD07cvID84950jlNQgdyoQFUGkqD80L6rIpVCJTY/R7LzR3aQjHnoqmq4JPo3w==} + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + '@module-federation/runtime@0.21.4': resolution: {integrity: sha512-wgvGqryurVEvkicufJmTG0ZehynCeNLklv8kIk5BLIsWYSddZAE+xe4xov1kgH5fIJQAoQNkRauFFjVNlHoAkA==} + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + '@module-federation/sdk@0.21.4': resolution: {integrity: sha512-tzvhOh/oAfX++6zCDDxuvioHY4Jurf8vcfoCbKFxusjmyKr32GPbwFDazUP+OPhYCc3dvaa9oWU6X/qpUBLfJw==} + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + '@module-federation/webpack-bundler-runtime@0.21.4': resolution: {integrity: sha512-dusmR3uPnQh9u9ChQo3M+GLOuGFthfvnh7WitF/a1eoeTfRmXqnMFsXtZCUK+f/uXf+64874Zj/bhAgbBcVHZA==} + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} @@ -543,6 +601,11 @@ packages: engines: {node: '>=18.12.0'} hasBin: true + '@rsbuild/core@1.7.1': + resolution: {integrity: sha512-ULIE/Qh+Ne80Pm/aUPbRHUvwvIzpap07jYNFB47azI8w5Q3sDEC4Gn574jsluT/42iNDsZTFADRBog9FEvtN9Q==} + engines: {node: '>=18.12.0'} + hasBin: true + '@rsbuild/plugin-vue@1.0.7': resolution: {integrity: sha512-VIXFIU2gcpRjDxZNR9QUZjFqWu3oPZ5a5AUe8cyv2moJBQzRPJ18VtPnIIcdlQB36Q8lm2Do0SSVqkXAuui65g==} peerDependencies: @@ -553,53 +616,105 @@ packages: cpu: [arm64] os: [darwin] + '@rspack/binding-darwin-arm64@1.7.0': + resolution: {integrity: sha512-HMYrhvVh3sMRBXl6cSI2JqsvlHJKQ42qX+Sw4qbj7LeZBN6Gv4GjfL3cXRLUTdO37FOC0uLEUYgxVXetx/Y4sA==} + cpu: [arm64] + os: [darwin] + '@rspack/binding-darwin-x64@1.6.3': resolution: {integrity: sha512-X6TEPwc+FeApTgnzBefc/viuUP7LkqTY1GxltRYuabs8E7bExlmYoyB8KhIlC66NWtgjmcNWvZIkUlr9ZalBkQ==} cpu: [x64] os: [darwin] + '@rspack/binding-darwin-x64@1.7.0': + resolution: {integrity: sha512-R/SoR04ySmHPqoIBGC+SjP9zRGjL1fS908mdwBvQ1RfFinKu7a/o/5rxH/vxUUsVQrHCyX+o7YXpfWq9xpvyQA==} + cpu: [x64] + os: [darwin] + '@rspack/binding-linux-arm64-gnu@1.6.3': resolution: {integrity: sha512-uid2GjLzRnYNzNuTTS/hUZdYO6bNATWfaeuhGBU8RWrRgB+clJwhZskSwhfVrvmyTXYbHI95CJIPt4TbZ1FRTg==} cpu: [arm64] os: [linux] + '@rspack/binding-linux-arm64-gnu@1.7.0': + resolution: {integrity: sha512-jDCcso++qshu58+Iuo6oiL0XKuX04lDugL0qwrWHW8SS/EjZ2rc1J3yQx+XDW0PCQsfI2c9ji0IOW56PzW1hXQ==} + cpu: [arm64] + os: [linux] + '@rspack/binding-linux-arm64-musl@1.6.3': resolution: {integrity: sha512-ZJqqyEARBAnv9Gj3+0/PGIw87r8Vg0ZEKiRT9u5tPKK01dptF+xGv4xywAlahOeFUik4Dni5aHixbarStzN9Cw==} cpu: [arm64] os: [linux] + '@rspack/binding-linux-arm64-musl@1.7.0': + resolution: {integrity: sha512-0W49s0SQQhr3hZ8Zd7Auyf2pv4OTBr6wQhgWUQ6XeeMEjB16KpAVypSK5Jpn1ON0v9jAPLdod+a255rz8/f3kg==} + cpu: [arm64] + os: [linux] + '@rspack/binding-linux-x64-gnu@1.6.3': resolution: {integrity: sha512-/W8/X3CBGVY7plii5eUzyIEyCKiYx1lqrSVuD1HLlVHvzC4H2Kpk0EwvY2gUhnQRLU0Ym77Sh4PRd1ZOOzP4LQ==} cpu: [x64] os: [linux] + '@rspack/binding-linux-x64-gnu@1.7.0': + resolution: {integrity: sha512-oFjzjTD1MmG0ucAaP0Wyg9eobrsnFwZjEHa7LwyzWDRBeC3GWAF9T04Bqd6Ba6DgASGzU0BjEJcUpjvtXxO95Q==} + cpu: [x64] + os: [linux] + '@rspack/binding-linux-x64-musl@1.6.3': resolution: {integrity: sha512-h0Q3aM0fkRCd330DfRGZ9O3nk/rfRyXRX4dEIoLcLAq34VOmp3HZUP7rEy7feiJbuU4Atcvd0MD7U6RLwa1umQ==} cpu: [x64] os: [linux] + '@rspack/binding-linux-x64-musl@1.7.0': + resolution: {integrity: sha512-MNGslPLOsurdwOcoo6r0u8mLpw1ADar3hkx67WzwwMqYnem/Ky0aANJC2JvQHPC22mu01gCOukHYyEaUFTxcuw==} + cpu: [x64] + os: [linux] + '@rspack/binding-wasm32-wasi@1.6.3': resolution: {integrity: sha512-XLCDe+b52kAajlHutsyfh9o+uKQvgis+rLFb3XIJ9FfCcL8opTWVyeGLNHBUBn7cGPXGEYWd0EU9CZJrjV+iVw==} cpu: [wasm32] + '@rspack/binding-wasm32-wasi@1.7.0': + resolution: {integrity: sha512-eaZzkGpxzVESmaX/UALMiQO+eNppe/i1VWQksGRfdoUu0rILqr/YDjsWFTcpbI9Dt3fg2kshHawBHxfwtxHcZQ==} + cpu: [wasm32] + '@rspack/binding-win32-arm64-msvc@1.6.3': resolution: {integrity: sha512-BU3VjyzAf8noYqb7NPuUZu9VVHRH2b+x4Q5A2oqQwEq4JzW/Mrhcd//vnRpSE9HHuezxTpQTtSSsB/YqV7BkDg==} cpu: [arm64] os: [win32] + '@rspack/binding-win32-arm64-msvc@1.7.0': + resolution: {integrity: sha512-XFg4l7sOhupnpG0soOfzYLeF2cgpSJMenmjmdzd9y06CotTyVId0hNoS7y+A7hEP8XGf3YPbdiUL5UDp6+DRBA==} + cpu: [arm64] + os: [win32] + '@rspack/binding-win32-ia32-msvc@1.6.3': resolution: {integrity: sha512-W2yHUFra9N8QbBKQC6PcyOwOJbj8qrmechK97XVQAwo0GWGnQKMphivJrbxHOxCz89FGn9kLGRakTH04bHT4MQ==} cpu: [ia32] os: [win32] + '@rspack/binding-win32-ia32-msvc@1.7.0': + resolution: {integrity: sha512-eWt2XV6la/c0IlU/18RlhQsqwHGShSypwA3kt4s/dpfOK0YB1h4f0fYeUZuvj2X0MIoJQGhMofMrgA35/IcAcw==} + cpu: [ia32] + os: [win32] + '@rspack/binding-win32-x64-msvc@1.6.3': resolution: {integrity: sha512-mxep+BqhySoWweQSXnUaYAHx+C8IzOTNMJYuAVchXn9bMG6SPAXvZqAF8X/Q+kNg8X7won8Sjz+O+OUw3OTyOQ==} cpu: [x64] os: [win32] + '@rspack/binding-win32-x64-msvc@1.7.0': + resolution: {integrity: sha512-LOL5G8rfbAwlmusx+t98r9QzuGRz+L9Bg+8s5s6K/Qe64iemcNIuxGr5QLVq1jLa0SGNTeog4N21pAzlkWh4jw==} + cpu: [x64] + os: [win32] + '@rspack/binding@1.6.3': resolution: {integrity: sha512-liRgxMjHWDL225c41pH4ZcFtPN48LM0+St3iylwavF5JFSqBv86R/Cv5+M+WLrhcihCQsxDwBofipyosJIFmmA==} + '@rspack/binding@1.7.0': + resolution: {integrity: sha512-xO+pZKG2dvU9CuRTTi+DcCc4p+CZhBJlvuYikBja/0a62cTntQV2PWV+/xU1a6Vbo89yNz158LR05nvjtKVwTw==} + '@rspack/core@1.6.3': resolution: {integrity: sha512-03pyxRtpZ9SNwuA4XHLcFG/jmmWqSd4NaXQGrwOHU0UoPKpVPTqkxtQYZLCfeNtDfAA9v2KPqgJ3b40x8nJGeA==} engines: {node: '>=18.12.0'} @@ -609,15 +724,40 @@ packages: '@swc/helpers': optional: true + '@rspack/core@1.7.0': + resolution: {integrity: sha512-uDxPQsPh/+2DnOISuKnUiXZ9M0y2G1BOsI0IesxPJGp42ME2QW7axbJfUqD3bwp4bi3RN2zqh56NgxU/XETQvA==} + engines: {node: '>=18.12.0'} + peerDependencies: + '@swc/helpers': '>=0.5.1' + peerDependenciesMeta: + '@swc/helpers': + optional: true + '@rspack/lite-tapable@1.1.0': resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} + '@rstest/core@0.7.9': + resolution: {integrity: sha512-RHNPS1MDUxtf+1Z0YZi+vIQ13SdvCbcbpzDA7XHcPziTRy2mAPg8nfcms+XzbIp95KXH75ucAhgAKNFO0QgARA==} + engines: {node: '>=18.12.0'} + hasBin: true + peerDependencies: + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + happy-dom: + optional: true + jsdom: + optional: true + '@rushstack/eslint-patch@1.15.0': resolution: {integrity: sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==} '@swc/helpers@0.5.17': resolution: {integrity: sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==} + '@swc/helpers@0.5.21': + resolution: {integrity: sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==} + '@tanstack/match-sorter-utils@8.8.4': resolution: {integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==} engines: {node: '>=12'} @@ -625,6 +765,9 @@ packages: '@tanstack/query-core@4.41.0': resolution: {integrity: sha512-193R4Jp9hjvlij6LryxrB5Mpbffd2L9PeWh3KlIy/hJV4SkBOfiQZ+jc5qAZLDCrdbkA5FjGj+UoDYw6TcNnyA==} + '@tanstack/virtual-core@3.13.23': + resolution: {integrity: sha512-zSz2Z2HNyLjCplANTDyl3BcdQJc2k1+yyFoKhNRmCr7V7dY8o8q5m8uFTI1/Pg1kL+Hgrz6u3Xo6eFUB7l66cg==} + '@tanstack/vue-query@4.41.0': resolution: {integrity: sha512-uqRasE5l4yxa1urhk+iC4wFTdKkjm89Vyo6CZSYQS3O7KggZnY3ZYdV7QLmv9nUdJ1L6QhQN8CI5ycPBcH4rwA==} peerDependencies: @@ -634,9 +777,20 @@ packages: '@vue/composition-api': optional: true + '@tanstack/vue-virtual@3.13.23': + resolution: {integrity: sha512-b5jPluAR6U3eOq6GWAYSpj3ugnAIZgGR0e6aGAgyRse0Yu6MVQQ0ZWm9SArSXWtageogn6bkVD8D//c4IjW3xQ==} + peerDependencies: + vue: ^2.7.0 || ^3.0.0 + '@tybys/wasm-util@0.10.1': resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/eslint-scope@3.7.7': resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} @@ -1025,6 +1179,10 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + agent-base@7.1.4: + resolution: {integrity: sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==} + engines: {node: '>= 14'} + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} peerDependencies: @@ -1066,6 +1224,10 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -1168,6 +1330,9 @@ packages: core-js@3.46.0: resolution: {integrity: sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA==} + core-js@3.47.0: + resolution: {integrity: sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1181,9 +1346,17 @@ packages: engines: {node: '>=4'} hasBin: true + cssstyle@4.6.0: + resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} + engines: {node: '>=18'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + de-indent@1.0.2: resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} @@ -1196,6 +1369,9 @@ packages: supports-color: optional: true + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -1238,6 +1414,10 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + es-define-property@1.0.1: resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} engines: {node: '>= 0.4'} @@ -1532,6 +1712,22 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + + https-proxy-agent@7.0.6: + resolution: {integrity: sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==} + engines: {node: '>= 14'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -1575,6 +1771,9 @@ packages: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -1593,6 +1792,15 @@ packages: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true + jsdom@26.1.0: + resolution: {integrity: sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -1638,6 +1846,9 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} @@ -1721,6 +1932,9 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + object-inspect@1.13.4: resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} engines: {node: '>= 0.4'} @@ -1750,6 +1964,9 @@ packages: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -1837,6 +2054,10 @@ packages: resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==} engines: {node: '>=6'} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + qs@6.14.0: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} @@ -1883,12 +2104,22 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rrweb-cssom@0.8.0: + resolution: {integrity: sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + schema-utils@4.3.2: resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==} engines: {node: '>= 10.13.0'} @@ -1970,6 +2201,9 @@ packages: resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} engines: {node: '>=10'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.11.11: resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -2009,6 +2243,17 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tldts-core@6.1.86: + resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + + tldts@6.1.86: + resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -2020,6 +2265,14 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@5.1.2: + resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} + engines: {node: '>=16'} + + tr46@5.1.1: + resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} + engines: {node: '>=18'} + transliteration@2.3.5: resolution: {integrity: sha512-HAGI4Lq4Q9dZ3Utu2phaWgtm3vB6PkLUFqWAScg/UW+1eZ/Tg6Exo4oC0/3VUol/w4BlefLhUUSVBr/9/ZGQOw==} engines: {node: '>=6.0.0'} @@ -2230,10 +2483,18 @@ packages: typescript: optional: true + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + watchpack@2.4.4: resolution: {integrity: sha512-c5EGNOiyxxV5qmTtAB7rbiXxi1ooX1pQKMLX/MIabJjRA0SJBQOjKF+KSVfHkr9U1cADPon0mRiVe/riyaiDUA==} engines: {node: '>=10.13.0'} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + webpack-sources@3.3.3: resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} @@ -2251,6 +2512,19 @@ packages: webpack-cli: optional: true + whatwg-encoding@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.2.0: + resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} + engines: {node: '>=18'} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -2263,6 +2537,25 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@8.20.0: + resolution: {integrity: sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2295,6 +2588,14 @@ snapshots: '@antfu/utils@9.3.0': {} + '@asamuzakjp/css-color@3.2.0': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 10.4.3 + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -2344,6 +2645,26 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@csstools/color-helpers@5.1.0': {} + + '@csstools/css-calc@2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-color-parser@3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/color-helpers': 5.1.0 + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + '@emnapi/core@1.7.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -2553,29 +2874,54 @@ snapshots: '@module-federation/error-codes@0.21.4': {} + '@module-federation/error-codes@0.22.0': {} + '@module-federation/runtime-core@0.21.4': dependencies: '@module-federation/error-codes': 0.21.4 '@module-federation/sdk': 0.21.4 + '@module-federation/runtime-core@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@module-federation/runtime-tools@0.21.4': dependencies: '@module-federation/runtime': 0.21.4 '@module-federation/webpack-bundler-runtime': 0.21.4 + '@module-federation/runtime-tools@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/webpack-bundler-runtime': 0.22.0 + '@module-federation/runtime@0.21.4': dependencies: '@module-federation/error-codes': 0.21.4 '@module-federation/runtime-core': 0.21.4 '@module-federation/sdk': 0.21.4 + '@module-federation/runtime@0.22.0': + dependencies: + '@module-federation/error-codes': 0.22.0 + '@module-federation/runtime-core': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@module-federation/sdk@0.21.4': {} + '@module-federation/sdk@0.22.0': {} + '@module-federation/webpack-bundler-runtime@0.21.4': dependencies: '@module-federation/runtime': 0.21.4 '@module-federation/sdk': 0.21.4 + '@module-federation/webpack-bundler-runtime@0.22.0': + dependencies: + '@module-federation/runtime': 0.22.0 + '@module-federation/sdk': 0.22.0 + '@napi-rs/wasm-runtime@1.0.7': dependencies: '@emnapi/core': 1.7.1 @@ -2659,6 +3005,14 @@ snapshots: core-js: 3.46.0 jiti: 2.6.1 + '@rsbuild/core@1.7.1': + dependencies: + '@rspack/core': 1.7.0(@swc/helpers@0.5.21) + '@rspack/lite-tapable': 1.1.0 + '@swc/helpers': 0.5.21 + core-js: 3.47.0 + jiti: 2.6.1 + '@rsbuild/plugin-vue@1.0.7(@rsbuild/core@1.6.6)(@vue/compiler-sfc@3.5.24)(vue@3.5.24(typescript@5.9.3))': dependencies: '@rsbuild/core': 1.6.6 @@ -2675,35 +3029,67 @@ snapshots: '@rspack/binding-darwin-arm64@1.6.3': optional: true + '@rspack/binding-darwin-arm64@1.7.0': + optional: true + '@rspack/binding-darwin-x64@1.6.3': optional: true + '@rspack/binding-darwin-x64@1.7.0': + optional: true + '@rspack/binding-linux-arm64-gnu@1.6.3': optional: true + '@rspack/binding-linux-arm64-gnu@1.7.0': + optional: true + '@rspack/binding-linux-arm64-musl@1.6.3': optional: true + '@rspack/binding-linux-arm64-musl@1.7.0': + optional: true + '@rspack/binding-linux-x64-gnu@1.6.3': optional: true + '@rspack/binding-linux-x64-gnu@1.7.0': + optional: true + '@rspack/binding-linux-x64-musl@1.6.3': optional: true + '@rspack/binding-linux-x64-musl@1.7.0': + optional: true + '@rspack/binding-wasm32-wasi@1.6.3': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true + '@rspack/binding-wasm32-wasi@1.7.0': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + '@rspack/binding-win32-arm64-msvc@1.6.3': optional: true + '@rspack/binding-win32-arm64-msvc@1.7.0': + optional: true + '@rspack/binding-win32-ia32-msvc@1.6.3': optional: true + '@rspack/binding-win32-ia32-msvc@1.7.0': + optional: true + '@rspack/binding-win32-x64-msvc@1.6.3': optional: true + '@rspack/binding-win32-x64-msvc@1.7.0': + optional: true + '@rspack/binding@1.6.3': optionalDependencies: '@rspack/binding-darwin-arm64': 1.6.3 @@ -2717,6 +3103,19 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.6.3 '@rspack/binding-win32-x64-msvc': 1.6.3 + '@rspack/binding@1.7.0': + optionalDependencies: + '@rspack/binding-darwin-arm64': 1.7.0 + '@rspack/binding-darwin-x64': 1.7.0 + '@rspack/binding-linux-arm64-gnu': 1.7.0 + '@rspack/binding-linux-arm64-musl': 1.7.0 + '@rspack/binding-linux-x64-gnu': 1.7.0 + '@rspack/binding-linux-x64-musl': 1.7.0 + '@rspack/binding-wasm32-wasi': 1.7.0 + '@rspack/binding-win32-arm64-msvc': 1.7.0 + '@rspack/binding-win32-ia32-msvc': 1.7.0 + '@rspack/binding-win32-x64-msvc': 1.7.0 + '@rspack/core@1.6.3(@swc/helpers@0.5.17)': dependencies: '@module-federation/runtime-tools': 0.21.4 @@ -2725,20 +3124,42 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.17 + '@rspack/core@1.7.0(@swc/helpers@0.5.21)': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.0 + '@rspack/lite-tapable': 1.1.0 + optionalDependencies: + '@swc/helpers': 0.5.21 + '@rspack/lite-tapable@1.1.0': {} + '@rstest/core@0.7.9(jsdom@26.1.0)': + dependencies: + '@rsbuild/core': 1.7.1 + '@types/chai': 5.2.3 + tinypool: 1.1.1 + optionalDependencies: + jsdom: 26.1.0 + '@rushstack/eslint-patch@1.15.0': {} '@swc/helpers@0.5.17': dependencies: tslib: 2.8.1 + '@swc/helpers@0.5.21': + dependencies: + tslib: 2.8.1 + '@tanstack/match-sorter-utils@8.8.4': dependencies: remove-accents: 0.4.2 '@tanstack/query-core@4.41.0': {} + '@tanstack/virtual-core@3.13.23': {} + '@tanstack/vue-query@4.41.0(vue@3.5.24(typescript@5.9.3))': dependencies: '@tanstack/match-sorter-utils': 8.8.4 @@ -2747,11 +3168,23 @@ snapshots: vue: 3.5.24(typescript@5.9.3) vue-demi: 0.13.11(vue@3.5.24(typescript@5.9.3)) + '@tanstack/vue-virtual@3.13.23(vue@3.5.24(typescript@5.9.3))': + dependencies: + '@tanstack/virtual-core': 3.13.23 + vue: 3.5.24(typescript@5.9.3) + '@tybys/wasm-util@0.10.1': dependencies: tslib: 2.8.1 optional: true + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + '@types/eslint-scope@3.7.7': dependencies: '@types/eslint': 9.6.1 @@ -3322,6 +3755,8 @@ snapshots: acorn@8.15.0: {} + agent-base@7.1.4: {} + ajv-formats@2.1.1(ajv@8.17.1): optionalDependencies: ajv: 8.17.1 @@ -3362,6 +3797,8 @@ snapshots: array-union@2.1.0: {} + assertion-error@2.0.1: {} + asynckit@0.4.0: {} axios@1.13.2: @@ -3465,6 +3902,8 @@ snapshots: core-js@3.46.0: {} + core-js@3.47.0: {} + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -3478,8 +3917,18 @@ snapshots: cssesc@3.0.0: {} + cssstyle@4.6.0: + dependencies: + '@asamuzakjp/css-color': 3.2.0 + rrweb-cssom: 0.8.0 + csstype@3.1.3: {} + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + de-indent@1.0.2: optional: true @@ -3487,6 +3936,8 @@ snapshots: dependencies: ms: 2.1.3 + decimal.js@10.6.0: {} + deep-is@0.1.4: {} defu@6.1.4: {} @@ -3522,6 +3973,8 @@ snapshots: entities@4.5.0: {} + entities@6.0.1: {} + es-define-property@1.0.1: {} es-errors@1.3.0: {} @@ -3843,6 +4296,28 @@ snapshots: he@1.2.0: optional: true + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.6: + dependencies: + agent-base: 7.1.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + ignore@5.3.2: {} import-fresh@3.3.0: @@ -3875,6 +4350,8 @@ snapshots: is-path-inside@3.0.3: {} + is-potential-custom-element-name@1.0.1: {} + isexe@2.0.0: {} jest-worker@27.5.1: @@ -3891,6 +4368,33 @@ snapshots: dependencies: argparse: 2.0.1 + jsdom@26.1.0: + dependencies: + cssstyle: 4.6.0 + data-urls: 5.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 5.1.2 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.2.0 + ws: 8.20.0 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@3.1.0: {} json-parse-even-better-errors@2.3.1: {} @@ -3928,6 +4432,8 @@ snapshots: lodash@4.17.21: {} + lru-cache@10.4.3: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4001,6 +4507,8 @@ snapshots: dependencies: boolbase: 1.0.0 + nwsapi@2.2.23: {} + object-inspect@1.13.4: {} ofetch@1.5.1: @@ -4036,6 +4544,10 @@ snapshots: dependencies: callsites: 3.1.0 + parse5@7.3.0: + dependencies: + entities: 6.0.1 + path-browserify@1.0.1: {} path-exists@4.0.0: {} @@ -4102,6 +4614,8 @@ snapshots: punycode@2.3.0: {} + punycode@2.3.1: {} + qs@6.14.0: dependencies: side-channel: 1.1.0 @@ -4154,12 +4668,20 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 + rrweb-cssom@0.8.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 safe-buffer@5.2.1: {} + safer-buffer@2.1.2: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + schema-utils@4.3.2: dependencies: '@types/json-schema': 7.0.15 @@ -4248,6 +4770,8 @@ snapshots: dependencies: has-flag: 4.0.0 + symbol-tree@3.2.4: {} + synckit@0.11.11: dependencies: '@pkgr/core': 0.2.9 @@ -4279,6 +4803,14 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinypool@1.1.1: {} + + tldts-core@6.1.86: {} + + tldts@6.1.86: + dependencies: + tldts-core: 6.1.86 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -4287,6 +4819,14 @@ snapshots: totalist@3.0.1: {} + tough-cookie@5.1.2: + dependencies: + tldts: 6.1.86 + + tr46@5.1.1: + dependencies: + punycode: 2.3.1 + transliteration@2.3.5: dependencies: yargs: 17.7.2 @@ -4482,11 +5022,17 @@ snapshots: optionalDependencies: typescript: 5.9.3 + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + watchpack@2.4.4: dependencies: glob-to-regexp: 0.4.1 graceful-fs: 4.2.11 + webidl-conversions@7.0.0: {} + webpack-sources@3.3.3: {} webpack-virtual-modules@0.6.2: {} @@ -4522,6 +5068,17 @@ snapshots: - esbuild - uglify-js + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.2.0: + dependencies: + tr46: 5.1.1 + webidl-conversions: 7.0.0 + which@2.0.2: dependencies: isexe: 2.0.0 @@ -4534,6 +5091,12 @@ snapshots: wrappy@1.0.2: {} + ws@8.20.0: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + y18n@5.0.8: {} yaml@2.8.1: {} diff --git a/ui/rstest.config.ts b/ui/rstest.config.ts new file mode 100644 index 0000000..11ea537 --- /dev/null +++ b/ui/rstest.config.ts @@ -0,0 +1,6 @@ +import { defineConfig } from '@rstest/core' + +export default defineConfig({ + include: ['tests/**/*.test.ts'], + testEnvironment: 'jsdom' +}) diff --git a/ui/src/assets/halo.png b/ui/src/assets/halo.png new file mode 100644 index 0000000..e730531 Binary files /dev/null and b/ui/src/assets/halo.png differ diff --git a/ui/src/assets/markdown.svg b/ui/src/assets/markdown.svg new file mode 100644 index 0000000..74c121d --- /dev/null +++ b/ui/src/assets/markdown.svg @@ -0,0 +1 @@ +Markdown \ No newline at end of file diff --git a/ui/src/components/AttachmentPolicy.vue b/ui/src/components/AttachmentPolicy.vue index 453566e..d738799 100644 --- a/ui/src/components/AttachmentPolicy.vue +++ b/ui/src/components/AttachmentPolicy.vue @@ -39,13 +39,15 @@ useQuery({ } }) if (props.attachments) { - attachmentTypes.value = Object.keys(groupBy(props.attachments, item => item.type)).map((type) => { - return { - type: type, - policyName: - type == 'LOCAL' ? localPolicyOptions.value[0]?.value : policyOptions.value[0]?.value + attachmentTypes.value = Object.keys(groupBy(props.attachments, (item) => item.type)).map( + (type) => { + return { + type: type, + policyName: + type == 'LOCAL' ? localPolicyOptions.value[0]?.value : policyOptions.value[0]?.value + } } - }) + ) } localPolicyOptions.value = policyOptions.value.filter((item) => item.templateName === 'local') diff --git a/ui/src/components/FileSelector.vue b/ui/src/components/FileSelector.vue index 3ce2402..595d2d9 100644 --- a/ui/src/components/FileSelector.vue +++ b/ui/src/components/FileSelector.vue @@ -1,9 +1,12 @@ + diff --git a/ui/src/components/MigrateAttachmentHandler.vue b/ui/src/components/MigrateAttachmentHandler.vue new file mode 100644 index 0000000..c13b915 --- /dev/null +++ b/ui/src/components/MigrateAttachmentHandler.vue @@ -0,0 +1,350 @@ + + + diff --git a/ui/src/components/MigratePreview.vue b/ui/src/components/MigratePreview.vue deleted file mode 100644 index a7a6ac9..0000000 --- a/ui/src/components/MigratePreview.vue +++ /dev/null @@ -1,84 +0,0 @@ - - diff --git a/ui/src/components/MigratePreviewItem.vue b/ui/src/components/MigratePreviewItem.vue deleted file mode 100644 index 1c14059..0000000 --- a/ui/src/components/MigratePreviewItem.vue +++ /dev/null @@ -1,14 +0,0 @@ - - diff --git a/ui/src/components/MigrateProvider.vue b/ui/src/components/MigrateProvider.vue index 737dd16..b3c6143 100644 --- a/ui/src/components/MigrateProvider.vue +++ b/ui/src/components/MigrateProvider.vue @@ -1,6 +1,5 @@ +