诗与远方

Hexo主题的数据封装,样式渲染和扩展实例

前言

Hexo的优化,网上有很多不错的文章,我就不写了。之前自己练习用LAMP(Linux Aphach Mysql Php)架构开发类似phpMyAdmin的线上数据库录入维护面板,实践过数据,功能,样式的分离和封装。当时印象很深刻,感叹原来一个网站不是像我学计算机之前想象的那样都是一张张简单的html静态页面。但时间久了,细节有点模糊了。这次趁搭博客,正好复习一下。

但网上搜了一下,分析Hexo NexT主题具体结构的帖子几乎没有。想要扩展的童鞋,一下子可能未必能搞清楚主题包里每个文件都是干啥的。我只好把今天做的练习贴上来,相信这个对NexT主题的小手术,对理解一个网站具体每部分是怎么渲染出来,然后组合到一起还是有点帮助,也方便自己以后回顾。

此文要大力感谢Wu Chong童鞋的文章。是我在网上找到的唯一一篇DIY扩展Hexo主题靠谱的文章。

Hexo主题结构

前言里说过了,小时候傻,以为网站就是由一万个单独html页面组成的,然后大家互相链接。知道学了计算机,自己动手造轮子,才知道被骗了。

数据

其实简单说,网页其实就是一堆乱七八糟的数据。
最简单的看看 /hexo/scaffolds/post.md/ 模板就知道了。

1
2
3
4
5
title: {{ title }}
author:
date: {{ date }}
categories:
tags:

其中title,author,date,categories,tags,每一个都会被封装成post大数据流中的一个字段。要用的时候,只要调用post.title,或post.tags就能用。
而且一篇文章实际生成的字段比我们看到的要多得多。
dataTable
数据抽象出来的好处,就是为了动态和复用。形象地说,就是数据和样式剥离,让数据管数据,样式管样式。尤其hexo这种没有后台数据库的网站框架,数据更要收拾好。这样网站开发起来,程序猿哥哥就只管数据和功能的实现,UI妹纸可以专心地设计好看的外观了。

布局和样式

然后呢这些数据被以一种”性感”的姿势展示出来。这”性感”的姿势就取决于排版和样式了。所以整个/hexo/themes/next/主题文件夹下的东西,iissnan童鞋都在定义什么是”性感的姿势”。

1
2
3
4
5
├── _config.yml
├── languages
├── layout
├── scripts
└── source
  • layout: 布局文件夹,模板都在里面。框框,图片,文本怎么组合。核心。
  • scripts: javascript脚本文件。
  • source: 除了模板之外其他的Asset。最重要的就是CSS样式。

说到布局,现在大家都不可能傻傻地一个个写html静态页面,基本都是javascript动态生成的。现在一般都用”模板“来实现了,然后用模板引擎”翻译”成html内容。说地好听点叫”渲染“。

NexT主题用的就是”swig“JS模板引擎。swig是个好同志,语法简单,嵌入式开发,大家一直用它。我这里搬砖她主页上一段小代码,一眼就能看明白swig是怎么把数据动态排版成一个页面的。

1. 创建模板:嵌入式,HTML标记,控制流,数据,都在一起。swig其实就是一个语法解释器,会把各部分都识别出来,然后重新组合。这里有一篇小胡子哥的文章,挺深入浅出。

1
2
3
4
5
6
7
8
<h1>{{ pagename|title }}</h1>
<ul>
{% for author in authors %}
<li{% if loop.first %} class="first"{% endif %}>
{{ author }}
</li>
{% endfor %}
</ul>

2. 渲染模板:调用模板,给进数据。

1
2
3
4
5
var swig = require('swig');
swig.renderFile('/path/to/template.html', {
pagename: 'awesome people',
authors: ['Paul', 'Jim', 'Jane']
});

3. 输出页面:数据就以我们预设的方式,被填进模板里。

1
2
3
4
5
6
<h1>Awesome People</h1>
<ul>
<li class="first">Paul</li>
<li>Jim</li>
<li>Jane</li>
</ul>

小练习

现在我们就通过对NexT主题做个小手术,来练练手。

before
上图是首页上一篇博文的摘要,通过点击标题或者more按钮大家可以阅读全文。问题是有点单调是不是?大家喜欢看图,为什么不给每篇文章选一张Logo图片呢。那好,我们就试着在标题和摘要中间,插进一张Logo图片。

数据部分:图片地址

说过了要把数据收拾好,手动写进文件里是很low的事,要让swig自动帮我们生成。所以我们可以把数据放到post模板的front-matter部分。hexo/scaffolds/post.md的front-matter长这样。我们加一个images字段(可以为空),用来存放图片地址。以后每篇新post模板生成都会带images字段。我们填的图片地址就会一直作为文章的一个属性被传递,用post.images调用。

1
2
3
4
5
6
title: {{ title }}
author:
date: {{ date }}
categories:
tags:
images: "/uploads/insertImg/after2.png"

css样式

hexo/themes/next/source/css/: 是next主题的样式文件,决定主题的外观。
hexo/themes/next/source/css/main.styl:汇总css文件夹中所有的样式。
hexo/themes/next/source/css/_custom/custom.styl:是空的,专门让开发者扩展。我们就要在custom.styl里为我们的图片设计一个专用容器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//主力图片外部的容器方框
.out-img-topic {
display: block;
max-height:300px;
margin-bottom: 24px;
overflow: hidden;
}
//主力图片
img.img-topic {
display: block ;
margin-left: .7em;
margin-right: .7em;
padding: 0;
float: right;
clear: right;
}

这里图片外部的容器用来限制图片显示的大小,最大的高度为300px,overflow: hidden;让多余部分隐藏。margin-bottom: 24px;确保图片和文章摘要部分空出一定空间。

渲染

Hexo里规定了,hexo/themes/next/layout/index.swig负责每个index页面的渲染工作。而其中正文部分,引用的是 hexo/themes/next/layout/_macro/post.swig

其中我们找到了下面这段代码,是对首页折叠文章摘要的渲染代码。 第2行if post.images里面的代码是我插入的。post是每一个post.md里整个数据流,包括front-matter。post.images是我加的images字段,也就是图片地址。class部分调用我们在custom.styl里定义的图片框。后面post.excerpt是插入文章摘要的地方,我们就是把图片插在标题和摘要之间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{% if is_index %}
{% if post.images %}
<div class="out-img-topic">
<img src={{ post.images }} class="img-topic">
</div>
{% endif %}
{% if post.description %}
{{ post.description }}
<div class="post-more-link text-center">
<a class="btn" href="{{ url_for(post.path) }}">
{{ __('post.read_more') }} &raquo;
</a>
</div>
{% elif post.excerpt %}
{{ post.excerpt }}
<div class="post-more-link text-center">
<a class="btn" href="{{ url_for(post.path) }}{% if theme.scroll_to_more %}#more{% endif %}" rel="contents">
{{ __('post.read_more') }} &raquo;
</a>
</div>

最后的效果

after1
after2

大功告成,收工!

此文转自沈玮的博客