diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..9d08a1a
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,9 @@
+root = true
+
+[*]
+charset = utf-8
+indent_style = space
+indent_size = 2
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
diff --git a/.gitignore b/.gitignore
index ab234eb..c1c1f15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
**/dist
**/out
**/tests.failed.json
+packages/playground/public/assets/locale/*
diff --git a/.localerc.json b/.localerc.json
new file mode 100644
index 0000000..0781c8e
--- /dev/null
+++ b/.localerc.json
@@ -0,0 +1,14 @@
+{
+ "basic": {
+ "source": "packages/playground/node_modules/@fuyeor/locale/src/common.json",
+ "outDir": "packages/playground/public/assets/locale"
+ },
+ "main": {
+ "source": "packages/playground/src/locale/locale.json",
+ "outDir": "packages/playground/public/assets/locale"
+ },
+ "prod": {
+ "source": "packages/playground/src/locale/locale.json",
+ "outDir": "packages/playground/public/assets/locale"
+ }
+}
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000..424942b
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+@fuyeor:registry=https://fpm.fuyeor.com/v1/
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1223cd0..af9c146 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,7 +4,7 @@
"editor.formatOnSave": true,
// assign default formatting tool
"[html]": {
- "editor.defaultFormatter": "esbenp.prettier-vscode"
+ "editor.defaultFormatter": "vscode.html-language-features"
},
"[json]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
diff --git a/Dockerfile b/Dockerfile
index d9352d3..a0be6bf 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -26,8 +26,11 @@ COPY . .
# build parser package before workspace consumers resolve its package exports
RUN pnpm --filter @fuyeor/markdown-parser build
+# generate production locale assets before the playground build copies public files
+RUN pnpm locale make playground prod
+
# build playground
-RUN pnpm --filter @fuyeor/markdown-parser-playground build
+RUN pnpm --filter @fuyeor/markdown-playground build
# ==========================================
# release
diff --git a/package.json b/package.json
index c188742..6786f01 100644
--- a/package.json
+++ b/package.json
@@ -6,9 +6,11 @@
"scripts": {
"format": "prettier --write \"**/*.ts\"",
"test": "pnpm -F @fuyeor/markdown-parser test",
- "playground": "pnpm -F @fuyeor/markdown-playground dev"
+ "playground": "pnpm -F @fuyeor/markdown-playground dev",
+ "locale": "locale-cli"
},
"devDependencies": {
+ "@fuyeor/locale-cli": "^0.1.1",
"@types/node": "^25.6.0",
"jsdom": "^29.0.1",
"prettier": "^3.8.3",
diff --git a/packages/markdown-parser-vue/src/index.ts b/packages/markdown-parser-vue/src/index.ts
new file mode 100644
index 0000000..d54cf72
--- /dev/null
+++ b/packages/markdown-parser-vue/src/index.ts
@@ -0,0 +1,2 @@
+// @fuyeor/markdown-parser-vue/src/index.ts
+export { renderToVue } from './render';
diff --git a/packages/playground/index.html b/packages/playground/index.html
index 157bee3..64e5d83 100644
--- a/packages/playground/index.html
+++ b/packages/playground/index.html
@@ -1,20 +1,114 @@
-
-
-
-
-
- @fuyeor/markdown-parser
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Fuyeor Flavored Markdown Playground
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/packages/playground/package.json b/packages/playground/package.json
index fa5166f..6dd0db8 100644
--- a/packages/playground/package.json
+++ b/packages/playground/package.json
@@ -3,25 +3,32 @@
"license": "MIT",
"author": "Fuyeor ",
"type": "module",
- "sideEffects": false,
"scripts": {
"dev": "vite dev",
- "build": "vite build"
- },
- "imports": {
- "#/*": "./src/*"
+ "build": "vite build",
+ "typecheck": "vue-tsc --noEmit"
},
"exports": {
".": "./src/main.ts"
},
"dependencies": {
- "@fuyeor/markdown-parser-lit": "workspace:*",
- "@fuyeor/locale": "https://github.com/Fuyeor/webroamer.git#path:packages/locale",
- "lit": "^3.3.2"
+ "@fuyeor/commons": "^0.1.2",
+ "@fuyeor/config": "^0.1.1",
+ "@fuyeor/interactify": "^0.1.1",
+ "@fuyeor/locale": "^0.1.0",
+ "@fuyeor/markdown-formatter": "workspace:*",
+ "@fuyeor/markdown-parser": "workspace:*",
+ "@fuyeor/markdown-parser-vue": "workspace:*",
+ "@fuyeor/vue-router": "^0.0.9",
+ "vue": "^3.5.41"
},
"devDependencies": {
- "@types/node": "^25.6.0",
- "typescript": "^6.0.3",
- "vite": "^8.0.1"
+ "@fuyeor/tsconfig": "0.1.0",
+ "@types/node": "^26.2.0",
+ "@vitejs/plugin-vue": "^6.0.8",
+ "html-minifier-terser": "^7.2.0",
+ "lightningcss": "^1.33.0",
+ "typescript": "^7.0.2",
+ "vite": "8.0.1"
}
}
diff --git a/packages/playground/public/assets/css/style.css b/packages/playground/public/assets/css/style.css
new file mode 100644
index 0000000..fbd8821
--- /dev/null
+++ b/packages/playground/public/assets/css/style.css
@@ -0,0 +1,99 @@
+:root {
+ --width-body: 100%;
+ --width-main: 1000px;
+ --width-left-sidebar: 350px;
+ --width-right-sidebar: 0;
+
+ --playground-border: #e2e8f0;
+ --playground-bg-section: #ffffff;
+ --playground-bg-header: #f8fafc;
+ --playground-font-mono:
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
+}
+
+@media (width >= 1000px) {
+ main {
+ width: 100%;
+ }
+
+ .header {
+ border: none;
+ }
+}
+
+h3::after {
+ display: none;
+}
+
+.markdown-rendered {
+ ol,
+ ul {
+ margin: 0 0 20px 20px;
+ padding: 0;
+ }
+
+ li {
+ margin: 10px 0 10px 0;
+ }
+
+ code,
+ pre,
+ pre * {
+ font-size: 0.9rem;
+ }
+}
+
+html {
+ /* remove scroll bar */
+ scrollbar-gutter: unset;
+}
+
+body {
+ overflow: hidden;
+}
+
+.playground-layout {
+ display: grid;
+ grid-template-columns: minmax(280px, 1fr) minmax(360px, 1.2fr);
+ height: calc(-110px + 100vh);
+}
+
+.section {
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ min-height: 0;
+ overflow: hidden;
+}
+
+.editor {
+ border-right: var(--border-subtle);
+
+ textarea {
+ flex: 1;
+ resize: none;
+ background: transparent;
+ font: 400 13px / 1.6 var(--playground-font-mono);
+ tab-size: 2;
+ overflow-y: auto;
+ }
+
+ textarea:hover,
+ textarea:focus {
+ box-shadow: none;
+ }
+}
+
+@media (width <= 900px) {
+ .playground-layout {
+ height: auto;
+ grid-template-columns: 1fr;
+ grid-template-rows: 400px 520px;
+ position: absolute;
+ top: var(--height-header);
+ }
+
+ .preview {
+ border-top: var(--border-subtle);
+ }
+}
diff --git a/packages/playground/public/assets/examples/en.ffm b/packages/playground/public/assets/examples/en.ffm
new file mode 100644
index 0000000..fdee748
--- /dev/null
+++ b/packages/playground/public/assets/examples/en.ffm
@@ -0,0 +1,45 @@
+# Welcome to Markdown Playground
+
+Edit the **Markdown** on the left and inspect the live outputs.
+
+This is a fully-featured Markdown parser that supports standard Markdown syntax, including:
+
+## Text Formatting
+
+You can use *italics*, **bold**, ~~strikethrough~~, and `inline code`.
+
+## Lists and Tasks
+
+- Unordered list item 1
+- Unordered list item 2
+ - Nested list item
+- [ ] Todo item
+- [x] Completed item
+
+1. Ordered list item 1
+2. Ordered list item 2
+
+## Blockquotes and Code Blocks
+
+> This is a blockquote.
+> It can contain multiple lines of text.
+
+```javascript
+// This is a code block
+function hello() {
+ console.log("Hello, Markdown!");
+}
+```
+
+## Links and Images
+
+Visit [Fuyeor](https://www.fuyeor.com) to learn more.
+
+## Tables
+
+| Header 1 | Header 2 | Header 3 |
+| --- | --- | --- |
+| Cell 1 | Cell 2 | Cell 3 |
+| Cell 4 | Cell 5 | Cell 6 |
+
+Switch the tabs on the right to view the Vue rendered preview, JSON (AST), and serialized HTML output.
diff --git a/packages/playground/public/assets/examples/zh-hans.ffm b/packages/playground/public/assets/examples/zh-hans.ffm
new file mode 100644
index 0000000..4cf4064
--- /dev/null
+++ b/packages/playground/public/assets/examples/zh-hans.ffm
@@ -0,0 +1,45 @@
+# 欢迎使用 Markdown 演练场
+
+在左侧编辑**Markdown**,实时查看输出结果。
+
+这是一个功能齐全的 Markdown 解析器,支持标准的 Markdown 语法,包括:
+
+## 文本格式化
+
+你可以使用 *斜体*、**粗体**、~~删除线~~,以及 `内联代码`。
+
+## 列表与任务
+
+- 无序列表项 1
+- 无序列表项 2
+ - 嵌套列表项
+- [ ] 待办事项
+- [x] 已完成事项
+
+1. 有序列表项 1
+2. 有序列表项 2
+
+## 引用与代码块
+
+> 这是一个引用块。
+> 它可以包含多行文本。
+
+```javascript
+// 这是一个代码块
+function hello() {
+ console.log("Hello, Markdown!");
+}
+```
+
+## 链接与图片
+
+访问 [Fuyeor](https://www.fuyeor.com) 了解更多。
+
+## 表格
+
+| 标题 1 | 标题 2 | 标题 3 |
+| --- | --- | --- |
+| 单元格 1 | 单元格 2 | 单元格 3 |
+| 单元格 4 | 单元格 5 | 单元格 6 |
+
+切换右侧的标签页,你可以分别查看 Vue 渲染预览、JSON (AST) 和序列化的 HTML 结果。
diff --git a/packages/playground/favicon.svg b/packages/playground/public/favicon.svg
similarity index 100%
rename from packages/playground/favicon.svg
rename to packages/playground/public/favicon.svg
diff --git a/packages/playground/public/robots.txt b/packages/playground/public/robots.txt
new file mode 100644
index 0000000..26b4d70
--- /dev/null
+++ b/packages/playground/public/robots.txt
@@ -0,0 +1,2 @@
+User-Agent: *
+Allow: /
\ No newline at end of file
diff --git a/packages/playground/src/App.vue b/packages/playground/src/App.vue
new file mode 100644
index 0000000..395a7f2
--- /dev/null
+++ b/packages/playground/src/App.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/api/examples.ts b/packages/playground/src/api/examples.ts
new file mode 100644
index 0000000..b06e81f
--- /dev/null
+++ b/packages/playground/src/api/examples.ts
@@ -0,0 +1,11 @@
+// @/api/examples.ts
+import apiClient from './index';
+
+export async function fetchExample(locale: string): Promise {
+ try {
+ return await apiClient.get(`assets/examples/${locale}.ffm`);
+ } catch (error) {
+ // Fallback to English example if the requested locale is not found
+ return await apiClient.get('assets/examples/en.ffm');
+ }
+}
diff --git a/packages/playground/src/api/index.ts b/packages/playground/src/api/index.ts
new file mode 100644
index 0000000..549b061
--- /dev/null
+++ b/packages/playground/src/api/index.ts
@@ -0,0 +1,9 @@
+// @/api/index.ts
+import { HttpClient } from '@fuyeor/commons';
+
+const apiClient = new HttpClient({
+ baseURL: '/',
+ timeout: 10000,
+});
+
+export default apiClient;
diff --git a/packages/playground/src/components/Playground/DocumentHistory.vue b/packages/playground/src/components/Playground/DocumentHistory.vue
new file mode 100644
index 0000000..6843dac
--- /dev/null
+++ b/packages/playground/src/components/Playground/DocumentHistory.vue
@@ -0,0 +1,291 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ {{
+ document.title || t('playground.documents.untitled')
+ }}
+
+ {{ formatTime(document.updated_at) }}
+
+ · {{ t('playground.documents.wordCount', { value: document.word_count }) }}
+
+
+
+
+
+
+
+ {{ t('playground.documents.empty') }}
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/components/Playground/DocumentStatsBar.vue b/packages/playground/src/components/Playground/DocumentStatsBar.vue
new file mode 100644
index 0000000..3fda9f2
--- /dev/null
+++ b/packages/playground/src/components/Playground/DocumentStatsBar.vue
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/components/Playground/MarkdownToolbar.vue b/packages/playground/src/components/Playground/MarkdownToolbar.vue
new file mode 100644
index 0000000..1961202
--- /dev/null
+++ b/packages/playground/src/components/Playground/MarkdownToolbar.vue
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/components/Playground/PlaygroundEditor.vue b/packages/playground/src/components/Playground/PlaygroundEditor.vue
new file mode 100644
index 0000000..e90b377
--- /dev/null
+++ b/packages/playground/src/components/Playground/PlaygroundEditor.vue
@@ -0,0 +1,245 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/components/Playground/PlaygroundPreview.vue b/packages/playground/src/components/Playground/PlaygroundPreview.vue
new file mode 100644
index 0000000..9b904fe
--- /dev/null
+++ b/packages/playground/src/components/Playground/PlaygroundPreview.vue
@@ -0,0 +1,77 @@
+
+
+
+
+ {{ t('playground.preview.render') }}
+ JSON/AST
+ HTML
+
+
+
+
+
+
{{ astJson }}
+
{{ renderedHtml }}
+
+
+
+
+
+
+
diff --git a/packages/playground/src/components/Playground/PlaygroundShare.vue b/packages/playground/src/components/Playground/PlaygroundShare.vue
new file mode 100644
index 0000000..c8b1532
--- /dev/null
+++ b/packages/playground/src/components/Playground/PlaygroundShare.vue
@@ -0,0 +1,128 @@
+
+
+
+
+
+
+ {{ t('playground.share') }}
+
+
+
{{ t('playground.share.desc') }}
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/composables/useCompression.ts b/packages/playground/src/composables/useCompression.ts
new file mode 100644
index 0000000..b960404
--- /dev/null
+++ b/packages/playground/src/composables/useCompression.ts
@@ -0,0 +1,59 @@
+// @/composables/useCompression.ts
+
+/**
+ * Encode a string to a base64-encoded compressed format using the CompressionStream API.
+ */
+export async function encodeSnippet(content: string): Promise {
+ if (!content) return '';
+ try {
+ const stream = new Blob([content])
+ .stream()
+ .pipeThrough(new CompressionStream('deflate-raw'));
+ const response = new Response(stream);
+ const blob = await response.blob();
+ const buffer = await blob.arrayBuffer();
+ const bytes = new Uint8Array(buffer);
+
+ // Convert to base64url format
+ let binary = '';
+ for (let i = 0; i < bytes.length; i++) {
+ binary += String.fromCharCode(bytes[i]!);
+ }
+ return btoa(binary)
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_')
+ .replace(/=+$/, '');
+ } catch (error) {
+ console.error('Failed to compress snippet:', error);
+ return '';
+ }
+}
+
+/**
+ * Decode a base64-encoded compressed format back to a string using the DecompressionStream API.
+ */
+export async function decodeSnippet(snippet: string): Promise {
+ if (!snippet) return '';
+ try {
+ // Convert base64url back to base64
+ let base64 = snippet.replace(/-/g, '+').replace(/_/g, '/');
+ while (base64.length % 4) {
+ base64 += '=';
+ }
+
+ const binary = atob(base64);
+ const bytes = new Uint8Array(binary.length);
+ for (let i = 0; i < binary.length; i++) {
+ bytes[i] = binary.charCodeAt(i);
+ }
+
+ const stream = new Blob([bytes])
+ .stream()
+ .pipeThrough(new DecompressionStream('deflate-raw'));
+ const response = new Response(stream);
+ return await response.text();
+ } catch (error) {
+ console.error('Failed to decompress snippet:', error);
+ return '';
+ }
+}
diff --git a/packages/playground/src/composables/useDocumentStats.ts b/packages/playground/src/composables/useDocumentStats.ts
new file mode 100644
index 0000000..181c4f9
--- /dev/null
+++ b/packages/playground/src/composables/useDocumentStats.ts
@@ -0,0 +1,43 @@
+// @/composables/useDocumentStats.ts
+import { computed, type Ref } from 'vue';
+
+export interface DocumentStats {
+ words: number;
+ characters: number;
+ sentences: number;
+ paragraphs: number;
+}
+
+export function countDocumentStats(text: string): DocumentStats {
+ if (!text) {
+ return { words: 0, characters: 0, sentences: 0, paragraphs: 0 };
+ }
+
+ const wordSegmenter = new window.Intl.Segmenter(undefined, {
+ granularity: 'word',
+ });
+ const words = [...wordSegmenter.segment(text)].filter(
+ ({ isWordLike }) => isWordLike,
+ ).length;
+
+ const characterSegmenter = new window.Intl.Segmenter(undefined, {
+ granularity: 'grapheme',
+ });
+ const characters = [...characterSegmenter.segment(text)].length;
+
+ const sentenceSegmenter = new window.Intl.Segmenter(undefined, {
+ granularity: 'sentence',
+ });
+ const sentences = [...sentenceSegmenter.segment(text)].length;
+
+ const paragraphs = text
+ .split(/\n\s*\n/)
+ .filter((paragraph) => paragraph.trim().length > 0).length;
+
+ return { words, characters, sentences, paragraphs };
+}
+
+export function useDocumentStats(source: Ref) {
+ const stats = computed(() => countDocumentStats(source.value));
+ return { stats };
+}
diff --git a/packages/playground/src/composables/useIndexedDb.ts b/packages/playground/src/composables/useIndexedDb.ts
new file mode 100644
index 0000000..eceb246
--- /dev/null
+++ b/packages/playground/src/composables/useIndexedDb.ts
@@ -0,0 +1,158 @@
+// @fuyeor/markdown-parser-playground/src/composables/useIndexedDb.ts
+import { onMounted, ref } from 'vue';
+import { countDocumentStats } from '@/composables/useDocumentStats';
+
+export interface HistoryDocument {
+ id: string;
+ title: string;
+ created_at: number;
+ updated_at: number;
+ content: string;
+ word_count?: number;
+}
+
+const DB_NAME = 'fuyeor-markdown-playground';
+const STORE_NAME = 'documents';
+const UPDATED_AT_INDEX = 'updated_at';
+const DB_VERSION = 1;
+
+const documents = ref([]);
+const isReady = ref(false);
+const error = ref(null);
+let database: IDBDatabase | null = null;
+let initialization: Promise | null = null;
+
+const loadAllDocuments = (): Promise => {
+ return new Promise((resolve, reject) => {
+ if (!database) {
+ reject(new Error('IndexedDB is not initialized'));
+ return;
+ }
+
+ const transaction = database.transaction(STORE_NAME, 'readwrite');
+ const request = transaction
+ .objectStore(STORE_NAME)
+ .index(UPDATED_AT_INDEX)
+ .openCursor(null, 'prev');
+ const result: HistoryDocument[] = [];
+
+ request.onsuccess = () => {
+ const cursor = request.result;
+ if (!cursor) {
+ transaction.oncomplete = () => {
+ documents.value = result;
+ resolve();
+ };
+ return;
+ }
+
+ const document = cursor.value as HistoryDocument;
+ const normalizedDocument = document.word_count === undefined
+ ? { ...document, word_count: countDocumentStats(document.content).words }
+ : document;
+ result.push(normalizedDocument);
+ if (normalizedDocument !== document) cursor.update(normalizedDocument);
+ cursor.continue();
+ };
+
+ request.onerror = () => reject(request.error ?? new Error('Failed to read documents'));
+ transaction.onerror = () => reject(transaction.error ?? new Error('Failed to read documents'));
+ transaction.onabort = () => reject(transaction.error ?? new Error('Failed to read documents'));
+ });
+};
+
+const initialize = (): Promise => {
+ if (initialization) return initialization;
+
+ initialization = new Promise((resolve, reject) => {
+ if (!window.indexedDB) {
+ reject(new Error('IndexedDB is not supported'));
+ return;
+ }
+
+ const request = window.indexedDB.open(DB_NAME, DB_VERSION);
+
+ request.onerror = () => reject(request.error ?? new Error('Failed to open IndexedDB'));
+ request.onupgradeneeded = () => {
+ const upgradedDatabase = request.result;
+ const upgradeTransaction = request.transaction;
+ const store = upgradedDatabase.objectStoreNames.contains(STORE_NAME)
+ ? upgradeTransaction?.objectStore(STORE_NAME)
+ : upgradedDatabase.createObjectStore(STORE_NAME, { keyPath: 'id' });
+
+ if (store && !store.indexNames.contains(UPDATED_AT_INDEX)) {
+ store.createIndex(UPDATED_AT_INDEX, 'updated_at', { unique: false });
+ }
+ };
+ request.onsuccess = () => {
+ database = request.result;
+ database.onversionchange = () => database?.close();
+ loadAllDocuments().then(resolve).catch(reject);
+ };
+ }).then(
+ () => {
+ isReady.value = true;
+ },
+ (reason: unknown) => {
+ error.value = reason instanceof Error ? reason : new Error(String(reason));
+ isReady.value = true;
+ throw error.value;
+ },
+ );
+
+ return initialization;
+};
+
+const requireDatabase = async (): Promise => {
+ await initialize();
+ if (!database) throw new Error('IndexedDB is not available');
+ return database;
+};
+
+export function useIndexedDb() {
+ const saveDocument = async (document: HistoryDocument): Promise => {
+ const activeDatabase = await requireDatabase();
+
+ await new Promise((resolve, reject) => {
+ const transaction = activeDatabase.transaction(STORE_NAME, 'readwrite');
+ const request = transaction.objectStore(STORE_NAME).put({ ...document });
+
+ request.onerror = () => reject(request.error ?? new Error('Failed to save document'));
+ transaction.onabort = () => reject(transaction.error ?? new Error('Failed to save document'));
+ transaction.oncomplete = resolve;
+ });
+
+ const index = documents.value.findIndex((item) => item.id === document.id);
+ if (index >= 0) documents.value[index] = { ...document };
+ else documents.value.push({ ...document });
+ documents.value.sort((a, b) => b.updated_at - a.updated_at);
+ };
+
+ const deleteDocument = async (id: string): Promise => {
+ const activeDatabase = await requireDatabase();
+
+ await new Promise((resolve, reject) => {
+ const transaction = activeDatabase.transaction(STORE_NAME, 'readwrite');
+ const request = transaction.objectStore(STORE_NAME).delete(id);
+
+ request.onerror = () => reject(request.error ?? new Error('Failed to delete document'));
+ transaction.onabort = () => reject(transaction.error ?? new Error('Failed to delete document'));
+ transaction.oncomplete = resolve;
+ });
+
+ documents.value = documents.value.filter((item) => item.id !== id);
+ };
+
+ onMounted(() => {
+ void initialize().catch(() => undefined);
+ });
+
+ return {
+ documents,
+ isReady,
+ error,
+ saveDocument,
+ deleteDocument,
+ loadAllDocuments,
+ };
+}
diff --git a/packages/playground/src/composables/useMarkdownEditor.ts b/packages/playground/src/composables/useMarkdownEditor.ts
new file mode 100644
index 0000000..67a9422
--- /dev/null
+++ b/packages/playground/src/composables/useMarkdownEditor.ts
@@ -0,0 +1,200 @@
+// @/composables/useMarkdownEditor.ts
+import { computed, nextTick, ref, type Ref } from 'vue';
+import { format as formatMarkdown } from '@fuyeor/markdown-formatter';
+
+export type MarkdownTool =
+ | 'bold'
+ | 'italic'
+ | 'heading'
+ | 'strike'
+ | 'unordered-list'
+ | 'ordered-list'
+ | 'checklist'
+ | 'quote'
+ | 'code'
+ | 'link'
+ | 'table';
+
+export function useMarkdownEditor(
+ source: Ref,
+ editor: Ref,
+) {
+ const history = ref([source.value]);
+ const historyIndex = ref(0);
+ const canUndo = computed(() => historyIndex.value > 0);
+ const canRedo = computed(() => historyIndex.value < history.value.length - 1);
+
+ // Keep the editor history bounded so repeated formatting does not grow memory indefinitely.
+ const recordHistory = (value: string) => {
+ const nextHistory = history.value.slice(0, historyIndex.value + 1);
+ if (nextHistory.at(-1) === value) return;
+ nextHistory.push(value);
+ if (nextHistory.length > 100) nextHistory.shift();
+ history.value = nextHistory;
+ historyIndex.value = nextHistory.length - 1;
+ };
+
+ const replaceSource = (value: string) => {
+ source.value = value;
+ history.value = [value];
+ historyIndex.value = 0;
+ };
+
+ const recordInput = () => recordHistory(source.value);
+
+ const setSource = (
+ value: string,
+ selectionStart: number,
+ selectionEnd: number,
+ scrollTop?: number,
+ ) => {
+ const element = editor.value;
+ if (element) {
+ element.focus();
+ // 使用 document.execCommand 来触发原生的输入事件,这样可以被 Ctrl+Z 撤销
+ // 由于 execCommand 已经被弃用但依然是所有浏览器支持插入文本且进入撤销栈的唯一标准方式
+ // 我们全选后替换来更新整个值,或只替换选区
+ element.select();
+ const success = document.execCommand('insertText', false, value);
+
+ // 如果 execCommand 失败(某些环境可能禁用),回退到直接赋值
+ if (!success) {
+ source.value = value;
+ element.value = value;
+ element.dispatchEvent(new Event('input', { bubbles: true }));
+ }
+ } else {
+ source.value = value;
+ }
+
+ recordHistory(value);
+ void nextTick(() => {
+ if (!element) return;
+ element.focus();
+ element.setSelectionRange(selectionStart, selectionEnd);
+ if (scrollTop !== undefined) {
+ element.scrollTop = scrollTop;
+ }
+ });
+ };
+
+ const applyTool = (tool: MarkdownTool) => {
+ const element = editor.value;
+ if (!element) return;
+ const start = element.selectionStart;
+ const end = element.selectionEnd;
+ const text = source.value.slice(start, end);
+ const fallback = text || 'text';
+
+ // 检查成对包裹语法是否已经存在
+ const toggleWrap = (prefix: string, suffix: string = prefix) => {
+ const isWrapped =
+ text.startsWith(prefix) &&
+ text.endsWith(suffix) &&
+ text.length >= prefix.length + suffix.length;
+ if (isWrapped) {
+ // 取消包裹
+ return text.slice(prefix.length, text.length - suffix.length);
+ }
+ // 添加包裹
+ return `${prefix}${fallback}${suffix}`;
+ };
+
+ let replacement = fallback;
+
+ if (tool === 'bold') replacement = toggleWrap('**');
+ else if (tool === 'italic') replacement = toggleWrap('*');
+ else if (tool === 'strike') replacement = toggleWrap('~~');
+ else if (tool === 'code') replacement = toggleWrap('`');
+ else if (tool === 'link')
+ replacement = `[${fallback}](https://example.com)`;
+ else if (tool === 'heading') replacement = `# ${fallback}`;
+ else if (tool === 'quote')
+ replacement = fallback
+ .split('\n')
+ .map((line) => `> ${line}`)
+ .join('\n');
+ else if (tool === 'unordered-list')
+ replacement = fallback
+ .split('\n')
+ .map((line) => `- ${line}`)
+ .join('\n');
+ else if (tool === 'ordered-list')
+ replacement = fallback
+ .split('\n')
+ .map((line, index) => `${index + 1}. ${line}`)
+ .join('\n');
+ else if (tool === 'checklist')
+ replacement = fallback
+ .split('\n')
+ .map((line) => `- [ ] ${line}`)
+ .join('\n');
+ else if (tool === 'table')
+ replacement = '| Column 1 | Column 2 |\n| --- | --- |\n| Value | Value |';
+
+ const selectionStart = text ? start : start + replacement.length;
+ const selectionEnd = text ? start + replacement.length : selectionStart;
+
+ // 如果工具栏触发时不需要替换全部文档,我们可以只选中文本并执行 insertText 替换选区
+ // 这样能保留更细粒度的 Ctrl+Z 历史
+ element.focus();
+ element.setSelectionRange(start, end);
+ const success = document.execCommand('insertText', false, replacement);
+
+ if (!success) {
+ // 降级策略
+ setSource(
+ `${source.value.slice(0, start)}${replacement}${source.value.slice(end)}`,
+ selectionStart,
+ selectionEnd,
+ element.scrollTop,
+ );
+ } else {
+ recordInput();
+ void nextTick(() => {
+ element.focus();
+ element.setSelectionRange(selectionStart, selectionEnd);
+ });
+ }
+ };
+
+ const formatDocument = () => {
+ const formatted = formatMarkdown(source.value);
+ if (formatted === source.value) return;
+
+ const element = editor.value;
+ if (element) {
+ setSource(
+ formatted,
+ element.selectionStart,
+ element.selectionEnd,
+ element.scrollTop,
+ );
+ } else {
+ setSource(formatted, 0, 0);
+ }
+ };
+
+ const undo = () => {
+ if (!canUndo.value) return;
+ historyIndex.value -= 1;
+ source.value = history.value[historyIndex.value];
+ };
+
+ const redo = () => {
+ if (!canRedo.value) return;
+ historyIndex.value += 1;
+ source.value = history.value[historyIndex.value];
+ };
+
+ return {
+ canUndo,
+ canRedo,
+ replaceSource,
+ recordInput,
+ applyTool,
+ formatDocument,
+ undo,
+ redo,
+ };
+}
diff --git a/packages/playground/src/composables/useMarkdownHighlighter.ts b/packages/playground/src/composables/useMarkdownHighlighter.ts
new file mode 100644
index 0000000..41c90b1
--- /dev/null
+++ b/packages/playground/src/composables/useMarkdownHighlighter.ts
@@ -0,0 +1,209 @@
+// @fuyeor/markdown-parser-playground/src/composables/useMarkdownHighlighter.ts
+import { computed, nextTick, onMounted, watch, type Ref } from 'vue';
+
+type CustomHighlightRegistry = {
+ delete: (name: string) => void;
+ set: (name: string, highlight: object) => void;
+};
+
+type CustomHighlightConstructor = new (...ranges: Range[]) => object;
+
+const customHighlightStyles = `
+::highlight(md-punctuation) { color: #a0aec0; }
+::highlight(md-heading) { color: #553c9a; }
+::highlight(md-quote) { color: #718096; }
+::highlight(md-list) { color: #2d3748; }
+::highlight(md-bold) { color: #1a202c; }
+::highlight(md-italic) { color: #1a202c; }
+::highlight(md-code) { color: #d53f8c; background-color: #faf5ff; }
+::highlight(md-strike) { text-decoration: line-through; color: #a0aec0; }
+::highlight(md-code-fence) { color: #805ad5; }
+`;
+
+const getCustomHighlightRegistry = (): CustomHighlightRegistry | null => {
+ const css = Reflect.get(globalThis, 'CSS');
+ const registry = css && Reflect.get(css, 'highlights');
+ return registry && typeof registry.delete === 'function' && typeof registry.set === 'function'
+ ? registry as CustomHighlightRegistry
+ : null;
+};
+
+const getCustomHighlightConstructor = (): CustomHighlightConstructor | null => {
+ const constructor = Reflect.get(globalThis, 'Highlight');
+ return typeof constructor === 'function' ? constructor as CustomHighlightConstructor : null;
+};
+
+const ensureCustomHighlightStyles = () => {
+ const styleId = 'fuyeor-playground-custom-highlight-styles';
+ if (document.getElementById(styleId)) return;
+
+ const style = document.createElement('style');
+ style.id = styleId;
+ style.textContent = customHighlightStyles;
+ document.head.append(style);
+};
+
+export function useMarkdownHighlighter(
+ source: Ref,
+ highlightTarget: Ref,
+ supportsCustomHighlight: boolean,
+) {
+ const lines = computed(() => source.value.split('\n'));
+
+ const lineNumbers = computed(() => {
+ return lines.value.map((_, i) => i + 1);
+ });
+
+ // Keep a small regex fallback for browsers without the Custom Highlight API.
+ const highlightedLines = computed(() => {
+ if (supportsCustomHighlight) return [];
+
+ return lines.value.map((line) => {
+ let html = line
+ .replace(/&/g, '&')
+ .replace(//g, '>');
+
+ if (/^#{1,6}\s/.test(html)) {
+ html = html.replace(/^(#{1,6})(\s.*)$/, '$1$2');
+ } else if (/^>\s/.test(html)) {
+ html = html.replace(/^(>\s)(.*)$/, '$1$2');
+ } else if (/^(\s*)([-*+]|\d+\.)(\s)/.test(html)) {
+ html = html.replace(/^(\s*)([-*+]|\d+\.)(\s)(.*)$/, '$1$2$3$4');
+ } else if (/^```/.test(html)) {
+ html = `${html}`;
+ } else {
+ html = html
+ .replace(/(\*\*)(.*?)\1/g, '**$2**')
+ .replace(/(\*)(.*?)\1/g, '*$2*')
+ .replace(/(`)(.*?)\1/g, '`$2`')
+ .replace(/(~~)(.*?)\1/g, '~~$2~~');
+ }
+
+ return html || ' ';
+ });
+ });
+
+ const tokenNames = [
+ 'md-punctuation',
+ 'md-heading',
+ 'md-quote',
+ 'md-list',
+ 'md-bold',
+ 'md-italic',
+ 'md-code',
+ 'md-strike',
+ 'md-code-fence',
+ ];
+
+ const removeCustomHighlights = (registry: CustomHighlightRegistry) => {
+ for (const name of tokenNames) registry.delete(name);
+ };
+
+ // Rebuild ranges against the mirrored text node without replacing editor DOM.
+ const updateCustomHighlights = () => {
+ if (!supportsCustomHighlight || !highlightTarget.value) return;
+
+ const registry = getCustomHighlightRegistry();
+ const Highlight = getCustomHighlightConstructor();
+ const textNode = highlightTarget.value.firstChild;
+
+ if (!registry || !Highlight || !(textNode instanceof Text)) {
+ if (registry) removeCustomHighlights(registry);
+ return;
+ }
+
+ const text = textNode.nodeValue ?? '';
+ const tokens: Record = {
+ 'md-punctuation': [],
+ 'md-heading': [],
+ 'md-quote': [],
+ 'md-list': [],
+ 'md-bold': [],
+ 'md-italic': [],
+ 'md-code': [],
+ 'md-strike': [],
+ 'md-code-fence': [],
+ };
+
+ const addRange = (category: string, start: number, end: number) => {
+ if (start < 0 || end > text.length || start >= end) return;
+
+ const range = new Range();
+ range.setStart(textNode, start);
+ range.setEnd(textNode, end);
+ tokens[category].push(range);
+ };
+
+ let currentPosition = 0;
+ for (const line of text.split('\n')) {
+ const lineStart = currentPosition;
+ const heading = /^(#{1,6})(\s.*)$/.exec(line);
+ const quote = /^(>\s)(.*)$/.exec(line);
+ const list = /^(\s*)([-*+]|\d+\.)(\s)(.*)$/.exec(line);
+
+ if (heading) {
+ addRange('md-punctuation', lineStart, lineStart + heading[1].length);
+ addRange('md-heading', lineStart + heading[1].length, lineStart + line.length);
+ } else if (quote) {
+ addRange('md-punctuation', lineStart, lineStart + quote[1].length);
+ addRange('md-quote', lineStart + quote[1].length, lineStart + line.length);
+ } else if (list) {
+ const markerStart = lineStart + list[1].length;
+ const markerEnd = markerStart + list[2].length;
+ addRange('md-punctuation', markerStart, markerEnd);
+ addRange('md-list', markerEnd + list[3].length, lineStart + line.length);
+ } else if (line.startsWith('```')) {
+ addRange('md-code-fence', lineStart, lineStart + line.length);
+ } else {
+ const inlinePattern = /(\*\*.*?\*\*|\*.*?\*|`.*?`|~~.*?~~)/g;
+ for (const match of line.matchAll(inlinePattern)) {
+ const matchText = match[0];
+ const matchStart = lineStart + (match.index ?? 0);
+ const matchEnd = matchStart + matchText.length;
+
+ if (matchText.startsWith('**')) {
+ addRange('md-punctuation', matchStart, matchStart + 2);
+ addRange('md-bold', matchStart + 2, matchEnd - 2);
+ addRange('md-punctuation', matchEnd - 2, matchEnd);
+ } else if (matchText.startsWith('*')) {
+ addRange('md-punctuation', matchStart, matchStart + 1);
+ addRange('md-italic', matchStart + 1, matchEnd - 1);
+ addRange('md-punctuation', matchEnd - 1, matchEnd);
+ } else if (matchText.startsWith('`')) {
+ addRange('md-punctuation', matchStart, matchStart + 1);
+ addRange('md-code', matchStart + 1, matchEnd - 1);
+ addRange('md-punctuation', matchEnd - 1, matchEnd);
+ } else if (matchText.startsWith('~~')) {
+ addRange('md-punctuation', matchStart, matchStart + 2);
+ addRange('md-strike', matchStart + 2, matchEnd - 2);
+ addRange('md-punctuation', matchEnd - 2, matchEnd);
+ }
+ }
+ }
+
+ currentPosition += line.length + 1;
+ }
+
+ removeCustomHighlights(registry);
+ for (const [name, ranges] of Object.entries(tokens)) {
+ if (ranges.length > 0) registry.set(name, new Highlight(...ranges));
+ }
+ };
+
+ if (supportsCustomHighlight) {
+ onMounted(ensureCustomHighlightStyles);
+ watch([source, highlightTarget], () => {
+ void nextTick(updateCustomHighlights);
+ }, { immediate: true });
+ }
+
+ return {
+ lines,
+ lineNumbers,
+ highlightedLines,
+ updateCustomHighlights,
+ };
+}
+
+export { customHighlightStyles };
diff --git a/packages/playground/src/composables/usePlaygroundSource.ts b/packages/playground/src/composables/usePlaygroundSource.ts
new file mode 100644
index 0000000..b7ce5d3
--- /dev/null
+++ b/packages/playground/src/composables/usePlaygroundSource.ts
@@ -0,0 +1,10 @@
+// @/composables/usePlaygroundSource.ts
+import { ref } from 'vue';
+
+const source = ref('');
+
+export function usePlaygroundSource() {
+ return {
+ source,
+ };
+}
diff --git a/packages/playground/src/config/locales.ts b/packages/playground/src/config/locales.ts
new file mode 100644
index 0000000..8a6fed1
--- /dev/null
+++ b/packages/playground/src/config/locales.ts
@@ -0,0 +1,16 @@
+// @/config/locales.ts
+
+export type SupportedLocale = (typeof SUPPORTED_LOCALES)[number];
+
+/**
+ * front-end UI supported locales
+ */
+// prettier-ignore
+export const SUPPORTED_LOCALES = [
+ 'en', 'fr', 'es', 'pt', 'de',
+ 'ar', 'ru', 'ja', 'ko',
+ 'zh-hans', 'zh-hant'
+] as const;
+
+// generate regex string for router
+export const LOCALE_REGEX = SUPPORTED_LOCALES.join('|');
diff --git a/packages/playground/src/config/sidebar/menu.config.ts b/packages/playground/src/config/sidebar/menu.config.ts
new file mode 100644
index 0000000..c7f7f5a
--- /dev/null
+++ b/packages/playground/src/config/sidebar/menu.config.ts
@@ -0,0 +1,11 @@
+// @/config/sidebar/menu.config.ts
+import { getIconUrl } from '@fuyeor/commons';
+import type { SidebarItemConfig } from '@fuyeor/interactify';
+
+export const sidebarItemsRaw: SidebarItemConfig[] = [
+ {
+ target: '/',
+ icon: getIconUrl('home'),
+ textKey: 'home',
+ },
+];
diff --git a/packages/playground/src/layout/Left.vue b/packages/playground/src/layout/Left.vue
new file mode 100644
index 0000000..43eb3fe
--- /dev/null
+++ b/packages/playground/src/layout/Left.vue
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+ {{ t('playground') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/playground/src/locale/locale.json b/packages/playground/src/locale/locale.json
new file mode 100644
index 0000000..38fbbe8
--- /dev/null
+++ b/packages/playground/src/locale/locale.json
@@ -0,0 +1,314 @@
+{
+ "playground": {
+ "ar": "ساحة التجربة",
+ "de": "Spielwiese",
+ "en": "Playground",
+ "es": "Área de pruebas",
+ "fr": "Aire de jeux",
+ "ja": "プレイグラウンド",
+ "ko": "플레이그라운드",
+ "pt": "Área de testes",
+ "ru": "Песочница",
+ "zh-hans": "实验场"
+ },
+ "playground.documents": {
+ "ar": "المستندات",
+ "de": "Dokumente",
+ "en": "Documents",
+ "es": "Documentos",
+ "fr": "Documents",
+ "ja": "ドキュメント",
+ "ko": "문서",
+ "pt": "Documentos",
+ "ru": "Документы",
+ "zh-hans": "文档"
+ },
+ "playground.documents.characters": {
+ "ar": "الأحرف",
+ "de": "Zeichen",
+ "en": "Characters",
+ "es": "Caracteres",
+ "fr": "Caractères",
+ "ja": "文字",
+ "ko": "문자",
+ "pt": "Caracteres",
+ "ru": "Символы",
+ "zh-hans": "字符数"
+ },
+ "playground.documents.createdAt": {
+ "ar": "تاريخ الإنشاء",
+ "de": "Erstellt",
+ "en": "Created",
+ "es": "Creado",
+ "fr": "Créé",
+ "ja": "作成",
+ "ko": "생성",
+ "pt": "Criado",
+ "ru": "Создано",
+ "zh-hans": "创建于"
+ },
+ "playground.documents.daysAgo": {
+ "ar": "منذ {value} يوم",
+ "de": "vor {value} Tagen",
+ "en": "{value} days ago",
+ "es": "hace {value} días",
+ "fr": "il y a {value} jours",
+ "ja": "{value}日前",
+ "ko": "{value}일 전",
+ "pt": "há {value} dias",
+ "ru": "{value} дн. назад",
+ "zh-hans": "{value} 天前"
+ },
+ "playground.documents.empty": {
+ "ar": "لا توجد مستندات",
+ "de": "Keine Dokumente",
+ "en": "No documents",
+ "es": "No hay documentos",
+ "fr": "Aucun document",
+ "ja": "ドキュメントはありません",
+ "ko": "문서가 없습니다",
+ "pt": "Nenhum documento",
+ "ru": "Нет документов",
+ "zh-hans": "暂无文档"
+ },
+ "playground.documents.hoursAgo": {
+ "ar": "منذ {value} ساعة",
+ "de": "vor {value} Std.",
+ "en": "{value} hr ago",
+ "es": "hace {value} h",
+ "fr": "il y a {value} h",
+ "ja": "{value}時間前",
+ "ko": "{value}시간 전",
+ "pt": "há {value} h",
+ "ru": "{value} ч назад",
+ "zh-hans": "{value} 小时前"
+ },
+ "playground.documents.justNow": {
+ "ar": "الآن",
+ "de": "Gerade eben",
+ "en": "Just now",
+ "es": "Ahora mismo",
+ "fr": "À l'instant",
+ "ja": "たった今",
+ "ko": "방금 전",
+ "pt": "Agora mesmo",
+ "ru": "Только что",
+ "zh-hans": "刚刚"
+ },
+ "playground.documents.minutesAgo": {
+ "ar": "منذ {value} دقيقة",
+ "de": "vor {value} Min.",
+ "en": "{value} min ago",
+ "es": "hace {value} min",
+ "fr": "il y a {value} min",
+ "ja": "{value}分前",
+ "ko": "{value}분 전",
+ "pt": "há {value} min",
+ "ru": "{value} мин назад",
+ "zh-hans": "{value} 分钟前"
+ },
+ "playground.documents.new": {
+ "ar": "جديد",
+ "de": "Neu",
+ "en": "New",
+ "es": "Nuevo",
+ "fr": "Nouveau",
+ "ja": "新規",
+ "ko": "새로 만들기",
+ "pt": "Novo",
+ "ru": "Новый",
+ "zh-hans": "新建"
+ },
+ "playground.documents.paragraphs": {
+ "ar": "الفقرات",
+ "de": "Absätze",
+ "en": "Paragraphs",
+ "es": "Párrafos",
+ "fr": "Paragraphes",
+ "ja": "段落",
+ "ko": "단락",
+ "pt": "Parágrafos",
+ "ru": "Абзацы",
+ "zh-hans": "段落数"
+ },
+ "playground.documents.search": {
+ "ar": "البحث في المستندات...",
+ "de": "Dokumente durchsuchen...",
+ "en": "Search documents...",
+ "es": "Buscar documentos...",
+ "fr": "Rechercher des documents...",
+ "ja": "ドキュメントを検索...",
+ "ko": "문서 검색...",
+ "pt": "Pesquisar documentos...",
+ "ru": "Поиск документов...",
+ "zh-hans": "搜索文档..."
+ },
+ "playground.documents.sentences": {
+ "ar": "الجمل",
+ "de": "Sätze",
+ "en": "Sentences",
+ "es": "Oraciones",
+ "fr": "Phrases",
+ "ja": "文",
+ "ko": "문장",
+ "pt": "Frases",
+ "ru": "Предложения",
+ "zh-hans": "句子数"
+ },
+ "playground.documents.untitled": {
+ "ar": "مستند بلا عنوان",
+ "de": "Unbenanntes Dokument",
+ "en": "Untitled document",
+ "es": "Documento sin título",
+ "fr": "Document sans titre",
+ "ja": "無題のドキュメント",
+ "ko": "제목 없는 문서",
+ "pt": "Documento sem título",
+ "ru": "Документ без названия",
+ "zh-hans": "未命名文档"
+ },
+ "playground.documents.updatedAt": {
+ "ar": "تم التعديل",
+ "de": "Überarbeitet",
+ "en": "Revised",
+ "es": "Revisado",
+ "fr": "Révisé",
+ "ja": "修訂",
+ "ko": "수정됨",
+ "pt": "Revisado",
+ "ru": "Изменено",
+ "zh-hans": "修订于"
+ },
+ "playground.documents.weeksAgo": {
+ "ar": "منذ {value} أسبوع",
+ "de": "vor {value} Wochen",
+ "en": "{value} wk ago",
+ "es": "hace {value} sem",
+ "fr": "il y a {value} sem.",
+ "ja": "{value}週間前",
+ "ko": "{value}주 전",
+ "pt": "há {value} sem.",
+ "ru": "{value} нед. назад",
+ "zh-hans": "{value} 周前"
+ },
+ "playground.documents.wordCount": {
+ "ar": "{value} كلمة",
+ "de": "{value} Wörter",
+ "en": "{value} words",
+ "es": "{value} palabras",
+ "fr": "{value} mots",
+ "ja": "{value}語",
+ "ko": "{value}단어",
+ "pt": "{value} palavras",
+ "ru": "{value} слов",
+ "zh-hans": "{value} 词"
+ },
+ "playground.documents.words": {
+ "ar": "الكلمات",
+ "de": "Wörter",
+ "en": "Words",
+ "es": "Palabras",
+ "fr": "Mots",
+ "ja": "単語",
+ "ko": "단어",
+ "pt": "Palavras",
+ "ru": "Слова",
+ "zh-hans": "词数"
+ },
+ "playground.documents.yesterday": {
+ "ar": "أمس",
+ "de": "Gestern",
+ "en": "Yesterday",
+ "es": "Ayer",
+ "fr": "Hier",
+ "ja": "昨日",
+ "ko": "어제",
+ "pt": "Ontem",
+ "ru": "Вчера",
+ "zh-hans": "昨天"
+ },
+ "playground.editor.source": {
+ "ar": "مصدر Markdown",
+ "de": "Markdown-Quelle",
+ "en": "Markdown source",
+ "es": "Fuente Markdown",
+ "fr": "Source Markdown",
+ "ja": "Markdown ソース",
+ "ko": "Markdown 소스",
+ "pt": "Fonte Markdown",
+ "ru": "Исходный Markdown",
+ "zh-hans": "Markdown 源码"
+ },
+ "playground.preview.render": {
+ "ar": "المعاينة",
+ "de": "Vorschau",
+ "en": "Preview",
+ "es": "Vista previa",
+ "fr": "Aperçu",
+ "ja": "プレビュー",
+ "ko": "미리보기",
+ "pt": "Pré-visualização",
+ "ru": "Предпросмотр",
+ "zh-hans": "渲染预览"
+ },
+ "playground.share": {
+ "ar": "مشاركة محتوى Markdown",
+ "de": "Markdown-Inhalt teilen",
+ "en": "Share Markdown content",
+ "es": "Compartir contenido Markdown",
+ "fr": "Partager le contenu Markdown",
+ "ja": "Markdownコンテンツを共有",
+ "ko": "Markdown 콘텐츠 공유",
+ "pt": "Compartilhar conteúdo Markdown",
+ "ru": "Поделиться контентом Markdown",
+ "zh-hans": "分享 Markdown 内容"
+ },
+ "playground.share.button": {
+ "ar": "مشاركة",
+ "de": "Teilen",
+ "en": "Share",
+ "es": "Compartir",
+ "fr": "Partager",
+ "ja": "共有",
+ "ko": "공유",
+ "pt": "Compartilhar",
+ "ru": "Поделиться",
+ "zh-hans": "分享"
+ },
+ "playground.share.desc": {
+ "ar": "انسخ الرابط التالي وأرسله:",
+ "de": "Kopieren Sie den folgenden Link zum Senden:",
+ "en": "Copy the following link to send:",
+ "es": "Copia el siguiente enlace para enviar:",
+ "fr": "Copiez le lien suivant à envoyer :",
+ "ja": "次のリンクをコピーして送信:",
+ "ko": "보내려면 다음 링크를 복사하세요:",
+ "pt": "Copie o link abaixo para enviar:",
+ "ru": "Скопируйте следующую ссылку для отправки:",
+ "zh-hans": "复制以下链接发送:"
+ },
+ "site.name": {
+ "ar": "Fuyeor Flavored Markdown",
+ "de": "Fuyeor Flavored Markdown",
+ "en": "Fuyeor Flavored Markdown",
+ "es": "Fuyeor Flavored Markdown",
+ "fr": "Fuyeor Flavored Markdown",
+ "ja": "Fuyeor Flavored Markdown",
+ "ko": "Fuyeor Flavored Markdown",
+ "pt": "Fuyeor Flavored Markdown",
+ "ru": "Fuyeor Flavored Markdown",
+ "zh-hans": "Fuyeor Flavored Markdown"
+ },
+ "site.title": {
+ "ar": "ساحة التجربة",
+ "de": "Spielwiese",
+ "en": "Playground",
+ "es": "Área de pruebas",
+ "fr": "Aire de jeux",
+ "ja": "プレイグラウンド",
+ "ko": "플레이그라운드",
+ "pt": "Área de testes",
+ "ru": "Песочница",
+ "zh-hans": "实验场"
+ }
+}
diff --git a/packages/playground/src/main.styles.ts b/packages/playground/src/main.styles.ts
deleted file mode 100644
index 202f5f7..0000000
--- a/packages/playground/src/main.styles.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-// @fuyeor/markdown-parser-playground/src/main.styles.ts
-import { css } from 'lit';
-
-export const styles = css`
- :host {
- display: grid;
- grid-template-columns: 1fr 1fr;
- grid-template-rows: 1fr 300px;
- height: 100vh;
- gap: 1px;
- background: #333;
- font-family: 'Fuyeor Sans', system-ui, sans-serif;
- }
- .pane {
- background: #1a1a1a;
- color: #ccc;
- display: flex;
- flex-direction: column;
- overflow: hidden;
- }
- .header {
- padding: 8px 16px;
- background: #252525;
- font-size: 12px;
- text-transform: uppercase;
- letter-spacing: 1px;
- border-bottom: 1px solid #333;
- }
- textarea {
- flex: 1;
- background: transparent;
- border: none;
- color: #fff;
- padding: 20px;
- font-family: 'Fuyeor Mono', monospace;
- font-size: 14px;
- resize: none;
- outline: none;
- line-height: 1.6;
- }
- #preview {
- flex: 1;
- background: #fff;
- color: #333;
- padding: 20px;
- overflow-y: auto;
- }
- #ast {
- grid-column: span 2;
- background: #000;
- color: #0f0;
- padding: 10px;
- font-family: monospace;
- font-size: 12px;
- overflow-y: auto;
- }
-`;
diff --git a/packages/playground/src/main.ts b/packages/playground/src/main.ts
index 681b400..8c8b4e6 100644
--- a/packages/playground/src/main.ts
+++ b/packages/playground/src/main.ts
@@ -1,45 +1,25 @@
-// @fuyeor/markdown-parser-playground/src/main.ts
-import { LitElement, html } from 'lit';
-import { customElement, state } from 'lit/decorators.js';
-import {
- createFuyeorMarkdownParser,
- render as renderMarkdown,
-} from '@fuyeor/markdown-parser-lit';
-import { styles as mainStyles } from './main.styles';
-import { styles as markdownStyles } from './markdown.styles';
+// @/main.ts
+// pnpm playground
+import App from './App.vue';
+import router from './router';
-@customElement('markdown-playground')
-export class MarkdownPlayground extends LitElement {
- static styles = [mainStyles, markdownStyles];
+import { createApp } from 'vue';
+import { initializeLocale, createHead } from '@fuyeor/commons';
+import { vRipple, vTooltip } from '@fuyeor/interactify';
- #parser = createFuyeorMarkdownParser();
+async function bootstrap() {
+ const app = createApp(App);
+ const head = createHead();
- @state()
- private _source =
- '# Welcome to Markdown Playground\n\nTry writing some **markdown** here!';
+ app.use(router);
+ app.use(head);
- render() {
- const ast = this.#parser(this._source);
+ await initializeLocale({ app });
- return html`
-
-
-
-
+ app.directive('ripple', vRipple);
+ app.directive('tooltip', vTooltip);
-
-
-
${renderMarkdown(ast)}
-
-
-
-
-
${JSON.stringify(ast, null, 2)}
-
- `;
- }
-
- #onInput(e: Event) {
- this._source = (e.target as HTMLTextAreaElement).value;
- }
+ app.mount('#app');
}
+
+bootstrap();
diff --git a/packages/playground/src/markdown.styles.ts b/packages/playground/src/markdown.styles.ts
deleted file mode 100644
index 64781fa..0000000
--- a/packages/playground/src/markdown.styles.ts
+++ /dev/null
@@ -1,588 +0,0 @@
-// @fuyeor/markdown-parser-playground/src/markdown.styles.ts
-import { css } from 'lit';
-
-export const styles = css`
- :host {
- /* 品牌/意图色 */
- --color-brand: #aea4e4;
- --color-brand-deeper: #9f8dff;
- --color-warn: #d93026;
- --color-success: #28a745;
- --color-note: #ffc107;
- --color-info: var(--interact-blue-2);
-
- /* 固定圆角:用于卡片、输入框 */
- --radius-sm: 8px;
- --radius-md: 12px;
- --radius-lg: 16px;
-
- /* 地面 */
- --surface: #f7f7f8;
- --surface-hover: #edeef1;
- --surface-transparent: #ffffffd0;
- /* 浮起块 */
- --surface-raised: #fff;
- --surface-raised-hover: rgba(0, 0, 0, 0.03);
- /* 顶端 */
- --surface-top: #f5f5f6;
- --surface-top-hover: #f0f2f4;
-
- /* 文字颜色 */
- --text-primary: #345;
- --text-secondary: #4d5763;
- --text-tertiary: #67717d;
- /* 链接及 hover */
- --text-accent: var(--interact-blue);
- --text-on-accent: #9c1a1b;
-
- /* 框架边框 */
- --border-subtle: 1px solid #f0f0f1;
- --border-default: 1px solid #dee2e6;
- }
-
- /*表格*/
- .table-container {
- width: 100%;
- overflow-x: auto;
- /* 允许水平滚动 */
- border: var(--border-default);
- /* 给容器添加边框 */
- border-radius: var(--radius-lg);
- /* 给容器添加圆角 */
- margin: 20px 0;
- }
-
- table {
- width: 100%;
- border-collapse: collapse;
- table-layout: auto;
- }
-
- table {
- /* 表格头部添加边框 */
- thead tr {
- border-bottom: var(--border-default);
- background: var(--surface-hover);
- }
-
- thead tr th:not(:first-child):not(:last-child) {
- border-left: var(--border-default);
- border-right: var(--border-default);
- }
-
- th,
- td,
- tr {
- min-width: 100px;
- text-align: left;
- word-wrap: break-word;
- white-space: normal;
- max-width: 400px;
- padding: 10px 4px 10px 10px;
- }
-
- /* 为非角落单元格添加边框 */
- tr td:not(:first-child):not(:last-child) {
- border-left: var(--border-default);
- /* 添加左侧边框 */
- border-right: var(--border-default);
- /* 添加右侧边框 */
- }
-
- tr:not(:first-child) td {
- border-top: var(--border-default);
- /* 添加顶部边框 */
- }
- }
-
- /* 内容区 markdown 富文本 */
- #preview {
- word-wrap: break-word;
- word-break: break-word;
-
- a {
- color: var(--text-accent);
- transition: color 0.3s;
- }
-
- a:hover,
- a:focus {
- color: var(--text-on-accent);
- }
-
- a[href*='www.fuyeor.com']:before {
- content: '';
- position: relative;
- right: 0;
- vertical-align: middle;
- margin-right: 4px;
- display: inline-block;
- width: 18px;
- height: 18px;
- background-size: 18px;
- background-repeat: no-repeat;
- background-position: 50%;
- }
-
- a[href*='www.fuyeor.com']:before {
- width: 20px;
- height: 20px;
- background-size: 20px;
- background-image: url('https://www.fuyeor.com/favicon.svg');
- }
-
- /*标题*/
- h1,
- h2,
- h3 {
- color: var(--text-secondary);
- margin: 24px 0 24px 0;
- }
-
- h2 {
- padding-bottom: 10px;
- border-bottom: var(--border-default);
- font-size: 23px;
- }
-
- pre {
- padding: 10px;
- border-radius: var(--radius-sm);
- overflow-x: auto;
- background: var(--surface-top);
- }
-
- code {
- margin: 0 4px;
- padding: 2px 4px;
- /* 使用等宽字体 */
- font-family: 'Courier New', Courier, monospace;
- font-size: 0.9rem;
- background: var(--surface-top);
- border-radius: 4px;
- }
-
- pre > code {
- background: none;
- white-space: pre;
- margin: 0;
- padding: 0;
- }
-
- p {
- color: var(--text-secondary);
- }
-
- u {
- text-decoration: none;
- border-bottom: var(--border-subtle);
- }
-
- hr {
- /* 先把祖传的 3D 边框全干掉! */
- border: none;
- border-top: var(--border-subtle);
- margin: 2rem 0px;
- }
-
- ol,
- ul {
- margin: 0 0 0 10px;
- padding: 0;
- }
-
- li {
- margin: 10px 0 10px 0;
- color: var(--text-secondary);
- }
-
- code,
- pre,
- pre * {
- font-family: 'Google Sans Code';
- }
-
- .code-block-wrapper {
- margin: 0 0 20px 0;
- background: var(--surface-top);
- border: var(--border-default);
- border-radius: var(--radius-lg);
- }
-
- .pre-language {
- font-size: 0.85rem;
- border-bottom: var(--border-default);
- padding: 10px;
- }
-
- pre {
- position: relative;
- padding: 10px 20px 10px 20px;
- overflow-x: auto;
- /* 横向滚动 */
- white-space: pre;
- /* 保留空格和换行,不自动折行 */
- word-break: normal;
- /* 禁止单词内断行 */
- scrollbar-width: none;
- }
-
- pre > code {
- background: none;
- white-space: pre;
- /* 保留空格和换行,不自动折行 */
- word-break: normal;
- /* 禁止单词内断行 */
- }
-
- /* Katex 公式 */
- .math-block {
- overflow-x: auto;
- overflow-y: hidden;
- white-space: nowrap;
- scrollbar-width: none;
- }
-
- .math-block > .katex-display {
- white-space: normal;
- /* 防止嵌套问题 */
- }
-
- blockquote {
- position: relative;
- padding: 4px 12px 4px 20px;
- margin: 0 0 10px 0;
- background: var(--surface-raised);
- background-image: url(https://deliver.fuyeor.net/@fu/commons/icons/filled/quote.svg);
- background-repeat: no-repeat;
- background-position: 8px 4px;
- background-size: 32px;
- color: var(--text-primary);
- border-radius: var(--radius-sm);
- cursor: pointer;
- }
-
- blockquote::before {
- content: '';
- position: absolute;
- top: 0;
- left: -8px;
- width: 5px;
- height: 100%;
- background-color: var(--surface-raised-hover);
- border-radius: 4px;
- }
-
- img {
- max-width: 100%;
- border-radius: 6px;
- }
-
- .blocked-image {
- padding: 20px;
- background: var(--surface-hover);
- border-radius: 6px;
- }
-
- .emoji {
- margin: 0 0.05rem;
- /* 微调左右间距 */
- position: relative;
- /* 用于微调定位 */
- top: -0.1rem;
- /* 精细微调位置(按需调整) */
- vertical-align: middle;
- /* 关键:垂直居中对齐 */
- border-radius: 0;
- }
-
- .emoji,
- img.emoji,
- span.emoji {
- height: 1.05rem;
- /* 高度与文字保持一致 */
- width: auto;
- /* 宽度按比例自适应 */
- display: inline-block;
- /* 保持行内特性 */
- }
-
- /* [UX 优化] Twemoji 样式:确保 emoji 图片和它的文字回退 都保持一致的尺寸和对齐方式
- img.emoji, span.emoji {
- margin: 0 0.05em 0 0.1rem;
- vertical-align: -0.15rem;
- }*/
- /* Youtube 播放器 */
- .youtube-facade {
- position: relative;
- width: 100%;
- /* 强制锁定 16:9 宽高比,防止页面跳动 (Layout Shift) */
- aspect-ratio: 16 / 9;
- background: #000;
- border-radius: var(--radius-md);
- overflow: hidden;
- cursor: pointer;
- margin: 1.5rem 0;
- border: var(--border-subtle);
- transition: 0.3s all;
-
- &:hover {
- .play-button {
- background: #ea333d;
- }
- }
-
- img {
- display: block;
- width: 100%;
- height: 100%;
- object-fit: cover;
- /* 裁剪模式,确保填满 */
- opacity: 0.9;
- /* 稍微暗一点,突显播放按钮 */
- transition: opacity 0.3s;
- }
-
- /* 纯 CSS 绘制的播放按钮 */
- .play-button {
- position: absolute;
- top: 50%;
- left: 50%;
- width: 50px;
- height: 50px;
- transform: translate(-50%, -50%);
- background: rgba(33, 33, 33, 0.8);
- border-radius: 50%;
- z-index: 2;
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
-
- /* 绘制三角形 */
- &::after {
- content: '';
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- border-style: solid;
- border-width: 10px 0 10px 18px;
- /* 三角形大小 */
- border-color: transparent transparent transparent #fff;
- /* 白色三角形 */
- margin-left: 2px;
- /* 视觉修正居中 */
- }
- }
-
- /* 播放状态 */
- &.is-playing {
- background: #000;
- }
- }
-
- .slide-container-wrapper {
- /* 作为一个容器块,上下留白 */
- margin: 1.5rem -1rem;
- /* 负 margin 让它在移动端可以贴边滑动 */
- padding: 0 1rem;
- /* 补偿 padding */
- overflow: hidden;
-
- /* 防止滚动条溢出容器外 */
- @media (width >= 768px) {
- /* 桌面端恢复正常边距 */
- margin: 1.5rem 0;
- padding: 0;
- }
- }
-
- .slide-container {
- display: flex;
- gap: 1rem;
- /* 卡片间距 */
- overflow-x: auto;
- /* 允许横向滚动 */
- scroll-snap-type: x mandatory;
- /* 隐藏滚动条 */
- scrollbar-width: none;
- }
-
- .slide-item {
- /* 布局核心 */
- flex: 0 0 88%;
- /* 移动端占据 88% 宽度,露出下一张的一点点 */
- scroll-snap-align: center;
- /* 停止时居中对齐 */
- border: var(--border-default);
- border-radius: var(--radius-md);
- padding: 0rem 1rem 0.5rem;
- box-sizing: border-box;
-
- /* 视频播放器取消边距 */
- .youtube-facade {
- margin: 0;
- }
-
- @media (width >= 768px) {
- /* 桌面端可以并列显示两个,或者宽度更小一点 */
- flex: 0 0 60%;
- scroll-snap-align: start;
- /* 桌面端左对齐更自然 */
- }
- }
-
- /* Smiles 化学结构式样式 */
- /* .smiles-block {} */
-
- /* 行内显示 ([smiles]) */
- .smiles-inline {
- display: inline-block;
- height: 1.5em;
- /* 高度跟随文字大小,稍微大一点点看着舒服 */
- vertical-align: middle;
- /* 与文字中线对齐 */
- margin: 0 2px;
- /* 左右留一点点呼吸空间 */
- transform: translateY(-2px);
- /* 微调视觉中心 */
- transition: filter 0.3s ease;
- }
-
- /* Chain (思考链/时间轴) 样式 */
- .chain-container {
- display: flex;
- flex-direction: column;
- /* 去掉 gap,让 item 紧贴,靠 padding 控制间距,这样线才好连 */
- margin: 1.5rem 0;
- padding-left: 1rem;
- font-style: italic;
- }
-
- .chain-item {
- position: relative;
- /* 用 padding 替代原来的 gap,给下一段留出呼吸空间 */
- padding-bottom: 1.2rem;
-
- /* 这是一条贯穿整个 item 的线 */
- &::before {
- content: '';
- position: absolute;
- /* 这里的 left 要和 marker 的中心对齐 */
- /* marker left 是 -18px, width 是 12px -> 中心点大概在 -12px 左右 */
- /* 我们微调一下,假设 marker 还是相对于 content 定位 */
- left: -13px;
- top: 0;
- bottom: 0;
- /* 撑满整个高度! */
- width: 1.5px;
- background: var(--text-tertiary);
- opacity: 0.3;
- /* 稍微淡一点,不要抢了圆圈的风头,显得极简 */
- z-index: 0;
- }
-
- /* 处理最后一个节点:线不要拖到底,只要连到圆圈就行 */
- &:last-child {
- padding-bottom: 0;
-
- &::before {
- /* 让线只延伸到圆圈的位置,或者直接隐藏下半部分 */
- /* 简单的做法:把线的高度设为圆圈的 top 值 */
- bottom: auto;
- height: 6px;
- }
- }
-
- /* 如果第一个节点上面不需要线 */
- &:first-child::before {
- top: 6px;
- /* 从圆圈中间开始往下画 */
- }
- }
-
- /* 圆圈 */
- .chain-marker {
- position: absolute;
- left: -20px;
- top: 0;
- /* 调整为 0 或配合 line-height 对齐 */
- margin-top: 6px;
- /* 微调垂直对齐,视字体大小而定 */
- width: 1rem;
- height: 1rem;
- border-radius: 50%;
- /* 加上边框颜色,强调一下 */
- border: 1.5px solid var(--color-brand);
- /* 背景色遮住后面的线 */
- background: var(--surface);
- z-index: 1;
- /* 必须比线高,压住线 */
- box-sizing: border-box;
- }
-
- .chain-content-wrapper {
- padding-left: 1rem;
- position: relative;
- }
-
- .chain-title {
- font-weight: bold;
- margin-bottom: 1rem;
- }
-
- .chain-body {
- color: var(--text-secondary);
- font-size: 0.95em;
-
- p {
- margin: 0.5rem 0;
- }
- }
-
- .chain-item.is-completed,
- .chain-item.is-pending {
- /* 圆圈里的图片样式 */
- .chain-marker::after {
- content: '';
- position: absolute;
- top: 50%;
- left: 50%;
- transform: translate(-48%, -48%);
- width: 14px;
- height: 14px;
- background-size: contain;
- background-repeat: no-repeat;
- background-position: center;
- z-index: 5;
- }
- }
-
- /* 状态:已完成 (is-completed) */
- .chain-item.is-completed {
- /* 圆圈变实心 */
- .chain-marker {
- border-color: var(--color-success);
- }
-
- /* 在圆圈里加个对勾 */
- .chain-marker::after {
- background-image: url('https://deliver.fuyeor.net/@fu/icons/outlined/checked.svg');
- }
-
- /* 标题稍微淡一点,表示已过去 */
- .chain-title {
- opacity: 0.8;
- }
- }
-
- /* 状态:待办 (is-pending) */
- .chain-item.is-pending {
- .chain-marker {
- border-color: var(--color-note);
- }
-
- .chain-marker::after {
- background-image: url('https://deliver.fuyeor.net/@fu/icons/outlined/more-horizon.svg');
- }
- }
- }
-`;
diff --git a/packages/playground/src/router/index.ts b/packages/playground/src/router/index.ts
new file mode 100644
index 0000000..e73d411
--- /dev/null
+++ b/packages/playground/src/router/index.ts
@@ -0,0 +1,90 @@
+// @/router/index.ts
+import { createRouter, RouterView, type RouteRecord } from '@fuyeor/vue-router';
+import { useTransitionBar } from '@fuyeor/interactify';
+import { useLocaleStore } from '@fuyeor/commons';
+import { LOCALE_REGEX } from '@/config/locales';
+
+const { start, done } = useTransitionBar();
+
+const appRoutes: Array = [
+ {
+ // flavored.fuyeor.com/
+ path: '',
+ name: 'Home',
+ component: () => import('@/views/Home.vue'),
+ meta: {
+ overrideTitle: ['site.name', '/', 'site.title'],
+ },
+ },
+ {
+ // flavored.fuyeor.com/playground or /playground/:id
+ // The optional segment uses URLPattern syntax required by @fuyeor/vue-router.
+ path: 'playground{/:id}?',
+ name: 'Playground',
+ component: () => import('@/views/Playground.vue'),
+ meta: {
+ titleKey: 'playground',
+ },
+ },
+];
+
+// root router
+const routes: Array = [
+ {
+ // optional locale prefix wrapper, only allows supported locales
+ path: `{/:locale(${LOCALE_REGEX})}?`,
+ component: RouterView,
+ // 将所有应用路由放入 children
+ // 注意:子路由的 path 如果不以 / 开头,会拼接在父路由后面
+ // 例如:/en/thought/123 或 /thought/123
+ children: appRoutes,
+ },
+
+ // 404 路由必须放在最外层,且在最后
+ // 如果 URL 是 /xx/thought/123 (不支持的语言),正则匹配失败,会落到这里
+ {
+ path: '/*', // 通配符路由,捕获所有未匹配的路径
+ name: 'NotFound',
+ component: () =>
+ import('@fuyeor/interactify/views').then((m) => m.NotFoundView),
+ meta: {
+ titleKey: 'notFound.title',
+ },
+ },
+];
+
+// 创建路由实例
+const router = createRouter({ routes });
+
+// 路由守卫
+router.beforeEach(async (to) => {
+ // 启动顶部进度条
+ start();
+
+ // 获取语言 store
+ const localeStore = useLocaleStore();
+
+ // 从路由参数中获取 locale (例如 'en' 或 undefined)
+ const routeLocale = to.params.locale as string | undefined;
+
+ // 如果没有语言参数就添加语言
+ if (!routeLocale) {
+ return {
+ name: to.name,
+ params: { ...to.params, locale: localeStore.locale },
+ };
+ }
+
+ // 如果代码能执行到这里,说明所有检查都通过了,允许导航
+ return true;
+});
+
+router.afterEach(() => {
+ done();
+});
+
+router.onError(() => {
+ done();
+});
+
+export default router;
diff --git a/packages/playground/src/views/Home.vue b/packages/playground/src/views/Home.vue
new file mode 100644
index 0000000..2d8e154
--- /dev/null
+++ b/packages/playground/src/views/Home.vue
@@ -0,0 +1,6 @@
+
+Hello
+
+
+
+
diff --git a/packages/playground/src/views/Playground.vue b/packages/playground/src/views/Playground.vue
new file mode 100644
index 0000000..18fa253
--- /dev/null
+++ b/packages/playground/src/views/Playground.vue
@@ -0,0 +1,268 @@
+
+
+
+
+
+
+
+
diff --git a/packages/playground/tsconfig.json b/packages/playground/tsconfig.json
index 1c78ed6..b664f43 100644
--- a/packages/playground/tsconfig.json
+++ b/packages/playground/tsconfig.json
@@ -1,20 +1,16 @@
{
- "$schema": "https://json.schemastore.org/tsconfig",
+ "extends": "@fuyeor/tsconfig/base.json",
"compilerOptions": {
"paths": {
- "#/*": ["./src/*"]
+ "@/*": ["./src/*"]
},
- "target": "ESNext",
- "module": "ESNext",
- "moduleResolution": "Bundler",
- "lib": ["ESNext", "DOM"],
- "strict": true,
- "isolatedModules": true,
- "resolveJsonModule": true,
- "skipLibCheck": true,
- "noEmit": true,
- "experimentalDecorators": true,
- "useDefineForClassFields": false
+ "types": ["vite/client", "node"]
},
- "include": ["src/**/*.ts", "vite.config.ts"]
+ "include": [
+ "vite.config.ts",
+ "vite-env.d.ts",
+ "src/**/*.ts",
+ "src/**/*.d.ts",
+ "src/**/*.vue"
+ ]
}
diff --git a/packages/playground/vite.config.ts b/packages/playground/vite.config.ts
index 9937df7..3548bf0 100644
--- a/packages/playground/vite.config.ts
+++ b/packages/playground/vite.config.ts
@@ -1,20 +1,15 @@
// @fuyeor/markdown-parser-playground/vite.config.ts
import { defineConfig } from 'vite';
+import { createViteConfig } from '@fuyeor/config/vite.config.js';
-export default defineConfig({
- plugins: [],
- server: {
- port: 7820,
- },
- build: {
- // generate to dist/assets/build/
- outDir: 'dist',
- rollupOptions: {
- output: {
- entryFileNames: `assets/entry.[hash].js`,
- chunkFileNames: `assets/chunk.[hash].js`,
- assetFileNames: `assets/asset.[hash].[ext]`,
+export default defineConfig(() => {
+ return createViteConfig(
+ {
+ server: {
+ host: '0.0.0.0',
+ port: 7820,
},
},
- },
+ import.meta.dirname,
+ );
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 0835787..db9d443 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,9 @@ importers:
.:
devDependencies:
+ '@fuyeor/locale-cli':
+ specifier: ^0.1.1
+ version: 0.1.1
'@types/node':
specifier: ^25.6.0
version: 25.6.0
@@ -22,7 +25,7 @@ importers:
version: 6.0.3
vitest:
specifier: ^4.1.0
- version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))
packages/benchmarks:
dependencies:
@@ -56,7 +59,7 @@ importers:
version: 6.0.3
vitest:
specifier: ^4.1.0
- version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))
packages/markdown-formatter:
devDependencies:
@@ -68,7 +71,7 @@ importers:
version: 6.0.3
vitest:
specifier: ^4.1.0
- version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))
packages/markdown-parser:
devDependencies:
@@ -80,7 +83,7 @@ importers:
version: 6.0.3
vitest:
specifier: ^4.1.0
- version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))
packages/markdown-parser-lit:
dependencies:
@@ -116,44 +119,55 @@ importers:
packages/playground:
dependencies:
+ '@fuyeor/commons':
+ specifier: ^0.1.2
+ version: 0.1.2(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/config':
+ specifier: ^0.1.1
+ version: 0.1.1(vite@8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/interactify':
+ specifier: ^0.1.1
+ version: 0.1.1(vue@3.5.41(typescript@7.0.2))
'@fuyeor/locale':
- specifier: https://github.com/Fuyeor/webroamer.git#path:packages/locale
- version: https://codeload.github.com/Fuyeor/webroamer/tar.gz/c502f739f4b633ab24386fe9f90fb77ed9f6ca9d#path:packages/locale(@lit-labs/signals@0.2.0)(lit@3.3.2)(signal-polyfill@0.2.2)
- '@fuyeor/markdown-parser-lit':
- specifier: workspace:*
- version: link:../markdown-parser-lit
- lit:
- specifier: ^3.3.2
- version: 3.3.2
- devDependencies:
- '@types/node':
- specifier: ^25.6.0
- version: 25.6.0
- typescript:
- specifier: ^6.0.3
- version: 6.0.3
- vite:
- specifier: ^8.0.1
- version: 8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)
-
- packages/vscode-extension:
- dependencies:
+ specifier: ^0.1.0
+ version: 0.1.0(vue@3.5.41(typescript@7.0.2))
'@fuyeor/markdown-formatter':
specifier: workspace:*
version: link:../markdown-formatter
+ '@fuyeor/markdown-parser':
+ specifier: workspace:*
+ version: link:../markdown-parser
+ '@fuyeor/markdown-parser-vue':
+ specifier: workspace:*
+ version: link:../markdown-parser-vue
+ '@fuyeor/vue-router':
+ specifier: ^0.0.9
+ version: 0.0.9(vue@3.5.41(typescript@7.0.2))
+ vue:
+ specifier: ^3.5.41
+ version: 3.5.41(typescript@7.0.2)
devDependencies:
- '@types/vscode':
- specifier: ^1.80.0
- version: 1.134.0
- esbuild:
- specifier: ^0.27.7
- version: 0.27.7
+ '@fuyeor/tsconfig':
+ specifier: 0.1.0
+ version: 0.1.0
+ '@types/node':
+ specifier: ^26.2.0
+ version: 26.2.0
+ '@vitejs/plugin-vue':
+ specifier: ^6.0.8
+ version: 6.0.8(vite@8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))(vue@3.5.41(typescript@7.0.2))
+ html-minifier-terser:
+ specifier: ^7.2.0
+ version: 7.2.0
+ lightningcss:
+ specifier: ^1.33.0
+ version: 1.33.0
typescript:
- specifier: ^6.0.3
- version: 6.0.3
- vitest:
- specifier: ^4.1.0
- version: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ specifier: ^7.0.2
+ version: 7.0.2
+ vite:
+ specifier: 8.0.1
+ version: 8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0)
packages:
@@ -176,19 +190,36 @@ packages:
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-string-parser@7.29.7':
+ resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-validator-identifier@7.28.5':
resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-validator-identifier@7.29.7':
+ resolution: {integrity: sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==}
+ engines: {node: '>=6.9.0'}
+
'@babel/parser@7.29.2':
resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==}
engines: {node: '>=6.0.0'}
hasBin: true
+ '@babel/parser@7.29.8':
+ resolution: {integrity: sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+
'@babel/types@7.29.0':
resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==}
engines: {node: '>=6.9.0'}
+ '@babel/types@7.29.8':
+ resolution: {integrity: sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==}
+ engines: {node: '>=6.9.0'}
+
'@bcoe/v8-coverage@1.0.2':
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
@@ -407,27 +438,97 @@ packages:
'@noble/hashes':
optional: true
- '@fuyeor/locale@https://codeload.github.com/Fuyeor/webroamer/tar.gz/c502f739f4b633ab24386fe9f90fb77ed9f6ca9d#path:packages/locale':
- resolution: {gitHosted: true, path: packages/locale, tarball: https://codeload.github.com/Fuyeor/webroamer/tar.gz/c502f739f4b633ab24386fe9f90fb77ed9f6ca9d}
- version: 1.0.0
+ '@floating-ui/core@1.8.0':
+ resolution: {integrity: sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==}
+
+ '@floating-ui/dom@1.8.0':
+ resolution: {integrity: sha512-yXSrzeHZBTZadLOlfyhCkJHNeLJnHRnRInwdZ40L7ZiaAtrBwoYlsDrX3v5zB1Utk7CLfzcOVnVVWoXEky7Ceg==}
+
+ '@floating-ui/utils@0.2.12':
+ resolution: {integrity: sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==}
+
+ '@floating-ui/vue@1.1.11':
+ resolution: {integrity: sha512-HzHKCNVxnGS35r9fCHBc3+uCnjw9IWIlCPL683cGgM9Kgj2BiAl8x1mS7vtvP6F9S/e/q4O6MApwSHj8hNLGfw==}
+
+ '@fuyeor/commons@0.1.0':
+ resolution: {integrity: sha256-0ftDuLXPoQiLotiSRC2cmVF/+cViXO11ZV2pTpbkXbM=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/commons/0.1.0.tgz}
+ peerDependencies:
+ vue: '*'
+
+ '@fuyeor/commons@0.1.2':
+ resolution: {integrity: sha256-X1Ejy4MgCaO8iFkvph8SavvY2kFJtaCXdJ6OYG8ceJE=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/commons/0.1.2.tgz}
+ peerDependencies:
+ vue: '*'
+
+ '@fuyeor/config@0.1.1':
+ resolution: {integrity: sha256-YdN7bfe71NeQWfak1cpnKna7byyJ3PYhnBbqDFCDRVo=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/config/0.1.1.tgz}
+ peerDependencies:
+ vite: ' ^8.0.0'
+
+ '@fuyeor/interactify@0.1.1':
+ resolution: {integrity: sha256-rz+0xlSjMcNjFnmliyDT3TkB8Y08XLiuRiTfZz7FqTQ=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/interactify/0.1.1.tgz}
+ peerDependencies:
+ vue: '*'
+
+ '@fuyeor/locale-cli-linux-x64@0.1.1':
+ resolution: {integrity: sha256-yUuBN7NGq6kvNjAx+gK/FjSAAQIsQXdTrUOIPmDAlPU=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/locale-cli-linux-x64/0.1.1.tgz}
+ cpu: [x64]
+ os: [linux]
+
+ '@fuyeor/locale-cli-win32-x64@0.1.1':
+ resolution: {integrity: sha256-kMoqlLWBKOyK1QSmiu50OCPt+oqfFRX1CF702XSum94=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/locale-cli-win32-x64/0.1.1.tgz}
+ cpu: [x64]
+ os: [win32]
+
+ '@fuyeor/locale-cli@0.1.1':
+ resolution: {integrity: sha256-i4zBm0Akv/BHJaBQmt/kXHqNYcBcCVQYVFcLVqpO6Fw=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/locale-cli/0.1.1.tgz}
+ hasBin: true
+
+ '@fuyeor/locale@0.1.0':
+ resolution: {integrity: sha256-ph3M1g9OPWb8WVAt+W0NeoDJT2uhb9ALn/NnCN0wvZU=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/locale/0.1.0.tgz}
+ peerDependencies:
+ vue: '*'
+
+ '@fuyeor/tsconfig@0.1.0':
+ resolution: {integrity: sha256-j5XnwkpNS2BAC5xfOcxuE25IxO8TPT0XDjtQ7j8r2HU=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/tsconfig/0.1.0.tgz}
+
+ '@fuyeor/vue-router@0.0.9':
+ resolution: {integrity: sha256-Hhbeyxi0tBIO7qPueEvCC1uzWdO2S3yCPZ8hPAQCMdM=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/vue-router/0.0.9.tgz}
+ peerDependencies:
+ vue: '*'
+
+ '@fuyeor/vue-router@0.1.0':
+ resolution: {integrity: sha256-+y1kO8p9TdcQaYtZFjc/PJBs+Yykhr8h8mPjbGzJ95k=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/vue-router/0.1.0.tgz}
peerDependencies:
- '@lit-labs/signals': '*'
- lit: '*'
- signal-polyfill: '*'
+ vue: '*'
+
+ '@fuyeor/vue-vaul@0.4.8':
+ resolution: {integrity: sha256-0dlkmUCIbw4hFtYoMO678Si2tTOF3dfSVN8fWWau2Eg=, tarball: https://fpm.fuyeor.net/packages/@fuyeor/vue-vaul/0.4.8.tgz}
+ peerDependencies:
+ vue: ^3.4.0
+
+ '@internationalized/date@3.12.3':
+ resolution: {integrity: sha512-fuLX+3ZKLsxI73y8b01EG/WjHb6gE6weCqlfawPO27kBWGMh9G1yH6Csv1uU7/cac9H2GHmOMt6CjmuQ1aia4Q==}
+
+ '@internationalized/number@3.6.7':
+ resolution: {integrity: sha512-3ji1fcrT+FPAK86UqEhB/psHixYo6niWPJtt7+qRaYFynt/BaJG8GhAPimtWUpEiVSTq8ZM8L5psMxGquiB/Vg==}
+
+ '@jridgewell/gen-mapping@0.3.13':
+ resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
'@jridgewell/resolve-uri@3.1.2':
resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==}
engines: {node: '>=6.0.0'}
+ '@jridgewell/source-map@0.3.11':
+ resolution: {integrity: sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==}
+
'@jridgewell/sourcemap-codec@1.5.5':
resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==}
'@jridgewell/trace-mapping@0.3.31':
resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==}
- '@lit-labs/signals@0.2.0':
- resolution: {integrity: sha512-68plyIbciumbwKaiilhLNyhz4Vg6/+nJwDufG2xxWA9r/fUw58jxLHCAlKs+q1CE5Lmh3cZ3ShyYKnOCebEpVA==}
-
'@lit-labs/ssr-dom-shim@1.5.1':
resolution: {integrity: sha512-Aou5UdlSpr5whQe8AA/bZG0jMj96CoJIWbGfZ91qieWu5AWUMKw8VR/pAkQkJYvBNhmCcWnZlyyk5oze8JIqYA==}
@@ -440,39 +541,79 @@ packages:
'@emnapi/core': ^1.7.1
'@emnapi/runtime': ^1.7.1
+ '@oxc-project/types@0.120.0':
+ resolution: {integrity: sha512-k1YNu55DuvAip/MGE1FTsIuU3FUCn6v/ujG9V7Nq5Df/kX2CWb13hhwD0lmJGMGqE+bE1MXvv9SZVnMzEXlWcg==}
+
'@oxc-project/types@0.126.0':
resolution: {integrity: sha512-oGfVtjAgwQVVpfBrbtk4e1XDyWHRFta6BS3GWVzrF8xYBT2VGQAk39yJS/wFSMrZqoiCU4oghT3Ch0HaHGIHcQ==}
+ '@rolldown/binding-android-arm64@1.0.0-rc.10':
+ resolution: {integrity: sha512-jOHxwXhxmFKuXztiu1ORieJeTbx5vrTkcOkkkn2d35726+iwhrY1w/+nYY/AGgF12thg33qC3R1LMBF5tHTZHg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
'@rolldown/binding-android-arm64@1.0.0-rc.16':
resolution: {integrity: sha512-rhY3k7Bsae9qQfOtph2Pm2jZEA+s8Gmjoz4hhmx70K9iMQ/ddeae+xhRQcM5IuVx5ry1+bGfkvMn7D6MJggVSA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [android]
+ '@rolldown/binding-darwin-arm64@1.0.0-rc.10':
+ resolution: {integrity: sha512-gED05Teg/vtTZbIJBc4VNMAxAFDUPkuO/rAIyyxZjTj1a1/s6z5TII/5yMGZ0uLRCifEtwUQn8OlYzuYc0m70w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
'@rolldown/binding-darwin-arm64@1.0.0-rc.16':
resolution: {integrity: sha512-rNz0yK078yrNn3DrdgN+PKiMOW8HfQ92jQiXxwX8yW899ayV00MLVdaCNeVBhG/TbH3ouYVObo8/yrkiectkcQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [darwin]
+ '@rolldown/binding-darwin-x64@1.0.0-rc.10':
+ resolution: {integrity: sha512-rI15NcM1mA48lqrIxVkHfAqcyFLcQwyXWThy+BQ5+mkKKPvSO26ir+ZDp36AgYoYVkqvMcdS8zOE6SeBsR9e8A==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
'@rolldown/binding-darwin-x64@1.0.0-rc.16':
resolution: {integrity: sha512-r/OmdR00HmD4i79Z//xO06uEPOq5hRXdhw7nzkxQxwSavs3PSHa1ijntdpOiZ2mzOQ3fVVu8C1M19FoNM+dMUQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [darwin]
+ '@rolldown/binding-freebsd-x64@1.0.0-rc.10':
+ resolution: {integrity: sha512-XZRXHdTa+4ME1MuDVp021+doQ+z6Ei4CCFmNc5/sKbqb8YmkiJdj8QKlV3rCI0AJtAeSB5n0WGPuJWNL9p/L2w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
'@rolldown/binding-freebsd-x64@1.0.0-rc.16':
resolution: {integrity: sha512-KcRE5w8h0OnjUatG8pldyD14/CQ5Phs1oxfR+3pKDjboHRo9+MkqQaiIZlZRpsxC15paeXme/I127tUa9TXJ6g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [freebsd]
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.10':
+ resolution: {integrity: sha512-R0SQMRluISSLzFE20sPWYHVmJdDQnRyc/FzSCN72BqQmh2SOZUFG+N3/vBZpR4C6WpEUVYJLrYUXaj43sJsNLA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16':
resolution: {integrity: sha512-bT0guA1bpxEJ/ZhTRniQf7rNF8ybvXOuWbNIeLABaV5NGjx4EtOWBTSRGWFU9ZWVkPOZ+HNFP8RMcBokBiZ0Kg==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm]
os: [linux]
+ '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.10':
+ resolution: {integrity: sha512-Y1reMrV/o+cwpduYhJuOE3OMKx32RMYCidf14y+HssARRmhDuWXJ4yVguDg2R/8SyyGNo+auzz64LnPK9Hq6jg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16':
resolution: {integrity: sha512-+tHktCHWV8BDQSjemUqm/Jl/TPk3QObCTIjmdDy/nlupcujZghmKK2962LYrqFpWu+ai01AN/REOH3NEpqvYQg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -480,6 +621,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@rolldown/binding-linux-arm64-musl@1.0.0-rc.10':
+ resolution: {integrity: sha512-vELN+HNb2IzuzSBUOD4NHmP9yrGwl1DVM29wlQvx1OLSclL0NgVWnVDKl/8tEks79EFek/kebQKnNJkIAA4W2g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.16':
resolution: {integrity: sha512-3fPzdREH806oRLxpTWW1Gt4tQHs0TitZFOECB2xzCFLPKnSOy90gwA7P29cksYilFO6XVRY1kzga0cL2nRjKPg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -487,6 +635,13 @@ packages:
os: [linux]
libc: [musl]
+ '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.10':
+ resolution: {integrity: sha512-ZqrufYTgzxbHwpqOjzSsb0UV/aV2TFIY5rP8HdsiPTv/CuAgCRjM6s9cYFwQ4CNH+hf9Y4erHW1GjZuZ7WoI7w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
'@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.16':
resolution: {integrity: sha512-EKwI1tSrLs7YVw+JPJT/G2dJQ1jl9qlTTTEG0V2Ok/RdOenRfBw2PQdLPyjhIu58ocdBfP7vIRN/pvMsPxs/AQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -494,6 +649,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.10':
+ resolution: {integrity: sha512-gSlmVS1FZJSRicA6IyjoRoKAFK7IIHBs7xJuHRSmjImqk3mPPWbR7RhbnfH2G6bcmMEllCt2vQ/7u9e6bBnByg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
'@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16':
resolution: {integrity: sha512-Uknladnb3Sxqu6SEcqBldQyJUpk8NleooZEc0MbRBJ4inEhRYWZX0NJu12vNf2mqAq7gsofAxHrGghiUYjhaLQ==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -501,6 +663,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@rolldown/binding-linux-x64-gnu@1.0.0-rc.10':
+ resolution: {integrity: sha512-eOCKUpluKgfObT2pHjztnaWEIbUabWzk3qPZ5PuacuPmr4+JtQG4k2vGTY0H15edaTnicgU428XW/IH6AimcQw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.16':
resolution: {integrity: sha512-FIb8+uG49sZBtLTn+zt1AJ20TqVcqWeSIyoVt0or7uAWesgKaHbiBh6OpA/k9v0LTt+PTrb1Lao133kP4uVxkg==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -508,6 +677,13 @@ packages:
os: [linux]
libc: [glibc]
+ '@rolldown/binding-linux-x64-musl@1.0.0-rc.10':
+ resolution: {integrity: sha512-Xdf2jQbfQowJnLcgYfD/m0Uu0Qj5OdxKallD78/IPPfzaiaI4KRAwZzHcKQ4ig1gtg1SuzC7jovNiM2TzQsBXA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
'@rolldown/binding-linux-x64-musl@1.0.0-rc.16':
resolution: {integrity: sha512-RuERhF9/EgWxZEXYWCOaViUWHIboceK4/ivdtQ3R0T44NjLkIIlGIAVAuCddFxsZ7vnRHtNQUrt2vR2n2slB2w==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -515,35 +691,75 @@ packages:
os: [linux]
libc: [musl]
+ '@rolldown/binding-openharmony-arm64@1.0.0-rc.10':
+ resolution: {integrity: sha512-o1hYe8hLi1EY6jgPFyxQgQ1wcycX+qz8eEbVmot2hFkgUzPxy9+kF0u0NIQBeDq+Mko47AkaFFaChcvZa9UX9Q==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
'@rolldown/binding-openharmony-arm64@1.0.0-rc.16':
resolution: {integrity: sha512-mXcXnvd9GpazCxeUCCnZ2+YF7nut+ZOEbE4GtaiPtyY6AkhZWbK70y1KK3j+RDhjVq5+U8FySkKRb/+w0EeUwA==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [openharmony]
+ '@rolldown/binding-wasm32-wasi@1.0.0-rc.10':
+ resolution: {integrity: sha512-Ugv9o7qYJudqQO5Y5y2N2SOo6S4WiqiNOpuQyoPInnhVzCY+wi/GHltcLHypG9DEUYMB0iTB/huJrpadiAcNcA==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
'@rolldown/binding-wasm32-wasi@1.0.0-rc.16':
resolution: {integrity: sha512-3Q2KQxnC8IJOLqXmUMoYwyIPZU9hzRbnHaoV3Euz+VVnjZKcY8ktnNP8T9R4/GGQtb27C/UYKABxesKWb8lsvQ==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [wasm32]
+ '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.10':
+ resolution: {integrity: sha512-7UODQb4fQUNT/vmgDZBl3XOBAIOutP5R3O/rkxg0aLfEGQ4opbCgU5vOw/scPe4xOqBwL9fw7/RP1vAMZ6QlAQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16':
resolution: {integrity: sha512-tj7XRemQcOcFwv7qhpUxMTBbI5mWMlE4c1Omhg5+h8GuLXzyj8HviYgR+bB2DMDgRqUE+jiDleqSCRjx4aYk/Q==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [arm64]
os: [win32]
+ '@rolldown/binding-win32-x64-msvc@1.0.0-rc.10':
+ resolution: {integrity: sha512-PYxKHMVHOb5NJuDL53vBUl1VwUjymDcYI6rzpIni0C9+9mTiJedvUxSk7/RPp7OOAm3v+EjgMu9bIy3N6b408w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.16':
resolution: {integrity: sha512-PH5DRZT+F4f2PTXRXR8uJxnBq2po/xFtddyabTJVJs/ZYVHqXPEgNIr35IHTEa6bpa0Q8Awg+ymkTaGnKITw4g==}
engines: {node: ^20.19.0 || >=22.12.0}
cpu: [x64]
os: [win32]
+ '@rolldown/pluginutils@1.0.0-rc.10':
+ resolution: {integrity: sha512-UkVDEFk1w3mveXeKgaTuYfKWtPbvgck1dT8TUG3bnccrH0XtLTuAyfCoks4Q/M5ZGToSVJTIQYCzy2g/atAOeg==}
+
'@rolldown/pluginutils@1.0.0-rc.16':
resolution: {integrity: sha512-45+YtqxLYKDWQouLKCrpIZhke+nXxhsw+qAHVzHDVwttyBlHNBVs2K25rDXrZzhpTp9w1FlAlvweV1H++fdZoA==}
+ '@rolldown/pluginutils@1.0.1':
+ resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==}
+
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+ '@swc/helpers@0.5.23':
+ resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==}
+
+ '@tanstack/virtual-core@3.17.8':
+ resolution: {integrity: sha512-BfEvehNpOT75r5Ksc5xW6NZuXujTfb7nlSEyVu4XHG3gdxNg1KqXruWbDewXOUaUYIo4oRbSfkjIajz4MAT8tA==}
+
+ '@tanstack/vue-virtual@3.13.36':
+ resolution: {integrity: sha512-gKpExv4RbB9luVG+SucTXoqPZv/gzu/Yvz6BNO+8kpNxJ2x+I/ulryzl5W9BRciahZGp5Tls3Dp5XP1ztVGbMw==}
+ peerDependencies:
+ vue: ^2.7.0 || ^3.0.0
+
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
@@ -559,11 +775,141 @@ packages:
'@types/node@25.6.0':
resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==}
+ '@types/node@26.2.0':
+ resolution: {integrity: sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg==}
+
'@types/trusted-types@2.0.7':
resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==}
- '@types/vscode@1.134.0':
- resolution: {integrity: sha512-NDEu0hg4sF7+vvFsADsktqUJ6f80LHSZvVK2Ovo1XiQ0/VHck1O3zst+ZZyVA/uvz6vo6LcuoqU2q48YMqOwWw==}
+ '@types/web-bluetooth@0.0.21':
+ resolution: {integrity: sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==}
+
+ '@typescript/typescript-aix-ppc64@7.0.2':
+ resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [ppc64]
+ os: [aix]
+
+ '@typescript/typescript-darwin-arm64@7.0.2':
+ resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@typescript/typescript-darwin-x64@7.0.2':
+ resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [darwin]
+
+ '@typescript/typescript-freebsd-arm64@7.0.2':
+ resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [freebsd]
+
+ '@typescript/typescript-freebsd-x64@7.0.2':
+ resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@typescript/typescript-linux-arm64@7.0.2':
+ resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [linux]
+
+ '@typescript/typescript-linux-arm@7.0.2':
+ resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm]
+ os: [linux]
+
+ '@typescript/typescript-linux-loong64@7.0.2':
+ resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [loong64]
+ os: [linux]
+
+ '@typescript/typescript-linux-mips64el@7.0.2':
+ resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [mips64el]
+ os: [linux]
+
+ '@typescript/typescript-linux-ppc64@7.0.2':
+ resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [ppc64]
+ os: [linux]
+
+ '@typescript/typescript-linux-riscv64@7.0.2':
+ resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [riscv64]
+ os: [linux]
+
+ '@typescript/typescript-linux-s390x@7.0.2':
+ resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==}
+ engines: {node: '>=16.20.0'}
+ cpu: [s390x]
+ os: [linux]
+
+ '@typescript/typescript-linux-x64@7.0.2':
+ resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [linux]
+
+ '@typescript/typescript-netbsd-arm64@7.0.2':
+ resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [netbsd]
+
+ '@typescript/typescript-netbsd-x64@7.0.2':
+ resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [netbsd]
+
+ '@typescript/typescript-openbsd-arm64@7.0.2':
+ resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [openbsd]
+
+ '@typescript/typescript-openbsd-x64@7.0.2':
+ resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [openbsd]
+
+ '@typescript/typescript-sunos-x64@7.0.2':
+ resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [sunos]
+
+ '@typescript/typescript-win32-arm64@7.0.2':
+ resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==}
+ engines: {node: '>=16.20.0'}
+ cpu: [arm64]
+ os: [win32]
+
+ '@typescript/typescript-win32-x64@7.0.2':
+ resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==}
+ engines: {node: '>=16.20.0'}
+ cpu: [x64]
+ os: [win32]
+
+ '@vitejs/plugin-vue@6.0.8':
+ resolution: {integrity: sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ peerDependencies:
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ vue: ^3.2.25
'@vitest/coverage-v8@4.1.4':
resolution: {integrity: sha512-x7FptB5oDruxNPDNY2+S8tCh0pcq7ymCe1gTHcsp733jYjrJl8V1gMUlVysuCD9Kz46Xz9t1akkv08dPcYDs1w==}
@@ -606,35 +952,84 @@ packages:
'@vue/compiler-core@3.5.32':
resolution: {integrity: sha512-4x74Tbtqnda8s/NSD6e1Dr5p1c8HdMU5RWSjMSUzb8RTcUQqevDCxVAitcLBKT+ie3o0Dl9crc/S/opJM7qBGQ==}
+ '@vue/compiler-core@3.5.41':
+ resolution: {integrity: sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==}
+
'@vue/compiler-dom@3.5.32':
resolution: {integrity: sha512-ybHAu70NtiEI1fvAUz3oXZqkUYEe5J98GjMDpTGl5iHb0T15wQYLR4wE3h9xfuTNA+Cm2f4czfe8B4s+CCH57Q==}
+ '@vue/compiler-dom@3.5.41':
+ resolution: {integrity: sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==}
+
'@vue/compiler-sfc@3.5.32':
resolution: {integrity: sha512-8UYUYo71cP/0YHMO814TRZlPuUUw3oifHuMR7Wp9SNoRSrxRQnhMLNlCeaODNn6kNTJsjFoQ/kqIj4qGvya4Xg==}
+ '@vue/compiler-sfc@3.5.41':
+ resolution: {integrity: sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ==}
+
'@vue/compiler-ssr@3.5.32':
resolution: {integrity: sha512-Gp4gTs22T3DgRotZ8aA/6m2jMR+GMztvBXUBEUOYOcST+giyGWJ4WvFd7QLHBkzTxkfOt8IELKNdpzITLbA2rw==}
+ '@vue/compiler-ssr@3.5.41':
+ resolution: {integrity: sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A==}
+
'@vue/reactivity@3.5.32':
resolution: {integrity: sha512-/ORasxSGvZ6MN5gc+uE364SxFdJ0+WqVG0CENXaGW58TOCdrAW76WWaplDtECeS1qphvtBZtR+3/o1g1zL4xPQ==}
+ '@vue/reactivity@3.5.41':
+ resolution: {integrity: sha512-rznsqKM0np0x18EjzF8x88MpEhdNsffbvFbckLL5+oUKz1BxAImEmO7J1ArRYSyo6aQaVoBDp7jEkT91OOxydA==}
+
'@vue/runtime-core@3.5.32':
resolution: {integrity: sha512-pDrXCejn4UpFDFmMd27AcJEbHaLemaE5o4pbb7sLk79SRIhc6/t34BQA7SGNgYtbMnvbF/HHOftYBgFJtUoJUQ==}
+ '@vue/runtime-core@3.5.41':
+ resolution: {integrity: sha512-Vcry58hiAKwGen9Z1jUZE0feFsNArPCMOImYI8el48A9Idf6DuQYD0U05zZIF2Iad1hGhPSvcbBbAOhNr55fhg==}
+
'@vue/runtime-dom@3.5.32':
resolution: {integrity: sha512-1CDVv7tv/IV13V8Nip1k/aaObVbWqRlVCVezTwx3K07p7Vxossp5JU1dcPNhJk3w347gonIUT9jQOGutyJrSVQ==}
+ '@vue/runtime-dom@3.5.41':
+ resolution: {integrity: sha512-3vVBahVBS9+U6cmXBLyb8nE6/yYo4J/CGI9eVFs3KiMc0YHuudwKyShTD65jtJy/L9PUUxNAFu4cj4LiJ0UFbw==}
+
'@vue/server-renderer@3.5.32':
resolution: {integrity: sha512-IOjm2+JQwRFS7W28HNuJeXQle9KdZbODFY7hFGVtnnghF51ta20EWAZJHX+zLGtsHhaU6uC9BGPV52KVpYryMQ==}
peerDependencies:
vue: 3.5.32
+ '@vue/server-renderer@3.5.41':
+ resolution: {integrity: sha512-n6hx/pNFfbD6SuyeuMVkvqox8bwf/ET9JlA/kAz/imw8sw++wkqKe2mHX5KutjPpbKE4Z56yTHszoOjGMI9igQ==}
+
'@vue/shared@3.5.32':
resolution: {integrity: sha512-ksNyrmRQzWJJ8n3cRDuSF7zNNontuJg1YHnmWRJd2AMu8Ij2bqwiiri2lH5rHtYPZjj4STkNcgcmiQqlOjiYGg==}
+ '@vue/shared@3.5.41':
+ resolution: {integrity: sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==}
+
+ '@vueuse/core@14.4.0':
+ resolution: {integrity: sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==}
+ peerDependencies:
+ vue: ^3.5.0
+
+ '@vueuse/metadata@14.4.0':
+ resolution: {integrity: sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==}
+
+ '@vueuse/shared@14.4.0':
+ resolution: {integrity: sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==}
+ peerDependencies:
+ vue: ^3.5.0
+
+ acorn@8.18.0:
+ resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+
argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ aria-hidden@1.2.6:
+ resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==}
+ engines: {node: '>=10'}
+
assertion-error@2.0.1:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
@@ -645,10 +1040,27 @@ packages:
bidi-js@1.0.3:
resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==}
+ buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+
+ camel-case@4.1.2:
+ resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==}
+
chai@6.2.2:
resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==}
engines: {node: '>=18'}
+ clean-css@5.3.3:
+ resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==}
+ engines: {node: '>= 10.0'}
+
+ commander@10.0.1:
+ resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
+ engines: {node: '>=14'}
+
+ commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+
convert-source-map@2.0.0:
resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
@@ -666,10 +1078,16 @@ packages:
decimal.js@10.6.0:
resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==}
+ defu@6.1.7:
+ resolution: {integrity: sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==}
+
detect-libc@2.1.2:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ dot-case@3.0.4:
+ resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==}
+
entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'}
@@ -728,6 +1146,11 @@ packages:
html-escaper@2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
+ html-minifier-terser@7.2.0:
+ resolution: {integrity: sha512-tXgn3QfqPIpGl9o+K5tpcj3/MN4SfLtsx2GWwBC3SSd0tXQGyF3gsSqad8loJgKZGM3ZxbYDd5yhiBIdWpmvLA==}
+ engines: {node: ^14.13.1 || >=16.0.0}
+ hasBin: true
+
is-potential-custom-element-name@1.0.1:
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
@@ -761,30 +1184,60 @@ packages:
cpu: [arm64]
os: [android]
+ lightningcss-android-arm64@1.33.0:
+ resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [android]
+
lightningcss-darwin-arm64@1.32.0:
resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
+ lightningcss-darwin-arm64@1.33.0:
+ resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [darwin]
+
lightningcss-darwin-x64@1.32.0:
resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
+ lightningcss-darwin-x64@1.33.0:
+ resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [darwin]
+
lightningcss-freebsd-x64@1.32.0:
resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
+ lightningcss-freebsd-x64@1.33.0:
+ resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [freebsd]
+
lightningcss-linux-arm-gnueabihf@1.32.0:
resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
+ lightningcss-linux-arm-gnueabihf@1.33.0:
+ resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm]
+ os: [linux]
+
lightningcss-linux-arm64-gnu@1.32.0:
resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==}
engines: {node: '>= 12.0.0'}
@@ -792,6 +1245,13 @@ packages:
os: [linux]
libc: [glibc]
+ lightningcss-linux-arm64-gnu@1.33.0:
+ resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
lightningcss-linux-arm64-musl@1.32.0:
resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==}
engines: {node: '>= 12.0.0'}
@@ -799,6 +1259,13 @@ packages:
os: [linux]
libc: [musl]
+ lightningcss-linux-arm64-musl@1.33.0:
+ resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
lightningcss-linux-x64-gnu@1.32.0:
resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==}
engines: {node: '>= 12.0.0'}
@@ -806,6 +1273,13 @@ packages:
os: [linux]
libc: [glibc]
+ lightningcss-linux-x64-gnu@1.33.0:
+ resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
lightningcss-linux-x64-musl@1.32.0:
resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==}
engines: {node: '>= 12.0.0'}
@@ -813,25 +1287,51 @@ packages:
os: [linux]
libc: [musl]
+ lightningcss-linux-x64-musl@1.33.0:
+ resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
lightningcss-win32-arm64-msvc@1.32.0:
resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
+ lightningcss-win32-arm64-msvc@1.33.0:
+ resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [arm64]
+ os: [win32]
+
lightningcss-win32-x64-msvc@1.32.0:
resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
+ lightningcss-win32-x64-msvc@1.33.0:
+ resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==}
+ engines: {node: '>= 12.0.0'}
+ cpu: [x64]
+ os: [win32]
+
lightningcss@1.32.0:
resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==}
engines: {node: '>= 12.0.0'}
+ lightningcss@1.33.0:
+ resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==}
+ engines: {node: '>= 12.0.0'}
+
linkify-it@5.0.0:
resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
+ linkify-it@5.0.2:
+ resolution: {integrity: sha512-ONTm2jCMAVZjgQa/Fy1kScXsuOoF5NPTsoFBdE1KVIZ2vAh/r9+Bqo+0jINCBYnavTPQZz38QzFTme79ENoN3Q==}
+
linkify-it@6.1.0:
resolution: {integrity: sha512-wJ/TwpSDTLepCrQoYWYIExIKg5Zchex2Nn5yk2mFnB+6PtdkHtyLx742md9csRjjOnGkKIS/RrbY7l8D6gT9Vw==}
@@ -844,6 +1344,9 @@ packages:
lit@3.3.2:
resolution: {integrity: sha512-NF9zbsP79l4ao2SNrH3NkfmFgN/hBYSQo90saIVI1o5GpjAdCPVstVzO1MrLOakHoEhYkrtRjPK6Ob521aoYWQ==}
+ lower-case@2.0.2:
+ resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
+
lru-cache@11.3.5:
resolution: {integrity: sha512-NxVFwLAnrd9i7KUBxC4DrUhmgjzOs+1Qm50D3oF1/oL+r1NpZ4gA7xvG0/zJ8evR7zIKn4vLf7qTNduWFtCrRw==}
engines: {node: 20 || >=22}
@@ -862,6 +1365,10 @@ packages:
resolution: {integrity: sha512-BuU2qnTti9YKgK5N+IeMubp14ZUKUUw7yeJbkjtosvHiP0AZ5c8IAgEMk79D0eC8F23r4Ac/q8cAIFdm2FtyoA==}
hasBin: true
+ markdown-it@14.3.0:
+ resolution: {integrity: sha512-RCEsPjR+sr0x+AuYp601tKTkgFG4YEPLCzHST3cQ/fhlJkqAkz1L2/Qbp1j9qw5SBwQHFBoW8+hoN5xssOF0Tw==}
+ hasBin: true
+
marked@18.0.2:
resolution: {integrity: sha512-NsmlUYBS/Zg57rgDWMYdnre6OTj4e+qq/JS2ot3KrYLSoHLw+sDu0Nm1ZGpRgYAq6c+b1ekaY5NzVchMCQnzcg==}
engines: {node: '>= 20'}
@@ -876,20 +1383,36 @@ packages:
mitata@0.1.14:
resolution: {integrity: sha512-8kRs0l636eT4jj68PFXOR2D5xl4m56T478g16SzUPOYgkzQU+xaw62guAQxzBPm+SXb15GQi1cCpDxJfkr4CSA==}
- nanoid@3.3.11:
- resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==}
+ nanoid@3.3.18:
+ resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
+ no-case@3.0.4:
+ resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==}
+
obug@2.1.1:
resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==}
+ ohash@2.0.12:
+ resolution: {integrity: sha512-65S/5gk9YSsaRjcyf7Nfa6h/d3E8/1gslpXfI4W7Dxn/oap8IKRuNT5VXkLQ1YFKIEg4apRY4Pj6aiwFzrDdmw==}
+
+ param-case@3.0.4:
+ resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==}
+
parse5@8.0.1:
resolution: {integrity: sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==}
+ pascal-case@3.1.2:
+ resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==}
+
pathe@2.0.3:
resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==}
+ photoswipe@5.4.4:
+ resolution: {integrity: sha512-WNFHoKrkZNnvFFhbHL93WDkW3ifwVOXSW3w1UuZZelSmgXpIGiZSNlZJq37rR8YejqME2rHs9EhH9ZvlvFH2NA==}
+ engines: {node: '>= 0.12.0'}
+
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
@@ -897,8 +1420,8 @@ packages:
resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==}
engines: {node: '>=12'}
- postcss@8.5.10:
- resolution: {integrity: sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==}
+ postcss@8.5.26:
+ resolution: {integrity: sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==}
engines: {node: ^10 || ^12 || >=14}
prettier@3.8.3:
@@ -914,6 +1437,15 @@ packages:
resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
engines: {node: '>=6'}
+ reka-ui@2.10.3:
+ resolution: {integrity: sha512-nJGZbwcha8AcP2wbnjodfzsciTKBqp1mIzepC9Pi2xDI/YK3++ej3vpJOSPyxqrkq1Oorj4K+BdJkbVCV6x6ag==}
+ peerDependencies:
+ vue: '>= 3.4.0'
+
+ relateurl@0.2.7:
+ resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==}
+ engines: {node: '>= 0.10'}
+
require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
@@ -921,6 +1453,11 @@ packages:
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ rolldown@1.0.0-rc.10:
+ resolution: {integrity: sha512-q7j6vvarRFmKpgJUT8HCAUljkgzEp4LAhPlJUvQhA5LA1SUL36s5QCysMutErzL3EbNOZOkoziSx9iZC4FddKA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+
rolldown@1.0.0-rc.16:
resolution: {integrity: sha512-rzi5WqKzEZw3SooTt7cgm4eqIoujPIyGcJNGFL7iPEuajQw7vxMHUkXylu4/vhCkJGXsgRmxqMKXUpT6FEgl0g==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -938,13 +1475,17 @@ packages:
siginfo@2.0.0:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
- signal-polyfill@0.2.2:
- resolution: {integrity: sha512-p63Y4Er5/eMQ9RHg0M0Y64NlsQKpiu6MDdhBXpyywRuWiPywhJTpKJ1iB5K2hJEbFZ0BnDS7ZkJ+0AfTuL37Rg==}
-
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
+ source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+
+ source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+
stackback@0.0.2:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
@@ -958,6 +1499,11 @@ packages:
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
+ terser@5.50.0:
+ resolution: {integrity: sha512-CN9BVxWhgS/hRxtUMjtC2uRWSTcSfQFHMDWma6sKKfIivCD91sM+FOPfvwoaRMqCSrUpe1nv3jDamd9eEQ4y+w==}
+ engines: {node: '>=10'}
+ hasBin: true
+
tinybench@2.9.0:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
@@ -1001,6 +1547,11 @@ packages:
engines: {node: '>=14.17'}
hasBin: true
+ typescript@7.0.2:
+ resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==}
+ engines: {node: '>=16.20.0'}
+ hasBin: true
+
uc.micro@2.1.0:
resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
@@ -1010,10 +1561,56 @@ packages:
undici-types@7.19.2:
resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==}
+ undici-types@8.3.0:
+ resolution: {integrity: sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ==}
+
undici@7.25.0:
resolution: {integrity: sha512-xXnp4kTyor2Zq+J1FfPI6Eq3ew5h6Vl0F/8d9XU5zZQf1tX9s2Su1/3PiMmUANFULpmksxkClamIZcaUqryHsQ==}
engines: {node: '>=20.18.1'}
+ vite@8.0.1:
+ resolution: {integrity: sha512-wt+Z2qIhfFt85uiyRt5LPU4oVEJBXj8hZNWKeqFG4gRG/0RaRGJ7njQCwzFVjO+v4+Ipmf5CY7VdmZRAYYBPHw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^20.19.0 || >=22.12.0
+ '@vitejs/devtools': ^0.1.0
+ esbuild: ^0.27.0
+ jiti: '>=1.21.0'
+ less: ^4.0.0
+ sass: ^1.70.0
+ sass-embedded: ^1.70.0
+ stylus: '>=0.54.8'
+ sugarss: ^5.0.0
+ terser: ^5.16.0
+ tsx: ^4.8.1
+ yaml: ^2.4.2
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ '@vitejs/devtools':
+ optional: true
+ esbuild:
+ optional: true
+ jiti:
+ optional: true
+ less:
+ optional: true
+ sass:
+ optional: true
+ sass-embedded:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ tsx:
+ optional: true
+ yaml:
+ optional: true
+
vite@8.0.9:
resolution: {integrity: sha512-t7g7GVRpMXjNpa67HaVWI/8BWtdVIQPCL2WoozXXA7LBGEFK4AkkKkHx2hAQf5x1GZSlcmEDPkVLSGahxnEEZw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -1098,6 +1695,17 @@ packages:
jsdom:
optional: true
+ vue-demi@0.14.10:
+ resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
+ 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.5.32:
resolution: {integrity: sha512-vM4z4Q9tTafVfMAK7IVzmxg34rSzTFMyIe0UUEijUCkn9+23lj0WRfA83dg7eQZIUlgOSGrkViIaCfqSAUXsMw==}
peerDependencies:
@@ -1106,6 +1714,14 @@ packages:
typescript:
optional: true
+ vue@3.5.41:
+ resolution: {integrity: sha512-2laE0p+aK+/AOPG/XL/WepOs/GlK755LJ1XECi9kDUrz1FKNw8rb2Xzlw9JS1rqEV55nb0ttsKxVlTCcd+R5cg==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
w3c-xmlserializer@5.0.0:
resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==}
engines: {node: '>=18'}
@@ -1158,17 +1774,30 @@ snapshots:
'@babel/helper-string-parser@7.27.1': {}
+ '@babel/helper-string-parser@7.29.7': {}
+
'@babel/helper-validator-identifier@7.28.5': {}
+ '@babel/helper-validator-identifier@7.29.7': {}
+
'@babel/parser@7.29.2':
dependencies:
'@babel/types': 7.29.0
+ '@babel/parser@7.29.8':
+ dependencies:
+ '@babel/types': 7.29.8
+
'@babel/types@7.29.0':
dependencies:
'@babel/helper-string-parser': 7.27.1
'@babel/helper-validator-identifier': 7.28.5
+ '@babel/types@7.29.8':
+ dependencies:
+ '@babel/helper-string-parser': 7.29.7
+ '@babel/helper-validator-identifier': 7.29.7
+
'@bcoe/v8-coverage@1.0.2':
optional: true
@@ -1296,27 +1925,117 @@ snapshots:
'@exodus/bytes@1.15.0': {}
- '@fuyeor/locale@https://codeload.github.com/Fuyeor/webroamer/tar.gz/c502f739f4b633ab24386fe9f90fb77ed9f6ca9d#path:packages/locale(@lit-labs/signals@0.2.0)(lit@3.3.2)(signal-polyfill@0.2.2)':
+ '@floating-ui/core@1.8.0':
dependencies:
- '@lit-labs/signals': 0.2.0
- lit: 3.3.2
- signal-polyfill: 0.2.2
+ '@floating-ui/utils': 0.2.12
- '@jridgewell/resolve-uri@3.1.2':
+ '@floating-ui/dom@1.8.0':
+ dependencies:
+ '@floating-ui/core': 1.8.0
+ '@floating-ui/utils': 0.2.12
+
+ '@floating-ui/utils@0.2.12': {}
+
+ '@floating-ui/vue@1.1.11(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@floating-ui/dom': 1.8.0
+ '@floating-ui/utils': 0.2.12
+ vue-demi: 0.14.10(vue@3.5.41(typescript@7.0.2))
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+ - vue
+
+ '@fuyeor/commons@0.1.0(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@fuyeor/locale': 0.1.0(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/vue-router': 0.1.0(vue@3.5.41(typescript@7.0.2))
+ vue: 3.5.41(typescript@7.0.2)
+
+ '@fuyeor/commons@0.1.2(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@fuyeor/locale': 0.1.0(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/vue-router': 0.0.9(vue@3.5.41(typescript@7.0.2))
+ vue: 3.5.41(typescript@7.0.2)
+
+ '@fuyeor/config@0.1.1(vite@8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@vitejs/plugin-vue': 6.0.8(vite@8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))(vue@3.5.41(typescript@7.0.2))
+ html-minifier-terser: 7.2.0
+ lightningcss: 1.33.0
+ vite: 8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0)
+ transitivePeerDependencies:
+ - vue
+
+ '@fuyeor/interactify@0.1.1(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@fuyeor/commons': 0.1.0(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/locale': 0.1.0(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/vue-router': 0.0.9(vue@3.5.41(typescript@7.0.2))
+ '@fuyeor/vue-vaul': 0.4.8(vue@3.5.41(typescript@7.0.2))
+ markdown-it: 14.3.0
+ photoswipe: 5.4.4
+ vue: 3.5.41(typescript@7.0.2)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+
+ '@fuyeor/locale-cli-linux-x64@0.1.1':
+ optional: true
+
+ '@fuyeor/locale-cli-win32-x64@0.1.1':
optional: true
+ '@fuyeor/locale-cli@0.1.1':
+ optionalDependencies:
+ '@fuyeor/locale-cli-linux-x64': 0.1.1
+ '@fuyeor/locale-cli-win32-x64': 0.1.1
+
+ '@fuyeor/locale@0.1.0(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ vue: 3.5.41(typescript@7.0.2)
+
+ '@fuyeor/tsconfig@0.1.0': {}
+
+ '@fuyeor/vue-router@0.0.9(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ vue: 3.5.41(typescript@7.0.2)
+
+ '@fuyeor/vue-router@0.1.0(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ vue: 3.5.41(typescript@7.0.2)
+
+ '@fuyeor/vue-vaul@0.4.8(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ reka-ui: 2.10.3(vue@3.5.41(typescript@7.0.2))
+ vue: 3.5.41(typescript@7.0.2)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+
+ '@internationalized/date@3.12.3':
+ dependencies:
+ '@swc/helpers': 0.5.23
+
+ '@internationalized/number@3.6.7':
+ dependencies:
+ '@swc/helpers': 0.5.23
+
+ '@jridgewell/gen-mapping@0.3.13':
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.5.5
+ '@jridgewell/trace-mapping': 0.3.31
+
+ '@jridgewell/resolve-uri@3.1.2': {}
+
+ '@jridgewell/source-map@0.3.11':
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.13
+ '@jridgewell/trace-mapping': 0.3.31
+
'@jridgewell/sourcemap-codec@1.5.5': {}
'@jridgewell/trace-mapping@0.3.31':
dependencies:
'@jridgewell/resolve-uri': 3.1.2
'@jridgewell/sourcemap-codec': 1.5.5
- optional: true
-
- '@lit-labs/signals@0.2.0':
- dependencies:
- lit: 3.3.2
- signal-polyfill: 0.2.2
'@lit-labs/ssr-dom-shim@1.5.1': {}
@@ -1331,44 +2050,90 @@ snapshots:
'@tybys/wasm-util': 0.10.1
optional: true
+ '@oxc-project/types@0.120.0': {}
+
'@oxc-project/types@0.126.0': {}
+ '@rolldown/binding-android-arm64@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-android-arm64@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-darwin-arm64@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-darwin-arm64@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-darwin-x64@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-darwin-x64@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-freebsd-x64@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-freebsd-x64@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-arm-gnueabihf@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-arm64-gnu@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-arm64-gnu@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-arm64-musl@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-arm64-musl@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-s390x-gnu@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-x64-gnu@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-x64-gnu@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-linux-x64-musl@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-linux-x64-musl@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-openharmony-arm64@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-openharmony-arm64@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-wasm32-wasi@1.0.0-rc.10(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
+ dependencies:
+ '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+ optional: true
+
'@rolldown/binding-wasm32-wasi@1.0.0-rc.16':
dependencies:
'@emnapi/core': 1.9.2
@@ -1376,16 +2141,37 @@ snapshots:
'@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
optional: true
+ '@rolldown/binding-win32-arm64-msvc@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-win32-arm64-msvc@1.0.0-rc.16':
optional: true
+ '@rolldown/binding-win32-x64-msvc@1.0.0-rc.10':
+ optional: true
+
'@rolldown/binding-win32-x64-msvc@1.0.0-rc.16':
optional: true
+ '@rolldown/pluginutils@1.0.0-rc.10': {}
+
'@rolldown/pluginutils@1.0.0-rc.16': {}
+ '@rolldown/pluginutils@1.0.1': {}
+
'@standard-schema/spec@1.1.0': {}
+ '@swc/helpers@0.5.23':
+ dependencies:
+ tslib: 2.8.1
+
+ '@tanstack/virtual-core@3.17.8': {}
+
+ '@tanstack/vue-virtual@3.13.36(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@tanstack/virtual-core': 3.17.8
+ vue: 3.5.41(typescript@7.0.2)
+
'@tybys/wasm-util@0.10.1':
dependencies:
tslib: 2.8.1
@@ -1404,9 +2190,79 @@ snapshots:
dependencies:
undici-types: 7.19.2
+ '@types/node@26.2.0':
+ dependencies:
+ undici-types: 8.3.0
+
'@types/trusted-types@2.0.7': {}
- '@types/vscode@1.134.0': {}
+ '@types/web-bluetooth@0.0.21': {}
+
+ '@typescript/typescript-aix-ppc64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-darwin-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-darwin-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-freebsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-freebsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-arm@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-loong64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-mips64el@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-ppc64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-riscv64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-s390x@7.0.2':
+ optional: true
+
+ '@typescript/typescript-linux-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-netbsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-netbsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-openbsd-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-openbsd-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-sunos-x64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-win32-arm64@7.0.2':
+ optional: true
+
+ '@typescript/typescript-win32-x64@7.0.2':
+ optional: true
+
+ '@vitejs/plugin-vue@6.0.8(vite@8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@rolldown/pluginutils': 1.0.1
+ vite: 8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0)
+ vue: 3.5.41(typescript@7.0.2)
'@vitest/coverage-v8@4.1.4(vitest@4.1.4)':
dependencies:
@@ -1420,7 +2276,7 @@ snapshots:
obug: 2.1.1
std-env: 4.1.0
tinyrainbow: 3.1.0
- vitest: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ vitest: 4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))
optional: true
'@vitest/expect@4.1.4':
@@ -1432,13 +2288,13 @@ snapshots:
chai: 6.2.2
tinyrainbow: 3.1.0
- '@vitest/mocker@4.1.4(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))':
+ '@vitest/mocker@4.1.4(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))':
dependencies:
'@vitest/spy': 4.1.4
estree-walker: 3.0.3
magic-string: 0.30.21
optionalDependencies:
- vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)
+ vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0)
'@vitest/pretty-format@4.1.4':
dependencies:
@@ -1472,11 +2328,24 @@ snapshots:
estree-walker: 2.0.2
source-map-js: 1.2.1
+ '@vue/compiler-core@3.5.41':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@vue/shared': 3.5.41
+ entities: 7.0.1
+ estree-walker: 2.0.2
+ source-map-js: 1.2.1
+
'@vue/compiler-dom@3.5.32':
dependencies:
'@vue/compiler-core': 3.5.32
'@vue/shared': 3.5.32
+ '@vue/compiler-dom@3.5.41':
+ dependencies:
+ '@vue/compiler-core': 3.5.41
+ '@vue/shared': 3.5.41
+
'@vue/compiler-sfc@3.5.32':
dependencies:
'@babel/parser': 7.29.2
@@ -1486,7 +2355,19 @@ snapshots:
'@vue/shared': 3.5.32
estree-walker: 2.0.2
magic-string: 0.30.21
- postcss: 8.5.10
+ postcss: 8.5.26
+ source-map-js: 1.2.1
+
+ '@vue/compiler-sfc@3.5.41':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@vue/compiler-core': 3.5.41
+ '@vue/compiler-dom': 3.5.41
+ '@vue/compiler-ssr': 3.5.41
+ '@vue/shared': 3.5.41
+ estree-walker: 2.0.2
+ magic-string: 0.30.21
+ postcss: 8.5.26
source-map-js: 1.2.1
'@vue/compiler-ssr@3.5.32':
@@ -1494,15 +2375,29 @@ snapshots:
'@vue/compiler-dom': 3.5.32
'@vue/shared': 3.5.32
+ '@vue/compiler-ssr@3.5.41':
+ dependencies:
+ '@vue/compiler-dom': 3.5.41
+ '@vue/shared': 3.5.41
+
'@vue/reactivity@3.5.32':
dependencies:
'@vue/shared': 3.5.32
+ '@vue/reactivity@3.5.41':
+ dependencies:
+ '@vue/shared': 3.5.41
+
'@vue/runtime-core@3.5.32':
dependencies:
'@vue/reactivity': 3.5.32
'@vue/shared': 3.5.32
+ '@vue/runtime-core@3.5.41':
+ dependencies:
+ '@vue/reactivity': 3.5.41
+ '@vue/shared': 3.5.41
+
'@vue/runtime-dom@3.5.32':
dependencies:
'@vue/reactivity': 3.5.32
@@ -1510,16 +2405,50 @@ snapshots:
'@vue/shared': 3.5.32
csstype: 3.2.3
+ '@vue/runtime-dom@3.5.41':
+ dependencies:
+ '@vue/reactivity': 3.5.41
+ '@vue/runtime-core': 3.5.41
+ '@vue/shared': 3.5.41
+ csstype: 3.2.3
+
'@vue/server-renderer@3.5.32(vue@3.5.32(typescript@6.0.3))':
dependencies:
'@vue/compiler-ssr': 3.5.32
'@vue/shared': 3.5.32
vue: 3.5.32(typescript@6.0.3)
+ '@vue/server-renderer@3.5.41':
+ dependencies:
+ '@vue/compiler-ssr': 3.5.41
+ '@vue/runtime-dom': 3.5.41
+ '@vue/shared': 3.5.41
+
'@vue/shared@3.5.32': {}
+ '@vue/shared@3.5.41': {}
+
+ '@vueuse/core@14.4.0(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ '@types/web-bluetooth': 0.0.21
+ '@vueuse/metadata': 14.4.0
+ '@vueuse/shared': 14.4.0(vue@3.5.41(typescript@7.0.2))
+ vue: 3.5.41(typescript@7.0.2)
+
+ '@vueuse/metadata@14.4.0': {}
+
+ '@vueuse/shared@14.4.0(vue@3.5.41(typescript@7.0.2))':
+ dependencies:
+ vue: 3.5.41(typescript@7.0.2)
+
+ acorn@8.18.0: {}
+
argparse@2.0.1: {}
+ aria-hidden@1.2.6:
+ dependencies:
+ tslib: 2.8.1
+
assertion-error@2.0.1: {}
ast-v8-to-istanbul@1.0.0:
@@ -1533,8 +2462,23 @@ snapshots:
dependencies:
require-from-string: 2.0.2
+ buffer-from@1.1.2: {}
+
+ camel-case@4.1.2:
+ dependencies:
+ pascal-case: 3.1.2
+ tslib: 2.8.1
+
chai@6.2.2: {}
+ clean-css@5.3.3:
+ dependencies:
+ source-map: 0.6.1
+
+ commander@10.0.1: {}
+
+ commander@2.20.3: {}
+
convert-source-map@2.0.0: {}
css-tree@3.2.1:
@@ -1553,8 +2497,15 @@ snapshots:
decimal.js@10.6.0: {}
+ defu@6.1.7: {}
+
detect-libc@2.1.2: {}
+ dot-case@3.0.4:
+ dependencies:
+ no-case: 3.0.4
+ tslib: 2.8.1
+
entities@4.5.0: {}
entities@7.0.1: {}
@@ -1623,6 +2574,16 @@ snapshots:
html-escaper@2.0.2:
optional: true
+ html-minifier-terser@7.2.0:
+ dependencies:
+ camel-case: 4.1.2
+ clean-css: 5.3.3
+ commander: 10.0.1
+ entities: 4.5.0
+ param-case: 3.0.4
+ relateurl: 0.2.7
+ terser: 5.50.0
+
is-potential-custom-element-name@1.0.1: {}
istanbul-lib-coverage@3.2.2:
@@ -1673,36 +2634,69 @@ snapshots:
lightningcss-android-arm64@1.32.0:
optional: true
+ lightningcss-android-arm64@1.33.0:
+ optional: true
+
lightningcss-darwin-arm64@1.32.0:
optional: true
+ lightningcss-darwin-arm64@1.33.0:
+ optional: true
+
lightningcss-darwin-x64@1.32.0:
optional: true
+ lightningcss-darwin-x64@1.33.0:
+ optional: true
+
lightningcss-freebsd-x64@1.32.0:
optional: true
+ lightningcss-freebsd-x64@1.33.0:
+ optional: true
+
lightningcss-linux-arm-gnueabihf@1.32.0:
optional: true
+ lightningcss-linux-arm-gnueabihf@1.33.0:
+ optional: true
+
lightningcss-linux-arm64-gnu@1.32.0:
optional: true
+ lightningcss-linux-arm64-gnu@1.33.0:
+ optional: true
+
lightningcss-linux-arm64-musl@1.32.0:
optional: true
+ lightningcss-linux-arm64-musl@1.33.0:
+ optional: true
+
lightningcss-linux-x64-gnu@1.32.0:
optional: true
+ lightningcss-linux-x64-gnu@1.33.0:
+ optional: true
+
lightningcss-linux-x64-musl@1.32.0:
optional: true
+ lightningcss-linux-x64-musl@1.33.0:
+ optional: true
+
lightningcss-win32-arm64-msvc@1.32.0:
optional: true
+ lightningcss-win32-arm64-msvc@1.33.0:
+ optional: true
+
lightningcss-win32-x64-msvc@1.32.0:
optional: true
+ lightningcss-win32-x64-msvc@1.33.0:
+ optional: true
+
lightningcss@1.32.0:
dependencies:
detect-libc: 2.1.2
@@ -1719,10 +2713,30 @@ snapshots:
lightningcss-win32-arm64-msvc: 1.32.0
lightningcss-win32-x64-msvc: 1.32.0
+ lightningcss@1.33.0:
+ dependencies:
+ detect-libc: 2.1.2
+ optionalDependencies:
+ lightningcss-android-arm64: 1.33.0
+ lightningcss-darwin-arm64: 1.33.0
+ lightningcss-darwin-x64: 1.33.0
+ lightningcss-freebsd-x64: 1.33.0
+ lightningcss-linux-arm-gnueabihf: 1.33.0
+ lightningcss-linux-arm64-gnu: 1.33.0
+ lightningcss-linux-arm64-musl: 1.33.0
+ lightningcss-linux-x64-gnu: 1.33.0
+ lightningcss-linux-x64-musl: 1.33.0
+ lightningcss-win32-arm64-msvc: 1.33.0
+ lightningcss-win32-x64-msvc: 1.33.0
+
linkify-it@5.0.0:
dependencies:
uc.micro: 2.1.0
+ linkify-it@5.0.2:
+ dependencies:
+ uc.micro: 2.1.0
+
linkify-it@6.1.0:
dependencies:
uc.micro: 3.0.0
@@ -1743,6 +2757,10 @@ snapshots:
lit-element: 4.2.2
lit-html: 3.3.2
+ lower-case@2.0.2:
+ dependencies:
+ tslib: 2.8.1
+
lru-cache@11.3.5: {}
magic-string@0.30.21:
@@ -1751,8 +2769,8 @@ snapshots:
magicast@0.5.2:
dependencies:
- '@babel/parser': 7.29.2
- '@babel/types': 7.29.0
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
source-map-js: 1.2.1
optional: true
@@ -1770,6 +2788,15 @@ snapshots:
punycode.js: 2.3.1
uc.micro: 2.1.0
+ markdown-it@14.3.0:
+ dependencies:
+ argparse: 2.0.1
+ entities: 4.5.0
+ linkify-it: 5.0.2
+ mdurl: 2.0.0
+ punycode.js: 2.3.1
+ uc.micro: 2.1.0
+
marked@18.0.2: {}
mdn-data@2.27.1: {}
@@ -1778,23 +2805,42 @@ snapshots:
mitata@0.1.14: {}
- nanoid@3.3.11: {}
+ nanoid@3.3.18: {}
+
+ no-case@3.0.4:
+ dependencies:
+ lower-case: 2.0.2
+ tslib: 2.8.1
obug@2.1.1: {}
+ ohash@2.0.12: {}
+
+ param-case@3.0.4:
+ dependencies:
+ dot-case: 3.0.4
+ tslib: 2.8.1
+
parse5@8.0.1:
dependencies:
entities: 8.0.0
+ pascal-case@3.1.2:
+ dependencies:
+ no-case: 3.0.4
+ tslib: 2.8.1
+
pathe@2.0.3: {}
+ photoswipe@5.4.4: {}
+
picocolors@1.1.1: {}
picomatch@4.0.4: {}
- postcss@8.5.10:
+ postcss@8.5.26:
dependencies:
- nanoid: 3.3.11
+ nanoid: 3.3.18
picocolors: 1.1.1
source-map-js: 1.2.1
@@ -1804,10 +2850,52 @@ snapshots:
punycode@2.3.1: {}
+ reka-ui@2.10.3(vue@3.5.41(typescript@7.0.2)):
+ dependencies:
+ '@floating-ui/dom': 1.8.0
+ '@floating-ui/vue': 1.1.11(vue@3.5.41(typescript@7.0.2))
+ '@internationalized/date': 3.12.3
+ '@internationalized/number': 3.6.7
+ '@tanstack/vue-virtual': 3.13.36(vue@3.5.41(typescript@7.0.2))
+ '@vueuse/core': 14.4.0(vue@3.5.41(typescript@7.0.2))
+ '@vueuse/shared': 14.4.0(vue@3.5.41(typescript@7.0.2))
+ aria-hidden: 1.2.6
+ defu: 6.1.7
+ ohash: 2.0.12
+ vue: 3.5.41(typescript@7.0.2)
+ transitivePeerDependencies:
+ - '@vue/composition-api'
+
+ relateurl@0.2.7: {}
+
require-from-string@2.0.2: {}
resolve-pkg-maps@1.0.0: {}
+ rolldown@1.0.0-rc.10(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2):
+ dependencies:
+ '@oxc-project/types': 0.120.0
+ '@rolldown/pluginutils': 1.0.0-rc.10
+ optionalDependencies:
+ '@rolldown/binding-android-arm64': 1.0.0-rc.10
+ '@rolldown/binding-darwin-arm64': 1.0.0-rc.10
+ '@rolldown/binding-darwin-x64': 1.0.0-rc.10
+ '@rolldown/binding-freebsd-x64': 1.0.0-rc.10
+ '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-rc.10
+ '@rolldown/binding-linux-arm64-gnu': 1.0.0-rc.10
+ '@rolldown/binding-linux-arm64-musl': 1.0.0-rc.10
+ '@rolldown/binding-linux-ppc64-gnu': 1.0.0-rc.10
+ '@rolldown/binding-linux-s390x-gnu': 1.0.0-rc.10
+ '@rolldown/binding-linux-x64-gnu': 1.0.0-rc.10
+ '@rolldown/binding-linux-x64-musl': 1.0.0-rc.10
+ '@rolldown/binding-openharmony-arm64': 1.0.0-rc.10
+ '@rolldown/binding-wasm32-wasi': 1.0.0-rc.10(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
+ '@rolldown/binding-win32-arm64-msvc': 1.0.0-rc.10
+ '@rolldown/binding-win32-x64-msvc': 1.0.0-rc.10
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+
rolldown@1.0.0-rc.16:
dependencies:
'@oxc-project/types': 0.126.0
@@ -1838,10 +2926,15 @@ snapshots:
siginfo@2.0.0: {}
- signal-polyfill@0.2.2: {}
-
source-map-js@1.2.1: {}
+ source-map-support@0.5.21:
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+
+ source-map@0.6.1: {}
+
stackback@0.0.2: {}
std-env@4.1.0: {}
@@ -1853,6 +2946,13 @@ snapshots:
symbol-tree@3.2.4: {}
+ terser@5.50.0:
+ dependencies:
+ '@jridgewell/source-map': 0.3.11
+ acorn: 8.18.0
+ commander: 2.20.3
+ source-map-support: 0.5.21
+
tinybench@2.9.0: {}
tinyexec@1.1.1: {}
@@ -1878,8 +2978,7 @@ snapshots:
dependencies:
punycode: 2.3.1
- tslib@2.8.1:
- optional: true
+ tslib@2.8.1: {}
tsx@4.21.0:
dependencies:
@@ -1890,31 +2989,74 @@ snapshots:
typescript@6.0.3: {}
+ typescript@7.0.2:
+ optionalDependencies:
+ '@typescript/typescript-aix-ppc64': 7.0.2
+ '@typescript/typescript-darwin-arm64': 7.0.2
+ '@typescript/typescript-darwin-x64': 7.0.2
+ '@typescript/typescript-freebsd-arm64': 7.0.2
+ '@typescript/typescript-freebsd-x64': 7.0.2
+ '@typescript/typescript-linux-arm': 7.0.2
+ '@typescript/typescript-linux-arm64': 7.0.2
+ '@typescript/typescript-linux-loong64': 7.0.2
+ '@typescript/typescript-linux-mips64el': 7.0.2
+ '@typescript/typescript-linux-ppc64': 7.0.2
+ '@typescript/typescript-linux-riscv64': 7.0.2
+ '@typescript/typescript-linux-s390x': 7.0.2
+ '@typescript/typescript-linux-x64': 7.0.2
+ '@typescript/typescript-netbsd-arm64': 7.0.2
+ '@typescript/typescript-netbsd-x64': 7.0.2
+ '@typescript/typescript-openbsd-arm64': 7.0.2
+ '@typescript/typescript-openbsd-x64': 7.0.2
+ '@typescript/typescript-sunos-x64': 7.0.2
+ '@typescript/typescript-win32-arm64': 7.0.2
+ '@typescript/typescript-win32-x64': 7.0.2
+
uc.micro@2.1.0: {}
uc.micro@3.0.0: {}
undici-types@7.19.2: {}
+ undici-types@8.3.0: {}
+
undici@7.25.0: {}
- vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0):
+ vite@8.0.1(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)(@types/node@26.2.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0):
dependencies:
lightningcss: 1.32.0
picomatch: 4.0.4
- postcss: 8.5.10
+ postcss: 8.5.26
+ rolldown: 1.0.0-rc.10(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
+ tinyglobby: 0.2.16
+ optionalDependencies:
+ '@types/node': 26.2.0
+ esbuild: 0.27.7
+ fsevents: 2.3.3
+ terser: 5.50.0
+ tsx: 4.21.0
+ transitivePeerDependencies:
+ - '@emnapi/core'
+ - '@emnapi/runtime'
+
+ vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0):
+ dependencies:
+ lightningcss: 1.33.0
+ picomatch: 4.0.4
+ postcss: 8.5.26
rolldown: 1.0.0-rc.16
tinyglobby: 0.2.16
optionalDependencies:
'@types/node': 25.6.0
esbuild: 0.27.7
fsevents: 2.3.3
+ terser: 5.50.0
tsx: 4.21.0
- vitest@4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)):
+ vitest@4.1.4(@types/node@25.6.0)(@vitest/coverage-v8@4.1.4)(jsdom@29.0.2)(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0)):
dependencies:
'@vitest/expect': 4.1.4
- '@vitest/mocker': 4.1.4(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0))
+ '@vitest/mocker': 4.1.4(vite@8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0))
'@vitest/pretty-format': 4.1.4
'@vitest/runner': 4.1.4
'@vitest/snapshot': 4.1.4
@@ -1931,7 +3073,7 @@ snapshots:
tinyexec: 1.1.1
tinyglobby: 0.2.16
tinyrainbow: 3.1.0
- vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(tsx@4.21.0)
+ vite: 8.0.9(@types/node@25.6.0)(esbuild@0.27.7)(terser@5.50.0)(tsx@4.21.0)
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 25.6.0
@@ -1940,6 +3082,10 @@ snapshots:
transitivePeerDependencies:
- msw
+ vue-demi@0.14.10(vue@3.5.41(typescript@7.0.2)):
+ dependencies:
+ vue: 3.5.41(typescript@7.0.2)
+
vue@3.5.32(typescript@6.0.3):
dependencies:
'@vue/compiler-dom': 3.5.32
@@ -1950,6 +3096,16 @@ snapshots:
optionalDependencies:
typescript: 6.0.3
+ vue@3.5.41(typescript@7.0.2):
+ dependencies:
+ '@vue/compiler-dom': 3.5.41
+ '@vue/compiler-sfc': 3.5.41
+ '@vue/runtime-dom': 3.5.41
+ '@vue/server-renderer': 3.5.41
+ '@vue/shared': 3.5.41
+ optionalDependencies:
+ typescript: 7.0.2
+
w3c-xmlserializer@5.0.0:
dependencies:
xml-name-validator: 5.0.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index 72b69d9..ea631ff 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,3 +1,5 @@
# /pnpm-workspace.yaml
packages:
- 'packages/*'
+allowBuilds:
+ vue-demi: true