chore: use svg sprites + search icons

pull/3539/head
userquin 2 years ago
parent 7739f8aef2
commit 7b9b3d43c1

@ -44,25 +44,9 @@ export const shared = defineConfig({
logo: { src: '/vitepress-logo-mini.svg', width: 24, height: 24 },
socialLinks: [
{
icon: {
id: 'github',
symbol: `<symbol id="github" viewBox="0 0 24 24">
<path d="M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"/>
</symbol>`
},
link: 'https://github.com/vuejs/vitepress'
},
{
icon: {
svg: `<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>npm</title><path d="M1.763 0C.786 0 0 .786 0 1.763v20.474C0 23.214.786 24 1.763 24h20.474c.977 0 1.763-.786 1.763-1.763V1.763C24 .786 23.214 0 22.237 0zM5.13 5.323l13.837.019-.009 13.836h-3.464l.01-10.382h-3.456L12.04 19.17H5.113z"/></svg>`
},
link: 'https://github.com/vuejs/vitepress'
}
{ icon: 'github', link: 'https://github.com/vuejs/vitepress' }
],
enableSocialLinksSVGSprite: true,
search: {
provider: 'algolia',
options: {

@ -4,7 +4,6 @@ declare const __ALGOLIA__: boolean
declare const __CARBON__: boolean
declare const __VUE_PROD_DEVTOOLS__: boolean
declare const __ASSETS_DIR__: string
declare const __SOCIAL_SVG_SPRITE_ICONS__: boolean
declare module '*.vue' {
import type { DefineComponent } from 'vue'
@ -34,3 +33,7 @@ declare module 'mark.js/src/vanilla.js' {
const mark: typeof Mark
export default mark
}
declare module 'virtual:vp-social-icons' {
export const socialIcons: Record<string, any>
}

@ -32,6 +32,14 @@ import { escapeRegExp } from '../../shared'
import { useData } from '../composables/data'
import { LRUCache } from '../support/lru'
import { createSearchTranslate } from '../support/translation'
import VPLocalSearchIcon from "./search-icons/VPLocalSearchIcon.vue";
import VPLocalSearchBackIcon from "./search-icons/VPLocalSearchBackIcon.vue";
import VPLocalSearchToggleIcon from "./search-icons/VPLocalSearchToggleIcon.vue";
import VPLocalSearchClearIcon from "./search-icons/VPLocalSearchClearIcon.vue";
import VPLocalSearchTilesIcon from "./search-icons/VPLocalSearchTilesIcon.vue";
import VPLocalSearchNavUpIcon from "./search-icons/VPLocalSearchNavUpIcon.vue";
import VPLocalSearchNavDownIcon from "./search-icons/VPLocalSearchNavDownIcon.vue";
import VPLocalSearchSelectIcon from "./search-icons/VPLocalSearchSelectIcon.vue";
const emit = defineEmits<{
(e: 'close'): void
@ -430,24 +438,7 @@ function formMarkRegex(terms: Set<string>) {
id="localsearch-label"
for="localsearch-input"
>
<svg
class="search-icon"
width="18"
height="18"
viewBox="0 0 24 24"
aria-hidden="true"
>
<g
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
>
<circle cx="11" cy="11" r="8" />
<path d="m21 21l-4.35-4.35" />
</g>
</svg>
<VPLocalSearchIcon class="search-icon" width="18" height="18" />
</label>
<div class="search-actions before">
<button
@ -455,21 +446,7 @@ function formMarkRegex(terms: Set<string>) {
:title="$t('modal.backButtonTitle')"
@click="$emit('close')"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M19 12H5m7 7l-7-7l7-7"
/>
</svg>
<VPLocalSearchBackIcon width="18" height="18" />
</button>
</div>
<input
@ -491,21 +468,7 @@ function formMarkRegex(terms: Set<string>) {
selectedIndex > -1 && (showDetailedList = !showDetailedList)
"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 14h7v7H3zM3 3h7v7H3zm11 1h7m-7 5h7m-7 6h7m-7 5h7"
/>
</svg>
<VPLocalSearchToggleIcon width="18" height="18" />
</button>
<button
@ -515,21 +478,7 @@ function formMarkRegex(terms: Set<string>) {
:title="$t('modal.resetButtonTitle')"
@click="resetSearch"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"
/>
</svg>
<VPLocalSearchClearIcon width="18" height="18" />
</button>
</div>
</form>
@ -568,16 +517,7 @@ function formMarkRegex(terms: Set<string>) {
class="title"
>
<span class="text" v-html="t" />
<svg width="18" height="18" viewBox="0 0 24 24">
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m9 18l6-6l-6-6"
/>
</svg>
<VPLocalSearchTilesIcon width="18" height="18" />
</span>
<span class="title main">
<span class="text" v-html="p.title" />
@ -606,45 +546,16 @@ function formMarkRegex(terms: Set<string>) {
<div class="search-keyboard-shortcuts">
<span>
<kbd :aria-label="$t('modal.footer.navigateUpKeyAriaLabel')">
<svg width="14" height="14" viewBox="0 0 24 24">
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 19V5m-7 7l7-7l7 7"
/>
</svg>
<VPLocalSearchNavUpIcon width="14" height="14" />
</kbd>
<kbd :aria-label="$t('modal.footer.navigateDownKeyAriaLabel')">
<svg width="14" height="14" viewBox="0 0 24 24">
<path
fill="none"
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M12 5v14m7-7l-7 7l-7-7"
/>
</svg>
<VPLocalSearchNavDownIcon width="14" height="14" />
</kbd>
{{ $t('modal.footer.navigateText') }}
</span>
<span>
<kbd :aria-label="$t('modal.footer.selectKeyAriaLabel')">
<svg width="14" height="14" viewBox="0 0 24 24">
<g
fill="none"
stroke="currentcolor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
>
<path d="m9 10l-5 5l5 5" />
<path d="M20 4v7a4 4 0 0 1-4 4H4" />
</g>
</svg>
<VPLocalSearchSelectIcon width="14" height="14" />
</kbd>
{{ $t('modal.footer.selectText') }}
</span>

@ -1,6 +1,7 @@
<script lang="ts" setup>
import type { ButtonTranslations } from '../../../../types/local-search'
import { createSearchTranslate } from '../support/translation'
import VPDocSearchIcon from './search-icons/VPDocSearchIcon.vue'
// Button-Translations
const defaultTranslations: { button: ButtonTranslations } = {
@ -16,22 +17,7 @@ const $t = createSearchTranslate(defaultTranslations)
<template>
<button type="button" class="DocSearch DocSearch-Button" :aria-label="$t('button.buttonAriaLabel')">
<span class="DocSearch-Button-Container">
<svg
class="DocSearch-Search-Icon"
width="20"
height="20"
viewBox="0 0 20 20"
aria-label="search icon"
>
<path
d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
stroke="currentColor"
fill="none"
fill-rule="evenodd"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
<VPDocSearchIcon class="DocSearch-Search-Icon" width="20" height="20" />
<span class="DocSearch-Button-Placeholder">{{ $t('button.buttonText') }}</span>
</span>
<span class="DocSearch-Button-Keys">

@ -1,6 +1,7 @@
<script lang="ts" setup>
import type { DefaultTheme } from 'vitepress/theme'
import { computed } from 'vue'
import { socialIcons } from 'virtual:vp-social-icons'
const props = defineProps<{
icon: DefaultTheme.SocialLinkIcon
@ -8,39 +9,16 @@ const props = defineProps<{
ariaLabel?: string
}>()
const svgSpriteRegex = __SOCIAL_SVG_SPRITE_ICONS__
? /\.\/sprite-social-icons\/VP(.*)Icon\.vue/
: /\.\/social-icons\/VP(.*)Icon\.vue/
const icons = Object.entries(__SOCIAL_SVG_SPRITE_ICONS__
?
import.meta.glob('./sprite-social-icons/*.vue', {
eager: true,
import: 'default'
})
: import.meta.glob('./social-icons/*.vue', {
eager: true,
import: 'default'
})
).reduce(
(acc, [path, component]) => {
const name = path
.match(svgSpriteRegex)![1]
.toLowerCase()
acc[name] = component
return acc
},
{} as Record<string, any>
)
const svg = computed(() => {
if (__SOCIAL_SVG_SPRITE_ICONS__) {
if (typeof props.icon === 'object' && 'id' in props.icon) return 'id' in props.icon ? icons[props.icon.id] : undefined
if (typeof props.icon === 'object') {
return 'id' in props.icon
? socialIcons[props.icon.id]
: 'svg' in props.icon
? { svg: props.icon.svg }
: undefined
}
if (typeof props.icon === 'object') return 'svg' in props.icon ? { svg: props.icon.svg } : undefined
return icons[props.icon]
return socialIcons[props.icon]
})
</script>
@ -57,7 +35,7 @@ const svg = computed(() => {
</a>
<a
v-else
class="VPSocialLink"
class="VPSocialLink no-icon"
:href="link"
:aria-label="ariaLabel ?? (typeof icon === 'string' ? icon : '')"
target="_blank"

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="DocSearch" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchBack" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchClear" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearch" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchNavDown" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchNavUp" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchSelect" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchTitles" sprite="local-search"/>
</template>

@ -0,0 +1,7 @@
<script setup lang="ts">
import VPIcon from '../VPSVGSpriteIcon.vue';
</script>
<template>
<VPIcon aria-hidden="true" focusable="false" icon="LocalSearchToggle" sprite="local-search"/>
</template>

@ -0,0 +1,2 @@
// keep this module empty: transformed by vitepress:svg-sprite plugin
export const socialIcons: Record<string, any> = {}

@ -153,9 +153,7 @@ export async function createVitePressPlugin(
!!site.themeConfig?.algolia, // legacy
__CARBON__: !!site.themeConfig?.carbonAds,
__ASSETS_DIR__: JSON.stringify(siteConfig.assetsDir),
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: !!process.env.DEBUG,
__SOCIAL_SVG_SPRITE_ICONS__:
site.themeConfig?.enableSocialLinksSVGSprite === true
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: !!process.env.DEBUG
},
optimizeDeps: {
// force include vue to avoid duplicated copies when linked + optimized

@ -4,11 +4,31 @@ import type { DefaultTheme } from '../index'
export function svgSpritePlugin(siteConfig: SiteConfig) {
let useSvgSprites: Record<string, string> = {}
let virtual: [name: string, path: string][] = []
const virtualName = 'virtual:vp-social-icons'
const resolvedVirtualName = `\0${virtualName}`
return {
name: 'vitepress:svg-sprite',
enforce: 'pre',
configResolved() {
useSvgSprites = prepareSvgSprites(useSvgSprites, siteConfig)
virtual = prepareSVGIcons(siteConfig)
},
resolveId(id: string) {
if (id === virtualName) {
return resolvedVirtualName
}
},
load(id) {
if (id === resolvedVirtualName) {
if (virtual.length === 0) {
return 'export const socialIcons = {}'
}
return `${virtual.map(([name, path]) => `import ${name} from ${JSON.stringify(path)}`).join('\n')}
export const socialIcons = {${virtual.map(([name]) => name).join(',')}}
`
}
},
generateBundle(_options, bundle) {
Object.entries(useSvgSprites).forEach(([fileName, source]) => {
@ -46,6 +66,45 @@ export function svgSpritePlugin(siteConfig: SiteConfig) {
} satisfies Plugin
}
function prepareSVGIcons({ site }: SiteConfig) {
const socialIconPrefix =
site.themeConfig?.enableSocialLinksSVGSprite === true
? 'vitepress/dist/client/theme-default/components/sprite-social-icons/'
: 'vitepress/dist/client/theme-default/components/social-icons/'
const socialIcons: DefaultTheme.SocialLink[] =
site.themeConfig?.socialLinks ?? []
return socialIcons
.filter((s) => typeof s.icon === 'string')
.map((s) => {
let icon: string = ''
switch (s.icon) {
case 'x':
icon = 'X'
break
case 'github':
icon = 'GitHub'
break
case 'youtube':
icon = 'YouTube'
break
case 'discord':
case 'facebook':
case 'instagram':
case 'mastodon':
case 'npm':
case 'slack':
case 'twitter':
icon = s.icon.charAt(0).toUpperCase() + s.icon.slice(1)
break
}
return [s.icon, `${socialIconPrefix}VP${icon}Icon.vue`] as [
name: string,
path: string
]
})
}
const svgSprite = `<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
<symbol id="AlignJustify" viewBox="0 0 24 24">
@ -131,11 +190,6 @@ const svgSprite = `<?xml version="1.0" encoding="UTF-8"?>
</svg>
`
const localSearchSvgSprite = `<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
</svg>
`
const socialSvgSpriteSymbols = {
discord: `<symbol id="discord" viewBox="0 0 24 24">
<path d="M20.317 4.3698a19.7913 19.7913 0 00-4.8851-1.5152.0741.0741 0 00-.0785.0371c-.211.3753-.4447.8648-.6083 1.2495-1.8447-.2762-3.68-.2762-5.4868 0-.1636-.3933-.4058-.8742-.6177-1.2495a.077.077 0 00-.0785-.037 19.7363 19.7363 0 00-4.8852 1.515.0699.0699 0 00-.0321.0277C.5334 9.0458-.319 13.5799.0992 18.0578a.0824.0824 0 00.0312.0561c2.0528 1.5076 4.0413 2.4228 5.9929 3.0294a.0777.0777 0 00.0842-.0276c.4616-.6304.8731-1.2952 1.226-1.9942a.076.076 0 00-.0416-.1057c-.6528-.2476-1.2743-.5495-1.8722-.8923a.077.077 0 01-.0076-.1277c.1258-.0943.2517-.1923.3718-.2914a.0743.0743 0 01.0776-.0105c3.9278 1.7933 8.18 1.7933 12.0614 0a.0739.0739 0 01.0785.0095c.1202.099.246.1981.3728.2924a.077.077 0 01-.0066.1276 12.2986 12.2986 0 01-1.873.8914.0766.0766 0 00-.0407.1067c.3604.698.7719 1.3628 1.225 1.9932a.076.076 0 00.0842.0286c1.961-.6067 3.9495-1.5219 6.0023-3.0294a.077.077 0 00.0313-.0552c.5004-5.177-.8382-9.6739-3.5485-13.6604a.061.061 0 00-.0312-.0286zM8.02 15.3312c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9555-2.4189 2.157-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.9555 2.4189-2.1569 2.4189zm7.9748 0c-1.1825 0-2.1569-1.0857-2.1569-2.419 0-1.3332.9554-2.4189 2.1569-2.4189 1.2108 0 2.1757 1.0952 2.1568 2.419 0 1.3332-.946 2.4189-2.1568 2.4189Z"/>
@ -172,44 +226,99 @@ const socialSvgSpriteSymbols = {
</symbol>`
}
const localSearchSvgSprite = `
<symbol id="LocalSearch" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<circle cx="11" cy="11" r="8" />
<path d="m21 21l-4.35-4.35" />
</g>
</symbol>
<symbol id="LocalSearchBack" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 12H5m7 7l-7-7l7-7" />
</symbol>
<symbol id="LocalSearchToggle" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 14h7v7H3zM3 3h7v7H3zm11 1h7m-7 5h7m-7 6h7m-7 5h7" />
</symbol>
<symbol id="LocalSearchClear" viewBox="0 0 24 24" >
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 5H9l-7 7l7 7h11a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2Zm-2 4l-6 6m0-6l6 6"/>
</symbol>
<symbol id="LocalSearchTitles" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m9 18l6-6l-6-6" />
</symbol>
<symbol id="LocalSearchNavUp" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 19V5m-7 7l7-7l7 7" />
</symbol>
<symbol id="LocalSearchNavDown" viewBox="0 0 24 24">
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 5v14m7-7l-7 7l-7-7" />
</symbol>
<symbol id="LocalSearchSelect" viewBox="0 0 24 24">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="m9 10l-5 5l5 5" />
<path d="M20 4v7a4 4 0 0 1-4 4H4" />
</g>
</symbol>
`
const DocSearchIcon = `
<symbol id="DocSearch" viewBox="0 0 20 20">
<path d="M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z"
stroke="currentColor"
fill="none"
fill-rule="evenodd"
stroke-linecap="round"
stroke-linejoin="round"
/>
</symbol>`
function prepareSvgSprites(
sprites: Record<string, string>,
siteConfig: SiteConfig
) {
sprites['vp-icons-sprite.svg'] = svgSprite
if (siteConfig.site.themeConfig?.enableSocialLinksSVGSprite) {
const socialLinks: DefaultTheme.SocialLink[] | undefined =
siteConfig.site.themeConfig.socialLinks
if (socialLinks?.length) {
const entries = Object.values(
socialLinks.reduce(
(sprite, l) => {
if (l.icon) {
if (typeof l.icon !== 'object') {
if (l.icon in socialSvgSpriteSymbols) {
sprite[l.icon] = socialSvgSpriteSymbols[l.icon]
}
} else if ('id' in l.icon && 'symbol' in l.icon) {
sprite[l.icon.id] = l.icon.symbol
// we don't need the symbol in the site configuration
l.icon.symbol = ''
const socialLinks: DefaultTheme.SocialLink[] | undefined =
siteConfig.site.themeConfig.socialLinks
if (socialLinks?.length) {
const entries = Object.values(
socialLinks.reduce(
(sprite, l) => {
if (l.icon) {
if (typeof l.icon !== 'object') {
if (l.icon in socialSvgSpriteSymbols) {
sprite[l.icon] = socialSvgSpriteSymbols[l.icon]
}
} else if ('id' in l.icon && 'symbol' in l.icon) {
sprite[l.icon.id] = l.icon.symbol
// we don't need the symbol in the site configuration
l.icon.symbol = ''
}
}
return sprite
},
{} as Record<string, string>
)
return sprite
},
{} as Record<string, string>
)
entries.unshift(`<?xml version="1.0" encoding="UTF-8"?>
)
entries.unshift(`<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">`)
entries.push('</svg>')
sprites['vp-social-icons-sprite.svg'] = entries.join('')
}
entries.push('</svg>')
sprites['vp-social-icons-sprite.svg'] = entries.join('')
}
if (siteConfig.site.themeConfig?.search?.provider === 'local') {
sprites['vp-local-search-icons-sprite.svg'] = localSearchSvgSprite
sprites['vp-local-search-icons-sprite.svg'] =
`<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
${DocSearchIcon.trim()}
${localSearchSvgSprite.trim()}
</svg>
`
} else {
sprites['vp-local-search-icons-sprite.svg'] =
`<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0">
${DocSearchIcon.trim()}
</svg>
`
}
return sprites

@ -89,19 +89,6 @@ export namespace DefaultTheme {
*/
socialLinks?: SocialLink[]
/**
* Should VitePress generate and use SVG Sprite to render SVG social links?.
*
* To enable this feature, you need to provide `{ sprite: string; symbol: string }` in `socialLinks` entries if you're using custom `svg`:
* - the symbol is the svg content: replace svg with symbol tag: `<svg...><content></svg>` => `<symbol><content></symbol>`
* - remove any xmlns and role attributes
* - include id attribute, must match the sprite value
* - remove title and desc tags if present
*
* @default false
*/
enableSocialLinksSVGSprite?: boolean
/**
* The footer configuration.
*/

Loading…
Cancel
Save