从Hugo折腾到Hexo过程记录

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 [email protected] -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 选项中的所有内容均为非必填的。但仍然建议至少填写 titledate 的值。

配置选项 默认值 描述
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 中的一个

注意:

  1. 如果 img 属性不填写的话,文章特色图会根据文章标题的 hashcode 的值取余,然后选取主题中对应的特色图片,从而达到让所有文章都的特色图各有特色
  2. date 的值尽量保证每篇文章是唯一的,因为本主题中 GitalkGitment 识别 id 是通过 date 的值来作为唯一标识的。
  3. 如果要对文章设置阅读验证密码的功能,不仅要在 Front-matter 中设置采用了 SHA256 加密的 password 的值,还需要在主题的 _config.yml 中激活了配置。有些在线的 SHA256 加密的地址,可供你使用:开源中国在线工具chahuo站长工具
  4. 您可以在文章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: /^\\([!"#$%&'()*+,\-./:;<=>[email protected]\[\]\\^_`{|}~])/,
    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
Author: zcp
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source zcp !
评论
Valine utteranc.es
 Previous
Linux/Windows使用记录
1 Ubuntu出现U盘能识别但打不开这个问题困扰了我很久,不知道是什么原因造成的,网上给出的大多数解决方案也都行不通,而且有时候重启下又可以正常打开了,不知道电脑是哪里抽风。 1.1 问题描述插入U盘后在桌面不显示
2019-11-22
Next 
Install Dakota 6.11 on Ubuntu 18.04
First I'd like to thank Chien Nguyen for his blog, it's very helpful for a noob to linux like me. Dakota releas
  TOC