diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index cfb87e63..4a4ede5c 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -5,6 +5,18 @@ export default defineConfig({ title: 'VitePress', description: 'Vite & Vue powered static site generator.', lastUpdated: true, + head: ()=>[ + ['meta', { name: 'author', content: '‹div›RIOTS' }], + [ + 'meta', + { + name: 'keywords', + content: + 'designsystems, design-systems, react, vue, svelte, angular, webcomponent, webcomponents, web-component, web-components', + }, + ], + ], + //cleanUrls: true, themeConfig: { repo: 'vuejs/vitepress', diff --git a/src/client/app/composables/head.ts b/src/client/app/composables/head.ts index b1f92529..bd1871e3 100644 --- a/src/client/app/composables/head.ts +++ b/src/client/app/composables/head.ts @@ -1,5 +1,6 @@ import { watchEffect, Ref } from 'vue' import { HeadConfig, SiteData } from '../../shared' +import { processHead } from '../../../shared/shared' import { Route } from '../router' export function useUpdateHead(route: Route, siteDataByRouteRef: Ref) { @@ -68,7 +69,7 @@ export function useUpdateHead(route: Route, siteDataByRouteRef: Ref) { updateHeadTags([ // site head can only change during dev - ...(import.meta.env.DEV ? siteData.head : []), + ...(import.meta.env.DEV ? processHead(siteData.head, pageData) : []), ...(frontmatterHead ? filterOutHeadDescription(frontmatterHead) : []) ]) }) diff --git a/src/node/build/render.ts b/src/node/build/render.ts index 88fef643..b8622511 100644 --- a/src/node/build/render.ts +++ b/src/node/build/render.ts @@ -2,6 +2,7 @@ import path from 'path' import fs from 'fs-extra' import { SiteConfig, resolveSiteDataByRoute } from '../config' import { HeadConfig } from '../shared' +import { processHead } from '../../shared/shared' import { normalizePath, transformWithEsbuild } from 'vite' import { RollupOutput, OutputChunk, OutputAsset } from 'rollup' import { slash } from '../utils/slash' @@ -97,11 +98,7 @@ export async function renderPage( ? `${pageData.title} | ${siteData.title}` : siteData.title - const head = addSocialTags( - title, - ...siteData.head, - ...filterOutHeadDescription(pageData.frontmatter.head) - ) + const head = processHead(siteData.head, pageData); let inlinedScript = '' if (config.mpa && result) { @@ -133,7 +130,7 @@ export async function renderPage( ${stylesheetLink} ${preloadLinksString} ${prefetchLinkString} - ${await renderHead(head)} + ${await renderHead([...head, ...pageData.head])}
${content}
@@ -207,29 +204,3 @@ function renderAttrs(attrs: Record): string { }) .join('') } - -function isMetaDescription(headConfig: HeadConfig) { - const [type, attrs] = headConfig - return type === 'meta' && attrs?.name === 'description' -} - -function filterOutHeadDescription(head: HeadConfig[] | undefined) { - return head ? head.filter((h) => !isMetaDescription(h)) : [] -} - -function hasTag(head: HeadConfig[], tag: HeadConfig) { - const [tagType, tagAttrs] = tag - const [attr, value] = Object.entries(tagAttrs)[0] // First key - return head.some(([type, attrs]) => type === tagType && attrs[attr] === value) -} - -function addSocialTags(title: string, ...head: HeadConfig[]) { - const tags: HeadConfig[] = [ - ['meta', { name: 'twitter:title', content: title }], - ['meta', { property: 'og:title', content: title }] - ] - tags.filter((tagAttrs) => { - if (!hasTag(head, tagAttrs)) head.push(tagAttrs) - }) - return head -} diff --git a/src/node/config.ts b/src/node/config.ts index a9277b85..d9ededed 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -12,6 +12,7 @@ import { import { Options as VuePluginOptions } from '@vitejs/plugin-vue' import { SiteData, + PageData, HeadConfig, LocaleConfig, createLangDictionary, @@ -33,7 +34,7 @@ export interface UserConfig { base?: string title?: string description?: string - head?: HeadConfig[] + head?: HeadConfig[] | ((pageData: PageData) => HeadConfig[]) themeConfig?: ThemeConfig locales?: Record markdown?: MarkdownOptions diff --git a/src/shared/shared.ts b/src/shared/shared.ts index 64d78615..241e12f7 100644 --- a/src/shared/shared.ts +++ b/src/shared/shared.ts @@ -1,4 +1,4 @@ -import { LocaleConfig, SiteData } from '../../types/shared' +import { HeadConfig, LocaleConfig, SiteData, PageData } from '../../types/shared' export type { SiteData, @@ -95,3 +95,10 @@ function cleanRoute(siteData: SiteData, route: string): string { return route.slice(baseWithoutSuffix.length) } + +/** + * Process `head` configuration. + */ +export function processHead(head: HeadConfig[] | ((pageData: PageData) => HeadConfig[]), pageData: PageData) : HeadConfig[] { + return !head ? [] : typeof head === 'function' ? head(pageData) : head; +} diff --git a/types/shared.d.ts b/types/shared.d.ts index 645c0114..1d3c1c90 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -20,7 +20,7 @@ export interface SiteData { lang: string title: string description: string - head: HeadConfig[] + head: HeadConfig[] | ( (pageData: PageData) => HeadConfig[]) themeConfig: ThemeConfig scrollOffset: number | string locales: Record