修改Hexo Light主題功能樣式

目錄
  1. 1.引用外觀
  2. 2.加大字體顯示
  3. 3.修改搜尋框內容為Google自訂搜尋
  4. 4.增加Google Adsense廣告區塊
    1. 4.1.側邊欄
    2. 4.2.留言上方
  5. 5.增加側邊欄連結區塊
  6. 6.增加Twitter獨立頁面
  7. 7.在彙整頁和分類頁增加上下頁
  8. 8.新增TOC(Table of Contents)
  9. 9.修改Disqus留言板
  10. 10.搜尋引擎最佳化(SEO)
    1. 10.1.網頁加入canonical標記
    2. 10.2.修改網頁描述
    3. 10.3.文章連結加入nofollow
    4. 10.4.建立網站地圖
  11. 11.新增RSS訂閱

Hexo Light主題外觀簡單大方,沒有什麼華麗特效,算是很好修改。本文主要紀錄我個人修改需求功能,單一功能樣式修改步驟不多,但想改的東西累積起來,也是蠻多的。修改內容語法不加以詳細解釋,請自行Google結果。

1.引用外觀

原始引用外觀實在是不太好看,字體太大、句子全部置中。開啟/themes/light/source/css/_partial/article.styl,搜尋:

1
2
3
4
5
6
7
8
blockquote
border-top 1px solid color-border
border-bottom 1px solid color-border
font-style italic
font-family font-serif
font-size 1.2em
padding 0 30px 15px
text-align center

改成:

1
2
3
4
5
6
7
8
9
10
blockquote
border-top 1px solid color-border
border-bottom 1px solid color-border
border-right 1px solid color-border
border-left: 7px solid #DDD
font-style italic
font-family font-serif
font-size 1.1em
padding 0 30px 15px
text-align left

效果如圖:
Hexo Light Quote

2.加大字體顯示

電腦和手機顯示的字體太小了,改大一點來看才不會吃力。開啟/themes/light/source/css/base/layout.styl,搜尋:

1
2
3
4
5
6
7
8
9
10
body
background color-background
color color-font
font-family font-default
font-size 14px
text-shadow 0 0 1px transparent
@media screen and (max-width: 1260px)
margin 0 30px
@media screen and (max-width: 600px)
font-size 13px

font-size電腦預設是14px,手機預設是13px,我改成16px和15px。改完發現標籤雲沒有跟著變大,查一下標籤雲字體大小寫在外掛裡。開啟/node_modules/hexo/lib/plugins/helper/tagcloud.js,搜尋:

1
2
3
4
options = options || {};

var min = options.min_font || 10;
var max = options.max_font || 20;

預設最小是10px,最大是20px,我改成12px和22px。改完重整一下,標籤雲相對變大。

3.修改搜尋框內容為Google自訂搜尋

使用主題搜尋框,搜尋結果使用Google代管網頁。不選擇其他自訂搜尋效果,最大原因是只有Google代管才能使用目前視窗點進去搜尋連結,其他效果都是點進去搜尋連結會開新視窗。大型網站資料量夠大或是搜尋包含多個網站,開新視窗很方便。反之,個人網站資料量小,Google搜尋精準,尤其是重疊效果,搜尋結果開新視窗就顯得多餘。

如果你有Google Adsense,建議使用裡面的自訂搜尋設定,設定好後,產生程式碼如下:

1
2
3
4
5
6
7
8
9
10
<form action="http://www.google.com.tw" id="cse-search-box">
<div>
<input type="hidden" name="cx" value="partner-pub-xxxxxxxxxxxxxxxx" />
<input type="hidden" name="ie" value="UTF-8" />
<input type="text" name="q" size="25" />
<input type="submit" name="sa" value="Search" />
</div>
</form>

<script type="text/javascript" src="http://www.google.com.tw/coop/cse/brand?form=cse-search-box&amp;lang=en"></script>

開啟/themes/light/layout/_widget/search.ejs,原始內容:

1
2
3
4
5
6
<div class="search">
<form action="//google.com/search" method="get" accept-charset="utf-8">
<input type="search" name="q" results="0" placeholder="<%= __('search') %>">
<input type="hidden" name="q" value="site:<%- config.url.replace(/^https?:\/\//, '') %>">
</form>
</div>

改成:

1
2
3
4
5
6
<div class="search">
<form action="http://www.google.com.tw" id="cse-search-box">
<input type="hidden" name="cx" value="partner-pub-xxxxxxxxxxxxxxxx" />
<input type="search" name="q" results="0" placeholder="<%= __('search') %>">
</form>
</div>

修改完畢,自行測試效果,其他自訂搜尋效果也是類似修改方式,例如兩頁效果需增加一個獨立頁面,內容為搜尋結果程式碼。

4.增加Google Adsense廣告區塊

4.1.側邊欄

到Google Adsense新增一個回應式廣告單元(依螢幕/裝置自動調整大小)。另外複製一個檔案在同資料夾下:/themes/light/layout/_widget/category.ejs,任意取名為adsense.ejs,修改其內容為:

1
2
3
4
5
6
<div class="widget tag">
<h3 class="title">廣告</h3>
<ul class="entry">
放置你的Google Adsense程式碼
</ul>
</div>

不想要標題欄位,把<h3 class="title">廣告</h3></ul>這兩行移掉(用uBlock Origin擋掉至少會好看一點XD)。之後開啟/themes/light/_config.yml,在widgets:底下新增一個- adsense區塊。

4.2.留言上方

參考〈Hexo 블로그에 구글 애드센스(Adsense) 추가하기〉,新增/layout/_ads資料夾,裡面新增adsense.ejs,內容一樣加入回應式廣告單元程式碼。

開啟/layout/_partial/comment.ejs,搜尋<section id="comment">,底下加入:

1
2
3
<!-- google adsense start -->
<%- partial('_ads/adsense') %>
<!-- google adsense end -->

此區廣告可用留言區塊來控制開關。

5.增加側邊欄連結區塊

參考〈Hexo中数据文件功能添加友情链接〉,在Hexo根目錄的source資料夾新增一個_data資料夾,在其資料夾再新增一個links.yml。內容範例格式為:

1
2
3
Google: http://www.google.com
Apple: http://www.apple.com
Hexo: http://hexo.io

另外複製一個檔案在同資料夾下:/themes/light/layout/_widget/category.ejs,任意取名為links.ejs,修改其內容為:

1
2
3
4
5
6
7
8
9
10
<% if (site.data.links){ %>
<div class="widget tag">
<h3 class="title">連結</h3>
<ul class="entry">
<% for (var i in site.data.links){ %>
<li class='link'><a href='<%- site.data.links[i] %>'><%= i %></a></li>
<% } %>
</ul>
</div>
<% } %>

開啟/themes/light/_config.yml,在widgets:底下新增一個- links區塊。之後編輯側邊欄連結,修改/source/_data/links.yml內容就可以了。

6.增加Twitter獨立頁面

使用command進入Hexo資料夾,輸入指令新增一個Twitter獨立頁面,到Twitter網頁找到小工具程式碼(使用者時間軸顯示):

1
2
<a class="twitter-timeline"  href="https://twitter.com/你的帳號" data-widget-id="xxxxxxxxxxxx">@你的帳號 發送的推文</a>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>

以上程式碼放到獨立頁面如果無法使用,改成:

1
<a class="twitter-timeline" href="https://twitter.com/你的帳號" data-widget-id="xxxxxxxxxxxx" data-chrome="noborders nofooter" data-tweet-limit="10" >@你的帳號 發送的推文</a><script async src="https://platform.twitter.com/widgets.js"></script>

其中data-tweet-limit="10"為顯示推文數量,評論記得要關閉。

7.在彙整頁和分類頁增加上下頁

不知為何Light主題在這兩種連結頁面並無上下頁?開啟/themes/light/layout資料夾中的archive.ejs(彙整)和category.ejs(分類),在第一行下方新增內容:

1
2
3
4
5
6
7
8
9
<nav id="pagination">
<% if (page.prev){ %>
<a href="<%- config.root %><%- page.prev_link %>" class="alignleft prev"><%= __('prev') %></a>
<% } %>
<% if (page.next){ %>
<a href="<%- config.root %><%- page.next_link %>" class="alignright next"><%= __('next') %></a>
<% } %>
<div class="clearfix"></div>
</nav>

之後就能在這兩種頁面看到上下頁了。

8.新增TOC(Table of Contents)

TOC就是文章內容的章節目錄,參考〈Hexo添加文章目录〉,寫長篇教學文時特別好用。開啟/themes/themename/layout/_partial/article.ejs,搜尋<%- item.content %>,新增內容放到<%- item.content %>上方,完整內容為:

1
2
3
4
5
6
7
8
9
10
  <% if (item.excerpt && index){ %>
<%- item.excerpt %>
<% } else { %>
<% if (!index && item.toc){ %>
<div id="toc" class="toc-article">
<strong class="toc-title">目錄</strong>
<%- toc(item.content) %>
</div>
<% } %>
<%- item.content %>

如果要關閉TOC編號,將上面的<%- toc(item.content) %>改成<%- toc(item.content, {list_number: false}) %>。手動輸入編號和錨點時,錨點連結需和TOC產生的連結一致,才不會錯亂。

新增TOC的CSS,開啟/themes/light/source/css/_partial/article.styl,在最下方新增內容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*toc*/
.toc-article
background #eee
border 1px solid #bbb
border-radius 10px
margin 0 0 0.3em 1.5em
padding 1.2em 1em 0 1em
max-width 28%
.toc-title
font-size 120%
padding 0.75em
#toc
line-height 1em
font-size 0.9em
float right
.toc
padding 0
margin 1em
line-height 1.8em
li
list-style-type none
.toc-child
margin-left 1em

之後編輯文章內容時,文章的front matter加入toc: true,在文章內容需要產生目錄開始地方加入<!-- toc -->語法(文章開頭標記有#會辨識為目錄)。進入文章本體才會出現TOC,其他地方都不會出現。
效果如圖:
Hexo Light TOC

9.修改Disqus留言板

原因:

其中被注释掉的disqus_config部分是用于初始化Disqus thread的。虽然不配置其中的url和identifier也可以用,但是这会导致Disqus直接使用当前页面的完整URL来初始化评论区。

也就是说,如果默认情况下你没有配置这些变量,访客每通过一个新的URL访问你的文章(就算只有Query String不一样),Disqus就会为它新建一个thread。这就导致了官方帮助文档中提到的split threads现象,即我上面在后台看到的一万个thread。

參考〈Hexo加入Disqus留言版(包含留言數) - 加入Disqus script〉,開啟/themes/light/layout/_partial/after_footer.ejs,搜尋:

1
2
3
4
5
<% if (config.disqus_shortname){ %>
<script type="text/javascript">
var disqus_shortname = '<%= config.disqus_shortname %>';
var disqus_url = '<%= config.url +"/"+ page.path %>';
var disqus_identifier = '<%= page.path %>';

改成:

1
2
3
4
5
6
7
8
<% if (config.disqus_shortname){ %>
<script type="text/javascript">
var disqus_shortname = '<%= config.disqus_shortname %>';
var disqus_config = function() {
this.page.url = '<%= page.permalink %>';
this.page.identifier = '<%= page.path %>';
this.page.title = '<%= page.title %>';
};

10.搜尋引擎最佳化(SEO)

10.1.網頁加入canonical標記

安裝hexo-auto-canonical,開啟/themes/light/layout/_partial/head.ejs,最底下加入內容:

1
<%- autoCanonical(config, page) %>

10.2.修改網頁描述

Head模版語法和其他主題相比,網頁描述語法的排列順序對搜尋引擎來說,並不友善,Google Search Console會提示出現很多重複的中繼說明。開啟/themes/light/layout/_partial/head.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
37
38
39
40
41
42
43
44
45
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<%
var title = [];
if (page.current > 1) title.push(__('page', page.current));
if (page.title) title.push(page.title);
if (page.category) title.push(page.category);
if (page.tag) title.push(page.tag);
if (page.archive){
if (page.year) title.push(__('archive_b', page.year + (page.month ? '/' + page.month : '')));
else title.push(__('archive_a'));
}
title.push(config.title);
%>
<title><%= title.join(' | ') %></title>
<% if (config.author){ %><meta name="author" content="<%= config.author %>"><% } %>
<% if (page.description){ %>
<meta name="description" content="<%= page.description %>">
<% } else if (config.description){ %>
<meta name="description" content="<%= config.description %>">
<% } else if (page.excerpt){ %>
<meta name="description" content="<%= strip_html(page.excerpt).replace(/^\s*/, '').replace(/\s*$/, '') %>">
<% } else if (page.content){ %>
<meta name="description" content="<%= strip_html(page.content).replace(/^\s*/, '').replace(/\s*$/, '').substring(0, 150) %>">
<% } %>
<% if (page.keywords){ %><meta name="keywords" content="<%= page.keywords %>"><% } %>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

<% if (page.title){ %><meta property="og:title" content="<%= page.title %>"/><% } %>
<meta property="og:site_name" content="<%= config.title %>"/>

<% if(page.cover) { %>
<meta property="og:image" content="<%= page.cover %>" />
<% } else { %>
<meta property="og:image" content="<%= config.cover %>"/>
<% } %>

<link href="<%- config.root %>favicon.png" rel="icon">
<link rel="alternate" href="<% if (theme.rss){ %><%- theme.rss %><% } else { %><%- config.root %>atom.xml<% } %>" title="<%= config.title %>" type="application/atom+xml">
<link rel="stylesheet" href="<%- config.root %>css/style.css" media="screen" type="text/css">
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<%- partial('google_analytics') %>
</head>

改成(複製其他主題的head.ejs內容,已加canonical標記):

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
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<%
var title = page.title;

if (is_archive()){
title = __('archive_a');

if (is_month()){
title += ': ' + page.year + '/' + page.month;
} else if (is_year()){
title += ': ' + page.year;
}
} else if (is_category()){
title = __('category') + ': ' + page.category;
} else if (is_tag()){
title = __('tag') + ': ' + page.tag;
}
%>
<title><% if (title){ %><%= title %> | <% } %><%= config.title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<%- open_graph({twitter_id: theme.twitter, google_plus: theme.google_plus, fb_admins: theme.fb_admins, fb_app_id: theme.fb_app_id}) %>
<%- autoCanonical(config, page) %>
<% if (theme.rss){ %>
<link rel="alternate" href="<%- theme.rss %>" title="<%= config.title %>" type="application/atom+xml">
<% } %>
<% if (theme.favicon){ %>
<link rel="icon" href="<%- theme.favicon %>">
<% } %>
<%- css('css/style') %>
<!--[if lt IE 9]><script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script><![endif]-->
<%- partial('google_analytics') %>
</head>

10.3.文章連結加入nofollow

參考〈hexo-filter-nofollow - Hexo官方的nofollow插件〉,安裝hexo-filter-nofollow,排除特定網域連結。開啟網站設定檔_config.yml,加入內容:

1
2
3
4
5
6
nofollow:
enable: true
field: site
exclude:
- 'exclude1.com'
- 'exclude2.com'

10.4.建立網站地圖

安裝hexo-generator-sitemap,開啟網站設定檔_config.yml,加入內容:

1
2
sitemap:
path: sitemap.xml

如果某篇文章不想加入Sitemap,文章的front matter加上sitemap: false

11.新增RSS訂閱

Hexo預設沒有RSS,安裝hexo-generator-feed,開啟網站設定檔_config.yml,加入內容:

1
2
3
4
feed:
type: atom
path: atom.xml
limit: 10

limit為文章RSS輸出最大數量。