Hexo 主題 Amber 開發與使用指南

Mitscherlich發表於2018-12-20

本文同步釋出在 Easy Hexo ?‍?

Amber 主題地址

? 基於 Bootstrap + Vue 誕生的一款 Hexo 單頁主題。

Amber 主題演示

amber

線上演示:

Mitscherlich's Blog

下載 Amber 主題

  1. 進入 Github,直接下載預設分支;

amber

  1. 將下載的檔案解壓並將得到的資料夾重新命名為 amber

  2. 將這個資料夾放到你的部落格根目錄下的 themes 資料夾下。

amber

如果你熟悉 git 的使用,可以直接克隆原始碼倉庫:

$ cd /path/to/your/blog # 進入你的部落格地址
$ cd themes             # 進入 `themes` 資料夾
$ git clone --depth 1 https://github.com/Mitscherlich/hexo-theme-amber.git amber # 克隆主題
複製程式碼

啟用 Amber 主題

非常簡單,只需要在部落格根目錄下的 _config.yml 檔案中將主題選項配置為 amber:

# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: amber
複製程式碼

你可以在本地執行你的部落格,或者重新生成它:

$ hexo clean && hexo s # 本地執行你的部落格
# 或者重新生成它!
$ hexo clean && hexo g && hexo s -s # 這隻會展示生成的靜態檔案
# 或者你偏愛 `serve` 也行!
$ serve public -p 8080
複製程式碼

現在,在你的瀏覽器中訪問 http://localhost:8080,看看有什麼變化?

配置 Amber 主題

TIP
在這一小節,沒有特殊說明的情況下,_config.yml 指代的是 themes/amber 目錄下的 _config.yml 檔案,<root>/_config.yml 代指的是部落格根目錄下的 _config.yml 檔案。

通過編輯 themes/amber 目錄下的 _config.yml 檔案來配置你的主題。以下所有的例子中的程式碼都可以在我的部落格中找到。

基本配置

導航條

找到 _config.yml 中的 menu 欄位,你可以很方便的定製你的導航條:

menu:
  home: /                 # 首頁
  archives: /archives     # 歸檔頁
  # 補充你的自定義選單
  # 末尾的 `/index.html` 視情況可以省略
  # 示例:
  # [O]  About: /about/index (如果你的頁面是 `sources/<dir>/index.md` 的形式)
  # [O]  About: /about       (如果你的頁面是 `sources/page.md` 的形式)
複製程式碼

由於這個主題是使用 vue 進行開發的,hexo 提供的 layout 功能沒法用了,這可能為你定製自己想要的頁面帶來了一些麻煩;但好訊息是,直接在 md 檔案中書寫 html 也是可以接受的,但如果你需要用到部落格資料或者自定義更復雜的功能,請參考高階玩家 - 自定義頁面這一小節,有兩個詳細的示例供你參考。

一個可行的例子是:

menu:
  Essay: /related/category/essay  # 找到所有分類為 essay 的文章
  Tech: /related/category/tech    # 找到所有分類為 tech 的文章
  Note: /related/category/note    # 找到所有分類為 note 的文章
  ACG: /related/tag/ACG           # 找到所有標籤含有 ACG 的文章
  Node.js: /related/tag/Node-js   # 找到所有標籤含有 Node.js/Node-js 的文章
  Python: /related/tag/Python     # 找到所有標籤含有 Python 的文章
  Archives: /archives             # 歸檔頁面
  pages:                          # 不支援二級選單,層級導航將被展平
    - text: Projects              # 一個自定義頁面
      link: /projects
    - text: Messages              # 另一個自定義頁面
      link: /messages
    - text: Donate                # 又一個自定義頁面
      link: /donate
    - text: Profile               # 還是自定義頁面
      link: /profile
複製程式碼

RSS/Atom 訂閱連結

如果你安裝並配置了 hexo-generator-feed,你可以開啟這一項為你的部落格新增 RSS 訂閱。在 _config.yml 裡找到 rss 欄位,一個可行的例子是:

rss:
  enable: true
  path: /api/atom.xml
複製程式碼

path 是你的 hexo-generator-feed 生成的檔案能被訪問到的絕對路徑,如果你的部落格在二級路徑下,請在前面補充你的二級路徑,因為這裡的跳轉不會被 vue-router 攔截到。

社交連結

這個配置影響邊欄中的 Elsewhere (友言) 小控制元件。在 _config.yml 中找到 social 欄位,它接受以下幾項配置:

social:
  # facebook: ...
  # github: ...
  # twitter: ...
  # weibo: ...
  websites:
    # - text: ...
    #   link: ...
複製程式碼

其中,facebookgithubtwitterweibo 欄位有自己的 font-awesome 小圖示,而 websites 欄位可以作為友鏈使用,text 欄位表示你想要顯示的文字內容,

一個可行的例子是:

social:
  github: https://github.com/Mitscherlich
  weibo: https://weibo.com/Mitscherlich
  websites:
    - text: YUOSC
      link: https://yuosc.club
    - text: EasyHexo
      link: https://easyhexo.github.io/Easy-Hexo/
複製程式碼

側邊欄

側邊欄中簡單的配置都放在這裡。在 _config.yml 中找到 sidebar 欄位,它接受以下幾項配置:

## Sidebar
sidebar:
  leaf: To descript your blog. *Markdown* supported.
  github: Mitscherlich
複製程式碼

其中,leaf 影響小控制元件 Leaf 的內容,可以使用 markdown 語法書寫,文字內容將被渲染後顯示在首頁上; github 條目是可選的,用來展示部落格作者的 Github 名片,如果留空,預設將會使用 <root>/_config.yml 中的 author 欄位。

評論系統

現在支援的評論系統有:GitalkGitmentValine,在 _config.yml 中找到 comments 欄位,它接受以下幾項配置:

comments:
  enable: true
  engine: gitalk|gitment|valine # 請只保留你需要啟用的評論系統!
複製程式碼

然後,為你的評論系統書寫配置,注意 ⚠️,請務必縮排在 comments 欄位下,配置將配自動載入:

例如,gitalk 接受以下幾項配置:

comments:
  enable: true
  engine: gitalk
  gitalk:
    # 必須: github application client id
    clientID: process.env.clientId
    # 必須: github application client secret
    clientSecret: process.env.clientSecret
    repo: process.env.repo    # 必須: github repo
    owner: process.env.author # 必須: github repo owner
    admin:
      - process.env.author  # 必須: gitHub repo owner and collaborators
                            # only these guys can initialize github issues
複製程式碼

或者 gitment:

comments:
  enable: true
  engine: gitalk
  gitment:
    repo: process.env.repo    # 必須: github repo
    owner: process.env.author # 必須: github repo owner
    oauth:
      # 必須: github application client id
      client_id: process.env.clientId
      # 必須: github application client secret
      client_secret: process.env.clientSecret
複製程式碼

或者 valine:

comments:
  enable: true
  engine: gitalk
  valine:
    # 必須: leancloud app id
    appId: process.env.appId
    # 必須: leancloud app key
    appKey: process.env.appKey
複製程式碼

關於 valine 的使用,請參考其官網教程,正確填寫 Leancloud 相關配置。

你可能注意到了,上面的配置中包含有大量 process.env.* 類似的文字,yaml 的語法並不允許從控制檯讀取環境變數,這意味著你必須將上述配置直接書寫在 _config.yml 中,如果你介意在你的公開程式碼中暴露這些私有變數,你可以參考高階玩家 - 安全變數一節來了解如何私有化你的配置。

頁尾資訊

在頁尾顯示作者的個人連結和相關資訊,在 _config.yml 中找到 powered_by 欄位,一個可行的例子是:

powered_by:
  author: Mitscherlich
  link: https://github.com/Mitscherlich
複製程式碼

Google Analytics

google_analytics:
  enable: true
  track_id: UA-xxxxxxxxx-x
複製程式碼

開啟後,將啟用 Google Analytics 統計服務。

沒有暴露配置的外掛

fancybox

主題整合了 fancybox 用於展示圖片幻燈,如果你不需要,請參考高階玩家 - 開啟/關閉可選功能一節瞭解更多。

dplayer

主題整合了 dplayer 視訊播放器,如果你不需要,請參考高階玩家 - 開啟/關閉可選功能一節瞭解更多。

katex

主題整合了 katex 用於渲染公式,如果你不需要,請參考高階玩家 - 開啟/關閉可選功能一節瞭解更多。

高階玩家

如果上面的基本配置還滿足不了你,那麼歡迎你進入“高玩”的地帶,這裡將告訴你如何更深入的配置 Amber 主題,並將帶你瞭解如何自定義這個主題。

注意 ⚠️
進入這一小節,我將預設你有一定的 html/css/js 基礎,熟悉 git 基本命令的使用,並且瞭解過 vue.js 開發相關知識。
如果你還沒準備好,我推薦你先去菜鳥教程閱讀 html5git 相關知識後再繼續。

首先你要做的事情,就是從 develop 分支重新拉取主題程式碼,預編譯的程式碼已經派不上用場了:

$ cd /path/to/your/blog
$ git clone -b develop --depth=1 https://github.com/Mitscherlich/hexo-theme-amber.git themes/amber
# 或者你不想覆蓋已有主題,可以拉取到 themes/amber-dev 目錄下
$ cd themes/amber # 或者 themes/amber-dev,視你上一步的結果而定
$ yarn install    # npm 也可以!但推薦使用 yarn!
複製程式碼

如果你將主題下載到了 themes/amber-dev 目錄下,你還需要在 <root>/_config.yml 中將 theme 欄位修改為 amber-dev

這一步完成後,你的目錄結構應該跟我的一樣:

amber

紅框中的檔案你是需要關注的部分你就說哪裡不需要吧

開啟/關閉可選功能

fancybox

fancybox 是一個 jquery 外掛,你可以通過這樣的形式在 md 檔案中快速插入 fancybox

{% fancybox slug /path/to/image [/path/to/thumbnail] [class] [title] %}
複製程式碼

例如:

{% fancybox esayhexo /assets/easyhexo/amber/preview.png Amber 主題示例圖 %}
複製程式碼

渲染得到的結果:

<p>
  <a data-fancybox="gallery" href="/assets/easyhexo/amber/preview.png" title="Amber 主題示例圖">
    <img class="" src="/assets/easyhexo/amber/preview.png" alt="Amber 主題示例圖">
  </a>
</p>
複製程式碼

如果你用不到 fancybox,並且想要提升載入速度,你可選擇僅用它。fancybox 並不沒有被整合在 vue 工程中,而是直接在 vue 模版中被引用。在 public 目錄下找到 index.html

amber

圖中標註的區域就是引入 jqueryfancybox 的程式碼,如果不需要,直接註釋掉就好:

amber

完成後,你不能在程式碼中繼續使用 fancybox 了,但 fancybox tag 還有效,在哪裡找?

amber

這個檔案負責在 hexo 中引入 fancybox tag,將它備份到一個不同於 scripts 的目錄就好:

$ mv scripts/tags/fancybox.js /path/to/backup.d/
複製程式碼

dplayer

DPlayerb站 前端大佬 @DIYGod 的開源視訊播放器(現同樣用於 b站 播放頁),支援懶載入、縮圖、彈幕等功能,你可以通過這樣的形式在 md 檔案中使用它:

{% dplayer key=value ... %}
複製程式碼

示例:

{% dplayer src=/assets/easyhexo/how-to-use-amber/install.mp4 %}
複製程式碼

渲染出來的結果:

<!-- dplayer counter starts with 0 -->
<div id="dplayer0" class="dplayer hexo-tag-dplayer-mark" style="margin-bottom: 20px;">
  <script>
    (function(){let player = {/* configs */};window.dplayers||(window.dplayers=[]);window.dplayers.push(player);})();
  </script>
</div>
複製程式碼

一個例子的效果:

amber

如果你不想使用 dplayer,同樣的,將它備份到一個不同的目錄就好:

$ mv scripts/tags/dplayer.js /path/to/backup.d/
複製程式碼

另外,如果你不想讓 dplayer 出現在你的構建中,你還需要在這兩個位置移除 dplayer 的引用,別擔心,雖然接下來涉及到一點點 Vue.jsTypeScript,但你完全可以跳過這一步,因為文章中沒有出現 dplayer 的話,它將不會被渲染,自然也不會影響到程式碼效能。

首先,你需要在 src/components/partials 下找到 Gallery.vue 這個檔案:

amber

然後註釋掉 renderDplayer

amber

接下來在 src/pages/articles 下找到 _slug.vue 這個檔案:

amber

同樣的,註釋掉 renderDplayer

amber

就是這樣!無論如何 dplayer 都不會被載入了!請允許我向 @DIYGod 大佬表達真摯的歉意

katex

主題同樣還整合了 KaTex 用於支援 LaTeX 公式。同樣的,在上述兩個檔案中,你很容易就能找到 renderMathInElement 函式,將它們註釋掉,katex 就不會再困擾你了!我很遺憾你放棄了這麼多不錯的功能

安全變數

注意 ⚠️
在這一小節,我將預設你瞭解 Linux/Unix 命令列的使用,並且已經正確配置了你的 CI/CD

hexo 使用 .yml 檔案書寫配置,這意味著將 OAuth Client Id/Secret 等變數暴露在外,是否會不太安全?如果你跟我有相同的顧慮,那麼我非常推薦你閱讀這一小節,若毫不在意的話,那好吧,跳過這一小節也影響不大。

Github 上託管程式碼基本意味著開放,尤其在需要與人協作時,你的一些似有配置可能被 CI/CD(持續整合/部署)所需要,這意味著未經加密的變數將對網際網路上的每個人都是可訪問的,但我們完全可以通過技術手段將這點問題解決。一下我將以 TravisCI 為例,為 gitalkgithub pages 配置安全變數。

首先,你需要在 TravisCI 中設定加密的安全變數:

amber

接著,在你的 .travis.yml 中新增以下內容:

before_script:
  - cd themes/amber # 要修改的是 `themes/amber` 下的 `_config.yml`,不是 `<root>/_config.yml`
  - sed -i "s|process.env.clientId|$OAUTH_CLIENT_ID|g" _config.yml
  - sed -i "s|process.env.clientSecret|$OAUTH_CLIENT_KEY|g" _config.yml
  - cd - # 回到 `<root>`
複製程式碼

如果你想要成功的構建釋出到 github pages,再新增以下內容:

deploy:
  provider: pages
  local-dir: public
  skip_cleanup: true
  keep-history: true
  committer-from-gh: true
  github-token: $GITHUB_TOKEN
複製程式碼

Ok! 這樣就完成了!

不過仍要指出,這樣配置的“安全變數”仍然是安全變數,只是在 CI/CD 中對外不可見而已,最後仍然會出現在你的前端構建中,即使例如本主題使用了 webpack 等構建工具也無濟於事有心之人仍然可以找出你“加密”的這些變數。最後,送給大家 Leancloud 的忠告:

AppKey 是客戶端中使用的 Key,理論上客戶端中所有請求都不應被信任,預設應認為 AppKey 是洩露的 —— Leancloud

自定義邊欄

注意 ⚠️
接下來兩個小節是這篇教程中最“高階”的部分,需要你對 Vue.jsTypeScript 都有所掌握,並且最好能熟練使用 pug 模版語法。當然,這兩個小節的程式碼都是經過驗證的,如果你想直接依葫蘆畫瓢也不是不可以。

不能自定義的主題不是好主題 —— 沃茲基·碩德

看來你的胃口有夠大,主題自帶的小控制元件已經不能滿足你了。那麼就讓我們開始實踐,編寫一個阿里雲廣告小控制元件,為你的部落格創收吧!

首先,在 src/components/sidebar/widgets 目錄下新建 Ads.vue 檔案:

amber

Ads.vue 檔案書寫頁面框架:

<template>
  <p>placeholder</p>
</template>

<script lang="ts">
</script>

<style lang="stylus" scoped>
</style>
複製程式碼

接著,在 template 裡面書寫以下內容:

<transition name="fade">
  <!-- b-carousel 是 bootstrap-vue 的內建元件 -->
  <b-carousel class="ads mb-4" indicators v-model="slide">
    <b-link v-for="({ text, image, link }, i) in ads" :key="`ads-${i}`" :href="link" target="_blank">
      <b-carousel-slide :img-src="image" style="height: 160px;"/>
    </b-link>
    <span class="dismiss cursor-pointer" @click="dismissAds">&times;</span>
    <span class="tips">{{ $t('ads') }}</span>
  </b-carousel>
</transition>
複製程式碼

如果你熟悉 pug,這樣寫更簡潔:

<template lang="pug">
  transition(name="fade")
    b-carousel.ads.mb-4(indicators, :interval="interval", v-model="slide", v-if="!dismiss")
      b-link(v-for="({ text, image, link }, i) in ads", :key="`ads-${i}`", :href="link", target="_blank")
        b-carousel-slide(:img-src="image", style="height: 160px;")
      span.dismiss.cursor-pointer(@click="dismissAds") &times;
      span.tips {{ $t('ads') }}
</template>
複製程式碼

後面的模版程式碼將全部用 pug 書寫

script 部分中新增以下內容:

import { Vue, Component, Prop } from 'vue-property-decorator';
import store from 'store';

@Component({ name: 'Ads' })
export default class Ads extends Vue {
  private slide: number = 0;
  private dismiss: boolean = false;

  @Prop({ type: Number, default: 10 * 1000 })
  private interval?: number;

  @Prop({ default: [] })
  private ads?: Array<{ text: string; image: string; link: string; }>;

  private beforeMount() {
    const now = Date.now();
    const last = store.get('ads_expire_date', now);
    if (now - last > 1) {
      store.set('dismiss_ads', false);
    }
    this.dismiss = store.get('dismiss_ads', false);
  }

  private dismissAds(e: any) {
    e.preventDefault();
    this.dismiss = true;
    store.set('dismiss_ads', true);
    const now = Date.now();
    const expired = 24 * 60 * 3600; // 1 day
    store.set('ads_expire_date', now + expired);
  }
}
複製程式碼

樣式向來複雜,這裡照抄就好:

@import "~@/common/stylus/variables"

.ads
  &:hover
    .dismiss
      display block
  span.dismiss
    z-index 99
    font-size 28px
    display none
    position absolute
    right .5rem
    top -0.5rem
    color color-muted
    &:hover
      color color-light
  span.tips
    position absolute
    padding .1rem .25rem
    right .5rem
    bottom .5rem
    color color-light
    border 1px solid color-light
    border-radius .25rem
    font-size 14px
複製程式碼

在上一級目錄中的 Sidebar.vue 中引用你新增的小控制元件:

amber

別忘了在 Sidebar 上新增 getter

class Sidebar extends Vue {
  ...
  private get ads() {
    // `data` 就是 `sources/_data` 下的檔案內容,和 `hexo` 資料目錄用法一致
    return this.$store.state.data.ads || [];
  }
  ...
}
複製程式碼

自定義頁面

看完了自定義小控制元件,來試試更復雜的功能:自定義頁面吧!在這個例子中,我將為大家展示如何編寫一個獨立頁面,用於展示你的專案作品。

首先,在 src/pages 目錄下新增 Projects.vue 檔案並書寫大致框架:

<template lang="pug">
  p placeholder
</template>

<script lang="ts">
</script>

<style lang="stylus" scoped>
</style>
複製程式碼

template 中插入以下內容:

.projects
  transition(name="fade", mode="out-in")
    b-card-group.mb-4(columns, v-if="projects.length")
      b-card(:img-src="preview", :key="`project-${i}`", v-for="({ name, description, link, preview }, i) in projects")
        h4 {{ name }}
        p {{ description }}
        footer(slot="footer"): b-link.text-muted(:href="link")
          fa-icon.mr-2.text-success(:icon="['far', 'thumbs-up']")
          small {{ $t('visit') }}
    b-row.justify-content-center(v-else): loading.my-5(style="margin: 0 auto;")
複製程式碼

script 中插入以下內容:

import { Vue, Component } from 'vue-property-decorator';

@Component({ name: 'Projects' })
export default class Projects extends Vue {
  private get projects() {
    return this.$store.state.data.projects || [];
  }
}
複製程式碼

style 中插入以下內容:

.projects
  .card
    .card-img
      border-bottom-right-radius 0!important
      border-bottom-left-radius 0!important
複製程式碼

怎麼樣,是不是非常簡單?最後頁面樣式如下:

amber

不要忘了將頁面元件加入路由,在 src/router.ts 中插入以下內容:

amber

現在,重新編譯你的主題檔案,如果沒有任何問題,那麼恭喜你,大功告成!?

寫在最後

大家在使用中有什麼問題可以在評論區留言,我將盡可能回覆。也歡迎在 Github知乎掘金B站微博 等關注我,及時獲取我的其他專案以及相關最新動態。

相關文章