Merge pull request #93 from pengzhanbo/RC-63

RC-63
This commit is contained in:
pengzhanbo 2024-06-07 20:49:54 +08:00 committed by GitHub
commit 2082e270bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
82 changed files with 2701 additions and 2329 deletions

View File

@ -9,11 +9,11 @@
"docs:serve": "anywhere -s -h localhost -d .vuepress/dist"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@iconify/json": "^2.2.215",
"@vuepress/bundler-vite": "2.0.0-rc.12",
"@iconify/json": "^2.2.217",
"@vuepress/bundler-vite": "2.0.0-rc.13",
"anywhere": "^1.6.0",
"chart.js": "^4.4.3",
"echarts": "^5.5.0",

View File

@ -41,8 +41,8 @@
"devDependencies": {
"@commitlint/cli": "^19.3.0",
"@commitlint/config-conventional": "^19.2.2",
"@pengzhanbo/eslint-config-vue": "^1.10.0",
"@pengzhanbo/stylelint-config": "^1.10.0",
"@pengzhanbo/eslint-config-vue": "^1.11.0",
"@pengzhanbo/stylelint-config": "^1.11.0",
"@types/lodash.merge": "^4.6.9",
"@types/node": "20.12.10",
"@types/webpack-env": "^1.18.5",
@ -52,7 +52,7 @@
"conventional-changelog-cli": "^5.0.0",
"cpx2": "^7.0.1",
"cz-conventional-changelog": "^3.3.0",
"eslint": "^9.3.0",
"eslint": "^9.4.0",
"husky": "^9.0.11",
"lint-staged": "^15.2.5",
"rimraf": "^5.0.7",

View File

@ -33,7 +33,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@pengzhanbo/utils": "^1.1.2",

View File

@ -33,7 +33,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"publishConfig": {
"access": "public"

View File

@ -37,7 +37,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@vue/devtools-api": "6.6.1",

View File

@ -2,7 +2,6 @@ import type { BlogPostData } from '../shared/index.js'
declare module '@internal/blogData' {
const blogPostData: BlogPostData
const extraBlogData: Record<string, any>
export { blogPostData, extraBlogData }
export { blogPostData }
}

View File

@ -1,6 +1,5 @@
import {
blogPostData as blogPostDataRaw,
extraBlogData as extraBlogDataRaw,
} from '@internal/blogData'
import { ref } from 'vue'
import type { Ref } from 'vue'
@ -18,19 +17,8 @@ export function useBlogPostData<
return blogPostData as BlogDataRef<T>
}
export type ExtraBlogDataRef = Ref<Record<string, any>>
export const extraBlogData: ExtraBlogDataRef = ref(extraBlogDataRaw)
export function useExtraBlogData(): ExtraBlogDataRef {
return extraBlogData as ExtraBlogDataRef
}
if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) {
__VUE_HMR_RUNTIME__.updateBlogData = (data: BlogPostData) => {
blogPostData.value = data
}
__VUE_HMR_RUNTIME__.updateExtraBlogData = (data: Record<string, any>) => {
extraBlogData.value = data
}
}

View File

@ -9,15 +9,11 @@ if (import.meta.webpackHot) {
if (__VUE_HMR_RUNTIME__.updateBlogData) {
__VUE_HMR_RUNTIME__.updateBlogData(blogPostData)
}
if (__VUE_HMR_RUNTIME__.updateExtraBlogData) {
__VUE_HMR_RUNTIME__.updateExtraBlogData(extraBlogData)
}
}
if (import.meta.hot) {
import.meta.hot.accept(({ blogPostData, extraBlogData }) => {
import.meta.hot.accept(({ blogPostData }) => {
__VUE_HMR_RUNTIME__.updateBlogData(blogPostData)
__VUE_HMR_RUNTIME__.updateExtraBlogData(extraBlogData)
})
}
`
@ -56,15 +52,10 @@ export async function preparedBlogData(app: App, pageFilter: (id: string) => boo
})
}
const extraBlogData: Record<string, any> = {}
if (typeof options.extraBlogData === 'function')
options.extraBlogData(extraBlogData)
const blogData: BlogPostData = pages.map((page: Page) => {
let extended: Partial<BlogPostDataItem> = {}
if (typeof options.extendBlogData === 'function')
extended = options.extendBlogData(page, extraBlogData)
extended = options.extendBlogData(page)
const data = {
path: page.path,
@ -87,9 +78,6 @@ export async function preparedBlogData(app: App, pageFilter: (id: string) => boo
export const blogPostData = JSON.parse(${JSON.stringify(
JSON.stringify(blogData),
)});
export const extraBlogData = JSON.parse(${JSON.stringify(
JSON.stringify(extraBlogData),
)});
`
// inject HMR code

View File

@ -5,10 +5,8 @@ export interface BlogDataPluginOptions {
exclude?: string | string[]
sortBy?: 'createTime' | false | (<T>(prev: T, next: T) => boolean)
excerpt?: boolean
extendBlogData?: <T = any>(page: T, extra: Record<string, any>) => Record<string, any>
extendBlogData?: <T = any>(page: T) => Record<string, any>
pageFilter?: (page: Page) => boolean
extraBlogData?: (extra: Record<string, any>) => void
}
export type BlogPostData<T extends object = object> = BlogPostDataItem<T>[]

View File

@ -44,7 +44,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"markdown-it-container": "^4.0.0"

View File

@ -37,7 +37,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"vue": "^3.4.27"

View File

@ -38,7 +38,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@vuepress-plume/plugin-content-update": "workspace:~",

View File

@ -33,7 +33,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"publishConfig": {
"access": "public"

View File

@ -37,7 +37,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@iconify/vue": "^4.1.2",

View File

@ -38,7 +38,7 @@
},
"peerDependencies": {
"@iconify/json": "^2",
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"peerDependenciesMeta": {
"@iconify/json": {
@ -47,18 +47,18 @@
},
"dependencies": {
"@iconify/utils": "^2.1.24",
"@vuepress/helper": "2.0.0-rc.33",
"@vuepress/helper": "2.0.0-rc.34",
"@vueuse/core": "^10.10.0",
"local-pkg": "^0.5.0",
"markdown-it-container": "^4.0.0",
"nanoid": "^5.0.7",
"shiki": "^1.6.1",
"tm-grammars": "^1.12.5",
"shiki": "^1.6.3",
"tm-grammars": "^1.12.8",
"tm-themes": "^1.4.3",
"vue": "^3.4.27"
},
"devDependencies": {
"@iconify/json": "^2.2.215",
"@iconify/json": "^2.2.217",
"@types/markdown-it": "^14.1.1"
},
"publishConfig": {

View File

@ -42,8 +42,9 @@ useEventListener('message', (event) => {
&& payload
&& payload.feature === props.feature
&& payload.meta === props.meta
)
) {
height.value = `${Math.ceil(payload.height)}px`
}
})
function parseData(data: string | MessageData): MessageData {

View File

@ -41,7 +41,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@iarna/toml": "^2.2.5",
@ -51,12 +51,12 @@
"cpx2": "^7.0.1",
"dotenv": "^16.4.5",
"esbuild": "^0.21.4",
"execa": "^9.1.0",
"netlify-cli": "^17.25.0",
"execa": "^9.2.0",
"netlify-cli": "^17.26.0",
"portfinder": "^1.0.32"
},
"devDependencies": {
"@types/node": "^20.12.13"
"@types/node": "^20.14.2"
},
"publishConfig": {
"access": "public"

View File

@ -34,8 +34,9 @@ export function useNetlifyFunctionsPlugin(app: App, options: UseNetlifyFunctionP
(plugin: PluginObject) =>
plugin.name === 'vuepress-plugin-netlify-functions',
)
)
) {
app.use(netlifyFunctionsPlugin())
}
const { proxyPrefix, directory } = getOptions()
const source = path.join(options.directory, '**/*.js')

View File

@ -37,7 +37,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@vue/devtools-api": "6.6.1",

View File

@ -1,18 +1,18 @@
import type { App, Plugin } from 'vuepress/core'
import type { Plugin } from 'vuepress/core'
import { getDirname, path } from 'vuepress/utils'
import type { NotesDataOptions } from '../shared/index.js'
import { prepareNotesData, watchNotesData } from './prepareNotesData.js'
export function notesDataPlugin(options: NotesDataOptions | NotesDataOptions[]): Plugin {
return (app: App) => {
return {
name: '@vuepress-plume/plugin-notes-data',
clientConfigFile: path.join(
getDirname(import.meta.url),
'../client/clientConfig.js',
),
onPrepared: () => prepareNotesData(app, options),
onWatched: (app, watchers) => watchNotesData(app, watchers, options),
}
return {
name: '@vuepress-plume/plugin-notes-data',
clientConfigFile: path.join(
getDirname(import.meta.url),
'../client/clientConfig.js',
),
onPrepared: app => prepareNotesData(app, options),
onWatched: (app, watchers) => watchNotesData(app, watchers, options),
}
}

View File

@ -31,7 +31,7 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@netlify/functions": "^2.7.0",

View File

@ -37,10 +37,10 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@vuepress/helper": "2.0.0-rc.33",
"@vuepress/helper": "2.0.0-rc.34",
"@vueuse/core": "^10.10.0",
"@vueuse/integrations": "^10.10.0",
"chokidar": "^3.6.0",

View File

@ -28,7 +28,7 @@ export function searchPlugin({
onPrepared: app => prepareSearchIndex({ app, isSearchable, searchOptions }),
onWatched: async (app, watchers) => {
onWatched: (app, watchers) => {
const searchIndexWatcher = chokidar.watch('pages/**/*.js', {
cwd: app.dir.temp(),
ignoreInitial: true,

View File

@ -33,19 +33,19 @@
"ts": "tsc -b tsconfig.build.json"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@shikijs/transformers": "^1.6.1",
"@shikijs/twoslash": "^1.6.1",
"@shikijs/transformers": "^1.6.3",
"@shikijs/twoslash": "^1.6.3",
"@types/hast": "^3.0.4",
"@vuepress/helper": "2.0.0-rc.33",
"@vuepress/helper": "2.0.0-rc.34",
"floating-vue": "^5.2.2",
"mdast-util-from-markdown": "^2.0.1",
"mdast-util-gfm": "^3.0.0",
"mdast-util-to-hast": "^13.1.0",
"nanoid": "^5.0.7",
"shiki": "^1.6.1",
"shiki": "^1.6.3",
"twoslash": "^0.2.6",
"twoslash-vue": "^0.2.6"
},

View File

@ -27,6 +27,7 @@ const cache = new LRUCache<string, string>(64)
const vueRE = /-vue$/
const RE_ESCAPE = /\[\\\!code/g
const mustacheRE = /\{\{.*?\}\}/g
const decorationsRE = /^\/\/ @decorations:(.*?)\n/
export async function highlight(
theme: ThemeOptions,
@ -75,8 +76,7 @@ export async function highlight(
{
name: 'shiki:inline-decorations',
preprocess(code, options) {
const reg = /^\/\/ @decorations:(.*?)\n/
code = code.replace(reg, (match, decorations) => {
code = code.replace(decorationsRE, (match, decorations) => {
options.decorations ||= []
options.decorations.push(...JSON.parse(decorations))
return ''
@ -90,6 +90,8 @@ export async function highlight(
},
]
const loadedLanguages = highlighter.getLoadedLanguages()
return (str: string, language: string, attrs: string) => {
attrs = attrs || ''
let lang = resolveLanguage(language) || defaultLang
@ -104,7 +106,7 @@ export async function highlight(
}
if (lang) {
const langLoaded = highlighter.getLoadedLanguages().includes(lang as any)
const langLoaded = loadedLanguages.includes(lang as any)
if (!langLoaded && !isPlainLang(lang) && !isSpecialLang(lang)) {
logger.warn(
c.yellow(

View File

@ -25,8 +25,9 @@ export function lineNumberPlugin(md: Markdown, { lineNumbers = true }: LineNumbe
if (
(!lineNumbers && !enableLineNumbers)
|| (lineNumbers && disableLineNumbers)
)
) {
return rawCode
}
const code = rawCode.slice(
rawCode.indexOf('<code>'),
@ -39,8 +40,9 @@ export function lineNumberPlugin(md: Markdown, { lineNumbers = true }: LineNumbe
typeof lineNumbers === 'number'
&& lines.length < lineNumbers
&& !enableLineNumbers
)
) {
return rawCode
}
const startNumbers
= Number(info.match(LINE_NUMBERS_START_REGEXP)?.[1] ?? 1) - 1

1911
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@ -63,7 +63,7 @@
"ts:watch": "tsc -b tsconfig.build.json --watch"
},
"peerDependencies": {
"vuepress": "2.0.0-rc.12"
"vuepress": "2.0.0-rc.13"
},
"dependencies": {
"@pengzhanbo/utils": "^1.1.2",
@ -76,28 +76,29 @@
"@vuepress-plume/plugin-notes-data": "workspace:*",
"@vuepress-plume/plugin-search": "workspace:*",
"@vuepress-plume/plugin-shikiji": "workspace:*",
"@vuepress/helper": "2.0.0-rc.33",
"@vuepress/plugin-active-header-links": "2.0.0-rc.33",
"@vuepress/plugin-comment": "2.0.0-rc.33",
"@vuepress/plugin-docsearch": "2.0.0-rc.33",
"@vuepress/plugin-git": "2.0.0-rc.33",
"@vuepress/plugin-markdown-container": "2.0.0-rc.33",
"@vuepress/plugin-nprogress": "2.0.0-rc.33",
"@vuepress/plugin-photo-swipe": "2.0.0-rc.33",
"@vuepress/plugin-reading-time": "2.0.0-rc.33",
"@vuepress/plugin-seo": "2.0.0-rc.33",
"@vuepress/plugin-sitemap": "2.0.0-rc.33",
"@vuepress/plugin-theme-data": "2.0.0-rc.33",
"@vuepress/plugin-watermark": "2.0.0-rc.33",
"@vueuse/core": "^10.9.0",
"@vuepress/helper": "2.0.0-rc.34",
"@vuepress/plugin-active-header-links": "2.0.0-rc.34",
"@vuepress/plugin-comment": "2.0.0-rc.34",
"@vuepress/plugin-docsearch": "2.0.0-rc.34",
"@vuepress/plugin-git": "2.0.0-rc.34",
"@vuepress/plugin-markdown-container": "2.0.0-rc.34",
"@vuepress/plugin-nprogress": "2.0.0-rc.34",
"@vuepress/plugin-photo-swipe": "2.0.0-rc.34",
"@vuepress/plugin-reading-time": "2.0.0-rc.34",
"@vuepress/plugin-seo": "2.0.0-rc.34",
"@vuepress/plugin-sitemap": "2.0.0-rc.34",
"@vuepress/plugin-theme-data": "2.0.0-rc.34",
"@vuepress/plugin-watermark": "2.0.0-rc.34",
"@vueuse/core": "^10.10.0",
"bcrypt-ts": "^5.0.2",
"chokidar": "^3.6.0",
"date-fns": "^3.6.0",
"katex": "^0.16.10",
"lodash.merge": "^4.6.2",
"nanoid": "^5.0.7",
"vue": "^3.4.27",
"vue-router": "^4.3.2",
"vuepress-plugin-md-enhance": "2.0.0-rc.47",
"vuepress-plugin-md-enhance": "2.0.0-rc.48",
"vuepress-plugin-md-power": "workspace:*"
}
}

View File

@ -39,8 +39,10 @@ function linkTo(e: Event) {
<template>
<Component
:is="tag" class="auto-link" :class="{ link }" :href="link"
:target="target ?? (isExternal ? '_blank' : undefined)" :rel="rel ?? (isExternal ? 'noreferrer' : undefined)"
:is="tag" class="auto-link" :class="{ link }"
:href="link"
:target="target ?? (isExternal ? '_blank' : undefined)"
:rel="rel ?? (isExternal ? 'noreferrer' : undefined)"
@click="linkTo($event)"
>
<slot />

View File

@ -1,8 +1,7 @@
<script lang="ts" setup>
import { useElementSize, useWindowScroll, useWindowSize } from '@vueuse/core'
import { computed, onMounted, ref, shallowRef, watch } from 'vue'
import { usePageData } from 'vuepress/client'
import type { PlumeThemePageData } from '../../shared/index.js'
import { useData } from '../composables/data.js'
const body = shallowRef<HTMLElement | null>()
const { height: bodyHeight } = useElementSize(body)
@ -11,7 +10,7 @@ onMounted(() => {
body.value = document.body
})
const page = usePageData<PlumeThemePageData>()
const { page } = useData()
const { y } = useWindowScroll()
const isScrolling = ref(false)

View File

@ -1,14 +1,14 @@
<script lang="ts" setup>
import { computed } from 'vue'
import type { PlumeThemeBlogPostItem } from '../../../shared/index.js'
import { useExtraBlogData } from '../../composables/index.js'
import { useTagColors } from '../../composables/index.js'
import AutoLink from '../AutoLink.vue'
const props = defineProps<{
post: PlumeThemeBlogPostItem
}>()
const extraData = useExtraBlogData()
const colors = useTagColors()
const categoryList = computed(() =>
props.post.categoryList ?? [],
@ -19,7 +19,7 @@ const tags = computed(() =>
.slice(0, 4)
.map(tag => ({
name: tag,
colors: extraData.value.tagsColorsPreset[extraData.value.tagsColors[tag]],
className: `vp-tag-${colors.value[tag]}`,
})),
)
@ -55,7 +55,7 @@ const createTime = computed(() =>
<template v-for="tag in tags" :key="tag.name">
<span
class="tag"
:style="{ '--vp-tag-color': tag.colors[0], '--vp-tag-bg-color': tag.colors[2] }"
:class="tag.className"
>
{{ tag.name }}
</span>
@ -188,7 +188,7 @@ const createTime = computed(() =>
font-size: 12px;
line-height: 1;
color: var(--vp-tag-color);
background-color: var(--vp-tag-bg-color);
background-color: var(--vp-tag-bg);
border-radius: 3px;
transition: color var(--t-color), background-color var(--t-color);
}

View File

@ -18,8 +18,7 @@ const { tags: tagsLink } = useBlogExtract()
v-for="tag in tags"
:key="tag.name"
class="tag"
:class="{ active: tag.name === currentTag }"
:style="{ '--vp-tag-color': tag.colors[0], '--vp-tag-hover-color': tag.colors[1] }"
:class="{ active: tag.name === currentTag, [tag.className]: true }"
@click="handleTagClick(tag.name)"
>
<span class="tag-name">{{ tag.name }}</span>

View File

@ -1,13 +1,13 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useThemeLocaleData } from '../composables/index.js'
import { useData } from '../composables/data.js'
const props = defineProps<{
compare: (password: string) => boolean
info?: string
}>()
const theme = useThemeLocaleData()
const { theme } = useData()
const password = ref('')
const errorCode = ref(0) // 0: no error, 1: wrong password

View File

@ -1,17 +1,15 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useSiteLocaleData } from 'vuepress/client'
import { useThemeLocaleData } from '../composables/index.js'
import { useData } from '../composables/data.js'
import { useGlobalEncrypt } from '../composables/encrypt.js'
import VFooter from './VFooter.vue'
import EncryptForm from './EncryptForm.vue'
const theme = useThemeLocaleData()
const siteData = useSiteLocaleData()
const { theme, site } = useData()
const { compareGlobal } = useGlobalEncrypt()
const avatar = computed(() => theme.value.avatar)
const title = computed(() => avatar.value?.name || siteData.value.title)
const title = computed(() => avatar.value?.name || site.value.title)
</script>
<template>

View File

@ -1,9 +1,9 @@
<script setup lang="ts">
import { usePageEncrypt } from '../composables/encrypt.js'
import { useThemeLocaleData } from '../composables/index.js'
import { useData } from '../composables/data.js'
import EncryptForm from './EncryptForm.vue'
const theme = useThemeLocaleData()
const { theme } = useData()
const { comparePage } = usePageEncrypt()
</script>

View File

@ -1,14 +1,12 @@
<script lang="ts" setup>
import { usePageFrontmatter } from 'vuepress/client'
import { computed } from 'vue'
import type { PlumeThemeFriendsFrontmatter } from '../../shared/index.js'
import { useEditNavLink } from '../composables/index.js'
import { useData, useEditNavLink } from '../composables/index.js'
import AutoLink from './AutoLink.vue'
import FriendsItem from './FriendsItem.vue'
import FriendsGroup from './FriendsGroup.vue'
const matter = usePageFrontmatter<PlumeThemeFriendsFrontmatter>()
const editNavLink = useEditNavLink()
const { frontmatter: matter } = useData<'friends'>()
const list = computed(() => matter.value.list || [])
const groups = computed(() => matter.value.groups || [])

View File

@ -72,7 +72,7 @@ const maxWidth = computed(() => {
}
}
.content-image :deep(.plume-image) {
.content-image :deep(.vp-image) {
width: 100%;
max-width: 128px;
margin: 0 auto;
@ -114,7 +114,7 @@ const maxWidth = computed(() => {
}
@media (min-width: 768px) {
.content-image :deep(.plume-image) {
.content-image :deep(.vp-image) {
max-width: 180px;
margin: 0 48px;
}
@ -129,7 +129,7 @@ const maxWidth = computed(() => {
gap: 48px;
}
.content-image :deep(.plume-image) {
.content-image :deep(.vp-image) {
max-width: 220px;
margin: 0 96px;
}

View File

@ -1,5 +1,6 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { computed, nextTick, ref, watch } from 'vue'
import { useRoute } from 'vuepress/client'
import { useData, useSidebar } from '../composables/index.js'
import { usePageEncrypt } from '../composables/encrypt.js'
import PageAside from './PageAside.vue'
@ -10,6 +11,7 @@ import TransitionFadeSlideY from './TransitionFadeSlideY.vue'
const { hasSidebar, hasAside } = useSidebar()
const { page, isDark } = useData()
const route = useRoute()
const { isPageDecrypted } = usePageEncrypt()
@ -23,6 +25,32 @@ const enableAside = computed(() => {
return hasAside.value && isPageDecrypted.value
})
const asideEl = ref<HTMLElement>()
watch(
() => route.hash,
hash =>
nextTick(() => {
if (!asideEl.value)
return
const activeItem = asideEl.value.querySelector(
`.outline-link[href="${hash}"]`,
)
if (!activeItem || !hash) {
asideEl.value.scrollTop = 0
return
}
const { top: navTop, height: navHeight }
= asideEl.value.getBoundingClientRect()
const { top: activeTop, height: activeHeight }
= activeItem.getBoundingClientRect()
if (activeTop < navTop || activeTop + activeHeight > navTop + navHeight)
activeItem.scrollIntoView({ block: 'center' })
}),
{ immediate: true },
)
</script>
<template>
@ -37,7 +65,7 @@ const enableAside = computed(() => {
>
<div class="container">
<div v-if="enableAside" class="aside">
<div class="aside-container">
<div ref="asideEl" class="aside-container">
<div class="aside-content">
<PageAside />
</div>

View File

@ -2,14 +2,14 @@
import { computed } from 'vue'
import {
useContributors,
useData,
useEditNavLink,
useLastUpdated,
usePageNav,
useThemeLocaleData,
} from '../composables/index.js'
import AutoLink from './AutoLink.vue'
const themeLocale = useThemeLocaleData()
const { theme } = useData()
const editNavLink = useEditNavLink()
const { datetime: lastUpdated, isoDatetime, lastUpdatedText } = useLastUpdated()
const contributors = useContributors()
@ -42,7 +42,7 @@ const showFooter = computed(() => {
<div v-if="contributors && contributors.length" class="contributors">
<span class="contributors-label">
{{ themeLocale.contributorsText || 'Contributors' }}:
{{ theme.contributorsText || 'Contributors' }}:
</span>
<span class="contributors-info">
<template v-for="(contributor, index) in contributors" :key="contributor">
@ -57,13 +57,13 @@ const showFooter = computed(() => {
<nav v-if="prev?.link || next?.link" class="prev-next">
<div class="pager">
<AutoLink v-if="prev?.link" class="pager-link prev" :href="prev.link">
<span class="desc" v-html="themeLocale.prevPageLabel || 'Previous page'" />
<span class="desc" v-html="theme.prevPageLabel || 'Previous page'" />
<span class="title" v-html="prev.text" />
</AutoLink>
</div>
<div class="pager">
<AutoLink v-if="next?.link" class="pager-link next" :href="next.link">
<span class="desc" v-html="themeLocale.nextPageLabel || 'Next page'" />
<span class="desc" v-html="theme.nextPageLabel || 'Next page'" />
<span class="title" v-html="next.text" />
</AutoLink>
</div>

View File

@ -1,11 +1,11 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useReadingTimeLocale } from '@vuepress/plugin-reading-time/client'
import { useData, useExtraBlogData } from '../composables/index.js'
import { useData, useTagColors } from '../composables/index.js'
const { page, frontmatter: matter } = useData<'post'>()
const extraData = useExtraBlogData()
const colors = useTagColors()
const readingTime = useReadingTimeLocale()
const createTime = computed(() => {
@ -23,7 +23,7 @@ const tags = computed(() => {
if (matter.value.tags) {
return matter.value.tags.slice(0, 4).map(tag => ({
name: tag,
colors: extraData.value.tagsColorsPreset[extraData.value.tagsColors[tag]] ?? [],
className: `vp-tag-${colors.value[tag]}`,
}))
}
@ -65,7 +65,7 @@ const hasMeta = computed(() => readingTime.value.time || tags.value.length || cr
v-for="tag in tags"
:key="tag.name"
class="tag"
:style="{ '--vp-tag-color': tag.colors[0], '--vp-tag-bg-color': tag.colors[2] }"
:class="tag.className"
>
{{ tag.name }}
</span>
@ -151,7 +151,7 @@ const hasMeta = computed(() => readingTime.value.time || tags.value.length || cr
font-size: 12px;
line-height: 1;
color: var(--vp-tag-color, var(--vp-c-text-3));
background-color: var(--vp-tag-bg-color, var(--vp-c-default-soft));
background-color: var(--vp-tag-bg, var(--vp-c-default-soft));
border-radius: 3px;
}

View File

@ -1,6 +1,7 @@
<script lang="ts" setup>
import { useScrollLock } from '@vueuse/core'
import { ref, watch } from 'vue'
import { onMounted, ref, watch } from 'vue'
import { useRoutePath } from 'vuepress/client'
import { useSidebar } from '../composables/sidebar.js'
import { inBrowser } from '../utils/index.js'
import SidebarItem from './SidebarItem.vue'
@ -11,6 +12,7 @@ const props = defineProps<{
}>()
const { sidebarGroups, hasSidebar, sidebarKey } = useSidebar()
const routePath = useRoutePath()
// a11y: focus Nav element when menu has opened
const navEl = ref<HTMLElement | null>(null)
@ -27,6 +29,21 @@ watch(
},
{ immediate: true, flush: 'post' },
)
onMounted(() => {
const activeItem = document.querySelector(
`.sidebar-wrapper .auto-link[href*="${routePath.value}"]`,
)
if (!activeItem || !navEl.value)
return
const { top: navTop, height: navHeight } = navEl.value.getBoundingClientRect()
const { top: activeTop, height: activeHeight }
= activeItem.getBoundingClientRect()
if (activeTop < navTop || activeTop + activeHeight > navTop + navHeight)
activeItem.scrollIntoView({ block: 'center' })
})
</script>
<template>

View File

@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed } from 'vue'
import { useRouter } from 'vuepress/client'
import { EXTERNAL_URL_RE } from '../utils/index.js'
import { isLinkExternal } from 'vuepress/shared'
interface Props {
tag?: string
@ -20,7 +20,7 @@ const props = withDefaults(defineProps<Props>(), {
const router = useRouter()
const isExternal = computed(
() => props.href && EXTERNAL_URL_RE.test(props.href),
() => props.href && isLinkExternal(props.href),
)
const component = computed(() => {

View File

@ -1,10 +1,10 @@
<script setup lang="ts">
import { useCssVar } from '@vueuse/core'
import { onMounted, ref } from 'vue'
import { useSidebar, useThemeLocaleData } from '../composables/index.js'
import { useData, useSidebar } from '../composables/index.js'
import { inBrowser } from '../utils/index.js'
const theme = useThemeLocaleData()
const { theme } = useData()
const { hasSidebar } = useSidebar()
const footerHeight = useCssVar('--vp-footer-height', inBrowser ? document.body : null)

View File

@ -1,11 +1,9 @@
<script lang="ts" setup>
import { withBase } from 'vuepress/client'
import type { ThemeImage } from '../../shared/index.js'
defineProps<{
image:
| string
| { src: string, alt?: string }
| { dark: string, light: string, alt?: string }
image: ThemeImage
alt?: string
}>()
</script>
@ -20,7 +18,7 @@ export default {
<template v-if="image">
<img
v-if="typeof image === 'string' || 'src' in image"
class="plume-image"
class="vp-image"
v-bind="typeof image === 'string' ? $attrs : { ...image, ...$attrs }"
:src="withBase(typeof image === 'string' ? image : image.src)"
:alt="alt ?? (typeof image === 'string' ? '' : image.alt || '')"
@ -43,11 +41,11 @@ export default {
</template>
<style scoped>
html:not(.dark) .plume-image.dark {
html:not(.dark) .vp-image.dark {
display: none;
}
.dark .plume-image.light {
.dark .vp-image.light {
display: none;
}
</style>

View File

@ -1,15 +1,11 @@
import { usePageLang } from 'vuepress/client'
import { useExtraBlogData as _useExtraBlogData, useBlogPostData } from '@vuepress-plume/plugin-blog-data/client'
import { type Ref, computed } from 'vue'
import { useBlogPostData } from '@vuepress-plume/plugin-blog-data/client'
import { computed } from 'vue'
import { useMediaQuery } from '@vueuse/core'
import type { PlumeThemeBlogPostItem } from '../../shared/index.js'
import { useData, useLocaleLink, useRouteQuery } from '../composables/index.js'
import { toArray } from '../utils/index.js'
export const useExtraBlogData = _useExtraBlogData as () => Ref<{
tagsColorsPreset: (readonly [string, string, string])[]
tagsColors: Record<string, number>
}>
import { useTagColors } from './tag-colors.js'
const DEFAULT_PER_PAGE = 10
@ -179,7 +175,7 @@ export type ShortPostItem = Pick<PlumeThemeBlogPostItem, 'title' | 'path' | 'cre
export function useTags() {
const list = useLocalePostList()
const extraData = useExtraBlogData()
const colors = useTagColors()
const tags = computed(() => {
const tagMap: Record<string, number> = {}
@ -196,7 +192,7 @@ export function useTags() {
return Object.keys(tagMap).map(tag => ({
name: tag,
count: tagMap[tag] > 99 ? '99+' : tagMap[tag],
colors: extraData.value.tagsColorsPreset[extraData.value.tagsColors[tag]] ?? [],
className: `vp-tag-${colors.value[tag]}`,
}))
})

View File

@ -3,6 +3,7 @@ import type { ThemeLocaleDataRef } from '@vuepress/plugin-theme-data/client'
import {
usePageData,
usePageFrontmatter,
usePageLang,
useSiteLocaleData,
} from 'vuepress/client'
import type {
@ -11,6 +12,7 @@ import type {
SiteLocaleDataRef,
} from 'vuepress/client'
import type {
PlumeThemeFriendsFrontmatter,
PlumeThemeLocaleData,
PlumeThemePageData,
PlumeThemePageFrontmatter,
@ -20,16 +22,19 @@ import { useThemeLocaleData } from './themeData.js'
import { hashRef } from './hash.js'
import { useDarkMode } from './darkMode.js'
type FrontmatterType = 'post' | 'page'
type FrontmatterType = 'post' | 'friends' | 'page'
type Frontmatter<T extends FrontmatterType = 'page'> = T extends 'post'
? PlumeThemePostFrontmatter
: PlumeThemePageFrontmatter
: T extends 'friends'
? PlumeThemeFriendsFrontmatter
: PlumeThemePageFrontmatter
export interface Data<T extends FrontmatterType = 'page'> {
theme: ThemeLocaleDataRef<PlumeThemeLocaleData>
page: PageDataRef<PlumeThemePageData>
frontmatter: PageFrontmatterRef<Frontmatter<T>>
lang: Ref<string>
hash: Ref<string>
site: SiteLocaleDataRef
isDark: Ref<boolean>
@ -41,6 +46,7 @@ export function useData<T extends FrontmatterType = 'page'>(): Data<T> {
const frontmatter = usePageFrontmatter<Frontmatter<T>>()
const site = useSiteLocaleData()
const isDark = useDarkMode()
const lang = usePageLang()
return { theme, page, frontmatter, hash: hashRef, site, isDark }
return { theme, page, frontmatter, lang, hash: hashRef, site, isDark }
}

View File

@ -6,6 +6,7 @@ export * from './sidebar.js'
export * from './aside.js'
export * from './page.js'
export * from './blog.js'
export * from './tag-colors.js'
export * from './locale.js'
export * from './useRouteQuery.js'
export * from './watermark.js'

View File

@ -1,14 +1,14 @@
import { resolveRoute, usePageData, useRouteLocale, withBase } from 'vuepress/client'
import { resolveRoute, useRouteLocale, withBase } from 'vuepress/client'
import { computed } from 'vue'
import type { PlumeThemePageData } from '../../shared/index.js'
import { useThemeData } from './themeData.js'
import { useData } from './data.js'
import { getSidebarFirstLink, getSidebarList, normalizePath, useNotesData } from './sidebar.js'
export function useLangs({
removeCurrent = true,
} = {}) {
const page = usePageData<PlumeThemePageData>()
const theme = useThemeData()
const { page } = useData()
const routeLocale = useRouteLocale()
const notesData = useNotesData()

View File

@ -1,6 +1,6 @@
import { onMounted, onUnmounted, onUpdated } from 'vue'
import type { Ref } from 'vue'
import type { PlumeThemeLocaleData } from '../../shared/index.js'
import type { ThemeOutline } from '../../shared/index.js'
import { throttleAndDebounce } from '../utils/index.js'
import { useAside } from './aside.js'
@ -41,7 +41,7 @@ export type MenuItem = Omit<Header, 'slug' | 'children'> & {
children?: MenuItem[]
}
export function getHeaders(range: PlumeThemeLocaleData['outline']): MenuItem[] {
export function getHeaders(range?: ThemeOutline): MenuItem[] {
const headers = Array.from(
document.querySelectorAll('.plume-content :where(h1,h2,h3,h4,h5,h6)'),
)
@ -68,8 +68,9 @@ function serializeHeader(h: Element): string {
if (
(node as Element).classList.contains('badge-view')
|| (node as Element).classList.contains('ignore-header')
)
) {
continue
}
ret += node.textContent
}
@ -88,7 +89,7 @@ function serializeHeader(h: Element): string {
return ret.trim()
}
export function resolveHeaders(headers: MenuItem[], range?: PlumeThemeLocaleData['outline']): MenuItem[] {
export function resolveHeaders(headers: MenuItem[], range?: ThemeOutline): MenuItem[] {
if (range === false)
return []

View File

@ -11,6 +11,7 @@ import { computed, onMounted, onUnmounted, ref, watch, watchEffect } from 'vue'
import type { PlumeThemePageData } from '../../shared/index.js'
import { isActive } from '../utils/index.js'
import { hashRef } from './hash.js'
import { useData } from './data.js'
export { useNotesData }
@ -57,8 +58,7 @@ export function getSidebarFirstLink(sidebar: NotesSidebarItem[]) {
export function useSidebar() {
const route = useRoute()
const notesData = useNotesData()
const frontmatter = usePageFrontmatter()
const page = usePageData<PlumeThemePageData>()
const { frontmatter } = useData()
const is960 = useMediaQuery('(min-width: 960px)')
@ -72,12 +72,15 @@ export function useSidebar() {
})
const sidebar = computed(() => {
return getSidebarList(route.path, notesData.value)
const link = typeof frontmatter.value.sidebar === 'string'
? frontmatter.value.sidebar
: route.path
return getSidebarList(link, notesData.value)
})
const hasSidebar = computed(() => {
return (
!frontmatter.value.home
&& !page.value.isBlogPost
&& sidebar.value.length > 0
&& frontmatter.value.sidebar !== false
)

View File

@ -0,0 +1,16 @@
import { articleTagColors } from '@internal/articleTagColors'
import { type Ref, ref } from 'vue'
export type TagColors = Record<string, string>
export type TagColorsRef = Ref<TagColors>
const tagColorsRef: TagColorsRef = ref(articleTagColors)
export const useTagColors = (): TagColorsRef => tagColorsRef
if (__VUEPRESS_DEV__ && (import.meta.webpackHot || import.meta.hot)) {
__VUE_HMR_RUNTIME__.updateArticleTagColor = (data: TagColors) => {
tagColorsRef.value = data
}
}

View File

@ -1,4 +1,4 @@
import './styles/index.scss'
import './styles/index.css'
import { defineClientConfig } from 'vuepress/client'
import type { ClientConfig } from 'vuepress/client'

View File

@ -16,10 +16,7 @@ import VFooter from '../components/VFooter.vue'
import BackToTop from '../components/BackToTop.vue'
import EncryptGlobal from '../components/EncryptGlobal.vue'
import TransitionFadeSlideY from '../components/TransitionFadeSlideY.vue'
import {
useCloseSidebarOnEscape,
useSidebar,
} from '../composables/index.js'
import { useCloseSidebarOnEscape, useSidebar } from '../composables/index.js'
import { useGlobalEncrypt, usePageEncrypt } from '../composables/encrypt.js'
const page = usePageData<PlumeThemePageData>()

View File

@ -6,3 +6,10 @@ declare module '*.vue' {
}
declare const __VUEPRESS_DEV__: string
declare module '@internal/articleTagColors' {
const articleTagColors: Record<string, string>
export {
articleTagColors,
}
}

View File

@ -0,0 +1,341 @@
.dark .vp-code span {
color: var(--shiki-dark, rgba(235, 235, 245, 0.6));
}
html:not(.dark) .vp-code span {
color: var(--shiki-light, rgba(60, 60, 67, 0.78));
}
.plume-content pre {
padding: 1.3rem 1.5rem;
margin: 0 0 0.85rem;
overflow-x: auto;
scrollbar-width: thin;
}
.plume-content pre code {
padding: 0;
font-size: var(--vp-code-font-size);
color: var(--vp-code-block-color);
overflow-wrap: unset;
background-color: transparent;
border-radius: 0;
transition: background-color, var(--t-color), color var(--t-color);
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
}
@media (min-width: 640px) {
.plume-content pre {
border-radius: 6px;
}
}
.plume-content .line-number {
font-family: var(--vp-font-family-mono);
}
div[class*="language-"] {
position: relative;
margin: 0.85rem -1.5rem;
background-color: var(--vp-code-block-bg);
transition: background-color, var(--t-color);
}
.plume-content .code-tabs div[class*="language-"] {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
@media (max-width: 639px) {
.plume-content li pre {
border-radius: 8px 0 0 8px;
}
}
div[class*="language-"]::before {
position: absolute;
top: 5px;
right: 1em;
z-index: 3;
font-size: 0.75rem;
color: var(--vp-code-line-number-color);
content: attr(data-ext);
transition: color var(--t-color);
}
div[class*="language-"] code {
display: inline-block;
width: fit-content;
min-width: 100%;
}
div[class*="language-"] pre {
position: relative;
z-index: 1;
background: transparent !important;
}
div[class*="language-"] pre,
div[class*="language-"] code {
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
/* rtl:ignore */
text-align: left;
word-break: normal;
word-wrap: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
white-space: pre;
word-spacing: normal;
/* rtl:ignore */
direction: ltr;
}
div[class*="language-"] .highlight-lines {
position: absolute;
top: 0;
left: 0;
width: 100%;
padding-top: 1.3rem;
line-height: 1.5;
user-select: none;
}
div[class*="language-"] .highlight-lines .highlight-line {
background-color: var(--vp-c-default-soft);
transition: background-color var(--t-color);
}
div[class*="language-"]:not(.line-numbers-mode) .line-numbers {
display: none;
}
div[class*="language-"].line-numbers-mode .highlight-lines .highlight-line {
position: relative;
}
div[class*="language-"].line-numbers-mode .highlight-lines .highlight-line::before {
position: absolute;
top: 0;
left: 0;
z-index: 2;
display: block;
height: 100%;
content: " ";
}
div[class*="language-"].line-numbers-mode pre {
padding-left: 1rem;
margin-left: 2rem;
vertical-align: middle;
}
div[class*="language-"].line-numbers-mode .line-numbers {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 2rem;
height: 100%;
padding-top: 1.3rem;
line-height: 1.4rem;
color: var(--vp-code-line-number-color);
text-align: center;
counter-reset: line-number;
border-right: var(--vp-code-block-divider-color) 1px solid;
transition: border-right var(--t-color), color var(--t-color);
}
div[class*="language-"].line-numbers-mode .line-numbers .line-number {
position: relative;
z-index: 3;
height: 1.5rem;
user-select: none;
}
div[class*="language-"].line-numbers-mode .line-numbers .line-number::before {
font-size: 0.85em;
content: counter(line-number);
counter-increment: line-number;
}
@media (min-width: 640px) {
div[class*="language-"] {
margin: 0;
border-radius: 6px;
}
}
@media (max-width: 639px) {
.plume-content li div[class*="language-"] {
border-radius: 8px 0 0 8px;
}
}
.plume-content div[class*="language-"] code .highlighted {
z-index: 2;
display: inline-block;
width: calc(100% + 48px);
padding: 0 24px;
margin: 0 -24px;
background-color: var(--vp-code-line-highlight-color);
transition: background-color 0.5s;
}
.plume-content div[class*="language-"] code .highlighted.error {
background-color: var(--vp-code-line-error-color);
}
.plume-content div[class*="language-"] code .highlighted.warning {
background-color: var(--vp-code-line-warning-color);
}
.plume-content div[class*="language-"] code .highlighted-word {
padding: 1px 3px;
margin: -1px -3px;
background-color: var(--vp-c-gray-soft);
border: 1px solid var(--vp-c-border);
border-radius: 4px;
}
.plume-content div[class*="language-"] code .tab,
.plume-content div[class*="language-"] code .space {
position: relative;
}
.plume-content div[class*="language-"] code .tab::before {
position: absolute;
content: "⇥";
opacity: 0.3;
}
.plume-content div[class*="language-"] code .space::before {
position: absolute;
content: "·";
opacity: 0.3;
}
.plume-content div[class*="language-"] code .diff {
display: inline-block;
width: calc(100% + 48px);
padding: 0 24px;
margin: 0 -24px;
transition: background-color 0.5s;
}
.plume-content div[class*="language-"] code .diff::before {
position: absolute;
left: 10px;
}
.plume-content div[class*="language-"] code .diff.remove {
background-color: var(--vp-code-line-diff-remove-color);
opacity: 0.7;
}
.plume-content div[class*="language-"] code .diff.remove::before {
color: var(--vp-code-line-diff-remove-symbol-color);
content: "-";
transform: translateX(-6px);
}
.plume-content div[class*="language-"] code .diff.add {
background-color: var(--vp-code-line-diff-add-color);
}
.plume-content div[class*="language-"] code .diff.add::before {
color: var(--vp-code-line-diff-add-symbol-color);
content: "+";
transform: translateX(-6px);
}
.plume-content div[class*="language-"] .has-focused-lines .line:not(.has-focus) {
filter: blur(0.095rem);
opacity: 0.7;
transition: filter 0.35s, opacity 0.35s;
}
.plume-content div[class*="language-"]:hover .has-focused-lines .line:not(.has-focus) {
filter: blur(0);
opacity: 1;
}
div[class*="language-"] button.copy {
position: absolute;
top: 12px;
/* rtl:ignore */
right: 12px;
z-index: 3;
width: 40px;
height: 40px;
cursor: pointer;
background-color: var(--vp-code-copy-code-bg);
background-image: var(--vp-icon-copy);
background-repeat: no-repeat;
background-position: 50%;
background-size: 20px;
border: 1px solid var(--vp-code-copy-code-border-color);
border-radius: 4px;
opacity: 0;
transition: border-color 0.25s, background-color 0.25s, opacity 0.25s;
/* rtl:ignore */
direction: ltr;
}
div[class*="language-"]:hover > button.copy,
div[class*="language-"] > button.copy:focus,
div[class*="language-"] > button.copy.copied {
opacity: 1;
}
div[class*="language-"] > button.copy:hover,
div[class*="language-"] > button.copy.copied {
background-color: var(--vp-code-copy-code-hover-bg);
border-color: var(--vp-code-copy-code-hover-border-color);
}
div[class*="language-"] > button.copy.copied,
div[class*="language-"] > button.copy:hover.copied {
background-color: var(--vp-code-copy-code-hover-bg);
background-image: var(--vp-icon-copied);
/* rtl:ignore */
border-radius: 0 4px 4px 0;
}
div[class*="language-"] > button.copy.copied::before,
div[class*="language-"] > button.copy:hover.copied::before {
position: relative;
top: -1px;
display: flex;
align-items: center;
justify-content: center;
width: fit-content;
height: 40px;
padding: 0 10px;
font-size: 12px;
font-weight: 500;
color: var(--vp-code-copy-code-active-text);
text-align: center;
white-space: nowrap;
content: attr(data-copied);
background-color: var(--vp-code-copy-code-hover-bg);
border: 1px solid var(--vp-code-copy-code-hover-border-color);
/* rtl:ignore */
border-right: 0;
border-radius: 4px 0 0 4px;
/* rtl:ignore */
transform: translateX(calc(-100% - 1px));
}

View File

@ -1,359 +0,0 @@
.dark .vp-code span {
color: var(--shiki-dark, rgba(235, 235, 245, 0.6));
}
html:not(.dark) .vp-code span {
color: var(--shiki-light, rgba(60, 60, 67, 0.78));
}
.plume-content {
pre {
padding: 1.3rem 1.5rem;
margin: 0 0 0.85rem;
overflow-x: auto;
scrollbar-width: thin;
code {
padding: 0;
font-size: var(--vp-code-font-size);
color: var(--vp-code-block-color);
overflow-wrap: unset;
background-color: transparent;
border-radius: 0;
transition: background-color, var(--t-color), color var(--t-color);
-webkit-font-smoothing: auto;
-moz-osx-font-smoothing: auto;
}
@media (min-width: 640px) {
& {
border-radius: 6px;
}
}
}
.line-number {
font-family: var(--vp-font-family-mono);
}
.code-tabs {
.div[class*="language-"] {
border-top-left-radius: 0;
border-top-right-radius: 0;
}
}
}
@media (max-width: 639px) {
.plume-content li pre {
border-radius: 8px 0 0 8px;
}
}
div[class*="language-"] {
position: relative;
margin: 0.85rem -1.5rem;
background-color: var(--vp-code-block-bg);
transition: background-color, var(--t-color);
&::before {
position: absolute;
top: 5px;
right: 1em;
z-index: 3;
font-size: 0.75rem;
color: var(--vp-code-line-number-color);
content: attr(data-ext);
transition: color var(--t-color);
}
code {
display: inline-block;
width: fit-content;
min-width: 100%;
}
pre {
position: relative;
z-index: 1;
// force override the background color to be compatible with shiki
background: transparent !important;
}
pre,
code {
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
/* rtl:ignore */
text-align: left;
word-break: normal;
word-wrap: normal;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
white-space: pre;
word-spacing: normal;
/* rtl:ignore */
direction: ltr;
}
.highlight-lines {
position: absolute;
top: 0;
left: 0;
width: 100%;
padding-top: 1.3rem;
line-height: 1.5;
user-select: none;
.highlight-line {
background-color: var(--vp-c-default-soft);
transition: background-color var(--t-color);
}
}
&:not(.line-numbers-mode) {
.line-numbers {
display: none;
}
}
&.line-numbers-mode {
.highlight-lines .highlight-line {
position: relative;
&::before {
position: absolute;
top: 0;
left: 0;
z-index: 2;
display: block;
height: 100%;
content: " ";
}
}
pre {
padding-left: 1rem;
margin-left: 2rem;
vertical-align: middle;
}
.line-numbers {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 2rem;
height: 100%;
padding-top: 1.3rem;
line-height: 1.4rem;
color: var(--vp-code-line-number-color);
text-align: center;
counter-reset: line-number;
border-right: var(--vp-code-block-divider-color) 1px solid;
transition: border-right var(--t-color), color var(--t-color);
.line-number {
position: relative;
z-index: 3;
height: 1.5rem;
user-select: none;
&::before {
font-size: 0.85em;
content: counter(line-number);
counter-increment: line-number;
}
}
}
}
@media (min-width: 640px) {
& {
margin: 0;
border-radius: 6px;
}
}
@media (max-width: 639px) {
.plume-content li & {
border-radius: 8px 0 0 8px;
}
}
}
.plume-content [class*="language-"] code .highlighted {
z-index: 2;
display: inline-block;
width: calc(100% + 2 * 24px);
padding: 0 24px;
margin: 0 -24px;
background-color: var(--vp-code-line-highlight-color);
transition: background-color 0.5s;
&.error {
background-color: var(--vp-code-line-error-color);
}
&.warning {
background-color: var(--vp-code-line-warning-color);
}
}
.plume-content [class*="language-"] code .highlighted-word {
padding: 1px 3px;
margin: -1px -3px;
background-color: var(--vp-c-gray-soft);
border: 1px solid var(--vp-c-border);
border-radius: 4px;
}
.plume-content [class*="language-"] code {
.tab,
.space {
position: relative;
}
.tab::before {
position: absolute;
content: "";
opacity: 0.3;
}
.space::before {
position: absolute;
content: "·";
opacity: 0.3;
}
}
.plume-content [class*="language-"] code .diff {
display: inline-block;
width: calc(100% + 2 * 24px);
padding: 0 24px;
margin: 0 -24px;
transition: background-color 0.5s;
/* stylelint-disable-next-line no-descending-specificity */
&::before {
position: absolute;
left: 10px;
}
&.remove {
background-color: var(--vp-code-line-diff-remove-color);
opacity: 0.7;
}
&.remove::before {
color: var(--vp-code-line-diff-remove-symbol-color);
content: "-";
transform: translateX(-6px);
}
&.add {
background-color: var(--vp-code-line-diff-add-color);
}
&.add::before {
color: var(--vp-code-line-diff-add-symbol-color);
content: "+";
transform: translateX(-6px);
}
}
.plume-content [class*="language-"] .has-focused-lines .line:not(.has-focus) {
filter: blur(0.095rem);
opacity: 0.7;
transition:
filter 0.35s,
opacity 0.35s;
}
.plume-content [class*="language-"]:hover .has-focused-lines .line:not(.has-focus) {
filter: blur(0);
opacity: 1;
}
[class*="language-"] button.copy {
position: absolute;
top: 12px;
/* rtl:ignore */
right: 12px;
z-index: 3;
width: 40px;
height: 40px;
cursor: pointer;
background-color: var(--vp-code-copy-code-bg);
background-image: var(--vp-icon-copy);
background-repeat: no-repeat;
background-position: 50%;
background-size: 20px;
border: 1px solid var(--vp-code-copy-code-border-color);
border-radius: 4px;
opacity: 0;
transition:
border-color 0.25s,
background-color 0.25s,
opacity 0.25s;
/* rtl:ignore */
direction: ltr;
}
[class*="language-"]:hover > button.copy,
[class*="language-"] > button.copy:focus,
[class*="language-"] > button.copy.copied {
opacity: 1;
}
[class*="language-"] > button.copy:hover,
[class*="language-"] > button.copy.copied {
background-color: var(--vp-code-copy-code-hover-bg);
border-color: var(--vp-code-copy-code-hover-border-color);
}
[class*="language-"] > button.copy.copied,
[class*="language-"] > button.copy:hover.copied {
background-color: var(--vp-code-copy-code-hover-bg);
background-image: var(--vp-icon-copied);
/* rtl:ignore */
border-radius: 0 4px 4px 0;
}
[class*="language-"] > button.copy.copied::before,
[class*="language-"] > button.copy:hover.copied::before {
position: relative;
top: -1px;
display: flex;
align-items: center;
justify-content: center;
width: fit-content;
height: 40px;
padding: 0 10px;
font-size: 12px;
font-weight: 500;
color: var(--vp-code-copy-code-active-text);
text-align: center;
white-space: nowrap;
content: attr(data-copied);
background-color: var(--vp-code-copy-code-hover-bg);
border: 1px solid var(--vp-code-copy-code-hover-border-color);
/* rtl:ignore */
border-right: 0;
border-radius: 4px 0 0 4px;
/* rtl:ignore */
transform: translateX(calc(-100% - 1px));
}

View File

@ -5,7 +5,6 @@
/**
* Headings
* -------------------------------------------------------------------------- */
.plume-content h1,
.plume-content h2,
.plume-content h3,
@ -52,27 +51,27 @@
position: relative;
color: inherit;
text-decoration: none;
}
&:hover::before {
position: absolute;
left: -0.75em;
font-size: 0.8em;
color: var(--vp-c-brand-1);
content: var(--vp-header-anchor-symbol);
transition: color var(--t-color);
}
.plume-content .header-anchor:hover::before {
position: absolute;
left: -0.75em;
font-size: 0.8em;
color: var(--vp-c-brand-1);
content: var(--vp-header-anchor-symbol);
transition: color var(--t-color);
}
&:focus-visible {
outline: none;
.plume-content .header-anchor:focus-visible {
outline: none;
}
&::before {
position: absolute;
left: -0.75em;
color: var(--vp-c-brand-1);
content: var(--vp-header-anchor-symbol);
outline: auto;
}
}
.plume-content .header-anchor:focus-visible::before {
position: absolute;
left: -0.75em;
color: var(--vp-c-brand-1);
content: var(--vp-header-anchor-symbol);
outline: auto;
}
@media (min-width: 768px) {
@ -98,7 +97,6 @@
/**
* Paragraph and inline elements
* -------------------------------------------------------------------------- */
.plume-content p,
.plume-content summary {
margin: 16px 0;
@ -129,22 +127,16 @@
color: var(--vp-c-brand-1);
text-decoration: underline;
text-underline-offset: 2px;
transition:
color var(--t-color),
opacity var(--t-color),
text-underline-offset var(--t-color);
transition: color var(--t-color), opacity var(--t-color), text-underline-offset var(--t-color);
}
@media print {
&[href^="http://"],
&[href^="https://"] {
&::after {
content: " (" attr(href) ") ";
}
}
@media print {
.plume-content a[href^="http://"]::after, .plume-content a[href^="https://"]::after {
content: " (" attr(href) ") ";
}
}
.plume-content :not(h1,h2,h3,h4,h5,h6) a:hover {
.plume-content :not(h1, h2, h3, h4, h5, h6) a:hover {
color: var(--vp-c-brand-2);
text-underline-offset: 5px;
}
@ -156,7 +148,6 @@
/**
* Lists
* -------------------------------------------------------------------------- */
.plume-content ul,
.plume-content ol {
padding-left: 1.25rem;
@ -183,7 +174,6 @@
/**
* Table
* -------------------------------------------------------------------------- */
.plume-content table {
display: block;
margin: 20px 0;
@ -226,7 +216,6 @@
/**
* Decorational elements
* -------------------------------------------------------------------------- */
.plume-content hr {
margin: 16px 0;
border: none;
@ -249,9 +238,7 @@
padding: 3px 6px;
background-color: var(--vp-code-bg);
border-radius: 4px;
transition:
color var(--t-color),
background-color var(--t-color);
transition: color var(--t-color), background-color var(--t-color);
}
.plume-content h1 > code,
@ -272,7 +259,7 @@
/**
* External links
* -------------------------------------------------------------------------- */
:is(.vp-external-link-icon, .plume-content a[href*='://'], .plume-content a[target='_blank']):not(.no-icon)::after {
:is(.vp-external-link-icon, .plume-content a[href*="://"], .plume-content a[target=_blank]):not(.no-icon)::after {
--icon: url("data:image/svg+xml, %3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' %3E%3Cpath d='M0 0h24v24H0V0z' fill='none' /%3E%3Cpath d='M9 5v2h6.59L4 18.59 5.41 20 17 8.41V15h2V5H9z' /%3E%3C/svg%3E");
display: inline-block;
@ -292,7 +279,7 @@
}
/* prettier-ignore */
.external-link-icon-enabled :is(.plume-content a[href*='://'], .plume-content a[target='_blank'])::after {
.external-link-icon-enabled :is(.plume-content a[href*="://"], .plume-content a[target=_blank])::after {
color: currentcolor;
content: "";
}

View File

@ -23,7 +23,6 @@
mask-size: 100% 100%;
}
/* internal icons - used under ISC from https://lucide.dev/ */
.vpi-align-left {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' stroke='currentColor' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath d='M21 6H3M15 12H3M17 18H3'/%3E%3C/svg%3E");

View File

@ -0,0 +1,14 @@
@charset "UTF-8";
@import url("./vars.css");
@import url("./normalize.css");
@import url("./icons.css");
@import url("./social-icons.css");
@import url("./nprogress.css");
@import url("./utils.css");
@import url("./content.css");
@import url("./code.css");
@import url("./twoslash.css");
@import url("./md-enhance.css");
@import url("./search.css");

View File

@ -1,12 +0,0 @@
@import "vars";
@import "normalize";
@import "icons";
@import "social-icons";
@import "nprogress";
@import "utils";
@import "content";
@import "code";
@import "twoslash";
@import "md-enhance";
@import "search";

View File

@ -0,0 +1,756 @@
/* stylelint-disable no-descending-specificity */
/* ------------------ Markdown Enhance: Hint Container ------------------ */
.plume-content .hint-container {
padding: 16px 16px 8px;
font-size: var(--vp-custom-block-font-size);
line-height: 24px;
color: var(--vp-c-text-2);
border-radius: 8px;
}
.plume-content .hint-container .hint-container-title {
margin-top: 0;
font-weight: 600;
}
.plume-content .hint-container p + p {
margin: 8px 0;
}
.plume-content .hint-container code {
font-size: var(--vp-custom-block-code-font-size);
color: inherit;
}
.plume-content .hint-container th,
.plume-content .hint-container blockquote > p {
font-size: var(--vp-custom-block-font-size);
color: inherit;
}
.plume-content .hint-container div[class*="language-"] {
margin: 8px 0;
}
.plume-content .hint-container .vp-code-tab div[class*="language-"] {
margin: 0 0 8px;
}
.plume-content .hint-container div[class*="language-"] code {
font-weight: 400;
background-color: transparent;
}
.plume-content .hint-container div[class*="language-"].line-numbers-mode .line-numbers {
line-height: 1.5rem;
}
@media (max-width: 419px) {
.plume-content .hint-container div[class*="language-"] {
margin: 0.85rem -0.75rem 0.85rem -1rem;
}
.plume-content .hint-container .vp-code-tab div[class*="language-"] {
margin: 0 -0.75rem 0.85rem -1rem;
}
}
.plume-content .hint-container.note {
color: var(--vp-c-text-3);
border-radius: 0;
}
.plume-content .hint-container.info {
color: var(--vp-custom-block-info-text);
}
.plume-content .hint-container.tip {
color: var(--vp-custom-block-tip-text);
}
.plume-content .hint-container.warning {
color: var(--vp-custom-block-warning-text);
}
.plume-content .hint-container.caution {
color: var(--vp-custom-block-danger-text);
}
.plume-content .hint-container.detail {
color: var(--vp-custom-block-detail-text);
}
.plume-content .hint-container.detail summary {
margin: -1.5rem -1.5rem -1.1rem;
font-weight: 700;
color: var(--vp-c-text-1);
cursor: pointer;
}
.plume-content .hint-container.detail summary + p {
margin: 8px 0;
}
.plume-content .hint-container.note a,
.plume-content .hint-container.note code,
.plume-content .hint-container.info a,
.plume-content .hint-container.info code,
.plume-content .hint-container.tip a,
.plume-content .hint-container.tip code,
.plume-content .hint-container.detail a,
.plume-content .hint-container.detail code {
color: var(--vp-c-brand-1);
}
.plume-content .hint-container.note a:hover,
.plume-content .hint-container.info a:hover,
.plume-content .hint-container.tip a:hover,
.plume-content .hint-container.detail a:hover {
color: var(--vp-c-brand-2);
}
.plume-content .hint-container.important a,
.plume-content .hint-container.important code {
color: var(--vp-c-purple-1);
}
.plume-content .hint-container.important a:hover {
color: var(--vp-c-purple-2);
}
.plume-content .hint-container.warning a,
.plume-content .hint-container.warning code {
color: var(--vp-c-warning-1);
}
.plume-content .hint-container.warning a:hover {
color: var(--vp-c-warning-2);
}
.plume-content .hint-container.caution a,
.plume-content .hint-container.caution code {
color: var(--vp-c-danger-1);
}
.plume-content .hint-container.caution a:hover {
color: var(--vp-c-danger-2);
}
.plume-content .hint-container [class*="language-"] .line-numbers {
padding-top: 21px;
}
/* ------------------ Markdown Enhance: Code Tabs ----------------------- */
.plume-content .code-tabs-nav {
margin-bottom: 0;
}
.plume-content .vp-code-tabs-nav {
padding: 0 12px;
margin: 0.85rem 0 0;
overflow-y: hidden;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--t-color), box-shadow var(--t-color);
}
.plume-content .vp-code-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--t-color);
}
.plume-content .vp-code-tab-nav::before {
display: none;
}
.plume-content .vp-code-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--t-color);
}
.plume-content .vp-code-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.plume-content .vp-code-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.plume-content .vp-code-tab-nav:hover {
background: transparent;
}
@media (max-width: 419px) {
.plume-content .vp-code-tabs-nav {
margin: 0 -1.5rem -0.85rem;
}
.plume-content .hint-container .vp-code-tabs-nav {
margin: 0.85rem -0.75rem 0 -1rem;
}
}
/* -------------------- Markdown Enhance: Code Demo -------------------- */
.plume-content .vp-code-demo {
overflow: hidden;
border: solid 1px var(--vp-c-divider);
transition: border var(--t-color);
}
@media (max-width: 419px) {
.plume-content .vp-code-demo .vp-code-demo-codes div[class*="language-"] {
margin: 0;
border-radius: 0;
}
}
.plume-content .vp-code-demo:hover {
box-shadow: none;
}
.plume-content .vp-code-demo .vp-code-demo-header {
padding: 8px 12px;
transition: background-color var(--t-color);
}
.plume-content .vp-code-demo .vp-code-demo-code-wrapper {
margin-bottom: -0.9rem;
}
.plume-content .vp-code-demo .vp-code-demo-toggle-button {
margin: 0 12px 0 8px;
background-color: var(--vp-c-gray-2);
transition: background-color var(--t-color);
}
.plume-content .vp-code-demo .vp-code-demo-toggle-button:hover {
background-color: var(--vp-c-gray-1);
}
.plume-content .vp-code-demo .vp-code-demo-title {
font-size: 1rem;
line-height: 1.75;
}
.plume-content .vp-code-demo .vp-code-demo-display {
border-bottom: transparent;
}
.plume-content .vp-code-demo .code-demo-jsfiddle .jsfiddle-button,
.plume-content .vp-code-demo .code-demo-codepen .codepen-button {
background-color: transparent;
}
.plume-content .vp-code-demo .vp-code-demo-codes div[class*="language-"] {
border-bottom: 2px dashed var(--vp-c-divider);
transition: border-bottom var(--t-color);
}
.plume-content .vp-code-demo .vp-code-demo-codes div[class*="language-"]:first-of-type {
border-top: 1px solid var(--vp-c-divider);
}
.plume-content .vp-code-demo .vp-code-demo-codes div[class*="language-"]:last-of-type {
border-bottom: none;
}
.plume-content .vp-code-demo .vp-code-demo-codes div[class*="language-"] pre {
margin-bottom: 0;
border-radius: 0;
}
@media (max-width: 419px) {
.plume-content .vp-code-demo {
margin: 8px -12px;
}
}
/* -------------------- Markdown Enhance: markdown Demo -------------------- */
.plume-content .vp-md-demo {
margin-bottom: 16px;
overflow: hidden;
border: solid 1px var(--vp-c-divider);
transition: border var(--t-color);
}
@media (max-width: 419px) {
.plume-content .vp-md-demo .vp-md-demo-codes div[class*="language-"] {
margin: 0;
border-radius: 0;
}
}
.plume-content .vp-md-demo:hover {
box-shadow: none;
}
.plume-content .vp-md-demo .vp-md-demo-header {
padding: 8px 12px;
font-size: 16px;
line-height: 1.7;
transition: background-color var(--t-color);
}
.plume-content .vp-md-demo .vp-md-demo-toggle-button {
margin: 0 12px 0 8px;
background-color: var(--vp-c-gray-2);
transition: background-color var(--t-color);
}
.plume-content .vp-md-demo .vp-md-demo-toggle-button:hover {
background-color: var(--vp-c-gray-1);
}
.plume-content .vp-md-demo .vp-md-demo-title {
font-size: 1rem;
line-height: 1.75;
}
.plume-content .vp-md-demo .vp-md-demo-display {
border-bottom: transparent;
}
.plume-content .vp-md-demo .vp-md-demo-codes div[class*="language-"] {
border-bottom: 2px dashed var(--vp-c-divider);
transition: border-bottom var(--t-color);
}
.plume-content .vp-md-demo .vp-md-demo-codes div[class*="language-"]:first-of-type {
border-top: 1px solid var(--vp-c-divider);
}
.plume-content .vp-md-demo .vp-md-demo-codes div[class*="language-"]:last-of-type {
border-bottom: none;
}
.plume-content .vp-md-demo .vp-md-demo-codes div[class*="language-"] pre {
margin-bottom: 0;
border-radius: 0;
}
@media (max-width: 419px) {
.plume-content .vp-md-demo {
margin: 8px -12px;
}
}
/* ---------------------- Markdown Enhance: Task List ---------------------- */
.plume-content .task-list-container {
padding-left: 0;
}
.plume-content .task-list-container .task-list-item input {
width: 0;
height: 0;
padding: 0;
margin: 0;
}
.plume-content .task-list-container .task-list-item label {
margin-left: 1.2em;
}
.plume-content .task-list-container .task-list-item input::before,
.plume-content .task-list-container .task-list-item input::after {
position: absolute;
top: -1em;
left: 0;
display: inline-block;
font-size: 1em;
content: none;
}
.plume-content .task-list-container .task-list-item input::after {
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23c2c2c4" d="M26 27.5H6A1.5 1.5 0 0 1 4.5 26V6c0-.83.67-1.5 1.5-1.5h20c.828 0 1.5.67 1.5 1.5v20a1.5 1.5 0 0 1-1.5 1.5m-18.5-3h17v-17h-17z"%2F%3E%3C%2Fsvg%3E');
background-color: transparent;
border: none;
}
.plume-content .task-list-container .task-list-item input:checked[disabled]::after {
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23299764" d="M29.548 3.043a2.5 2.5 0 0 0-3.513.4L16 16.067l-3.508-4.414a2.5 2.5 0 0 0-3.915 3.112l5.465 6.875c.474.597 1.195.943 1.957.943s1.482-.35 1.957-.944L29.95 6.555c.86-1.08.68-2.654-.402-3.513zM24.5 24.5h-17v-17h12.756l2.385-3H6c-.83 0-1.5.67-1.5 1.5v20c0 .828.67 1.5 1.5 1.5h20a1.5 1.5 0 0 0 1.5-1.5V12.85l-3 3.774z"%2F%3E%3C%2Fsvg%3E');
background-color: transparent;
border: none;
}
/* ---------------------------- Markdown Enhance: Tabs ----------------------------- */
.plume-content .vp-tabs {
margin: 1.5rem -0.75rem;
overflow: hidden;
border: 1px solid var(--vp-c-divider);
transition: border var(--t-color);
}
.plume-content .vp-tabs-nav {
padding: 0 12px;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--t-color), box-shadow var(--t-color);
}
.plume-content .vp-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--t-color);
}
.plume-content .vp-tab-nav::before {
display: none;
}
.plume-content .vp-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--t-color);
}
.plume-content .vp-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.plume-content .vp-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.plume-content .vp-tab-nav:hover {
background: transparent;
}
@media (min-width: 419px) {
.plume-content .vp-tabs {
margin: 1.5rem 0;
}
}
.plume-content .hint-container .vp-tabs {
margin: 1rem -0.45rem 1rem -0.75rem;
}
.plume-content .hint-container .vp-tabs .vp-tabs-nav {
background: var(--vp-c-default-soft);
}
.plume-content .hint-container .vp-tabs .vp-tab {
padding: 0.45rem 0.75rem;
font-size: 14px;
background: transparent;
}
.plume-content .hint-container .vp-tabs .vp-tab p {
margin: 8px 0;
}
/* --------------------- Markdown Enhance: Footnote -------------------------------- */
.plume-content .footnotes-sep {
margin-top: 48px;
}
.plume-content .footnotes {
position: relative;
padding: 48px 0 12px 16px;
margin-left: -16px;
font-size: 14px;
border-left: 4px solid var(--vp-c-default-soft);
}
@media (max-width: 419px) {
.plume-content .footnotes {
margin-left: 0;
}
}
.plume-content .footnotes::before {
position: absolute;
top: 12px;
left: 16px;
font-size: 16px;
font-weight: 700;
}
[lang="zh-CN"] .plume-content .footnotes::before {
content: "脚注:";
}
[lang="en-US"] .plume-content .footnotes::before {
content: "Footnotes:";
}
.plume-content .footnotes ol {
margin: 0;
}
.plume-content .footnotes ol p {
margin: 8px 0;
}
.plume-content .footnotes ol li:first-of-type p:first-of-type {
margin-top: 0;
}
.plume-content .footnotes ol li:last-of-type p:last-of-type {
margin-bottom: 0;
}
.plume-content .footnote-item {
padding-top: 0;
margin-top: 0;
}
.plume-content .footnote-item > p {
margin-bottom: 0;
}
.plume-content .footnote-backref {
position: relative;
color: transparent;
text-decoration: none;
}
.plume-content .footnote-backref:hover {
color: transparent;
}
.plume-content .footnote-backref::before {
position: absolute;
top: -0.4em;
left: 0;
font-size: 1em;
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 48 48"%3E%3Cg fill="none" stroke="%23c2c2c4" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"%3E%3Cpath d="m13 8l-7 6l7 7"%2F%3E%3Cpath d="M6 14h22.994c6.883 0 12.728 5.62 12.996 12.5c.284 7.27-5.723 13.5-12.996 13.5H11.998"%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E');
}
.plume-content .footnote-anchor {
top: 0;
}
/* -------------- Markdown Enhance: Image Figure --------------------- */
.plume-content figure {
position: relative;
display: flex;
flex-direction: column;
width: auto;
margin: 1rem auto;
text-align: center;
}
.plume-content figure img {
margin: 0 auto;
overflow: hidden;
}
@media print {
.plume-content figure > a[href^="http://"]::after, .plume-content figure > a[href^="https://"]::after {
content: "";
}
}
.plume-content figure > a .external-icon {
display: none;
}
.plume-content figure figcaption {
display: inline-block;
margin: 6px auto;
font-size: 0.8rem;
}
/* --------------------- demo-wrapper ------------------------ */
.plume-content .demo-wrapper {
display: flex;
flex-direction: column;
min-height: 40px;
margin: 40px -16px;
border: solid 1px var(--vp-c-divider);
border-radius: 8px;
box-shadow: var(--vp-shadow-2);
transition: var(--t-color);
transition-property: border, box-shadow;
}
.plume-content .demo-wrapper.has-title .demo-head {
border-bottom-color: transparent;
}
.plume-content .demo-wrapper.only-img {
overflow: hidden;
}
.plume-content .demo-wrapper.only-img img {
display: block;
}
.plume-content .demo-wrapper.only-img .demo-container,
.plume-content .demo-wrapper.no-padding .demo-container {
padding: 0;
}
.plume-content .demo-wrapper.has-height .demo-container {
height: var(--demo-container-height);
overflow-y: auto;
}
.plume-content .demo-wrapper .demo-head {
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 0;
border-bottom: solid 1px var(--vp-c-divider);
transition: border-bottom var(--t-color);
}
.plume-content .demo-wrapper .demo-ctrl {
display: flex;
gap: 5px;
align-items: center;
justify-content: flex-start;
padding: 5px 0 5px 8px;
}
.plume-content .demo-wrapper .demo-ctrl i {
display: inline-block;
width: 10px;
height: 10px;
background-color: #ccc;
border-radius: 100%;
transition: background-color var(--t-color);
}
.plume-content .demo-wrapper .demo-ctrl i:nth-child(1) {
background-color: var(--vp-c-danger-3);
}
.plume-content .demo-wrapper .demo-ctrl i:nth-child(2) {
background-color: var(--vp-c-warning-3);
}
.plume-content .demo-wrapper .demo-ctrl i:nth-child(3) {
background-color: var(--vp-c-green-3);
}
.plume-content .demo-wrapper .demo-title {
position: relative;
min-width: 0;
padding: 0 16px;
margin: 0 20px -1px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
background-color: var(--vp-c-bg-alt);
border-top-left-radius: 8px;
border-top-right-radius: 8px;
transition: var(--t-color);
transition-property: color, background-color;
}
.plume-content .demo-wrapper .demo-title p {
max-width: 100%;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
text-wrap: nowrap;
}
.plume-content .demo-wrapper .demo-title::after,
.plume-content .demo-wrapper .demo-title::before {
position: absolute;
bottom: 0;
z-index: 1;
width: 8px;
height: 8px;
content: " ";
transition: background var(--t-color);
}
.plume-content .demo-wrapper .demo-title::before {
left: 100%;
background: radial-gradient(16px at right top, transparent 50%, var(--vp-c-bg-alt) 50%);
}
.plume-content .demo-wrapper .demo-title::after {
right: 100%;
background: radial-gradient(16px at left top, transparent 50%, var(--vp-c-bg-alt) 50%);
}
.plume-content .demo-wrapper .demo-container {
min-height: 0;
padding: 20px;
font-size: 14px;
line-height: 22px;
background-color: var(--vp-c-bg-alt);
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
transition: background-color var(--t-color);
}
.plume-content .demo-wrapper .demo-container > *:first-child {
margin-top: 0;
}
.plume-content .demo-wrapper .demo-container > *:last-child {
margin-bottom: 0;
}
@media (min-width: 419px) {
.plume-content .demo-wrapper {
margin: 40px 0;
}
}
/* --------------------- Markdown Enhance: Mermaid ------------------------ */
.mermaid-actions {
padding-right: 20px;
}
.mermaid-actions .preview-button,
.mermaid-actions .download-button {
width: 1.5rem;
height: 1.5rem;
color: var(--vp-c-text-2);
transition: color var(--t-color);
}
.mermaid-actions .preview-button:hover,
.mermaid-actions .download-button:hover {
color: var(--vp-c-brand-1);
}
.mermaid-wrapper svg {
display: inline-block;
}
.flowchart-wrapper svg {
display: inline-block;
}

View File

@ -1,783 +0,0 @@
/* stylelint-disable order/order */
/* stylelint-disable no-descending-specificity */
/* ------------------ Markdown Enhance: Hint Container ------------------ */
.plume-content {
.hint-container {
padding: 16px 16px 8px;
font-size: var(--vp-custom-block-font-size);
line-height: 24px;
color: var(--vp-c-text-2);
border-radius: 8px;
.hint-container-title {
margin-top: 0;
font-weight: 600;
}
p + p {
margin: 8px 0;
}
code {
font-size: var(--vp-custom-block-code-font-size);
color: inherit;
}
th,
blockquote > p {
font-size: var(--vp-custom-block-font-size);
color: inherit;
}
div[class*="language-"] {
margin: 8px 0;
}
.vp-code-tab div[class*="language-"] {
margin: 0 0 8px;
}
div[class*="language-"] code {
font-weight: 400;
background-color: transparent;
}
div[class*="language-"].line-numbers-mode .line-numbers {
line-height: 1.5rem;
}
@media (max-width: 419px) {
div[class*="language-"] {
margin: 0.85rem -0.75rem 0.85rem -1rem;
}
.vp-code-tab div[class*="language-"] {
margin: 0 -0.75rem 0.85rem -1rem;
}
}
&.note {
color: var(--vp-c-text-3);
border-radius: 0;
}
&.info {
color: var(--vp-custom-block-info-text);
}
&.tip {
color: var(--vp-custom-block-tip-text);
}
&.warning {
color: var(--vp-custom-block-warning-text);
}
&.caution {
color: var(--vp-custom-block-danger-text);
}
&.detail {
color: var(--vp-custom-block-detail-text);
summary {
margin: -1.5rem -1.5rem -1.1rem;
font-weight: 700;
color: var(--vp-c-text-1);
cursor: pointer;
}
summary + p {
margin: 8px 0;
}
}
&.note,
&.info,
&.tip,
&.detail {
a,
code {
color: var(--vp-c-brand-1);
}
a:hover {
color: var(--vp-c-brand-2);
}
}
&.important {
a,
code {
color: var(--vp-c-purple-1);
}
a:hover {
color: var(--vp-c-purple-2);
}
}
&.warning {
a,
code {
color: var(--vp-c-warning-1);
}
a:hover {
color: var(--vp-c-warning-2);
}
}
&.caution {
a,
code {
color: var(--vp-c-danger-1);
}
a:hover {
color: var(--vp-c-danger-2);
}
}
[class*="language-"] .line-numbers {
padding-top: 21px;
}
}
}
/* ------------------ Markdown Enhance: Code Tabs ----------------------- */
.plume-content {
.code-tabs-nav {
margin-bottom: 0;
}
.vp-code-tabs-nav {
padding: 0 12px;
margin: 0.85rem 0 0;
overflow-y: hidden;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--t-color), box-shadow var(--t-color);
}
.vp-code-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--t-color);
}
.vp-code-tab-nav::before {
display: none;
}
.vp-code-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--t-color);
}
.vp-code-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.vp-code-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.vp-code-tab-nav:hover {
background: transparent;
}
@media (max-width: 419px) {
.vp-code-tabs-nav {
margin: 0 -1.5rem -0.85rem;
}
.hint-container .vp-code-tabs-nav {
margin: 0.85rem -0.75rem 0 -1rem;
}
}
}
/* -------------------- Markdown Enhance: Code Demo -------------------- */
.plume-content {
.vp-code-demo {
overflow: hidden;
border: solid 1px var(--vp-c-divider);
transition: border var(--t-color);
@media (max-width: 419px) {
.vp-code-demo-codes div[class*="language-"] {
margin: 0;
border-radius: 0;
}
}
&:hover {
box-shadow: none;
}
.vp-code-demo-header {
padding: 8px 12px;
transition: background-color var(--t-color);
}
.vp-code-demo-code-wrapper {
margin-bottom: -0.9rem;
}
.vp-code-demo-toggle-button {
margin: 0 12px 0 8px;
background-color: var(--vp-c-gray-2);
transition: background-color var(--t-color);
&:hover {
background-color: var(--vp-c-gray-1);
}
}
.vp-code-demo-title {
font-size: 1rem;
line-height: 1.75;
}
.vp-code-demo-display {
border-bottom: transparent;
}
.code-demo-jsfiddle .jsfiddle-button,
.code-demo-codepen .codepen-button {
background-color: transparent;
}
.vp-code-demo-codes div[class*="language-"] {
border-bottom: 2px dashed var(--vp-c-divider);
transition: border-bottom var(--t-color);
&:first-of-type {
border-top: 1px solid var(--vp-c-divider);
}
&:last-of-type {
border-bottom: none;
}
}
.vp-code-demo-codes div[class*="language-"] pre {
margin-bottom: 0;
border-radius: 0;
}
}
@media (max-width: 419px) {
.vp-code-demo {
margin: 8px -12px;
}
}
}
/* -------------------- Markdown Enhance: markdown Demo -------------------- */
.plume-content {
.vp-md-demo {
margin-bottom: 16px;
overflow: hidden;
border: solid 1px var(--vp-c-divider);
transition: border var(--t-color);
@media (max-width: 419px) {
.vp-md-demo-codes div[class*="language-"] {
margin: 0;
border-radius: 0;
}
}
&:hover {
box-shadow: none;
}
.vp-md-demo-header {
padding: 8px 12px;
font-size: 16px;
line-height: 1.7;
transition: background-color var(--t-color);
}
.vp-md-demo-toggle-button {
margin: 0 12px 0 8px;
background-color: var(--vp-c-gray-2);
transition: background-color var(--t-color);
&:hover {
background-color: var(--vp-c-gray-1);
}
}
.vp-md-demo-title {
font-size: 1rem;
line-height: 1.75;
}
.vp-md-demo-display {
border-bottom: transparent;
}
.vp-md-demo-codes div[class*="language-"] {
border-bottom: 2px dashed var(--vp-c-divider);
transition: border-bottom var(--t-color);
&:first-of-type {
border-top: 1px solid var(--vp-c-divider);
}
&:last-of-type {
border-bottom: none;
}
}
.vp-md-demo-codes div[class*="language-"] pre {
margin-bottom: 0;
border-radius: 0;
}
}
@media (max-width: 419px) {
.vp-md-demo {
margin: 8px -12px;
}
}
}
/* ---------------------- Markdown Enhance: Task List ---------------------- */
.plume-content {
.task-list-container {
padding-left: 0;
.task-list-item {
input {
width: 0;
height: 0;
padding: 0;
margin: 0;
}
label {
margin-left: 1.2em;
}
input::before,
input::after {
position: absolute;
top: -1em;
left: 0;
display: inline-block;
font-size: 1em;
content: none;
}
input::after {
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23c2c2c4" d="M26 27.5H6A1.5 1.5 0 0 1 4.5 26V6c0-.83.67-1.5 1.5-1.5h20c.828 0 1.5.67 1.5 1.5v20a1.5 1.5 0 0 1-1.5 1.5m-18.5-3h17v-17h-17z"%2F%3E%3C%2Fsvg%3E');
background-color: transparent;
border: none;
}
input:checked[disabled]::after {
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 32 32"%3E%3Cpath fill="%23299764" d="M29.548 3.043a2.5 2.5 0 0 0-3.513.4L16 16.067l-3.508-4.414a2.5 2.5 0 0 0-3.915 3.112l5.465 6.875c.474.597 1.195.943 1.957.943s1.482-.35 1.957-.944L29.95 6.555c.86-1.08.68-2.654-.402-3.513zM24.5 24.5h-17v-17h12.756l2.385-3H6c-.83 0-1.5.67-1.5 1.5v20c0 .828.67 1.5 1.5 1.5h20a1.5 1.5 0 0 0 1.5-1.5V12.85l-3 3.774z"%2F%3E%3C%2Fsvg%3E');
background-color: transparent;
border: none;
}
}
}
}
/* ---------------------------- Markdown Enhance: Tabs ----------------------------- */
.plume-content {
.vp-tabs {
margin: 1.5rem -0.75rem;
overflow: hidden;
border: 1px solid var(--vp-c-divider);
transition: border var(--t-color);
}
.vp-tabs-nav {
padding: 0 12px;
background-color: var(--vp-code-tab-bg);
box-shadow: inset 0 -1px var(--vp-code-tab-divider);
transition: background-color var(--t-color), box-shadow var(--t-color);
}
.vp-tab-nav {
position: relative;
padding: 0 12px;
font-size: 14px;
font-weight: 500;
line-height: 48px;
color: var(--vp-code-tab-text-color);
white-space: nowrap;
border-bottom: 1px solid transparent;
transition: color var(--t-color);
}
.vp-tab-nav::before {
display: none;
}
.vp-tab-nav::after {
position: absolute;
right: 8px;
bottom: -1px;
left: 8px;
z-index: 1;
display: block;
width: auto;
height: 2px;
content: "";
background: transparent;
border-radius: 2px;
transition: background var(--t-color);
}
.vp-tab-nav.active {
color: var(--vp-code-tab-active-text-color);
background: transparent;
}
.vp-tab-nav.active::after {
background: var(--vp-code-tab-active-bar-color);
}
.vp-tab-nav:hover {
background: transparent;
}
@media (min-width: 419px) {
.vp-tabs {
margin: 1.5rem 0;
}
}
.hint-container .vp-tabs {
margin: 1rem -0.45rem 1rem -0.75rem;
.vp-tabs-nav {
background: var(--vp-c-default-soft);
}
.vp-tab {
padding: 0.45rem 0.75rem;
font-size: 14px;
background: transparent;
p {
margin: 8px 0;
}
}
}
}
/* --------------------- Markdown Enhance: Footnote -------------------------------- */
.plume-content {
.footnotes-sep {
margin-top: 48px;
}
.footnotes {
position: relative;
padding: 48px 0 12px 16px;
margin-left: -16px;
font-size: 14px;
border-left: 4px solid var(--vp-c-default-soft);
@media (max-width: 419px) {
& {
margin-left: 0;
}
}
&::before {
position: absolute;
top: 12px;
left: 16px;
font-size: 16px;
font-weight: 700;
[lang="zh-CN"] & {
content: "脚注:";
}
[lang="en-US"] & {
content: "Footnotes:";
}
}
ol {
margin: 0;
p {
margin: 8px 0;
}
li:first-of-type p:first-of-type {
margin-top: 0;
}
li:last-of-type p:last-of-type {
margin-bottom: 0;
}
}
}
.footnote-item {
padding-top: 0;
margin-top: 0;
> p {
margin-bottom: 0;
}
}
.footnote-backref {
position: relative;
color: transparent;
text-decoration: none;
&:hover {
color: transparent;
}
&::before {
position: absolute;
top: -0.4em;
left: 0;
font-size: 1em;
content: url('data:image/svg+xml,%3Csvg xmlns="http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg" width="1em" height="1em" viewBox="0 0 48 48"%3E%3Cg fill="none" stroke="%23c2c2c4" stroke-linecap="round" stroke-linejoin="round" stroke-width="4"%3E%3Cpath d="m13 8l-7 6l7 7"%2F%3E%3Cpath d="M6 14h22.994c6.883 0 12.728 5.62 12.996 12.5c.284 7.27-5.723 13.5-12.996 13.5H11.998"%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E');
}
}
.footnote-anchor {
top: 0;
}
}
/* -------------- Markdown Enhance: Image Figure --------------------- */
.plume-content {
figure {
position: relative;
display: flex;
flex-direction: column;
width: auto;
margin: 1rem auto;
text-align: center;
img {
margin: 0 auto;
overflow: hidden;
}
> a {
&[href^="http://"],
&[href^="https://"] {
&::after {
@media print {
content: "";
}
}
}
.external-icon {
display: none;
}
}
figcaption {
display: inline-block;
margin: 6px auto;
font-size: 0.8rem;
}
}
}
/* --------------------- demo-wrapper ------------------------ */
.plume-content .demo-wrapper {
display: flex;
flex-direction: column;
min-height: 40px;
margin: 40px -16px;
border: solid 1px var(--vp-c-divider);
border-radius: 8px;
box-shadow: var(--vp-shadow-2);
transition: var(--t-color);
transition-property: border, box-shadow;
&.has-title .demo-head {
border-bottom-color: transparent;
}
&.only-img {
overflow: hidden;
}
&.only-img img {
display: block;
}
&.only-img .demo-container,
&.no-padding .demo-container {
padding: 0;
}
&.has-height .demo-container {
height: var(--demo-container-height);
overflow-y: auto;
}
.demo-head {
display: flex;
align-items: center;
justify-content: flex-start;
min-height: 0;
border-bottom: solid 1px var(--vp-c-divider);
transition: border-bottom var(--t-color);
}
.demo-ctrl {
display: flex;
gap: 5px;
align-items: center;
justify-content: flex-start;
padding: 5px 0 5px 8px;
}
.demo-ctrl i {
display: inline-block;
width: 10px;
height: 10px;
background-color: #ccc;
border-radius: 100%;
transition: background-color var(--t-color);
&:nth-child(1) {
background-color: var(--vp-c-danger-3);
}
&:nth-child(2) {
background-color: var(--vp-c-warning-3);
}
&:nth-child(3) {
background-color: var(--vp-c-green-3);
}
}
.demo-title {
position: relative;
min-width: 0;
padding: 0 16px;
margin: 0 20px -1px;
font-size: 14px;
font-weight: 500;
color: var(--vp-c-text-2);
background-color: var(--vp-c-bg-alt);
border-top-left-radius: 8px;
border-top-right-radius: 8px;
transition: var(--t-color);
transition-property: color, background-color;
}
.demo-title p {
max-width: 100%;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
text-wrap: nowrap;
}
.demo-title::after,
.demo-title::before {
position: absolute;
bottom: 0;
z-index: 1;
width: 8px;
height: 8px;
content: " ";
transition: background var(--t-color);
}
.demo-title::before {
left: 100%;
background: radial-gradient(16px at right top, transparent 50%, var(--vp-c-bg-alt) 50%);
}
.demo-title::after {
right: 100%;
background: radial-gradient(16px at left top, transparent 50%, var(--vp-c-bg-alt) 50%);
}
.demo-container {
min-height: 0;
padding: 20px;
font-size: 14px;
line-height: 22px;
background-color: var(--vp-c-bg-alt);
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
transition: background-color var(--t-color);
> *:first-child {
margin-top: 0;
}
> *:last-child {
margin-bottom: 0;
}
}
}
@media (min-width: 419px) {
.plume-content .demo-wrapper {
margin: 40px 0;
}
}
/* --------------------- Markdown Enhance: Mermaid ------------------------ */
.mermaid-actions {
padding-right: 20px;
}
.mermaid-actions .preview-button,
.mermaid-actions .download-button {
width: 1.5rem;
height: 1.5rem;
color: var(--vp-c-text-2);
transition: color var(--t-color);
&:hover {
color: var(--vp-c-brand-1);
}
}
.mermaid-wrapper svg {
display: inline-block;
}
.flowchart-wrapper svg {
display: inline-block;
}

View File

@ -8,7 +8,5 @@
}
#nprogress .peg {
box-shadow:
0 0 10px var(--vp-c-brand-1),
0 0 5px var(--vp-c-brand-1);
box-shadow: 0 0 10px var(--vp-c-brand-1), 0 0 5px var(--vp-c-brand-1);
}

View File

@ -114,9 +114,7 @@
/* rtl:begin:ignore */
border-right: none;
border-radius: 4px 0 0 4px;
transition:
color var(--t-color),
border-color var(--t-color);
transition: color var(--t-color), border-color var(--t-color);
}
.DocSearch-Button .DocSearch-Button-Key + .DocSearch-Button-Key {
@ -145,7 +143,7 @@
}
.mac .DocSearch-Button .DocSearch-Button-Key:first-child::after {
content: "\2318";
content: "";
}
.DocSearch-Button .DocSearch-Button-Key:first-child > * {
@ -174,7 +172,6 @@
}
/* plugin-search */
/* stylelint-disable-next-line order/order */
@media (min-width: 768px) {
.navbar-search {

View File

@ -1,4 +1,3 @@
/* social icons - used under CC0 1.0 from https://simpleicons.org/ */
.vpi-social-discord {
--icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418Z'/%3E%3C/svg%3E");

View File

@ -119,9 +119,7 @@
.twoslash .twoslash-error {
padding-bottom: 2px;
background:
url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E")
repeat-x bottom left;
background: url("data:image/svg+xml,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%206%203'%20enable-background%3D'new%200%200%206%203'%20height%3D'3'%20width%3D'6'%3E%3Cg%20fill%3D'%23c94824'%3E%3Cpolygon%20points%3D'5.5%2C0%202.5%2C3%201.1%2C3%204.1%2C0'%2F%3E%3Cpolygon%20points%3D'4%2C0%206%2C2%206%2C0.6%205.4%2C0'%2F%3E%3Cpolygon%20points%3D'0%2C2%201%2C3%202.4%2C3%200%2C0.6'%2F%3E%3C%2Fg%3E%3C%2Fsvg%3E") repeat-x bottom left;
}
/* ===== Completeions ===== */
@ -240,7 +238,6 @@
}
/* ========== floating vue ================== */
:root {
--twoslash-popup-bg: var(--vp-c-bg, inherit);
--twoslash-popup-color: var(--vp-c-text-1);

View File

@ -8,17 +8,11 @@
white-space: nowrap;
}
// .icon {
// width: 20px;
// height: 20px;
// }
.vp-iconify {
margin: 0.3em;
}
/* ----------------- Transition ------------------------ */
.fade-slide-y-enter-active {
transition: all 0.25s ease !important;
}
@ -33,7 +27,6 @@
transform: translateY(10px);
}
.fade-slide-x-enter-active {
transition: all 0.25s ease !important;
}

View File

@ -1,7 +1,6 @@
/**
* Colors: Solid
* -------------------------------------------------------------------------- */
:root {
--vp-c-white: #fff;
--vp-c-black: #000;
@ -41,7 +40,6 @@
* to create a accent, such as when having inline code block inside
* custom containers.
* -------------------------------------------------------------------------- */
:root {
--vp-c-gray-1: #dddde3;
--vp-c-gray-2: #e4e4e9;
@ -122,7 +120,6 @@
* - `bg-soft`: The bg color to slightly distinguish some components from
* the page. Used for things like "carbon ads" or "table".
* -------------------------------------------------------------------------- */
:root {
--vp-c-bg: #fff;
--vp-c-bg-alt: #f6f6f7;
@ -151,7 +148,6 @@
* - `gutter`: This is used to divide components in the page. For example
* the header and the lest of the page.
* -------------------------------------------------------------------------- */
:root {
--vp-c-border: #c2c2c4;
--vp-c-divider: #e2e2e3;
@ -173,7 +169,6 @@
*
* - `text-3`: Used for subtle texts, such as "placeholders" or "caret icon".
* -------------------------------------------------------------------------- */
:root {
--vp-c-text-1: rgba(60, 60, 67);
--vp-c-text-2: rgba(60, 60, 67, 0.78);
@ -210,7 +205,6 @@
*
* To understand the scaling system, refer to "Colors: Palette" section.
* -------------------------------------------------------------------------- */
:root {
--vp-c-default-1: var(--vp-c-gray-1);
--vp-c-default-2: var(--vp-c-gray-2);
@ -244,7 +238,6 @@
/**
* Typography
* -------------------------------------------------------------------------- */
:root {
--vp-font-family-base:
"Chinese Quotes",
@ -276,7 +269,6 @@
/**
* Shadows
* -------------------------------------------------------------------------- */
:root {
--vp-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.04), 0 1px 2px rgba(0, 0, 0, 0.06);
--vp-shadow-2: 0 3px 12px rgba(0, 0, 0, 0.07), 0 1px 4px rgba(0, 0, 0, 0.07);
@ -296,7 +288,6 @@
/**
* Z-indexes
* -------------------------------------------------------------------------- */
:root {
--vp-z-index-footer: 10;
--vp-z-index-local-nav: 20;
@ -311,7 +302,6 @@
/**
* Layouts
* -------------------------------------------------------------------------- */
:root {
--vp-layout-max-width: 1440px;
--content-width: var(--vp-layout-max-width);
@ -320,7 +310,6 @@
/**
* Component: Header Anchor
* -------------------------------------------------------------------------- */
:root {
--vp-header-anchor-symbol: "#";
}
@ -328,7 +317,6 @@
/**
* Component: Code
* -------------------------------------------------------------------------- */
:root {
--vp-code-line-height: 1.7;
--vp-code-font-size: 0.875em;
@ -340,30 +328,25 @@
--vp-code-block-color: var(--vp-c-text-2);
--vp-code-block-bg: var(--vp-c-bg-safe);
--vp-code-block-divider-color: var(--vp-c-gutter);
--vp-code-lang-color: var(--vp-c-text-3);
--vp-code-line-highlight-color: var(--vp-c-default-soft);
--vp-code-line-number-color: var(--vp-c-text-3);
--vp-code-line-diff-add-color: var(--vp-c-green-soft);
--vp-code-line-diff-add-symbol-color: var(--vp-c-green-1);
--vp-code-line-diff-remove-color: var(--vp-c-red-soft);
--vp-code-line-diff-remove-symbol-color: var(--vp-c-red-1);
--vp-code-line-warning-color: var(--vp-c-yellow-soft);
--vp-code-line-error-color: var(--vp-c-red-soft);
--vp-icon-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2'/%3E%3C/svg%3E");
--vp-icon-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' height='20' width='20' stroke='rgba(128,128,128,1)' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M9 5H7a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2M9 5a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2M9 5a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2m-6 9 2 2 4-4'/%3E%3C/svg%3E");
--vp-code-copy-code-border-color: var(--vp-c-divider);
--vp-code-copy-code-bg: var(--vp-c-bg-soft);
--vp-code-copy-code-hover-border-color: var(--vp-c-divider);
--vp-code-copy-code-hover-bg: var(--vp-c-bg);
--vp-code-copy-code-active-text: var(--vp-c-text-2);
--vp-code-tab-divider: var(--vp-code-block-divider-color);
--vp-code-tab-text-color: var(--vp-c-text-2);
--vp-code-tab-bg: var(--vp-code-block-bg);
@ -375,7 +358,6 @@
/**
* Component: Button
* -------------------------------------------------------------------------- */
:root {
--vp-button-brand-border: transparent;
--vp-button-brand-text: var(--vp-c-white);
@ -386,7 +368,6 @@
--vp-button-brand-active-border: transparent;
--vp-button-brand-active-text: var(--vp-c-white);
--vp-button-brand-active-bg: var(--vp-c-brand-1);
--vp-button-alt-border: transparent;
--vp-button-alt-text: var(--vp-c-text-1);
--vp-button-alt-bg: var(--vp-c-default-3);
@ -396,16 +377,6 @@
--vp-button-alt-active-border: transparent;
--vp-button-alt-active-text: var(--vp-c-text-1);
--vp-button-alt-active-bg: var(--vp-c-default-1);
// --vp-button-sponsor-border: var(--vp-c-text-2);
// --vp-button-sponsor-text: var(--vp-c-text-2);
// --vp-button-sponsor-bg: transparent;
// --vp-button-sponsor-hover-border: var(--vp-c-sponsor);
// --vp-button-sponsor-hover-text: var(--vp-c-sponsor);
// --vp-button-sponsor-hover-bg: transparent;
// --vp-button-sponsor-active-border: var(--vp-c-sponsor);
// --vp-button-sponsor-active-text: var(--vp-c-sponsor);
// --vp-button-sponsor-active-bg: transparent;
}
.dark {
@ -417,7 +388,6 @@
/**
* Component: Custom Block
* -------------------------------------------------------------------------- */
:root {
--vp-custom-block-font-size: 14px;
--vp-custom-block-code-font-size: 13px;
@ -451,18 +421,15 @@
/**
* Component: Input
* -------------------------------------------------------------------------- */
:root {
--vp-input-border-color: var(--vp-c-border);
--vp-input-bg-color: var(--vp-c-bg-alt);
--vp-input-switch-bg-color: var(--vp-c-default-soft);
}
/**
* Component: Nav
* -------------------------------------------------------------------------- */
:root {
--vp-nav-height: 64px;
--vp-nav-bg-color: var(--vp-c-bg);
@ -481,7 +448,6 @@
/**
* Component: Local Nav
* -------------------------------------------------------------------------- */
:root {
--vp-local-nav-bg-color: var(--vp-c-bg);
}
@ -489,7 +455,6 @@
/**
* Component: Sidebar
* -------------------------------------------------------------------------- */
:root {
--vp-sidebar-width: 272px;
--vp-sidebar-bg-color: var(--vp-c-bg-alt);
@ -498,7 +463,6 @@
/**
* Colors Backdrop
* -------------------------------------------------------------------------- */
:root {
--vp-backdrop-bg-color: rgba(0, 0, 0, 0.6);
}
@ -506,14 +470,11 @@
/**
* Component: Home
* -------------------------------------------------------------------------- */
:root {
--vp-home-hero-name-color: var(--vp-c-brand-1);
--vp-home-hero-name-background: transparent;
--vp-home-hero-image-background-image: none;
--vp-home-hero-image-filter: none;
--vp-c-text-hero-name: var(--vp-c-text-dark-1);
--vp-c-text-hero-tagline: var(--vp-c-text-dark-2);
--vp-c-text-hero-text: var(--vp-c-text-dark-1);
@ -532,20 +493,16 @@
/**
* Component: Badge
* -------------------------------------------------------------------------- */
:root {
--vp-badge-info-border: transparent;
--vp-badge-info-text: var(--vp-c-text-2);
--vp-badge-info-bg: var(--vp-c-default-soft);
--vp-badge-tip-border: transparent;
--vp-badge-tip-text: var(--vp-c-brand-1);
--vp-badge-tip-bg: var(--vp-c-brand-soft);
--vp-badge-warning-border: transparent;
--vp-badge-warning-text: var(--vp-c-warning-1);
--vp-badge-warning-bg: var(--vp-c-warning-soft);
--vp-badge-danger-border: transparent;
--vp-badge-danger-text: var(--vp-c-danger-1);
--vp-badge-danger-bg: var(--vp-c-danger-soft);
@ -555,28 +512,10 @@
* Component: Carbon Ads
* -------------------------------------------------------------------------- */
// :root {
// --vp-carbon-ads-text-color: var(--vp-c-text-1);
// --vp-carbon-ads-poweredby-color: var(--vp-c-text-2);
// --vp-carbon-ads-bg-color: var(--vp-c-bg-soft);
// --vp-carbon-ads-hover-text-color: var(--vp-c-brand-1);
// --vp-carbon-ads-hover-poweredby-color: var(--vp-c-text-1);
// }
/**
* Component: Local Search
* -------------------------------------------------------------------------- */
// :root {
// --vp-local-search-bg: var(--vp-c-bg);
// --vp-local-search-result-bg: var(--vp-c-bg);
// --vp-local-search-result-border: var(--vp-c-divider);
// --vp-local-search-result-selected-bg: var(--vp-c-bg);
// --vp-local-search-result-selected-border: var(--vp-c-brand-1);
// --vp-local-search-highlight-bg: var(--vp-c-brand-1);
// --vp-local-search-highlight-text: var(--vp-c-neutral-inverse);
// }
/** Component: Search **/
:root {
--search-bg-color: var(--vp-c-default-soft);
@ -610,37 +549,31 @@ html.dark {
--important-border-color: transparent;
--important-code-bg-color: var(--vp-c-purple-soft);
// info
--info-title-color: var(--vp-c-text-1);
--info-bg-color: var(--vp-custom-block-info-bg);
--info-border-color: var(--vp-custom-block-info-border);
--info-code-bg-color: var(--vp-custom-block-info-code-bg);
// note
--note-title-color: var(--vp-c-text-3);
--note-bg-color: var(--vp-c-bg);
--note-border-color: var(--vp-c-divider);
--note-code-bg-color: var(--vp-c-default-soft);
// tip
--tip-title-color: var(--vp-c-text-1);
--tip-bg-color: var(--vp-custom-block-tip-bg);
--tip-border-color: var(--vp-custom-block-tip-border);
--tip-code-bg-color: var(--vp-custom-block-tip-code-bg);
// warning
--warning-title-color: var(--vp-c-text-1);
--warning-bg-color: var(--vp-custom-block-warning-bg);
--warning-border-color: var(--vp-custom-block-warning-border);
--warning-code-bg-color: var(--vp-custom-block-warning-code-bg);
// caution
--caution-title-color: var(--vp-c-text-1);
--caution-bg-color: var(--vp-custom-block-danger-bg);
--caution-border-color: var(--vp-custom-block-danger-border);
--caution-code-bg-color: var(--vp-custom-block-danger-code-bg);
// detail
--detail-bg-color: var(--vp-custom-block-details-bg);
--detail-text-color: inherit;
--detail-code-bg-color: var(--vp-custom-block-details-code-bg);

View File

@ -30,7 +30,7 @@ export function resolveThemeData(app: App, options: PlumeThemeLocaleOptions): Pl
entries(options.locales || {}).forEach(([locale, opt]) => {
// 注入预设 导航栏
// home | blog | tags | archives
if (opt.navbar !== false && opt.navbar?.length === 0) {
if (opt.navbar !== false && (!opt.navbar || opt.navbar.length === 0)) {
// fallback navbar option
const localePath = locale === '/' ? root : locale
const navbar: NavItem[] = [{

View File

@ -0,0 +1,18 @@
import { addViteConfig, addViteOptimizeDepsInclude, addViteSsrNoExternal } from '@vuepress/helper'
import type { App } from 'vuepress'
export function extendsBundlerOptions(bundlerOptions: any, app: App): void {
addViteConfig(bundlerOptions, app, {
build: {
chunkSizeWarningLimit: 1024,
},
})
addViteOptimizeDepsInclude(bundlerOptions, app, '@vueuse/core', true)
addViteSsrNoExternal(bundlerOptions, app, [
'@vuepress/helper',
'@vuepress/plugin-reading-time',
'@vuepress/plugin-watermark',
])
}

View File

@ -1,41 +0,0 @@
import { hasOwn, random, toArray } from '@pengzhanbo/utils'
export type BlogTagsColorsItem = readonly [
string, // normal color
string, // hover color
string, // background color
]
export const BLOG_TAGS_COLORS_PRESET: BlogTagsColorsItem[] = [
['#6aa1b7', '#5086a1', 'rgba(131, 208, 218, 0.314)'],
['#299764', '#18794e', 'rgba(16, 185, 129, 0.14)'],
['#946300', '#915930', 'rgba(234, 179, 8, 0.14)'],
['#d5393e', '#b8272c', 'rgba(244, 63, 94, 0.14)'],
['#7e4cc9', '#6f42c1', 'rgba(159, 122, 234, 0.14)'],
['#3a5ccc', '#3451b2', 'rgba(100, 108, 255, 0.14)'],
['#fab10f', '#f39c12', 'rgba(255, 213, 0, 0.14)'],
['#cc6699', '#c75191', 'rgba(255, 153, 204, 0.14)'],
]
const len = BLOG_TAGS_COLORS_PRESET.length
let prevIndex: number[] = []
function getRandom() {
let index: number
do
index = random(0, len - 1)
while (prevIndex.includes(index))
prevIndex.push(index)
prevIndex = prevIndex.slice(-5)
return index
}
export function generateBlogTagsColors(map: Record<string, any>, tags?: string[]) {
if (!tags || tags.length === 0)
return
toArray(tags).forEach((tag) => {
if (!hasOwn(map, tag))
map[tag] = getRandom()
})
}

View File

@ -92,8 +92,9 @@ export function getPlugins({
}))
}
if (pluginOptions.nprogress !== false)
if (pluginOptions.nprogress !== false) {
plugins.push(nprogressPlugin())
}
if (pluginOptions.git ?? isProd) {
plugins.push(gitPlugin({
@ -171,14 +172,17 @@ export function getPlugins({
}))
}
if (pluginOptions.comment)
if (pluginOptions.comment) {
plugins.push(commentPlugin(pluginOptions.comment))
}
if (pluginOptions.baiduTongji !== false && pluginOptions.baiduTongji?.key && isProd)
if (pluginOptions.baiduTongji !== false && pluginOptions.baiduTongji?.key && isProd) {
plugins.push(baiduTongjiPlugin(pluginOptions.baiduTongji))
}
if (pluginOptions.sitemap !== false && hostname && isProd)
if (pluginOptions.sitemap !== false && hostname && isProd) {
plugins.push(sitemapPlugin({ hostname }))
}
if (pluginOptions.seo !== false && hostname && isProd) {
plugins.push(seoPlugin({

View File

@ -6,10 +6,6 @@ import {
} from '../config/index.js'
import { normalizePath } from '../utils.js'
import type { PlumeThemeEncrypt, PlumeThemeLocaleOptions } from '../..//shared/index.js'
import {
BLOG_TAGS_COLORS_PRESET,
generateBlogTagsColors,
} from './blogTags.js'
export function resolveBlogDataOptions(
localeOptions: PlumeThemeLocaleOptions,
@ -35,13 +31,8 @@ export function resolveBlogDataOptions(
pageFilter: (page: any) => page.frontmatter.article !== undefined
? !!page.frontmatter.article
: true,
extraBlogData(extra) {
extra.tagsColorsPreset = BLOG_TAGS_COLORS_PRESET
extra.tagsColors = {}
},
extendBlogData: (page: any, extra) => {
extendBlogData: (page: any) => {
const tags = page.frontmatter.tags
generateBlogTagsColors(extra.tagsColors, tags)
const data: Record<string, any> = {
categoryList: page.data.categoryList,
tags,

View File

@ -0,0 +1,20 @@
import type { App } from 'vuepress'
import { watch } from 'chokidar'
import { prepareArticleTagColors } from './prepareArticleTagColor.js'
export async function setupPrepare(app: App): Promise<void> {
await prepareArticleTagColors(app)
}
export function watchPrepare(app: App, watchers: any[]): void {
const watcher = watch('pages/**', {
cwd: app.dir.temp(),
ignoreInitial: true,
})
watcher.on('change', () => prepareArticleTagColors(app))
watcher.on('add', () => prepareArticleTagColors(app))
watcher.on('unlink', () => prepareArticleTagColors(app))
watchers.push(watcher)
}

View File

@ -0,0 +1,108 @@
import { toArray } from '@pengzhanbo/utils'
import type { App } from 'vuepress'
import { nanoid } from '../utils.js'
export type TagsColorsItem = readonly [
string, // normal color
string, // hover color
string, // background color
]
export const PRESET: TagsColorsItem[] = [
['#6aa1b7', '#5086a1', 'rgba(131, 208, 218, 0.314)'],
['#299764', '#18794e', 'rgba(16, 185, 129, 0.14)'],
['#946300', '#915930', 'rgba(234, 179, 8, 0.14)'],
['#d5393e', '#b8272c', 'rgba(244, 63, 94, 0.14)'],
['#7e4cc9', '#6f42c1', 'rgba(159, 122, 234, 0.14)'],
['#3a5ccc', '#3451b2', 'rgba(100, 108, 255, 0.14)'],
['#fab10f', '#f39c12', 'rgba(255, 213, 0, 0.14)'],
['#cc6699', '#c75191', 'rgba(255, 153, 204, 0.14)'],
['#55AAEE', '#0088CC', 'rgba(0, 136, 204, 0.14)'],
['#AA66CC', '#9933CC', 'rgba(153, 121, 204, 0.14)'],
['#9933CC', '#993399', 'rgba(153, 151, 204, 0.14)'],
['#CC9999', '#CC8888', 'rgba(204, 153, 153, 0.14)'],
['#9999CC', '#9999FF', 'rgba(153, 153, 204, 0.14)'],
['#66CCCC', '#66CCAA', 'rgba(102, 204, 204, 0.14)'],
['#CCBC99', '#CCAA99', 'rgba(204, 204, 153, 0.14)'],
]
const HMR_CODE = `
if (import.meta.webpackHot) {
import.meta.webpackHot.accept()
if (__VUE_HMR_RUNTIME__.updateArticleTagColors) {
__VUE_HMR_RUNTIME__.updateArticleTagColor(articleTagColors)
}
}
if (import.meta.hot) {
import.meta.hot.accept(({ articleTagColors }) => {
__VUE_HMR_RUNTIME__.updateArticleTagColor(articleTagColors)
})
}
`
// { index: className }
const cache: Record<number, string> = {}
export async function prepareArticleTagColors(app: App): Promise<void> {
const articleTagColors: Record<string, string> = {}
const tagList = new Set<string>()
app.pages.forEach((page) => {
const { frontmatter: { tags } } = page
if (tags) {
toArray(tags).forEach((tag) => {
tag && tagList.add(tag as string)
})
}
})
tagList.forEach((tag) => {
const code = getTagCode(tag)
if (!cache[code]) {
cache[code] = nanoid(4)
}
if (!articleTagColors[tag]) {
articleTagColors[tag] = cache[code]
}
})
let code = `\
import './articleTagColors.css'
export const articleTagColors = ${JSON.stringify(articleTagColors)}
`
if (app.env.isDev) {
code += HMR_CODE
}
await app.writeTemp('internal/articleTagColors.css', genTagColorsStyle())
await app.writeTemp('internal/articleTagColors.ts', code)
}
function getTagCode(tag: string): number {
tag = tag.toLowerCase()
let code = 0
for (let i = 0; i < tag.length; i++) {
code += tag.charCodeAt(i)
}
return code % PRESET.length
}
function genTagColorsStyle(): string {
let css = ''
for (const [code, className] of Object.entries(cache)) {
const index = Number(code)
const [color, hoverColor, backgroundColor] = PRESET[index]
css += `\
.vp-tag-${className} {
--vp-tag-color: ${color};
--vp-tag-hover-color: ${hoverColor};
--vp-tag-bg: ${backgroundColor};
}
`
}
return css
}

View File

@ -0,0 +1,11 @@
import { type TemplateRendererContext, templateRenderer } from 'vuepress/utils'
import { getThemePackage } from './utils.js'
export function templateBuildRenderer(template: string, context: TemplateRendererContext) {
const pkg = getThemePackage()
template = template
.replace('{{ themeVersion }}', pkg.version || '')
.replace(/^\s+|\s+$/gm, '')
.replace(/\n/g, '')
return templateRenderer(template, context)
}

View File

@ -1,11 +1,13 @@
import type { Page, Theme } from 'vuepress/core'
import { templateRenderer } from 'vuepress/utils'
import { addViteConfig, addViteOptimizeDepsInclude, addViteSsrNoExternal, isPlainObject } from '@vuepress/helper'
import { isPlainObject } from '@vuepress/helper'
import type { PlumeThemeOptions, PlumeThemePageData } from '../shared/index.js'
import { getPlugins } from './plugins/index.js'
import { extendsPageData, setupPage } from './setupPages.js'
import { THEME_NAME, getThemePackage, logger, resolve, templates } from './utils.js'
import { THEME_NAME, logger, resolve, templates } from './utils.js'
import { resolveEncrypt, resolveLocaleOptions, resolvePageHead } from './config/index.js'
import { extendsBundlerOptions } from './extendsBundlerOptions.js'
import { templateBuildRenderer } from './templateBuildRenderer.js'
import { setupPrepare, watchPrepare } from './prepare/index.js'
export function plumeTheme({
themePlugins,
@ -15,7 +17,6 @@ export function plumeTheme({
...localeOptions
}: PlumeThemeOptions = {}): Theme {
const pluginOptions = plugins ?? themePlugins ?? {}
const pkg = getThemePackage()
const watermarkFullPage = isPlainObject(pluginOptions.watermark)
? pluginOptions.watermark.fullPage !== false
@ -29,6 +30,7 @@ export function plumeTheme({
return (app) => {
localeOptions = resolveLocaleOptions(app, localeOptions)
return {
name: THEME_NAME,
@ -43,34 +45,26 @@ export function plumeTheme({
plugins: getPlugins({ app, pluginOptions, localeOptions, encrypt, hostname }),
onInitialized: async app => await setupPage(app, localeOptions),
onInitialized: async (app) => {
await setupPage(app, localeOptions)
},
onPrepared: async (app) => {
await setupPrepare(app)
},
onWatched: (app, watchers) => {
watchPrepare(app, watchers)
},
extendsPage: (page) => {
extendsPageData(page as Page<PlumeThemePageData>, localeOptions)
resolvePageHead(page, localeOptions)
},
extendsBundlerOptions(bundlerOptions, app) {
addViteConfig(bundlerOptions, app, {
build: {
chunkSizeWarningLimit: 1024,
},
})
addViteOptimizeDepsInclude(bundlerOptions, app, '@vueuse/core', true)
addViteSsrNoExternal(bundlerOptions, app, [
'@vuepress/helper',
'@vuepress/plugin-reading-time',
'@vuepress/plugin-watermark',
])
},
extendsBundlerOptions,
templateBuildRenderer(template, context) {
template = template
.replace('{{ themeVersion }}', pkg.version || '')
.replace(/^\s+|\s+$/gm, '')
.replace(/\n/g, '')
return templateRenderer(template, context)
},
templateBuildRenderer,
}
}
}

View File

@ -1,8 +1,12 @@
export type PlumeThemeImage =
export type ThemeImage =
| string
| { src: string, alt?: string }
| { dark: string, light: string, alt?: string }
export type ThemeColor = string | { light: string, dark: string }
export type ThemeOutline = false | number | [number, number] | 'deep'
export interface SocialLink {
icon: SocialLinkIcon
link: string

View File

@ -1,5 +1,6 @@
import type { WatermarkPluginFrontmatter } from '@vuepress/plugin-watermark'
import type { NavItemWithLink, PlumeThemeImage } from '.'
import type { ThemeImage, ThemeOutline } from './base.js'
import type { NavItemWithLink } from './options/navbar.js'
/* =============================== Home begin ==================================== */
export interface PlumeThemeHomeFrontmatter extends Omit<PlumeThemeHomeBanner, 'type'> {
@ -58,7 +59,7 @@ export interface PlumeThemeHomeHero extends PlumeHomeConfigBase {
export interface PlumeThemeHomeTextImage extends PlumeHomeConfigBase {
type: 'text-image' | 'image-text'
image: PlumeThemeImage
image: ThemeImage
width?: number | string
title?: string
description?: string
@ -101,7 +102,7 @@ export interface PlumeThemeHomeProfile extends PlumeHomeConfigBase {
type: 'profile'
name?: string
description?: string
avatar?: PlumeThemeImage
avatar?: ThemeImage
circle?: boolean
}
@ -112,6 +113,7 @@ export interface PlumeThemeHomeCustom extends PlumeHomeConfigBase {
/* =============================== Home end ==================================== */
export interface PlumeThemePageFrontmatter {
home?: false
comments?: boolean
editLink?: boolean
editLinkPattern?: string
@ -119,7 +121,9 @@ export interface PlumeThemePageFrontmatter {
contributors?: boolean
prev?: string | NavItemWithLink
next?: string | NavItemWithLink
outline?: false | number | [number, number] | 'deep'
sidebar?: string | false
aside?: boolean
outline?: ThemeOutline
backToTop?: boolean
externalLink?: boolean
readingTime?: boolean

View File

@ -1,6 +1,6 @@
import type { LocaleData } from 'vuepress/core'
import type { NotesDataOptions } from '@vuepress-plume/plugin-notes-data'
import type { SocialLink, SocialLinkIconUnion } from '../base.js'
import type { SocialLink, SocialLinkIconUnion, ThemeOutline } from '../base.js'
import type { PlumeThemeBlog } from '../blog.js'
import type { NavItem } from './navbar.js'
@ -74,7 +74,7 @@ export interface PlumeThemeLocaleData extends LocaleData {
*/
notes?: false | NotesDataOptions
outline?: false | number | [number, number] | 'deep'
outline?: ThemeOutline
/**
* language text

View File

@ -3,7 +3,7 @@
"compilerOptions": {
"baseUrl": ".",
"rootDir": "./src",
"types": ["vuepress/client-types", "vite/client"],
"types": ["vuepress/client-types", "vite/client", "webpack-env"],
"outDir": "./lib"
},
"files": [],