修改Hexo Light主題功能樣式

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

引用外觀

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

    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

改成:

    blockquote
      border-left 6px solid #dfe2e5
      color #6a737d
      padding 0 20px
      text-align left

效果如圖:
Hexo Theme Light Quote

加大字體顯示

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

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。改完發現標籤雲沒有跟著變大,參考官方給的標籤雲參數來修改。編輯/themes/light/layout/_widget/tagcloud.ejs,搜尋:

<%- tagcloud(site.tags, {}) %>

改成:

<%- tagcloud(site.tags, {min_font: 12, max_font: 22}) %>

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

讓文章內的H1~H6標題顯示錨點符號

參考〈hexo-theme-murasaki的_common.styl第37行〉的&:hover .headerlink:before這段語法。編輯/themes/light/source/css/_partial/article.styl,搜尋:

    h1, h2
       font-weight normal
       border-bottom 1px solid color-border
       padding-bottom 10px
       margin-top 20px

    h3, h4, h5, h6
       font-weight normal

改成:

    h1, h2
       font-weight normal
       border-bottom 1px solid color-border
       padding-bottom 10px
       margin-top 20px
       &:hover .headerlink:before
         content '#'
         float left
         padding-right 1em
         margin-left -0.8em
         position absolute

    h3, h4, h5, h6
       font-weight normal
       &:hover .headerlink:before
         content '#'
         float left
         padding-right 1em
         margin-left -0.8em
         position absolute

當游標移到H1~H6標題時,左邊便會自動顯示井字號錨點。

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

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

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

<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,將內容:

<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>

改成:

<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>

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

新增Google Adsense廣告區塊

側邊欄

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

<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區塊。

文章下方

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

編輯/layout/_partial/after_footer.ejs,搜尋<%- partial('post/category') %>,在上面加入:

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

新增側邊欄連結區塊

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

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

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

<% 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內容就可以了。

在彙整頁和分類頁新增上下頁

不知為何Light主題在這兩個頁面並無上下頁。編輯/themes/light/layout/archive.ejs(彙整)和/themes/light/layout/category.ejs(分類),在第一行下方加入:

<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>

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

新增TOC(Table of Contents)

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

  <% 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,加入:

/*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 Theme Light TOC

修改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,搜尋:

<% 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 %>';

改成:

<% 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 %>';
  };

搜尋引擎最佳化(SEO)

網頁加入canonical標記

安裝hexo-auto-canonical,編輯/themes/light/layout/_partial/head.ejs,加入:

<%- autoCanonical(config, page) %>

修改網頁描述

Head模版語法和其他主題相比,網頁描述語法的排列順序對搜尋引擎來說,並不友善,Google Search Console會提示出現很多重複的中繼說明。編輯/themes/light/layout/_partial/head.ejs,原始內容如下:

<!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">
  
  <%- partial('google_analytics') %>
</head>

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

<!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') %>
  
  <%- partial('google_analytics') %>
</head>

文章連結加入nofollow

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

nofollow:
  enable: true
  field: site
  exclude:
    - 'exclude1.com'
    - 'exclude2.com'

建立網站地圖

安裝hexo-generator-sitemap,編輯網站設定檔_config.yml,加入:

sitemap:
  path: sitemap.xml

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

新增RSS訂閱

Hexo預設沒有RSS,安裝hexo-generator-feed,編輯網站設定檔_config.yml,加入:

feed:
  type: atom
  path: atom.xml
  limit: 10

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