feat(theme): add iconify support
This commit is contained in:
parent
3331455790
commit
ae7adc6f8a
@ -28,18 +28,34 @@ export default defineUserConfig({
|
||||
social: [{ icon: 'github', link: 'https://github.com/pengzhanbo' }],
|
||||
notes,
|
||||
navbar: [
|
||||
{ text: 'Blog', link: '/blog/', activeMatch: '/blog/' },
|
||||
{ text: 'Home', link: '/', icon: 'material-symbols:home-outline' },
|
||||
{
|
||||
text: 'Blog',
|
||||
link: '/blog/',
|
||||
icon: 'material-symbols:article-outline',
|
||||
},
|
||||
{
|
||||
text: 'VuePress',
|
||||
icon: 'vscode-icons:file-type-vue',
|
||||
items: [
|
||||
{ text: 'theme-plume', link: '/note/vuepress-theme-plume/' },
|
||||
{
|
||||
text: 'theme-plume',
|
||||
link: '/note/vuepress-theme-plume/',
|
||||
icon: 'icon-park-outline:theme',
|
||||
},
|
||||
{
|
||||
text: 'Plugin',
|
||||
icon: 'mingcute:plugin-2-line',
|
||||
items: [
|
||||
{ text: 'caniuse', link: '/note/vuepress-plugin/caniuse/' },
|
||||
{
|
||||
text: 'caniuse',
|
||||
link: '/note/vuepress-plugin/caniuse/',
|
||||
icon: 'tabler:brand-css3',
|
||||
},
|
||||
{
|
||||
text: 'netlify-functions',
|
||||
link: '/note/vuepress-plugin/netlify-functions/',
|
||||
icon: 'teenyicons:netlify-outline',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@ -12,6 +12,7 @@ export default definePlumeNotesConfig({
|
||||
'',
|
||||
{
|
||||
text: '指南',
|
||||
icon: 'icon-park-outline:guide-board',
|
||||
items: ['快速开始', '编写文章'],
|
||||
},
|
||||
{
|
||||
|
||||
@ -44,6 +44,6 @@
|
||||
"VuePress",
|
||||
"vuepress plugin",
|
||||
"iconify",
|
||||
"vuepress-plugin-plugin-iconify"
|
||||
"vuepress-plugin-iconify"
|
||||
]
|
||||
}
|
||||
|
||||
@ -6,15 +6,14 @@ export const iconifyPlugin = ({
|
||||
componentName = 'Iconify',
|
||||
size = '1em',
|
||||
color = 'currentColor',
|
||||
}: IconifyOptions): Plugin => {
|
||||
}: IconifyOptions = {}): Plugin => {
|
||||
return (app: App) => {
|
||||
return {
|
||||
name: '@vuepress-plume/vuepress-plugin-iconify',
|
||||
define: {
|
||||
__VUEPRESS_PLUGIN_ICONIFY_COMPONENT_NAME__:
|
||||
JSON.stringify(componentName),
|
||||
__VUEPRESS_PLUGIN_ICONIFY_DEFAULT_SIZE__: JSON.stringify(size),
|
||||
__VUEPRESS_PLUGIN_ICONIFY_DEFAULT_COLOR__: JSON.stringify(color),
|
||||
__VUEPRESS_PLUGIN_ICONIFY_COMPONENT_NAME__: componentName,
|
||||
__VUEPRESS_PLUGIN_ICONIFY_DEFAULT_SIZE__: size,
|
||||
__VUEPRESS_PLUGIN_ICONIFY_DEFAULT_COLOR__: color,
|
||||
},
|
||||
clientConfigFile: path.resolve(
|
||||
getDirname(import.meta.url),
|
||||
|
||||
@ -49,6 +49,7 @@
|
||||
"@vuepress-plume/vuepress-plugin-blog-data": "workspace:*",
|
||||
"@vuepress-plume/vuepress-plugin-caniuse": "workspace:*",
|
||||
"@vuepress-plume/vuepress-plugin-copy-code": "workspace:*",
|
||||
"@vuepress-plume/vuepress-plugin-iconify": "workspace:*",
|
||||
"@vuepress-plume/vuepress-plugin-notes-data": "workspace:*",
|
||||
"@vuepress/client": "2.0.0-beta.60",
|
||||
"@vuepress/core": "2.0.0-beta.60",
|
||||
|
||||
@ -3,13 +3,17 @@ import MenuLink from './MenuLink.vue'
|
||||
|
||||
defineProps<{
|
||||
text?: string
|
||||
icon?: string
|
||||
items: any[]
|
||||
}>()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="menu-group">
|
||||
<p v-if="text" class="title">{{ text }}</p>
|
||||
<p v-if="text" class="title">
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
{{ text }}
|
||||
</p>
|
||||
|
||||
<template v-for="item in items">
|
||||
<MenuLink v-if="'link' in item" :key="item?.link" :item="item" />
|
||||
|
||||
@ -22,6 +22,7 @@ const page = usePageData()
|
||||
}"
|
||||
:href="item.link"
|
||||
>
|
||||
<Icon v-if="item.icon" :name="item.icon" />
|
||||
{{ item.text }}
|
||||
</AutoLink>
|
||||
</div>
|
||||
|
||||
@ -12,7 +12,12 @@ defineProps<{
|
||||
<div v-if="items" class="items">
|
||||
<template v-for="item in items" :key="item.text">
|
||||
<MenuLink v-if="'link' in item" :item="item" />
|
||||
<MenuGroup v-else :text="item.text" :items="item.items" />
|
||||
<MenuGroup
|
||||
v-else
|
||||
:text="item.text"
|
||||
:items="item.items"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ import IconMoreHorizontal from '../icons/IconMoreHorizontal.vue'
|
||||
import VMenu from './VMenu.vue'
|
||||
|
||||
defineProps<{
|
||||
prefixIcon?: string
|
||||
icon?: any
|
||||
button?: string
|
||||
label?: string
|
||||
@ -22,6 +23,13 @@ function onBlur() {
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
// eslint-disable-next-line vue/match-component-file-name
|
||||
name: 'Flyout',
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
ref="el"
|
||||
@ -38,6 +46,7 @@ function onBlur() {
|
||||
@click="open = !open"
|
||||
>
|
||||
<span v-if="button || icon" class="text">
|
||||
<Icon v-if="prefixIcon" :name="prefixIcon" />
|
||||
<Component :is="icon" v-if="icon" class="option-icon" />
|
||||
{{ button }}
|
||||
<IconChevronDown class="text-icon" />
|
||||
|
||||
@ -19,5 +19,6 @@ const page = usePageData()
|
||||
}"
|
||||
:button="item.text"
|
||||
:items="item.items"
|
||||
:prefix-icon="item.icon"
|
||||
/>
|
||||
</template>
|
||||
|
||||
@ -24,6 +24,7 @@ const page = usePageData()
|
||||
:href="item.link"
|
||||
:no-icon="true"
|
||||
>
|
||||
<Icon v-if="item.icon" :name="item.icon" />
|
||||
{{ item.text }}
|
||||
</AutoLink>
|
||||
</template>
|
||||
|
||||
@ -13,6 +13,7 @@ const theme = useThemeLocaleData()
|
||||
v-if="'link' in item"
|
||||
:text="item.text"
|
||||
:link="item.link"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
<NavScreenMenuGroup v-else :text="item.text || ''" :items="item.items" />
|
||||
</template>
|
||||
|
||||
@ -6,6 +6,7 @@ import NavScreenMenuGroupSection from './NavScreenMenuGroupSection.vue'
|
||||
|
||||
const props = defineProps<{
|
||||
text: string
|
||||
icon?: string
|
||||
items: any[]
|
||||
}>()
|
||||
|
||||
@ -28,18 +29,29 @@ function toggle() {
|
||||
:aria-expanded="isOpen"
|
||||
@click="toggle"
|
||||
>
|
||||
<span class="button-text">{{ text }}</span>
|
||||
<span class="button-text">
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
{{ text }}
|
||||
</span>
|
||||
<IconPlus class="button-icon" />
|
||||
</button>
|
||||
|
||||
<div :id="groupId" class="items">
|
||||
<template v-for="item in items" :key="item.text">
|
||||
<div v-if="'link' in item" :key="item.text" class="item">
|
||||
<NavScreenMenuGroupLink :text="item.text" :link="item.link" />
|
||||
<NavScreenMenuGroupLink
|
||||
:text="item.text"
|
||||
:link="item.link"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div v-else class="group">
|
||||
<NavScreenMenuGroupSection :text="item.text" :items="item.items" />
|
||||
<NavScreenMenuGroupSection
|
||||
:text="item.text"
|
||||
:items="item.items"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
|
||||
@ -3,6 +3,7 @@ import { inject } from 'vue'
|
||||
import AutoLink from '../AutoLink.vue'
|
||||
|
||||
defineProps<{
|
||||
icon?: string
|
||||
text: string
|
||||
link: string
|
||||
}>()
|
||||
@ -16,6 +17,7 @@ const closeScreen = inject('close-screen') as () => void
|
||||
:href="link"
|
||||
@click="closeScreen"
|
||||
>
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
{{ text }}
|
||||
</AutoLink>
|
||||
</template>
|
||||
|
||||
@ -3,6 +3,7 @@ import type { NavItemWithLink } from '../../../shared/index.js'
|
||||
import NavScreenMenuGroupLink from './NavScreenMenuGroupLink.vue'
|
||||
|
||||
defineProps<{
|
||||
icon?: string
|
||||
text?: string
|
||||
items: NavItemWithLink[]
|
||||
}>()
|
||||
@ -10,12 +11,16 @@ defineProps<{
|
||||
|
||||
<template>
|
||||
<div class="nav-screen-menu-group-section">
|
||||
<p v-if="text" class="title">{{ text }}</p>
|
||||
<p v-if="text" class="title">
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
{{ text }}
|
||||
</p>
|
||||
<NavScreenMenuGroupLink
|
||||
v-for="item in items"
|
||||
:key="item.text"
|
||||
:text="item.text"
|
||||
:link="item.link"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -5,6 +5,7 @@ import AutoLink from '../AutoLink.vue'
|
||||
defineProps<{
|
||||
text: string
|
||||
link: string
|
||||
icon?: string
|
||||
}>()
|
||||
|
||||
const closeScreen = inject('close-screen') as () => void
|
||||
@ -12,6 +13,7 @@ const closeScreen = inject('close-screen') as () => void
|
||||
|
||||
<template>
|
||||
<AutoLink class="nav-screen-menu-link" :href="link" @click="closeScreen">
|
||||
<Icon v-if="icon" :name="icon" />
|
||||
{{ text }}
|
||||
</AutoLink>
|
||||
</template>
|
||||
|
||||
@ -31,6 +31,15 @@ export default defineClientConfig({
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
// eslint-disable-next-line vue/match-component-file-name
|
||||
app.component('Icon', (props) => {
|
||||
const Iconify = app.component('Iconify')
|
||||
if (Iconify) {
|
||||
return h(Iconify, props)
|
||||
}
|
||||
return null
|
||||
})
|
||||
},
|
||||
setup() {
|
||||
setupDarkMode()
|
||||
|
||||
@ -12,3 +12,7 @@
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.vp-iconify {
|
||||
margin: 0.3em;
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { baiduTongjiPlugin } from '@vuepress-plume/vuepress-plugin-baidu-tongji'
|
||||
import { blogDataPlugin } from '@vuepress-plume/vuepress-plugin-blog-data'
|
||||
import { caniusePlugin } from '@vuepress-plume/vuepress-plugin-caniuse'
|
||||
import { copyCodePlugin } from '@vuepress-plume/vuepress-plugin-copy-code'
|
||||
import { iconifyPlugin } from '@vuepress-plume/vuepress-plugin-iconify'
|
||||
import { notesDataPlugin } from '@vuepress-plume/vuepress-plugin-notes-data'
|
||||
import type { App, PluginConfig } from '@vuepress/core'
|
||||
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
|
||||
@ -74,7 +75,11 @@ export const setupPlugins = (
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
localeOptions.notes ? notesDataPlugin(localeOptions.notes) : [],
|
||||
|
||||
iconifyPlugin(),
|
||||
|
||||
activeHeaderLinksPlugin({
|
||||
headerLinkSelector: 'a.outline-link',
|
||||
headerAnchorSelector: '.header-anchor',
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
export * from './base.js'
|
||||
export * from './frontmatter.js'
|
||||
export * from './note.js'
|
||||
export * from './options/index.js'
|
||||
export * from './page.js'
|
||||
export * from './blog.js'
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
export interface PlumeThemeNotesOptions {
|
||||
/**
|
||||
* notes 链接前缀
|
||||
*
|
||||
* 默认: /note/
|
||||
*/
|
||||
link?: string
|
||||
/**
|
||||
* notes 笔记所在目录
|
||||
*
|
||||
* 此处配置的为所有笔记的存放目录,
|
||||
*
|
||||
* 该目录应该在 sourceDir 目录的子目录
|
||||
*
|
||||
* 目录中的所有文章默认不会出现在 article文章列表之中
|
||||
*
|
||||
* 默认值: _notes
|
||||
*/
|
||||
dir?: string
|
||||
|
||||
/**
|
||||
* 是否可折叠
|
||||
*
|
||||
* 默认不折叠, 仅对一级有效
|
||||
*/
|
||||
collapsible?: boolean
|
||||
/**
|
||||
* 笔记集合配置
|
||||
*
|
||||
* 允许存在多个 note,统一以文件夹形式放在 dir 子级
|
||||
*/
|
||||
notes: PlumeThemeNotesItem[]
|
||||
}
|
||||
|
||||
export interface PlumeThemeNotesItem {
|
||||
text: string
|
||||
link: string
|
||||
dir: string
|
||||
sidebar?: PlumeThemeSidebarConfigOptions | 'auto'
|
||||
}
|
||||
|
||||
export type PlumeThemeSidebarConfigOptions = (
|
||||
| PlumeThemeNotesConfigItem
|
||||
| string
|
||||
)[]
|
||||
export interface PlumeThemeNotesConfigItem {
|
||||
text: string
|
||||
link?: string
|
||||
dir?: string
|
||||
children: PlumeThemeSidebarConfigOptions
|
||||
}
|
||||
@ -3,6 +3,7 @@ export type NavItem = NavItemWithLink | NavItemWithChildren
|
||||
export type NavItemWithLink = {
|
||||
text: string
|
||||
link: string
|
||||
icon?: string
|
||||
|
||||
/**
|
||||
* `activeMatch` is expected to be a regex string. We can't use actual
|
||||
@ -13,11 +14,13 @@ export type NavItemWithLink = {
|
||||
|
||||
export type NavItemChildren = {
|
||||
text?: string
|
||||
icon?: string
|
||||
items: NavItemWithLink[]
|
||||
}
|
||||
|
||||
export interface NavItemWithChildren {
|
||||
text?: string
|
||||
icon?: string
|
||||
items: (NavItemChildren | NavItemWithLink)[]
|
||||
|
||||
/**
|
||||
|
||||
2
pnpm-lock.yaml
generated
2
pnpm-lock.yaml
generated
@ -295,6 +295,7 @@ importers:
|
||||
'@vuepress-plume/vuepress-plugin-blog-data': workspace:*
|
||||
'@vuepress-plume/vuepress-plugin-caniuse': workspace:*
|
||||
'@vuepress-plume/vuepress-plugin-copy-code': workspace:*
|
||||
'@vuepress-plume/vuepress-plugin-iconify': workspace:*
|
||||
'@vuepress-plume/vuepress-plugin-notes-data': workspace:*
|
||||
'@vuepress/client': 2.0.0-beta.60
|
||||
'@vuepress/core': 2.0.0-beta.60
|
||||
@ -333,6 +334,7 @@ importers:
|
||||
'@vuepress-plume/vuepress-plugin-blog-data': link:../plugin-blog-data
|
||||
'@vuepress-plume/vuepress-plugin-caniuse': link:../plugin-caniuse
|
||||
'@vuepress-plume/vuepress-plugin-copy-code': link:../plugin-copy-code
|
||||
'@vuepress-plume/vuepress-plugin-iconify': link:../plugin-iconify
|
||||
'@vuepress-plume/vuepress-plugin-notes-data': link:../plugin-notes-data
|
||||
'@vuepress/client': 2.0.0-beta.60
|
||||
'@vuepress/core': 2.0.0-beta.60
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user