From c37b1308e9cd0945054ec1bfc0156f180bd85eb4 Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Sun, 25 Feb 2024 00:48:52 +0800 Subject: [PATCH] =?UTF-8?q?feat(plugin-shikiji):=20=E4=BD=BF=E7=94=A8=20fl?= =?UTF-8?q?oating-vue=20=E5=AE=9E=E7=8E=B0=20twoslash=20=E6=A8=A1=E6=80=81?= =?UTF-8?q?=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/.vuepress/theme.ts | 1 + docs/2.preview/主题效果预览.md | 12 + plugins/plugin-search/package.json | 1 - plugins/plugin-shikiji/package.json | 13 +- plugins/plugin-shikiji/src/client/config.ts | 52 ++ plugins/plugin-shikiji/src/node/highlight.ts | 49 +- .../src/node/renderer-floating-vue.ts | 190 ++++++ .../src/node/rendererTransformer.ts | 70 +++ .../plugin-shikiji/src/node/shikijiPlugin.ts | 35 +- plugins/plugin-shikiji/src/node/types.ts | 6 + pnpm-lock.yaml | 579 +++++++++++++++++- theme/src/client/styles/twoslash.scss | 136 ++++ 12 files changed, 1109 insertions(+), 35 deletions(-) create mode 100644 plugins/plugin-shikiji/src/client/config.ts create mode 100644 plugins/plugin-shikiji/src/node/renderer-floating-vue.ts create mode 100644 plugins/plugin-shikiji/src/node/rendererTransformer.ts diff --git a/docs/.vuepress/theme.ts b/docs/.vuepress/theme.ts index bdd70673..b3a0ad03 100644 --- a/docs/.vuepress/theme.ts +++ b/docs/.vuepress/theme.ts @@ -35,5 +35,6 @@ export const theme: Theme = themePlume({ // appId: '111', // indexName: '1234', // }, + shiki: { twoslash: true }, }, }) diff --git a/docs/2.preview/主题效果预览.md b/docs/2.preview/主题效果预览.md index 0e4601c1..bfd05969 100644 --- a/docs/2.preview/主题效果预览.md +++ b/docs/2.preview/主题效果预览.md @@ -197,6 +197,18 @@ Number.parseInt('123', 10) // ``` +```vue twoslash + + + +``` + **代码分组** ::: code-tabs diff --git a/plugins/plugin-search/package.json b/plugins/plugin-search/package.json index 8c02735b..a618cf99 100644 --- a/plugins/plugin-search/package.json +++ b/plugins/plugin-search/package.json @@ -32,7 +32,6 @@ ], "scripts": { "build": "pnpm run clean && pnpm run copy && pnpm run ts", - "dev": "pnpm copy --watch", "clean": "rimraf --glob ./lib ./*.tsbuildinfo", "copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib", "ts": "tsc -b tsconfig.build.json" diff --git a/plugins/plugin-shikiji/package.json b/plugins/plugin-shikiji/package.json index 2269b891..a9a58195 100644 --- a/plugins/plugin-shikiji/package.json +++ b/plugins/plugin-shikiji/package.json @@ -36,10 +36,17 @@ "vuepress": "2.0.0-rc.8" }, "dependencies": { - "@shikijs/transformers": "^1.1.6", - "@shikijs/twoslash": "^1.1.6", + "@shikijs/transformers": "^1.1.7", + "@shikijs/twoslash": "^1.1.7", + "@types/hast": "^3.0.4", + "floating-vue": "^5.2.2", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm": "^3.0.0", + "mdast-util-to-hast": "^13.1.0", "nanoid": "^5.0.6", - "shiki": "^1.1.6" + "shiki": "^1.1.7", + "twoslash": "^0.2.4", + "twoslash-vue": "^0.2.4" }, "publishConfig": { "access": "public" diff --git a/plugins/plugin-shikiji/src/client/config.ts b/plugins/plugin-shikiji/src/client/config.ts new file mode 100644 index 00000000..fd6c70b7 --- /dev/null +++ b/plugins/plugin-shikiji/src/client/config.ts @@ -0,0 +1,52 @@ +import { type ClientConfig, defineClientConfig } from 'vuepress/client' +import FloatingVue, { recomputeAllPoppers } from 'floating-vue' +import 'floating-vue/dist/style.css' + +const isMobile = typeof navigator !== 'undefined' && /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) + +export type FloatingVueConfig = Parameters<(typeof FloatingVue)['install']>[1] + +export default defineClientConfig({ + enhance({ app }) { + if (typeof window !== 'undefined') { + // Recompute poppers when clicking on a tab + window.addEventListener('click', (e) => { + const path = e.composedPath() + if (path.some((el: any) => el?.classList?.contains?.('vp-code-group') || el?.classList?.contains?.('tabs'))) + recomputeAllPoppers() + }, { passive: true }) + } + app.use(FloatingVue, { + themes: { + 'twoslash': { + $extend: 'dropdown', + triggers: isMobile ? ['touch'] : ['hover', 'touch'], + popperTriggers: isMobile ? ['touch'] : ['hover', 'touch'], + placement: 'bottom-start', + overflowPadding: 10, + delay: 0, + handleResize: false, + autoHide: true, + instantMove: true, + flip: false, + arrowPadding: 8, + autoBoundaryMaxSize: true, + }, + 'twoslash-query': { + $extend: 'twoslash', + triggers: ['click'], + popperTriggers: ['click'], + autoHide: false, + }, + 'twoslash-completion': { + $extend: 'twoslash-query', + triggers: ['click'], + popperTriggers: ['click'], + autoHide: false, + distance: 0, + arrowOverflow: true, + }, + }, + }) + }, +}) as ClientConfig diff --git a/plugins/plugin-shikiji/src/node/highlight.ts b/plugins/plugin-shikiji/src/node/highlight.ts index 815e1303..1669a7dd 100644 --- a/plugins/plugin-shikiji/src/node/highlight.ts +++ b/plugins/plugin-shikiji/src/node/highlight.ts @@ -16,11 +16,13 @@ import { transformerNotationWordHighlight, transformerRenderWhitespace, } from '@shikijs/transformers' -import { rendererRich, transformerTwoslash } from '@shikijs/twoslash' import type { HighlighterOptions, ThemeOptions } from './types.js' import { resolveAttrs } from './resolveAttrs.js' +import { LRUCache } from './lru.js' +import { defaultHoverInfoProcessor, transformerTwoslash } from './rendererTransformer.js' const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10) +const cache = new LRUCache(64) const RE_ESCAPE = /\[\\\!code/g const mustacheRE = /\{\{.*?\}\}/g @@ -28,6 +30,7 @@ const mustacheRE = /\{\{.*?\}\}/g export async function highlight( theme: ThemeOptions, options: HighlighterOptions, + isDev: boolean, ): Promise<(str: string, lang: string, attrs: string) => string> { const { defaultHighlightLang: defaultLang = '', @@ -68,6 +71,18 @@ export async function highlight( delete node.properties.style }, }, + { + name: 'shiki:inline-decorations', + preprocess(code, options) { + const reg = /^\/\/ @decorations:(.*?)\n/ + code = code.replace(reg, (match, decorations) => { + options.decorations ||= [] + options.decorations.push(...JSON.parse(decorations)) + return '' + }) + return code + }, + }, { name: 'vuepress-shikiji:remove-escape', postprocess: code => code.replace(RE_ESCAPE, '[!code'), @@ -77,6 +92,14 @@ export async function highlight( return (str: string, lang: string, attrs: string) => { lang = lang || defaultLang + const key = str + lang + attrs + + if (isDev) { + const rendered = cache.get(key) + if (rendered) + return rendered + } + if (lang) { const langLoaded = highlighter.getLoadedLanguages().includes(lang as any) if (!langLoaded && !isPlainLang(lang) && !isSpecialLang(lang)) { @@ -108,6 +131,9 @@ export async function highlight( s = s.replaceAll(marker, match) }) + if (attributes.twoslash && options.twoslash) + s = s.replace(/{/g, '{') + return `${s}\n` } @@ -115,11 +141,13 @@ export async function highlight( const inlineTransformers: ShikiTransformer[] = [] - if (attributes.twoslash) { + if (attributes.twoslash && options.twoslash) { inlineTransformers.push(transformerTwoslash({ - renderer: rendererRich({ - classExtra: 'vp-copy-ignore', - }), + processHoverInfo(info) { + return defaultHoverInfoProcessor(info) + // Remove shiki_core namespace + .replace(/_shikijs_core[\w_]*\./g, '') + }, })) } @@ -137,15 +165,18 @@ export async function highlight( ...inlineTransformers, ...userTransformers, ], - meta: { - __raw: rawAttrs, - }, + meta: { __raw: rawAttrs }, ...(typeof theme === 'object' && 'light' in theme && 'dark' in theme ? { themes: theme, defaultColor: false } : { theme }), }) - return restoreMustache(highlighted) + const rendered = restoreMustache(highlighted) + + if (isDev) + cache.set(key, rendered) + + return rendered } catch (e) { logger.error(e) diff --git a/plugins/plugin-shikiji/src/node/renderer-floating-vue.ts b/plugins/plugin-shikiji/src/node/renderer-floating-vue.ts new file mode 100644 index 00000000..7eb1f58b --- /dev/null +++ b/plugins/plugin-shikiji/src/node/renderer-floating-vue.ts @@ -0,0 +1,190 @@ +import { defaultHoverInfoProcessor, rendererRich } from '@shikijs/twoslash' +import type { RendererRichOptions, TwoslashRenderer } from '@shikijs/twoslash' +import type { Element, ElementContent, Text } from 'hast' +import type { ShikiTransformerContextCommon } from 'shiki' +import { gfmFromMarkdown } from 'mdast-util-gfm' +import { fromMarkdown } from 'mdast-util-from-markdown' +import { defaultHandlers, toHast } from 'mdast-util-to-hast' + +export { defaultHoverInfoProcessor } + +export interface TwoslashFloatingVueOptions { + classCopyIgnore?: string + classFloatingPanel?: string + classCode?: string + classMarkdown?: string + + floatingVueTheme?: string + floatingVueThemeQuery?: string + floatingVueThemeCompletion?: string +} + +export interface TwoslashFloatingVueRendererOptions extends RendererRichOptions { + /** + * Class and themes for floating-vue specific nodes + */ + floatingVue?: TwoslashFloatingVueOptions +} + +export function rendererFloatingVue(options: TwoslashFloatingVueRendererOptions = {}): TwoslashRenderer { + const { + classCopyIgnore = 'vp-copy-ignore', + classFloatingPanel = 'twoslash-floating', + classCode = 'vp-code', + classMarkdown = 'plume-content', + floatingVueTheme = 'twoslash', + floatingVueThemeQuery = 'twoslash-query', + floatingVueThemeCompletion = 'twoslash-completion', + } = options.floatingVue || {} + + const { + errorRendering = 'line', + } = options + + const hoverBasicProps = { + 'class': 'twoslash-hover', + 'popper-class': ['shiki', classFloatingPanel, classCopyIgnore, classCode].join(' '), + 'theme': floatingVueTheme, + } + + function compose(parts: { token: Element | Text, popup: Element }): Element[] { + return [ + { + type: 'element', + tagName: 'span', + properties: {}, + children: [parts.token], + }, + { + type: 'element', + tagName: 'template', + properties: { + 'v-slot:popper': '{}', + }, + content: { + type: 'root', + children: [vPre(parts.popup)], + }, + children: [], + }, + ] + } + + const rich = rendererRich({ + classExtra: classCopyIgnore, + ...options, + renderMarkdown, + renderMarkdownInline, + hast: { + hoverToken: { + tagName: 'v-menu', + properties: hoverBasicProps, + }, + hoverCompose: compose, + queryToken: { + tagName: 'v-menu', + properties: { + ...hoverBasicProps, + ':shown': 'true', + 'theme': floatingVueThemeQuery, + }, + }, + queryCompose: compose, + popupDocs: { + class: `twoslash-popup-docs ${classMarkdown}`, + }, + popupDocsTags: { + class: `twoslash-popup-docs twoslash-popup-docs-tags ${classMarkdown}`, + }, + popupError: { + class: `twoslash-popup-error ${classMarkdown}`, + }, + errorToken: errorRendering === 'line' + ? undefined + : { + tagName: 'v-menu', + properties: { + ...hoverBasicProps, + class: 'twoslash-error twoslash-error-hover', + }, + }, + errorCompose: compose, + completionCompose({ popup, cursor }) { + return [ + { + type: 'element', + tagName: 'v-menu', + properties: { + 'popper-class': ['shiki twoslash-completion', classCopyIgnore, classFloatingPanel], + 'theme': floatingVueThemeCompletion, + ':shown': 'true', + }, + children: [ + cursor, + { + type: 'element', + tagName: 'template', + properties: { + 'v-slot:popper': '{}', + }, + content: { + type: 'root', + children: [vPre(popup)], + }, + }, + ], + }, + ] + }, + }, + }) + + return rich +} + +function vPre(el: T): T { + if (el.type === 'element') { + el.properties = el.properties || {} + el.properties['v-pre'] = '' + } + return el +} + +function renderMarkdown(this: ShikiTransformerContextCommon, md: string): ElementContent[] { + const mdast = fromMarkdown( + md.replace(/{@link ([^}]*)}/g, '$1'), // replace jsdoc links + { mdastExtensions: [gfmFromMarkdown()] }, + ) + + return (toHast( + mdast, + { + handlers: { + code: (state, node) => { + const lang = node.lang || '' + if (lang) { + return this.codeToHast( + node.value, + { + ...this.options, + transformers: [], + lang, + }, + ).children[0] as Element + } + return defaultHandlers.code(state, node) + }, + }, + }, + ) as Element).children +} + +function renderMarkdownInline(this: ShikiTransformerContextCommon, md: string, context?: string): ElementContent[] { + if (context === 'tag:param') + md = md.replace(/^([\w$-]+)/, '`$1` ') + + const children = renderMarkdown.call(this, md) + if (children.length === 1 && children[0].type === 'element' && children[0].tagName === 'p') + return children[0].children + return children +} diff --git a/plugins/plugin-shikiji/src/node/rendererTransformer.ts b/plugins/plugin-shikiji/src/node/rendererTransformer.ts new file mode 100644 index 00000000..4e51334e --- /dev/null +++ b/plugins/plugin-shikiji/src/node/rendererTransformer.ts @@ -0,0 +1,70 @@ +/* eslint-disable node/prefer-global/process */ +import type { TransformerTwoslashOptions } from '@shikijs/twoslash/core' +import { createTransformerFactory } from '@shikijs/twoslash/core' +import { createTwoslasher } from 'twoslash-vue' +import type { ShikiTransformer } from 'shiki' +import { removeTwoslashNotations } from 'twoslash' +import type { TwoslashFloatingVueRendererOptions } from './renderer-floating-vue.js' +import { rendererFloatingVue } from './renderer-floating-vue.js' + +export * from './renderer-floating-vue.js' + +export interface VitePressPluginTwoslashOptions extends TransformerTwoslashOptions, TwoslashFloatingVueRendererOptions { + /** + * Requires adding `twoslash` to the code block explicitly to run twoslash + * @default true + */ + explicitTrigger?: TransformerTwoslashOptions['explicitTrigger'] +} + +/** + * Create a Shiki transformer for VitePress to enable twoslash integration + * + * Add this to `markdown.codeTransformers` in `.vitepress/config.ts` + */ +export function transformerTwoslash(options: VitePressPluginTwoslashOptions = {}): ShikiTransformer { + const { + explicitTrigger = true, + } = options + + const onError = (error: any, code: string) => { + const isCI = typeof process !== 'undefined' && process?.env?.CI + const isDev = typeof process !== 'undefined' && process?.env?.NODE_ENV === 'development' + const shouldThrow = (options.throws || isCI || !isDev) && options.throws !== false + console.error(`\n\n--------\nTwoslash error in code:\n--------\n${code.split(/\n/g).slice(0, 15).join('\n').trim()}\n--------\n`) + if (shouldThrow) + throw error + else + console.error(error) + return removeTwoslashNotations(code) + } + + const twoslash = createTransformerFactory( + createTwoslasher(), + )({ + langs: ['ts', 'tsx', 'js', 'jsx', 'json', 'vue'], + renderer: rendererFloatingVue(options), + onTwoslashError: onError, + onShikiError: onError, + ...options, + explicitTrigger, + }) + + return { + ...twoslash, + name: '@shikijs/vuepress-twoslash', + preprocess(code, options) { + const cleanup = options.transformers?.find(i => i.name === 'vuepress:clean-up') + if (cleanup) + options.transformers?.splice(options.transformers.indexOf(cleanup), 1) + + return twoslash.preprocess!.call(this, code, options) + }, + postprocess(html) { + if (this.meta.twoslash) + return html.replace(/{/g, '{') + + return html + }, + } +} diff --git a/plugins/plugin-shikiji/src/node/shikijiPlugin.ts b/plugins/plugin-shikiji/src/node/shikijiPlugin.ts index 91254c08..8ae984ce 100644 --- a/plugins/plugin-shikiji/src/node/shikijiPlugin.ts +++ b/plugins/plugin-shikiji/src/node/shikijiPlugin.ts @@ -1,18 +1,45 @@ -import type { Plugin } from 'vuepress/core' +import type { Plugin, PluginObject } from 'vuepress/core' +import { getDirname, path } from 'vuepress/utils' import { highlight } from './highlight.js' import type { HighlighterOptions } from './types' export type ShikiPluginOptions = HighlighterOptions +const __dirname = getDirname(import.meta.url) + export function shikiPlugin(options: ShikiPluginOptions = {}): Plugin { - return { + const plugin: PluginObject = { name: '@vuepress-plume/plugin-shikiji', - extendsMarkdown: async (md) => { + extendsMarkdown: async (md, app) => { const theme = options.theme ?? { light: 'github-light', dark: 'github-dark' } - const highlighter = await highlight(theme, options) + const highlighter = await highlight(theme, options, app.env.isDev) md.options.highlight = highlighter }, } + + if (!options.twoslash) + return plugin + + return { + + ...plugin, + + clientConfigFile: path.resolve(__dirname, '../client/config.js'), + + extendsMarkdownOptions: (options) => { + if (options.code === false) + return + + // 注入 floating-vue 后,需要关闭 代码块 的 v-pre 配置 + if (options.code?.vPre) { + options.code.vPre.block = false + } + else { + options.code ??= {} + options.code.vPre = { block: false } + } + }, + } } diff --git a/plugins/plugin-shikiji/src/node/types.ts b/plugins/plugin-shikiji/src/node/types.ts index 7195ca3c..e9b5234f 100644 --- a/plugins/plugin-shikiji/src/node/types.ts +++ b/plugins/plugin-shikiji/src/node/types.ts @@ -59,6 +59,12 @@ export interface HighlighterOptions { */ codeTransformers?: ShikiTransformer[] + /** + * Enable transformerTwoslash + * @default false + */ + twoslash?: boolean + /** * Enable transformerRenderWhitespace * @default false diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 88747b83..449c1137 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -289,17 +289,38 @@ importers: plugins/plugin-shikiji: dependencies: '@shikijs/transformers': - specifier: ^1.1.6 - version: 1.1.6 + specifier: ^1.1.7 + version: 1.1.7 '@shikijs/twoslash': - specifier: ^1.1.6 - version: 1.1.6(typescript@5.3.3) + specifier: ^1.1.7 + version: 1.1.7(typescript@5.3.3) + '@types/hast': + specifier: ^3.0.4 + version: 3.0.4 + floating-vue: + specifier: ^5.2.2 + version: 5.2.2(vue@3.4.19) + mdast-util-from-markdown: + specifier: ^2.0.0 + version: 2.0.0 + mdast-util-gfm: + specifier: ^3.0.0 + version: 3.0.0 + mdast-util-to-hast: + specifier: ^13.1.0 + version: 13.1.0 nanoid: specifier: ^5.0.6 version: 5.0.6 shiki: - specifier: ^1.1.6 - version: 1.1.6 + specifier: ^1.1.7 + version: 1.1.7 + twoslash: + specifier: ^0.2.4 + version: 0.2.4(typescript@5.3.3) + twoslash-vue: + specifier: ^0.2.4 + version: 0.2.4(typescript@5.3.3) vuepress: specifier: 2.0.0-rc.8 version: 2.0.0-rc.8(@vuepress/bundler-vite@2.0.0-rc.8)(@vuepress/bundler-webpack@2.0.0-rc.8)(typescript@5.3.3)(vue@3.4.19) @@ -1617,6 +1638,22 @@ packages: readable-stream: 4.3.0 dev: false + /@floating-ui/core@1.6.0: + resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==} + dependencies: + '@floating-ui/utils': 0.2.1 + dev: false + + /@floating-ui/dom@1.1.1: + resolution: {integrity: sha512-TpIO93+DIujg3g7SykEAGZMDtbJRrmnYRCNYSjJlvIbGhBjRSNTLVbNeDQBrzy9qDgUbiWdc7KA0uZHZ2tJmiw==} + dependencies: + '@floating-ui/core': 1.6.0 + dev: false + + /@floating-ui/utils@0.2.1: + resolution: {integrity: sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q==} + dev: false + /@humanwhocodes/config-array@0.11.13: resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} engines: {node: '>=10.10.0'} @@ -3195,20 +3232,20 @@ packages: dev: false optional: true - /@shikijs/core@1.1.6: - resolution: {integrity: sha512-kt9hhvrWTm0EPtRDIsoAZnSsFlIDBVBBI5CQewpA/NZCPin+MOKRXg+JiWc4y+8fZ/v0HzfDhu/UC+OTZGMt7A==} + /@shikijs/core@1.1.7: + resolution: {integrity: sha512-gTYLUIuD1UbZp/11qozD3fWpUTuMqPSf3svDMMrL0UmlGU7D9dPw/V1FonwAorCUJBltaaESxq90jrSjQyGixg==} dev: false - /@shikijs/transformers@1.1.6: - resolution: {integrity: sha512-R+eI1I9sQv0MCJyfR4kAG1G1SKSctw5ILszP0tHVrAgzSHWTpaHbXreZrDueahqtUCNHjt+MKmKJ8EMFtiitOQ==} + /@shikijs/transformers@1.1.7: + resolution: {integrity: sha512-lXz011ao4+rvweps/9h3CchBfzb1U5OtP5D51Tqc9lQYdLblWMIxQxH6Ybe1GeGINcEVM4goMyPrI0JvlIp4UQ==} dependencies: - shiki: 1.1.6 + shiki: 1.1.7 dev: false - /@shikijs/twoslash@1.1.6(typescript@5.3.3): - resolution: {integrity: sha512-0HJK7Il7HevTpRvpPlnJ0ow8UyoQxhvxQ0/lhfw1C0xW/7eLtSAtZfSKdel5Nch6HgbbtfucEzuUFmRIRXUFUg==} + /@shikijs/twoslash@1.1.7(typescript@5.3.3): + resolution: {integrity: sha512-WH/Ee67eixqDWjsAUXIJQUgRzPDApsz7Bci65Yobc7SWHNc8T2sY1UBa+MCV2mAj0D6VCYBwWlNxMDTfhN7K0Q==} dependencies: - '@shikijs/core': 1.1.6 + '@shikijs/core': 1.1.7 twoslash: 0.2.4(typescript@5.3.3) transitivePeerDependencies: - supports-color @@ -3485,6 +3522,12 @@ packages: resolution: {integrity: sha512-UP28RddqY8xcU0SCEp9YKutQICXpaAq9N8U2klqF5hegGha7KzTOL8EdhIIV3bOSGBzjEpN9bU/d+nNZBdJYVw==} dev: false + /@types/hast@3.0.4: + resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} + dependencies: + '@types/unist': 3.0.2 + dev: false + /@types/html-minifier-terser@6.1.0: resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} dev: false @@ -3563,6 +3606,12 @@ packages: '@types/unist': 2.0.10 dev: true + /@types/mdast@4.0.3: + resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + dependencies: + '@types/unist': 3.0.2 + dev: false + /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} @@ -3665,6 +3714,10 @@ packages: resolution: {integrity: sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==} dev: true + /@types/unist@3.0.2: + resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + dev: false + /@types/web-bluetooth@0.0.20: resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} dev: false @@ -3934,7 +3987,6 @@ packages: /@ungap/structured-clone@1.2.0: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - dev: true /@vercel/nft@0.23.0(supports-color@9.2.2): resolution: {integrity: sha512-1iuPjyltiPqyZrvc/bW1CyICRdng8bVhpJT8MsIXV7Wj+mRFyJs9krsHbVy2pZwu7BMAgforQsT5TCY1JoBDxw==} @@ -3990,6 +4042,18 @@ packages: vue: 3.4.19(typescript@5.3.3) dev: false + /@volar/language-core@1.11.1: + resolution: {integrity: sha512-dOcNn3i9GgZAcJt43wuaEykSluAuOkQgzni1cuxLxTV0nJKanQztp7FxyswdRILaKH+P2XZMPRp2S4MV/pElCw==} + dependencies: + '@volar/source-map': 1.11.1 + dev: false + + /@volar/source-map@1.11.1: + resolution: {integrity: sha512-hJnOnwZ4+WT5iupLRnuzbULZ42L7BWWPMmruzwtLhJfpDVoZLjNBxHDi2sY2bgZXCKlpU5XcsMFoYrsQmPhfZg==} + dependencies: + muggle-string: 0.3.1 + dev: false + /@vue/compiler-core@3.4.19: resolution: {integrity: sha512-gj81785z0JNzRcU0Mq98E56e4ltO1yf8k5PQ+tV/7YHnbZkrM0fyFyuttnN8ngJZjbpofWE/m4qjKBiLl8Ju4w==} dependencies: @@ -4032,6 +4096,26 @@ packages: resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==} dev: false + /@vue/language-core@1.8.27(typescript@5.3.3): + resolution: {integrity: sha512-L8Kc27VdQserNaCUNiSFdDl9LWT24ly8Hpwf1ECy3aFb9m6bDhBGQYOujDm21N7EW3moKIOKEanQwe1q5BK+mA==} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@volar/language-core': 1.11.1 + '@volar/source-map': 1.11.1 + '@vue/compiler-dom': 3.4.19 + '@vue/shared': 3.4.19 + computeds: 0.0.1 + minimatch: 9.0.3 + muggle-string: 0.3.1 + path-browserify: 1.0.1 + typescript: 5.3.3 + vue-template-compiler: 2.7.16 + dev: false + /@vue/reactivity@3.4.19: resolution: {integrity: sha512-+VcwrQvLZgEclGZRHx4O2XhyEEcKaBi50WbxdVItEezUf4fqRh838Ix6amWTdX0CNb/b6t3Gkz3eOebfcSt+UA==} dependencies: @@ -5529,6 +5613,10 @@ packages: resolution: {integrity: sha512-mtj5ur2FFPZcCEpXFy8ADXbDACuNFXg6mxVDqp7tqooX6l3zwm+d8EPoeOSIFRDvHs8qu7/SLFOGniULkcH2iA==} dev: false + /ccount@2.0.1: + resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + dev: false + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -5561,6 +5649,10 @@ packages: resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} dev: true + /character-entities@2.0.2: + resolution: {integrity: sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==} + dev: false + /character-reference-invalid@1.1.4: resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} dev: true @@ -5997,6 +6089,10 @@ packages: - supports-color dev: false + /computeds@0.0.1: + resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==} + dev: false + /concat-map@0.0.1: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} @@ -6737,6 +6833,10 @@ packages: resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} dev: false + /de-indent@1.0.2: + resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==} + dev: false + /debounce@2.0.0: resolution: {integrity: sha512-xRetU6gL1VJbs85Mc4FoEGSjQxzpdxRyFhe3lmWFyy2EzydIcD4xzUvRJMD+NPDfMwKNhxa3PvsIOU32luIWeA==} engines: {node: '>=18'} @@ -6791,6 +6891,12 @@ packages: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} engines: {node: '>=0.10.0'} + /decode-named-character-reference@1.0.2: + resolution: {integrity: sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg==} + dependencies: + character-entities: 2.0.2 + dev: false + /decode-uri-component@0.2.0: resolution: {integrity: sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og==} engines: {node: '>=0.10'} @@ -6913,6 +7019,11 @@ packages: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} dev: false + /dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + dev: false + /destr@2.0.2: resolution: {integrity: sha512-65AlobnZMiCET00KaFFjUefxDX0khFA/E4myqZ7a6Sq1yZtR8+FVIvilVX66vF2uobSumxooYZChiRPCKNqhmg==} @@ -7014,6 +7125,12 @@ packages: - supports-color dev: false + /devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dependencies: + dequal: 2.0.3 + dev: false + /diff@4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} @@ -8426,6 +8543,20 @@ packages: resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} dev: true + /floating-vue@5.2.2(vue@3.4.19): + resolution: {integrity: sha512-afW+h2CFafo+7Y9Lvw/xsqjaQlKLdJV7h1fCHfcYQ1C4SVMlu7OAekqWgu5d4SgvkBVU0pVpLlVsrSTBURFRkg==} + peerDependencies: + '@nuxt/kit': ^3.2.0 + vue: ^3.2.0 + peerDependenciesMeta: + '@nuxt/kit': + optional: true + dependencies: + '@floating-ui/dom': 1.1.1 + vue: 3.4.19(typescript@5.3.3) + vue-resize: 2.0.0-alpha.1(vue@3.4.19) + dev: false + /flush-write-stream@2.0.0: resolution: {integrity: sha512-uXClqPxT4xW0lcdSBheb2ObVU+kuqUk3Jk64EwieirEXZx9XUrVwp/JuBfKAWaM4T5Td/VL7QLDWPXp/MvGm/g==} dependencies: @@ -10576,6 +10707,10 @@ packages: triple-beam: 1.3.0 dev: false + /longest-streak@3.1.0: + resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} + dev: false + /longest@2.0.1: resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} engines: {node: '>=0.10.0'} @@ -10701,6 +10836,10 @@ packages: uc.micro: 2.0.0 dev: false + /markdown-table@3.0.3: + resolution: {integrity: sha512-Z1NL3Tb1M9wH4XESsCDEksWoKTdlUafKc4pt0GRwjUyXaCFZ+dc3g2erqB6zm3szA2IUSi7VnPI+o/9jnxh9hw==} + dev: false + /mathml-tag-names@2.1.3: resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} dev: true @@ -10725,6 +10864,15 @@ packages: blueimp-md5: 2.19.0 dev: false + /mdast-util-find-and-replace@3.0.1: + resolution: {integrity: sha512-SG21kZHGC3XRTSUhtofZkBzZTJNM5ecCi0SK2IMKmSXR8vO3peL+kb1O0z7Zl83jKtutG4k5Wv/W7V3/YHvzPA==} + dependencies: + '@types/mdast': 4.0.3 + escape-string-regexp: 5.0.0 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + /mdast-util-from-markdown@0.8.5: resolution: {integrity: sha512-2hkTXtYYnr+NubD/g6KGBS/0mFmBcifAsI0yIWRiRo0PjVs6SSOSOdtzbp6kSGnShDN6G5aWZpKQ2lWRy27mWQ==} dependencies: @@ -10737,10 +10885,138 @@ packages: - supports-color dev: true + /mdast-util-from-markdown@2.0.0: + resolution: {integrity: sha512-n7MTOr/z+8NAX/wmhhDji8O3bRvPTV/U0oTCaZJkjhPSKTPhS3xufVhKGF8s1pJ7Ox4QgoIU7KHseh09S+9rTA==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + mdast-util-to-string: 4.0.0 + micromark: 4.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-decode-string: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + unist-util-stringify-position: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-autolink-literal@2.0.0: + resolution: {integrity: sha512-FyzMsduZZHSc3i0Px3PQcBT4WJY/X/RCtEJKuybiC6sjPqLv7h1yqAkmILZtuxMSsUyaLUWNp71+vQH2zqp5cg==} + dependencies: + '@types/mdast': 4.0.3 + ccount: 2.0.1 + devlop: 1.1.0 + mdast-util-find-and-replace: 3.0.1 + micromark-util-character: 2.1.0 + dev: false + + /mdast-util-gfm-footnote@2.0.0: + resolution: {integrity: sha512-5jOT2boTSVkMnQ7LTrd6n/18kqwjmuYqo7JUPe+tRCY6O7dAuTFMtTPauYYrMPpox9hlN0uOx/FL8XvEfG9/mQ==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + micromark-util-normalize-identifier: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-strikethrough@2.0.0: + resolution: {integrity: sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==} + dependencies: + '@types/mdast': 4.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-table@2.0.0: + resolution: {integrity: sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + markdown-table: 3.0.3 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm-task-list-item@2.0.0: + resolution: {integrity: sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==} + dependencies: + '@types/mdast': 4.0.3 + devlop: 1.1.0 + mdast-util-from-markdown: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-gfm@3.0.0: + resolution: {integrity: sha512-dgQEX5Amaq+DuUqf26jJqSK9qgixgd6rYDHAv4aTBuA92cTknZlKpPfa86Z/s8Dj8xsAQpFfBmPUHWJBWqS4Bw==} + dependencies: + mdast-util-from-markdown: 2.0.0 + mdast-util-gfm-autolink-literal: 2.0.0 + mdast-util-gfm-footnote: 2.0.0 + mdast-util-gfm-strikethrough: 2.0.0 + mdast-util-gfm-table: 2.0.0 + mdast-util-gfm-task-list-item: 2.0.0 + mdast-util-to-markdown: 2.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-phrasing@4.1.0: + resolution: {integrity: sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==} + dependencies: + '@types/mdast': 4.0.3 + unist-util-is: 6.0.0 + dev: false + + /mdast-util-to-hast@13.1.0: + resolution: {integrity: sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==} + dependencies: + '@types/hast': 3.0.4 + '@types/mdast': 4.0.3 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + dev: false + + /mdast-util-to-markdown@2.1.0: + resolution: {integrity: sha512-SR2VnIEdVNCJbP6y7kVTJgPLifdr8WEU440fQec7qHoHOUz/oJ2jmNRqdDQ3rbiStOXb2mCDGTuwsK5OPUgYlQ==} + dependencies: + '@types/mdast': 4.0.3 + '@types/unist': 3.0.2 + longest-streak: 3.1.0 + mdast-util-phrasing: 4.1.0 + mdast-util-to-string: 4.0.0 + micromark-util-decode-string: 2.0.0 + unist-util-visit: 5.0.0 + zwitch: 2.0.4 + dev: false + /mdast-util-to-string@2.0.0: resolution: {integrity: sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w==} dev: true + /mdast-util-to-string@4.0.0: + resolution: {integrity: sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==} + dependencies: + '@types/mdast': 4.0.3 + dev: false + /mdn-data@2.0.28: resolution: {integrity: sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==} dev: false @@ -10833,6 +11109,157 @@ packages: resolution: {integrity: sha512-2tzWP1w2Hh+r7kCYa4f//jpBEA6dAueiuLco38NxfjF9Py3KCCI7wVOTdCvOhmTC043t+ulclVBdl3v+s+UJIQ==} dev: false + /micromark-core-commonmark@2.0.0: + resolution: {integrity: sha512-jThOz/pVmAYUtkroV3D5c1osFXAMv9e0ypGDOIZuCeAe91/sD6BoE2Sjzt30yuXtwOYUmySOhMas/PVyh02itA==} + dependencies: + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-factory-destination: 2.0.0 + micromark-factory-label: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-factory-title: 2.0.0 + micromark-factory-whitespace: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-classify-character: 2.0.0 + micromark-util-html-tag-name: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-destination@2.0.0: + resolution: {integrity: sha512-j9DGrQLm/Uhl2tCzcbLhy5kXsgkHUrjJHg4fFAeoMRwJmJerT9aw4FEhIbZStWN8A3qMwOp1uzHr4UL8AInxtA==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-label@2.0.0: + resolution: {integrity: sha512-RR3i96ohZGde//4WSe/dJsxOX6vxIg9TimLAS3i4EhBAFx8Sm5SmqVfR8E87DPSR31nEAjZfbt91OMZWcNgdZw==} + dependencies: + devlop: 1.1.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-space@2.0.0: + resolution: {integrity: sha512-TKr+LIDX2pkBJXFLzpyPyljzYK3MtmllMUMODTQJIUfDGncESaqB90db9IAUcz4AZAJFdd8U9zOp9ty1458rxg==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-title@2.0.0: + resolution: {integrity: sha512-jY8CSxmpWLOxS+t8W+FG3Xigc0RDQA9bKMY/EwILvsesiRniiVMejYTE4wumNc2f4UbAa4WsHqe3J1QS1sli+A==} + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-factory-whitespace@2.0.0: + resolution: {integrity: sha512-28kbwaBjc5yAI1XadbdPYHX/eDnqaUFVikLwrO7FDnKG7lpgxnvk/XGRhX/PN0mOZ+dBSZ+LgunHS+6tYQAzhA==} + dependencies: + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-character@2.1.0: + resolution: {integrity: sha512-KvOVV+X1yLBfs9dCBSopq/+G1PcgT3lAK07mC4BzXi5E7ahzMAF8oIupDDJ6mievI6F+lAATkbQQlQixJfT3aQ==} + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-chunked@2.0.0: + resolution: {integrity: sha512-anK8SWmNphkXdaKgz5hJvGa7l00qmcaUQoMYsBwDlSKFKjc6gjGXPDw3FNL3Nbwq5L8gE+RCbGqTw49FK5Qyvg==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-classify-character@2.0.0: + resolution: {integrity: sha512-S0ze2R9GH+fu41FA7pbSqNWObo/kzwf8rN/+IGlW/4tC6oACOs8B++bh+i9bVyNnwCcuksbFwsBme5OCKXCwIw==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-combine-extensions@2.0.0: + resolution: {integrity: sha512-vZZio48k7ON0fVS3CUgFatWHoKbbLTK/rT7pzpJ4Bjp5JjkZeasRfrS9wsBdDJK2cJLHMckXZdzPSSr1B8a4oQ==} + dependencies: + micromark-util-chunked: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-decode-numeric-character-reference@2.0.1: + resolution: {integrity: sha512-bmkNc7z8Wn6kgjZmVHOX3SowGmVdhYS7yBpMnuMnPzDq/6xwVA604DuOXMZTO1lvq01g+Adfa0pE2UKGlxL1XQ==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-decode-string@2.0.0: + resolution: {integrity: sha512-r4Sc6leeUTn3P6gk20aFMj2ntPwn6qpDZqWvYmAG6NgvFTIlj4WtrAudLi65qYoaGdXYViXYw2pkmn7QnIFasA==} + dependencies: + decode-named-character-reference: 1.0.2 + micromark-util-character: 2.1.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + dev: false + + /micromark-util-html-tag-name@2.0.0: + resolution: {integrity: sha512-xNn4Pqkj2puRhKdKTm8t1YHC/BAjx6CEwRFXntTaRf/x16aqka6ouVoutm+QdkISTlT7e2zU7U4ZdlDLJd2Mcw==} + dev: false + + /micromark-util-normalize-identifier@2.0.0: + resolution: {integrity: sha512-2xhYT0sfo85FMrUPtHcPo2rrp1lwbDEEzpx7jiH2xXJLqBuy4H0GgXk5ToU8IEwoROtXuL8ND0ttVa4rNqYK3w==} + dependencies: + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-resolve-all@2.0.0: + resolution: {integrity: sha512-6KU6qO7DZ7GJkaCgwBNtplXCvGkJToU86ybBAUdavvgsCiG8lSSvYxr9MhwmQ+udpzywHsl4RpGJsYWG1pDOcA==} + dependencies: + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + dependencies: + micromark-util-character: 2.1.0 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + dev: false + + /micromark-util-subtokenize@2.0.0: + resolution: {integrity: sha512-vc93L1t+gpR3p8jxeVdaYlbV2jTYteDje19rNSS/H5dlhxUYll5Fy6vJ2cDwP8RnsXi818yGty1ayP55y3W6fg==} + dependencies: + devlop: 1.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: false + + /micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + dev: false + + /micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + dev: false + /micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} dependencies: @@ -10842,6 +11269,30 @@ packages: - supports-color dev: true + /micromark@4.0.0: + resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} + dependencies: + '@types/debug': 4.1.12 + debug: 4.3.4(supports-color@9.2.2) + decode-named-character-reference: 1.0.2 + devlop: 1.1.0 + micromark-core-commonmark: 2.0.0 + micromark-factory-space: 2.0.0 + micromark-util-character: 2.1.0 + micromark-util-chunked: 2.0.0 + micromark-util-combine-extensions: 2.0.0 + micromark-util-decode-numeric-character-reference: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-normalize-identifier: 2.0.0 + micromark-util-resolve-all: 2.0.0 + micromark-util-sanitize-uri: 2.0.0 + micromark-util-subtokenize: 2.0.0 + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + transitivePeerDependencies: + - supports-color + dev: false + /micromatch@3.1.10: resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} engines: {node: '>=0.10.0'} @@ -11069,6 +11520,10 @@ packages: /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + /muggle-string@0.3.1: + resolution: {integrity: sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==} + dev: false + /multicast-dns@7.2.5: resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} hasBin: true @@ -12029,6 +12484,10 @@ packages: engines: {node: '>=0.10.0'} dev: false + /path-browserify@1.0.1: + resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} + dev: false + /path-exists@3.0.0: resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} engines: {node: '>=4'} @@ -13337,10 +13796,10 @@ packages: /shell-quote@1.8.1: resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} - /shiki@1.1.6: - resolution: {integrity: sha512-j4pcpvaQWHb42cHeV+W6P+X/VcK7Y2ctvEham6zB8wsuRQroT6cEMIkiUmBU2Nqg2qnHZDH6ZyRdVldcy0l6xw==} + /shiki@1.1.7: + resolution: {integrity: sha512-9kUTMjZtcPH3i7vHunA6EraTPpPOITYTdA5uMrvsJRexktqP0s7P3s9HVK80b4pP42FRVe03D7fT3NmJv2yYhw==} dependencies: - '@shikijs/core': 1.1.6 + '@shikijs/core': 1.1.7 dev: false /side-channel@1.0.4: @@ -14364,6 +14823,10 @@ packages: hasBin: true dev: true + /trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: false + /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} @@ -14458,6 +14921,19 @@ packages: resolution: {integrity: sha512-AEGTJj4mFGfvQc/M6qi0+s82Zq+mxLcjWZU+EUHGG8LQElyHDs+uDR+/3+m1l+WP7WL+QmWrVzFXgFX+hBg+bg==} dev: false + /twoslash-vue@0.2.4(typescript@5.3.3): + resolution: {integrity: sha512-AIcsYRSxn5WuZC+dD7/n99s1UEY6e5IljoGL3YijQvI/pylgsKk5sWXptp5NrRTH0srBLXoeVpE1re1Eo6eiJw==} + peerDependencies: + typescript: '*' + dependencies: + '@vue/language-core': 1.8.27(typescript@5.3.3) + twoslash: 0.2.4(typescript@5.3.3) + twoslash-protocol: 0.2.4 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: false + /twoslash@0.2.4(typescript@5.3.3): resolution: {integrity: sha512-hc3y11BjLHP4kV37TR6lUKksxpZp0LQi9kCy95ka6qobye/gV49PqXZIuWlRaRVGNvp4AJBMg8aiwkp0M8x/nQ==} peerDependencies: @@ -14621,12 +15097,45 @@ packages: crypto-random-string: 4.0.0 dev: false + /unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + dependencies: + '@types/unist': 3.0.2 + dev: false + /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: '@types/unist': 2.0.10 dev: true + /unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + dependencies: + '@types/unist': 3.0.2 + dev: false + + /unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + dev: false + + /unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: false + /universal-user-agent@6.0.0: resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} dev: false @@ -14844,6 +15353,21 @@ packages: engines: {node: '>= 0.8'} dev: false + /vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + dev: false + + /vfile@6.0.1: + resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + dev: false + /vite@5.1.3(@types/node@20.9.1)(sass@1.71.1): resolution: {integrity: sha512-UfmUD36DKkqhi/F75RrxvPpry+9+tTkrXfMNZD+SboZqBCMsxKtO52XeGzzuh7ioz+Eo/SYDBbdb0Z7vgcDJew==} engines: {node: ^18.0.0 || >=20.0.0} @@ -14970,6 +15494,14 @@ packages: webpack: 5.90.2 dev: false + /vue-resize@2.0.0-alpha.1(vue@3.4.19): + resolution: {integrity: sha512-7+iqOueLU7uc9NrMfrzbG8hwMqchfVfSzpVlCMeJQe4pyibqyoifDNbKTZvwxZKDvGkB+PdFeKvnGZMoEb8esg==} + peerDependencies: + vue: ^3.0.0 + dependencies: + vue: 3.4.19(typescript@5.3.3) + dev: false + /vue-router@4.2.5(vue@3.4.19): resolution: {integrity: sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==} peerDependencies: @@ -14979,6 +15511,13 @@ packages: vue: 3.4.19(typescript@5.3.3) dev: false + /vue-template-compiler@2.7.16: + resolution: {integrity: sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==} + dependencies: + de-indent: 1.0.2 + he: 1.2.0 + dev: false + /vue@3.4.19(typescript@5.3.3): resolution: {integrity: sha512-W/7Fc9KUkajFU8dBeDluM4sRGc/aa4YJnOYck8dkjgZoXtVsn3OeTGni66FV1l3+nvPA7VBFYtPioaGKUmEADw==} peerDependencies: @@ -15645,3 +16184,7 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} dev: false + + /zwitch@2.0.4: + resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} + dev: false diff --git a/theme/src/client/styles/twoslash.scss b/theme/src/client/styles/twoslash.scss index d8981a50..7c46df32 100644 --- a/theme/src/client/styles/twoslash.scss +++ b/theme/src/client/styles/twoslash.scss @@ -260,3 +260,139 @@ div[class*="language-"].line-numbers-mode:has(> .twoslash) { background-color: var(--twoslash-tag-annotate-bg); border-left: 3px solid var(--twoslash-tag-annotate-color); } + +/* ========== floating vue ================== */ + +:root { + --twoslash-popup-bg: var(--vp-c-bg, inherit); + --twoslash-popup-color: var(--vp-c-text-1); + --twoslash-docs-color: var(--vp-c-text-1); + --twoslash-docs-font: var(--vp-font-family-base); + --twoslash-code-font: var(--vp-font-family-mono); + --twoslash-code-size: var(--vp-code-font-size); + --twoslash-underline-color: #8888; + --twoslash-border-color: var(--vp-c-border); + --twoslash-cursor-color: var(--vp-c-brand-1); + --twoslash-matched-color: var(--vp-c-brand-1); + --twoslash-unmatched-color: var(--vp-c-text-2); +} + +.v-popper--theme-twoslash { + z-index: calc(var(--vp-z-index-local-nav) - 1); +} + +.v-popper--theme-twoslash .v-popper__inner { + color: var(--twoslash-popup-color); + background: var(--twoslash-popup-bg); + border-color: var(--twoslash-border-color); +} + +.v-popper--theme-twoslash .v-popper__arrow-outer { + border-color: var(--twoslash-border-color); +} + +.v-popper--theme-twoslash .v-popper__arrow-inner { + border-color: var(--twoslash-popup-bg); +} + +.twoslash-popup-container { + transform: translateY(1.5em); +} + +.twoslash-query-presisted .twoslash-popup-container { + transform: translateY(1.8em); +} + +.twoslash .v-popper { + display: inline-block; +} + +.twoslash-completion-list .twoslash-completions-icon { + color: var(--twoslash-unmatched-color) !important; +} + +.twoslash-floating .twoslash-popup-code { + display: block; + width: fit-content; + min-width: 100%; + max-width: 600px; + padding: 6px 12px; + font-size: var(--twoslash-code-size); + line-height: var(--vp-code-line-height); + white-space: pre-wrap; + transition: color 0.5s; +} + +.twoslash-floating .twoslash-popup-docs, +.twoslash-floating .twoslash-popup-error { + max-width: 700px; + max-height: 500px; + padding: 0 12px !important; + overflow: hidden auto; + font-family: var(--twoslash-docs-font); + font-size: 0.9em; + text-wrap: balance; +} + +.twoslash-floating .twoslash-popup-docs { + color: var(--twoslash-docs-color); + border-top: 1px solid var(--twoslash-border-color); +} + +.twoslash-floating .twoslash-popup-error { + color: var(--twoslash-error-color); +} + +.twoslash-floating .twoslash-popup-error.twoslash-error-level-warning { + color: var(--twoslash-warn-color); +} + +.twoslash-floating .twoslash-popup-docs p, +.twoslash-floating .twoslash-popup-error p { + padding: 6px 0; + margin: 0; + text-wrap: balance; +} + +.twoslash-floating .twoslash-popup-docs pre .twoslash-floating .twoslash-popup-error pre { + padding: 12px; + margin: 6px -2px; + overflow-x: auto; + background-color: var(--vp-code-block-bg); + border-radius: 8px; +} + +.twoslash-floating .twoslash-popup-docs-tags { + display: flex; + flex-direction: column; + padding: 8px 12px !important; +} + +.twoslash-floating .twoslash-popup-docs-tags .twoslash-popup-docs-tag-name { + margin-right: 0.5em; + font-family: var(--twoslash-code-font); + color: var(--twoslash-unmatched-color); +} + +.twoslash-completion-cursor { + display: inline-block; + width: 2px; + height: 1.2em; + margin-bottom: -0.2em; + user-select: none; + background: var(--twoslash-cursor-color); +} + +.twoslash-floating.twoslash-completion .v-popper__arrow-container { + display: none; +} + +.twoslash-floating.twoslash-completion .twoslash-completion-list { + padding: 6px; + font-family: var(--twoslash-code-font); + font-size: var(--twoslash-code-size) !important; +} + +.twoslash-floating.twoslash-completion .twoslash-completion-list li { + padding: 3px 0; +}