├── .gitignore ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── client ├── index.ts └── tsconfig.json ├── index.ts ├── package.json ├── pnpm-lock.yaml ├── tooling ├── index.ts └── tsconfig.json └── tsconfig.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.d.ts 3 | *.js 4 | *.tsbuildinfo 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "typescript.format.semicolons": "insert", 3 | "editor.insertSpaces": false, 4 | "editor.detectIndentation": false, 5 | "typescript.tsdk": "node_modules/typescript/lib" 6 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022-present Johnson Chu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vite-plugin-vue-component-preview 2 | 3 | This Vite plugin support `` custom block in SFC for preview single Vue component. 4 | 5 | To use this with VSCode + Volar, see https://github.com/johnsoncodehk/volar/discussions/1511 6 | 7 | ## Setup 8 | 9 | `vite.config.ts` 10 | 11 | ```ts 12 | import { defineConfig } from 'vite'; 13 | import vue from '@vitejs/plugin-vue'; 14 | import preview from 'vite-plugin-vue-component-preview'; 15 | 16 | export default defineConfig({ 17 | plugins: [ 18 | preview(), 19 | vue(), 20 | ], 21 | }) 22 | ``` 23 | 24 | `main.ts` 25 | 26 | ```ts 27 | import { createApp } from 'vue'; 28 | import App from './App.vue'; 29 | import Preview from 'vite-plugin-vue-component-preview/client'; 30 | 31 | const app = createApp(App); 32 | app.use(Preview); 33 | ``` 34 | 35 | `tsconfig.json` (For IDE and vue-tsc support) 36 | 37 | ```json 38 | { 39 | "vueCompilerOptions": { 40 | "plugins": ["vite-plugin-vue-component-preview/tooling"] 41 | } 42 | } 43 | ``` 44 | 45 | ## Example 46 | 47 | ```html 48 | 49 | 53 | 54 | 61 | 62 | 63 | 64 | 65 | 66 | # This is preview page of HelloWorld.vue 67 | 68 | ## Props 69 | 70 | | Props | Description | 71 | | ----------- | -------------- | 72 | | msg | Title message | 73 | 74 | ## Examples 75 | 76 | 82 | 83 | 86 | 87 | 92 | 93 | 94 | ``` 95 | 96 | Example repo: https://github.com/johnsoncodehk/volar-starter (Open http://localhost:3000/__preview/src/components/HelloWorld.vue to see the result.) 97 | 98 | ### Self-import 99 | 100 | When you want to preview the component including ``, importing the component itself provides the solution as follows: 101 | 102 | ```html 103 | 108 | 109 | 110 | 111 | 115 | 116 | 121 | 122 | 123 | ``` 124 | 125 | This method relates to [#17](https://github.com/johnsoncodehk/vite-plugin-vue-component-preview/issues/17). 126 | 127 | ## Sponsors 128 | 129 |

130 | 131 | 132 | 133 |

134 | 135 | ## Credits 136 | 137 | - Markdown parser power by https://github.com/antfu/vite-plugin-vue-markdown 138 | -------------------------------------------------------------------------------- /client/index.ts: -------------------------------------------------------------------------------- 1 | import { App, defineAsyncComponent, DefineComponent, h } from 'vue'; 2 | 3 | export default function (app: App) { 4 | 5 | const location = globalThis.location; 6 | 7 | if (location && location.pathname.includes('/__preview/')) { 8 | 9 | const importPath = location.pathname.replace('/__preview', ''); 10 | const Component = defineAsyncComponent(() => import(/* @vite-ignore */importPath)); 11 | const Layout = defineAsyncComponent(() => import(/* @vite-ignore */importPath + '__preview.vue')); 12 | 13 | if (import.meta.hot) { 14 | fireHash(); 15 | window.addEventListener('hashchange', fireHash); 16 | } 17 | 18 | (app._component as DefineComponent).setup = () => { 19 | return () => h(Layout, undefined, { 20 | default: (props: any) => h(Component, props) 21 | }); 22 | }; 23 | 24 | function fireHash() { 25 | try { 26 | import.meta.hot?.send('vue-component-preview:hash', { 27 | file: importPath, 28 | text: location.hash ? atob(location.hash.substring(1)) : '', 29 | }); 30 | } catch { } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "ESNext", 5 | }, 6 | "include": [ 7 | "./index.ts" 8 | ], 9 | } -------------------------------------------------------------------------------- /index.ts: -------------------------------------------------------------------------------- 1 | import * as fs from 'fs'; 2 | import MagicString from 'magic-string'; 3 | import * as path from 'path'; 4 | import type { Plugin, ViteDevServer } from 'vite'; 5 | import Markdown from 'vite-plugin-vue-markdown'; 6 | 7 | export default function vuePreviewPlugin(): Plugin { 8 | 9 | const markdown = Markdown(); 10 | const previewBlockReg = /\<(preview)[\s\S]*?\>([\s\S]*?)\<\/\1\>/g; 11 | const fileHash: Record = {}; 12 | 13 | let server: ViteDevServer; 14 | let currentProxyHotUpdateFile: string | undefined; 15 | 16 | return { 17 | name: 'vite-plugin-vue-component-preview', 18 | configureServer(_server) { 19 | server = _server; 20 | server.middlewares.use((req, res, next) => { 21 | if (req.url?.startsWith(server.config.base + '__preview/')) { 22 | req.url = server.config.base; // avoid 404 23 | } 24 | next(); 25 | }); 26 | server.ws.on('vue-component-preview:hash', (data: { file: string, text: string; }) => { 27 | data.file = path.join(server.config.root, data.file); 28 | if ((fileHash[data.file] ?? '') !== data.text) { 29 | fileHash[data.file] = data.text; 30 | server.watcher.emit('change', data.file); 31 | } 32 | }); 33 | }, 34 | resolveId(id) { 35 | if (id.startsWith('/__skip_vite/')) { 36 | // handle for nuxt 37 | id = path.join(server.config.root, id.substring('/__skip_vite/'.length)); 38 | } 39 | const cleanId = id.replace(/\?.*$/, ''); 40 | if ( 41 | cleanId.endsWith('__preview.vue') && 42 | !cleanId.startsWith(server.config.root) 43 | ) { 44 | id = path.join(server.config.root, id); 45 | return id; 46 | } 47 | }, 48 | load(id) { 49 | if (id.endsWith('__preview.vue')) { 50 | const fileName = id.substring(0, id.length - '__preview.vue'.length); 51 | if (fileHash[fileName]) { 52 | return parsePreviewCode(fileHash[fileName]); 53 | } 54 | if (fs.existsSync(fileName)) { 55 | return parsePreviewCode(fs.readFileSync(fileName, 'utf-8')); 56 | } 57 | else { 58 | console.warn(`[vite-plugin-vue-component-preview] ${fileName} not found`); 59 | } 60 | } 61 | }, 62 | transform(code, id) { 63 | let str = new MagicString(code); 64 | if (id.endsWith('.vue')) { 65 | // remove preview block 66 | if (fileHash[id] && fileHash[id] !== str.toString()) { 67 | str = str.overwrite(0, str.length(), fileHash[id].replace(previewBlockReg, '')); 68 | } 69 | else { 70 | str = str.replaceAll(previewBlockReg, ''); 71 | } 72 | } 73 | return { 74 | code: str.toString(), 75 | map: str.generateMap(), 76 | }; 77 | }, 78 | handleHotUpdate(ctx) { 79 | if (currentProxyHotUpdateFile === undefined && ctx.file.endsWith('.vue')) { 80 | setTimeout(() => { 81 | currentProxyHotUpdateFile = ctx.file; 82 | ctx.server.watcher.emit('change', ctx.file); 83 | }, 100); 84 | } 85 | else if (currentProxyHotUpdateFile === ctx.file) { 86 | currentProxyHotUpdateFile = undefined; 87 | const originalFile = ctx.file; 88 | ctx.file = ctx.file + '__preview.vue'; 89 | ctx.modules = [...ctx.server.moduleGraph.getModulesByFile(ctx.file) ?? []]; 90 | const read = ctx.read; 91 | ctx.read = async () => parsePreviewCode(fileHash[originalFile] || await read()); 92 | } 93 | }, 94 | }; 95 | 96 | async function parsePreviewCode(code: string) { 97 | // extract preview block content 98 | code = code.replace(//g, ''); 99 | const previewBlock = code.match(previewBlockReg); 100 | if (previewBlock) { 101 | const startTagEnd = previewBlock[0].indexOf('>') + 1; 102 | const endTagStart = previewBlock[0].lastIndexOf(''; 114 | } 115 | } 116 | else { 117 | code = ''; 118 | } 119 | return code; 120 | } 121 | }; 122 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-plugin-vue-component-preview", 3 | "version": "1.1.7", 4 | "license": "MIT", 5 | "files": [ 6 | "**/*.js", 7 | "**/*.d.ts" 8 | ], 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/johnsoncodehk/vite-plugin-vue-component-preview.git" 12 | }, 13 | "scripts": { 14 | "prepublishOnly": "tsc -b" 15 | }, 16 | "devDependencies": { 17 | "@types/node": "latest", 18 | "typescript": "latest", 19 | "vite": "latest", 20 | "vue": "latest" 21 | }, 22 | "dependencies": { 23 | "@volar/vue-language-core": "^1.0.24", 24 | "magic-string": "^0.27.0", 25 | "vite-plugin-vue-markdown": "^0.22.4" 26 | }, 27 | "peerDependencies": { 28 | "vue": ">=3.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | settings: 4 | autoInstallPeers: true 5 | excludeLinksFromLockfile: false 6 | 7 | dependencies: 8 | '@volar/vue-language-core': 9 | specifier: ^1.0.24 10 | version: 1.0.24 11 | magic-string: 12 | specifier: ^0.27.0 13 | version: 0.27.0 14 | vite-plugin-vue-markdown: 15 | specifier: ^0.22.4 16 | version: 0.22.4(vite@5.3.2) 17 | 18 | devDependencies: 19 | '@types/node': 20 | specifier: latest 21 | version: 20.14.9 22 | typescript: 23 | specifier: latest 24 | version: 5.5.2 25 | vite: 26 | specifier: latest 27 | version: 5.3.2(@types/node@20.14.9) 28 | vue: 29 | specifier: latest 30 | version: 3.4.31(typescript@5.5.2) 31 | 32 | packages: 33 | 34 | /@antfu/utils@0.7.2: 35 | resolution: {integrity: sha512-vy9fM3pIxZmX07dL+VX1aZe7ynZ+YyB0jY+jE6r3hOK6GNY2t6W8rzpFC4tgpbXUYABkFQwgJq2XYXlxbXAI0g==} 36 | dev: false 37 | 38 | /@babel/helper-string-parser@7.19.4: 39 | resolution: {integrity: sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==} 40 | engines: {node: '>=6.9.0'} 41 | 42 | /@babel/helper-validator-identifier@7.19.1: 43 | resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} 44 | engines: {node: '>=6.9.0'} 45 | 46 | /@babel/parser@7.20.15: 47 | resolution: {integrity: sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==} 48 | engines: {node: '>=6.0.0'} 49 | hasBin: true 50 | dependencies: 51 | '@babel/types': 7.20.7 52 | dev: false 53 | 54 | /@babel/parser@7.24.7: 55 | resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} 56 | engines: {node: '>=6.0.0'} 57 | hasBin: true 58 | dependencies: 59 | '@babel/types': 7.20.7 60 | dev: true 61 | 62 | /@babel/types@7.20.7: 63 | resolution: {integrity: sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==} 64 | engines: {node: '>=6.9.0'} 65 | dependencies: 66 | '@babel/helper-string-parser': 7.19.4 67 | '@babel/helper-validator-identifier': 7.19.1 68 | to-fast-properties: 2.0.0 69 | 70 | /@esbuild/aix-ppc64@0.21.5: 71 | resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} 72 | engines: {node: '>=12'} 73 | cpu: [ppc64] 74 | os: [aix] 75 | requiresBuild: true 76 | optional: true 77 | 78 | /@esbuild/android-arm64@0.21.5: 79 | resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} 80 | engines: {node: '>=12'} 81 | cpu: [arm64] 82 | os: [android] 83 | requiresBuild: true 84 | optional: true 85 | 86 | /@esbuild/android-arm@0.21.5: 87 | resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} 88 | engines: {node: '>=12'} 89 | cpu: [arm] 90 | os: [android] 91 | requiresBuild: true 92 | optional: true 93 | 94 | /@esbuild/android-x64@0.21.5: 95 | resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} 96 | engines: {node: '>=12'} 97 | cpu: [x64] 98 | os: [android] 99 | requiresBuild: true 100 | optional: true 101 | 102 | /@esbuild/darwin-arm64@0.21.5: 103 | resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} 104 | engines: {node: '>=12'} 105 | cpu: [arm64] 106 | os: [darwin] 107 | requiresBuild: true 108 | optional: true 109 | 110 | /@esbuild/darwin-x64@0.21.5: 111 | resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} 112 | engines: {node: '>=12'} 113 | cpu: [x64] 114 | os: [darwin] 115 | requiresBuild: true 116 | optional: true 117 | 118 | /@esbuild/freebsd-arm64@0.21.5: 119 | resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} 120 | engines: {node: '>=12'} 121 | cpu: [arm64] 122 | os: [freebsd] 123 | requiresBuild: true 124 | optional: true 125 | 126 | /@esbuild/freebsd-x64@0.21.5: 127 | resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} 128 | engines: {node: '>=12'} 129 | cpu: [x64] 130 | os: [freebsd] 131 | requiresBuild: true 132 | optional: true 133 | 134 | /@esbuild/linux-arm64@0.21.5: 135 | resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} 136 | engines: {node: '>=12'} 137 | cpu: [arm64] 138 | os: [linux] 139 | requiresBuild: true 140 | optional: true 141 | 142 | /@esbuild/linux-arm@0.21.5: 143 | resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} 144 | engines: {node: '>=12'} 145 | cpu: [arm] 146 | os: [linux] 147 | requiresBuild: true 148 | optional: true 149 | 150 | /@esbuild/linux-ia32@0.21.5: 151 | resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} 152 | engines: {node: '>=12'} 153 | cpu: [ia32] 154 | os: [linux] 155 | requiresBuild: true 156 | optional: true 157 | 158 | /@esbuild/linux-loong64@0.21.5: 159 | resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} 160 | engines: {node: '>=12'} 161 | cpu: [loong64] 162 | os: [linux] 163 | requiresBuild: true 164 | optional: true 165 | 166 | /@esbuild/linux-mips64el@0.21.5: 167 | resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} 168 | engines: {node: '>=12'} 169 | cpu: [mips64el] 170 | os: [linux] 171 | requiresBuild: true 172 | optional: true 173 | 174 | /@esbuild/linux-ppc64@0.21.5: 175 | resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} 176 | engines: {node: '>=12'} 177 | cpu: [ppc64] 178 | os: [linux] 179 | requiresBuild: true 180 | optional: true 181 | 182 | /@esbuild/linux-riscv64@0.21.5: 183 | resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} 184 | engines: {node: '>=12'} 185 | cpu: [riscv64] 186 | os: [linux] 187 | requiresBuild: true 188 | optional: true 189 | 190 | /@esbuild/linux-s390x@0.21.5: 191 | resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} 192 | engines: {node: '>=12'} 193 | cpu: [s390x] 194 | os: [linux] 195 | requiresBuild: true 196 | optional: true 197 | 198 | /@esbuild/linux-x64@0.21.5: 199 | resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} 200 | engines: {node: '>=12'} 201 | cpu: [x64] 202 | os: [linux] 203 | requiresBuild: true 204 | optional: true 205 | 206 | /@esbuild/netbsd-x64@0.21.5: 207 | resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} 208 | engines: {node: '>=12'} 209 | cpu: [x64] 210 | os: [netbsd] 211 | requiresBuild: true 212 | optional: true 213 | 214 | /@esbuild/openbsd-x64@0.21.5: 215 | resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} 216 | engines: {node: '>=12'} 217 | cpu: [x64] 218 | os: [openbsd] 219 | requiresBuild: true 220 | optional: true 221 | 222 | /@esbuild/sunos-x64@0.21.5: 223 | resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} 224 | engines: {node: '>=12'} 225 | cpu: [x64] 226 | os: [sunos] 227 | requiresBuild: true 228 | optional: true 229 | 230 | /@esbuild/win32-arm64@0.21.5: 231 | resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} 232 | engines: {node: '>=12'} 233 | cpu: [arm64] 234 | os: [win32] 235 | requiresBuild: true 236 | optional: true 237 | 238 | /@esbuild/win32-ia32@0.21.5: 239 | resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} 240 | engines: {node: '>=12'} 241 | cpu: [ia32] 242 | os: [win32] 243 | requiresBuild: true 244 | optional: true 245 | 246 | /@esbuild/win32-x64@0.21.5: 247 | resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} 248 | engines: {node: '>=12'} 249 | cpu: [x64] 250 | os: [win32] 251 | requiresBuild: true 252 | optional: true 253 | 254 | /@jridgewell/sourcemap-codec@1.4.14: 255 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 256 | dev: false 257 | 258 | /@jridgewell/sourcemap-codec@1.4.15: 259 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 260 | dev: true 261 | 262 | /@mdit-vue/plugin-component@0.11.2: 263 | resolution: {integrity: sha512-ucFiEULCkLcCG1Tf1MfG5u5PS4BIXWIeKGHRGsXxz1ix2GbZWKFVgWEdNEckBu8s75Fv1WJLIOiAYZyri2f1nw==} 264 | dependencies: 265 | '@types/markdown-it': 12.2.3 266 | markdown-it: 13.0.1 267 | dev: false 268 | 269 | /@mdit-vue/plugin-frontmatter@0.11.1: 270 | resolution: {integrity: sha512-AdZJInjD1pTJXlfhuoBS5ycuIQ3ewBfY0R/XHM3TRDEaDHQJHxouUCpCyijZmpdljTU45lFetIowaKtAi7GBog==} 271 | dependencies: 272 | '@mdit-vue/types': 0.11.0 273 | '@types/markdown-it': 12.2.3 274 | gray-matter: 4.0.3 275 | markdown-it: 13.0.1 276 | dev: false 277 | 278 | /@mdit-vue/types@0.11.0: 279 | resolution: {integrity: sha512-ygCGP7vFpqS02hpZwEe1uz8cfImWX06+zRs08J+tCZRKb6k+easIaIHFtY9ZSxt7j9L/gAPLDo/5RmOT6z0DPQ==} 280 | dev: false 281 | 282 | /@rollup/pluginutils@5.0.2: 283 | resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} 284 | engines: {node: '>=14.0.0'} 285 | peerDependencies: 286 | rollup: ^1.20.0||^2.0.0||^3.0.0 287 | peerDependenciesMeta: 288 | rollup: 289 | optional: true 290 | dependencies: 291 | '@types/estree': 1.0.0 292 | estree-walker: 2.0.2 293 | picomatch: 2.3.1 294 | dev: false 295 | 296 | /@rollup/rollup-android-arm-eabi@4.18.0: 297 | resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} 298 | cpu: [arm] 299 | os: [android] 300 | requiresBuild: true 301 | optional: true 302 | 303 | /@rollup/rollup-android-arm64@4.18.0: 304 | resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} 305 | cpu: [arm64] 306 | os: [android] 307 | requiresBuild: true 308 | optional: true 309 | 310 | /@rollup/rollup-darwin-arm64@4.18.0: 311 | resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} 312 | cpu: [arm64] 313 | os: [darwin] 314 | requiresBuild: true 315 | optional: true 316 | 317 | /@rollup/rollup-darwin-x64@4.18.0: 318 | resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} 319 | cpu: [x64] 320 | os: [darwin] 321 | requiresBuild: true 322 | optional: true 323 | 324 | /@rollup/rollup-linux-arm-gnueabihf@4.18.0: 325 | resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} 326 | cpu: [arm] 327 | os: [linux] 328 | requiresBuild: true 329 | optional: true 330 | 331 | /@rollup/rollup-linux-arm-musleabihf@4.18.0: 332 | resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} 333 | cpu: [arm] 334 | os: [linux] 335 | requiresBuild: true 336 | optional: true 337 | 338 | /@rollup/rollup-linux-arm64-gnu@4.18.0: 339 | resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} 340 | cpu: [arm64] 341 | os: [linux] 342 | requiresBuild: true 343 | optional: true 344 | 345 | /@rollup/rollup-linux-arm64-musl@4.18.0: 346 | resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} 347 | cpu: [arm64] 348 | os: [linux] 349 | requiresBuild: true 350 | optional: true 351 | 352 | /@rollup/rollup-linux-powerpc64le-gnu@4.18.0: 353 | resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} 354 | cpu: [ppc64] 355 | os: [linux] 356 | requiresBuild: true 357 | optional: true 358 | 359 | /@rollup/rollup-linux-riscv64-gnu@4.18.0: 360 | resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} 361 | cpu: [riscv64] 362 | os: [linux] 363 | requiresBuild: true 364 | optional: true 365 | 366 | /@rollup/rollup-linux-s390x-gnu@4.18.0: 367 | resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} 368 | cpu: [s390x] 369 | os: [linux] 370 | requiresBuild: true 371 | optional: true 372 | 373 | /@rollup/rollup-linux-x64-gnu@4.18.0: 374 | resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} 375 | cpu: [x64] 376 | os: [linux] 377 | requiresBuild: true 378 | optional: true 379 | 380 | /@rollup/rollup-linux-x64-musl@4.18.0: 381 | resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} 382 | cpu: [x64] 383 | os: [linux] 384 | requiresBuild: true 385 | optional: true 386 | 387 | /@rollup/rollup-win32-arm64-msvc@4.18.0: 388 | resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} 389 | cpu: [arm64] 390 | os: [win32] 391 | requiresBuild: true 392 | optional: true 393 | 394 | /@rollup/rollup-win32-ia32-msvc@4.18.0: 395 | resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} 396 | cpu: [ia32] 397 | os: [win32] 398 | requiresBuild: true 399 | optional: true 400 | 401 | /@rollup/rollup-win32-x64-msvc@4.18.0: 402 | resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} 403 | cpu: [x64] 404 | os: [win32] 405 | requiresBuild: true 406 | optional: true 407 | 408 | /@types/estree@1.0.0: 409 | resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} 410 | dev: false 411 | 412 | /@types/estree@1.0.5: 413 | resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} 414 | 415 | /@types/linkify-it@3.0.2: 416 | resolution: {integrity: sha512-HZQYqbiFVWufzCwexrvh694SOim8z2d+xJl5UNamcvQFejLY/2YUtzXHYi3cHdI7PMlS8ejH2slRAOJQ32aNbA==} 417 | dev: false 418 | 419 | /@types/markdown-it@12.2.3: 420 | resolution: {integrity: sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==} 421 | dependencies: 422 | '@types/linkify-it': 3.0.2 423 | '@types/mdurl': 1.0.2 424 | dev: false 425 | 426 | /@types/mdurl@1.0.2: 427 | resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} 428 | dev: false 429 | 430 | /@types/node@20.14.9: 431 | resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} 432 | dependencies: 433 | undici-types: 5.26.5 434 | 435 | /@volar/language-core@1.0.24: 436 | resolution: {integrity: sha512-vTN+alJiWwK0Pax6POqrmevbtFW2dXhjwWiW/MW4f48eDYPLdyURWcr8TixO7EN/nHsUBj2udT7igFKPtjyAKg==} 437 | dependencies: 438 | '@volar/source-map': 1.0.24 439 | muggle-string: 0.1.0 440 | dev: false 441 | 442 | /@volar/source-map@1.0.24: 443 | resolution: {integrity: sha512-Qsv/tkplx18pgBr8lKAbM1vcDqgkGKQzbChg6NW+v0CZc3G7FLmK+WrqEPzKlN7Cwdc6XVL559Nod8WKAfKr4A==} 444 | dependencies: 445 | muggle-string: 0.1.0 446 | dev: false 447 | 448 | /@volar/vue-language-core@1.0.24: 449 | resolution: {integrity: sha512-2NTJzSgrwKu6uYwPqLiTMuAzi7fAY3yFy5PJ255bGJc82If0Xr+cW8pC80vpjG0D/aVLmlwAdO4+Ya2BI8GdDg==} 450 | dependencies: 451 | '@volar/language-core': 1.0.24 452 | '@volar/source-map': 1.0.24 453 | '@vue/compiler-dom': 3.2.47 454 | '@vue/compiler-sfc': 3.2.47 455 | '@vue/reactivity': 3.2.47 456 | '@vue/shared': 3.2.47 457 | minimatch: 5.1.6 458 | vue-template-compiler: 2.7.14 459 | dev: false 460 | 461 | /@vue/compiler-core@3.2.47: 462 | resolution: {integrity: sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==} 463 | dependencies: 464 | '@babel/parser': 7.20.15 465 | '@vue/shared': 3.2.47 466 | estree-walker: 2.0.2 467 | source-map: 0.6.1 468 | dev: false 469 | 470 | /@vue/compiler-core@3.4.31: 471 | resolution: {integrity: sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==} 472 | dependencies: 473 | '@babel/parser': 7.24.7 474 | '@vue/shared': 3.4.31 475 | entities: 4.5.0 476 | estree-walker: 2.0.2 477 | source-map-js: 1.2.0 478 | dev: true 479 | 480 | /@vue/compiler-dom@3.2.47: 481 | resolution: {integrity: sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==} 482 | dependencies: 483 | '@vue/compiler-core': 3.2.47 484 | '@vue/shared': 3.2.47 485 | dev: false 486 | 487 | /@vue/compiler-dom@3.4.31: 488 | resolution: {integrity: sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==} 489 | dependencies: 490 | '@vue/compiler-core': 3.4.31 491 | '@vue/shared': 3.4.31 492 | dev: true 493 | 494 | /@vue/compiler-sfc@3.2.47: 495 | resolution: {integrity: sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==} 496 | dependencies: 497 | '@babel/parser': 7.20.15 498 | '@vue/compiler-core': 3.2.47 499 | '@vue/compiler-dom': 3.2.47 500 | '@vue/compiler-ssr': 3.2.47 501 | '@vue/reactivity-transform': 3.2.47 502 | '@vue/shared': 3.2.47 503 | estree-walker: 2.0.2 504 | magic-string: 0.25.9 505 | postcss: 8.4.21 506 | source-map: 0.6.1 507 | dev: false 508 | 509 | /@vue/compiler-sfc@3.4.31: 510 | resolution: {integrity: sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==} 511 | dependencies: 512 | '@babel/parser': 7.24.7 513 | '@vue/compiler-core': 3.4.31 514 | '@vue/compiler-dom': 3.4.31 515 | '@vue/compiler-ssr': 3.4.31 516 | '@vue/shared': 3.4.31 517 | estree-walker: 2.0.2 518 | magic-string: 0.30.10 519 | postcss: 8.4.39 520 | source-map-js: 1.2.0 521 | dev: true 522 | 523 | /@vue/compiler-ssr@3.2.47: 524 | resolution: {integrity: sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==} 525 | dependencies: 526 | '@vue/compiler-dom': 3.2.47 527 | '@vue/shared': 3.2.47 528 | dev: false 529 | 530 | /@vue/compiler-ssr@3.4.31: 531 | resolution: {integrity: sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==} 532 | dependencies: 533 | '@vue/compiler-dom': 3.4.31 534 | '@vue/shared': 3.4.31 535 | dev: true 536 | 537 | /@vue/reactivity-transform@3.2.47: 538 | resolution: {integrity: sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==} 539 | dependencies: 540 | '@babel/parser': 7.20.15 541 | '@vue/compiler-core': 3.2.47 542 | '@vue/shared': 3.2.47 543 | estree-walker: 2.0.2 544 | magic-string: 0.25.9 545 | dev: false 546 | 547 | /@vue/reactivity@3.2.47: 548 | resolution: {integrity: sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==} 549 | dependencies: 550 | '@vue/shared': 3.2.47 551 | dev: false 552 | 553 | /@vue/reactivity@3.4.31: 554 | resolution: {integrity: sha512-VGkTani8SOoVkZNds1PfJ/T1SlAIOf8E58PGAhIOUDYPC4GAmFA2u/E14TDAFcf3vVDKunc4QqCe/SHr8xC65Q==} 555 | dependencies: 556 | '@vue/shared': 3.4.31 557 | dev: true 558 | 559 | /@vue/runtime-core@3.4.31: 560 | resolution: {integrity: sha512-LDkztxeUPazxG/p8c5JDDKPfkCDBkkiNLVNf7XZIUnJ+66GVGkP+TIh34+8LtPisZ+HMWl2zqhIw0xN5MwU1cw==} 561 | dependencies: 562 | '@vue/reactivity': 3.4.31 563 | '@vue/shared': 3.4.31 564 | dev: true 565 | 566 | /@vue/runtime-dom@3.4.31: 567 | resolution: {integrity: sha512-2Auws3mB7+lHhTFCg8E9ZWopA6Q6L455EcU7bzcQ4x6Dn4cCPuqj6S2oBZgN2a8vJRS/LSYYxwFFq2Hlx3Fsaw==} 568 | dependencies: 569 | '@vue/reactivity': 3.4.31 570 | '@vue/runtime-core': 3.4.31 571 | '@vue/shared': 3.4.31 572 | csstype: 3.1.3 573 | dev: true 574 | 575 | /@vue/server-renderer@3.4.31(vue@3.4.31): 576 | resolution: {integrity: sha512-D5BLbdvrlR9PE3by9GaUp1gQXlCNadIZytMIb8H2h3FMWJd4oUfkUTEH2wAr3qxoRz25uxbTcbqd3WKlm9EHQA==} 577 | peerDependencies: 578 | vue: 3.4.31 579 | dependencies: 580 | '@vue/compiler-ssr': 3.4.31 581 | '@vue/shared': 3.4.31 582 | vue: 3.4.31(typescript@5.5.2) 583 | dev: true 584 | 585 | /@vue/shared@3.2.47: 586 | resolution: {integrity: sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==} 587 | dev: false 588 | 589 | /@vue/shared@3.4.31: 590 | resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==} 591 | dev: true 592 | 593 | /argparse@1.0.10: 594 | resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} 595 | dependencies: 596 | sprintf-js: 1.0.3 597 | dev: false 598 | 599 | /argparse@2.0.1: 600 | resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} 601 | dev: false 602 | 603 | /balanced-match@1.0.2: 604 | resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} 605 | dev: false 606 | 607 | /brace-expansion@2.0.1: 608 | resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} 609 | dependencies: 610 | balanced-match: 1.0.2 611 | dev: false 612 | 613 | /csstype@3.1.3: 614 | resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} 615 | dev: true 616 | 617 | /de-indent@1.0.2: 618 | resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} 619 | dev: false 620 | 621 | /entities@3.0.1: 622 | resolution: {integrity: sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==} 623 | engines: {node: '>=0.12'} 624 | dev: false 625 | 626 | /entities@4.5.0: 627 | resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} 628 | engines: {node: '>=0.12'} 629 | dev: true 630 | 631 | /esbuild@0.21.5: 632 | resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} 633 | engines: {node: '>=12'} 634 | hasBin: true 635 | requiresBuild: true 636 | optionalDependencies: 637 | '@esbuild/aix-ppc64': 0.21.5 638 | '@esbuild/android-arm': 0.21.5 639 | '@esbuild/android-arm64': 0.21.5 640 | '@esbuild/android-x64': 0.21.5 641 | '@esbuild/darwin-arm64': 0.21.5 642 | '@esbuild/darwin-x64': 0.21.5 643 | '@esbuild/freebsd-arm64': 0.21.5 644 | '@esbuild/freebsd-x64': 0.21.5 645 | '@esbuild/linux-arm': 0.21.5 646 | '@esbuild/linux-arm64': 0.21.5 647 | '@esbuild/linux-ia32': 0.21.5 648 | '@esbuild/linux-loong64': 0.21.5 649 | '@esbuild/linux-mips64el': 0.21.5 650 | '@esbuild/linux-ppc64': 0.21.5 651 | '@esbuild/linux-riscv64': 0.21.5 652 | '@esbuild/linux-s390x': 0.21.5 653 | '@esbuild/linux-x64': 0.21.5 654 | '@esbuild/netbsd-x64': 0.21.5 655 | '@esbuild/openbsd-x64': 0.21.5 656 | '@esbuild/sunos-x64': 0.21.5 657 | '@esbuild/win32-arm64': 0.21.5 658 | '@esbuild/win32-ia32': 0.21.5 659 | '@esbuild/win32-x64': 0.21.5 660 | 661 | /esprima@4.0.1: 662 | resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} 663 | engines: {node: '>=4'} 664 | hasBin: true 665 | dev: false 666 | 667 | /estree-walker@2.0.2: 668 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 669 | 670 | /extend-shallow@2.0.1: 671 | resolution: {integrity: sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==} 672 | engines: {node: '>=0.10.0'} 673 | dependencies: 674 | is-extendable: 0.1.1 675 | dev: false 676 | 677 | /fsevents@2.3.3: 678 | resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} 679 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 680 | os: [darwin] 681 | requiresBuild: true 682 | optional: true 683 | 684 | /gray-matter@4.0.3: 685 | resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} 686 | engines: {node: '>=6.0'} 687 | dependencies: 688 | js-yaml: 3.14.1 689 | kind-of: 6.0.3 690 | section-matter: 1.0.0 691 | strip-bom-string: 1.0.0 692 | dev: false 693 | 694 | /he@1.2.0: 695 | resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} 696 | hasBin: true 697 | dev: false 698 | 699 | /is-extendable@0.1.1: 700 | resolution: {integrity: sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==} 701 | engines: {node: '>=0.10.0'} 702 | dev: false 703 | 704 | /js-yaml@3.14.1: 705 | resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} 706 | hasBin: true 707 | dependencies: 708 | argparse: 1.0.10 709 | esprima: 4.0.1 710 | dev: false 711 | 712 | /kind-of@6.0.3: 713 | resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} 714 | engines: {node: '>=0.10.0'} 715 | dev: false 716 | 717 | /linkify-it@4.0.1: 718 | resolution: {integrity: sha512-C7bfi1UZmoj8+PQx22XyeXCuBlokoyWQL5pWSP+EI6nzRylyThouddufc2c1NDIcP9k5agmN9fLpA7VNJfIiqw==} 719 | dependencies: 720 | uc.micro: 1.0.6 721 | dev: false 722 | 723 | /magic-string@0.25.9: 724 | resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} 725 | dependencies: 726 | sourcemap-codec: 1.4.8 727 | dev: false 728 | 729 | /magic-string@0.27.0: 730 | resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} 731 | engines: {node: '>=12'} 732 | dependencies: 733 | '@jridgewell/sourcemap-codec': 1.4.14 734 | dev: false 735 | 736 | /magic-string@0.30.10: 737 | resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} 738 | dependencies: 739 | '@jridgewell/sourcemap-codec': 1.4.15 740 | dev: true 741 | 742 | /markdown-it@13.0.1: 743 | resolution: {integrity: sha512-lTlxriVoy2criHP0JKRhO2VDG9c2ypWCsT237eDiLqi09rmbKoUetyGHq2uOIRoRS//kfoJckS0eUzzkDR+k2Q==} 744 | hasBin: true 745 | dependencies: 746 | argparse: 2.0.1 747 | entities: 3.0.1 748 | linkify-it: 4.0.1 749 | mdurl: 1.0.1 750 | uc.micro: 1.0.6 751 | dev: false 752 | 753 | /mdurl@1.0.1: 754 | resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} 755 | dev: false 756 | 757 | /minimatch@5.1.6: 758 | resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} 759 | engines: {node: '>=10'} 760 | dependencies: 761 | brace-expansion: 2.0.1 762 | dev: false 763 | 764 | /muggle-string@0.1.0: 765 | resolution: {integrity: sha512-Tr1knR3d2mKvvWthlk7202rywKbiOm4rVFLsfAaSIhJ6dt9o47W4S+JMtWhd/PW9Wrdew2/S2fSvhz3E2gkfEg==} 766 | dev: false 767 | 768 | /nanoid@3.3.4: 769 | resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} 770 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 771 | hasBin: true 772 | dev: false 773 | 774 | /nanoid@3.3.7: 775 | resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} 776 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 777 | hasBin: true 778 | 779 | /picocolors@1.0.0: 780 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 781 | dev: false 782 | 783 | /picocolors@1.0.1: 784 | resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} 785 | 786 | /picomatch@2.3.1: 787 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 788 | engines: {node: '>=8.6'} 789 | dev: false 790 | 791 | /postcss@8.4.21: 792 | resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==} 793 | engines: {node: ^10 || ^12 || >=14} 794 | dependencies: 795 | nanoid: 3.3.4 796 | picocolors: 1.0.0 797 | source-map-js: 1.0.2 798 | dev: false 799 | 800 | /postcss@8.4.39: 801 | resolution: {integrity: sha512-0vzE+lAiG7hZl1/9I8yzKLx3aR9Xbof3fBHKunvMfOCYAtMhrsnccJY2iTURb9EZd5+pLuiNV9/c/GZJOHsgIw==} 802 | engines: {node: ^10 || ^12 || >=14} 803 | dependencies: 804 | nanoid: 3.3.7 805 | picocolors: 1.0.1 806 | source-map-js: 1.2.0 807 | 808 | /rollup@4.18.0: 809 | resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} 810 | engines: {node: '>=18.0.0', npm: '>=8.0.0'} 811 | hasBin: true 812 | dependencies: 813 | '@types/estree': 1.0.5 814 | optionalDependencies: 815 | '@rollup/rollup-android-arm-eabi': 4.18.0 816 | '@rollup/rollup-android-arm64': 4.18.0 817 | '@rollup/rollup-darwin-arm64': 4.18.0 818 | '@rollup/rollup-darwin-x64': 4.18.0 819 | '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 820 | '@rollup/rollup-linux-arm-musleabihf': 4.18.0 821 | '@rollup/rollup-linux-arm64-gnu': 4.18.0 822 | '@rollup/rollup-linux-arm64-musl': 4.18.0 823 | '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 824 | '@rollup/rollup-linux-riscv64-gnu': 4.18.0 825 | '@rollup/rollup-linux-s390x-gnu': 4.18.0 826 | '@rollup/rollup-linux-x64-gnu': 4.18.0 827 | '@rollup/rollup-linux-x64-musl': 4.18.0 828 | '@rollup/rollup-win32-arm64-msvc': 4.18.0 829 | '@rollup/rollup-win32-ia32-msvc': 4.18.0 830 | '@rollup/rollup-win32-x64-msvc': 4.18.0 831 | fsevents: 2.3.3 832 | 833 | /section-matter@1.0.0: 834 | resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} 835 | engines: {node: '>=4'} 836 | dependencies: 837 | extend-shallow: 2.0.1 838 | kind-of: 6.0.3 839 | dev: false 840 | 841 | /source-map-js@1.0.2: 842 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 843 | engines: {node: '>=0.10.0'} 844 | dev: false 845 | 846 | /source-map-js@1.2.0: 847 | resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} 848 | engines: {node: '>=0.10.0'} 849 | 850 | /source-map@0.6.1: 851 | resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} 852 | engines: {node: '>=0.10.0'} 853 | dev: false 854 | 855 | /sourcemap-codec@1.4.8: 856 | resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} 857 | deprecated: Please use @jridgewell/sourcemap-codec instead 858 | dev: false 859 | 860 | /sprintf-js@1.0.3: 861 | resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} 862 | dev: false 863 | 864 | /strip-bom-string@1.0.0: 865 | resolution: {integrity: sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g==} 866 | engines: {node: '>=0.10.0'} 867 | dev: false 868 | 869 | /to-fast-properties@2.0.0: 870 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 871 | engines: {node: '>=4'} 872 | 873 | /typescript@5.5.2: 874 | resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} 875 | engines: {node: '>=14.17'} 876 | hasBin: true 877 | dev: true 878 | 879 | /uc.micro@1.0.6: 880 | resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==} 881 | dev: false 882 | 883 | /undici-types@5.26.5: 884 | resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} 885 | 886 | /vite-plugin-vue-markdown@0.22.4(vite@5.3.2): 887 | resolution: {integrity: sha512-+kDzqGI5Lq0Wa6M4EJtV7cqOIHgGp6g4jcazXljQKLl9Og4fRs6FuGAPa2HiJ44Z9es85LAPiPbTjwrZEGEUKA==} 888 | peerDependencies: 889 | vite: ^2.0.0 || ^3.0.0-0 || ^4.0.0 890 | dependencies: 891 | '@antfu/utils': 0.7.2 892 | '@mdit-vue/plugin-component': 0.11.2 893 | '@mdit-vue/plugin-frontmatter': 0.11.1 894 | '@mdit-vue/types': 0.11.0 895 | '@rollup/pluginutils': 5.0.2 896 | '@types/markdown-it': 12.2.3 897 | markdown-it: 13.0.1 898 | vite: 5.3.2(@types/node@20.14.9) 899 | transitivePeerDependencies: 900 | - rollup 901 | dev: false 902 | 903 | /vite@5.3.2(@types/node@20.14.9): 904 | resolution: {integrity: sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==} 905 | engines: {node: ^18.0.0 || >=20.0.0} 906 | hasBin: true 907 | peerDependencies: 908 | '@types/node': ^18.0.0 || >=20.0.0 909 | less: '*' 910 | lightningcss: ^1.21.0 911 | sass: '*' 912 | stylus: '*' 913 | sugarss: '*' 914 | terser: ^5.4.0 915 | peerDependenciesMeta: 916 | '@types/node': 917 | optional: true 918 | less: 919 | optional: true 920 | lightningcss: 921 | optional: true 922 | sass: 923 | optional: true 924 | stylus: 925 | optional: true 926 | sugarss: 927 | optional: true 928 | terser: 929 | optional: true 930 | dependencies: 931 | '@types/node': 20.14.9 932 | esbuild: 0.21.5 933 | postcss: 8.4.39 934 | rollup: 4.18.0 935 | optionalDependencies: 936 | fsevents: 2.3.3 937 | 938 | /vue-template-compiler@2.7.14: 939 | resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} 940 | dependencies: 941 | de-indent: 1.0.2 942 | he: 1.2.0 943 | dev: false 944 | 945 | /vue@3.4.31(typescript@5.5.2): 946 | resolution: {integrity: sha512-njqRrOy7W3YLAlVqSKpBebtZpDVg21FPoaq1I7f/+qqBThK9ChAIjkRWgeP6Eat+8C+iia4P3OYqpATP21BCoQ==} 947 | peerDependencies: 948 | typescript: '*' 949 | peerDependenciesMeta: 950 | typescript: 951 | optional: true 952 | dependencies: 953 | '@vue/compiler-dom': 3.4.31 954 | '@vue/compiler-sfc': 3.4.31 955 | '@vue/runtime-dom': 3.4.31 956 | '@vue/server-renderer': 3.4.31(vue@3.4.31) 957 | '@vue/shared': 3.4.31 958 | typescript: 5.5.2 959 | dev: true 960 | -------------------------------------------------------------------------------- /tooling/index.ts: -------------------------------------------------------------------------------- 1 | import { VueLanguagePlugin, VueFile, getDefaultVueLanguagePlugins } from '@volar/vue-language-core'; 2 | 3 | const plugin: VueLanguagePlugin = (ctx) => { 4 | 5 | const ts = ctx.modules.typescript; 6 | const plugins = getDefaultVueLanguagePlugins(ts, ctx.compilerOptions, { ...ctx.vueCompilerOptions, plugins: [] }); 7 | const previewBlockFiles = new Map(); 8 | 9 | return { 10 | version: 1, 11 | getEmbeddedFileNames(fileName, sfc) { 12 | const previewBlock = sfc.customBlocks.find(b => b.type === 'preview' && (b.lang || 'md') === 'md'); 13 | if (previewBlock) { 14 | const snapshot = ts.ScriptSnapshot.fromString(previewBlock.content); 15 | let vueFile = previewBlockFiles.get(fileName); 16 | if (!vueFile) { 17 | vueFile = new VueFile(fileName + '__VLS_preview.md', snapshot, ts, plugins); 18 | previewBlockFiles.set(fileName, vueFile); 19 | } 20 | else { 21 | vueFile.update(snapshot); 22 | } 23 | return vueFile.embeddedFiles.map(file => file.fileName); 24 | } 25 | return []; 26 | }, 27 | resolveEmbeddedFile(fileName, sfc, embeddedFile) { 28 | const vueFile = previewBlockFiles.get(fileName); 29 | if (vueFile) { 30 | const targetFile = vueFile._allEmbeddedFiles.value.find(file => file.file.fileName === embeddedFile.fileName); 31 | const previewBlock = sfc.customBlocks.find(b => b.type === 'preview' && (b.lang || 'md') === 'md'); 32 | if (targetFile && previewBlock) { 33 | { // watch 34 | previewBlock?.content; 35 | } 36 | Object.assign(embeddedFile, targetFile.file); 37 | const newContent: typeof embeddedFile.content = []; 38 | for (const segment of targetFile.file.content) { 39 | if (typeof segment === 'string') { 40 | newContent.push(segment); 41 | } 42 | else { 43 | let base = 0; 44 | if (segment[1] === 'template') { 45 | base = vueFile.sfc.template!.startTagEnd; 46 | } 47 | else if (segment[1] === 'script') { 48 | base = vueFile.sfc.script!.startTagEnd; 49 | } 50 | else if (segment[1] === 'scriptSetup') { 51 | base = vueFile.sfc.scriptSetup!.startTagEnd; 52 | } 53 | else if (segment[1]?.startsWith('style_')) { 54 | const index = Number(segment[1].substring('style_'.length)); 55 | base = vueFile.sfc.styles[index]!.startTagEnd; 56 | } 57 | else if (segment[1]?.startsWith('customBlock_')) { 58 | const index = Number(segment[1].substring('customBlock_'.length)); 59 | base = vueFile.sfc.customBlocks[index]!.startTagEnd; 60 | } 61 | newContent.push([ 62 | segment[0], 63 | previewBlock.name, 64 | typeof segment[2] === 'number' 65 | ? segment[2] + base 66 | : [ 67 | segment[2][0] + base, 68 | segment[2][1] + base, 69 | ], 70 | segment[3], 71 | ]); 72 | } 73 | } 74 | embeddedFile.content = newContent; 75 | embeddedFile.parentFileName = fileName + '.customBlock_preview_0.md'; 76 | } 77 | } 78 | }, 79 | }; 80 | }; 81 | 82 | export = plugin; 83 | -------------------------------------------------------------------------------- /tooling/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "module": "CommonJS", 5 | }, 6 | "include": [ 7 | "./index.ts" 8 | ], 9 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2020", 4 | "module": "CommonJS", 5 | "moduleResolution": "node", 6 | "esModuleInterop": true, 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "skipLibCheck": true, 10 | "declaration": true, 11 | "composite": true, 12 | "types": [ 13 | "vite/client", 14 | ] 15 | }, 16 | "include": [ 17 | "./index.ts", 18 | ], 19 | "references": [ 20 | { 21 | "path": "./client/tsconfig.json" 22 | }, 23 | { 24 | "path": "./tooling/tsconfig.json" 25 | }, 26 | ] 27 | } --------------------------------------------------------------------------------