本文续接 Hexo 文档讲解篇
Yelee主题介绍
更换主题
创建 Hexo 主题非常容易,您只要在 themes 文件夹内,新增一个任意名称的文件夹,并修改 _config.yml 内的 theme 设定,即可切换主题。一个主题可能会有以下的结构:
.
├── _config.yml //这个是主题配置项文件
├── languages //这个是语言文件
├── layout //这个是模板文件
├── scripts
└── source
盛年不重来,一日难再晨。及时当勉励,岁月不待人
-
Layout
布局文件夹。用于存放主题的模板文件,决定了网站内容的呈现方式,Hexo 内建 Swig 模板引擎,您可以另外安装插件来获得 `EJS`、`Haml` 或 `Jade` 支持,Hexo 根据模板文件的扩展名来决定所使用的模板引擎,例如:
layout.ejs - 使用 EJS layout.swig - 使用 Swig
yelle主题采用的是EJS模板,EJS模板可以参考 ejs中文文档
-
source
资源文件夹,除了模板以外的 Asset,例如 CSS、JavaScript 文件等,都应该放在这个文件夹中。文件或文件夹开头名称为 _(下划线线)或隐藏的文件会被忽略。
如果文件可以被渲染的话,会经过解析然后储存到 public 文件夹,否则会直接拷贝到 public 文件夹。
模板
模板决定了网站内容的呈现方式,每个主题至少都应包含一个 index 模板,以下是各页面相对应的模板名称:
模板 | 用途 | 回调 |
---|---|---|
index | 首页 | |
post | 文章 | index |
page | 分页 | index |
archive | 归档 | index |
category | 分类归档 | archive |
tag | 标签归档 | archive |
布局
如果页面结构类似,例如两个模板都有页首(Header)和页脚(Footer),您可考虑通过「布局」让两个模板共享相同的结构。一个布局文件必须要能显示 body 变量的内容,如此一来模板的内容才会被显示,举例来说:
{% codeblock index,ejs %}
index
{% endcodeblock %}
{% codeblock layout.ejs %}
{% endcodeblock %}
生成 :
index
每个模板都默认使用 layout 布局,您可在 front-matter 指定其他布局,或是设为 false 来关闭布局功能,您甚至可在布局中再使用其他布局来建立嵌套布局。
局部模板
局部模板让您在不同模板之间共享相同的组件,例如页首(Header)、页脚(Footer)或侧边栏(Sidebar)等,可利用局部模板功能分割为个别文件,让维护更加便利。举例来说:
{% codeblock partial/header.ejs %}
<%= config.title %>
{% endcodeblock %}
{% codeblock index.ejs %}
<%- partial('partial/header') %>
{% endcodeblock %}
生成:
My Site
Home page
局部变量
您可以在局部模板中指定局部变量并使用。
{% codeblock partial/header.ejs %}
<%= title>
{% endcodeblock %}
{% codeblock index.ejs %}
<%- partial('partial/header', {title: 'Hello World'}) %>
{% endcodeblock %}
生成:
Hello World
Home page
优化
如果您的主题太过于复杂,或是需要生成的文件量太过于庞大,可能会大幅降低性能,除了简化主题外,您可以考虑 Hexo 2.7 新增的局部缓存(Fragment Caching) 功能。
本功能借鉴于 Ruby on Rails,它储存局部内容,下次便能直接使用缓存内容,可以减少文件夹查询并使生成速度更快。
它可用于页首、页脚、侧边栏等文件不常变动的位置,举例来说:
<%- fragment_cache('header', function(){
return ' ';
});
如果您使用局部模板的话,可以更简单:
<%- partial('header', {}, {cache: true});
但是,如果您开启了 relative_link 参数的话,请勿使用局部缓存功能,因为相对链接在每个页面可能不同。
变量
这些变量很重要,因为将来自定义ejs,加入新的页面的时候,都需要了解这些变量
全局变量
变量 | 描述 |
---|---|
site | 网站变量 |
page | 针对该页面的内容以及 front-matter 所设定的变量。 |
config | 网站配置 |
theme | 主题配置。继承自网站配置。 |
_ (单下划线) | Lodash 函数库 |
path | 当前页面的路径(不含根路径) |
url | 当前页面的完整网址 |
env | 环境变量 |
网站变量
变量 | 描述 |
---|---|
site.posts | 所有文章 |
site.pages | 所有分页 |
site.categories | 所有分类 |
site.tags | 所有标签 |
页面变量
变量 | 描述 |
---|---|
site.posts | 所有文章 |
site.pages | 所有分页 |
site.categories | 所有分类 |
site.tags | 所有标签 |
A、页面
变量 | 描述 |
---|---|
page.title | 页面标题 |
page.date | 页面建立日期(Moment.js 对象) |
page.updated | 页面更新日期(Moment.js 对象) |
page.comments | 留言是否开启 |
page.layout | 布局名称 |
page.content | 页面的完整内容 |
page.excerpt | 页面摘要 |
page.more | 除了页面摘要的其余内容 |
page.source | 页面原始路径 |
page.full_source | 页面的完整原始路径 |
page.path | 页面网址(不含根路径)。我们通常在主题中使用 url_for(page.path)。 |
page.permalink | 页面的完整网址 |
page.prev | 上一个页面。如果此为第一个页面则为 null。 |
page.next | 下一个页面。如果此为最后一个页面则为 null。 |
page.raw | 文章的原始内容 |
page.photos | 文章的照片(用于相簿) |
page.link | 文章的外部链接(用于链接文章) |
B、文章
变量 | 描述 |
---|---|
page.published | 如果该文章已发布则为True |
page.categories | 该文章的所有分类 |
page.tags | 该文章的所有标签 |
C、首页
变量 | 描述 |
---|---|
page.per_page | 每页显示的文章数量 |
page.total | 总文章数 |
page.current | 目前页数 |
page.current_url | 目前分页的网址 |
page.posts | 本页文章 |
page.prev | 上一页的页数。如果此页是第一页的话则为 0。 |
page.prev_link | 上一页的网址。如果此页是第一页的话则为 ''。 |
page.next | 下一页的页数。如果此页是最后一页的话则为 0。 |
page.next_link | 下一页的网址。如果此页是最后一页的话则为 ''。 |
page.path | 当前页面的路径(不含根目录)。我们通常在主题中使用 url_for(page.path)。 |
D、归档
变量 | 描述 |
---|---|
page.archive | 等于 true |
page.year | 年份归档 (4位) |
page.month | 月份归档 (没有前导零的2位数) |
E、分类
变量 | 描述 |
---|---|
page.category | 分类名称 |
F、标签
变量 | 描述 |
---|---|
page.tag | 标签名称 |
辅助函数
辅助函数帮助您在模版中快速插入内容。辅助函数不能在源文件中使用。
网址
A、url_for
在路径前加上根路径,从 Hexo 2.7 开始您应该使用此函数而不是 config.root + path
。
<%- url_for(path) %>
<%- url_for(/2017/02/20/HexoBlog/) %>
B、relative_url
取得与 from 相对的 to 路径。
<%- relative_url(from, to) %>
C、gravatar
插入 Gravatar 图片。
如果你不指定 options 参数,将会应用默认参数。否则,你可以将其设置为一个数字,这个数字将会作为 Gravatar 的大小参数。最后,如果你设置它一个对象,它将会被转换为 Gravatar 的一个查询字符串参数。
<%- gravatar(email, [options]) %>;
示例:
<%- gravatar('[email protected]') %>
// http://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787
<%- gravatar('[email protected]', 40) %>
// http://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40
<%- gravatar('[email protected]' {s: 40, d: 'http://example.com/image.png'}) %>
// http://www.gravatar.com/avatar/b9b00e66c6b8a70f88c73cb6bdb06787?s=40&d=http%3A%2F%2Fexample.com%2Fimage.png
<%- gravatar('[email protected]') %>
<%- gravatar('[email protected]', 40) %>
<%- gravatar('[email protected]' {s: 40, d: 'http://example.com/image.png'}) %>
注意了没,这个不是在文中中使用的哦,这个是ejs模板语法,要在ejs模板文件中使用
HTML 标签
A、css
载入 CSS 文件。path 可以是数组或字符串,如果 path 开头不是 / 或任何协议,则会自动加上根路径;如果后面没有加上 .css 扩展名的话,也会自动加上。
<%- css(path, ...) %>
示例:
<%- css('style.css') %>
//
<%- css(['style.css', 'screen.css']) %>
//
//
B、js
载入 JavaScript 文件。path 可以是数组或字符串,如果 path 开头不是 / 或任何协议,则会自动加上根路径;如果后面没有加上 .js 扩展名的话,也会自动加上。
<%- js(path, ...) %>
示例:
<%- js('script.js') %>
//
<%- js(['script.js', 'gallery.js']) %>
//
//
C、link_to
插入链接。
<%- link_to(path, [text], [options]) %>
参数 | 描述 | 默认值 |
---|---|---|
external | 在新视窗打开链接 | false |
class | Class 名称 | |
id | ID |
示例:
<%- link_to('http://www.google.com') %>
// http://www.google.com
<%- link_to('http://www.google.com', 'Google') %>
// Google
<%- link_to('http://www.google.com', 'Google', {external: true}) %>
// Google
D、mail_to
插入电子邮箱链接。
<%- mail_to(path, [text], [options]) %>
参数 | 描述 |
---|---|
class | Class 名称 |
id | ID |
subject | 邮件主题 |
cc | 抄送(CC) |
bcc | 密送(BCC) |
body | 邮件内容 |
示例:
<%- mail_to('[email protected]') %>
// [email protected]
<%- mail_to('[email protected]', 'Email') %>
// Email
E、image_tag
插入图片。
<%- image_tag(path, [options]) %>
参数 | 描述 |
---|---|
alt | 图片的替代文字 |
class | Class 名称 |
id | ID |
width | 图片宽度 |
height | 图片高度 |
F、favicon_tag
插入favicon。
<%- favicon_tag(path) %>
G、feed_tag
插入 feed 链接。
<%- feed_tag(path, [options]) %>
参数 | 描述 | 默认值 |
---|---|---|
title | Feed | 标题 |
type | Feed | 类型 atom |
条件函数
A、is_current
检查 path 是否符合目前页面的网址。开启 strict 选项启用严格比对。
<%- is_current(path, [strict]) %>
B、is_home
检查目前是否为首页。
<%- is_home() %>
C、is_post
检查目前是否为文章。
<%- is_post() %>
D、is_archive
检查目前是否为存档页面。
<%- is_archive() %>
E、is_year
检查目前是否为年度归档页面。
<%- is_year() %>
F、is_month
检查目前是否为月度归档页面。
<%- is_month() %>
G、is_category
检查目前是否为分类归档页面。
如果给定一个字符串作为参数,将会检查目前是否为指定分类。
<%- is_category() %>
<%- is_category('hobby') %>
H、is_tag
检查目前是否为标签归档页面。
如果给定一个字符串作为参数,将会检查目前是否为指定标签。
<%- is_tag() %>
<%- is_tag('hobby') %>
字符串处理
A、trim
清除字符串开头和结尾的空格。
<%- trim(string) %>
B、strip_html
清除字符串中的 HTML 标签。
<%- strip_html(string) %>
示例:
<%- strip_html('It's not important anymore!') %>
// It's not important anymore!
C、titlecase
把字符串转换为正确的 Title case。
<%- titlecase(string) %>
示例:
<%- titlecase('this is an apple') %>
# This is an Apple
D、markdown
使用 Markdown 解析字符串。
<%- markdown(str) %>
示例:
<%- markdown('make me **strong**') %>
// make me strong
E、render
解析字符串。
<%- render(str, engine, [options]) %>
F、word_wrap
使每行的字符串长度不超过 length。length 预设为 80。
<%- word_wrap(str, [length]) %>
示例:
<%- word_wrap('Once upon a time', 8) %>
// Once upon\n a time
G、truncate
移除超过 length 长度的字符串。
<%- truncate(text, length) %>
示例:
<%- truncate('Once upon a time in a world far far away', {length: 17}) %>
// Once upon a ti...
<%- truncate('Once upon a time in a world far far away', {length: 17, separator: ' '}) %>
// Once upon a...
<%- truncate('And they found that many people were sleeping better.', {length: 25, omission: '... (continued)'}) %>
// And they f... (continued)
模板
A、partial
载入其他模板文件,您可在 locals 设定区域变量。
<%- partial(layout, [locals], [options]) %>
参数 | 描述 | 默认值 |
---|---|---|
cache | 缓存(使用 Fragment cache) | false |
only | 限制局部变量。在模板中只能使用 locals 中设定的变量。 | false |
B、fragment_cache
局部缓存。它储存局部内容,下次使用时就能直接使用缓存。
<%- fragment_cache(id, fn);
示例:
<%- fragment_cache('header', function(){
return ' ';
}) %>
日期与时间
date
插入格式化的日期。date
可以是 UNIX
时间、ISO 字符串、Date 对象或 Moment.js 对象。format
默认为 date_format
配置信息。
<%- date(date, [format]) %>
示例:
<%- date(Date.now()) %>
// 2013-01-01
<%- date(Date.now(), 'YYYY/M/D') %>
// Jan 1 2013
date_xml
插入 XML 格式的日期。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。
<%- date_xml(date) %>
示例:
<%- date_xml(Date.now()) %>
// 2013-01-01T00:00:00.000Z
time
插入格式化的时间。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。format 默认为 time_format 配置信息。
<%- time(date, [format]) %>
示例:
<%- time(Date.now()) %>
// 13:05:12
<%- time(Date.now(), 'h:mm:ss a') %>
// 1:05:12 pm
full_date
插入格式化的日期和时间。date 可以是 UNIX 时间、ISO 字符串、Date 对象或 Moment.js 对象。format 默认为 date_format + time_format。
<%- full_date(date, [format]) %>
示例:
<%- full_date(new Date()) %>
// Jan 1, 2013 0:00:00
<%- full_date(new Date(), 'dddd, MMMM Do YYYY, h:mm:ss a') %>
// Tuesday, January 1st 2013, 12:00:00 am
moment
Moment.js 函数库。
列表
list_categories
插入分类列表。
<%- list_categories([options]) %>
参数 | 描述 | 默认值 |
---|---|---|
orderby | 分类排列方式 | name |
order | 分类排列顺序。1, asc 升序;-1, desc 降序。 | 1 |
show_count | 显示每个分类的文章总数 | true |
style | 分类列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 | list |
separator | 分类间的分隔符号。只有在 style 不是 list 时有用。 | , |
depth | 要显示的分类层级。0 显示所有层级的分类;-1 和 0 很类似,但是显示不分层级;1 只显示第一层的分类。 | 0 |
class | 分类列表的 class 名称。 | category |
transform | 改变分类名称显示方法的函数 |
list_tags
插入标签列表。
<%- list_tags([options]) %>
参数 | 描述 | 默认值 |
---|---|---|
orderby | 标签排列方式 | name |
order | 标签排列顺序。1, asc 升序;-1, desc 降序。 | 1 |
show_count | 显示每个标签的文章总数 | true |
style | 标签列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 | list |
separator | 标签间的分隔符号。只有在 style 不是 list 时有用。 | |
class | 标签列表的 class 名称。 | tag |
transform | 改变标签名称显示方法的函数 | |
amount | 要显示的标签数量(0 = 无限制) | 0 |
list_archives
插入归档列表。
<%- list_archives([options]) %>
参数 | 描述 | 默认值 |
---|---|---|
type | 类型。此设定可为 yearly 或 monthly。 | monthly |
order | 排列顺序。1, asc 升序;-1, desc 降序。 | 1 |
show_count | 显示每个归档的文章总数 | true |
format | 日期格式 | MMMM YYYY |
style | 归档列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 | list |
separator | 归档间的分隔符号。只有在 style 不是 list 时有用。 | |
class | 归档列表的 class 名称。 archive | |
transform | 改变归档名称显示方法的函数 |
list_posts
插入文章列表。
<%- list_posts([options]) %>
参数 | 描述 | 默认值 |
---|---|---|
orderby | 文章排列方式 | date |
order | 文章排列顺序。1, asc 升序;-1, desc 降序。 | -1 |
style | 文章列表的显示方式。使用 list 以无序列表(unordered list)方式显示。 | list |
separator | 文章间的分隔符号。只有在 style 不是 list 时有用。 | |
class | 文章列表的 class 名称。 post | |
amount | 要显示的文章数量(0 = 无限制) | 6 |
transform | 改变文章名称显示方法的函数 |
tagcloud
插入标签云。
<%- tagcloud([tags], [options]) %>
参数 | 描述 | 默认值 |
---|---|---|
min_font | 最小字体尺寸 | 10 |
max_font | 最大字体尺寸 | 20 |
unit | 字体尺寸的单位 | px |
amount | 标签总量 | 40 |
orderby | 标签排列方式 | name |
order | 标签排列顺序。1, sac 升序;-1, desc 降序 | 1 |
color | 使用颜色 | false |
start_color | 开始的颜色。您可使用十六进位值(#b700ff),rgba(rgba(183, 0, 255, 1)),hsla(hsla(283, 100%, 50%, 1))或 颜色关键字。此变量仅在 color 参数开启时才有用。 | |
end_color | 结束的颜色。您可使用十六进位值(#b700ff),rgba(rgba(183, 0, 255, 1)),hsla(hsla(283, 100%, 50%, 1))或 颜色关键字。此变量仅在 color 参数开启时才有用。 |
其他
paginator
插入分页链接。
<%- paginator(options) %>
参数 | 描述 | 默认值 |
---|---|---|
base | 基础网址 | / |
format | 网址格式 | page/%d/ |
total | 分页总数 | 1 |
current | 目前页数 | 0 |
prev_text | 上一页链接的文字。仅在 prev_next 设定开启时才有用。 | Prev |
next_text | 下一页链接的文字。仅在 prev_next 设定开启时才有用。 | Next |
space | 空白文字 … | |
prev_next | 显示上一页和下一页的链接 | true |
end_size | 显示于两侧的页数 | 1 |
mid_size | 显示于中间的页数 | 2 |
show_all | 显示所有页数。如果开启此参数的话,end_size 和 mid_size 就没用了。 | false |
search_form
插入 Google 搜索框。
<%- search_form(options) %>
参数 | 描述 | 默认值 |
---|---|---|
class | 表单的 class name | search-form |
text | 搜索提示文字 | Search |
button | 显示搜索按钮。此参数可为布尔值(boolean)或字符串,当设定是字符串的时候,即为搜索按钮的文字。 | false |
number_format
格式化数字。
<%- number_format(number, [options]) %>
参数 | 描述 | 默认值 |
---|---|---|
precision | 数字精度。此选项可为 false 或非负整数。 | false |
delimiter | 千位数分隔符号 | , |
separator | 整数和小数之间的分隔符号 | , |
示例:
<%- number_format(12345.67, {precision: 1}) %>
// 12,345.68
<%- number_format(12345.67, {precision: 4}) %>
// 12,345.6700
<%- number_format(12345.67, {precision: 0}) %>
// 12,345
<%- number_format(12345.67, {delimiter: ''}) %>
// 12345.67
<%- number_format(12345.67, {separator: '/'}) %>
// 12,345/67
open_graph
插入 open graph 资源。
<%- open_graph([options]) %>
参数 | 描述 | 默认值 |
---|---|---|
title | 页面标题 (og:title) | page.title |
type | 页面类型 (og:type) | blog |
url | 页面网址 (og:url) | url |
image | 页面图片 (og:image) | 内容中的图片 |
site_name | 网站名称 (og:site_name) | config.title |
description | 页面描述 (og:desription) | 内容摘要或前 200 字 |
twitter_card | Twitter 卡片类型 (twitter:card) | summary |
twitter_id | Twitter ID | (twitter:creator) |
twitter_site | Twitter 网站 | (twitter:site) |
google_plus | Google+ | 个人资料链接 |
fb_admins | 管理者 ID | |
fb_app_id | 应用程序 ID |
last: toc
解析内容中的标题标签 (h1~h6) 并插入目录。
<%- toc(str, [options]) %>
参数 | 描述 | 默认值 |
---|---|---|
class | Class 名称 | toc |
list_number | 显示编号 | true |
示例:
<%- toc(page.content) %>
Hexo页面渲染流程
Yelee目录说明
看一下,Yelee主题的文件目录:
根据这个目录我们来分析Hexo
是如何工作的
我们都知道两个命名,一个是 hexo new page name
,一个是 hexo new post name
hexo new page name
创建一个新页面 , 页面具体渲染模板在Theme主题下的layout文件夹下面hexo new post name/hexo new post draft
是创建一篇新文章,新文章保存在source/_posts目录下,如果是hexo new draft name
,则是保存在source/_drafts
目录下,那么根据scaffolds
的模板,可以确定新建的文章或者草稿的基本配置
看下图:
下面看一下我们的,引擎模板文件:
入口模板
具体实现
想要自定义404吗?想要写一个个性化的about me吗?想要实现完全自定义吗?哈哈这个你还是得去学习 EJS
啦
如何实现用D3-cloud来展现标签云
有没有感觉 Hexo
自带的 tag-cloud
标签云太丑陋了呢!作为一个前端程序员,对审美可是有着比较高的要求,github
上面有 d3-cloud
这个项目,那么我们来玩一玩吧,把github
上的d3-cloud
项目在我们的hexo博客
中使用哈!
hexo是静态博客,所以最后在网上看到的都是静态的内容,也就是说,我们的看到的标签云也是静态的已经生成好的内容,并不会随着刷新页面而重新计算生成另外样式的标签云。
当然d3-cloud这个项目,提供了浏览器端和node端运行的版本,见它的例子,我们可以在客户端运行,也可以在服务端作为 node运行。
具体操作流程
:
找到关于tagcloud模板文件以及JS和CSS
我上面说的,应该很容易找到吧,我已经找到了呀-
安装模块
npm install canvas --save npm install d3-cloud --save npm install d3 --save
-
找到文件: 你的
blog项目 -> node_modules -> hexo ->plugins -> helper -> index.js
var tagcloud = require('./tagcloud'); helper.register('tagcloud', tagcloud); helper.register('tag_cloud', tagcloud); //修改为下面的代码:目的是不直接修改tagcloud.js,保留代码 var tagcloud = require('./tagcloud'); var tagcloudd3 = require('./tagcloudd3'); helper.register('tagcloud', tagcloudd3); helper.register('tag_cloud', tagcloudd3);
-
新建文件tagcloudd3.js :位置在blog项目 -> node_modules -> hexo ->plugins -> helper -> tagcloudd3.js
tagcloud3.js的内容如下
:'use strict'; var Canvas = require("canvas"); var cloud = require("d3-cloud"); var d3 = require("d3"); var layout = cloud()//利用d3-cloud计算每个标签的位置 .size([600, 400]) .canvas(function() { return new Canvas(1, 1); }) .padding(7) .rotate(function() { return ~~(Math.random() * 2) * 90; }) .font("Impact") .fontSize(function(d) { return d.size; }); var fill = d3.scale.category20();//利用d3的接口给每个标签颜色 function tagcloudHelper(tags){ /****与tagcloud.js一样,获得tags 开始***/ if ((!tags || !tags.hasOwnProperty('length'))){ tags = this.site.tags; } if (!tags || !tags.length) return ''; var result = []; tags = tags.sort('name', 1); // Ignore tags with zero posts tags = tags.filter(function(tag){ return tag.length; }); /****与tagcloud.js一样,获得tags 结束***/ //计算标签出现次数最大值,比如,博客中一共有两个标签,一个是hello,一个是world,hello出现2次,world 出现1次,那么maxsize就是2 var maxsize = 1; tags.sort('length').forEach(function(tag){ var length = tag.length; if(length > maxsize) maxsize = length; }); //构建传入layout的words var arr = [],words; tags.forEach(function(tag){ arr.push({"name": tag.name,"num" : tag.length}); }); words = arr.map(function(d) { var text = d.name.replace(/[^\x00-\xff]/g,"ab");//对中文的投机处理,用ab代替中文字符 return {name:d.name, text: text, size : Math.log(d.num)/(Math.log(maxsize)-Math.log(1)) * 15 + 30};//size的计算取对数,是为了让标签之间的大小相对平均一些。因为博客侧重前端内容,所以某一些标签会比较多,标签最大最小次数的差距会比较大。 }); layout.words(words); layout.start(); result.push(''); return result.join(''); } module.exports = tagcloudHelper;
运行,就可以看到结果啦
这个我并没有实际操作,原因很简单,最近比较忙,还有一个就是,node安装canvas实在是太麻烦了呀,
这里给出地址:
如何用npm install canvas?
npm install canvas
Yelee 主题配置
关于主题的配置,这篇文章讲的很详细啦,Yelee中文参考手册
关于Hexo,还有最后一篇文章,请看 :搭建Hexo博客进阶篇--API和一些小部件
参考资料
Hexo官方网站 : https://hexo.io/
利用d3-cloud实现标签云 : http://www.cnblogs.com/lilyimage/p/5207697.html