Icarus 主题自定义(基于2.x)

本文是基于icarus 2.x的版本,icarus从3.0开始使用jsx重写了,查看最新版本

本博客所选取的主题是 Icarus ,并做了一些个性化的修改,很多修改都可以直观的看到。详细的差异可以查看 diff,这里记录一些主要的改动。

注: 可以通过变量 page.layout 来判断当前页面类型,'post' 表示当前是文章页面,具体可参考 hexo 文档。

布局

文章页面两栏布局

主题默认是三栏布局,并且显示了很多的 widget ,但在阅读文章时显得有些拥挤。因此在文章页面,修改为两栏布局,并显示特定的 widget

diff:includes/helpers/layout.js
1
2
3
4
5
6
7
8
9
10
     const widgets = hexo.extend.helper.get('get_config').bind(this)('widgets');
- return widgets.filter(widget => widget.hasOwnProperty('position') && widget.position === position);
+ if (this.page.layout !== 'post') {
+ return widgets.filter(widget => widget.hasOwnProperty('position') && widget.position === position);
+ }
+ if (position === 'left') {
+ return widgets.filter(widget => widget.hasOwnProperty('position') && (widget.type === 'toc' || widget.type === 'profile'));
+ } else {
+ return []
+ }

可以参考上述代码,即可实现不同页面不同 widget

但两栏整体宽度跟三栏不同。因此强制指定为三栏布局,并且修改相应的宽度,这样所有的页面侧边栏宽度保持一致。

diff:layout/common/widget.ejs
1
2
3
4
5
6
 <% function side_column_class() {
switch (column_count()) {
case 2:
- return 'is-4-tablet is-4-desktop is-4-widescreen';
+ return 'is-4-tablet is-4-desktop is-3-widescreen';
case 3:
diff:layout/layout.ejs
1
2
3
4
5
6
7
8
9
10
-<body class="is-<%= column_count() %>-column">
+<body class="is-3-column">
<%- partial('common/navbar', { page }) %>
<% function main_column_class() {
switch (column_count()) {
case 1:
return 'is-12';
case 2:
- return 'is-8-tablet is-8-desktop is-8-widescreen';
+ return 'is-8-tablet is-8-desktop is-9-widescreen';

并修改在不同屏幕小大下的宽度

diff:source/css/style.styl
1
2
3
4
5
6
7
8
9
10
11
12
13
     .is-2-column .container
max-width: screen-desktop - 2 * gap
width: screen-desktop - 2 * gap
+ .is-3-column .container
+ max-width: screen-widescreen - gap
+ width: screen-widescreen - gap
@media screen and (min-width: screen-fullhd)
+ .is-3-column .container
+ max-width: screen-fullhd - 2 * gap
+ width: screen-fullhd - 2 * gap
.is-2-column .container
max-width: screen-widescreen - 2 * gap
width: screen-widescreen - 2 * gap

优化文章标题布局

标题移动到文章信息上方,增加更新时间,并增加了icon。

diff:layout/common/article.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
     <div class="card-content article <%= post.hasOwnProperty('direction') ? post.direction : '' %>">
+ <h1 class="title is-size-3 is-size-4-mobile has-text-weight-normal">
+ <% if (index) { %>
+ <a class="has-link-black-ter" href="<%- url_for(post.link ? post.link : post.path) %>"><i class="fas fa-angle-double-right"></i><%= post.title %></a>
+ <% } else { %>
+ <i class="fas fa-angle-double-right"></i><%= post.title %>
+ <% } %>
+ </h1>
<% if (post.layout != 'page') { %>
<div class="level article-meta is-size-7 is-uppercase is-mobile is-overflow-x-auto">
<div class="level-left">
- <time class="level-item has-text-grey" datetime="<%= date_xml(post.date) %>"><%= date(post.date) %></time>
+ <time class="level-item has-text-grey" datetime="<%= date_xml(post.date) %>"><i class="far fa-calendar-alt">&nbsp;</i><%= date(post.date) %></time>
+ <% if (post.updated && post.updated > post.date) { %>
+ <time class="level-item has-text-grey is-hidden-mobile" datetime="<%= date_xml(post.updated) %>"><i class="far fa-calendar-check">&nbsp;</i><%= date(post.updated) %></time>
+ <% } %>
<% if (post.categories && post.categories.length) { %>

其中创建时间使用日期。

diff:source/js/main.js
1
2
3
4
5
-    if (typeof(moment) === 'function') {
- $('.article-meta time').each(function () {
- $(this).text(moment($(this).attr('datetime')).fromNow());
- });
- }

优化文章结尾布局

在文章结尾增加一个 hr,并修改 tags 展示。在预览时也显示 tags,并且将 Read More 按钮放置在右边。

diff:layout/common/article.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
     <% if (!index && post.tags && post.tags.length) { %>
+ <hr style="height:1px;margin:1rem 0"/>
<div class="level is-size-7 is-uppercase">
<div class="level-start">
<div class="level-item">
- <span class="is-size-6 has-text-grey has-mr-7">#</span>
+ <i class="fas fa-tags has-text-grey"></i>&nbsp;
<%- list_tags(post.tags, {
class: 'has-link-grey ',
show_count: false,
- style: 'link'
+ style: 'link',
+ separator: ',&nbsp;'
}) %>
</div>
</div>
</div>
<% } %>
<% if (index && post.excerpt) { %>
- <div class="level is-mobile">
+ <hr style="height:1px;margin:1rem 0"/>
+ <div class="level is-mobile is-flex">
+ <div class="level-start">
+ <% if (post.tags && post.tags.length) { %>
+ <div class="level-item is-size-7 is-uppercase">
+ <i class="fas fa-tags has-text-grey"></i>&nbsp;
+ <%- list_tags(post.tags, {
+ class: 'has-link-grey ',
+ show_count: false,
+ style: 'link',
+ separator: ',&nbsp;'
+ }) %>
+ </div>
+ <% } %>
+ </div>
<div class="level-start">

优化个人信息布局

减少头像大小,头像下方计数的地方增加链接,follow前增加icon。

diff:layout/widget/profile.ejs
1
2
3
4
5
6
7
-    <nav class="level is-mobile">
+ <nav class="level menu-list is-mobile" style="margin-bottom:1rem">
<div class="level-item has-text-centered is-marginless">
- <div>
+ <a href="<%- url_for('/archives/') %>">
<p class="heading">
......

优化移动端显示

在移动端,隐藏 archivetagcloud

diff:layout/widget/archive.ejs
1
2
-<div class="card widget">
+<div class="card widget is-hidden-mobile">
diff:layout/widget/tagcloud.ejs
1
2
-<div class="card widget">
+<div class="card widget is-hidden-mobile">

目录粘性布局

增加 column-left is-sticky 类。

diff:layout/widget/toc.ejs
1
2
-<div class="card widget" id="toc">
+<div class="card widget column-left is-sticky" id="toc">

功能

增加版权说明

diff:layout/common/article.ejs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
     <div class="content">
<%- index && post.excerpt ? post.excerpt : post.content %>
</div>
+ <% if (!index && post.layout === 'post' && post.copyright !== false) { %>
+ <ul class="post-copyright">
+ <li><strong>本文标题:</strong><a href="<%= post.permalink %>"><%= page.title %></a></li>
+ <li><strong>本文作者:</strong><a href="<%= theme.url %>"><%= theme.author %></a></li>
+ <li><strong>本文链接:</strong><a href="<%= post.permalink %>"><%= post.permalink %></a></li>
+ <li><strong>发布时间:</strong><%= post.date.format("YYYY-MM-DD") %></li>
+ <li><strong>版权声明:</strong>本博客所有文章除特别声明外,均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="external nofollow" target="_blank">CC BY-NC-SA 4.0</a> 许可协议。转载请注明出处!
+ </li>
+ </ul>
+ <% } %>
<% if (!index && post.tags && post.tags.length) { %>

并增加样式

diff:source/css/style.styl
1
2
3
4
5
6
7
8
+.post-copyright
+ font-size: 1rem
+ letter-spacing: 0.02rem
+ word-break: break-all
+ margin: 2.5rem 0 0
+ padding: 1rem 1rem
+ border-left: 3px solid #FF1700
+ background-color: #F9F9F9

增加标题自动计数

diff:source/css/style.styl
1
2
3
4
5
6
7
+.article {counter-reset:section}
+.article h2{counter-reset:sub-section}
+.article h3{counter-reset:composite}
+.article h4{counter-reset:detail}
+.article h2:before{content:counter(section) " ";counter-increment:section}
+.article h3:before{content:counter(section) "." counter(sub-section) " ";counter-increment:sub-section}
+.article h4:before{content:counter(section) "." counter(sub-section) "." counter(composite) " ";counter-increment:composite}

默认显示目录

正常开启目录需要在 meta 信息中加入 toc: true 开启,但绝大部分文章都是有目录的,因此修改为默认开启。因为有多个地方引用了 get_config('toc') 并且需要判断当前页面,改起来稍微麻烦一些,因此直接修改了 get_config 方法。

diff:includes/helpers/config.js
1
2
3
4
5
6
7
        return defaultValue;
} else {
const property = readProperty(specs, configName);
- return property === null ? null : property[descriptors.defaultValue];
+ const result = property === null ? null : property[descriptors.defaultValue];
+ return (configName === 'toc' && this.page.layout === 'post' && result === null) ? true : result;
}

页面footer显示一组icon

默认情况下一个icon对应一个链接,但例如 CC BY-NC-SA 4.0 需要四个图标一组。因此修改代码,使得配置 link.icon 可以是一个数组,效果可以参考页面底部。

diff:layout/common/footer.ejs
1
2
3
4
     <% } else { %>
- <i class="<%= link.icon %>"></i>
+ <% for (let icon of (Array.isArray(link.icon) ? link.icon : [link.icon])) { %><i class="<%= icon %>"></i>&nbsp;<% } %>
<% } %>
diff:includes/specs/icon_link.spec.js
1
2
3
4
5
     icon: {
[required]: true,
- [type]: 'string',
+ [type]: ['string', 'array'],
[doc]: 'Link icon class names'

_config.yml 中配置如下

_config.yml
1
2
3
4
5
6
7
8
9
footer:
links:
CC BY-NC-SA 4.0:
icon:
- fab fa-creative-commons
- fab fa-creative-commons-by
- fab fa-creative-commons-nc
- fab fa-creative-commons-sa
url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/'

可以配置文章开头是否显示图片

Icarus 支持文章设置一个图片,在文章开头、最近的文章、时间线等地方显示。但有些图放大之后会显得很不协调,因此修改以支持自定义是否显示。修改 has_thumbnail 方法,增加参数 isArticle 参数,默认 false,并在文章页面修改调用参数。

diff:includes/helpers/page.js
1
2
3
4
5
6
7
8
9
10
11
-    hexo.extend.helper.register('has_thumbnail', function (post) {
+ hexo.extend.helper.register('has_thumbnail', function (post, isArticle = false) {
const getConfig = hexo.extend.helper.get('get_config').bind(this);
const allowThumbnail = getConfig('article.thumbnail', true);
if (!allowThumbnail) {
return false;
}
+ if (isArticle && post['article-thumbnail'] === false){
+ return false;
+ }
return post.hasOwnProperty('thumbnail') && post.thumbnail;
diff:layout/common/article.ejs
1
2
3
4
 <div class="card">
- <% if (has_thumbnail(post)) { %>
+ <% if (has_thumbnail(post, true)) { %>
<div class="card-image">

这样修改之后,如果文章 meta 信息中包含 article-thumbnail: false,就可以取消图片的显示。

样式

修改 logo 和 favicon

用 Python 设计 Logo,并微调样式。

按钮背景颜色增加渐变

diff:source/css/style.styl
1
2
3
4
5
6
     .menu-list li ul
margin-right: 0
+ .menu-list a
+ transition: background-color 0.3s ease-in-out
.menu-list a.level
display: flex

card 增加浮动效果

:hover 时增大阴影,并增加动画属性 ease-in-out

diff:source/css/style.styl
1
2
3
4
5
 .card
border-radius: 4px
box-shadow: 0 4px 10px rgba(0,0,0,0.05), 0 0 1px rgba(0,0,0,0.1)
+ &:hover
+ box-shadow: 0 6px 15px rgba(0,0,0,0.15), 0 0 1px rgba(0,0,0,0.1)
diff:source/js/animation.js
1
2
3
     element.style.transform = '';
- element.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out';
+ element.style.transition = 'opacity 0.3s ease-out, transform 0.3s ease-out, box-shadow 0.3s ease-in-out';

更新

2020-02-16 合并了 2.7.0 版本,冲突不算太多,有两个点需要注意一下。

icarus 的配置里面,plugins.clipboard 需要移除,相关的配置移动到 article.highlight.clipboard

_config.yml
1
2
3
4
5
6
7
8
9
10
article:
# Code highlight settings
highlight:
# Code highlight themes
# https://github.com/highlightjs/highlight.js/tree/master/src/styles
theme: github-gist
# Show code copying button
clipboard: true
# Default folding status of the code blocks. Can be "", "folded", "unfolded"
fold: unfolded

如果之前 links widget 没有配置链接,可能会遇到编译错误,需要增加一下判断。

diff:layout/widget/links.locals.js
1
2
3
4
5
     const links = get_config_from_obj(locals.widget, 'links');
- if (Object.keys(links).length == 0) {
+ if (!links || Object.keys(links).length == 0) {
return null;
}

总结

这里只列举了部分改动,详细的差异可以查看 diff

本文会持续更新,保持跟最新的博客效果一致,希望能给你自定义主题一些帮助。

如果有其他想法或者意见,可以在下方留言。

😊

Icarus 主题自定义(基于2.x)

https://www.alphalxy.com/2019/03/customize-icarus-2/

Author

Xinyu Liu

Posted on

2019-03-24

Updated on

2021-09-06


Comments