难度:⭐️
最终效果:
为了避免昂贵的服务器费用支付,我们很多人的博客选用了 github pages, 搭配 hexo 这种静态博客生成器,通过普通的 git workflow就可以很轻松地搭建自己的博客。不过,我们总觉得有点不那么酷,那就自己打造一个主题吧!
目录结构
在你的 hexo博客目录下肯定有一个 theme
目录,这里存放主题的源码,本次我的主题起名叫 hexo-theme-eleme
,查看一下结构:
.
├── _config.yml
├── languages
│ └── zh-CN.yml
├── layout
│ ├── archive.ejs
│ ├── category.ejs
│ ├── index.ejs
│ ├── layout.ejs
│ ├── page.ejs
│ ├── partials
│ ├── post.ejs
│ └── tag.ejs
└── source
├── css
├── favicon.ico
├── img
└── js
其中必需的是 _config.yml
是指主题的配置文件,languages
文件夹下存放多国语言的配置(视个人喜好而定),layout
文件夹下存放模板用于生成 HTML,source
文件夹下存放一些常用的静态资源。
技术选型
hexo 支持多种模板,此次我选用的是 EJS模板,CSS预处理选用了 stylus,语法都比较简单。
动手
1.配置静态资源
layout.ejs 是整个页面的入口,所有的页面都基于 layout.ejs生成,区分页面的方法是使用 hexo 内置函数,相关文档可以在 hexo.io找到。我们首先需要引入 css和 js,在HTML 头部:
<% if (theme.stylesheets !== undefined && theme.stylesheets.length > 0) { %>
<!-- stylesheets list from config.yml -->
<% theme.stylesheets.forEach(function(url) { %>
<link rel="stylesheet" href="<%=url_for(url)%>">
<% }); %>
<% } %>
CSS的 url我配置在了 _config.yml
:
# stylesheets loaded in the <head>
stylesheets:
- /css/eleme-theme.css
这个路径其实就是 source/css/eleme-theme.styl
, hexo生成的时候会自动帮你预处理 stylus文件。 url_for()
是 hexo内置函数,帮助你找到站内资源的 url。
需要区分 theme的 _config.yml 和 hexo 的 _config.yml
javascript同理,不过我把它放在了 body
底部载入。
2.header 和 footer
头部和脚部在所有页面都是公用的,所以直接放在 layout.ejs中。菜单配置在 _config.yml中,直接遍历一下:
<% Object.keys(theme.menu).forEach(function(key) { %>
<a href="<%=url_for(theme.menu[key])%>"><%=_p(key)%></a>
<% }); %>
url_for()
函数前面有提及,_p()
函数是另一个内置函数,根据 key获取对应的多语言字符串。如果不使用多语言,这里直接就用<%=key%>
就可以了。
footer同理,就不再赘述了。所有的博客内容都是一个 hexo的 body变量,直接通过<%-body%>
放在页面中。这个 body是 hexo根据不同页面的模板渲染的 html。
3.index
index 页面包括一个文章列表和一个分页:
<%-partial('partials/recent-posts')%>
<%-partial('partials/pagination')%>
分页组件在其他页面也有用到,所以组件需要分开。列表页面比较容易做,hexo 的 context中可以通过 site.posts
拿到所有文章,遍历输出标题等信息就好了。分页组件相对不那么好做一点,不过也可以从 context中拿到 page变量。
<% if (typeof page.current === 'number' && typeof page.total === 'number') { %>
<p class="page-number">
第<%=page.current%>/<%=page.total%>页
</p>
<% } %>
4.文章和其他页面
参考上面的代码可以发现,其实大部分的操作都要基于 hexo的内置变量,比如拿到 post后可以输出 post的标题,作者,内容等,hexo都会帮我们正确地嵌套到最终的 layout.ejs中生成正确的 HTML。
5.stylus与 CSS
HTML 输出后我们可以使用 CSS美化页面,CSS是全局的,只要通过编写 stylus就可以预处理输出了。stylus 可以定义变量,像编程一样写 CSS,比如我定义一些变量在 values.styl中:
// Config
support-for-ie = false
vendor-prefixes = webkit moz ms official
//Font
font-sans = -apple-system, BlinkMacSystemFont,
"Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell",
"Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif
// Colors
eleme-blue = #3190e8
eleme-orange = #ff6000
eleme-red = #d83f34
然后在 eleme-theme.styl中:
@import values
就可以使用了,stylus 语法写起来也有点意思,缩进什么的比较像 python:
body
background: eleme-background-light !important
margin: 0 auto !important
max-width: eleme-max-width
font-family: font-sans
height: 100%
overflow-x: hidden
6.配置评论系统
评论通常放在一篇博文底部,我选用了 Disqus:
<% if(theme.comment) {%>
<div id="disqus_thread"></div>
<script type="text/javascript">
var disqus_shortname = '<%=theme.disqus_shortname%>';
var disqus_identifier = '<%=page.path%>';
var disqus_title = '<%=page.title%>';
var disqus_url = '<%=page.permalink%>';
function run_disqus_script(disqus_script){
var dsq = document.createElement('script');
dsq.type = 'text/javascript';
dsq.async = true;
dsq.src = '//' + disqus_shortname + '.disqus.com/' + disqus_script;
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
}
run_disqus_script('count.js');
<% if(page.comments) {%>
run_disqus_script('embed.js');
<%}%>
</script>
<noscript>Please enable JavaScript to view the comments</noscript>
<% } %>
然后在 _config.yml中添加字段:
comment: true
disqus_shortname: your_short_name
使用主题
把主题文件夹放到 hexo源文件的 theme文件夹下,更改 hexo的主题为 hexo-theme-eleme
,运行 hexo s
就可以看到了。
做出一个漂亮的主题可能需要一点点 UED的帮助吧 :)
-EOF-