diff --git a/demo/starter/slides.md b/demo/starter/slides.md index 59c6c86c5a..56cce38de5 100644 --- a/demo/starter/slides.md +++ b/demo/starter/slides.md @@ -20,6 +20,9 @@ drawings: transition: slide-left # enable MDC Syntax: https://sli.dev/features/mdc mdc: true +# open graph +# seoMeta: +# ogImage: https://cover.sli.dev --- # Welcome to Slidev diff --git a/docs/custom/index.md b/docs/custom/index.md index a546109b58..2022e93152 100644 --- a/docs/custom/index.md +++ b/docs/custom/index.md @@ -108,6 +108,19 @@ drawings: htmlAttrs: dir: ltr lang: en + +# SEO meta tags +seoMeta: + ogTitle: Slidev Starter Template + ogDescription: Presentation slides for developers + ogImage: https://cover.sli.dev + ogUrl: https://example.com + twitterCard: summary_large_image + twitterTitle: Slidev Starter Template + twitterDescription: Presentation slides for developers + twitterImage: https://cover.sli.dev + twitterSite: username + twitterUrl: https://example.com --- ``` diff --git a/docs/vite.config.ts b/docs/vite.config.ts index 5034513157..c1d5e14e4c 100644 --- a/docs/vite.config.ts +++ b/docs/vite.config.ts @@ -23,7 +23,7 @@ export default defineConfig({ llmstxt({ ignoreFiles: [ 'index.md', - 'README.md' + 'README.md', ], }), Components({ diff --git a/packages/client/constants.ts b/packages/client/constants.ts index 045e773e2a..e1e5c05ed7 100644 --- a/packages/client/constants.ts +++ b/packages/client/constants.ts @@ -83,4 +83,5 @@ export const HEADMATTER_FIELDS = [ 'mdc', 'contextMenu', 'wakeLock', + 'seoMeta', ] diff --git a/packages/parser/src/config.ts b/packages/parser/src/config.ts index 3e16e63784..52fbb03da8 100644 --- a/packages/parser/src/config.ts +++ b/packages/parser/src/config.ts @@ -44,6 +44,7 @@ export function getDefaultConfig(): SlidevConfig { wakeLock: true, remote: false, mdc: false, + seoMeta: {}, } } diff --git a/packages/slidev/node/cli.ts b/packages/slidev/node/cli.ts index 21c6d300ce..13b27ab99c 100644 --- a/packages/slidev/node/cli.ts +++ b/packages/slidev/node/cli.ts @@ -30,6 +30,7 @@ const CONFIG_RESTART_FIELDS: (keyof SlidevConfig)[] = [ 'mdc', 'editor', 'theme', + 'seoMeta', ] /** diff --git a/packages/slidev/node/options.ts b/packages/slidev/node/options.ts index 80e74e7663..4b352c745b 100644 --- a/packages/slidev/node/options.ts +++ b/packages/slidev/node/options.ts @@ -84,7 +84,7 @@ export async function createDataUtils(resolved: Omit monacoTypesIgnorePackagesMatches.some(i => i.test(pkg)), diff --git a/packages/slidev/node/setups/indexHtml.ts b/packages/slidev/node/setups/indexHtml.ts index 4832237408..3e660780b7 100644 --- a/packages/slidev/node/setups/indexHtml.ts +++ b/packages/slidev/node/setups/indexHtml.ts @@ -1,9 +1,11 @@ -import type { ResolvedSlidevOptions } from '@slidev/types' +import type { ResolvedSlidevOptions, SeoMeta } from '@slidev/types' +import type { ResolvableLink } from 'unhead/types' import { existsSync, readFileSync } from 'node:fs' import { join } from 'node:path' import { slash } from '@antfu/utils' import { white, yellow } from 'ansis' import { escapeHtml } from 'markdown-it/lib/common/utils.mjs' +import { createHead, transformHtmlTemplate } from 'unhead/server' import { version } from '../../package.json' import { getSlideTitle } from '../commands/shared' import { toAtFS } from '../resolver' @@ -13,22 +15,11 @@ function toAttrValue(unsafe: unknown) { return JSON.stringify(escapeHtml(String(unsafe))) } -export default function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data, base }: Omit): string { +export default async function setupIndexHtml({ mode, entry, clientRoot, userRoot, roots, data, base }: Omit): Promise { let main = readFileSync(join(clientRoot, 'index.html'), 'utf-8') let head = '' let body = '' - const { info, author, keywords } = data.headmatter - head += [ - ``, - mode === 'dev' && ``, - ``, - `${getSlideTitle(data)}`, - info && ``, - author && ``, - keywords && ``, - ].filter(Boolean).join('\n') - for (const root of roots) { const path = join(root, 'index.html') if (!existsSync(path)) @@ -46,19 +37,55 @@ export default function setupIndexHtml({ mode, entry, clientRoot, userRoot, root body += `\n${(index.match(/([\s\S]*?)<\/body>/i)?.[1] || '').trim()}` } - if (data.features.tweet) + if (data.features.tweet) { body += '\n' + } + const webFontsLink: ResolvableLink[] = [] if (data.config.fonts.webfonts.length) { const { provider } = data.config.fonts - if (provider === 'google') - head += `\n` - else if (provider === 'coollabs') - head += `\n` + if (provider === 'google') { + webFontsLink.push({ rel: 'stylesheet', href: generateGoogleFontsUrl(data.config.fonts), type: 'text/css' }) + } + else if (provider === 'coollabs') { + webFontsLink.push({ rel: 'stylesheet', href: generateCoollabsFontsUrl(data.config.fonts), type: 'text/css' }) + } } - if (data.headmatter.lang) - main = main.replace('', ``) + const { info, author, keywords } = data.headmatter + const seoMeta = (data.headmatter.seoMeta ?? {}) as SeoMeta + + const title = getSlideTitle(data) + const description = info ? toAttrValue(info) : null + const unhead = createHead({ + init: [ + { + htmlAttrs: { lang: (data.headmatter.lang as string | undefined) ?? 'en' }, + title, + link: [ + { rel: 'icon', href: data.config.favicon }, + ...webFontsLink, + ], + meta: [ + { property: 'slidev:version', content: version }, + { charset: 'slidev:entry', content: mode === 'dev' && slash(entry) }, + { name: 'description', content: description }, + { name: 'author', content: author ? toAttrValue(author) : null }, + { name: 'keywords', content: keywords ? toAttrValue(Array.isArray(keywords) ? keywords.join(', ') : keywords) : null }, + { property: 'og:title', content: seoMeta.ogTitle || title }, + { property: 'og:description', content: seoMeta.ogDescription || description }, + { property: 'og:image', content: seoMeta.ogImage }, + { property: 'og:url', content: seoMeta.ogUrl }, + { property: 'twitter:card', content: seoMeta.twitterCard }, + { property: 'twitter:site', content: seoMeta.twitterSite }, + { property: 'twitter:title', content: seoMeta.twitterTitle }, + { property: 'twitter:description', content: seoMeta.twitterDescription }, + { property: 'twitter:image', content: seoMeta.twitterImage }, + { property: 'twitter:url', content: seoMeta.twitterUrl }, + ], + }, + ], + }) const baseInDev = mode === 'dev' && base ? base.slice(0, -1) : '' main = main @@ -66,5 +93,7 @@ export default function setupIndexHtml({ mode, entry, clientRoot, userRoot, root .replace('', head) .replace('', body) - return main + const html = await transformHtmlTemplate(unhead, main) + + return html } diff --git a/packages/slidev/package.json b/packages/slidev/package.json index 39f34722e0..9f702fc5d2 100644 --- a/packages/slidev/package.json +++ b/packages/slidev/package.json @@ -102,6 +102,7 @@ "sirv": "catalog:", "source-map-js": "catalog:", "typescript": "catalog:", + "unhead": "catalog:", "unocss": "catalog:", "unplugin-icons": "catalog:", "unplugin-vue-components": "catalog:", diff --git a/packages/types/src/frontmatter.ts b/packages/types/src/frontmatter.ts index 07f48652e9..30ddb35565 100644 --- a/packages/types/src/frontmatter.ts +++ b/packages/types/src/frontmatter.ts @@ -255,6 +255,12 @@ export interface HeadmatterConfig extends TransitionOptions { * @default [] */ monacoRunAdditionalDeps?: string[] + /** + * Seo meta tags settings + * + * @default {} + */ + seoMeta?: SeoMeta } export interface Frontmatter extends TransitionOptions { @@ -454,3 +460,19 @@ export interface TransitionGroupProps { leaveActiveClass?: string leaveToClass?: string } + +/** + * The following type should map to unhead MataFlat type + */ +export interface SeoMeta { + ogTitle?: string + ogDescription?: string + ogImage?: string + ogUrl?: string + twitterCard?: 'summary' | 'summary_large_image' | 'app' | 'player' + twitterSite?: string + twitterTitle?: string + twitterDescription?: string + twitterImage?: string + twitterUrl?: string +} diff --git a/packages/vscode/schema/headmatter.json b/packages/vscode/schema/headmatter.json index 20308be8aa..8907ee4739 100644 --- a/packages/vscode/schema/headmatter.json +++ b/packages/vscode/schema/headmatter.json @@ -484,6 +484,12 @@ "markdownDescription": "Additional local modules to load as dependencies of monaco runnable", "default": [] }, + "seoMeta": { + "$ref": "#/definitions/SeoMeta", + "description": "Seo meta tags settings", + "markdownDescription": "Seo meta tags settings", + "default": {} + }, "defaults": { "$ref": "#/definitions/Frontmatter", "description": "Default frontmatter options applied to all slides", @@ -777,6 +783,49 @@ } } }, + "SeoMeta": { + "type": "object", + "properties": { + "ogTitle": { + "type": "string" + }, + "ogDescription": { + "type": "string" + }, + "ogImage": { + "type": "string" + }, + "ogUrl": { + "type": "string" + }, + "twitterCard": { + "type": "string", + "enum": [ + "summary", + "summary_large_image", + "app", + "player" + ] + }, + "twitterSite": { + "type": "string" + }, + "twitterTitle": { + "type": "string" + }, + "twitterDescription": { + "type": "string" + }, + "twitterImage": { + "type": "string" + }, + "twitterUrl": { + "type": "string" + } + }, + "description": "The following type should map to unhead MataFlat type", + "markdownDescription": "The following type should map to unhead MataFlat type" + }, "Frontmatter": { "type": "object", "properties": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d30dbb211d..15a5b5cc2b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -112,8 +112,8 @@ catalogs: specifier: ^0.9.7 version: 0.9.7 '@unhead/vue': - specifier: ^1.11.20 - version: 1.11.20 + specifier: ^2.0.2 + version: 2.0.2 '@unocss/extractor-mdc': specifier: ^66.0.0 version: 66.0.0 @@ -345,6 +345,9 @@ catalogs: typeit: specifier: 8.1.0 version: 8.1.0 + unhead: + specifier: ^2.0.2 + version: 2.0.2 unocss: specifier: ^66.0.0 version: 66.0.0 @@ -743,7 +746,7 @@ importers: version: 0.9.7(typescript@5.8.2) '@unhead/vue': specifier: 'catalog:' - version: 1.11.20(vue@3.5.13(typescript@5.8.2)) + version: 2.0.2(vue@3.5.13(typescript@5.8.2)) '@unocss/reset': specifier: 'catalog:' version: 66.0.0 @@ -921,7 +924,7 @@ importers: version: 3.7.0 debug: specifier: 'catalog:' - version: 4.4.0(supports-color@5.5.0) + version: 4.4.0(supports-color@8.1.1) fast-deep-equal: specifier: 'catalog:' version: 3.1.3 @@ -1024,6 +1027,9 @@ importers: typescript: specifier: ^5.8.2 version: 5.8.2 + unhead: + specifier: 'catalog:' + version: 2.0.2 unocss: specifier: 'catalog:' version: 66.0.0(postcss@8.5.3)(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)) @@ -2519,19 +2525,10 @@ packages: '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@unhead/dom@1.11.20': - resolution: {integrity: sha512-jgfGYdOH+xHJF/j8gudjsYu3oIjFyXhCWcgKaw3vQnT616gSqyqnGQGOItL+BQtQZACKNISwIfx5PuOtztMKLA==} - - '@unhead/schema@1.11.20': - resolution: {integrity: sha512-0zWykKAaJdm+/Y7yi/Yds20PrUK7XabLe9c3IRcjnwYmSWY6z0Cr19VIs3ozCj8P+GhR+/TI2mwtGlueCEYouA==} - - '@unhead/shared@1.11.20': - resolution: {integrity: sha512-1MOrBkGgkUXS+sOKz/DBh4U20DNoITlJwpmvSInxEUNhghSNb56S0RnaHRq0iHkhrO/cDgz2zvfdlRpoPLGI3w==} - - '@unhead/vue@1.11.20': - resolution: {integrity: sha512-sqQaLbwqY9TvLEGeq8Fd7+F2TIuV3nZ5ihVISHjWpAM3y7DwNWRU7NmT9+yYT+2/jw1Vjwdkv5/HvDnvCLrgmg==} + '@unhead/vue@2.0.2': + resolution: {integrity: sha512-pUGcbmPNCALOVWnQRtIjJ5ubNaZus3nHfCBDPEVwhbiLzeLF6wbhgTakwksZ1EegKNOZwRAkmVbV6i+23OYEUQ==} peerDependencies: - vue: '>=2.7 || >=3' + vue: '>=3.5.13' '@unocss/astro@66.0.0': resolution: {integrity: sha512-GBhXT6JPqXjDXoJZTXhySk83NgOt0UigChqrUUdG4x7Z+DVYkDBION8vZUJjw0OdIaxNQ4euGWu4GDsMF6gQQg==} @@ -5324,9 +5321,6 @@ packages: package-manager-detector@1.0.0: resolution: {integrity: sha512-7elnH+9zMsRo7aS72w6MeRugTpdRvInmEB4Kmm9BVvPw/SLG8gXUGQ+4wF0Mys0RSWPz0B9nuBbDe8vFeA2sfg==} - packrup@0.1.2: - resolution: {integrity: sha512-ZcKU7zrr5GlonoS9cxxrb5HVswGnyj6jQvwFBa6p5VFw7G71VAHcUKL5wyZSU/ECtPM/9gacWxy2KFQKt1gMNA==} - pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -6336,8 +6330,8 @@ packages: resolution: {integrity: sha512-U8uCCl2x9TK3WANvmBavymRzxbfFYG+tAu+fgx3zxQy3qdagQqBLwJVrdyO1TBfUXvfKveMKJZhpvUYoOjM+4g==} engines: {node: '>=18.17'} - unhead@1.11.20: - resolution: {integrity: sha512-3AsNQC0pjwlLqEYHLjtichGWankK8yqmocReITecmpB1H0aOabeESueyy+8X1gyJx4ftZVwo9hqQ4O3fPWffCA==} + unhead@2.0.2: + resolution: {integrity: sha512-1pcK/rSA70sezpdgmupQPd/yrul8pVFJRwMvWjEthbsXoTXMqjNQlV7NBXWeWt5r2uje1lZJsvRTHF7IvdOhcg==} unicorn-magic@0.1.0: resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} @@ -6832,9 +6826,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zhead@2.2.4: - resolution: {integrity: sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==} - zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -7125,7 +7116,7 @@ snapshots: '@babel/traverse': 7.25.9 '@babel/types': 7.26.0 convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -7262,7 +7253,7 @@ snapshots: '@babel/parser': 7.26.2 '@babel/template': 7.25.9 '@babel/types': 7.26.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -7547,7 +7538,7 @@ snapshots: '@eslint/config-array@0.19.2': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -7565,7 +7556,7 @@ snapshots: '@eslint/eslintrc@3.3.0': dependencies: ajv: 6.12.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) espree: 10.3.0 globals: 14.0.0 ignore: 5.3.2 @@ -7660,7 +7651,7 @@ snapshots: '@antfu/install-pkg': 1.0.0 '@antfu/utils': 8.1.0 '@iconify/types': 2.0.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) globals: 15.15.0 kolorist: 1.8.0 local-pkg: 1.1.1 @@ -8238,7 +8229,7 @@ snapshots: '@typescript-eslint/types': 8.26.0 '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) '@typescript-eslint/visitor-keys': 8.26.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.22.0(jiti@2.4.2) typescript: 5.8.2 transitivePeerDependencies: @@ -8253,7 +8244,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) '@typescript-eslint/utils': 8.26.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.22.0(jiti@2.4.2) ts-api-utils: 2.0.1(typescript@5.8.2) typescript: 5.8.2 @@ -8266,7 +8257,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.26.0 '@typescript-eslint/visitor-keys': 8.26.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -8298,34 +8289,17 @@ snapshots: '@typescript/vfs@1.6.1(typescript@5.8.2)': dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) typescript: 5.8.2 transitivePeerDependencies: - supports-color '@ungap/structured-clone@1.2.0': {} - '@unhead/dom@1.11.20': - dependencies: - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 - - '@unhead/schema@1.11.20': - dependencies: - hookable: 5.5.3 - zhead: 2.2.4 - - '@unhead/shared@1.11.20': + '@unhead/vue@2.0.2(vue@3.5.13(typescript@5.8.2))': dependencies: - '@unhead/schema': 1.11.20 - packrup: 0.1.2 - - '@unhead/vue@1.11.20(vue@3.5.13(typescript@5.8.2))': - dependencies: - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 hookable: 5.5.3 - unhead: 1.11.20 + unhead: 2.0.2 vue: 3.5.13(typescript@5.8.2) '@unocss/astro@66.0.0(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2))': @@ -8853,7 +8827,7 @@ snapshots: agent-base@7.1.1: dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -9935,7 +9909,7 @@ snapshots: '@types/doctrine': 0.0.9 '@typescript-eslint/scope-manager': 8.26.0 '@typescript-eslint/utils': 8.26.0(eslint@9.22.0(jiti@2.4.2))(typescript@5.8.2) - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) doctrine: 3.0.0 enhanced-resolve: 5.17.1 eslint: 9.22.0(jiti@2.4.2) @@ -9955,7 +9929,7 @@ snapshots: '@es-joy/jsdoccomment': 0.49.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint: 9.22.0(jiti@2.4.2) espree: 10.3.0 @@ -10025,7 +9999,7 @@ snapshots: eslint-plugin-toml@0.12.0(eslint@9.22.0(jiti@2.4.2)): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.22.0(jiti@2.4.2) eslint-compat-utils: 0.6.3(eslint@9.22.0(jiti@2.4.2)) lodash: 4.17.21 @@ -10072,7 +10046,7 @@ snapshots: eslint-plugin-yml@1.17.0(eslint@9.22.0(jiti@2.4.2)): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint: 9.22.0(jiti@2.4.2) eslint-compat-utils: 0.6.3(eslint@9.22.0(jiti@2.4.2)) @@ -10113,7 +10087,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 @@ -10579,7 +10553,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -10597,7 +10571,7 @@ snapshots: https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -10921,7 +10895,7 @@ snapshots: dependencies: chalk: 5.4.1 commander: 13.1.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) execa: 8.0.1 lilconfig: 3.1.3 listr2: 8.2.5 @@ -11391,7 +11365,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.1 @@ -11670,8 +11644,6 @@ snapshots: package-manager-detector@1.0.0: {} - packrup@0.1.2: {} - pako@1.0.11: {} parent-module@1.0.1: @@ -12597,7 +12569,7 @@ snapshots: cac: 6.7.14 chokidar: 4.0.3 consola: 3.4.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) esbuild: 0.25.0 joycon: 3.1.1 picocolors: 1.1.1 @@ -12708,11 +12680,8 @@ snapshots: undici@6.19.8: {} - unhead@1.11.20: + unhead@2.0.2: dependencies: - '@unhead/dom': 1.11.20 - '@unhead/schema': 1.11.20 - '@unhead/shared': 1.11.20 hookable: 5.5.3 unicorn-magic@0.1.0: {} @@ -12794,7 +12763,7 @@ snapshots: dependencies: '@antfu/install-pkg': 1.0.0 '@iconify/utils': 2.3.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) local-pkg: 1.1.1 unplugin: 2.2.0 optionalDependencies: @@ -12810,7 +12779,7 @@ snapshots: unplugin-vue-components@28.4.1(@babel/parser@7.26.2)(@nuxt/kit@3.13.0(rollup@4.35.0))(vue@3.5.13(typescript@5.8.2)): dependencies: chokidar: 3.6.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) local-pkg: 1.1.1 magic-string: 0.30.17 mlly: 1.7.4 @@ -12925,7 +12894,7 @@ snapshots: vite-node@3.0.8(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0): dependencies: cac: 6.7.14 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) es-module-lexer: 1.6.0 pathe: 2.0.3 vite: 6.2.1(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0) @@ -12946,7 +12915,7 @@ snapshots: vite-plugin-inspect@11.0.0(@nuxt/kit@3.13.0(rollup@4.35.0))(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0)): dependencies: ansis: 3.17.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) error-stack-parser-es: 1.0.5 ohash: 2.0.4 open: 10.1.0 @@ -12962,7 +12931,7 @@ snapshots: vite-plugin-remote-assets@1.0.0(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0)): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) magic-string: 0.30.17 node-fetch-native: 1.6.6 ohash: 1.1.4 @@ -12981,7 +12950,7 @@ snapshots: vite-plugin-vue-server-ref@1.0.0(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(tsx@4.19.2)(yaml@2.7.0))(vue@3.5.13(typescript@5.8.2)): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) klona: 2.0.6 mlly: 1.7.4 ufo: 1.5.4 @@ -13075,7 +13044,7 @@ snapshots: '@vitest/spy': 3.0.8 '@vitest/utils': 3.0.8 chai: 5.2.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) expect-type: 1.1.0 magic-string: 0.30.17 pathe: 2.0.3 @@ -13166,7 +13135,7 @@ snapshots: vue-eslint-parser@10.1.1(eslint@9.22.0(jiti@2.4.2)): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.22.0(jiti@2.4.2) eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 @@ -13326,8 +13295,6 @@ snapshots: yocto-queue@0.1.0: {} - zhead@2.2.4: {} - zwitch@2.0.4: {} zx@8.4.0: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 881e736050..3750aa60b0 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -44,7 +44,8 @@ catalog: '@types/vscode': ^1.89.0 '@types/yargs': ^17.0.33 '@typescript/ata': ^0.9.7 - '@unhead/vue': ^1.11.20 + '@unhead/vue': ^2.0.2 + unhead: ^2.0.2 '@unocss/extractor-mdc': ^66.0.0 '@unocss/reset': ^66.0.0 '@vitejs/plugin-vue': ^5.2.1