vuepress-theme-hope主题
组件的使用
在markdown文件里引入组件(容器)
自定义注册组件
src.vuepress\components\NavCard.vue
<template>
<el-row :gutter="30">
<el-col :xs="24" :sm="24" :md="12" :lg="8" :xl="8" v-for="(cardObj, index) in cardArr" :key="index"
style="margin-top:20px;height:100px;width:100%;overflow:auto;">
<!-- <el-link class="link-style" :underline="false" target="_blank" :href="cardObj.url" > -->
<!-- <el-card class="box-card" shadow="always" :body-style="{ padding:'5px' }" > -->
<el-card shadow="never" :body-style="{ padding: '20px' }">
<el-row class="box-card-header">
<el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12" style="padding:0px;">
<img style="width:30px;height:30px;text-align:left;" :src="$withBase(cardObj.icon)"
:alt="cardObj.title" />
</el-col>
<el-col :xs="12" :sm="12" :md="12" :lg="12" :xl="12" style="padding:0px;">
<div style="text-align:right;">
<el-tooltip effect="dark" :content="cardObj.desc" placement="bottom">
<el-button :type="type" plain
@click.native="gotoSite(cardObj.url)">{{ cardObj.title }}</el-button>
</el-tooltip>
</div>
</el-col>
</el-row>
<el-row class="box-card-body">
<div style="font-size:10px;color:#999999">{{ cardObj.desc }}</div>
</el-row>
</el-card>
<!-- </el-link> -->
</el-col>
</el-row>
</template>
<script>
export default {
name: "NavCard",
components: {},
props: {
arr: {
type: String,
default: ''
}
},
data() {
return {
cardArr: JSON.parse(this.arr),
type: 'success',
}
},
methods: {
gotoSite(url) {
// console.log(url);
// 在新标签页打开
window.open(url, '_blank').location;
},
},
}
</script>
<style>
.link-style {
width: 100%;
height: 100%;
padding: 0px;
}
.box-card {
width: 100%;
height: 100%;
}
.box-card-header {
width: 100%;
height: 50%;
margin-bottom: 1px;
padding: 0px;
}
.box-card-body {
width: 100%;
height: 50%;
margin-top: 1px;
padding: 0px;
}
.el-card {
border-radius: 10px;
border: none;
background-color: #F6F6F6;
box-shadow: 0px 1px 5px 4px #0000001a;
}
.el-card:hover {
transform: scale(1.03);
/* boder-top: none; */
/* background-color: #FDF853; */
background-color: #98fb98;
}</style>
创建src.vuepress\client.ts
// 客户端增强配置文件-https://v2.vuepress.vuejs.org/zh/guide/migration.html#%E7%BA%A6%E5%AE%9A%E6%96%87%E4%BB%B6%E5%8F%98%E6%9B%B4
import { defineClientConfig } from "@vuepress/client";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
export default defineClientConfig({
enhance: ({ app, router, siteData }) => {
// 引入Element-plus组件库
// 【引入的主要目的不是在MD文档中使用Element的组件,主要是为了编写自己的组件】
// 【自己写的组件被registerComponentsPlugin插件引入全局在进行使用】
app.use(ElementPlus);
},
});
在config.ts插件配置中配置
// 注册全局组件的插件
registerComponentsPlugin({
componentsDir: path.resolve(__dirname, "./components"),
}),
同时需要在config.ts头部引入
import { registerComponentsPlugin } from "@vuepress/plugin-register-components";
import { getDirname, path } from "@vuepress/utils";
const __dirname = getDirname(import.meta.url);
这样就可以在src.vuepress\components文件夹下自由引入相应的组件了
例如引入src.vuepress\components\NavCard.vue组件:
---
# # 当前页面内容标题
title: 友链
# 当前页面图标
icon: link
# 分类
category:
- 友链
# 标签
tag:
- 博客链接
sticky: false
# 是否收藏在博客主题的文章列表中,当填入数字时,数字越大,排名越靠前。
star: false
# 是否将该文章添加至文章列表中
article: false
# 是否将该文章添加至时间线中
---
## 博客推荐
<NavCard arr='[
{"title":"keney","url":"https://blog.nnxx.me/","desc":"基于hexo-matery搭建的博客","icon":"https://pic.imgdb.cn/item/640d9bf1f144a010073218ac.png"}></NavCard>
效果如下图:
链接
src.vuepress\components\MyLinks.vue
MyLinks.vue
<script setup lang="ts">
import { document } from '../data/document.js';
import { friend } from '../data/friend.js';
import { tools } from '../data/tools.js';
const props = defineProps<{
type: string;
src: string;
}>();
let linkData = document;
switch (props.src) {
case 'document':
linkData = document;
break;
case 'tools':
linkData = tools;
break;
case 'friend':
linkData = friend;
break;
default:
linkData = document;
}
</script>
<template>
<div class="MyLinks project-panel" v-if="props.type">
<template v-if="linkData.length > 0">
<template v-for="(item, index) in linkData">
<a
class="linkWrapper project"
target="_blank"
:class="`project${index % 9}`"
:href="item.href"
:key="index"
v-if="item.type.indexOf(props.type) > -1"
>
<img class="image" :src="item.cover" />
<div class="name">
{{ item.name }}
</div>
<div class="desc">
{{ item.desc }}
</div>
</a>
</template>
</template>
</div>
</template>
<style lang="scss" scoped>
a.linkWrapper {
text-decoration: none;
}
</style>
src.vuepress\data\friend.ts
export const friend = [
{
name: 'keney',
desc: '博客',
href: 'https://hisnxg.github.io/',
cover: '/navicon/r2coding.png',
type: ['friend'],
},
];
/*
{
name: 'xxxx',
desc: 'xxxx',
href: 'xxxx',
cover: 'xxxx',
type: ['xxx'],
},
*/
ahout.md引入:
---
icon: youlian
---
# 友链
::: tip 欢迎交换友情链接
:::
<MyLinks type="friend" src="friend"/>
---
效果:
参考:https://github.com/mo7cc/BlogSource
自定义链接
src.vuepress\containers\projects.ts
projects.ts:
import yaml from 'js-yaml'
import type Token from 'markdown-it/lib/token.js'
import { withBase } from '../utils'
export interface Project {
icon: string
name: string
desc: string
link: string
}
/**
* 渲染容器列表
* @param tokens
* @param idx
* @returns
*/
export const renderProjects = (tokens: Token[], idx: number) => {
const { nesting: tokenNesting, info: tokenInfo } = tokens[idx]
// 渲染开头的 ':::' 标记
if (tokenNesting === 1) {
let yamlStr = ''
for (let i = idx; i < tokens.length; i++) {
const { type, content, info } = tokens[i]
if (type === 'container_projects_close') break
if (!content) continue
if (type === 'fence' && info === 'yaml') {
// 是代码块类型,并且是yaml代码
yamlStr = content
}
}
if (yamlStr) {
const dataObj = yaml.load(yamlStr) // 将yaml字符串解析成js对象
let dataList: Project[] = []
if (dataObj) {
// 正确解析出数据对象
if (Array.isArray(dataObj)) {
dataList = dataObj
} else {
dataList = dataObj.data
}
}
// 判断是否有数据
if (dataList && dataList.length) {
const getProjectItem = (
project: Project,
index: number,
type?: string
) => {
const isFriends = type === 'friends'
return `
<a class="project project${index % 9}"
href="${withBase(project.link)}"
${isFriends ? '' : 'rel="noopener noreferrer"'}
target="_blank">
<img src="${withBase(project.icon)}"
alt="${project.name}" class="image" />
<div class="name">${project.name}</div>
<div class="desc">${project.desc}</div>
</a>
`
}
const getProjects = (projects: Project[], type?: string) => {
let projectsStr = ''
projects.map((project, index) => {
projectsStr += getProjectItem(project, index, type)
})
return projectsStr
}
const type = tokenInfo.split(' ').pop()
return `<div class="project-panel">${getProjects(dataList, type)}`
}
}
} else {
// 渲染':::' 结尾
return '</div>'
}
return ''
}
使用自定义容器需要在packge.json中引入依赖包
"js-yaml": "^4.1.0",
src.vuepress\utils.ts
增加utils.ts
export const withBase = (path: string) => {
if (!path) return ''
const base = '/'
if (base && path.charAt(0) === '/') {
return base + path.slice(1)
} else {
return path
}
}
src.vuepress\config.ts
在config.ts中插件配置
// VuePress插件配置
// 自定义容器插件
containerPlugin({
type: 'projects',
render: (tokens, idx) => {
return renderProjects(tokens, idx)
}
}),
注意:在config.ts头部引入
>*// VuePress插件配置* >*// 自定义容器插件* >import { containerPlugin } from '@vuepress/plugin-container' >import { renderProjects } from './containers/projects'
通过yaml方式处理,显示会多出代码块,就需要在自定义样式中隐藏掉
src.vuepress\styles\index.scss:
.project-panel {
a {
&:hover {
text-decoration: none;
}
}
.project {
.image {
border-radius: 50%;
}
}
.language-yaml {
display: none;
}
}
在about.md文件中添加
---
toc: false
breadcrumb: false
---
# 关于本站
一个基于 VuePress 的个人博客。
## 服务提供
本站由以下内容提供服务
::: projects
```yaml
- icon: https://image.liubing.me/2023/02/11/7f17f3cf426c3.png
name: Cloudflare
desc: 提供免费的 CDN 服务。
link: https://www.cloudflare.com/
- icon: https://image.liubing.me/2023/02/11/a6de6381e4ae6.png
name: Contabo
desc: VPS 所属供应商。
link: https://contabo.com/
- icon: https://image.liubing.me/2023/02/11/50994f9710667.ico
name: 宝塔 Linux 面板
desc: 用来管理 VPS
link: https://cn.vuejs.org/
- icon: https://vuepress.vuejs.org/hero.png
name: VuePress
desc: 博客驱动引擎。
link: https://vuepress.vuejs.org/zh/
- icon: https://theme-hope.vuejs.press/logo.png
name: VuePress Theme Hope
desc: 本站博客所用主题
link: https://theme-hope.vuejs.press/zh/
- icon: https://image.liubing.me/2023/02/11/a7643dcbbc234.png
name: Buddy
desc: 本站自动化打包构建发布工具。
link: https://buddy.works
- icon: https://image.liubing.me/2023/02/05/834597e9e927e.png
name: Waline
desc: 本站评论所用服务。
link: https://waline.js.org/
```
:::
效果跟上图一样
功能
评论
在主题插件中配置:
src.vuepress\theme.ts
comment: {
provider: "Waline",
serverURL: "自己搭建的walineAPI接口地址",
}
效果:
参考:https://github.com/walinejs/waline
https://plugin-comment2.vuejs.press/zh/
订阅插件
在主题插件中配置:
src.vuepress\theme.ts
//订阅插件SSR
feed: {
// 插件选项
atom: true,
json: true,
rss: true,
},
底部页脚(备案信息)
在src.vuepress\theme.ts配置中
const footer_HTML = `<div class="container-box">
<div class="footer-btn">
<a class="footer-icp" href="https://beian.miit.gov.cn" target="_blank">
<img src="icp.png">
鄂ICP备2021号
</a>
</div>
</div>`
然后启用页脚即可:
// 全局设置页脚信息
footer: footer_HTML,
// 显示页脚
displayFooter: true,
如果只想局部显示,可以在相应的markdown文件头部添加footer
参考:https://theme-hope.vuejs.press/zh/guide/layout/footer.html
注意
如有报错根据提示,引入相应的依赖,一般在package.json中配置。
附件
参考:
vuepress-theme-hope仓库:https://github.com/vuepress-theme-hope/vuepress-theme-hope