feat(stage-web): load and save live2d model (#41)

* wip: ui

* wip: load local live2d zip

* feat(stage-web): save model to indexed db

* fix: apply suggestion

Co-authored-by: Neko <neko@ayaka.moe>

---------

Co-authored-by: Neko <neko@ayaka.moe>
This commit is contained in:
LemonNeko
2025-03-03 01:39:37 +08:00
committed by GitHub
co-authored by Neko
parent b6abd69a36
commit 0528239bfd
12 changed files with 400 additions and 88 deletions
+4 -1
View File
@@ -49,5 +49,8 @@
"yaml"
],
"typescript.tsdk": "node_modules/typescript/lib"
"typescript.tsdk": "node_modules/typescript/lib",
"cSpell.words": [
"localforage"
]
}
+12
View File
@@ -54,6 +54,18 @@ settings:
microphone: Microphone
model-provider:
title: Model Providers
live2d:
title: Live2D Settings
change-model:
title: Change Model
from-url: Load from URL
from-url-placeholder: Enter Live2D model URL
from-url-confirm: Load
from-file: Load from File
from-file-select: Select
map-motions:
title: Map Motions
play: Play Motion
models: Model
openai-api-key:
label: OpenAI API Key
+12
View File
@@ -41,6 +41,18 @@ settings:
title: 语言
model-provider:
title: 模型提供商
live2d:
title: Live2D 设置
change-model:
title: 更换模型
from-url: 从 URL 加载
from-url-placeholder: 输入 Live2D 模型 URL
from-url-confirm: 加载
from-file: 从文件加载
from-file-select: 选择
map-motions:
title: 映射动作
play: 播放动作
models: 模型
openai-api-key:
label: OpenAI API 密钥
+1
View File
@@ -61,6 +61,7 @@
"drizzle-kit": "^0.30.5",
"drizzle-orm": "^0.40.0",
"jszip": "^3.10.1",
"localforage": "^1.10.0",
"nprogress": "^0.2.0",
"ofetch": "^1.4.1",
"onnxruntime-web": "^1.20.1",
@@ -0,0 +1,102 @@
<script setup lang="ts">
import { Collapsable } from '@proj-airi/stage-ui/components'
import { useSettings } from '@proj-airi/stage-ui/stores'
import { useFileDialog } from '@vueuse/core'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const modelFile = useFileDialog({
accept: 'application/zip',
})
const settings = useSettings()
const modelUrl = ref(settings.live2dModel)
modelFile.onChange((files) => {
if (files && files.length > 0) {
settings.live2dModel = files[0]
}
})
</script>
<template>
<Collapsable w-full>
<template #trigger="slotProps">
<button
bg="zinc-100 dark:zinc-800"
hover="bg-zinc-200 dark:bg-zinc-700"
transition="all ease-in-out duration-250"
w-full flex items-center gap-1.5 rounded-lg px-4 py-3 outline-none
class="[&_.provider-icon]:grayscale-100 [&_.provider-icon]:hover:grayscale-0"
@click="slotProps.setVisible(!slotProps.visible)"
>
<div flex="~ row 1" items-center gap-1.5>
<div
i-solar:magic-stick-3-bold-duotone class="provider-icon size-6"
transition="filter duration-250 ease-in-out"
/>
<div>
{{ t('settings.live2d.change-model.title') }}
</div>
</div>
<div transform transition="transform duration-250" :class="{ 'rotate-180': slotProps.visible }">
<div i-solar:alt-arrow-down-bold-duotone />
</div>
</button>
</template>
<div p-4>
<div class="space-y-4">
<div class="flex items-center justify-between">
<div>
<div class="flex items-center gap-1 text-sm font-medium">
{{ t('settings.live2d.change-model.from-url') }}
</div>
</div>
<div>
<input
v-model="modelUrl"
:disabled="settings.loadingLive2dModel"
type="text"
rounded
border="zinc-300 dark:zinc-800 solid 1 focus:zinc-400 dark:focus:zinc-600"
transition="border duration-250 ease-in-out"
px-2 py-1 text-sm outline-none
:placeholder="t('settings.live2d.change-model.from-url-placeholder')"
>
<button
:disabled="settings.loadingLive2dModel"
bg="zinc-100 dark:zinc-800"
hover="bg-zinc-200 dark:bg-zinc-700"
transition="all ease-in-out duration-250"
ml-2 rounded px-2 py-1 text-sm outline-none
@click="settings.live2dModel = modelUrl"
>
{{ t('settings.live2d.change-model.from-url-confirm') }}
</button>
</div>
</div>
<div class="flex items-center justify-between">
<div>
<div class="flex items-center gap-1 text-sm font-medium">
{{ t('settings.live2d.change-model.from-file') }}
</div>
</div>
<button
:disabled="settings.loadingLive2dModel"
rounded
bg="zinc-100 dark:zinc-800"
hover="bg-zinc-200 dark:bg-zinc-700"
transition="all ease-in-out duration-250"
px-2 py-1 text-sm outline-none
@click="modelFile.open()"
>
{{ t('settings.live2d.change-model.from-file-select') }}
</button>
</div>
</div>
</div>
</Collapsable>
</template>
@@ -24,6 +24,11 @@ function navigateToProviders() {
currentView.value = 'providers'
}
function navigateToLive2D() {
slideDirection.value = 'forward'
currentView.value = 'live2d'
}
function navigateBack() {
slideDirection.value = 'backward'
currentView.value = 'main'
@@ -122,6 +127,22 @@ function navigateBack() {
</div>
</div>
</label>
<!-- Live2D Setting -->
<div
grid="~ cols-[150px_1fr]"
bg="zinc-100 dark:zinc-800"
hover="bg-zinc-200 dark:bg-zinc-700"
transition="all ease-in-out duration-250"
cursor-pointer items-center gap-1.5 rounded-lg px-4 py-3
@click="navigateToLive2D"
>
<div text="sm">
<span>{{ t('settings.live2d.title') }}</span>
</div>
<div flex="~ row" w-full justify-end>
<div i-solar:alt-arrow-right-bold-duotone />
</div>
</div>
</div>
</div>
</div>
@@ -141,6 +162,21 @@ function navigateBack() {
</div>
<ModelProviderSettings />
</div>
<!-- Live2D Settings View -->
<div v-else-if="currentView === 'live2d'" key="live2d">
<div mb-4 flex items-center gap-2>
<button
text="zinc-800/80 dark:zinc-200/80"
@click="navigateBack"
>
<div i-solar:alt-arrow-left-bold-duotone />
</button>
<h2 text="zinc-800/80 dark:zinc-200/80 xl" font-bold>
{{ t('settings.live2d.title') }}
</h2>
</div>
<Live2DSettings />
</div>
</Transition>
</div>
</template>
@@ -6,16 +6,18 @@ import type { Ref } from 'vue'
import { extensions } from '@pixi/extensions'
import { InteractionManager } from '@pixi/interaction'
import { Ticker, TickerPlugin } from '@pixi/ticker'
import { breakpointsTailwind, useBreakpoints, useDark, useDebounceFn } from '@vueuse/core'
import { breakpointsTailwind, useBreakpoints, useDark, useDebounceFn, watchDebounced } from '@vueuse/core'
import localforage from 'localforage'
import { storeToRefs } from 'pinia'
import { DropShadowFilter } from 'pixi-filters'
import { Live2DModel, MotionPreloadStrategy, MotionPriority } from 'pixi-live2d-display/cubism4'
import { Live2DFactory, Live2DModel, MotionPriority } from 'pixi-live2d-display/cubism4'
import { computed, onMounted, onUnmounted, ref, toRef, watch } from 'vue'
import { useLive2DIdleEyeFocus } from '../../composables/live2d'
import { useSettings } from '../../stores'
const props = withDefaults(defineProps<{
app?: Application
model: string
mouthOpenSize?: number
width: number
height: number
@@ -58,16 +60,31 @@ function setScale(model: Ref<Live2DModel<InternalModel> | undefined>) {
model.value.scale.set(scale, scale)
}
async function initLive2DPixiStage() {
const { live2dModel, loadingLive2dModel } = storeToRefs(useSettings())
// FIXME: it cannot blink if loading other model
async function loadModel(source: string | Blob) {
if (!pixiApp.value)
return
// https://guansss.github.io/pixi-live2d-display/#package-importing
Live2DModel.registerTicker(Ticker)
extensions.add(TickerPlugin)
extensions.add(InteractionManager)
if (model.value) {
pixiApp.value.stage.removeChild(model.value)
model.value.destroy()
model.value = undefined
}
model.value = await Live2DModel.from(props.model, { motionPreload: MotionPreloadStrategy.ALL })
loadingLive2dModel.value = true
const modelInstance = new Live2DModel()
if (source instanceof Blob) {
await Live2DFactory.setupLive2DModel(modelInstance, [source])
}
else {
await Live2DFactory.setupLive2DModel(modelInstance, source)
}
model.value = modelInstance
pixiApp.value.stage.addChild(model.value as any)
initialModelWidth.value = model.value.width
initialModelHeight.value = model.value.height
@@ -112,6 +129,30 @@ async function initLive2DPixiStage() {
}
return true
}
// save to indexdb
await localforage.setItem('live2dModel', source)
loadingLive2dModel.value = false
}
async function initLive2DPixiStage() {
if (!pixiApp.value)
return
// https://guansss.github.io/pixi-live2d-display/#package-importing
Live2DModel.registerTicker(Ticker)
extensions.add(TickerPlugin)
extensions.add(InteractionManager)
// load indexdb model first
const live2dModelBlob = await localforage.getItem<Blob>('live2dModel')
if (live2dModelBlob) {
await loadModel(live2dModelBlob)
return
}
await loadModel(live2dModel.value)
}
async function setMotion(motionName: string) {
@@ -148,8 +189,17 @@ watch(paused, (value) => {
value ? pixiApp.value?.stop() : pixiApp.value?.start()
})
watchDebounced(live2dModel, (value) => {
if (!value)
return
loadModel(value)
}, { debounce: 1000 })
onMounted(updateDropShadowFilter)
onUnmounted(() => model.value && pixiApp.value?.stage.removeChild(model.value))
onUnmounted(() => {
model.value && pixiApp.value?.stage.removeChild(model.value)
})
</script>
<template>
@@ -16,7 +16,6 @@ import Screen from '../Screen.vue'
import TransitionVertical from '../TransitionVertical.vue'
withDefaults(defineProps<{
model: string
paused: boolean
mouthOpenSize?: number
}>(), {
@@ -30,7 +29,7 @@ const show = ref(false)
<template>
<Screen v-slot="{ width, height }" relative>
<Live2DCanvas v-slot="{ app }" :width="width" :height="height">
<Live2DModel :app="app" :model="model" :mouth-open-size="mouthOpenSize" :width="width" :height="height" :motion="motion" :paused="paused" />
<Live2DModel :app="app" :mouth-open-size="mouthOpenSize" :width="width" :height="height" :motion="motion" :paused="paused" />
</Live2DCanvas>
<div absolute bottom="3" right="3">
<div flex="~ row" cursor-pointer>
@@ -234,7 +234,6 @@ onMounted(async () => {
v-if="stageView === '2d'"
:motion="motion"
:mouth-open-size="mouthOpenSize"
model="./assets/live2d/models/hiyori_pro_zh.zip"
min-w="50% <lg:full" min-h="100 sm:100" h-full w-full flex-1
:paused="paused"
/>
+8
View File
@@ -23,6 +23,11 @@ export const useSettings = defineStore('settings', () => {
const elevenlabsVoiceEnglish = useLocalStorage<Voice>('settings/llm/elevenlabs/voice/en', Voice.Myriam)
const elevenlabsVoiceJapanese = useLocalStorage<Voice>('settings/llm/elevenlabs/voice/ja', Voice.Morioki)
// TODO: extract to a separate store
const live2dModel = ref<File | string>('./assets/live2d/models/hiyori_pro_zh.zip')
const live2dPosition = useLocalStorage('settings/live2d/position', { x: 0, y: 0 }) // position is relative to the center of the screen
const loadingLive2dModel = ref(false)
watch(isAudioInputOn, (value) => {
if (value === 'false') {
selectedAudioDevice.value = undefined
@@ -49,6 +54,9 @@ export const useSettings = defineStore('settings', () => {
openAiApiBaseURL,
openAiModel,
elevenLabsApiKey,
live2dModel,
live2dPosition,
loadingLive2dModel,
language,
stageView,
isAudioInputOn,
@@ -1,8 +1,81 @@
import type { ModelSettings } from 'pixi-live2d-display/cubism4'
import JSZip from 'jszip'
import { ZipLoader } from 'pixi-live2d-display/cubism4'
import { Cubism4ModelSettings, ZipLoader } from 'pixi-live2d-display/cubism4'
ZipLoader.zipReader = (data: Blob, _url: string) => JSZip.loadAsync(data)
const defaultCreateSettings = ZipLoader.createSettings
ZipLoader.createSettings = async (reader: JSZip) => {
const filePaths = Object.keys(reader.files)
if (!filePaths.find(file => isSettingsFile(file))) {
return createFakeSettings(filePaths)
}
return defaultCreateSettings(reader)
}
export function isSettingsFile(file: string) {
return file.endsWith('model3.json')
}
export function isMocFile(file: string) {
return file.endsWith('.moc3')
}
export function basename(path: string): string {
// https://stackoverflow.com/a/15270931
return path.split(/[\\/]/).pop()!
}
// copy and modified from https://github.com/guansss/live2d-viewer-web/blob/f6060b2ce52c2e26b6b61fa903c837fe343f72d1/src/app/upload.ts#L81-L142
function createFakeSettings(files: string[]): ModelSettings {
const mocFiles = files.filter(file => isMocFile(file))
if (mocFiles.length !== 1) {
const fileList = mocFiles.length ? `(${mocFiles.map(f => `"${f}"`).join(',')})` : ''
throw new Error(`Expected exactly one moc file, got ${mocFiles.length} ${fileList}`)
}
const mocFile = mocFiles[0]
const modelName = basename(mocFile).replace(/\.moc3?/, '')
const textures = files.filter(f => f.endsWith('.png'))
if (!textures.length) {
throw new Error('Textures not found')
}
const motions = files.filter(f => f.endsWith('.mtn') || f.endsWith('.motion3.json'))
const physics = files.find(f => f.includes('physics'))
const pose = files.find(f => f.includes('pose'))
const settings = new Cubism4ModelSettings({
url: `${modelName}.model3.json`,
Version: 3,
FileReferences: {
Moc: mocFile,
Textures: textures,
Physics: physics,
Pose: pose,
Motions: motions.length
? {
'': motions.map(motion => ({ File: motion })),
}
: undefined,
},
})
settings.name = modelName;
// provide this property for FileLoader
(settings as any)._objectURL = `example://${settings.url}`
return settings
}
ZipLoader.readText = (jsZip: JSZip, path: string) => {
const file = jsZip.file(path)
+90 -73
View File
@@ -378,7 +378,7 @@ importers:
version: 2.3.0
'@intlify/unplugin-vue-i18n':
specifier: ^6.0.3
version: 6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.21.0(jiti@2.4.2))(rollup@2.79.1)(typescript@5.8.2)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
version: 6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.21.0(jiti@2.4.2))(rollup@4.34.9)(typescript@5.8.2)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
'@proj-airi/elevenlabs':
specifier: workspace:^
version: link:../../packages/elevenlabs
@@ -405,10 +405,10 @@ importers:
version: 5.2.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))
'@vue-macros/volar':
specifier: ^0.30.15
version: 0.30.15(rollup@2.79.1)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
version: 0.30.15(rollup@4.34.9)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
'@vueuse/motion':
specifier: ^2.2.6
version: 2.2.6(magicast@0.3.5)(rollup@2.79.1)(vue@3.5.13(typescript@5.8.2))
version: 2.2.6(magicast@0.3.5)(rollup@4.34.9)(vue@3.5.13(typescript@5.8.2))
electron:
specifier: ^34.3.0
version: 34.3.0
@@ -426,28 +426,28 @@ importers:
version: 3.2.0(unocss@66.1.0-beta.3(postcss@8.5.3)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)))
unplugin-auto-import:
specifier: ^19.1.1
version: 19.1.1(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@2.79.1))(@vueuse/core@12.7.0(typescript@5.8.2))
version: 19.1.1(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(@vueuse/core@12.7.0(typescript@5.8.2))
unplugin-vue-components:
specifier: ^28.4.1
version: 28.4.1(@babel/parser@7.26.7)(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@2.79.1))(vue@3.5.13(typescript@5.8.2))
version: 28.4.1(@babel/parser@7.26.7)(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(vue@3.5.13(typescript@5.8.2))
unplugin-vue-macros:
specifier: ^2.14.5
version: 2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@2.79.1)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
version: 2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
unplugin-vue-markdown:
specifier: ^28.3.1
version: 28.3.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
unplugin-vue-router:
specifier: ^0.11.2
version: 0.11.2(rollup@2.79.1)(vue-router@4.5.0(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
version: 0.11.2(rollup@4.34.9)(vue-router@4.5.0(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
vite-bundle-visualizer:
specifier: ^1.2.1
version: 1.2.1(rollup@2.79.1)
version: 1.2.1(rollup@4.34.9)
vite-plugin-pwa:
specifier: ^0.21.1
version: 0.21.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.3.0)(workbox-window@7.3.0)
vite-plugin-vue-devtools:
specifier: ^7.7.2
version: 7.7.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@2.79.1))(rollup@2.79.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))
version: 7.7.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(rollup@4.34.9)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))
vite-plugin-vue-layouts:
specifier: ^0.11.0
version: 0.11.0(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-router@4.5.0(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
@@ -589,6 +589,9 @@ importers:
jszip:
specifier: ^3.10.1
version: 3.10.1
localforage:
specifier: ^1.10.0
version: 1.10.0
nprogress:
specifier: ^0.2.0
version: 0.2.0
@@ -682,7 +685,7 @@ importers:
version: 2.3.0
'@intlify/unplugin-vue-i18n':
specifier: ^6.0.3
version: 6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.21.0(jiti@2.4.2))(rollup@4.34.9)(typescript@5.8.2)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
version: 6.0.3(@vue/compiler-dom@3.5.13)(eslint@9.21.0(jiti@2.4.2))(rollup@2.79.1)(typescript@5.8.2)(vue-i18n@11.1.1(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
'@proj-airi/drizzle-duckdb-wasm':
specifier: workspace:^
version: link:../../packages/drizzle-duckdb-wasm
@@ -718,10 +721,10 @@ importers:
version: 5.2.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))
'@vue-macros/volar':
specifier: ^0.30.15
version: 0.30.15(rollup@4.34.9)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
version: 0.30.15(rollup@2.79.1)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
'@vueuse/motion':
specifier: ^2.2.6
version: 2.2.6(magicast@0.3.5)(rollup@4.34.9)(vue@3.5.13(typescript@5.8.2))
version: 2.2.6(magicast@0.3.5)(rollup@2.79.1)(vue@3.5.13(typescript@5.8.2))
hfup:
specifier: workspace:^
version: link:../../packages/hfup
@@ -730,28 +733,28 @@ importers:
version: 4.0.1
unplugin-auto-import:
specifier: ^19.1.1
version: 19.1.1(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(@vueuse/core@12.7.0(typescript@5.8.2))
version: 19.1.1(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@2.79.1))(@vueuse/core@12.7.0(typescript@5.8.2))
unplugin-vue-components:
specifier: ^28.4.1
version: 28.4.1(@babel/parser@7.26.7)(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(vue@3.5.13(typescript@5.8.2))
version: 28.4.1(@babel/parser@7.26.7)(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@2.79.1))(vue@3.5.13(typescript@5.8.2))
unplugin-vue-macros:
specifier: ^2.14.5
version: 2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.19.12)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
version: 2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.19.12)(rollup@2.79.1)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
unplugin-vue-markdown:
specifier: ^28.3.1
version: 28.3.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
unplugin-vue-router:
specifier: ^0.11.2
version: 0.11.2(rollup@4.34.9)(vue-router@4.5.0(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
version: 0.11.2(rollup@2.79.1)(vue-router@4.5.0(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
vite-bundle-visualizer:
specifier: ^1.2.1
version: 1.2.1(rollup@4.34.9)
version: 1.2.1(rollup@2.79.1)
vite-plugin-pwa:
specifier: ^0.21.1
version: 0.21.1(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(workbox-build@7.3.0)(workbox-window@7.3.0)
vite-plugin-vue-devtools:
specifier: ^7.7.2
version: 7.7.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.34.9))(rollup@4.34.9)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))
version: 7.7.2(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@2.79.1))(rollup@2.79.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))
vite-plugin-vue-layouts:
specifier: ^0.11.0
version: 0.11.0(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-router@4.5.0(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
@@ -1191,7 +1194,7 @@ importers:
version: 1.2.0(encoding@0.1.13)
neuri:
specifier: ^0.0.22
version: 0.0.22(@types/json-schema@7.0.15)(@typeschema/valibot@0.14.0(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2)))(@typeschema/zod@0.14.0(@types/json-schema@7.0.15)(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2))(@valibot/to-json-schema@1.0.0-rc.0(valibot@1.0.0-beta.9(typescript@5.8.2)))(encoding@0.1.13)(vitest@3.0.7)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2)
version: 0.0.22(@types/json-schema@7.0.15)(@typeschema/valibot@0.14.0(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2)))(@typeschema/zod@0.14.0(@types/json-schema@7.0.15)(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2))(encoding@0.1.13)(vitest@3.0.7)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2)
prismarine-block:
specifier: ^1.21.0
version: 1.21.0
@@ -8096,6 +8099,9 @@ packages:
libsodium@0.7.15:
resolution: {integrity: sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==}
lie@3.1.1:
resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==}
lie@3.3.0:
resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==}
@@ -8131,6 +8137,9 @@ packages:
resolution: {integrity: sha512-xbZBuX6gYIWrlLmZG43aAVer4ocntYO09vPy9lxd6Ns8DnR4U7N+IIeDkubinqFOHHzoMlPxTxwo0jhE7oYjAw==}
engines: {node: '>=14'}
localforage@1.10.0:
resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==}
locate-path@5.0.0:
resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==}
engines: {node: '>=8'}
@@ -15002,7 +15011,7 @@ snapshots:
dependencies:
'@typeschema/core': 0.14.0(@types/json-schema@7.0.15)
optionalDependencies:
'@typeschema/valibot': 0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.19.12)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))
'@typeschema/valibot': 0.14.0(@gcornut/valibot-json-schema@0.42.0(esbuild@0.25.0)(typescript@5.8.2))(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2))
'@typeschema/zod': 0.14.0(@types/json-schema@7.0.15)(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2)
transitivePeerDependencies:
- '@types/json-schema'
@@ -19680,6 +19689,10 @@ snapshots:
libsodium@0.7.15: {}
lie@3.1.1:
dependencies:
immediate: 3.0.6
lie@3.3.0:
dependencies:
immediate: 3.0.6
@@ -19753,6 +19766,10 @@ snapshots:
pkg-types: 1.3.1
quansync: 0.2.6
localforage@1.10.0:
dependencies:
lie: 3.1.1
locate-path@5.0.0:
dependencies:
p-locate: 4.1.0
@@ -20688,7 +20705,7 @@ snapshots:
neotraverse@0.6.18: {}
neuri@0.0.22(@types/json-schema@7.0.15)(@typeschema/valibot@0.14.0(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2)))(@typeschema/zod@0.14.0(@types/json-schema@7.0.15)(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2))(@valibot/to-json-schema@1.0.0-rc.0(valibot@1.0.0-beta.9(typescript@5.8.2)))(encoding@0.1.13)(vitest@3.0.7)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2):
neuri@0.0.22(@types/json-schema@7.0.15)(@typeschema/valibot@0.14.0(@types/json-schema@7.0.15)(valibot@1.0.0-beta.9(typescript@5.8.2)))(@typeschema/zod@0.14.0(@types/json-schema@7.0.15)(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2))(encoding@0.1.13)(vitest@3.0.7)(ws@8.18.1(bufferutil@4.0.9)(utf-8-validate@5.0.10))(zod-to-json-schema@3.24.3(zod@3.24.2))(zod@3.24.2):
dependencies:
'@fetch-mock/vitest': 0.2.8(vitest@3.0.7)
'@guiiai/logg': 1.0.7
@@ -23385,17 +23402,17 @@ snapshots:
'@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.34.9)
'@vueuse/core': 12.7.0(typescript@5.8.2)
unplugin-combine@1.2.0(esbuild@0.19.12)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
unplugin-combine@1.2.0(esbuild@0.19.12)(rollup@2.79.1)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
optionalDependencies:
esbuild: 0.19.12
rollup: 4.34.9
rollup: 2.79.1
unplugin: 1.16.1
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
unplugin-combine@1.2.0(esbuild@0.25.0)(rollup@2.79.1)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
unplugin-combine@1.2.0(esbuild@0.25.0)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)):
optionalDependencies:
esbuild: 0.25.0
rollup: 2.79.1
rollup: 4.34.9
unplugin: 1.16.1
vite: 6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0)
@@ -23446,53 +23463,7 @@ snapshots:
transitivePeerDependencies:
- vue
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.19.12)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
dependencies:
'@vue-macros/better-define': 1.11.4(vue@3.5.13(typescript@5.8.2))
'@vue-macros/boolean-prop': 0.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/chain-call': 0.4.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/common': 1.16.1(vue@3.5.13(typescript@5.8.2))
'@vue-macros/config': 0.6.1(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-emit': 0.5.4(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-models': 1.3.5(@vueuse/core@12.7.0(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-prop': 0.6.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-props': 4.0.6(@vue-macros/reactivity-transform@1.1.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-props-refs': 1.3.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-render': 1.6.6(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-slots': 1.2.6(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-stylex': 0.2.3(vue@3.5.13(typescript@5.8.2))
'@vue-macros/devtools': 0.4.1(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
'@vue-macros/export-expose': 0.3.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/export-props': 0.6.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/export-render': 0.3.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/hoist-static': 1.7.0(vue@3.5.13(typescript@5.8.2))
'@vue-macros/jsx-directive': 0.10.6(typescript@5.8.2)
'@vue-macros/named-template': 0.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/reactivity-transform': 1.1.6(vue@3.5.13(typescript@5.8.2))
'@vue-macros/script-lang': 0.2.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/setup-block': 0.4.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/setup-component': 0.18.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/setup-sfc': 0.18.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/short-bind': 1.1.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/short-emits': 1.6.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/short-vmodel': 1.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/volar': 0.30.15(rollup@4.34.9)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
unplugin: 1.16.1
unplugin-combine: 1.2.0(esbuild@0.19.12)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
unplugin-vue-define-options: 1.5.5(vue@3.5.13(typescript@5.8.2))
vue: 3.5.13(typescript@5.8.2)
transitivePeerDependencies:
- '@rspack/core'
- '@vueuse/core'
- esbuild
- rolldown
- rollup
- typescript
- vite
- vue-tsc
- webpack
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@2.79.1)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.19.12)(rollup@2.79.1)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
dependencies:
'@vue-macros/better-define': 1.11.4(vue@3.5.13(typescript@5.8.2))
'@vue-macros/boolean-prop': 0.5.5(vue@3.5.13(typescript@5.8.2))
@@ -23524,7 +23495,53 @@ snapshots:
'@vue-macros/short-vmodel': 1.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/volar': 0.30.15(rollup@2.79.1)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
unplugin: 1.16.1
unplugin-combine: 1.2.0(esbuild@0.25.0)(rollup@2.79.1)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
unplugin-combine: 1.2.0(esbuild@0.19.12)(rollup@2.79.1)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
unplugin-vue-define-options: 1.5.5(vue@3.5.13(typescript@5.8.2))
vue: 3.5.13(typescript@5.8.2)
transitivePeerDependencies:
- '@rspack/core'
- '@vueuse/core'
- esbuild
- rolldown
- rollup
- typescript
- vite
- vue-tsc
- webpack
unplugin-vue-macros@2.14.5(@vueuse/core@12.7.0(typescript@5.8.2))(esbuild@0.25.0)(rollup@4.34.9)(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2)):
dependencies:
'@vue-macros/better-define': 1.11.4(vue@3.5.13(typescript@5.8.2))
'@vue-macros/boolean-prop': 0.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/chain-call': 0.4.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/common': 1.16.1(vue@3.5.13(typescript@5.8.2))
'@vue-macros/config': 0.6.1(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-emit': 0.5.4(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-models': 1.3.5(@vueuse/core@12.7.0(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-prop': 0.6.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-props': 4.0.6(@vue-macros/reactivity-transform@1.1.6(vue@3.5.13(typescript@5.8.2)))(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-props-refs': 1.3.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-render': 1.6.6(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-slots': 1.2.6(vue@3.5.13(typescript@5.8.2))
'@vue-macros/define-stylex': 0.2.3(vue@3.5.13(typescript@5.8.2))
'@vue-macros/devtools': 0.4.1(typescript@5.8.2)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
'@vue-macros/export-expose': 0.3.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/export-props': 0.6.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/export-render': 0.3.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/hoist-static': 1.7.0(vue@3.5.13(typescript@5.8.2))
'@vue-macros/jsx-directive': 0.10.6(typescript@5.8.2)
'@vue-macros/named-template': 0.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/reactivity-transform': 1.1.6(vue@3.5.13(typescript@5.8.2))
'@vue-macros/script-lang': 0.2.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/setup-block': 0.4.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/setup-component': 0.18.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/setup-sfc': 0.18.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/short-bind': 1.1.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/short-emits': 1.6.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/short-vmodel': 1.5.5(vue@3.5.13(typescript@5.8.2))
'@vue-macros/volar': 0.30.15(rollup@4.34.9)(typescript@5.8.2)(vue-tsc@2.2.6(typescript@5.8.2))(vue@3.5.13(typescript@5.8.2))
unplugin: 1.16.1
unplugin-combine: 1.2.0(esbuild@0.25.0)(rollup@4.34.9)(unplugin@1.16.1)(vite@6.2.0(@types/node@22.13.8)(jiti@2.4.2)(less@4.2.1)(terser@5.17.6)(tsx@4.19.3)(yaml@2.7.0))
unplugin-vue-define-options: 1.5.5(vue@3.5.13(typescript@5.8.2))
vue: 3.5.13(typescript@5.8.2)
transitivePeerDependencies: