前言:
本系列文章翻譯自@Jonathan Klughertz的博客,將會用三篇文章的篇幅詳細講解如何製做一個Hexo主題。
我不是學翻譯出身,如有翻譯錯誤或是不到位之處,請指正。css
在這個系列教程中,你將學習怎麼從零開始製做一個Hexo主題。我很喜歡Hexo,而且天天都在使用,不幸的是,直到今天關於主題製做的文檔仍是至關稀缺。因此我打算彌補這個空缺。html
這個項目旨在製做一個Hexo主題並詳細瞭解Hexo引擎的工做方式。
我不想在HTML和CSS上花費太多時間,因此咱們將重置下面這個Hexo主題:https://getbootstrap.com/docs... 。它是Bootstrap文檔中的一個標準初始模板樣例。
咱們將一步步地重用CSS、複製粘貼HTML,直到最後實現想要的效果。
若是你感到困惑或者只對它的代碼感興趣,請前往github。html5
讓咱們從搭建一個全新的hexo博客開始吧jquery
# Create a new folder mkdir hexo-theme-creation cd hexo-theme-creation # Initialise Hexo hexo init
# Enter the theme folder cd themes # bootstrap-blog-hexo is also going to be the name of our theme mkdir bootstrap-blog-hexo
注意:若是你想在git中保存主題的話(你也應該這麼作),請在/themes/bootstrap-blog-hexo/
中初始化git。git
這是咱們開始工做所須要的文件和文件夾:github
|-- layout // .ejs templates |-- source // source files (CSS, scripts) |-- _config.yml
建立如下兩個文件夾和_config.yml文件。ajax
從bootstrap blog template複製全部咱們須要的源碼並放在source文件夾裏。你能夠選擇經過瀏覽器查看源碼並複製下來,或者是下載該壓縮包,以後解壓到source文件夾裏。bootstrap
|-- layout |-- source |-- bootstrap // Copy the boostrap library files here |-- css // Copy the blog's css file here |-- favicon |-- favicon.ico // Your choice of favicon |-- js // Copy the blog's js file here |-- _config.yml
在咱們開始寫第一個模板文件以前,先來看看Hexo博客生成過程的基本要素。api
咱們可以在主題中定義6種頁面類型,與之相對應地,在public文件夾生成的每個單獨的HTML頁面都屬於下面模板中的其中一個:瀏覽器
模板 | 備用模板 | 頁面描述 |
---|---|---|
index | 無 | 這是博客的首頁,也是網站的主要入口。本教程中咱們將讓其顯示文章摘要列表 |
post | index | 這是文章的詳情頁。咱們將展現一篇完整的文章以及一個評論區 |
page | index | 這是頁面的詳情頁,與post同樣,可是是page類型的post |
archive | index | 這是歸檔頁。它將顯示咱們博客中全部文章的標題和詳情頁連接 |
category | archive | 這是分類頁。與歸檔頁相似,可是會根據類別進行篩選 |
tag | archive | 這是標籤頁。與分類頁相似,可是會根據標籤進行篩選 |
在本篇教程中咱們將建立index模板。
在頁面生成過程當中,Hexo將會搜索名字爲index.ejs,post.ejs,page.ejs等的文件,這些模板以後用於建立靜態HTML頁面。
Hexo支持使用公共的佈局文件,上面的模板都將使用到該文件。
該文件命名爲layout.ejs。不一樣頁面類型的模板會建立一些內容,而這個文件就比如這些內容的「外殼」。
在咱們的主題中,公共佈局將包括:<html>
標籤、<head>
標籤、頭部、菜單、底部和側邊欄。基本上是全部類型的頁面都具有的元素。
不一樣的頁面模板將只負責建立實際內容,這些內容將放在咱們的主體部位。
在全部的模板中,咱們均可以使用hexo引擎提供的內置變量。如下是部分變量:
site
包含了網站的信息。例如,咱們能夠經過site.posts
訪問博客中的全部文章。當咱們想要顯示統計數據的時候,這將派上用場。page
是主要變量,包含了許多與當前頁面相關的信息,包括全部的文章標題、日期、內容等。config
是一個指向站點_config.yml
文件的JavaScript對象theme
是一個指向主題_config.yml
文件的JavaScript對象上面說起了/layout/layout.ejs
文件,如今咱們開始來建立它。
首先建立layout.ejs文件並插入<html></html>
標籤
//layout/layout.ejs <html> <!-- Head tag --> <%- partial('_partial/head') %> </html>
這裏咱們將全部<head>
標籤裏的代碼提取出來並放在局部視圖中,這有助於實現關注點分離和代碼重用。
語法是partial('path' [, arguments])
在建立layout/_partial/head.ejs
文件後,從bootstrap源碼中複製head標籤裏的代碼:
// layout/_partial/head.ejs <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content=""> <link rel="icon" href="favicon/favicon.ico"> <title>Blog Template for Bootstrap</title> <!-- Bootstrap core CSS --> <%- css('bootstrap/css/bootstrap.min.css') %> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <%- css('css/ie10-viewport-bug-workaround.css') %> <!-- Custom styles for this template --> <%- css('css/blog.css') %> <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries --> <!--[if lt IE 9]> <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script> <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script> <![endif]--> </head>
這很簡單,咱們只需使用CSS helper插入樣式表。
source文件夾中的文件將會被複制到站點根目錄下,因此不要在路徑中包含source/
咱們將讓<title>
和<meta>
標籤保持動態,不過如今先暫且無論它們。
底部標籤位於</body>
以前。咱們將在這個局部視圖中包含全部腳本。
先修改一下佈局:
// layout/layout.ejs <html> <!-- Head tag --> <%- partial('_partial/head') %> <body> <!-- After footer scripts --> <%- partial('_partial/after-footer') %> </body> </html>
而後建立layout/_partial/after-footer.ejs
的內容:
// layout/_partial/after-footer.ejs <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <%- js('bootstrap/js/bootstrap.min.js') %> <!-- IE10 viewport hack for Surface/desktop Windows 8 bug --> <%- js('js/ie10-viewport-bug-workaround.js') %>
注意JS helper function的使用,它將引用本地js文件。
相似地,在<body>
標籤後建立頂部菜單。
// layout/layout.ejs // [...] <body> <!-- Menu --> <%- partial('_partial/menu') %> // [...]
layout/_partial/menu.ejs
的內容:
// layout/_partial/menu.ejs <div class="blog-masthead"> <div class="container"> <nav class="blog-nav"> <% for (var i in theme.menu){ %> <a class="blog-nav-item" href="<%- url_for(theme.menu[i]) %>"><%= i %></a> <% } %> </nav> </div> </div>
注意theme
全局變量的使用,它指向的是主題的_config.yml
文件。爲了能夠在主題配置中配置菜單,咱們須要在_config.yml
文件中添加配置:
_config.yml # Header menu: Home: / Archives: /archives
在menu.ejs
中咱們遍歷了配置文件中全部的菜單項目並建立對應的連接。
頂部將位於頂部菜單下面,它包含了博客標題和子標題:
// layout/_partial/header.ejs <div class="blog-header"> <h1 class="blog-title"><%= config.title %></h1> <p class="lead blog-description"><% if (config.subtitle){ %><%= config.subtitle %><% } %></p> </div>
這裏咱們使用了指向站點_config.yml
文件的config
變量,它包含了可供配置的標題和子標題屬性。
注意在佈局的<div class="container"><div>
中嵌套頂部:
// layout/layout.ejs <html> <!-- Head tag --> <%- partial('_partial/head') %> <body> <!-- Menu --> <%- partial('_partial/menu') %> <div class="container"> <!-- Blog Header: title and subtitle --> <%- partial('_partial/header') %> </div> // [...]
底部如今是徹底靜態的,內容以下:
// layout/_partial/footer.ejs <footer class="blog-footer"> <p>Blog template built for <a href="http://getbootstrap.com">Bootstrap</a> by <a href="https://twitter.com/mdo">@mdo</a>.</p> <p>Adapted to Hexo by <a href="http://www.codeblocq.com/">klugjo</a>.</p> <p><a href="#">Back to top</a></p> </footer>
此時,咱們再加上主要內容和側邊欄,基本就差很少了。
下面是最終的layout.ejs
:
// layout/layout.ejs <html> <!-- Head tag --> <%- partial('_partial/head') %> <body> <!-- Menu --> <%- partial('_partial/menu') %> <div class="container"> <!-- Blog Header: title and subtitle --> <%- partial('_partial/header') %> <div class="row"> <!-- Main Content --> <div class="col-sm-8 blog-main"> <%- body %> </div> <!-- Sidebar --> <div class="col-sm-3 col-sm-offset-1 blog-sidebar"> <%- partial('_partial/sidebar') %> </div> </div> </div> <!-- Footer --> <%- partial('_partial/footer') %> <!-- After footer scripts --> <%- partial('_partial/after-footer') %> </body> </html>
body
變量對應了不一樣頁面類型模板建立的內容(參見上面)。
至於側邊欄,咱們如今暫且使用來自bootstrap模板的硬編碼:
// layout/_partial/sidebar.ejs <div class="sidebar-module sidebar-module-inset"> <h4>About</h4> <p>Etiam porta <em>sem malesuada magna</em> mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.</p> </div> <div class="sidebar-module"> <h4>Archives</h4> <ol class="list-unstyled"> <li><a href="#">March 2014</a></li> <li><a href="#">February 2014</a></li> <li><a href="#">January 2014</a></li> <li><a href="#">December 2013</a></li> <li><a href="#">November 2013</a></li> </ol> </div> <div class="sidebar-module"> <h4>Elsewhere</h4> <ol class="list-unstyled"> <li><a href="#">GitHub</a></li> <li><a href="#">Twitter</a></li> <li><a href="#">Facebook</a></li> </ol> </div>
佈局到位後,咱們就能夠開始建立第一個頁面類型模板inde.ejs了。
這是比較簡陋的第一個版本:
// layout/index.ejs <span>Content</span>
別小瞧它,咱們能夠用這個在瀏覽器中測試主題:
# Verify that everything is alright hexo generate # Start hexo server hexo server
訪問 http://localhost:4000/ 。哇!
注意:不要忘記在站點的config文件中更新主題:
_config.yml # Extensions ## Plugins: http://hexo.io/plugins/ ## Themes: http://hexo.io/themes/ theme: bootstrap-blog-hexo
咱們想要在首頁顯示各篇文章的摘要。
首先,在咱們的index.ejs文件中遍歷文章:
// layout.index.ejs <% page.posts.each(function(item){ %> <%- partial('_partial/article-excerpt', {item: item}) %> <% }); %>
page.posts
獲取該頁面的全部文章<%- partial('name', args) %>
給partial傳參建立article-excerpt.ejs
文件,添加適合主題的代碼。這是個人佈局:
// layout/_partial/article-excerpt.ejs <div class="blog-post"> <!-- Title --> <h2 class="blog-post-title"> <a href="<%- config.root %><%- item.path %>"> <%- item.title %> </a> </h2> <!-- Date and Author --> <p class="blog-post-meta"> <%= item.date.format(config.date_format) %> <% if(item.author) { %> by <%- item.author %> <% } %> </p> <!-- Content --> <%- item.excerpt || item.content %> <!-- Only display the Read More link if we are displaying an excerpt --> <% if(item.excerpt) { %> <p> <a href="<%- config.root %><%- item.path %>"> <%= theme.excerpt_link %> </a> </p> <% } %> </div>
全文連接是由config.root
(配置選項,至關於/
)和item.path
(相對路徑或者絕對路徑,指向全文)鏈接組成的。
默認狀況下,Hexo沒有關於做者屬性的的文章變量。不過咱們能夠在front matter中添加任意本身想要的變量。
若是你想要在文章中顯示做者名字,那麼文章的front matter應該相似以下進行設置:
title: Hello World author: Klughertz Jonathan ---
當用Hexo編輯文章時,你能夠用<!-- more -->
標籤從文章內容中截取摘要。在本教程中,由於咱們展現的是文章列表,因此選擇顯示摘要。以後用戶能夠經過點擊文章標題或者「閱讀更多」的連接瀏覽全文。
別忘了,你須要像我這樣在主題的配置文件中添加一個新的屬性:
_config.yml # Read More text excerpt_link: Read More
但願接下來的代碼容易理解。如今,我建議你寫一些除了默認的Hello World以外的文章並享受這個結果。
在本篇文章中,咱們最後須要處理的是首頁的分頁器。
在index.ejs
文件中增長一個分頁器的partial:
// layout/index.ejs <% page.posts.each(function(item){ %> <%- partial('_partial/article-excerpt', {item: item}) %> <% }); %> <%- partial('_partial/pagination') %>
以後開始建立分頁器的內容,layout/_partial/pagination.ejs
:
// layout/_partial/pagination.ejs <nav> <ul class="pager"> <% if (page.prev){ %> <li><a href="<%- config.root %><%- page.prev_link %>">Previous</a></li> <% } %> <% if (page.next){ %> <li><a href="<%- config.root %><%- page.next_link %>">Next</a></li> <% } %> </ul> </nav>
page.prev
:上一頁的頁碼。若是當前頁是第一頁,則爲0page.next
:下一頁的頁碼。若是當前頁是最後一頁,則爲0page.next_link
和page.prev_link
是什麼就不用多說了。若是你沒有足夠的文章用來查看分頁器的工做效果,能夠在主配置文件中(per_page
屬性)調整每一頁的文章數。
這就是今天的內容,在下一篇教程中,咱們將完成博客剩下的全部頁面。