Hexo博客搭建(4)——常见问题

温馨提示:点击页面下方以展开或折叠目录

摘要:这部分内容主要对博客做最后的完善,包括魔改部分页面和拯救强迫症。

Hexo博客搭建
博客系列:Hexo博客搭建(1)——建站及部署,环境搭建并部署至Github。
博客系列:Hexo博客搭建(2)——主题配置,针对pure主题进行个性化配置。
博客系列:Hexo博客搭建(3)——优化评论系统,主要对Valine评论系统进行优化。
博客系列:Hexo博客搭建(4)——常见问题,修复了pure主题的系列小bug。
文章作者:鴻塵

1.如何使其支持Mathjax

参考文章:如何在 hexo 中支持 Mathjax?
注: Mathjax公式中*号表示斜体,\times才表示乘号×

  • 1.使用Kramed代替Marked
    Hexo默认的渲染引擎是marked,但是marked不支持mathjax公式,kramed是在marked的基础上进行修改。执行以下命令卸载marked、安装kramed

    1
    2
    npm uninstall hexo-renderer-marked --save
    npm install hexo-renderer-kramed --save

    然后修改./node_modules/hexo-renderer-kramed/lib/renderer.js第65行函数的return部分:

    1
    2
    3
    4
    5
    6
    // Change inline math rule
    function formatText(text) {
    // Fit kramed's rule: $$ + \1 + $$
    // return text.replace(/`\$(.*?)\$`/g, '$$$$$1$$$$');
    return text;
    }
  • 2.停用hexo-math
    卸载hexo-math,安装hexo-renderer-mathjaxGitHub地址】:

    1
    2
    npm uninstall hexo-math --save
    npm install hexo-renderer-mathjax --save
  • 3.更新Mathjax的 CDN 链接
    修改./node_modules/hexo-renderer-mathjax/mathjax.html最后一行的<script>标签的src属性:

    1
    <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script>
  • 4.更改默认转义规则
    因为Hexo默认的转义规则会将一些字符进行转义,比如_转为<em>,所以我们需要对默认的规则进行修改,文件路径为./node_modules/kramed/lib/rules/inline.js

    1
    2
    3
    4
    5
    6
    7
    # 第11行(上为原文,下为修改)
    escape: /^\\([\\`*{}\[\]()#$+\-.!_>])/,
    escape: /^\\([`*\[\]()# +\-.!_>])/,

    # 第20行(上为原文,下为修改)
    em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
    em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
  • 5.开启Mathjax

    • 站点配置文件_config.yml中开启Mathjax,在文件末尾添加如下代码:
      1
      2
      mathjax:
      enable: true
    • 在已发布的文章*.md文件的Front-matter中开启mathjax
      1
      2
      3
      4
      5
      6
      ---
      title: xxx
      category: xxx
      date: 2020-10-14 21:24:15
      mathjax: true
      ---
    • 可修改./scaffolds/post.md模板文件,在Front-matter中开启Mathjax:mathjax: true
  • 6.重新生成页面
    修改完成后清除缓存、重新生成页面、部署,「一键三连」即可。


2.如何更改左侧IconFont 图标

主题配置文件默认的有github,微博,twitter,facebook等,但可能与自己需求不同,故需定制
需要就加上,不需要就注释,4~6个为宜
可用参考:适配IconFont 图标

第一步:vi ./themes/pure/_config.yml
第二步:profilesociallinks层级下对应修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# profile
profile:
......
social:
links:
github: https://github.com/hwame
weibo: https://weibo.com/hwamei
# twitter: https://twitter.com
# facebook: https://facebook.com
zhihu: https://www.zhihu.com/people/hwame
# dribbble: /
# behance: https://www.behance.net
# rss: atom.xml
segmentfault: https://segmentfault.com/u/hwame
gitee: https://gitee.com/hwame
# qzone: https://qzone.qq.com/
# email: mailto:user@qq.com
# qq: https://im.qq.com/
# wechat: https://wx.qq.com/
# alipay: https://www.alipay.com/
# juejin: https://juejin.im/
stackoverflow: https://stackoverflow.com/questions
# friendship: https://
......

例如,我开启了「github」、「weibo」、「zhihu」、「segmentfault」、「gitee」、「stackoverflow」六个,效果如图:
左侧IconFont 图标


3.如何取消文章目录的自动编号

有时我们文章的展开目录不需要自动编号,而是希望和*.md保持一致
但是Hexo默认会加上编号,这会导致①在有编号的地方重复编号;②在不需要编号(譬如某些三级目录)的地方也会编号
所以需要修改源码:./node_modules/hexo/lib/plugins/helper/toc.js

第一步:vi ./node_modules/hexo/lib/plugins/helper/toc.js
第二步:修改其中list_number: true的属性值,默认true为使用自动编号,如下第六行

1
2
3
4
5
6
7
function tocHelper(str, options = {}) {
options = Object.assign({
min_depth: 1,
max_depth: 6,
class: 'toc',
list_number: true // 自行修改,true/false
}, options);

注意:在主题配置文件修改无效:

1
2
3
4
5
6
7
8
9
# 原文:
config:
toc: true # 是否开启文章章节目录导航

# 无效的修改:
config:
toc:
enable: true # 是否开启文章章节目录导航
number: false

关于目录的特别说明
有的小伙伴不知道怎样开启目录,在这里一并说明:

此部分是「如何取消文章目录的自动编号」,是对于「已经开启了目录显示」而言的。那如何开启目录显示呢?

  • ①主题配置文件./themes/pure/_config.yml里开启目录功能:config: toc: true;
  • 文章里必须有目录(一级目录#,二级目录##等等),然后在文章的Front-matter(就是.md文件顶部的两个---之间的部分)中添加toc: true,如图;
    开启文章目录
  • 上述条件缺一不可

因为「目录的展开/折叠」是主题自带的,只需自行开启不涉及魔改,所以没有特意写。

另外在手机上浏览时,只显示一个「」图标,所以加一个「温馨提示」。直接在<div class="article-meta">···</div>后添加即可,样式自行修改,文件位置./themes/pure/layout/_partial/article.ejs

1
2
3
4
<div class="article-header">***省略***</div>
<div style="background-color:#D7BDE2;border:1px solid #D7BDE2;border-radius:10px;padding:5px">
<b>温馨提示</b>:点击页面下方<i style="color:red" class="icon icon-anchor"></i>以展开或折叠目录~
</div>


4.如何修改代码字体及图片居中

此部分参考Hexo博客搭建——CSS样式修改,文件位置为./themes/pure/source/css/style.css,修改了三个部分(可能由于添加过注释,代码行数会有所偏差):

  • 行内代码颜色,原始颜色和正文接近,对比度区分不够明显,修改为橙黄色
  • 代码字体,原始代码字体为「宋体」,修改经典的「Consolas」;
  • 文章图片居中,文章图片默认为左对齐,修改为居中。

4.1.行内代码颜色

第一步:vi ./themes/pure/source/css/style.css
第二步:5549行code修改colorbackground

1
2
3
4
5
6
7
8
9
code {
text-shadow: 0 1px #fff;
padding: 0.2em 0.4em;
margin: 0 0.3em;
color: #FF4500;
/* 行内代码颜色及背景 */
background: #F0FFFF;
border-radius: 3px;
font-size: 85%;

4.2.代码字体

第一步:vi ./themes/pure/source/css/style.css
第二步:155行samp添加Consolas字体:

1
2
3
4
samp {
font-family: consolas,monospace;
font-size: 1em;
}


4.3.如何使文章图片居中

第一步:vi ./themes/pure/source/css/style.css
第二步:125行img修改:

1
2
3
4
5
6
7
8
img {
border: 0;
box-sizing: border-box;
margin: auto;
padding: 3px;
text-align: center;
display: block;
}


5.如何添加文章描述

参考文章:如何添加文章描述-首页截断设置
md文章写一个摘要,结尾加上<!-- more -->即可。例如

1
2
3
4
5
6
7
8
9
10
11
12
13
---
title: Hexo博客搭建(2)——优化及完善
date: 2020-05-20 13:14:52
tags:
- Hexo
categories:
- Hexo
toc: true
---

文章描述测试<!-- more -->

以下是正文……

首页效果如图
首页效果图


6.如何实现点击图片放大

主题配置文件./themes/pure/_config.yml自带了一个选项fancybox: false,其默认是关闭的,打开之后即可实现「点击图片查看大图」的功能。
然而,在我们不需要的地方也会这样,比如,「友情链接」板块,fancybox: true时点击头像并没有跳转,而是当做图片打开,并且也并没有打开图片。因为图片(头像)对应的超链接是「小伙伴个人主页」,头像本身的链接是「图床上的图片」。
所以要修改源码:./themes/pure/layout/_partial/archive-link.ejs

其核心部分为for (var link in site.data.links) {}这个循环,获取每一个友链name,对应的item为每个友链的三个值item.linkitem.avataritem.desc,分别渲染。


第一步href="<%= item.link %>"改为href="<%= item.avatar %>"。既然点击头像既不能查看大图,也不能跳转,那我们修改为查看大图吧。只需要将图片的超链接还给头像自己即可,如下第7行,将<a href="<%= item.link %>" target="_blank" class="img-burn thumb-md media-middle">修改为<a href="<%= item.avatar %>" target="_blank" class="img-burn thumb-md media-middle">
第二步alt=""改为alt="<%= item.desc %>"。现在只让他变图片了,好人做到底,加个图片描述吧,就用那个desc:第8行,将<img src="<%= item.avatar %>" class="w-full" alt="">修改为<img src="<%= item.avatar %>" class="w-full" alt="<%= item.desc %>">
第三步,其实就已经好了,但是友链跳转是点击那个「名字」,默认是黑色(class="text-dark"),不够明显,希望换个颜色表示超链接。将h4下的<span>修改为<span style="color:#9932CC" title="点击跳转"><%= name %></span>

修改完成后的核心循环部分如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<% for (var name in site.data.links) { %>
<% var item = site.data.links[name]; %>
<div class="col-sm-6 col-md-4">
<div class="panel panel-default hover-shadow hover-grow">
<figure class="media media-middle">
<div class="media-left pr-no">
<a href="<%= item.avatar %>" target="_blank" class="img-burn thumb-md media-middle">
<img src="<%= item.avatar %>" class="w-full" alt="<%= item.desc %>">
</a>
</div>
<div class="media-body p-0x">
<h4 class="media-heading"><a href="<%= item.link %>" target="_blank">
<span style="color:#9932CC" title="点击跳转"><%= name %></span></a>
</h4>
<div class="text-muted">
<%= item.desc %>
</div>
</div>
</figure>
</div>
</div>
<% } %>

7.添加「相册」页面

由于博主没有豆瓣账号,主题自带的「豆瓣书单」页面一直用不上,因此想着改成其他实用的。
最初修改为「留言板」,奈何无人回应😂😂(尴尬.jpg),受第6部分【6.如何实现点击图片放大】的启发,最终决定修改为分享摄影作品的「相册」页面。

7.1.重命名相关文件

此部分是魔改相册,代码及文件(夹)原本是以book(s)命名的,既然现在是「相册」了,就得改名叫「gallery」了。
./themes/pure/下的文件或文件内容中所有的book(s)改为gallery

序号 类型 原文件名 修改后文件名
1 文件夹 ./themes/pure/_source/books/ ./themes/pure/_source/gallery/
2 文件 ./themes/pure/layout/books.ejs ./themes/pure/layout/gallery.ejs
3 文件 ./themes/pure/layout/_partial/archive-book.ejs ./themes/pure/layout/_partial/archive-gallery.ejs

7.2.修改源代码

  • ./themes/pure/layout/gallery.ejs,文件路径改为'_partial/archive-gallery'即可。
  • ./themes/pure/layout/_partial/archive-gallery.ejs,代码参考第6部分【6.如何实现点击图片放大】,修改后完整内容如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    <article class="article article-links article-type-list" itemscope="">
    <header class="article-header">
    <h1 itemprop="title"><%= page.title %></h1>
    <p class="text-muted">
    <%= __('page.gallery-desc') %>
    </p>
    </header>
    <div class="article-body">
    <div class="row">
    <% for (var link in site.data.gallery) { %>
    <% var item = site.data.gallery[link]; %>
    <div class="col-sm-6 col-md-4">
    <div class="panel panel-default hover-shadow hover-grow">
    <figure class="media media-middle">
    <div class="media-left pr-no">
    <a href="<%= item.full_link %>" target="_blank" class="img-burn thumb-md media-middle">
    <img src="<%= item.thumb_link %>" class="w-full" alt="">
    </a>
    </div>
    <div class="media-body p-0x">
    <h4 class="media-heading"><a href="<%= item.full_link %>" target="_blank"><span class="text-dark"><%= link %></span></a></h4>
    <div class="text-muted">
    <%= item.desc %>
    </div>
    </div>
    </figure>
    </div>
    </div>
    <% } %>
    </div>
    </div>
    </article>
    <% if (theme.comment.type && !is_home()) { %>
    <%- partial('post/comment', {post: page}) %>
    <% } %>

7.3.配置相册

./source/_data/目录下新建一个gallery.yml文件,格式如下:

  • Name:相片名称,多张照片保证不要重名
  • full_linkthumb_link:原图和缩略图链接,图床上的图片直接以地址引用,./themes/pure/source/images/文件夹下的图片以/images/subdir/img.jpg的格式引用
  • desc:相片描述
1
2
3
4
Name:
full_link: /path/to/img.jpg
thumb_link: /path/to/thumb_img.jpg
desc: "photo description"

7.4.修改主题相关配置

  • 主题配置文件./themes/pure/_config.yml的菜单选项:
    • Books: books修改为Gallery: gallery
    • books: icon-book-fill修改为gallery: icon-delicious,图标名参考【这里】
  • 语言配置文件./themes/pure/languages/zh-CN.yml,如果使用其他语言只需对应修改:
    • menuBooks: 书单修改为Gallery: 相册
    • pagebooks: 书单修改为gallery: 相册books-desc: 个人收藏的书单推荐给大家修改为gallery-desc: 摄影爱好者的个人拍摄作品
  • 样式表文件./themes/pure/source/css/gallery.css,整理这部分内容时发现多出了这个CSS文件,但是应该不是必需的

7.5.生成页面及说明

如果没有./source/gallery/./source/gallery/index.md,则执行hexo new page "gallery"生成新的页面,修改./source/gallery/index.md文件的typelayout

1
2
3
4
5
6
7
8
---
title: 相册
copyright: false
comments: true
date: 2020-05-27 11:25:35
type: gallery
layout: gallery
---

说明:

评论区有小伙伴提到原版gallery的问题,我在主题文件夹下查找与gallery相关的文件,如下图所示:
与gallery相关的文件

  • 文件名含有gallery的文件:
    • .themes/pure/_source/_data/gallery.yml
    • .themes/pure/layout/_partial/post/gallery.ejs
  • 文件内容含有gallery的文件:
    • .themes/pure/layout/_partial/post/gallery.ejs
    • .themes/pure/layout/_partial/article.ejs

其中gallery.yml位于_source文件夹内,暂时不用考虑;
看看剩下两个.ejs文件的代码,在article.ejs里引用了gallery.ejs,所以可以看到这是「博文配图」的样式(即fancybox效果),跟「相册」没有关系。
但是我们可以借鉴这个样式,来定制「相册」浏览的页面,布局呢可以借鉴「友情链接」的布局。于是就有了来自于第6部分【6.如何实现点击图片放大】的灵感。
另一方面,看看gallery.yml的文件结构,是不是简直和links.yml一模一样,所以我们的照片没有必要写到HTML.ejs里,仿照友链用循环处理多张照片,然后把照片信息添加在gallery.yml里。
至此,是不是就豁然开朗了呢?


8.如何显示「最近文章」缩略图

第一步:在主题配置文件./themes/pure/_config.yml中开启:

1
2
config:
thumbnail: true

第二步:在文章Front-matter中添加文章缩略图链接地址(图片地址可以是图床上的图片,也可以放在./themes/pure/source/images/文件夹下,引用方式如下):

1
2
3
4
5
6
---
title: xxx
toc: true
date: 2020-10-15 11:18:23
thumbnail: /images/avatar.jpg
---


9.部分地方中文适配

由于languages中的中文配置问题,部分地方没有完全改为中文:「分类」「归档」页面的「全部」、「共xxx篇文章」、「第x页,共x页」等,只需要修改./themes/pure/languages/zh-CN.yml即可:

  • 导航navall: All修改为all: 全部
  • 分页paginationpageof: Page %d of %s修改为pageof: 第 %d 页,共 %s 页

10.免密部署问题

前文Hexo博客搭建(1)——建站及部署之部署Hexo原本部署部分设置的是repository: https://github.com/username/username.github.io.git,这种方式有时候会需要手动输入用户名和密码,有时候还会出现Error: Spawn failed的错误,参考文章《hexo发生error:spawn failed错误的解决方法》,直接修改为repository: git@github.com:username/username.github.io.git即可。


11.自定义左下角信息

11.1.添加访问量和访客数

原版左下角是Theme by cofess base on pure.过于单调,考虑加入「站点访问量」和「访客数」,至于文章阅读量可以通过LeanCloud并且已经实现。文件位置:./themes/pure/layout/_common/footer.ejs

「访问量」和「访客数」可以使用「不蒜子-极简网页计数器」,该网站也提供了「网站总访问量」的示例:

1
2
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<span id="busuanzi_container_site_pv">本站总访问量<span id="busuanzi_value_site_pv"></span></span>

通过F12可以发现设置的方法:

  • 文章阅读量:<span id="busuanzi_value_page_pv"></span>
  • 站点访问量:<span id="busuanzi_value_site_pv"></span>
  • 站点访客数:<span id="busuanzi_value_site_uv"></span>

结合网站示例,将Theme by cofess base on pure.注释掉,并加入「访问量」和「访客数」,还可以通过<div class="publishby">标签加入「网站备案信息」,修改后如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
<footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
<%- partial('_common/social', null, {cache: !config.relative_link}) %>
<div class="copyright">
<% if(theme.site.copyright) { %>
&copy; <%= date(new Date(), 'YYYY') %> <%= config.author || config.title %>
<% } %>

<div class="publishby">
<span id="busuanzi_container_site_pv">
点击<span id="busuanzi_value_site_pv" style="font-family:Courier"></span>次,
访客<span id="busuanzi_value_site_uv" style="font-family:Courier"></span>
</span>
</div>

<!--
<div class="publishby">
<%= __('copyright.theme_by') %>
<a href="https://github.com/cofess" target="_blank"> cofess </a>
<%= __('copyright.base_on') %>
<a href="https://github.com/cofess/hexo-theme-pure" target="_blank">pure</a>.
</div>
-->
</div>
</footer>

11.2.添加网站运行时间

此部分内容参考moyu的文章为博客添加一些小功能以及美化之建站时间时间

文件位置:./themes/pure/layout/_common/footer.ejs。其实现逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<script>function siteTime(){
window.setTimeout("siteTime()", 1000);
var seconds = 1000;
var minutes = seconds * 60;
var hours = minutes * 60;
var days = hours * 24;
var years = days * 365;
var today = new Date();
var todayYear = today.getFullYear();
var todayMonth = today.getMonth()+1;
var todayDate = today.getDate();
var todayHour = today.getHours();
var todayMinute = today.getMinutes();
var todaySecond = today.getSeconds();
/* Date.UTC() -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳)
year - 作为date对象的年份,为4位年份值
month - 0-11之间的整数,做为date对象的月份
day - 1-31之间的整数,做为date对象的天数
hours - 0(午夜24点)-23之间的整数,做为date对象的小时数
minutes - 0-59之间的整数,做为date对象的分钟数
seconds - 0-59之间的整数,做为date对象的秒数
microseconds - 0-999之间的整数,做为date对象的毫秒数
*/
var t1 = Date.UTC(2020,05,19,21,20,52); //t1为建站时间
var t2 = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
var diff = t2-t1;
var diffYears = Math.floor(diff/years);
var diffDays = Math.floor((diff/days)-diffYears*365);
var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
document.getElementById("sitetime").innerHTML="已运行"+/*diffYears+" 年 "+*/diffDays+"天"+diffHours+"小时"+diffMinutes+"分钟"+diffSeconds+"秒";
// 因为建站时间还没有一年,就将之注释掉了。需要的可以取消
}
siteTime();
</script>

最后将标签<span id="sitetime"></span>添加到合适的位置,例如上文11.1节添加访问量和访客数的「访问量」和「访客数」后。

number.toString().padStart(n, '0')将数字转换为「补零字符串」,效果为m:nnn:xx:yy:zz,表示运行时间为m年nnn天xx时yy分zz秒

1
2
3
4
5
6
7
// 将「数字」转「补零字符串」
var y = diffYears.toString()
var d = diffDays.toString().padStart(3, '0')
var h = diffHours.toString().padStart(2, '0')
var m = diffMinutes.toString().padStart(2, '0')
var s = diffSeconds.toString().padStart(2, '0')
document.getElementById("sitetime").innerHTML = y + ":" + d + ":" + h + ":" + m + ":" + s;


12.代码块添加一键复制

此部分参考kajweb大佬的文章Hexo优化记录之为代码块增加复制按钮

由于kajweb大佬已写得很清楚,此处就不再赘述,主要步骤如下:

  • 1.增加全局函数addLoadEvent,注意是在文件末尾,而不是在});内;
  • 2.新增复制按钮;
  • 3.插入到页面,主题代码<%- partial('_partial/article-copy-code')%>插入的位置;
  • 4.增加语言文件,例如copy_button设置为一键复制
  • 5.修改主题配置文件,如果开启copyright则当一键复制代码后会加上content版权声明内容,个人不喜欢所以禁用了。

13.调整菜单栏高度

由于页面较多,有时候在不同的浏览器或不同分辨率电脑上会和左下角footer重叠,因此考虑调整菜单栏的高度。

此部分及下部分如何隐藏valine版权信息都需要在CSS文件添加自定义样式,特别感谢陈园园提供的帮助。

添加后有一个小bug,menu-item的高度为35pxa标签的高度为默认值41px,即会出现重叠部分,参考文章CSS设置超链接A标签宽度和高度的第一种方案,使用display: block实现自定义a标签的高度。

文件位置:./themes/pure/source/css/style.css,直接在末尾添加如下代码:

1
2
3
4
5
6
7
8
9
10
/* 调整左侧菜单栏高度 */
.menu-item{
height: 35px;
}

/* 调整a标签的高度 */
.menu-item a{
display: block;
height: 35px;
}


14.如何隐藏valine版权信息

采用Valine评论系统会在评论区右下角显示Powered By Valine v1.4.14的字样,其实是否显示都无所谓,纯粹是修改上节时的举手之劳。

同上,需要在CSS文件添加自定义样式。文件位置:./themes/pure/source/css/style.css,直接在末尾添加如下代码:

1
2
3
4
/* 隐藏valine版权信息 */
.txt-right{
display: none;
}


15.添加回到顶部

由于博文经常会有好几千字,尽管有目录能够快速跳转,但是对于长文来说「回到顶部」的功能还是很实用的。
然而Pure主题恰巧没有,因此添加一个「回到顶部」的按钮,参考文章Hexo博客搭建之回到顶部

文件位置:./themes/pure/layout/_common/script.ejs,在合适位置添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<div id="go-top"></div>
<style type="text/css">
#go-top {
width:40px;height:36px;
background-color:#DDA0DD;
position:relative;
border-radius:2px;
position:fixed;right:10px;bottom:60px;
cursor:pointer;display:none;
}
#go-top:after {
content:" ";
position:absolute;left:14px;top:14px;
border-top:2px solid #fff;border-right:2px solid #fff;
width:12px;height:12px;
transform:rotate(-45deg);
}
#go-top:hover {
background-color:#8A2BE2;
}
</style>
<script>
$(function () {
var top=$("#go-top");
$(window).scroll(function () {
($(window).scrollTop() > 300) ? top.show(300) : top.hide(200);
$("#go-top").click(function () {
$('body,html').animate({scrollTop:0});
return false();
})
});
});
</script>


16.添加RSS订阅功能

RSS简介(摘自Segmentfault用户一步的文章为hexo博客添加RSS订阅功能):

RSS(Really Simple Syndication) ,即「简易信息聚合」,在互联网上被广泛采用的内容包装和投递协。
是一种描述同步网站内容的格式,使用xml格式. 当网站内容更新时,可以通过订阅RSS源在RSS阅读器上获取更新的信息。
大多数内容提供的网站都会提供RSS订阅的功能,方便用户去获取最新的内容。

之前觉得现在这个时代RSS订阅就是一个鸡肋,所以在前面的配置中都是直接关闭了该功能,但是见过的别人的博客都有,还是觉得少了这一个功能不太好,因此重新开启。

第一步,安装插件:站点根目录执行:

1
npm install hexo-generator-feed --save

第二步,修改配置:在主题配置文件中开启rss、配置rss文件路径:

1
2
3
4
5
6
7
8
# rss
rss: true

# profile
profile:
social:
links:
rss: atom.xml


17.设置文章置顶

「博文置顶」的功能算是刚需了,但是在网上找了很多教程,都没有基于Pure主题的,尽管如此还是找到了一些思路。

此部分主要参考hexo博客优化之文章置顶+置顶标签

第一步,安装插件:站点根目录执行:

1
2
npm uninstall hexo-generator-index --save
npm install hexo-generator-index-pin-top --save

第二步,修改标题文件:其实在安装了插件之后就已经可以实现「文章置顶」功能了,但是即使文章位于顶部,如果没有置顶标志的话会比较莫名其妙就很尴尬(别问我怎么知道)。

网上文章都是定位到<div class="post-meta">标签,但是我们的Pure主题没有啊,它是<div class="article-header">,找到对应的文件是./themes/pure/layout/_partial/post/title.ejs,而不是post.xxx。分析了一下,在<h1 itemprop="name">后直接添加判断即可:如果设置了置顶,则显示一个「📌置顶」:

1
2
3
4
<h1 itemprop="name">
<% if (post.top) { %>
<span class="<%= class_name %>" style="color:#7D26CD">📌置顶</span>
<% } %>

说明:我使用的是📌emoji作为图标,如果按参考文章写的,因为不同主题使用的图标不一样,需要自行修改(详见Pure主题图标样式),不过好像没什么合适的,例如可以改成下面这样:
注意:按参考文章写的会还有一个问题,置顶标志和标题字号不一致比较突兀,所以可以使用与标题相同的class,如上class="<%= class_name %>";判断语句用<% clause %>而非{% clause %}
1
2
3
4
5
6
<h1 itemprop="name">
<% if (post.top) { %>
<i class="icon icon-map-marker"></i>
<font color=#7D26CD>置顶</font>
<span class="post-meta-divider">|</span>
<% } %>

至于进一步美化置顶,那就需要各位自己去调了~

第三步,使用置顶:在需要被置顶的文章Front-matter中添加top: truetop: 999即可,置顶排序规则为:数值越大越靠上(相同则按时间)。


18.添加文章更新时间

有时候一篇文章写完后,可能会多次修改反复更新,因此需要将「博文更新时间」也显示在文章上,然而小众主题可供参考的文章几乎没有。

找了一圈,发现Hiker主题和Pure主题几乎一模一样,于是参考了Hexo博客Hiker主题增加文章最后编辑时间并按照最后编辑时间排序。在此非常感谢Vientiane详细而清晰的修改教程,本文仅针对于自己的需求进行修改,若需更多配置,烦请移步原文。

Hiker主题和Pure主题layout结构是一致的,根据Vientiane的分析和网页HTML结构,需要修改的文件为./themes/pure/layout/_partial/post/date.ejs

data.ejs这个文件在很多地方会被引用到,可谓是牵一发而动全身啊,如果你改在这个文件上,就会发现所有原本出现发布时间的地方同时还会有更新时间,看上去真的是有点丑啊。
我不需要它在文章正文以外的部分出现更新时间,所以选择新建一个updated.ejs文件,就放在与date.ejs同级的post文件夹。

实际上,data.ejs只在「文章页」和「首页」出现,也没有出现在不该出现的地方,因此我们直接修改该文件,从而不需要新建updated.ejs文件,也不需要修改./themes/pure/layout/_partial/article.ejs

直接复制一份,对应修改为post.updateditemprop="dateUpdated",并选择合适的图标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<span class="article-date">
<i class="icon icon-calendar"></i>
<a href="<%- url_for(post.path) %>" class="<%= class_name %>">
<time datetime="<%= date_xml(post.date) %>" itemprop="datePublished">
<%= date(post.date, date_format) %>
</time>
</a>
</span>

<span class="article-date">
<i class="icon icon-calendar-check"></i>
<a href="<%- url_for(post.path) %>" class="<%= class_name %>">
<time datetime="<%= date_xml(post.updated) %>" itemprop="dateUpdated">
<%= date(post.updated, date_format) %>
</time>
</a>
</span>

到这里就已经改好了,重新生成页面就可以看到效果。以下是几点说明,自行取舍:

  • 如果在Front-matter中定义了updated,那么更新时间就是定义的那个值,否则就是.md文件的修改时间;
  • 首页文章排序规则和时间格式需要分别修改站点配置文件./_config.ymlindex_generator: order_by: -datedate_format: YYYY-MM-DD
  • 文章的「发布时间」和「更新时间」如果不加区别地放在一起,可能会让人迷惑,因此需要:
    • 通过一个有辨识度的图标来区分;
    • 在两处<time>标签前通过字段显式地区分:
      • 直接写死,例如更新于<time>···
      • 也可以<%= __('updated') %> <time>···,这种方式适应多种语言环境,因此还需到语言配置文件中增加对应字段updated: 更新于(如果没有设置则显示为标签中的值updated);
  • 如果article-meta内容过多或其他原因,只希望在「文章页」显示,则需要新建updated.ejs文件。
  • 关于「首页」和「文章页」时间格式不一致的问题:「首页」时间格式是由archive-post.ejs(默认值为date_format: 'MMM D')决定,「文章页」时间格式是由article.ejs(默认值为date_format: null)决定,这两个文件都在<xx class="article-meta">中引入了date.ejs,在date.ejs接受配置文件_config.yml中的时间格式。分析可知:

    • _config.yml中设置的时间格式仅能影响date.ejs,再传给另外两者解析;
    • archive-post.ejsarticle.ejs各自有时间解析的格式,因此导致了不同。如果在这两者中指定了date_format则按它来解析,否则用已有的值。

    由此解决方案便显而易见了:archive-post.ejs中的date_format: 'MMM D'修改为date_format: null即可。

  • 没了。

19.添加搜索引擎收录

19.1.谷歌收录

谷歌收录的操作很简单,唯一的问题就是你能否打开这串神奇的字符:
https://search.google.com/search-console

操作方法:

  • 1.登陆或注册谷歌账号,如图所示:
    注册谷歌账号
  • 2.添加资源:资源类型选择「网址前缀」【如果选择「网域」,则需要进行DNS验证,可能比较麻烦】,输入包含协议头的网址,例如https://hwame.top如图所示:
    选择资源类型
  • 3.验证所有权:可使用的方法有以下几种,如图所示:
    验证所有权
    • HTML文件——将HTML文件上传至您的网站,如图所示,这是谷歌推荐使用的验证方法,需要将googlexxx.html文件上传到网址上,对于Hexo博客而言,直接将其放在./source/文件夹下(与CNAME文件同级)即可;
      HTML文件
    • HTML标记——向您网站的首页添加元标记,如图所示,这是我使用的方法,在网页中添加元标记。
      HTML标记
      需要将Google提供的元标记粘贴至网页<head>部分。对于Hexo博客而言,可以将其添加到./themes/pure/layout/_common/head.ejs中,可以使每个页面都能被收录而不仅是首页:
      1
      2
      3
      4
      <meta name="xxx" content="xxx">
      <meta name="xxx" content="xxx">
      <!-- 谷歌收录 -->
      <meta name="google-site-verification" content="xxxxxx" />
    • 剩余三种可根据自身情况,如图所示:
      • Google Analytics(分析)——使用您的Google Analytics(分析)帐号
      • Google Tag Manager——使用您的Google跟踪代码管理器帐号
      • 域名提供商——将DNS记录与Google关联
        剩余三种验证方法
  • 4.验证完成:所有权验证完成后,如图所示:
    所有权验证完成

    说明:上述验证方式可以同时采用,以添加多种验证方法,从而避免验证状态丢失。

  • 5.效果预览:由于谷歌抓取内容需要一定的时间,所以暂时还看不到内容:
    效果预览
    等一段时间即可看到效果,如图所示:
    效果展示

19.2.百度收录

与谷歌收录相比,百度收录就麻烦多了。
第一步,注册或登陆「百度搜索资源平台」:https://ziyuan.baidu.com/login/index?u=/crawl/

第二步,添加站点,将自己博客网址添加,可设置成默认站点,如图所示:
添加站点

第三步,网站验证,站点添加以后完成验证,如图所示:
完成网站验证

第四步,资源提交,在左侧导航栏找到「资源提交」→「普通收录」进行资源的推送,推送方式包括以下四种:

  • API提交」,利用推送接口http://data.zz.baidu.com/urls?site=<yoursite>&token=<yourtoken>,结合推送示例进行结构化数据的提交,可根据自己的情况使用擅长的语言编写代码。这也是我所使用的方式,下文将详细展开。
    API提交
  • 自动推送」,自动推送仅对关联过主体的站点开放,需要在左侧导航栏依次展开「搜索展现」→「站点属性」→「基础信息」→「关联主体」,由于未使用这种方式因此不再叙述,参考【关联主体使用说明】。
    自动推送
    自动推送的js代码需要在每个HTML页面中都包含,因此可以写入到./themes/pure/layout/_common/head.ejs中:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <script>
    (function(){
    var bp = document.createElement('script');
    var curProtocol = window.location.protocol.split(':')[0];
    if (curProtocol === 'https'){
    bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
    }
    else{
    bp.src = 'http://push.zhanzhang.baidu.com/push.js';
    }
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(bp, s);
    })();
    </script>
  • sitemap」,根据百度百科的解释,站点地图可方便网站管理员通知搜索引擎他们网站上有哪些可供抓取的网页,一般为XML文件,例如atom.xml。直接将XML文件地址添加提交即可。注意图中的提示信息
    sitemap
  • 手动提交」,顾名思义即将文章链接地址手动填写并提交。注意图中的提示信息
    手动提交

19.3.API提交

主动推送的API提交可以简单借助Hexo插件,可以参考Hexo插件之百度主动提交链接,以下是自己写的。

百度提供了phpruby的推送示例,参考curl推送示例编写python代码。
整个的思路就是先用Python提取网站所有文章的链接,然后将其写入urls.txt,再写一个shell脚本执行curl命令,推送完成后删除txt文件。
Python主逻辑如下,利用爬虫抓取「归档」页面所有的文章链接放入列表,然后打印。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests
from lxml import etree
def get_article_links(site_url):
# 「归档」页提取所有文章链接
archive_url = site_url.rstrip("/") + "/archives/"
articles = []
# 第一页,若直接"/archives/page/1/"则报错404
text = requests.get(archive_url).text
html = etree.HTML(text)
data = html.xpath('/html/body/main/article/div/section/div[2]/div/div/a/@href')
articles.extend(data)
# 第二页至末尾
page = html.xpath('/html/body/main/nav/div/div')
if len(page):
for i in range(1, int(page[0].text.split('/')[-1])):
page_url = archive_url + "page/{}/".format(i + 1)
text = requests.get(page_url).text
html = etree.HTML(text)
data = html.xpath('/html/body/main/article/div/section/div[2]/div/div/a/@href')
articles.extend(data)
return list(map(lambda item: site_url + item, articles))

将打印的内容重定向到urls.txt,然后执行curl命令,主要命令如下:
1
2
3
python submit.py > urls.txt
curl -H 'Content-Type:text/plain' --data-binary @urls.txt "http://data.zz.baidu.com/urls?site=<yoursite>&token=<yourtoken>"
erase urls.txt

执行效果如图:
执行效果

说明:

此脚本适用于Windows系统,Unix系统只需将cmd的删除命令erase替换为rm -f
更简单简洁的办法是从站点地图里提取链接,去重后进行推送,这种方式不仅能推送文章,还可以推送页面;
cmdshell脚本是基于curl推送的,参考百度的post推送示例,可以只需要一个Python脚本,利用requests.post()方法,主要逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
def submit_to_baidu(articles, site, token):
# articles列表为上文get_article_links()函数的返回值
baidu_url = f"http://data.zz.baidu.com/urls?site={site}&token={token}"
headers = {"User-Agent": "curl/7.12.1",
"Host": "data.zz.baidu.com",
"Content-Type": "text/plain",
"Content-Length": "83"
}
post_url = "\n".join(articles)
res = requests.post(url=baidu_url, headers=headers, data=post_url)
return res.text

通用Python脚本点我下载来了,命令行执行python submit.py,输入参数、主站网址、token即可,如图所示:
Python脚本执行过程

19.4.收录效果

谷歌收录相对较快,大概一两天就能看到:
谷歌收录效果

百度收录就很慢了,大概需要一周的时间:
百度收录效果


上面搜索是使用关键字,所以排名比较靠后;如果精确搜索,则霸占头版,且搜索内容全部相关:
谷歌精确搜索
百度精确搜索


20.自定义图片大小

Hexo博客中原生的Markdown语法不支持设置图片大小,如果需要指定图片大小只能通过HTML语法来设置,这未免有点麻烦。那么有没有简单的办法呢?答案是肯定的:

可以通过额外的js来对![图片描述](图片地址)进行解析, 此回答参考:Hexo中扩展Markdown语法设置图片的大小

只需要在布局文件./themes/xxx/layout/layout.ejs中引入js文件即可:https://cdn.jsdelivr.net/gh/bobcn/hexo_resize_image.js@master/hexo_resize_image.js

引入位置在<body>前即可,如下所示:

1
2
<script src="https://cdn.jsdelivr.net/gh/bobcn/hexo_resize_image.js@master/hexo_resize_image.js"></script>
<body class="<%= bodyClass %>" xxx>

使用时在.md文件中插入图片时,只需要在图片地址后添加?<width>x<height>即可,具体有以下几种方式:

格式 示例 描述
?widthxheight ?400x300 同时指定宽度和高度
?widthx ?400x 指定宽度400
?xheight ?x300 指定高度300
?scale ?50 按比例缩放,示例表示50%

例如:

  • ![avatar](https://cdn.jsdelivr.net/gh/hwame/pics@main/avatar.jpg?200x200)
  • ![avatar](https://cdn.jsdelivr.net/gh/hwame/pics@main/avatar.jpg?200x)
  • ![avatar](https://cdn.jsdelivr.net/gh/hwame/pics@main/avatar.jpg?x200)
  • ![avatar](https://cdn.jsdelivr.net/gh/hwame/pics@main/avatar.jpg?80)