Hexo 主题开发

去年就开始说要更新博客主题了,拖到现在终于有点空闲时间和动力了,相信大家已经使用过 Hexo 了,安装之类的我都不多废话了,直接开始。

想要自定义一个 Hexo 主题大概需要了解一个 模板引擎,Hexo 内置了 Swig,我所用的是默认安装的 EJS,反正都差不多,都提供了一些模板语法,书写还是按照Js的方法来的。
然后先按照文档创建完主体目录结构和模板组件,就可以开始开发了,我比较偷懒没有使用 yeoman + generator-hexo-theme 来创建,直接复制了原先的 landscape 主题。

哦,对了!还要选择一个CSS预编译器,我还是没有选择适用了默认安装的 Stylus,你也可以按照习惯去安装,并且 install 对应的 Hexo 插件。

# Templates
$ npm install --save hexo-renderer-ejs
$ npm install --save hexo-renderer-pug
$ npm install --save hexo-renderer-haml

# Styles
$ npm install --save hexo-renderer-less
$ npm install --save hexo-renderer-sass
$ npm install --save hexo-renderer-stylus

然后不需要配置,Hexo 会自动按照文件后缀名使用对应的拓展编译文件。

📚 前置学习

以上四个文档希望你可以阅读完,特别是辅助函数,会在制作过程中反复用到,也是最关键的部分,我相信大家已经对 [html, css, js] 三剑客很熟悉了,所以就不提他们了。

完整目录如下:

│
├─ layout    # 布局文件夹
│   ├─ partials  # 局部模版
│   │   └─ recent-posts.ejs # 列表页文章Item
│   ├─ index.ejs      # 首页模板
│   ├─ layout.ejs     # html结构
│   ├─ post.ejs       # 文章列表模板
│   ├─ archive.ejs    # 归档列表模板
│   ├─ category.ejs   # 分类归档列表模板
│   ├─ tag.ejs        # 标签归档列表模板
│   └─ page.ejs       # 单页模板
│
├─ scripts  # 脚本文件夹
│
├─ source   # 资源文件夹
│   ├─ css
│   ├─ js
│   └─ favicon.ico
│
├─ .editorconfig  # 编辑器配置文件
├─ _config.yml    # 主题配置文件
└─ package.json   # 项目包管理文件

Part1. 主题模板开发

首先会想到要着手的肯定是首页,但是直接开发首页肯定是不行的,还需要先把网页的结构搭完,好比现在 SPA 项目的 index.html 文件。
那么就会先就需要调整 layout.ejs 这个模板文件,打开的话,可以看到一个简单的 html 结构,这个时候就是需要按照自己的想法来搭建主题的公共部分了,
比如说 页首页尾,然后使用 <%- partial(path, [locals], [option]) %> 来引入组件 locals和option的可接收参数文档
我把 meta 信息也提取成部件了,完成大概是这样的结构。

<!-- layout page -->
<!DOCTYPE html>
<html lang="<%= config.language =>">
  <%- partial('_partial/meta') %>
  <body>
    <%- partial('_partial/header', null, {cache: true}) %>
    <div id="wrap">
      <%- body %><!-- body变量,用于输出页面内容 -->
    </div>
    <%- partial('_partial/footer', null, {cache: true}) %>
  </body>
</html>

然后开始编辑 index.ejs 这个文件,开始可以按照自己的喜好编辑首页了,记得使用 hexo s 命令开打开发模式查看效果。
我是顺着上一版本的主页,只是展示文章,所以直接把文章卡片抽成组件了,从 page.posts 接收到文章列表,使用 forEach() 循环出列表,然后使用 paginator()函数 把分页组件也写好了

呃….好像也没有什么好说的,就是和过去 CMS 时代用模板语法来写 template 那样,只是以前是嵌入 php 的代码然后用 php 来执行渲染,而 Hexo 是用 JS 来编译成静态文件。

我这边大概完成主题之后的目录结构如下:

layout
 ├─_partial                    # 小部件
 │    │  archive.ejs             # 文章分类列表组件
 │    │  archive_post.ejs        # 列表页文章卡片组件
 │    │  article.ejs             # 文章详情组件
 │    │  footer.ejs              # 页尾组件
 │    │  header.ejs              # 页头组件
 │    │  meta.ejs                # meta组件
 │    │  sidebar.ejs             # 侧边栏组件
 │    │  soliloquy.ejs           # 关于我组件
 │    │  
 │    ├─_post                  # 文章组件
 │    │      article_body.ejs     # 文章内容部件
 │    │      category.ejs        # 文章分类部件
 │    │      date.ejs            # 文章日期部件
 │    │      nav.ejs             # 文章详情分页部件
 │    │      tag.ejs             # 文章标签部件
 │    │      title.ejs           # 文章标题部件
 │    │      
 │    └─_widget                # 侧边栏卡片组件
 │            archive.ejs        # 文章归档卡片
 │            author.ejs         # 个人信息卡片
 │            category.ejs       # 文章分类卡片
 │            recent_posts.ejs   # 最近发布卡片
 │            shortcut_menu.ejs  # 快捷分类菜单卡片
 │            tag.ejs            # 标签列表卡片
 │            tag_cloud.ejs       # 标签云卡片
 │ 
 │  about.ejs         # 关于我模板
 │  archive.ejs       # 文章列表模板
 │  category.ejs      # 分类列表模板
 │  index.ejs         # 主页
 │  layout.ejs        # 布局模板
 │  page.ejs          # 单页模板
 │  post.ejs          # 文章详情模板
 └─ tag.ejs           # 标签页模板

需要注意的是一些默认的模板名称,hexo 会自动去寻找这些模板来生成对应的页面。模板文档 - Hexo

模板名 用途 回退
layout 布局 -
index 首页 -
post 文章 index
page 分页 index
archive 归档 index
category 分类归档 archive
tag 标签归档 archive

所以你的主题目录:

  1. 应包含一个 index 模板
  2. 如果要使用 layout 组件,必须要使用 <%- body %> 输出模板的内容。

Part2. 配置文件设置

在开发主题的时候你会遇到一些属性可能全局会用到,比如说头部导航,页尾配置,侧边栏卡片显隐等,就可以配置 _config.yml 文件来实现全局变量 文档

Hexo的配置文件分为 站点配置文件主题配置文件,分别位于 项目根目录主题根目录 下。

一般来说,全局的一些配置项需要放到 站点配置文件 中,比如说:站点配置,静态页面生成规则,插件配置等,然后通过 config.xxx 来获取&使用。
和主题有关的配置则放到 主题配置文件 中,比如:侧边栏开关,社交账户信息,头部导航等控制主题内容的部分,通过 theme.xxx 来使用。

我的想法是尽量减少对于站点配置文件的控制,能放到主题配置文件中的就放到主题配置文件中。

🎉 尾声

基本上关于主题开发的内容就那么多,整体来说只要你懂一些三剑客的基础很容易就可以自己开发出一个主题,只是有一些犄角旮旯需要你去查文档,有一些说明并不明显,需要耐心的从文档中检索出来。

如果需要发布到 Hexo 上,还需要通过 主题单元测试,确保每一项功能都能正常使用,发布步骤见文档

如果需要发布你的主题,那么我会在另一篇文章中来记录。我先挖一个坑,因为自己制作完主题之后还没有按照文档规范走完测试流程。


遇到的问题

# 使用 is_current(path) 判断生成的 ‘active’ 类不会在对应分类添加,只会执行一次
查看引入的部件 <%- partial('partial/xxx',{ cache: <Boolean> }) %> 部分是否开启了缓存 👉 模版 | Hexo

# orderby 有哪些可选参数?

  • name 名称
  • length 文章数
  • random 随机排列

# 空白主题不支持 markdowntable 语法/看不到表格
因为没有设置 <table> 的样式,自己使用CSS写一个表格样式就好。

# 使用 hexo-prism-plugin 进行代码高亮处理,但是在列表页的预览内容中的代码块不会被处理
其实会被处理,只是我在用 hexo-theme-unit-test 测试的时候有使用 代码块标签插件 的测试文章,类似这样:

{% codeblock lang:js mark:1,7-8,10 %}
const http = require('http');

const hostname = '127.0.0.1';
const port = 1337;

http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
}).listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
{% endcodeblock %}

需要开启 prismjs,默认是关闭的,在 _config.yml 中开启即可。

资源