From ce544d2dfc931d3e6fda9c93e65fb6c1609ba91c Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Fri, 26 Jul 2024 16:46:05 +0800
Subject: [PATCH 1/9] feat(theme): add support disable `blog`
---
theme/src/client/composables/langs.ts | 3 +-
.../node/autoFrontmatter/resolveOptions.ts | 56 ++++++++++---------
theme/src/node/config/resolveThemeData.ts | 32 ++++++-----
theme/src/node/prepare/prepareBlogData.ts | 6 ++
theme/src/node/setupPages.ts | 3 +
theme/src/shared/options/locale.ts | 4 +-
6 files changed, 59 insertions(+), 45 deletions(-)
diff --git a/theme/src/client/composables/langs.ts b/theme/src/client/composables/langs.ts
index 994b1149..7aee9516 100644
--- a/theme/src/client/composables/langs.ts
+++ b/theme/src/client/composables/langs.ts
@@ -29,8 +29,9 @@ export function useLangs({
const { notFound, path } = resolveRoute(targetPath)
if (!notFound)
return path
+
const blog = theme.value.blog
- if (isBlogPost.value)
+ if (isBlogPost.value && blog !== false)
return withBase(blog?.link || normalizeLink(locale, 'blog/'))
const sidebarList = sidebar.value
diff --git a/theme/src/node/autoFrontmatter/resolveOptions.ts b/theme/src/node/autoFrontmatter/resolveOptions.ts
index c417240b..35947d59 100644
--- a/theme/src/node/autoFrontmatter/resolveOptions.ts
+++ b/theme/src/node/autoFrontmatter/resolveOptions.ts
@@ -194,34 +194,36 @@ export function resolveOptions(
include: '**/{readme,README,index}.md',
frontmatter: {},
},
- {
- include: localeOptions.blog?.include ?? ['**/*.md'],
- frontmatter: {
- ...options.title !== false
- ? {
- title(title: string, { relativePath }) {
- if (title)
- return title
- const basename = path.basename(relativePath || '', '.md')
- return basename
- },
- } as AutoFrontmatterObject
- : undefined,
- ...baseFrontmatter,
- ...options.permalink !== false
- ? {
- permalink(permalink: string, { relativePath }) {
- if (permalink)
- return permalink
- const locale = resolveLocale(relativePath)
- const prefix = withBase(articlePrefix, locale)
+ localeOptions.blog !== false
+ ? {
+ include: localeOptions.blog?.include ?? ['**/*.md'],
+ frontmatter: {
+ ...options.title !== false
+ ? {
+ title(title: string, { relativePath }) {
+ if (title)
+ return title
+ const basename = path.basename(relativePath || '', '.md')
+ return basename
+ },
+ } as AutoFrontmatterObject
+ : undefined,
+ ...baseFrontmatter,
+ ...options.permalink !== false
+ ? {
+ permalink(permalink: string, { relativePath }) {
+ if (permalink)
+ return permalink
+ const locale = resolveLocale(relativePath)
+ const prefix = withBase(articlePrefix, locale)
- return normalizePath(`${prefix}/${nanoid()}/`)
- },
- } as AutoFrontmatterObject
- : undefined,
- },
- },
+ return normalizePath(`${prefix}/${nanoid()}/`)
+ },
+ } as AutoFrontmatterObject
+ : undefined,
+ },
+ }
+ : '',
{
include: '*',
diff --git a/theme/src/node/config/resolveThemeData.ts b/theme/src/node/config/resolveThemeData.ts
index 1484be1a..a8f025e4 100644
--- a/theme/src/node/config/resolveThemeData.ts
+++ b/theme/src/node/config/resolveThemeData.ts
@@ -35,8 +35,6 @@ export function resolveThemeData(app: App, options: PlumeThemeLocaleOptions): Pl
}
})
- const blog = options.blog || {}
- const blogLink = blog.link || '/blog/'
entries(options.locales || {}).forEach(([locale, opt]) => {
// 注入预设 导航栏
// home | blog | tags | archives
@@ -47,21 +45,25 @@ export function resolveThemeData(app: App, options: PlumeThemeLocaleOptions): Pl
text: PRESET_LOCALES[localePath].home,
link: locale,
}]
- navbar.push({
- text: PRESET_LOCALES[localePath].blog,
- link: withBase(blogLink, locale),
- })
- if (blog.tags !== false) {
+ if (options.blog !== false) {
+ const blog = options.blog || {}
+ const blogLink = blog.link || '/blog/'
navbar.push({
- text: PRESET_LOCALES[localePath].tag,
- link: withBase(blog.tagsLink || `${blogLink}/tags/`, locale),
- })
- }
- if (blog.archives !== false) {
- navbar.push({
- text: PRESET_LOCALES[localePath].archive,
- link: withBase(blog.archivesLink || `${blogLink}/archives/`, locale),
+ text: PRESET_LOCALES[localePath].blog,
+ link: withBase(blogLink, locale),
})
+ if (blog.tags !== false) {
+ navbar.push({
+ text: PRESET_LOCALES[localePath].tag,
+ link: withBase(blog.tagsLink || `${blogLink}/tags/`, locale),
+ })
+ }
+ if (blog.archives !== false) {
+ navbar.push({
+ text: PRESET_LOCALES[localePath].archive,
+ link: withBase(blog.archivesLink || `${blogLink}/archives/`, locale),
+ })
+ }
}
themeData.locales![locale].navbar = navbar
diff --git a/theme/src/node/prepare/prepareBlogData.ts b/theme/src/node/prepare/prepareBlogData.ts
index c563a048..ee8531ac 100644
--- a/theme/src/node/prepare/prepareBlogData.ts
+++ b/theme/src/node/prepare/prepareBlogData.ts
@@ -25,6 +25,12 @@ export async function preparedBlogData(
localeOptions: PlumeThemeLocaleOptions,
encrypt?: PlumeThemeEncrypt,
): Promise {
+ if (localeOptions.blog === false) {
+ const content = resolveContent(app, { name: 'blogPostData', content: [] })
+ await writeTemp(app, 'internal/blogData.js', content)
+ return
+ }
+
const start = performance.now()
const blog = localeOptions.blog || {}
diff --git a/theme/src/node/setupPages.ts b/theme/src/node/setupPages.ts
index 3beb8c93..7892cff4 100644
--- a/theme/src/node/setupPages.ts
+++ b/theme/src/node/setupPages.ts
@@ -18,6 +18,9 @@ export async function setupPage(
app: App,
localeOption: PlumeThemeLocaleOptions,
) {
+ if (localeOption.blog === false)
+ return
+
const pageList: Promise[] = []
const locales = localeOption.locales || {}
const rootPath = getRootLangPath(app)
diff --git a/theme/src/shared/options/locale.ts b/theme/src/shared/options/locale.ts
index 47af52a4..97f09d65 100644
--- a/theme/src/shared/options/locale.ts
+++ b/theme/src/shared/options/locale.ts
@@ -64,7 +64,7 @@ export interface PlumeThemeLocaleData extends LocaleData {
/**
* 博客配置
*/
- blog?: PlumeThemeBlog
+ blog?: false | PlumeThemeBlog
/**
* 文章链接前缀
@@ -274,7 +274,7 @@ export interface PlumeThemeLocaleData extends LocaleData {
encryptPlaceholder?: string
}
-/** =========================== Avatar ================================ */
+/** =========================== Profile ================================ */
/**
* 个人资料
From 5e9d2d043a4842f9769b0fa856982a4e0dd61aae Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Fri, 26 Jul 2024 16:48:02 +0800
Subject: [PATCH 2/9] feat(theme): add support for optional `features`
---
theme/package.json | 3 +++
theme/tsup.config.ts | 20 ++++++++++++++++++++
2 files changed, 23 insertions(+)
diff --git a/theme/package.json b/theme/package.json
index 9dd17fbc..51293cde 100644
--- a/theme/package.json
+++ b/theme/package.json
@@ -37,6 +37,9 @@
"types": "./lib/client/composables/index.d.ts",
"import": "./lib/client/composables/index.js"
},
+ "./features/*": {
+ "import": "./lib/client/features/components/*"
+ },
"./shared": {
"types": "./lib/shared/index.d.ts",
"import": "./lib/shared/index.js"
diff --git a/theme/tsup.config.ts b/theme/tsup.config.ts
index 56142148..4a6f6da7 100644
--- a/theme/tsup.config.ts
+++ b/theme/tsup.config.ts
@@ -1,3 +1,6 @@
+import process from 'node:process'
+import fs from 'node:fs'
+import path from 'node:path'
import { type Options, defineConfig } from 'tsup'
const sharedExternal: (string | RegExp)[] = [
@@ -12,6 +15,11 @@ const clientExternal: (string | RegExp)[] = [
/.*\.css$/,
]
+const featuresComposables = fs.readdirSync(
+ path.join(process.cwd(), 'src/client/features/composables'),
+ { recursive: true, encoding: 'utf-8' },
+)
+
export default defineConfig((cli) => {
const DEFAULT_OPTIONS: Options = {
dts: !cli.watch,
@@ -35,6 +43,7 @@ export default defineConfig((cli) => {
outDir: './lib/node',
external: sharedExternal,
target: 'node18',
+ watch: false,
},
// client/utils/index.js
{
@@ -77,5 +86,16 @@ export default defineConfig((cli) => {
'./config.js',
],
},
+ ...featuresComposables.map(file => ({
+ ...DEFAULT_OPTIONS,
+ entry: [`./src/client/features/composables/${file}`],
+ outDir: `./lib/client/features/composables/`,
+ external: [
+ ...clientExternal,
+ '../../composables/index.js',
+ '../../utils/index.js',
+ ...featuresComposables.map(file => `./${file.replace('.ts', '.js')}`),
+ ],
+ })),
]
})
From 4c44462e61a0561e01c4c6d80cf79d0315a95f4c Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Fri, 26 Jul 2024 16:49:28 +0800
Subject: [PATCH 3/9] feat(theme): add component ``
---
.../client/features/components/RepoCard.vue | 155 ++++++++++++++++++
.../features/composables/github-repo.ts | 48 ++++++
2 files changed, 203 insertions(+)
create mode 100644 theme/src/client/features/components/RepoCard.vue
create mode 100644 theme/src/client/features/composables/github-repo.ts
diff --git a/theme/src/client/features/components/RepoCard.vue b/theme/src/client/features/components/RepoCard.vue
new file mode 100644
index 00000000..a1c36b77
--- /dev/null
+++ b/theme/src/client/features/components/RepoCard.vue
@@ -0,0 +1,155 @@
+
+
+
+
+
+
+
diff --git a/theme/src/client/features/composables/github-repo.ts b/theme/src/client/features/composables/github-repo.ts
new file mode 100644
index 00000000..aff888bf
--- /dev/null
+++ b/theme/src/client/features/composables/github-repo.ts
@@ -0,0 +1,48 @@
+import { computed, ref, toValue, watch } from 'vue'
+import type { MaybeRef } from 'vue'
+
+export interface GithubRepoInfo {
+ name: string
+ fullName: string
+ description: string
+ url: string
+ stars: number
+ forks: number
+ watchers: number
+ language: string
+ languageColor: string
+ visibility: 'Private' | 'Public' // private, public
+ template: boolean
+ ownerType: 'User' | 'Organization'
+ license: {
+ name: string
+ url: string
+ } | null
+}
+
+export function useGithubRepo(repo: MaybeRef) {
+ const repoRef = computed(() => {
+ const info = toValue(repo)
+ const [owner = '', name = ''] = info.split('/')
+ return { owner, name }
+ })
+ const data = ref(null)
+ const loaded = ref(false)
+
+ async function fetchData() {
+ const { owner, name } = repoRef.value
+ if (__VUEPRESS_SSR__ || !owner || !name)
+ return
+
+ loaded.value = false
+ const res = await fetch(`https://api.pengzhanbo.cn/github/repo/${owner}/${name}`)
+ .then(res => res.json()) as GithubRepoInfo
+
+ data.value = res
+ loaded.value = true
+ }
+
+ watch(repoRef, fetchData, { immediate: true })
+
+ return { data, loaded }
+}
From 46b382e0b34cbe0e209d897fd6c09a8fad7eed94 Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Fri, 26 Jul 2024 16:50:00 +0800
Subject: [PATCH 4/9] perf(theme): improve prepare icons data
---
theme/src/client/components/VPIconify.vue | 2 +-
theme/src/node/prepare/prepareIcons.ts | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/theme/src/client/components/VPIconify.vue b/theme/src/client/components/VPIconify.vue
index d2492c09..a4a63fde 100644
--- a/theme/src/client/components/VPIconify.vue
+++ b/theme/src/client/components/VPIconify.vue
@@ -61,7 +61,7 @@ const bind = computed(() => ({
diff --git a/theme/src/node/prepare/prepareIcons.ts b/theme/src/node/prepare/prepareIcons.ts
index 44dd6120..bc085bf7 100644
--- a/theme/src/node/prepare/prepareIcons.ts
+++ b/theme/src/node/prepare/prepareIcons.ts
@@ -16,8 +16,8 @@ interface IconData {
type CollectMap = Record
type IconDataMap = Record
-const ICON_REGEXP = /<(?:VP)?Icon(?:ify)?([^>]*)>/g
-const ICON_NAME_REGEXP = /name="([^"]+)"/
+const ICON_REGEXP = /<(?:VP)?(Icon|Card|LinkCard)([^>]*)>/g
+const ICON_NAME_REGEXP = /(?:name|icon)="([^"]+)"/
const URL_CONTENT_REGEXP = /(url\([\s\S]+\))/
const JS_FILENAME = 'internal/iconify.js'
const CSS_FILENAME = 'internal/iconify.css'
From aa96c35bd589bcba026add17da8932e8ae5744ce Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Sat, 27 Jul 2024 19:23:09 +0800
Subject: [PATCH 5/9] feat(theme): add component ``
---
.../client/features/components/NpmBadge.vue | 35 ++++
.../features/components/NpmBadgeGroup.vue | 37 ++++
.../client/features/composables/npm-badge.ts | 175 ++++++++++++++++++
3 files changed, 247 insertions(+)
create mode 100644 theme/src/client/features/components/NpmBadge.vue
create mode 100644 theme/src/client/features/components/NpmBadgeGroup.vue
create mode 100644 theme/src/client/features/composables/npm-badge.ts
diff --git a/theme/src/client/features/components/NpmBadge.vue b/theme/src/client/features/components/NpmBadge.vue
new file mode 100644
index 00000000..98fcd98c
--- /dev/null
+++ b/theme/src/client/features/components/NpmBadge.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/theme/src/client/features/components/NpmBadgeGroup.vue b/theme/src/client/features/components/NpmBadgeGroup.vue
new file mode 100644
index 00000000..ea684901
--- /dev/null
+++ b/theme/src/client/features/components/NpmBadgeGroup.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/theme/src/client/features/composables/npm-badge.ts b/theme/src/client/features/composables/npm-badge.ts
new file mode 100644
index 00000000..919ed869
--- /dev/null
+++ b/theme/src/client/features/composables/npm-badge.ts
@@ -0,0 +1,175 @@
+import { computed, inject, provide, ref, toValue } from 'vue'
+import type { ComputedRef, InjectionKey, Ref } from 'vue'
+
+const DEFAULT_COLOR = '#32A9C3'
+const DEFAULT_LABEL_COLOR = '#1B3C4A'
+const BADGE_URL = 'https://img.shields.io'
+const GITHUB_URL = 'https://github.com'
+const NPM_URL = 'https://www.npmjs.com/package'
+
+export type NpmBadgeType =
+ // github
+ | 'source' // github source
+ | 'stars' // github stars
+ | 'forks' // github forks
+ | 'license' // github license
+ // npm
+ | 'version' // npm version
+ | 'dt' // alias d18m
+ | 'd18m' // npm downloads last 18 months
+ | 'dw' // npm downloads weekly
+ | 'dm' // npm downloads monthly
+ | 'dy' // npm downloads yearly
+
+export type NpmBadgeTheme = 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' | 'social'
+
+export interface NpmBadgeBaseOptions {
+ // npm package name
+ name?: string
+ // github repo
+ repo?: string
+ // github branch
+ branch?: string
+ // github directory
+ dir?: string
+ // text color
+ color?: string
+ // label color
+ labelColor?: string
+ // badge style
+ theme?: NpmBadgeTheme
+}
+
+export interface NpmBadgeOptions extends NpmBadgeBaseOptions {
+ type: NpmBadgeType
+ // label text
+ label?: string
+}
+
+export interface NpmBadgeGroupOptions extends Omit {
+ items?: string | NpmBadgeType | NpmBadgeType[]
+}
+
+export interface NpmBadgeInfo {
+ badgeUrl: string
+ link?: string
+ alt?: string
+}
+
+type NpmBadgeBaseOptionsRef = Ref
+
+const NpmBadgeSymbol: InjectionKey = Symbol(__VUEPRESS_DEV__ ? 'NpmBadge' : '')
+
+export function useNpmBadge(opt: Ref): ComputedRef {
+ const parentOpt = inject(NpmBadgeSymbol, ref({}) as NpmBadgeBaseOptionsRef)
+
+ return computed(() => {
+ const po = toValue(parentOpt)
+ const o = toValue(opt)
+ const res: NpmBadgeOptions = {
+ name: o.name || po.name,
+ repo: o.repo || po.repo,
+ branch: o.branch || po.branch,
+ dir: o.dir || po.dir,
+ type: o.type,
+ color: o.color || po.color,
+ label: o.label,
+ labelColor: o.labelColor || po.labelColor,
+ theme: o.theme || po.theme,
+ }
+ return resolveNpmBadgeOptions(res)
+ })
+}
+
+export function useNpmBadgeGroup(opt: Ref) {
+ const baseOptions = computed(() => {
+ const o = toValue(opt)
+ return {
+ name: o.name,
+ repo: o.repo,
+ branch: o.branch,
+ dir: o.dir,
+ color: o.color,
+ labelColor: o.labelColor,
+ theme: o.theme,
+ }
+ })
+
+ provide(NpmBadgeSymbol, baseOptions)
+}
+
+function resolveNpmBadgeOptions(options: NpmBadgeOptions): NpmBadgeInfo {
+ let { name = '', repo = '', branch = 'main', dir = '', type, color, label, labelColor, theme = '' } = options
+ name = name || repo.split('/')?.[1] || ''
+ const normalizeName = encodeURIComponent(name)
+
+ const githubLink = repo ? `${GITHUB_URL}/${repo}${dir ? `/tree/${branch}/${dir}` : ''}` : ''
+ const npmLink = `${NPM_URL}/${name}`
+
+ const params = new URLSearchParams()
+
+ if (type !== 'source' && type !== 'stars' && type !== 'forks') {
+ params.append('style', theme || 'flat')
+ params.append('color', color || DEFAULT_COLOR)
+ params.append('labelColor', labelColor || DEFAULT_LABEL_COLOR)
+ }
+
+ switch (type) {
+ case 'source': {
+ params.append('logo', 'github')
+ params.append('color', labelColor || DEFAULT_LABEL_COLOR)
+ return {
+ badgeUrl: `${BADGE_URL}/badge/source-a?${params.toString()}`,
+ link: githubLink,
+ alt: 'github source',
+ }
+ }
+ case 'stars':
+ case 'forks': {
+ params.append('style', theme || 'social')
+ return {
+ badgeUrl: `${BADGE_URL}/github/${type}/${repo}?${params.toString()}`,
+ link: githubLink,
+ alt: `github ${type}`,
+ }
+ }
+ case 'license':
+ return {
+ badgeUrl: `${BADGE_URL}/github/license/${repo}?${params.toString()}`,
+ link: githubLink,
+ alt: 'license',
+ }
+ case 'version': {
+ params.append('label', label || name || 'npm')
+ return {
+ badgeUrl: `${BADGE_URL}/npm/v/${normalizeName}?${params.toString()}`,
+ link: npmLink,
+ alt: 'npm version',
+ }
+ }
+ case 'dt':
+ case 'd18m': {
+ params.append('label', label || 'downloads')
+ return {
+ badgeUrl: `${BADGE_URL}/npm/d18m/${normalizeName}?${params.toString()}`,
+ link: npmLink,
+ alt: 'npm downloads',
+ }
+ }
+ case 'dm':
+ case 'dy':
+ case 'dw': {
+ params.append('label', label || 'downloads')
+ return {
+ badgeUrl: `${BADGE_URL}/npm/${type}/${normalizeName}?${params.toString()}`,
+ link: npmLink,
+ alt: 'npm downloads',
+ }
+ }
+ default:
+ return {
+ badgeUrl: `${BADGE_URL}/badge/unknown?${params.toString()}`,
+ alt: 'unknown',
+ }
+ }
+}
From a81c20a21cbcef0c66b6996b518ea3dac1fda824 Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Sat, 27 Jul 2024 19:23:39 +0800
Subject: [PATCH 6/9] perf(theme): improve content layout
---
theme/src/client/components/VPDoc.vue | 4 ++--
theme/src/client/features/components/RepoCard.vue | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/theme/src/client/components/VPDoc.vue b/theme/src/client/components/VPDoc.vue
index 6346705e..4cc2abfd 100644
--- a/theme/src/client/components/VPDoc.vue
+++ b/theme/src/client/components/VPDoc.vue
@@ -174,7 +174,7 @@ watch(
@media (min-width: 1440px) {
.vp-doc-container:not(.has-sidebar) .content {
- max-width: 784px;
+ max-width: 884px;
}
.vp-doc-container.is-blog:not(.has-sidebar.has-aside) .content {
@@ -275,6 +275,6 @@ watch(
}
.vp-doc-container.has-aside .content-container {
- max-width: 688px;
+ max-width: 788px;
}
diff --git a/theme/src/client/features/components/RepoCard.vue b/theme/src/client/features/components/RepoCard.vue
index a1c36b77..efe94170 100644
--- a/theme/src/client/features/components/RepoCard.vue
+++ b/theme/src/client/features/components/RepoCard.vue
@@ -17,7 +17,7 @@ const { loaded, data } = useGithubRepo(toRef(props, 'repo'))
{{ data.ownerType === 'Organization' ? data.fullName : data.name }}
- {{ data.visibility + (data.template ? ' Template' : '') }}
+ {{ data.visibility + (data.template ? ' Template' : '') }}
{{ data.description }}
From ac8984d050c79f7589830fe6b6cdb8b5e4ef3ed2 Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Sat, 27 Jul 2024 19:23:53 +0800
Subject: [PATCH 7/9] docs: update docs
---
docs/.vuepress/notes.ts | 30 +++--
docs/notes/theme/config/主题配置.md | 2 +
docs/notes/theme/guide/功能/npmBadge.md | 151 ++++++++++++++++++++++++
docs/notes/theme/guide/功能/repoCard.md | 91 ++++++++++++++
4 files changed, 264 insertions(+), 10 deletions(-)
create mode 100644 docs/notes/theme/guide/功能/npmBadge.md
create mode 100644 docs/notes/theme/guide/功能/repoCard.md
diff --git a/docs/.vuepress/notes.ts b/docs/.vuepress/notes.ts
index b0e17600..7438bdc8 100644
--- a/docs/.vuepress/notes.ts
+++ b/docs/.vuepress/notes.ts
@@ -22,31 +22,36 @@ export const zhNotes = definePlumeNotesConfig({
{
text: 'markdown',
icon: 'material-symbols:markdown-outline',
- dir: 'markdown',
+ prefix: 'markdown',
+ collapsed: true,
items: ['基础', '扩展', '进阶'],
},
{
text: '代码块',
- dir: '代码',
+ prefix: '代码',
icon: 'ph:code-bold',
+ collapsed: true,
items: ['介绍', '特性支持', '代码组', '导入代码', 'twoslash'],
},
{
text: '代码演示',
- dir: '代码演示',
+ prefix: '代码演示',
icon: 'carbon:demo',
+ collapsed: true,
items: ['前端', 'rust', 'golang', 'kotlin', 'codepen', 'jsFiddle', 'codeSandbox', 'replit'],
},
{
text: '图表',
icon: 'mdi:chart-line',
- dir: '图表',
+ prefix: '图表',
+ collapsed: true,
items: ['chart', 'echarts', 'mermaid', 'flowchart'],
},
{
text: '资源嵌入',
icon: 'dashicons:embed-video',
- dir: '嵌入',
+ prefix: '嵌入',
+ collapsed: true,
items: ['pdf', 'bilibili', 'youtube'],
},
],
@@ -55,8 +60,13 @@ export const zhNotes = definePlumeNotesConfig({
text: '功能',
icon: 'lucide:box',
collapsed: false,
- dir: '功能',
- items: ['图标', '代码复制', '内容搜索', '评论', '加密', '组件', '文章水印', '友情链接页', 'seo', 'sitemap'],
+ prefix: '功能',
+ items: ['图标', '代码复制', '内容搜索', '评论', '加密', '组件', '文章水印', '友情链接页', 'seo', 'sitemap', {
+ text: '非内置功能',
+ icon: 'system-uicons:box-add',
+ collapsed: false,
+ items: ['repoCard', 'npmBadge'],
+ }],
},
{
text: '自定义',
@@ -89,13 +99,13 @@ export const zhNotes = definePlumeNotesConfig({
},
{
text: 'frontmatter',
- dir: 'frontmatter',
+ prefix: 'frontmatter',
collapsed: false,
items: ['basic', 'home', 'post', 'friend'],
},
{
text: '内置插件',
- dir: 'plugins',
+ prefix: 'plugins',
collapsed: false,
items: ['', '代码高亮', '搜索', '阅读统计', 'markdown增强', 'markdownPower', '百度统计', '水印'],
},
@@ -109,7 +119,7 @@ export const zhNotes = definePlumeNotesConfig({
text: '插件',
items: [
// 'caniuse',
- 'iconify',
+ // 'iconify',
'shiki',
'md-power',
'content-updated',
diff --git a/docs/notes/theme/config/主题配置.md b/docs/notes/theme/config/主题配置.md
index 7a14c0d3..68a66509 100644
--- a/docs/notes/theme/config/主题配置.md
+++ b/docs/notes/theme/config/主题配置.md
@@ -179,6 +179,8 @@ interface BlogOptions {
::: warning
该字段不支持在 [主题配置文件 `plume.config.js`](./配置说明.md#主题配置文件) 中进行配置。
+
+ 为了使缓存能够生效,您应该 **删除** `package.json` 中 `vuepress dev` 开发服务启动脚本中的 `--clean-cache` 参数。
:::
### locales
diff --git a/docs/notes/theme/guide/功能/npmBadge.md b/docs/notes/theme/guide/功能/npmBadge.md
new file mode 100644
index 00000000..e3640aae
--- /dev/null
+++ b/docs/notes/theme/guide/功能/npmBadge.md
@@ -0,0 +1,151 @@
+---
+title: Npm 徽章
+author: pengzhanbo
+icon: akar-icons:npm-fill
+createTime: 2024/07/26 22:07:23
+permalink: /guide/npm-badge/
+---
+
+
+
+## 概述
+
+Npm 徽章组件 用于显示 npm 包信息,并提供相关的链接。
+
+徽章由 提供支持。
+
+## 使用
+
+使用该组件需要你手动导入 `NpmBadge` 或 `NpmBadgeGroup` 组件:
+
+```md :no-line-numbers
+
+
+
+
+
+
+
+
+```
+
+
+
+
+
+## ``
+
+单个 npm badge
+
+### Props
+
+| 名称 | 类型 | 必填 | 默认值 | 说明 |
+| ---------- | --------------- | --------------- | ----------- | --------------------------------------- |
+| name | `string` | 否 | `''` | npm 包名,为空则从 `repo` 中获取 |
+| repo | `string` | name 为空时必填 | `''` | 包 github 仓库地址, 格式为 `owner/repo` |
+| type | `NpmBadgeType` | 是 | - | 徽章类型 |
+| theme | `NpmBadgeTheme` | 否 | `'flat'` | 徽章主题 |
+| label | `string` | 否 | `''` | 徽章标签 |
+| color | `string` | 否 | `'#32A9C3'` | 徽章颜色 |
+| labelColor | `string` | 否 | `'#1B3C4A'` | 徽章标签颜色 |
+| branch | `string` | 否 | `'main'` | 仓库分支 |
+| dir | `string` | 否 | `''` | 包所在仓库目录,适用于 monorepo 项目 |
+
+### Types
+
+```ts
+type NpmBadgeType =
+ // github
+ | 'source' // github source
+ | 'stars' // github stars
+ | 'forks' // github forks
+ | 'license' // github license
+ // npm
+ | 'version' // npm version
+ | 'dt' // alias d18m
+ | 'd18m' // npm downloads last 18 months
+ | 'dw' // npm downloads weekly
+ | 'dm' // npm downloads monthly
+ | 'dy' // npm downloads yearly
+
+type NpmBadgeTheme = 'flat' | 'flat-square' | 'plastic' | 'for-the-badge' | 'social'
+```
+
+### 示例
+
+- `` -
+- `` -
+- `` -
+- `` -
+- `` -
+- `` -
+- `` -
+- `` -
+- `` -
+- `` -
+
+## ``
+
+组合多个 npm badge
+
+### Props
+
+| 名称 | 类型 | 必填 | 默认值 | 说明 |
+| ---------- | --------------- | --------------- | ------ | --------------------------------------- |
+| name | `string` | 否 | `''` | npm 包名,为空则从 `repo` 中获取 |
+| repo | `string` | name 为空时必填 | `''` | 包 github 仓库地址, 格式为 `owner/repo` |
+| items | `string \| NpmBadgeType[]` | 否 | - | 徽章类型列表, 传入 `string` 时用 `','`分隔,会自动转换为 `NpmBadgeType[]` |
+| theme | `NpmBadgeTheme` | 否 | `''` | 徽章主题 |
+| color | `string` | 否 | `''` | 徽章颜色 |
+| labelColor | `string` | 否 | `''` | 徽章标签颜色 |
+| branch | `string` | 否 | `''` | 仓库分支 |
+| dir | `string` | 否 | `''` | 包所在仓库目录,适用于 monorepo 项目 |
+
+### Slots
+
+`` 支持传入 多个 `` 组件。
+
+`` 声明的 `Props` 将被注入到 `` 组件中。通过这种方式来实现和简化徽章组合。
+
+### 示例
+
+**输入:**
+
+```md :no-line-numbers
+
+```
+
+**输出:**
+
+
+
+使用 `` 灵活定义徽章组合:
+
+**输入:**
+
+```md :no-line-numbers
+
+
+
+
+
+
+```
+
+**输出:**
+
+
+
+
+
+
+
diff --git a/docs/notes/theme/guide/功能/repoCard.md b/docs/notes/theme/guide/功能/repoCard.md
new file mode 100644
index 00000000..60535f6d
--- /dev/null
+++ b/docs/notes/theme/guide/功能/repoCard.md
@@ -0,0 +1,91 @@
+---
+title: Repo 卡片
+author: pengzhanbo
+icon: octicon:repo-16
+createTime: 2024/07/26 21:11:56
+permalink: /guide/github-repo-card/
+---
+
+
+
+## 概述
+
+Repo 卡片组件 用于显示 GitHub 仓库信息。
+
+## 使用
+
+使用该组件需要你手动导入 `RepoCard` 组件:
+
+```md :no-line-numbers
+
+
+
+
+
+```
+
+注册为全局组件:
+
+::: code-tabs
+@tab .vuepress/client.ts
+
+```ts
+import { defineClientConfig } from 'vuepress/client'
+import RepoCard from 'vuepress-theme-plume/features/RepoCard.vue'
+
+export default defineClientConfig({
+ enhance({ app }) {
+ app.component('RepoCard', RepoCard)
+ },
+})
+```
+
+:::
+
+全局组件可在 其他任意 markdown 文件中使用
+
+```md
+
+```
+
+### Props
+
+`RepoCard` 组件的 接收一个 `repo` 参数,传入的是仓库的地址,格式为 `owner/repo`。
+
+## 示例
+
+### 单卡片
+
+**输入:**
+
+```md
+
+```
+
+**输出:**
+
+
+
+### 多卡片
+
+如果希望以紧凑的方式并排展示多个卡片,可以使用 `CardGrid` 组件。
+
+**输入:**
+
+```md
+
+
+
+
+```
+
+**输出:**
+
+
+
+
+
From 6bf5302da12689b4e088e068d75edfd7b968b552 Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Sat, 27 Jul 2024 20:48:10 +0800
Subject: [PATCH 8/9] perf(theme): improve sidebar active link
---
theme/src/client/composables/sidebar.ts | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/theme/src/client/composables/sidebar.ts b/theme/src/client/composables/sidebar.ts
index 7f8fcc3c..226e5fe8 100644
--- a/theme/src/client/composables/sidebar.ts
+++ b/theme/src/client/composables/sidebar.ts
@@ -16,7 +16,6 @@ import {
ref,
watch,
watchEffect,
- watchPostEffect,
} from 'vue'
import { sidebar as sidebarRaw } from '@internal/sidebar'
import { isActive, normalizeLink, normalizePrefix, resolveNavLink } from '../utils/index.js'
@@ -368,7 +367,7 @@ export function useSidebarControl(item: ComputedRef): Sideb
)
}
- watch([page, item, () => route.hash], updateIsActiveLink)
+ watch([() => page.value.path, item, () => route.hash], updateIsActiveLink)
onMounted(updateIsActiveLink)
const hasActiveLink = computed(() => {
@@ -389,11 +388,11 @@ export function useSidebarControl(item: ComputedRef): Sideb
collapsed.value = !!(collapsible.value && item.value.collapsed)
})
- watchPostEffect(() => {
+ watch(() => [page.value.path, isActiveLink.value, hasActiveLink.value], () => {
if (isActiveLink.value || hasActiveLink.value) {
collapsed.value = false
}
- })
+ }, { immediate: true, flush: 'post' })
const toggle = (): void => {
if (collapsible.value) {
From b55d2682851dc15945b0ffbdbc6f004924744fa1 Mon Sep 17 00:00:00 2001
From: pengzhanbo
Date: Sun, 28 Jul 2024 00:13:01 +0800
Subject: [PATCH 9/9] docs: update docs
---
docs/.vuepress/notes.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/.vuepress/notes.ts b/docs/.vuepress/notes.ts
index 7438bdc8..a7f1a73a 100644
--- a/docs/.vuepress/notes.ts
+++ b/docs/.vuepress/notes.ts
@@ -64,7 +64,7 @@ export const zhNotes = definePlumeNotesConfig({
items: ['图标', '代码复制', '内容搜索', '评论', '加密', '组件', '文章水印', '友情链接页', 'seo', 'sitemap', {
text: '非内置功能',
icon: 'system-uicons:box-add',
- collapsed: false,
+ collapsed: true,
items: ['repoCard', 'npmBadge'],
}],
},