banner
keney

keney

remain optimistic
twitter

vuepress-theme-hope主題擴展

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://nnxx.me/","desc":"基於hexo-matery搭建的博客","icon":"https://pic.imgdb.cn/item/640d9bf1f144a010073218ac.png"}'></NavCard>

效果如下圖:

image-20230409171516473

鏈接#

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

---

效果:

image-20230409164014787

參考: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接口地址",
    }

效果:

image-20230409173318195

參考: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

vuepress-theme-hope 倉庫:https://github.com/vuepress-theme-hope/vuepress-theme-hope

基于VuePress的个人博客,记录日常开发问题。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。