1 前言
本来对自己之前基于hugo的博客感觉挺满意的,直到某一天手贱点开了一篇关于如何把豆瓣读书等模块加入到博客中的文章,于是羡慕之情油然而生。
在网上搜了一下发现是有个大佬写了个基于Hexo的小插件,顿时心灰意冷,因为当时从零基础开始折腾博客花费了太多时间,到最后也没完全弄懂。
一边纠结着到底要不要换成Hexo一边看着程序员大佬们的博客,忽然眼前一亮发现了一款比较好的主题Fluid ,Material Design 风格而且功能比较多文档描述的很详细,大呼为什么没有早点发现这么好的东西,于是开始了为期3天的折腾之旅。
折腾到一半发现这个hexo-theme-fluid主题主页两边比较空,想改看了下源码却不知道从何开始下手;再加上不知道这个主题和hexo-douban是否兼容,又有点犹豫了,后悔花了时间却啥也没干成之余,无意间又发现了一款Material Design的主题 hexo-theme-matery!功能更加全面而且也很好看,阅读时目录、上下一篇等小细节也做的不错,于是义无反顾地选择了它。
用户体验还是很不错的,折腾完后我非常高兴。总算可以不再去弄这些华丽胡哨的,专心去读书写作了(其实都是借口)。
下面简单记录一下我从零开始建立这个基于Hexo的博客的过程,由于有很多这方面的文章,我只记录一些比较细节的东西,防止自己再次踩坑
2 首先得安装Hexo吧
发现和hugo其实差不太多,但好像hugo当时没有必须要nodejs吧,这里我先升级了npm和nodejs ,防止版本过低又弄出什么bug
sudo apt update
sudo apt-get install git-core #git是肯定要有的
sudo npm install npm@latest -g
sudo npm cache clean -f
sudo npm install -g n
sudo n stable
sudo apt-get install nodejs-legacy
node -v
安装hexo~ sudo npm install -g hexo-cli
3 当前操作系统配置Key(差点忘记)
免得每次push的时候都得输入用户名密码,让更新blog变得更方便。
cd ~/.ssh
ssh-keygen -t rsa -C "邮件地址"
#敲入代码后连续按3次回车,最终会生成一个文件在用户目录下,打开用户目录,找到.ssh\id_rsa.pub文件,记事本打开并复制里面的内容。打开你的 GitHub 主页,进入个人设置 -> SSH and GPG keys -> New SSH key,并将刚刚复制的内容填入 Key 那里。
ssh -T [email protected]
#如果提示Are you sure you want to continue connecting (yes/no)?,输入yes 并回车
git config --global user.name "你的 GitHub 用户名"
git config --global user.email "你的 GitHub 注册邮箱"
之后如果要clone自己的仓库到本地时记得选择用SSH的URL来clone,这样在push时就可以不用输入用户名和密码了。(不过windows下我好像就用了普通的URLclone结果也不用输入密码,不太清楚原理)
4 建立站点下载主题
mkdir Hexo_site
cd Hexo_site
hexo init
cd themes
git clone -b develop https://github.com/blinkfox/hexo-theme-matery.git
接着只要运行
hexo clean && hexo g \
hexo s
就可以看到这个主题模板已经建立好了。
5 具体配置过程(重中之重)
前面的所有步骤15分钟内就可以完成,真正难在怎么去自定义这个模板,修改成自己舒服的样式才是最重要的嘛。不然大家为什么花那么多时间去折腾。
我这个主题的文档也说明的非常详细了,可以对照着它从头到尾先根据自己情况修改一遍。
5.1 如何建立新页面
照着说明文档建立了tags、about、categories等页面之后,大概明白了怎么去配置菜单栏,首先在_config.yml
中建立起一二级菜单,排好序、选好图标、确定url名称,下面是我主题配置文件相关部分:
menu:
Index:
url: /
icon: fas fa-home
Tags:
url: /tags
icon: fas fa-tags
Categories:
url: /categories
icon: fas fa-bookmark
Archives:
url: /archives
icon: fas fa-archive
About:
url: /about
icon: fas fa-user-circle
Contact:
url: /contact
icon: fas fa-comments
Friends:
url: /friends
icon: fas fa-address-book
Medias:
icon: fas fa-list
children:
- name: Books
url: /books
icon: fas fa-book
- name: Games
url: /games
icon: fas fa-gamepad
- name: Movies
url: /movies
icon: fas fa-film
- name: Hitokoto
url: /hitokoto
icon: fas fa-comment-alt
建好了之后去根目录/source
文件夹下建好相应子文件夹,这里我的/books /games /movies
是之后用hexo-douban插件生成的页面所以不需要建立文件夹。
然后先可以去看下效果,发现有的页面已经接近完美了,因为layout里面就有相关的样式设置。这时候需要认真阅读themes/hexo-theme-matery/layout
相关样式文件(.ejs),然后到处抄一点最后完成自定义页面的布局…
我是不怎么会抄所以只能做一个简单的一言页面。
5.2 豆瓣插件的安装
终于到这部分了,害得我花了几天折腾博客的罪魁祸首。关于怎么安装,作者的github上已经说的很清楚了,这里主要问题是适配和一些小问题的解决:
5.2.1 适配主题
我自己不太会弄,这里参考了一位医学大佬的解决方案。啥都不用想,抄就完事了,多轻松。
5.2.2 关于弹窗
弄好之后发现每次打开豆瓣读书相关页面会弹出三个空白窗口,在网上搜了一下发现是Hexo4.0新版本的问题,详细请参考这里,我的解决方法是将根目录的配置文件中相关部分改为:
external_link:
enable: true
field: post
然后就不会出现不需要的弹窗了,或者将hexo版本降至3.9
5.3 关于Markdown把英文的引号’显示成’的解决方案
这个不是主题的问题,而是相关插件hexo-renderer-marked的设置问题。
在/node_modules/hexo-renderer-marked
文件夹下,找到index.js
,将其中smartypants选项改成:
smartypants: false,
应该就没问题了。
5.4 评论系统的邮件提醒问题
如果用的是Valine评论系统并打开了回复邮件提醒但没设置模板,那么对方可能忽然收到这样一封莫名其妙的邮件:
您请求重设应用xxxx 的密码。点击下列链接来重设您的帐号密码(链接在 48 小时内有效):
https://leancloud.cn/reset.html?token=xxxxxxxxxxxxxxxxx
我刚建立好博客的时候也有这个问题,还好被别人提醒了。于是干脆部署了Valine Admin,是Valine 评论系统的扩展和增强,可以确保对方收到了自己的回复,并定时检查博客的新留言情况。
缺点是步骤比较复杂,还得先实名认证一下(现在的实名认证越来越嚣张了,动不动就给你采集个人脸信息。没办法,有空子谁不想钻呢)。
5.5 关于CNAME
上传到github之前记得在根目录source
文件夹下建立一个无后缀叫做CNAME
的文档,里面写上自己用来当博客的域名(买了域名的)。这样保证每次上传后不用重复去github设定自定义域名。
5.6 404页面
发现这个主题好像没有404页面,于是自己建了一个。步骤很简单:
hexo new page "404"
然后去编辑/source/404
下的index.md
文件就行了,觉得不够好看的再去layout
建立个样式文件。
6 关于post
记住post的Front-matter选项还是很有必要的,这里把主题相关说明文档抄了一部分过来:
Front-matter
选项中的所有内容均为非必填的。但仍然建议至少填写 title
和 date
的值。
配置选项 | 默认值 | 描述 |
---|---|---|
title | Markdown 的文件标题 |
文章标题,强烈建议填写此选项 |
date | 文件创建时的日期时间 | 发布时间,强烈建议填写此选项,且最好保证全局唯一 |
author | 根 _config.yml 中的 author |
文章作者 |
img | featureImages 中的某个值 |
文章特征图,推荐使用图床(腾讯云、七牛云、又拍云等)来做图片的路径.如: http://xxx.com/xxx.jpg |
top | true |
推荐文章(文章是否置顶),如果 top 值为 true ,则会作为首页推荐文章 |
cover | false |
v1.0.2 版本新增,表示该文章是否需要加入到首页轮播封面中 |
coverImg | 无 | v1.0.2 版本新增,表示该文章在首页轮播封面需要显示的图片路径,如果没有,则默认使用文章的特色图片 |
password | 无 | 文章阅读密码,如果要对文章设置阅读验证密码的话,就可以设置 password 的值,该值必须是用 SHA256 加密后的密码,防止被他人识破。前提是在主题的 config.yml 中激活了 verifyPassword 选项 |
toc | true |
是否开启 TOC,可以针对某篇文章单独关闭 TOC 的功能。前提是在主题的 config.yml 中激活了 toc 选项 |
mathjax | false |
是否开启数学公式支持 ,本文章是否开启 mathjax ,且需要在主题的 _config.yml 文件中也需要开启才行 |
summary | 无 | 文章摘要,自定义的文章摘要内容,如果这个属性有值,文章卡片摘要就显示这段文字,否则程序会自动截取文章的部分内容作为摘要 |
categories | 无 | 文章分类,本主题的分类表示宏观上大的分类,只建议一篇文章一个分类 |
tags | 无 | 文章标签,一篇文章可以多个标签 |
reprintPolicy | cc_by | 文章转载规则, 可以是 cc_by, cc_by_nd, cc_by_sa, cc_by_nc, cc_by_nc_nd, cc_by_nc_sa, cc0, noreprint 或 pay 中的一个 |
注意:
- 如果
img
属性不填写的话,文章特色图会根据文章标题的hashcode
的值取余,然后选取主题中对应的特色图片,从而达到让所有文章都的特色图各有特色。date
的值尽量保证每篇文章是唯一的,因为本主题中Gitalk
和Gitment
识别id
是通过date
的值来作为唯一标识的。- 如果要对文章设置阅读验证密码的功能,不仅要在 Front-matter 中设置采用了 SHA256 加密的 password 的值,还需要在主题的
_config.yml
中激活了配置。有些在线的 SHA256 加密的地址,可供你使用:开源中国在线工具、chahuo、站长工具。- 您可以在文章md文件的 front-matter 中指定 reprintPolicy 来给单个文章配置转载规则
下面是一个例子,防止自己将来忘记所以列出了尽可能多的选项:
---
title: typora
date: 2019-11-20
author:
img: /source/images/xxx.jpg
top: true
cover: true
coverImg: /images/1.jpg
password:
toc: false
mathjax: false
summary: 这是你自定义的文章摘要内容,如果这个属性有值,文章卡片摘要就显示这段文字,否则程序会自动截取文章的部分内容作为摘要
categories: Markdown
tags:
- Typora
- Markdown
---
2019/11/22更新 有人说我的博客打不开,再加上我Godaddy买的域名没办法续费,干脆连着domain全部搬家
7 CDN加速,把DNS迁移到cloudflare
7.1 注册帐号
翻了下好像中文只在帮助里有一小部分,主要还是英文。在注册之前可以先解除原来第三方的托管,我之前用的是DNSPOD,大半年没看一打开DNS怎么这么多条。
毫不犹豫能删的先全删了再说,然后进我买域名的Godaddy里将DNS托管改为cloudflare(按照它这里给的提示)。
然后托管成功之后先把DNS给加上(因为之前全删了),我是用的github平台,直接用CNAME加了@和www,指向chengpengzhao.github.io 。当然也可以使用A方式加ip就行了,我懒得去ping一下ip所以没用这种方法。
接下来的部分就难到我了,简直选择困难,这也体现了cloudflare的强大之处:这配置项也太多了吧。只能慢慢看它的说明一个个设置,先开个版块记录一下有哪些坑。
7.2 cloudflare设置
7.2.1 Scrape Shield
这一大项是关于反爬虫的,可以适当打开几个保护措施,但其中的Hotlink Protection可以选择关闭,不然在别人blog加你友链时他那边没法显示你的头像(不要问我怎么知道的)。
7.2.2 Speeding
这个里面有很多选项可以加快博客的访问速度,我先全部打开试了试,发现在浏览博客时很多效果都没了,直接不让加载,要按F5才能刷新出来。经过排查应该是Brotli这个选项的问题,因为我只关了这个然后问题就解决了,当然也不排除是别的原因。
7.2.3 Page Rules
据说这个功能挺强大的,我也不太会就按照网上别人的设置弄了一下,先看看实际效果如何吧。
7.3 将整个域名迁移到cloudflare
既然能够放在一起那我为什么还要多记一个账号的信息呢,godaddy再见了您。
首先在DNS管理页面能够看到当前domain所在运营商,如下图:
点击Manage domain
就可以开始迁移流程了,不过在此之前需要在cloudflare账号中绑定支付手段,可以是VISA卡或者PayPal,不支持银联等国内的支付产品(不过可以通过Paypal绑定银联卡)。
然后你会收到Godaddy发来的一系列邮件,这里注意要想马上迁移完成需要登录Godaddy账号点一下Accept,中文版网站我好像没找到这个选项,切成英文就OK了:
过了15分钟左右就会收到Godaddy最后煽情的告别邮件:
大功告成,接下来就可以享受cloudflare的服务了,域名的费用是8美刀一年,应该算是比较便宜的吧。我当初在Godaddy上买10年也花了580人民币,续费好像更贵。
8 Post排版自定义
忽然觉得Post如果有很多一二三级标题的话就有点难阅读了,有时候一眼看过去不能立即分辨出来这是第几级标题。所以感觉编号还是很重要的,但在写文章的时候还要注意编号就太不效率了,最后我选择给Post标题加入自动编号。
8.1 标题自动编号
8.1.1 先折腾一番再说
百度了一下自动编号的实现方式,根据这个主题的layout立马试了下,对layout/_partial
文件夹下post-detail-toc.ejs
文件的开头部分作了些修改:
#articleContent h1 {
counter-increment: counter_h1;
counter-reset: counter_h2;
}
#articleContent h1:before {
content: counter(counter_h1)" ";
}
#articleContent h2 {
counter-increment: counter_h2;
counter-reset: counter_h3;
}
#articleContent h2:before {
content: counter(counter_h1)"."counter(counter_h2)" ";
}
#articleContent h3 {
counter-increment: counter_h3;
counter-reset: counter_h4;
}
#articleContent h3:before {
content: counter(counter_h1)"."counter(counter_h2)"."counter(counter_h3)" ";
}
这段代码利用css的counter属性实现自动编号;但编号有是有了,我发现侧边目录也就是Toc仍没有编号,并且点击右侧跳转当前标题会被上面的状态栏挡住,还是需要进一步修改。
在matery.css
里改来改去,还是有点小问题,而且侧边栏的编号不知道怎么加,最后我放弃了这条思路。
8.1.2 最后采用的方法
抱着一点期待在github上翻了下,还真的有相关的小工具,hexo-heading-index,按照说明先用npm安装:
sudo npm install hexo-heading-index --save
再在根目录的_config.yml
中插入相关设置:
heading_index:
enable: true
index_styles: "{1} {1} {1} {1} {1} {1}"
connector: "."
global_prefix: ""
global_suffix: " "
可以根据个人喜好适当修改,这里我用了个&emsp
来让序号和标题隔得更开一点。再hexo s
看看效果,恩不错,还是白嫖人家写的东西好。但仍有个小问题就是在不想要出现序号的地方也给编了号,比如说我的友情链接。这里中部的文字也是Post的格式所以也给加上了编号,看起来自然不太舒服。
但这个插件好像没更新过了不知道怎么设置不编号的区域,所以只能自己改源码。好在代码写得还比较清楚,我通过只对前三级标题编号,在不想自动编号的地方用后三级标题的方式解决,只需要在hexo-heading-index/lib/index.js
中稍作修改:
function updateHeadingIndexes(options, data) {
var $ = cheerio.load(data, { decodeEntities: false });
var headings = $('h1, h2, h3');
//这里修改需要几级标题
headings
里面只保留想要自动编号的部分就行了。大功告成~
8.2 一级标题下自动插入分隔线
只需要在hexo-theme-matery/source/js/matery.js
中相应部分加一行就行了:
/*文章内容详情的一些初始化特性*/
let articleInit = function () {
$('#articleContent a').attr('target', '_blank');
$('#articleContent h1').after('<hr>'); //一级标题后加一行分隔线
然后可以在matery.css
里修改下分隔线的样式:
/*修改hr的样式*/
hr {
margin: 20px 0;
height: 3px;
border: none;
border: 0;
border-top: 1px solid #ccc;
background-color: #272822;
background-image: repeating-linear-gradient(
-45deg,
white,
white 4px,
transparent 4px,
transparent 8px
);
}
如果你也觉得再让一级标题居中会更舒服的话,只需在h1样式中加入text-align: center;
就OK了。
以下内容更新于2019-12-02 20:08:06
9 调整hexo-renderer-marked中Mathjax公式显示
发现默认的mathjax和marked的配置有的冲突,一些公式没法正常显示,做如下调整:
layout/post.ejs
文件中相关部分调整,防止()内的内容显示为公式<script> MathJax.Hub.Config({ tex2jax: {inlineMath: [['$', '$']], displayMath: [["$$","$$"]], processEscapes: true, skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code'] }, TeX: {equationNumbers: { autoNumber: "AMS" } } }); </script>
node_modules/marked/lib/marked.js
文件修改正则表达式部分,调整渲染策略
其余部分未作调整。var inline = { escape: /^\\([!"#$%'()*+,\-./:;<=>?@\[\]^_`|~])/, //escape: escape: /^\\([!"#$%&'()*+,\-./:;<=>?@\[\]\\^_`{|}~])/, br: /^ {2,}\n(?!\s*$)/, //br: /^( {2,}|\\)\n(?!\s*$)/,
以下内容更新于2019-12-04 16:39:37
10 hexo-prism-plugin相关语言支持及缩写
Markup - markup, html, xml, svg, mathml
CSS - css
C-like - clike
JavaScript - javascript, js
ABAP - abap
Augmented Backus–Naur form - abnf
ActionScript - actionscript
Ada - ada
ANTLR4 - antlr4, g4
Apache Configuration - apacheconf
APL - apl
AppleScript - applescript
AQL - aql
Arduino - arduino
ARFF - arff
AsciiDoc - asciidoc, adoc
6502 Assembly - asm6502
ASP.NET (C#) - aspnet
AutoHotkey - autohotkey
AutoIt - autoit
Bash - bash, shell
BASIC - basic
Batch - batch
BBcode - bbcode
Bison - bison
Backus–Naur form - bnf, rbnf
Brainfuck - brainfuck
BrightScript - brightscript
Bro - bro
C - c
C# - csharp, cs, dotnet
C++ - cpp
CIL - cil
CoffeeScript - coffeescript, coffee
CMake - cmake
Clojure - clojure
Crystal - crystal
Content-Security-Policy - csp
CSS Extras - css-extras
D - d
Dart - dart
Diff - diff
Django/Jinja2 - django, jinja2
DNS zone file - dns-zone-file, dns-zone
Docker - docker, dockerfile
Extended Backus–Naur form - ebnf
Eiffel - eiffel
EJS - ejs
Elixir - elixir
Elm - elm
Embedded Lua templating - etlua
ERB - erb
Erlang - erlang
F# - fsharp
Firestore security rules - firestore-security-rules
Flow - flow
Fortran - fortran
FreeMarker Template Language - ftl
G-code - gcode
GDScript - gdscript
GEDCOM - gedcom
Gherkin - gherkin
Git - git
GLSL - glsl
GameMaker Language - gml, gamemakerlanguage
Go - go
GraphQL - graphql
Groovy - groovy
Haml - haml
Handlebars - handlebars
Haskell - haskell, hs
Haxe - haxe
HCL - hcl
HTTP - http
HTTP Public-Key-Pins - hpkp
HTTP Strict-Transport-Security - hsts
IchigoJam - ichigojam
Icon - icon
Inform 7 - inform7
Ini - ini
Io - io
J - j
Java - java
JavaDoc - javadoc
JavaDoc-like - javadoclike
Java stack trace - javastacktrace
Jolie - jolie
JQ - jq
JSDoc - jsdoc
JS Extras - js-extras
JS Templates - js-templates
JSON - json
JSONP - jsonp
JSON5 - json5
Julia - julia
Keyman - keyman
Kotlin - kotlin
LaTeX - latex, tex, context
Less - less
LilyPond - lilypond, ly
Liquid - liquid
Lisp - lisp, emacs, elisp, emacs-lisp
LiveScript - livescript
LOLCODE - lolcode
Lua - lua
Makefile - makefile
Markdown - markdown, md
Markup templating - markup-templating
MATLAB - matlab
MEL - mel
Mizar - mizar
Monkey - monkey
MoonScript - moonscript, moon
N1QL - n1ql
N4JS - n4js, n4jsd
Nand To Tetris HDL - nand2tetris-hdl
NASM - nasm
nginx - nginx
Nim - nim
Nix - nix
NSIS - nsis
Objective-C - objectivec
OCaml - ocaml
OpenCL - opencl
Oz - oz
PARI/GP - parigp
Parser - parser
Pascal - pascal, objectpascal
Pascaligo - pascaligo
PC-Axis - pcaxis, px
Perl - perl
PHP - php
PHPDoc - phpdoc
PHP Extras - php-extras
PL/SQL - plsql
PowerShell - powershell
Processing - processing
Prolog - prolog
.properties - properties
Protocol Buffers - protobuf
Pug - pug
Puppet - puppet
Pure - pure
Python - python, py
Q (kdb+ database) - q
Qore - qore
R - r
React JSX - jsx
React TSX - tsx
Ren'py - renpy
Reason - reason
Regex - regex
reST (reStructuredText) - rest
Rip - rip
Roboconf - roboconf
Robot Framework - robotframework, robot
Ruby - ruby, rb
Rust - rust
SAS - sas
Sass (Sass) - sass
Sass (Scss) - scss
Scala - scala
Scheme - scheme
Shell session - shell-session
Smalltalk - smalltalk
Smarty - smarty
Solidity (Ethereum) - solidity
Soy (Closure Template) - soy
SPARQL - sparql, rq
Splunk SPL - splunk-spl
SQF: Status Quo Function (Arma 3) - sqf
SQL - sql
Stylus - stylus
Swift - swift
TAP - tap
Tcl - tcl
Textile - textile
TOML - toml
Template Toolkit 2 - tt2
Turtle - turtle, trig
Twig - twig
TypeScript - typescript, ts
T4 Text Templates (C#) - t4-cs, t4
T4 Text Templates (VB) - t4-vb
T4 templating - t4-templating
Vala - vala
VB.Net - vbnet
Velocity - velocity
Verilog - verilog
VHDL - vhdl
vim - vim
Visual Basic - visual-basic, vb
WebAssembly - wasm
Wiki markup - wiki
Xeora - xeora, xeoracube
Xojo (REALbasic) - xojo
XQuery - xquery
YAML - yaml, yml
Zig - zig
以下内容更新于2019-12-10 08:48:18
11 RSS订阅中文章显示不完整问题
解决方法:将atom改为rss2
具体参照node_modules/hexo-generator-feed
设置说明
我的根目录_confg.yml
:
feed:
type: rss2
path: rss2.xml
limit: false
hub:
icon: /medias/logo.png
content: true
content_limit: 140
content_limit_delim: '...'
order_by: -date