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

カスタムコンテナを使用するには、package.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テーマ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 ファイルの先頭にフッターを追加します

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

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。