By烟花易冷

Hexo模板主题开发 入门念叨
2016-07-04

在主机测评群中,貌似好几个大牛都对Hexo博客挺感兴趣,也确实,hexo这种方式占用VPS资源极少,并且门槛低,甚至可以运行于github等代码托管平台。但是,从目前寻找到的资料来看,Hexo主题开发没有wordperss和typecho的那么简单,可以来一段我初步收集到的资料吧。

庆祝的话已经说的差不多了,下面来讲一讲如何开发一个Hexo主题。

结构

主题结构

Hexo主题的结构大体如下:

.
├── _config.yml
├── languages
│   ├── default.yml
│   └── zh-Hans.yml
├── layout
│   ├── achieve.swig
│   ├── category.swig
│   ├── index.swig
│   ├── _layout.swig
│   ├── page.swig
│   ├── _partials
│   ├── post.swig
│   └── tag.swig
└── source
    ├── css
    ├── fonts
    ├── img
    ├── js
    └── vendors

首先有一个 _config.yml 负责提供主题级别的配置,可以在 layout 中通过theme.xxx 的形式进行调用。

然后 languages 负责实现博客的i18N功能,如果博客没有多语言的需求,只需要实现一个 default.yml 即可。

其次是最为重要的 layout 文件夹,这个里面主要存放博客的结构,Hexo 引擎会使用指定的渲染引擎将 layout 文件渲染成HTML页面。

最后是 source ,把所有主题需要用到的资源,比如CSS,Fonts,JS等都存放到这个文件夹中。

这个主题使用了 swig

页面结构

页面结构分为两个维度,一者是我要呈现哪些页面,二者是每个页面上都有哪些内容。

哪些页面?

作为一个博客,主要需要的页面有以下这些:

  • 主页
  • 单页
  • 归档页面
  • 分类页面
  • 标签页面
  • 文章页

哪些内容?

如果没有什么特别的设计,博客的页面大体上可以分为这几个部分:

  • head:头部文件
  • body:主体内容
    • header:题图,导航栏等
    • content: 内容
    • footer:尾部的联系方式等

实现

前面讲到了 Hexo 的结构,下面来聊一聊具体的实现。

原理

Hexo 渲染的入口是 _layout.swig ,所以一个主题至少需要实现一个_layout.swig

然后Hexo会遍历Hexo目录下 source 文件夹中的所有Markdown文件,根据Markdown文件所指定的layout进行渲染,默认类型为 post

技巧

_layout.swig结构

整体的结构基本如下:

<!doctype html>
<html>
<head>
    {% include '_partials/head.swig' %}
    <title>{% block title %}{% endblock %}</title>
</head>
<body id="home">
    {% include '_partials/menu.swig' %}
    <div id="wrap">
        {% include '_partials/nav.swig' %}
        {% include '_partials/header.swig' %}
        <div id="start" class="container content">
            {% block content %}{% endblock %}
        </div>
        {% include '_partials/footer.swig' %}
    </div>
</body>
</html>

实现文章渲染

这个地方主要是借鉴了NexT主题的设计,实现了一个swig的宏来生成对应的文章。这个宏主要有两个参数,第一个是post对象,第二个是是否为主页。如果是主页就只显示简略的内容,如果不是就输出全文。

判断的部分实现如下:

{% if is_index %}
    {% if post.excerpt %}
        {{ post.excerpt }}
        <a class="" href="{{ url_for(post.path) }}">Read more</a>
    {% endif %}
{% else %}
    {{ post.content }}
{% endif %}

用到的post页的参数可以 我翻译的中文文档

分页插件

Hexo 自己实现了一个分页插件,直接使用paginator函数即可。

{% if page.prev or page.next %}
    <nav class="pagination">
        {{ paginator({
            prev_text: '<i class="fa fa-angle-left"></i>',
            next_text: '<i class="fa fa-angle-right"></i>',
            mid_size: 1
        }) }}
    </nav>
{% endif %}

评论系统

对于Hexo来说,评论系统就是调用一个第三方的JS。所以只需要在合适的位置插入代码即可。

<div id="disqus_thread"></div>
<script>
    var disqus_config = function () {
        this.page.url = '{{ page.permalink }}';
        this.page.identifier = '{{ page.path }}';
    };
    (function () {
        var d = document, s = d.createElement('script');
        s.src = '//abc.disqus.com/embed.js';
        s.setAttribute('data-timestamp', +new Date());
        (d.head || d.body).appendChild(s);
    })();
</script>