本篇博客向大家介紹一下Markdown博客系統的搭建。關於搭建博客的具體細節大部分內容參考於:使用hexo+github搭建免費個人博客詳細教程。筆者親自嘗試後,又做了一點補充,應該能夠讓大家很容易地學會如何利用hexo做一個博客系統。首先,給出效果:https://jack13163.github.io/。
目錄
1. markdown簡介
這裏,筆者需要補充如下兩點說明。
1.1 markdown是什麼?
markdown是一種輕量級標記語言,它允許人們使用易讀易寫的純文本格式編寫文檔,然後轉換成格式豐富的 HTML 頁面。筆者的理解是,markdown是一種html代碼生成引擎,爲什麼這樣說?因爲markdown最終要通過markdown解析器解釋爲html代碼。
1.2 爲什麼我們要用markdown做博客系統?
筆者自己爲什麼喜歡markdown呢?主要是它太流行了,太方便了。你不需要了解html的相關知識,就可以生成非常漂亮的界面,這對於一個後端開發者來說是多麼有吸引力。
還有一點,就是它具有非常通用性,因爲這個社區非常活躍,所以大家開發了用markdown寫各種各樣的東西的輪子,例如,我們可以用Markdown寫微信公衆號,將公衆號素材用 Markdown 編輯好後,貼到在線排版工具以後,複製到公衆號編輯器裏即可。有多種頁面主題和代碼主題可選擇。一位大佬維護的工具地址:https://md.mazhuang.org。
傳統的博客系統在搭建時往往比較複雜,除了搭建開發、運行環境之外,還得需要比較高深的相關編程語言,比如說前天用JS、CSS,後臺用Java,數據庫用MySQL等等等等。
除了這些之外,我們還需要了解項目的基礎框架,比如說現今流行的SSM。還需要我們知道開發博客的業務邏輯,比如說我們得展示前臺吧,這就需要前臺的業務邏輯,而我們的前臺數據是通過後臺進行維護的,因而在後臺有需要有一個後臺管理的業務邏輯。同時,在實際的項目開發過程之中,光了解上面的那些是遠遠不夠的,因爲一個系統最起碼得有一個登陸吧,而登錄這方面就需要RBAC權限管理的技術支持,否則誰都能操作後臺,豈不亂了套了,諸如此類的技術還有很多,這我就不一一舉例了。
但是仔細一想的話,雖然搭建一個傳統的博客網站系統其實就已經很複雜了,但是其實有很多的功能並不是我們一定需要的,有時我們僅僅只是用於記錄日誌,用於自己博客信息的展示,其不需要太多的功能,在實現自己基本需求的情況下,簡潔而美觀,使用搭建方便,這纔是我們追求的目標,否則光一個博客系統的搭建就耗費大把的時間,恐怕很多的博客愛好者就會止步於此了。
通過上述描述,我們基本上可以看出Markdown博客系統的優點,那就是基於現成的模版,搭建迅速,使用簡單,並且易於維護。
2. 搭建markdown博客系統
在開始一切之前,你必須已經:
- 有一個github賬號;
- 安裝了node.js、npm,並瞭解相關的基礎知識;
- 安裝了git。
2.1 hexo介紹
Hexo是一個簡單、快速、強大的基於 Github Pages 的博客發佈工具,支持Markdown格式,有衆多優秀插件和主題。
- hexo 可以理解爲是基於node.js製作的一個博客工具,不是我們理解的一個開源的博客系統。
- hexo 正常來說,不需要部署到我們的服務器上,我們的服務器上保存的,其實是基於在hexo通過markdown編寫的文章,然後hexo幫我們生成靜態的html頁面,然後,將生成的html上傳到我們的服務器。簡而言之:hexo是個靜態頁面生成、上傳的工具。
2.2 安裝hexo
打開命令行工具cmd,輸入下述腳本。
npm install -g hexo
2.3 初始化
在電腦的某個地方新建一個文件夾作爲你存放代碼的地方。
cd C:/code/hexo
hexo init
hexo會自動下載一些文件到這個目錄,包括node_modules,目錄結構如下圖:
文件/文件夾 | 說明 |
---|---|
_config.yml | 配置文件,修改博客的基礎配置、模板等; |
public | 生成的靜態文件,這個目錄最終會發布到服務器; |
scaffolds | 一些通用的markdown模板; |
source | 編寫的markdown文件,_drafts草稿文件,_posts發佈的文章; |
themes | 博客的模板。 |
用 npm 安裝話經常出現卡住而導致無法正常安裝,解決辦法就是修改 npm 的安裝源,這裏選擇淘寶 NPM 鏡像。
npm config set registry https://registry.npm.taobao.org
一次解決所有卡頓問題!
2.4 生成html
hexo g # 生成
hexo s # 啓動服務
執行以上命令之後,hexo就會在public文件夾生成相關html文件,這些文件將來都是要提交到github去的:
hexo s
是開啓本地預覽服務,打開瀏覽器訪問 http://localhost:4000 即可看到內容,很多人會碰到瀏覽器一直在轉圈但是就是加載不出來的問題,一般情況下是因爲端口占用的緣故,因爲4000這個端口太常見了,解決端口衝突問題請參考博客。
第一次初始化的時候,hexo已經幫我們寫了一篇名爲 Hello World 的文章:
2.5 修改主題
默認的主題比較醜,替換一個好看點的主題,這裏推薦比較喜歡的2個主題:hexo-theme-jekyll 和 hexo-theme-yilia。
首先,下載主題:
cd C:/code/hexo/
git clone https://github.com/litten/hexo-theme-yilia.git themes/yilia
下載後的主題都在這裏:
修改_config.yml
中的theme: landscape
改爲theme: yilia
,如果直接重新執行hexo g
來重新生成,則會出現模塊缺失的錯誤:
按照提示,我們需要在_config.yml文件中加入下述內容:
# yilia主題所需新增內容
jsonContent:
meta: false
pages: false
posts:
title: true
date: true
path: true
text: false
raw: false
content: false
slug: false
updated: false
comments: false
link: false
permalink: false
excerpt: false
categories: false
tags: true
如果還有其他莫名其妙的問題,可以先執行hexo clean
來清理一下public的內容,然後再來重新生成和發佈。 需要注意的是,_config.yml文件中,冒號後面必須有一個空格,否則可能會出問題。 主題更換後,效果如下圖所示。
2.6 上傳到github
如果你一切都配置好了,發佈上傳很容易,一句hexo d
就搞定,當然關鍵還是你要把所有東西配置好。這裏,假設各位您的github的ssh key
肯定已經配置好了。
2.6.1 創建github倉庫
Github 有兩種形式的page:
- 個人或組織的page:只能存在一個,master 分支,地址爲 xxx.github.io
- 項目page:每個項目可以生成一個,gh-pages 分支,地址爲 xxx.github.io/projectname
這裏筆者採用的是個人版本的page,即倉庫名需要命名爲:github用戶名.github.io。
當創建倉庫名爲其他時:
無法在GitHub Pages中找到URL。
當創建倉庫名爲自己的github用戶名.github.io時:
在GitHub Pages中可以看到URL。
2.6.2 配置部署信息
配置_config.yml
中有關deploy的部分:
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repository: https://github.com/jack13163/jack13163.github.io.git
branch: master
有很多人說這種方式不正確,主要原因是:如果使用https鏈接URL,將默認使用https協議,而無法使用ssh免密登錄功能,每次hexo d提交本地到遠程時還是會需要輸入密碼,很是麻煩,因此,筆者建議這裏直接寫成下面的形式:
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repository: [email protected]:jack13163/jack13163.github.io.git
branch: master
上面的鏈接地址可以通過下面的方式獲得:
2.6.3 安裝hexo的git插件
直接執行hexo d
的話一般會報如下錯誤:
Deployer not found: github 或者 Deployer not found: git
原因是還需要安裝一個插件:
npm install hexo-deployer-git --save
2.6.4 部署hexo
輸入hexo d
就會將本次有改動的代碼全部提交,沒有改動的不會:
就像上一節中提到的,如果您的配置https的方式而不是ssh的方式,每次都需要輸入github的用戶名和密碼。另外,需要確保本地安裝的git配置好了ssh代理,具體可參見:ssh代理實現免密登錄。
因爲這裏容易配置錯誤,所以這裏給出筆者的配置文件。
# Hexo Configuration
## Docs: https://hexo.io/docs/configuration.html
## Source: https://github.com/hexojs/hexo/
# Site
title: Hexo
subtitle:
description:
keywords:
author: John Doe
language: en
timezone:
# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: http://yoursite.com
root: /
permalink: :year/:month/:day/:title/
permalink_defaults:
# Directory
source_dir: source
public_dir: public
tag_dir: tags
archive_dir: archives
category_dir: categories
code_dir: downloads/code
i18n_dir: :lang
skip_render:
# Writing
new_post_name: :title.md # File name of new posts
default_layout: post
titlecase: false # Transform title into titlecase
external_link: true # Open external links in new tab
filename_case: 0
render_drafts: false
post_asset_folder: false
relative_link: false
future: true
highlight:
enable: true
line_number: true
auto_detect: false
tab_replace:
# Home page setting
# path: Root path for your blogs index page. (default = '')
# per_page: Posts displayed per page. (0 = disable pagination)
# order_by: Posts order. (Order by date descending by default)
index_generator:
path: ''
per_page: 10
order_by: -date
# Category & Tag
default_category: uncategorized
category_map:
tag_map:
# Date / Time format
## Hexo uses Moment.js to parse and display date
## You can customize the date format as defined in
## http://momentjs.com/docs/#/displaying/format/
date_format: YYYY-MM-DD
time_format: HH:mm:ss
# Pagination
## Set per_page to 0 to disable pagination
per_page: 10
pagination_dir: page
# Extensions
## Plugins: https://hexo.io/plugins/
## Themes: https://hexo.io/themes/
theme: yilia
# yilia主題所需新增內容
jsonContent:
meta: false
pages: false
posts:
title: true
date: true
path: true
text: false
raw: false
content: false
slug: false
updated: false
comments: false
link: false
permalink: false
excerpt: false
categories: false
tags: true
# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
type: git
repository: [email protected]:jack13163/jack13163.github.io.git
branch: master
2.7 保留CNAME、README.md等文件
提交之後網頁上一看,發現以前其它代碼都沒了,此時不要慌,一些非md文件可以把他們放到source文件夾下,這裏的所有文件都會原樣複製(除了md文件)到public目錄的:
由於hexo默認會把所有md文件都轉換成html,包括README.md,所以需要每次生成之後、上傳之前,都需要手動將README.md複製到public目錄,並刪除README.html。
2.8 常用hexo命令
常見命令
hexo new "postName" #新建文章
hexo new page "pageName" #新建頁面
hexo generate #生成靜態頁面至public目錄
hexo server #開啓預覽訪問端口(默認端口4000,'ctrl + c'關閉server)
hexo deploy #部署到GitHub
hexo help # 查看幫助
hexo version #查看Hexo的版本
縮寫:
hexo n == hexo new
hexo g == hexo generate
hexo s == hexo server
hexo d == hexo deploy
組合命令:
hexo s -g #生成並本地預覽
hexo d -g #生成並上傳
3. 寫博客
定位到hexo根目錄,執行命令:
hexo new 'my-first-blog'
hexo會幫我們在_posts
下生成相關md文件:
我們只需要打開這個文件就可以開始寫博客了,默認生成如下內容:
當然你也可以直接自己新建md文件,用這個命令的好處是幫我們自動生成了時間。
一般完整格式如下:
---
title: postName #文章頁面上的顯示名稱,一般是中文
date: 2013-12-02 15:30:16 #文章生成時間,一般不改,當然也可以任意修改
categories: 默認分類 #分類
tags: [tag1,tag2,tag3] #文章標籤,可空,多標籤請用格式,注意:後面有個空格
description: 附加一段文章摘要,字數最好在140字以內,會出現在meta的description裏面
---
以下是正文
那麼hexo new page 'postName'
命令和hexo new 'postName'
有什麼區別呢?
hexo new page "my-second-blog"
生成如下:
最終部署時生成:hexo\public\my-second-blog\index.html
,但是它不會作爲文章出現在博文目錄。
那麼用什麼工具寫博客呢?這個我還沒去找,以前自己使用editor.md簡單弄了個,大家有好用的hexo寫博客工具可以推薦個。
默認情況下,生成的博文目錄會顯示全部的文章內容,如何設置文章摘要的長度呢?
答案是在合適的位置加上<!--more-->
即可,例如:
# 前言
使用github pages服務搭建博客的好處有:
1. 全是靜態文件,訪問速度快;
2. 免費方便,不用花一分錢就可以搭建一個自由的個人博客,不需要服務器不需要後臺;
3. 可以隨意綁定自己的域名,不仔細看的話根本看不出來你的網站是基於github的;
<!--more-->
4. 數據絕對安全,基於github的版本管理,想恢復到哪個歷史版本都行;
5. 博客內容可以輕鬆打包、轉移、發佈到其它平臺;
6. 等等;
最終效果:
4. 添加Gitalk評論系統
Gitalk 是一個基於 GitHub Issue 和 Preact 開發的評論插件。支持在前端直接引入,不需要任何後端代碼,可以在頁面進行登錄、查看、評論、點贊等操作,同時有完整的 Markdown / GFM 和代碼高亮支持,尤爲適合各種基於 GitHub Pages 的靜態博客或項目頁面。缺點是隻能使用 GitHub 賬號進行評論。
本部分內容參考自:Git博客Hexo+Yilia主題設置gitalk評論功能,在此向大佬們表示感謝。
4.1 註冊 OAuth Application
在 GitHub 上註冊一個新的 OAuth Application。
注意,一定要是 OAuth Application,不是Github Application,筆者曾經不注意搞錯了,導致配置出錯,初始化評論。
前面3項內容都可以隨意填寫,但要確保最後一個 Authorization callback URL
是你的網站域名(比如http://www.wangxingfeng.com)。成功註冊之後,你將會得到一個 client ID 和一個 client secret,這個將被用於之後的實例化 Gitment。
4.2 配置Gitalk
在yilia主題下的_config.yml文件中配置代碼,注意冒號後面都有一個空格:
#6、配置gitalk
gitalk:
enable: true
client_id: OAuth application註冊成功獲得
client_secret: OAuth application註冊成功獲得
repo: 存儲博客評論的倉庫地址,可以是存儲博客的倉庫
owner: github賬戶名
admin: github賬戶名
下載gitalk項目,點這裏
拷貝gitalk/dist/目錄下的gitalk.css和gitalk.min.js到yilia/source/lib/gitalk目錄(沒有的話新建文件)
在yilia主題下的>>layout>>_partial>>post文件夾下新建文件gitalk.ejs,複製代碼,這裏筆者增加了md5方法,確保id長度不超過50:
<div class="gitalk" style="margin:30px">
<div id="gitalk-container"></div>
<script type="text/javascript">
function md5(md5str) {
var createMD5String = function(string) {
var x = Array()
var k, AA, BB, CC, DD, a, b, c, d
var S11 = 7,
S12 = 12,
S13 = 17,
S14 = 22
var S21 = 5,
S22 = 9,
S23 = 14,
S24 = 20
var S31 = 4,
S32 = 11,
S33 = 16,
S34 = 23
var S41 = 6,
S42 = 10,
S43 = 15,
S44 = 21
string = uTF8Encode(string)
x = convertToWordArray(string)
a = 0x67452301
b = 0xEFCDAB89
c = 0x98BADCFE
d = 0x10325476
for (k = 0; k < x.length; k += 16) {
AA = a
BB = b
CC = c
DD = d
a = FF(a, b, c, d, x[k + 0], S11, 0xD76AA478)
d = FF(d, a, b, c, x[k + 1], S12, 0xE8C7B756)
c = FF(c, d, a, b, x[k + 2], S13, 0x242070DB)
b = FF(b, c, d, a, x[k + 3], S14, 0xC1BDCEEE)
a = FF(a, b, c, d, x[k + 4], S11, 0xF57C0FAF)
d = FF(d, a, b, c, x[k + 5], S12, 0x4787C62A)
c = FF(c, d, a, b, x[k + 6], S13, 0xA8304613)
b = FF(b, c, d, a, x[k + 7], S14, 0xFD469501)
a = FF(a, b, c, d, x[k + 8], S11, 0x698098D8)
d = FF(d, a, b, c, x[k + 9], S12, 0x8B44F7AF)
c = FF(c, d, a, b, x[k + 10], S13, 0xFFFF5BB1)
b = FF(b, c, d, a, x[k + 11], S14, 0x895CD7BE)
a = FF(a, b, c, d, x[k + 12], S11, 0x6B901122)
d = FF(d, a, b, c, x[k + 13], S12, 0xFD987193)
c = FF(c, d, a, b, x[k + 14], S13, 0xA679438E)
b = FF(b, c, d, a, x[k + 15], S14, 0x49B40821)
a = GG(a, b, c, d, x[k + 1], S21, 0xF61E2562)
d = GG(d, a, b, c, x[k + 6], S22, 0xC040B340)
c = GG(c, d, a, b, x[k + 11], S23, 0x265E5A51)
b = GG(b, c, d, a, x[k + 0], S24, 0xE9B6C7AA)
a = GG(a, b, c, d, x[k + 5], S21, 0xD62F105D)
d = GG(d, a, b, c, x[k + 10], S22, 0x2441453)
c = GG(c, d, a, b, x[k + 15], S23, 0xD8A1E681)
b = GG(b, c, d, a, x[k + 4], S24, 0xE7D3FBC8)
a = GG(a, b, c, d, x[k + 9], S21, 0x21E1CDE6)
d = GG(d, a, b, c, x[k + 14], S22, 0xC33707D6)
c = GG(c, d, a, b, x[k + 3], S23, 0xF4D50D87)
b = GG(b, c, d, a, x[k + 8], S24, 0x455A14ED)
a = GG(a, b, c, d, x[k + 13], S21, 0xA9E3E905)
d = GG(d, a, b, c, x[k + 2], S22, 0xFCEFA3F8)
c = GG(c, d, a, b, x[k + 7], S23, 0x676F02D9)
b = GG(b, c, d, a, x[k + 12], S24, 0x8D2A4C8A)
a = HH(a, b, c, d, x[k + 5], S31, 0xFFFA3942)
d = HH(d, a, b, c, x[k + 8], S32, 0x8771F681)
c = HH(c, d, a, b, x[k + 11], S33, 0x6D9D6122)
b = HH(b, c, d, a, x[k + 14], S34, 0xFDE5380C)
a = HH(a, b, c, d, x[k + 1], S31, 0xA4BEEA44)
d = HH(d, a, b, c, x[k + 4], S32, 0x4BDECFA9)
c = HH(c, d, a, b, x[k + 7], S33, 0xF6BB4B60)
b = HH(b, c, d, a, x[k + 10], S34, 0xBEBFBC70)
a = HH(a, b, c, d, x[k + 13], S31, 0x289B7EC6)
d = HH(d, a, b, c, x[k + 0], S32, 0xEAA127FA)
c = HH(c, d, a, b, x[k + 3], S33, 0xD4EF3085)
b = HH(b, c, d, a, x[k + 6], S34, 0x4881D05)
a = HH(a, b, c, d, x[k + 9], S31, 0xD9D4D039)
d = HH(d, a, b, c, x[k + 12], S32, 0xE6DB99E5)
c = HH(c, d, a, b, x[k + 15], S33, 0x1FA27CF8)
b = HH(b, c, d, a, x[k + 2], S34, 0xC4AC5665)
a = II(a, b, c, d, x[k + 0], S41, 0xF4292244)
d = II(d, a, b, c, x[k + 7], S42, 0x432AFF97)
c = II(c, d, a, b, x[k + 14], S43, 0xAB9423A7)
b = II(b, c, d, a, x[k + 5], S44, 0xFC93A039)
a = II(a, b, c, d, x[k + 12], S41, 0x655B59C3)
d = II(d, a, b, c, x[k + 3], S42, 0x8F0CCC92)
c = II(c, d, a, b, x[k + 10], S43, 0xFFEFF47D)
b = II(b, c, d, a, x[k + 1], S44, 0x85845DD1)
a = II(a, b, c, d, x[k + 8], S41, 0x6FA87E4F)
d = II(d, a, b, c, x[k + 15], S42, 0xFE2CE6E0)
c = II(c, d, a, b, x[k + 6], S43, 0xA3014314)
b = II(b, c, d, a, x[k + 13], S44, 0x4E0811A1)
a = II(a, b, c, d, x[k + 4], S41, 0xF7537E82)
d = II(d, a, b, c, x[k + 11], S42, 0xBD3AF235)
c = II(c, d, a, b, x[k + 2], S43, 0x2AD7D2BB)
b = II(b, c, d, a, x[k + 9], S44, 0xEB86D391)
a = addUnsigned(a, AA)
b = addUnsigned(b, BB)
c = addUnsigned(c, CC)
d = addUnsigned(d, DD)
}
var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d)
return tempValue.toLowerCase()
}
var rotateLeft = function(lValue, iShiftBits) {
return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits))
}
var addUnsigned = function(lX, lY) {
var lX4, lY4, lX8, lY8, lResult
lX8 = (lX & 0x80000000)
lY8 = (lY & 0x80000000)
lX4 = (lX & 0x40000000)
lY4 = (lY & 0x40000000)
lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF)
if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8)
if (lX4 | lY4) {
if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8)
else return (lResult ^ 0x40000000 ^ lX8 ^ lY8)
} else {
return (lResult ^ lX8 ^ lY8)
}
}
var F = function(x, y, z) {
return (x & y) | ((~x) & z)
}
var G = function(x, y, z) {
return (x & z) | (y & (~z))
}
var H = function(x, y, z) {
return (x ^ y ^ z)
}
var I = function(x, y, z) {
return (y ^ (x | (~z)))
}
var FF = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac))
return addUnsigned(rotateLeft(a, s), b)
}
var GG = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac))
return addUnsigned(rotateLeft(a, s), b)
}
var HH = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac))
return addUnsigned(rotateLeft(a, s), b)
}
var II = function(a, b, c, d, x, s, ac) {
a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac))
return addUnsigned(rotateLeft(a, s), b)
}
var convertToWordArray = function(string) {
var lWordCount
var lMessageLength = string.length
var lNumberOfWordsTempOne = lMessageLength + 8
var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64
var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16
var lWordArray = Array(lNumberOfWords - 1)
var lBytePosition = 0
var lByteCount = 0
while (lByteCount < lMessageLength) {
lWordCount = (lByteCount - (lByteCount % 4)) / 4
lBytePosition = (lByteCount % 4) * 8
lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition))
lByteCount++
}
lWordCount = (lByteCount - (lByteCount % 4)) / 4
lBytePosition = (lByteCount % 4) * 8
lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition)
lWordArray[lNumberOfWords - 2] = lMessageLength << 3
lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29
return lWordArray
}
var wordToHex = function(lValue) {
var WordToHexValue = '',
WordToHexValueTemp = '',
lByte, lCount
for (lCount = 0; lCount <= 3; lCount++) {
lByte = (lValue >>> (lCount * 8)) & 255
WordToHexValueTemp = '0' + lByte.toString(16)
WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2)
}
return WordToHexValue
}
var uTF8Encode = function(string) {
string = string.toString().replace(/\x0d\x0a/g, '\x0a')
var output = ''
for (var n = 0; n < string.length; n++) {
var c = string.charCodeAt(n)
if (c < 128) {
output += String.fromCharCode(c)
} else if ((c > 127) && (c < 2048)) {
output += String.fromCharCode((c >> 6) | 192)
output += String.fromCharCode((c & 63) | 128)
} else {
output += String.fromCharCode((c >> 12) | 224)
output += String.fromCharCode(((c >> 6) & 63) | 128)
output += String.fromCharCode((c & 63) | 128)
}
}
return output
}
return createMD5String(md5str)
}
const gitalk = new Gitalk({
clientID: '<%=theme.gitalk.client_id%>',
clientSecret: '<%=theme.gitalk.client_secret%>',
repo: '<%=theme.gitalk.repo%>',
owner: '<%=theme.gitalk.owner%>',
admin: ['<%=theme.gitalk.admin%>'],
id: md5(location.pathname), // Ensure uniqueness and length less than 50
distractionFreeMode: false // Facebook-like distraction free mode
})
gitalk.render('gitalk-container')
</script>
</div>
在yilia主題下的>>layout>>_partial>>article.ejs文件中添加代碼:
<% if (!index && theme.gitalk.enable && post.comments){ %>
<%- partial('post/gitalk', {
key: post.slug,
title: post.title,
url: config.url+url_for(post.path)
}) %>
<% } %>
在yilia主題下的layout>>_partial>>head.ejs文件中添加代碼:
<% if (theme.gitalk.enable){ %>
<link rel="stylesheet" href="/lib/gitalk/gitalk.css">
<script src="/lib/gitalk/gitalk.min.js"></script>
<% } %>
您將會在對應的倉庫下的Issues選項卡中看到下述內容: