本文同步發佈在 Easy Hexo 👨💻javascript
Amber 主題地址css
🎉 基於 Bootstrap + Vue 誕生的一款 Hexo 單頁主題。html
在線演示:前端
將下載的文件解壓並將獲得的文件夾重命名爲 amber
;html5
將這個文件夾放到你的博客根目錄下的 themes
文件夾下。java
若是你熟悉 git
的使用,能夠直接克隆源碼倉庫:jquery
$ cd /path/to/your/blog # 進入你的博客地址
$ cd themes # 進入 `themes` 文件夾
$ git clone --depth 1 https://github.com/Mitscherlich/hexo-theme-amber.git amber # 克隆主題
複製代碼
很是簡單,只須要在博客根目錄下的 _config.yml
文件中將主題選項配置爲 amber
:webpack
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: amber
複製代碼
你能夠在本地運行你的博客,或者從新生成它:git
$ hexo clean && hexo s # 本地運行你的博客
# 或者從新生成它!
$ hexo clean && hexo g && hexo s -s # 這隻會展現生成的靜態文件
# 或者你偏心 `serve` 也行!
$ serve public -p 8080
複製代碼
如今,在你的瀏覽器中訪問 http://localhost:8080,看看有什麼變化?
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
複製代碼
若是你安裝並配置了 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: ...
複製代碼
其中,facebook
、github
、twitter
、weibo
字段有本身的 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
字段。
如今支持的評論系統有:Gitalk、Gitment 和 Valine,在 _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
複製代碼
你可能注意到了,上面的配置中包含有大量 process.env.*
相似的文字,yaml
的語法並不容許從控制檯讀取環境變量,這意味着你必須將上述配置直接書寫在 _config.yml
中,若是你介意在你的公開代碼中暴露這些私有變量,你能夠參考高級玩家 - 安全變量一節來了解如何私有化你的配置。
在頁腳顯示做者的我的連接和相關信息,在 _config.yml
中找到 powered_by
字段,一個可行的例子是:
powered_by:
author: Mitscherlich
link: https://github.com/Mitscherlich
複製代碼
google_analytics:
enable: true
track_id: UA-xxxxxxxxx-x
複製代碼
開啓後,將啓用 Google Analytics 統計服務。
主題集成了 fancybox
用於展現圖片幻燈,若是你不須要,請參考高級玩家 - 開啓/關閉可選功能一節瞭解更多。
主題集成了 dplayer
視頻播放器,若是你不須要,請參考高級玩家 - 開啓/關閉可選功能一節瞭解更多。
主題集成了 katex
用於渲染公式,若是你不須要,請參考高級玩家 - 開啓/關閉可選功能一節瞭解更多。
若是上面的基本配置還知足不了你,那麼歡迎你進入「高玩」的地帶,這裏將告訴你如何更深刻的配置 Amber 主題,並將帶你瞭解如何自定義這個主題。
注意 ⚠️
進入這一小節,我將默認你有必定的html/css/js
基礎,熟悉git
基本命令的使用,而且瞭解過vue.js
開發相關知識。
若是你還沒準備好,我推薦你先去菜鳥教程閱讀 html5 和 git 相關知識後再繼續。
首先你要作的事情,就是從 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
這一步完成後,你的目錄結構應該跟個人同樣:
紅框中的文件你是須要關注的部分你就說哪裏不須要吧
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
:
圖中標註的區域就是引入 jquery
和 fancybox
的代碼,若是不須要,直接註釋掉就好:
完成後,你不能在代碼中繼續使用 fancybox
了,但 fancybox tag
還有效,在哪裏找?
這個文件負責在 hexo
中引入 fancybox tag
,將它備份到一個不一樣於 scripts
的目錄就好:
$ mv scripts/tags/fancybox.js /path/to/backup.d/
複製代碼
DPlayer 是 b站 前端大佬 @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>
複製代碼
一個例子的效果:
若是你不想使用 dplayer
,一樣的,將它備份到一個不一樣的目錄就好:
$ mv scripts/tags/dplayer.js /path/to/backup.d/
複製代碼
另外,若是你不想讓 dplayer
出如今你的構建中,你還須要在這兩個位置移除 dplayer
的引用,別擔憂,雖然接下來涉及到一點點 Vue.js
和 TypeScript
,但你徹底能夠跳過這一步,由於文章中沒有出現 dplayer
的話,它將不會被渲染,天然也不會影響到代碼性能。
首先,你須要在 src/components/partials
下找到 Gallery.vue
這個文件:
而後註釋掉 renderDplayer
:
接下來在 src/pages/articles
下找到 _slug.vue
這個文件:
一樣的,註釋掉 renderDplayer
:
就是這樣!不管如何 dplayer
都不會被加載了!請容許我向 @DIYGod 大佬表達真摯的歉意
主題一樣還集成了 KaTex 用於支持 LaTeX
公式。一樣的,在上述兩個文件中,你很容易就能找到 renderMathInElement
函數,將它們註釋掉,katex
就不會再困擾你了!我很遺憾你放棄了這麼多不錯的功能
注意 ⚠️
在這一小節,我將默認你瞭解 Linux/Unix 命令行的使用,而且已經正確配置了你的 CI/CD。
hexo
使用 .yml
文件書寫配置,這意味着將 OAuth Client Id/Secret
等變量暴露在外,是否會不太安全?若是你跟我有相同的顧慮,那麼我很是推薦你閱讀這一小節,若絕不在乎的話,那好吧,跳過這一小節也影響不大。
在 Github 上託管代碼基本意味着開放,尤爲在須要與人協做時,你的一些似有配置可能被 CI/CD(持續集成/部署)所須要,這意味着未經加密的變量將對互聯網上的每一個人都是可訪問的,但咱們徹底能夠經過技術手段將這點問題解決。一下我將以 TravisCI 爲例,爲 gitalk
和 github pages
配置安全變量。
首先,你須要在 TravisCI 中設置加密的安全變量:
接着,在你的 .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.js
和TypeScript
都有所掌握,而且最好能熟練使用pug
模版語法。固然,這兩個小節的代碼都是通過驗證的,若是你想直接依葫蘆畫瓢也不是不能夠。
不能自定義的主題不是好主題 —— 沃茲基·碩德
看來你的胃口有夠大,主題自帶的小控件已經不能知足你了。那麼就讓咱們開始實踐,編寫一個阿里雲廣告小控件,爲你的博客創收吧!
首先,在 src/components/sidebar/widgets
目錄下新建 Ads.vue
文件:
在 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">×</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") ×
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
中引用你添加的小控件:
別忘了在 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
複製代碼
怎麼樣,是否是很是簡單?最後頁面樣式以下:
不要忘了將頁面組件加入路由,在 src/router.ts
中插入如下內容:
如今,從新編譯你的主題文件,若是沒有任何問題,那麼恭喜你,大功告成!🎊
你們在使用中有什麼問題能夠在評論區留言,我將盡量回復。也歡迎在 Github、知乎、掘金、B站、微博 等關注我,及時獲取個人其餘項目以及相關最新動態。