feat(theme): add iconify support

This commit is contained in:
pengzhanbo 2023-02-18 05:05:40 +08:00
parent 3331455790
commit ae7adc6f8a
23 changed files with 98 additions and 67 deletions

View File

@ -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',
},
],
},

View File

@ -12,6 +12,7 @@ export default definePlumeNotesConfig({
'',
{
text: '指南',
icon: 'icon-park-outline:guide-board',
items: ['快速开始', '编写文章'],
},
{

View File

@ -44,6 +44,6 @@
"VuePress",
"vuepress plugin",
"iconify",
"vuepress-plugin-plugin-iconify"
"vuepress-plugin-iconify"
]
}

View File

@ -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),

View File

@ -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",

View File

@ -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" />

View File

@ -22,6 +22,7 @@ const page = usePageData()
}"
:href="item.link"
>
<Icon v-if="item.icon" :name="item.icon" />
{{ item.text }}
</AutoLink>
</div>

View File

@ -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>

View File

@ -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" />

View File

@ -19,5 +19,6 @@ const page = usePageData()
}"
:button="item.text"
:items="item.items"
:prefix-icon="item.icon"
/>
</template>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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()

View File

@ -12,3 +12,7 @@
width: 20px;
height: 20px;
}
.vp-iconify {
margin: 0.3em;
}

View File

@ -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',

View File

@ -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'

View File

@ -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
}

View File

@ -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
View File

@ -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