Hexo Blog
Table of Contents
如您在页脚处所见, 本站是由 Emacs Org mode 生成的, 而不是 Hexo. Hexo 陪伴了我很长一段时间, 但自从入手 Org mode 之后我就不再使用 Hexo 了, 关于 Hexo 的事情就不应该再归在 Site Config Doc 里了. 但 Hexo 的确很便于初学者搭建博客, 实际上, 本站的主体配色就基本上来自 Hexo 的 NexT.Pisces (NexT 主题的 Pisces scheme), 遂把之前写过的内容迁移到此以表感激之情.
1. Prerequisite
sudo pacman -S npm sudo npm install -g hexo-cli
2. Basics
2.1. Init
mkdir Blog && cd Blog hexo init npm install # install dependency
2.2. Essential modules
通过npm安装的模块都位于./nodemodules/:
npm list npm install --save hexo-deployer-git npm install --save hexo-math npm install --save hexo-blog-encrypt npm install --save hexo-renderer-org # If use Emacs Org mode npm uninstall xxx
2.3. ./_config.yml
要注意yml文件的 缩进. 关于如何同时推到两个git repo的写法, 参考hexojs/hexo-deployer-git: Git deployer plugin for Hexo.
# Site title: OChicken #Hexo author: Shouran Ma #John Doe timezone: Europe/Berlin #'' # URL url: https://ochicken.top #http://example.com # Writing post_asset_folder: true # Extensions theme: next #landscape math: engine: 'mathjax' # or 'katex' mathjax: src: #custom_mathjax_source config: # MathJax config katex: css: custom_css_source js: custom_js_source # not used config: # KaTeX config ## Security encrypt: enable: true silent: true # Deployment ## Docs: https://hexo.io/docs/one-command-deployment deploy: - type: git repo: [email protected]:OChicken/OChicken.github.io.git branch: master - type: git repo: [email protected]:OChicken/OChicken.DigitalOcean.io.git branch: master
2.4. Usage
hexo clean # 清空冗余文件 hexo g (= hexo generate) # 生成网页 hexo s (= hexo server) # 浏览器里输入 http://localhost:4000/, 就可以看到刚才的成果了 Ctrl+C # 结束 hexo d (= hexo deploy) # 部署到云
顺带一提: "博客" 这个词给人第一感觉是托管在 "云 服务器" 里的. 实际上如前面提到的, "云" 这个前缀只不过是有一个独立IP可供世界各地的人访问而已; 如果你只想自个儿看, 那在一个甚至不需要联网的 PC 里都可以完成, 这个东西就是 http://localhost
, 本地主机.
3. Theme NexT: Basic
Hexo官方主题合集: Themes | Hexo
Hexo下载的是默认的 landscape
主题. 当然可以换别的. 最常用的是 NexT
, 其目录位于 ./theme/next/
.
3.1. Install
这是有效的那个版本:
git clone https://github.com/theme-next/hexo-theme-next.git themes/next
NexT还有别的版本, 含原始版本和衍生版本, 谨记录在此, 不保证有用:
git clone https://github.com/iissnan/hexo-theme-next.git theme/next # 原始版本 git clone https://github.com/next-theme/hexo-theme-next.git themes/next # 衍生版本 npm install hexo-theme-next # 衍生版本, 通过npm安装
虽然 ./theme/next/_config.yml
和 ./_config.yml
同名, 但 都掌管着各自的前端, 不可随意替换.
本节的内容主要是编辑 ./theme/next/_config.yml
.
3.2. Avatar
Setup ./images/Cola.png and ./images/wechatchannel.jpg.
favicon: small: /images/favicon-16x16-next.png medium: /images/favicon-32x32-next.png small: /images/Cola.png #favicon-16x16-next.png medium: /images/Cola.png #favicon-32x32-next.png apple_touch_icon: /images/apple-touch-icon-next.png safari_pinned_tab: /images/logo.svg #android_manifest: /images/manifest.json footer: # Specify the date when the site was setup. If not defined, current year will be used. #since: 2015 # Icon between year and copyright info. icon: # ... # Change the color of icon, using Hex Code. color: "#808080" #"#ff0000" # If not defined, `author` from Hexo `_config.yml` will be used. copyright: "OChicken" # ... # Schemes #scheme: Muse #scheme: Mist scheme: Pisces #scheme: Gemini # Sidebar Avatar avatar: # Replace the default image and set the url here. url: /images/Cola.png #/images/avatar.gif # If true, the avatar will be dispalyed in circle. rounded: false # If true, the avatar will be rotated with the cursor. rotated: false # Posts / Categories / Tags in sidebar. site_state: false #true
3.5. Math
# Math Formulas Render Support math: # Default (true) will load mathjax / katex script on demand. # That is it only render those page which has `mathjax: true` in Front-matter. # If you set it to false, it will load mathjax / katex srcipt EVERY PAGE. per_page: true # hexo-renderer-pandoc (or hexo-renderer-kramed) required for full MathJax support. mathjax: enable: true #false # See: https://mhchem.github.io/MathJax-mhchem/ mhchem: false
3.6. 访客统计
# Show Views / Visitors of the website / page with busuanzi. # Get more information on http://ibruce.info/2015/04/04/busuanzi busuanzi_count: enable: true #false
4. Theme NexT: Advanced styles
本节编辑的文件都是 ./source/css/main.styl
. (它的 syntax 实际上就是一个 CSS 文件)
4.1. Line height
This is a patch to ./source/css/_variables/base.styl
. Change $line-height-base
from 2 to 1.5:
// Variables Layer // -------------------------------------------------- for $variable in $variables @import "_variables/" + $variable; for $inject_variable in hexo-config('injects.variable') @import $inject_variable; $line-height-base = 1.5; // patch
4.2. Common Scaffolding
This is a patch to ./source/css/_common/scaffolding/base.styl
, aiming to modify headers (h1-6), horizontal rule (hr), paragraph (p):
// Scaffolding @import "_common/scaffolding"; h1, h2, h3, h4, h5, h6 { // patch line-height: 1.0; // patch margin: 15px 0 15px; // patch } // patch hr { // patch margin: 15px 0; // patch } // patch p { // patch margin: 0 0 10px 0; // patch } // patch
4.3. Common Layout
This is a patch to ./source/css/_common/outline/sidebar/sidebar-author-links.styl
. 默认的social links是居中的, 当某个link名字特别长的时候就不对齐. 此设置把text-align设为左对齐以缓解此问题.
// Layout @import "_common/outline"; .links-of-author a, span.exturl { // patch text-align: left; // patch } // patch
4.4. Common Components - Global Font-size
This is a patch to ./source/css/_common/components/post/post.styl
. Set global font-size in post:
// Components @import "_common/components"; .post-body { // patch font-size: $font-size-medium; // patch } // patch
当时想过在 ./_config.yml
设置 font:
, 但是这样子搞, 会把post正文, 连同sidebar和toc的字体都改小. toc的字体再小一号就太小了, 遂不得不在./source/css/main.styl里手动改.
4.5. Common Components - Unordered List
This is a patch to ./source/css/_common/components/post/post.styl
. 写文档的时候总会出现这种用语情境: "其原因有: xxx, yyy, …" 如是分点列出. 我们发现, 经Hexo渲染之后, 无序表 ("xxx, yyy, …") 跟它的前一段 ("其原因有:") 总是隔着很大margin. 为此我做了如下设置:
@import "_common/components"; .post-body ul { // patch margin-top: -10px; // patch margin-bottom: 0; // patch } // patch
现在解释一下为何这么设置. 前面我设置了段落 p
的格式, margin-top为0, margin-bottom为10px. ul
也是 p
的一种, 即无序表的margin-top为0, margin-bottom为10px. 段落 "其原因有:" 跟无序表 "xxx, yyy, …" 被视为了两个段落 (就行文逻辑而言它们应该是一段), 这两个段落之间的margin是 "其原因有:" 这个段落的margin-bottom造成的. 所以, 需要把 ul
的margin-top设为-10px, 抵销掉 这个margin, 这样二者就看起来是一段的了.
另一方面, ul
的margin-bottom设为0, 跟 p
的margin-top为0相适配, 表明它们之间没有margin. 这也符合实际: 假如列完无序表后还有一些补充 (这也应当视为一段), 那么紧跟着写就是了, 中间不会有任何margin; 如果是新开一个段落, 那么就加个空行.
须注意, 此设置仅用于Hexo在网页前端的渲染, 其html文件里依然是有空行的 — 换句话说, 是Hexo前端欺骗了你. 如果你用pandoc或Emacs Org将本文件生成为html, 再用Emacs-EWW打开, 会发现它们中间的确是空了一行, 只是再经过Hexo的样式渲染, 才看到浏览器上显示的结果.
4.6. Images Container
这个功能相当于LaTeX的float环境; 在css里, 使用flex来作为图片的container, 中间用hfill填充, 图片默认宽度为linewidth的25%.
.image-container { // patch display: flex; // patch justify-content: space-between; // patch } // patch .image { // patch width: 50%; // patch } // patch
4.7. 加密后不显示目录
Ref: Hexo博客文章加密 | IT范儿
打开 ./layout/_macro/sidebar.swig
, 把这个block
{%- if display_toc %} {%- set toc = toc(page.content, { class: "nav", list_number: page.toc.number, max_depth: page.toc.max_depth }) %} {%- set display_toc = toc.length > 1 and display_toc %} {%- endif %}
的第2行改为
{%- if (page.encrypt) %} {%- set toc = toc(page.origin, { class: "nav", list_number: page.toc.number, max_depth: page.toc.max_depth }) %} {%- else %} {%- set toc = toc(page.content, { class: "nav", list_number: page.toc.number, max_depth: page.toc.max_depth }) %} {%- endif %}
以及把这个block
<div class="post-toc-wrap sidebar-panel"> {%- if display_toc %} <div class="post-toc motion-element">{{ toc }}</div> {%- endif %} </div>
第1,2行之间插入这一块
{%- if (page.encrypt) %} <div id="toc-div" style="display:none"> {%- endif %}
5. Deploy
很多关于搭 Hexo 相关的博客都提到, 要搞定发布博客到云服务器的这一步, 须自己在云服务器搭一个 git repo. 我认为自建 git repo 的难度远高于去配置 Hexo 博客本身, 这两个放一起, 对初学者是很不友好的, 除非你有像我当年一样一连两个月去自己捣鼓这个.
实际上 要做 deploy, 你其实可以不那么折腾. hexo g
之后, 直接把生成出来的 public/
目录里的东西一股脑地 上传 到 /var/www/html/
就行了, 用过 scp
的读者都应该知道这真的是小事, 再不济, 如果你用 Windows 的话, 你还有 WinScp. 自建 git repo 的作用恐怕在于, 便于你像 hexo d
到 GitHub 那样去 hexo d
到自己的 VPS, 兜兜转转一大圈, 竟然只是为了用 hexo d 去 deploy! 我不知道为什么那么多 Hexo 相关的博客谈及 deploy 都说要自己搭 git repo (至少我印象中) …
当然如果你知道怎么自建 git repo, 那也不亏, Your patient mastery of this is well-rewarded. I assure you.
Refs:
- Hexo搭建个人博客并部署到vps服务器 - 掘金
- Hexo搭建个人博客并使用Git部署到VPS - 简书 (「安装配置nginx」一节)
5.1. 远程git仓库
GitHub 就是一类天然带了 git 仓库的 VPS, 只不过是我们没法 shell 登录, 也不知道专属的 IP 是多少; 自己购买的 VPS 并不像 GitHub 那样有 git 仓库, 所以得自己配置. 在VPS上自建git仓库 来托管代码就是重点要讨论的主题.
Hexo 个人博客的关键一步是 在VPS上创建git仓库.
5.1.1. 创建git用户
使用如下命令创建git用户. -m
表示创建用户目录/home/git, -G sudo
表示用户git除了隶属于 git
这个用户组以外还隶属于 sudo
; -s /usr/bin/git-shell
表示login shell为git-shell.
useradd -m -G sudo -s /usr/bin/git-shell git
login shell不是/bin/bash, 因为须禁止git以shell登录.
5.1.2. 给git配置公钥
sudo su # now you are root mkdir -p /home/git/.ssh cp /home/OChicken/.ssh/authorized_keys /home/git/.ssh/
给git用户配置公钥并不是为了用来登录, 而是发布博客时, 本地 hexo d
就直接 免密git push 到云服务器了, 就像我们通常使用git push一样.
5.1.3. Blog.git
在继续之前先理解下面几个写法:
git clone [email protected]:OChicken/Blog.git scp [email protected]:OChicken/Blog.git ./ git clone [email protected]:Pigcatdog/Blog.git scp [email protected]:PigCatDog/Blog.git ./
git clone和scp的功能是非常相似的, 都可以把云上的一个目录”下载”下来到本地. 可是, OChicken和PigCatDog是github.com上的两个不同的用户, 为什么scp的时候都是[email protected]呢? 就ssh的经验来讲, 不应该是[email protected], [email protected]吗?
其实, github.com的服务器上只有一个用户: git, 其 HOME=/home/git/
. 每注册一个用户, 就在$HOME下创建一个目录: $HOME/OChicken
, $HOME/User1
, HOME/User2
, … 我OChicken每创建一个repo, 其在github.com上的路径就是 $HOME/OChicken/Blog.git
, $HOME/OChicken/Work.git
, … 当我在本地克隆时, git clone的写法就跟scp的写法非常相似了.
如果说在GitHub上用的是 git clone [email protected]:OChicken/Blog.git
, 那么在OChicken.net上的情形就应该是 git clone [email protected]:OChicken/Blog.git
. 为此
cd /home/git mkdir -p OChicken && cd OChicken git init --bare Blog.git
Blog.git的内容是这样的:
branches config description HEAD hooks info objects refs
这是empty Git repo的特征. 尝试在本地 git clone [email protected]:OChicken/Blog.git
, 并git add commit push三连, 其效果跟你在github.com上操作是完全一样的, 这表明我们确实在OChicken.net上创建了个git仓库, 只是域名从github.com换成了OChicken.net而已.
注: git init --bare
是指创建bare repo, 必须要有个 --bare
, 不然一定报错. 理由详见Git Push error: refusing to update checked out branch - Stack Overflow
5.1.4. 配置git hooks, 指向 /var/www/html/
到此步之前, 所建立的远程git仓库都还仅局限在自己的小天地. 我们希望Blog.git的内容能open to the public, 也就是出现在 /var/www/html/
. 为此须编辑git hooks:
cd /home/git/OChicken/Blog.git/hooks
touch post-receive
chmod 755 post-receive
vim post-receive
输入如下内容后保存退出.
#!/bin/bash GIT_REPO=/home/git/OChicken/Blog.git TMP_GIT_CLONE=/tmp/blog PUBLIC_WWW=/var/www/html rm -rf ${TMP_GIT_CLONE} cd ${PUBLIC_WWW} find . -type f ! -path "./library/*" -delete cd - git clone $GIT_REPO $TMP_GIT_CLONE cp -rf ${TMP_GIT_CLONE}/* ${PUBLIC_WWW}
这表示, 每次git push (其实是hexo d) 后, 都会把Blog.git的内容复制到 /var/www/html/
.
5.1.5. 收尾: 修改所有者
别忘了修改读取权限和所有者
chown -R git:git /home/git/ chown -R git:git /var/www/html/
作为测试, 再来一次git add commit push三连, 应该能够在 /var/www/html/
看到non-trivial的内容.
5.2. 本地配置
这里只谈Hexo Blog本地配置涉及deploy到服务器的部分. 在博客根目录的 _config.yml
:
# Deployment ## Docs: https://hexo.io/docs/one-command-deployment deploy: - type: git repo: [email protected]:OChicken/OChicken.github.io.git branch: master - type: git repo: [email protected]:OChicken/Blog.git branch: master
然后使用 hexo d
部署. 关于Hexo如何配置和使用, 请看上一节.