组织的链接。
常用功能的实现
Hexo 提供了很多专门的变量及函数,用于在编写主题时使用。请参见 变量列表和 帮助函数列表。这里针对常用的一些功能做对应的介绍。
获取站点的所有的文章、页面、标签和分类
Hexo 为主题提供了一个变量 site,这个变量包括以下几个成员: site.posts博客里的所有文章列表
site.pages所有创建的页面的列表
site.categories分类列表
site.tags标签列表
其中, site.posts与 site.pages两个结构是相同的,它们各自包括两个成员,一个 length 为长度,一个 data 为具体的数组,它是个对象,但索引是数组,成员是各个文章的详情。
site.categories和 site.tags则为两个对象,成员比较多,但具体的分类和标签列表,存在索引为 data的成员上,该成员为对象,对象的索引为分类和标签对应的 id,类似于:
"data":{ "cipap3lwj0001fhpvlubaa0sp":{ "name":"乱七八糟", "_id":"cipap3lwj0001fhpvlubaa0sp" }}
不过实际在编写主题的时候,很少会直接用到这几个变量。
获取当前页面的数据
这个变量便是 page,这个变量的特点是,在不同的页面中,它的成员会不一样。比如,在文章归档页,它就有文章列表,如果在文章详情页,它就包含有文章的相关信息。而且在不同的页面中,就算同一个索引的成员,值也会不一样,比如 page.posts,在首页,它是按分页设置限制过的文章列表,而在存档页则是所有文章的列表。
比如,在我们生成的代码中,首页里使用 includes/recent-posts.swig( 在线代码)来显示文章列表,其主要代码如下:
{% if site.posts.length > 0 %} {# ... #} {% for postItem in site.posts.toArray() %} {# ... #} {% endfor %}{% endif %}
如果你的博客已经有几篇文章得话,会发现文章虽然列出来了,但并不是按时间来排列的。所以几乎没什么用,但如果使用 page.posts变量替代 site.posts,结果就不一样了,修改一下试试。
再刷新一下首页,可以看到,文章只有几篇,并不是全部文章,且按时间倒序排列。 page的所有成员,请参见 列表。
各种链接的处理
获取某个页面的地址,有很多方法。包括: 全局的变量 path url
page.path page.permalink,这两个值在单个的文章、分类和标签中,也是都有的
我们来看看这几个值各自有何作用。打开 layout/post.swig,在第4行前插入如下代码:
{{ path | json }}
{{ url | json }}
{{ page.path | json }}
{{ page.permalink | json }}
然后启动博客,进入做任意一篇文章,可以在顶部看到三个字符串,类似于:
"2016-06/Material-Design-Float-Action-Button.html""http://chensd.com/2016-06/Material-Design-Float-Action-Button.html""2016-06/Material-Design-Float-Action-Button.html""http://chensd.com/2016-06/Material-Design-Float-Action-Button.html"
链接的具体样式,是主配置文件中 permalink来决定的,这里的配置值为 :year-:month/:title.html。可以看出来, path与 page.path输出一致, url与 page.permalink一致。而这几个链接都是无法直接使用的。因为 page.path的值是相对路径,所以除了首页都是不能直接当链接的。而 path.permalink,则是带有主配置文件中 url值配置的全路径,也不太好当作站内链接直接使用。这时候,就需要 Hexo 提供的帮助函数 url_for()来救场了。
再来加一行:
{{ url_for(page.path) | json }}
输出为:
"/2016-06/Material-Design-Float-Action-Button.html"
这个结果就比较适合作为站内链接了。
在页面中加入 css 与 js 文件
Hexo 提供了两个帮助函数 css()和 js(),传入路径数组便可生成对应的 link/ script标签。路径数组配置在主题的配置文件中。
当前页面类型的判断
由于有些代码在不同的页面都是共用的,所以有时候就需要根据不同的页面,做不同的显示。比如,一般会把 HTML 的部分写到一个单独的文件里。比如,这里生成的 layout/includes/layout.swig文件里,就需要根据不同的页面,来生成不同的 标签值。 这类判断的方法主要有: is_tag()
is_category()
is_month()存档页中的按月份文章列表页
is_year()存档页中的按年份文章列表页
is_archive()
is_post()
is_home()
is_current()传入一个 URL ,判断是否本页就是,比如,链接中要对当前页面的链接做加强显示,就可以利用这个方法来添加对应的 class
常用的字符串处理函数 strip_html()去除一段 HTML 代码中的标签,返回其包含的字符
markdown()将 md 代码转换为 HTML
word_wrap()将一段字符,按固定宽度插入换行符号
truncate()按固定长度截取字符串,比如,生成摘要时,如果没有摘要,可以截取一段文本
另外几个,请参见 字符串处理函数列表。
时间的处理
Hexo 提供了多个 时间处理函数,不过一个 date()也就够用了,接受两个参数,第一个为时间值,第二个为格式,模板引用中用法如下:
{% set thisYear = date(Date.now(), 'YYYY') %}
HTML 中用法如下:
{{ date(postItem.date, 'M-D') }}
由于是使用 Moment.js 来显示的时间,所以直接使用 Moment.js 的 时间格式就行了,常用的如下: YYYY-MM-DD=> 2016-06-17
M-D=> 6-17
HH:mm:SS=> 07:38:19
生成标签云
Hexo 提供了帮助函数 tagcloud()来生成标签云。生成的时候,可以设定标签云的文字大小范围、排序、颜色等值。具体请参见 参数列表。
以下是生成的一个标签云 HTML:
这样便可以通知设置 tag-cloud-tags的样式来自定义标签云的外观。
生成文章的目录
对于长文章,目录还是非常实用的,Hexo 也提供了 toc()来实现这一功能,具体请参见 文档。
生成的 HTML 是个有序列表,结构如下:
只要使用了 toc()函数,无论当前页面有几个标题,都会生成对应的代码。比如想当目录少于三个的时候自动隐藏,那就得靠 JavaScript 了。可以通过获取 ol.toc子成员的数量,来确定其显示或隐藏,jQuery 代码如下:
if($("ol.toc").children().length <= 3) { $(".toc").hide();}
这样当目录条数少于四条时,便自动隐藏目录。
页面的组织
代码的复用
上面我们曾经提到,对于一个主题,主要有首页、存档页、标签文章列表页、分类文章列表页、文章详情页、页面详情页这几个页面。这些页面的实现中,你会发现有大量的代码是可以共享的,比如: HTML 的 部分
页面的顶部导航
页面的底部版权和链接
各个文章列表页中的单个文章的链接(一般包括文章标题、标签、分类、时间、摘要等信息)
第三方插件代码,如评论、统计等
分页按钮
所以,对于这部分的代码,一般都会设计成可复用的代码段,将这些代码段文章存放在 includes文件夹中,如果在某个页面中需要使用,只需要使用模板引擎的 include 功能来包含。比如,我们来看看如何组织一个文章列表中的单个文章的链接,这个代码段会在存档页、标签和分类的文章列表页等地方用到,创建文件 includes/post-title-item.swig,代码如下:
{# postItem 为存有一个文章的所有信息的对象 #} {# postItem.title 为文章标题,如果没有标题,则直接截取文章内容 #} {# strip_html 是将 html 代码中提取可供普通人阅读的文字部分 #} {# trim 是去除前后空格 #} {% set postTitle = postItem.title || trim(strip_html(postItem.content)) %} {# 标题最多 80 个字符,超过得话,使用 truncate 来截取 #} {% if postTitle.length < 80 %} {{ postTitle }} {% else %} {{ truncate( postTitle, {length: 80}) }} {% endif %}
{# 显示时间 #} {{ date(postItem.date, 'M-D') }} {% if postItem.categories.length %} {# 组织分类的链接列表 #} {{ __('category_title') }} {% set i = 0 %} {% for cat in postItem.categories %} {% if i !== 0 %} {{'/'}} {% endif %} {% set i = i + 1 %} {{ cat.name }} {% endfor %} {% endif %} {# 组织标签的链接列表 #} {% if postItem.tags.length %} {{ __('tag_title') }} {% set i = 0 %} {% for tag in postItem.tags %} {% if i !== 0 %} {{'/'}} {% endif %} {% set i = i + 1 %} {{ tag.name }} {% endfor %} {% endif %} {# 有些在文章的头部指定了照片,也显示出来 #} {% if postItem.photos %}
{% set i = 0 %} {% for photo in postItem.photos %} {% set i = i + 1 %} {% if i <= 3 %} {# 这里使用了 fancybox 的一些功能,具体后面了解 #} {% endif %} {% endfor %} {% endif %}
这样,在需要使用的页面中,单个文章对象的常量名设置为 postItem便可以组织为相应的结构。比如,在标签文章列表页,可以这样组织:
{# 遍历所有文章,注意,单个文章的对象为 `postItem` #}{% for postItem in site.posts.toArray() %} {% set isShow = false %} {# 确定一下某一个文章,是否包含当前这个标签 #} {% for tag in postItem.tags %} {% if tag.name === page.tag %} {% set isShow = true %} {% endif %} {% endfor %} {# 包含就显示 #} {% if isShow %} {% include 'includes/post-title-item.swig' %} {% endif %}{% endfor %}
以上代码在 layout/tag.swig中, 在线代码。
首页
首页一般会包括一些链接和最近的几篇文章,使用的模板文章为 layout/index.swig。链接可以固定的,比如,显示首页、存档页。也可以从配置文件中读取链接列表,再予以显示。
如果要显示最近的几篇文章的列表,可以使用 page.posts中的文章列表,注意加上翻页链接。
分类列表页与分类文章列表页
分类列表页显示博客里的所有分类,分类文章列表页显示某个分类中的文章列表。
Hexo 并没有专门分类列表页的模板,那该如何处理呢?一般是写在页面模板中,即 layout/page.swig里,然后判断页面类型变量 page.type,如果是 categories,则显示分类列表页。再在博客里创建一个页面,指定其 type为 categories。实现方法如下,先来看看 layout/page.swig中的代码:
{% extends 'includes/layout.swig' %}{% block body %} {% set page_title = page.title %} {# 判断是否是分类列表页,如果是,显示对应内容 #} {% if 'categories' === page.type %}
{{ page_title || __('category_title') }} {{ list_categories() }} {# 显示普通页面的内容 #} {% else %}
{{ page_title }} {% autoescape false %}{{page.content }}{% endautoescape %} {% endif %} {% include 'includes/pagination.swig' %}{% endblock %}
要显示所有的分类,这里是使用了 list_category()来显示,也可以从 site.categories中遍历组织显示。接着,使用如下命令创建一个页面:
hexo new page categories
然后在站点的 source文件夹下,会多出来一个名为 categories的文件夹,只包括一个名为 index.md的文件,内容如下:
title: categoriesdate: 2016-06-19 10:29:23---
将其内容修改为:
title: 分类date: 2016-06-19 10:29:23type: "categories"comments: false---
这样,Hexo 在生成页面时,判断到 type为 categories,便会生成分类列表。页面的地址为 /categories/。
而对于分类文章列表页,则需要在 layout/category.swig中编辑。具体的文章列表,可以从 page.posts中取,也可以从 site.posts中取文章,再根据文章分类筛选显示。
标签列表页与标签文章列表页
这个与分类的处理类似,不做重复介绍。
归档页
归档页使用的 layout/archive.swig模板,一般是按年或按月来显示文章。Hexo 里其实有专门按年和月显示的文章列表页,从 page.posts里读取文章列表,再根据上文中提到的 is_month()/ is_year()来组织显示。
文章列表显示比较简单,单说一点,如何按年分隔来显示文章列表,当然,按月分隔显示的操作也一样。
操作方法其实比较简单,先遍历 page.posts,判断当年文章对比前一篇文章的发表年份是否变化,如果变化,则加一个年份的显示,代码实现如下:
{# 先遍历一篇文章列表,找出每年各发了多少文章,以便显示 #}{% set howMuch = {} %}{% for postItem in page.posts.toArray() %} {% set thisYear = date(postItem.date, 'YYYY') %} {% if !howMuch[thisYear] %} {% set howMuch[thisYear] = 0 %} {% endif %} {% set howMuch[thisYear] = howMuch[thisYear] + 1 %}{% endfor %}{# 开始显示, lastYear 为上一篇文章的发表年份 #}{% set lastYear %}{% for postItem in page.posts.toArray() %} {# 当前文章的发表年份 #} {% set thisYear = date(postItem.date, 'YYYY') %} {# 如果当前文章年份与上一篇不一样,则显示年份 #} {% if thisYear !== lastYear %} {% set lastYear = thisYear %}
{{ thisYear }} {# 年份后面,显示一下这年共发表了多少篇文章 #} {% if howMuch[thisYear] %} {{ __('total_title') }} {{ howMuch[thisYear] }} {% if 1 === howMuch[thisYear] %} {{ __('post_title') }} {% else %} {{ __('posts_title') }} {% endif %} {% else %} {{ __('not_post') }} {% endif %} {% endif %} {% include 'post-title-item.swig' %}{% endfor %}
图片与图片库
文章的图片放在 photos之中,在 page.photos和 post.photos中都有。Hexo 主题一般的做法是使用 FancyBox来展示图片。
两个地方可能要显示图片,一个是文章或页面的详情中, 另外一个是在各个文章列表中。
代码的显示
代码段一般是使用 highlight的样式,直接加载它的 css 就行。另外可能需要调整一下代码段的 padding和 margin,另外就是字体。具体被 highlight 处理后的代码段的 HTML 结构,请通过 Chrome 调试工具查看,这里就不列了。
除了代码段,在正文中之内还有一些代码文字,会使用 标签包裹,这个需要单独针对这个标签设置样式。比如,可以给一个浅灰的背景色,再改个字体,加个斜体等等。
代码的字体,可以 www.cssfontstack.com上找一组合适的,并且兼容 Windows / OS X 的字符,比如下面这个:
code, table .line{ font-family: Consolas, Monaco, Courier New, Lucida Console;}
主题的发布
如果你想要更多的人看到你的主题,可以考虑发布到 Hexo 官方网站的主题列表中。需要经过几个步骤来实现。
主题测试
官方提供了一个站点的示例,里面包含了多种需要考虑的可能情况。克隆 hexo-theme-unit-test,然后在这个站点里安装你的主题。并确定主题可以成功的处理如下几种类型的文章: 图片文章
无标题的文章
带摘要的文章
带视频的文章
带图库的文章
支持常用的标签,如代码块、Gist、jsFddle和引用等
标签是网址的文章
对东亚文字的支持——必然的
发布
先 Fork 官方站点, hexojs/site,然后克隆到本地,再编辑站点内 source/_data/theme.yml,增加一段如下的数据:
- name: Random description: A hexo theme with random fullscreen background image. link: https://github.com/stiekel/hexo-theme-random preview: http://hexo-theme-random.herokuapp.com/ tags: - responsive - one_column - background_image - random - iconfont - modal
然后再在 source/theme/screenshots/文件夹中放一个主题截图,尺寸为 800 * 500 ,文件名与主题名字一致。可以参考 这个图片。
其实主题制作,主要是各种细节,按你想要的样子去实现吧。
声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理