这里是我写的主题toki以及预览。 欢迎star,我的简历,如果您有各厂内推的机会,不妨考虑我,致谢?!
Hexo是一个知名的静态博客生成工具,尤其在github用户中广为人知。hexo的主题可以自由变换,但是想要找到一个完全合自己心意的主题仿佛大海捞针。与其不停寻找,不如自己动手制作一个主题,既解决了自己看什么主题都不合心的问题,还能在其中学习更多知识。
这里是我写的主题toki以及预览。如果你觉得这篇文章对你起到了一点作用,欢迎你star或者fork进行进一步的学习,不必担心难度,因为这也是我第一个hexo主题。
hexo主题结构
目录结构如下:
.
├── _config.yml
├── layout
│ └── _partial
└── source
├── css
├── fonts
└── js
其中config文件是存储与主题相关的变量,如点赞、评论功能是否开启,在整个站点下也有一个config文件,它是用来存储一些和整个站点有关的,比如站点的标题。而并非所有的hexo主题都支持点赞,所以点赞功能的开启放在具体的theme下更合适。
Layout文件夹下存放的是布局模板文件,可以用ejs、jade等编写,里边包含index、post等hexo中默认使用的模板,也可以编写一个自己额外定义的页面,比如about页。对于这些自己额外编写的模板,需要用户自己执行hexo new [layout] <title>
中声明layout:about
才可以。_partial子文件夹中存放的是一些可以服用的组件或者想要细分的部分,如打赏部分、点赞部分,可以分离出来,使得结构更加清晰明了。
Source文件夹下存放的是资源文件,比如css文件,字体文件,图片文件等。source文件在最后生成的时候会把其中的文件都直接放在根目录下,所以在文件中引用地址的时候不需要写source
,而是直接写./css/app.css
就可以。
hexo变量和函数
想要编写一个hexo模板,我们在其中必定要添加一些hexo站点下的信息,如网站的title。还有我们之前提到的主题下也有一个config文件,其中的变量我们也需要调用。除了以上两个部分,hexo还提供了一些用来简化操作的辅助函数。
具体的变量和辅助函数可以访问hexo官网。这里只介绍一些常用的。
变量:
- page.title
- site.posts
- page.excerpt
关于整个站点下的config文件需要通过config.xxx来进行调用,对于这个主题的config文件需要通过theme.xxx来调用。而诸如page、site等就是hexo自身的一些变量了。
函数:
- <%- list_categories([options]) %>
- <%- titlecase(string) %>
模板文件
Hexo已经定义的模板文件有以下几个:
- index
- post
- page
- archive
- category
- tag
特别的还有一个layout文件,可以在layout文件中编写一些公共部分,实现在其他页面中的复用,如果你对模板引擎并不了解,我建议你先学习相关知识是非常必要的,不过不用太多,花十几分钟大概理解一下就可以。
当然你并不需要都要包括这些模板,只是写了这些模板文件后,你不需要hexo new
它,它也有固定的页面地址。每个主题最少可以只包括一个index页面即可。但是为了功能上比较完善,我还是建议最少编写index、post、archive这三个页面。
在hexo中编写文件,需要选择一种模板引擎,这里我使用的ejs,hexo自己提供的ejs的支持,而且理解起来也很容易,没什么选择其他的理由。当然如果你想要编写的主题比较庞大,那还是选择自己最顺手的好。
我们分别讲解index、post、archive的编写,然后在进行拓展。
layout页面
这一页要包含菜单、页脚声明。
<!DOCTYPE html>
<html lang="en">
<head>
<title><%= config.title %></title>
<!-- 引入站点的标题-->
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<%- css('./css/app.css') %>
<!-- 这里的css 就是一个辅助函数-->
</head>
<body>
<%- partial('_partial/header') %>
<!-- 引入其他部分-->
<main>
<%- body %>
<!-- 这里会将其他页面的内容填充进来组成一个完整的页面 -->
</main>
<%- partial('_partial/footer') %>
</body>
</html>
index页面
显然的,这是我们进入网站看到的第一个页面,一般来说,这个页面要包含最近的文章展示,根据个人喜好,也可以添加标签云、最新评论等。
<section class="posts">
<% page.posts.each(function (post) { %>
<article class="post">
<h1>
<a class="title" href="<%- url_for(post.path) %>">
<%= post.title %>
</a>
</h1>
<%- partial('_partial/meta',{page:post}) %>
<div class="content">
<% if(post.excerpt) {%>
<%- post.excerpt %>
<%} else{ %>
<%- post.content %>
<% } %>
</div>
<div class="continue">
<a href="<%- url_for(post.path) %>">
<%- __('Post.Continue') -%>
<i class="fa fa-angle-right" aria-hidden="true"></i>
</a>
</div>
</article>
<% }) %>
</section>
<%- partial('_partial/paginator') %>
这个页面看起来要复杂了许多。我们从大到小入手:通过page.posts我们获取到了文章列表,对于其中的post,又有title、tag、category等量。content四获取文章的内容,而excerpt是用来获取摘要。如果在书写markdown 文章时加入<!-- more -->
那么在这之前的内容将会被视为摘要,如果你懒得做,也可以使用自动生成摘要的插件。<%- partial('_partial/meta',{page:post}) %>
这段代码中比layout页面中的引入要多出了一个参数,这里是将meta这个页面中的page都赋值为post。主要是用来进行参数传递作用,这里是因为meta不仅在主页要用,在文章页也要使用,而文章页中我们时通过page.tags来取得内容的。<%- __('Post.Continue') -%>
这个写法看起来有些奇怪,它也是一个辅助函数吗?虽然在hexo的文档中没有把它明确为一个辅助函数,但实际上这确实是一个函数,它的作用是进行站点国际化。听起来很高大上吧!不过其实实现很简单,在上述的项目结构中我们还可以增加一个language目录,其中针对每一种语言增加一个yml文件,把需要国际化的量储存在里边,根据整个站点config中的language声明的语言而进行动态调整。比如,我们在en.yml 将Continue声明为continue,在zh-CN.yml中声明为继续阅读。<%- partial('_partial/paginator') %>
这里我们引入了一个paginator组件,它是用来分页的,跟普通的分页不同,hexo中分页的实际工作我们丝毫没有涉及,只需要简单地使用辅助函数就可以:
<%- paginator({
prev_text: "« "+ __('Paginator.Prev'),
next_text: __('Paginator.Next')+" »"
}) %>
post页面
有了前面两个页面的基础,这里就不废话了。
<article class="post">
<h1>
<a class="title" href="<%- url_for(page.path) %>">
<%= page.title %>
</a>
</h1>
<%- partial('_partial/meta') %>
<%- partial('_partial/toc') %>
<div class="content">
<%- page.content %>
</div>
<%- partial('_partial/copyright') %>
</article>
archive页面
<section class="archive">
<ul class="post-archive">
<% var last = 1997 %>
<% page.posts.each(function (post) { %>
<% if (last != post.date.year()){ %>
<span class="year"> <a><%=post.date.year()%></a></span>
<% last = post.date.year()%>
<%}%>
<li class="post-item">
<span class="date"><%= date(post.date, "MM-DD") %></span>
<a class="title" href="<%- url_for(post.path) %>"><%= post.title %></a>
</li>
<% }) %>
</ul>
</section>
<%- partial('_partial/paginator') %>
对这个页面,我们只讲解一下<% var last = 1997 %>
,这里参考了hexo自带主题landscape的方案。为了实现按照不同年份归档,先定义一个很小的年份值,如果以后的年份不同于之前的值,那就把last置为它,并且显示一个较大的年份块。
添加样式
这里我们选用的是stylus来书写css,选择它的原因也很简单,因为hexo自带。
这里已经没什么需要额外讲解的了,css总不会也跟其他的有不同吧。只是请注意,为了保证你的主题能够被更多人使用,请务必做好不同浏览器的兼容。类似地,你也应该在配置文件中增加更多的自定义开关,你不能默认认为用户总是想向你提供两个打赏的二维码,所以一个二维码的样式呢?或者索性不想要打赏呢?
提交主题
经历了以上这些,你的主题已经基本具有可用性了,但是如何让更多人知道并且使用你的主题呢?你可以通过在各种技术型社区发帖,也可以发动身边的人使用。更官方的方案,是向hexo提交自己的主题。你具体可以参考这里主题| Hexo。准备好一份截图,fork一份hexojs/site添加自己的主题信息和截图后再向官方提出pull request请求,不必担心,因为他们真的很友善。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。