從零開始制作 Hexo 主題


原文地址: 從零開始制作 Hexo 主題 · Ahonn

樣式參考網站:https://blankj.com/

圖片參考網站:http://www.sitecube.com/signup.php

寫在前面

本文將會從零開始開發一個簡單的博客主題。樣式主要參考 Hexo theme 中的 Noise 主題。

開始之前你需要了解:

  • 模板引擎 ejs官網

  • CSS預處理器

  • Hexo 文檔

本文使用的模板引擎為 ejs,使用的 CSS 預處理器為 stylus。這也是 hexo 項目預裝了的 render 插件,如果想使用其他模板引擎或者其他 CSS 預處理器,可以安裝相對應的 render 插件。例如我的 Even 主題使用的是 Swig 與 SCSS。

目錄結構

主題目錄結構以自帶的 landscape 主題為例:

.
├── languages  語言文件,用於國際化
├── layout     頁面模板文件
├── scripts    Hexo 腳本
└── source 主題資源文件,包括頁面樣式,腳本,字體等

我們在 themes 中新建 theme-example 文件夾,然后在 theme-demo 中按照 landscape 主題的目錄結構新建 languageslayoutscripts 與 source 文件夾。

創建布局模板

在 layout 中創建 index.ejs 文件,首頁將會使用該布局模板生成 HTML 文件。

layout/index.ejs:

<html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <title>Home</title> </head> <body> <h1>Hello Word</h1> </body> </html>

修改站點配置文件中的主題配置,使用我們剛剛創建的 theme-example 主題:

# Extensions ## Plugins: https://hexo.io/plugins/ ## Themes: https://hexo.io/themes/ theme: theme-example

運行

hexo clean   清除public靜態文件

hexo generate 生成public靜態文件

hexo server --debug 以 debug 模式開啟 Hexo 本地服務器預覽,訪問 http://localhost:4000/

Hello World

 

 

寫作

在工作文件夾中執行這條命令來新建一篇文章,title即為文章的標題。

$ hexo new <title>  

終端會返回一條信息,告訴你文章源文件存放在哪里:

 

添加頁面導航

現在我們需要在頁面中添加導航,由於導航不單單會在首頁出現,所以我們在 layout 中創建共用的布局文件 layout.ejs, 同時創建 _partial/head.ejs 保存 HTML 的 head 以及創建 _partial/header.ejs 文件,編寫頁面導航部分。

layout/layout.ejs:

<!DOCTYPE html> <html> <%- partial('_partial/head') %> <body> <%- partial('_partial/header') %> <main class="main"> <%- body %> </main> </body> </html>

layout.ejs 文件通過 partial() 函數來包含其他文件,使得我們能夠更好的組織代碼。詳見 Templates | Hexo

layout/_partial/head.ejs:

<head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <title><%= config.title %></title> </head>

這里使用了 config 變量,該變量包含的是站點配置(即站點根目錄下 _config.yml 中的配置)。除此之外,Hexo 還提供了許多變量可在模板中使用,詳見 Variables | Hexo

layout/_partial/header.ejs:

<header class="header"> <div class="blog-title"> <a href="<%- url_for() %>" class="logo"><%= config.title %></a> </div> <nav class="navbar"> <ul class="menu"> <li class="menu-item"> <a href="/" class="menu-item-link">Home</a> </li> <li class="menu-item"> <a href="/archives" class="menu-item-link">Archive</a> </li> </ul> </nav> </header>

接着我們清空 index.ejs 中的內容,並添加 <h2>Hello World</h2>。在 layout 目錄下的 index.ejs 會自動繼承 layout.ejs,並將其中的內容填入 <%- body %> 的位置。我們將得到一個有導航菜單的 Hello World 頁面。

添加主題配置文件

實際上我們需要讓導航菜單根據我們的需要顯示不同的項,上面這種寫法不方便修改。所以我們會在主題的配置文件中添加導航菜單的配置。在 thmem-demo 下新建主題的配置文件 _config.yml,在其中添加需要配置的字段。然后可以通過 theme這個變量來拿到該配置文件中的配置。

theme-demo/_config.yml:

menu: Home: / Archives: /archives

這樣我們就可以在 header.ejs 中使用 theme.menu 獲取到導航菜單的設置。將 header.ejs 修改為:

<header class="header"> <div class="blog-title"> <a href="<%- url_for() %>" class="logo"><%= config.title %></a> </div> <nav class="navbar"> <ul class="menu"> <% for (name in theme.menu) { %> <li class="menu-item"> <a href="<%- url_for(theme.menu[name]) %>" class="menu-item-link"><%= name %></a> </li> <% } %> </ul> </nav> </header>

當需要在導航中添加鏈接的時候就可以在配置文件中直接添加,例如添加 Github 的鏈接:

menu: Home: / Archives: /archives Github: https://github.com/ahonn

除此之外還可以添加其他需要的配置,例如 RSS,評論等等。

添加首頁文章列表

接着我們完善首頁的模板,使其能夠顯示文章列表。前面已經說過 Hexo 提供了各種有用的變量,在這里將會使用到 page這個變量。page 會根據不同的頁面擁有不同的屬性。具體有什么屬性,可以獲取到哪些數據可以查看這里

那么這里我們會使用 page 變量的 posts 屬性拿到文章數據的集合。編輯 index.ejs 文件:

<section class="posts"> <% page.posts.each(function (post) { %> <article class="post"> <div class="post-title"> <a class="post-title-link" href="<%- url_for(post.path) %>"><%= post.title %></a> </div> <div class="post-content"> <%- post.content %> </div> <div class="post-meta"> <span class="post-time"><%- date(post.date, "YYYY-MM-DD") %></span> </div> </article> <% }) %> </section>

從 page.posts 中獲取單篇文章的數據,並獲取文章的標題,內容等數據填充到模板中。處理文章創建時間的時候使用了 date() 函數,這是 Hexo 提供的時間處理的輔助函數。本文中使用到的函數如無特別說明,即為 Hexo 的輔助函數。

文章摘錄

由於首頁顯示文章內容時使用的是 post.content,即文章的全部內容。所以首頁會顯示每一篇文章的內容,實際上我們並不想在首頁顯示那么多內容,只想顯示文章的摘錄。

Hexo 提供了 excerpt 屬性來獲取文章的摘錄部分,不過這里需要在文章中添加一個 <!-- more --> 標記。添加了這個標記之后,post.excerpt 將會獲取到標記之前的內容。如果沒有這個標記,那么 post.excerpt 會是空的。所以我們可以把首頁文章內容部分的 post.content 替換成 post.excerpt

<div class="post-content"> <%- post.excerpt %> </div>

添加頁面樣式

到目前為止,我們完成了首頁的頁面結構,但是並沒有添加樣式,所以看起來很丑。我們在 source 文件中創建一個 css 文件夾來存放樣式文件。

由於 Hexo 在新建項目的時候會安裝 hexo-renderer-stylus 這個插件,所以我們無需其他步驟,只需要將樣式文件放到 css 文件夾中。Hexo 在生成頁面的時候會將 source 中的所有文件復制到生成的 public 文件中,並且在此之前會編譯 styl 為 css 文件。

在 css 文件夾中創建 style.styl,編寫一些基礎的樣式,並把所有樣式 import 到這個文件。所以最終編譯之后只會有 style.css 一個文件。創建 _partial/header.styl 與 _partial/post.style 存放頁面導航以及文章的樣式,並且在 style.styl 中 import 這兩個文件。

_partial/header.styl:

.header { margin-top: 2em display: flex align-items: baseline justify-content: space-between .blog-title .logo { color: #AAA; font-size: 2em; font-family: "Comic Sans MS",cursive,LiSu,sans-serif; text-decoration: none; } .menu { margin: 0; padding: 0; .menu-item { display: inline-block; margin-right: 10px; } .menu-item-link { color: #AAA; text-decoration: none; &:hover { color: #368CCB; } } } }

_partial/post.style:

.post {
  margin: 1em auto; padding: 30px 50px; background-color: #fff; border: 1px solid #ddd; box-shadow: 0 0 2px #ddd; } .posts { .post:first-child { margin-top: 0; } .post-title { font-size: 1.5em; .post-title-link { color: #368CCB; text-decoration: none; } } .post-content { a { color: #368CCB; text-decoration: none; } } .post-meta { color: #BABABA; } }

style.styl:

body { background-color: #F2F2F2; font-size: 1.25rem; line-height: 1.5; } .container { max-width: 960px; margin: 0 auto; } @import "_partial/header"; @import "_partial/post";

最后,我們需要把樣式添加到頁面中,這里使用了另外一個輔助函數 css():

layout/_partial/head.ejs

<head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport"> <title><%= config.title %></title> <%- css('css/style.css') %> </head>

至此,我們會看到站點的首頁是這個樣子的:

添加分頁

在站點的 source/_post/ 目錄下存放的是我們的文章,現在我們把原本的 hello-world.md 復制黏貼 10+ 次,再查看站點首頁。會發現,首頁只顯示了 10 篇文章。

首頁顯示的文章數量我們可以通過站點配置文件中的 per_page 字段來修改,但是我們不可能把所有文章都放在一頁,所以我們現在來添加文章列表的分頁。

新建 _partial/paginator.ejs:

<% if (page.total > 1){ %> <nav class="page-nav"> <%- paginator({ prev_text: "&laquo; Prev", next_text: "Next &raquo;" }) %> </nav> <% } %>

在 index.ejs 中添加這個文件的內容:

...
</section> <%- partial('_partial/paginator') %>

這里我們使用到了另外的一個輔助函數 paginator,它能夠幫助我們插入分頁鏈接。

添加文章詳情頁

文章詳情頁對應的布局文件是 post.ejs,新建 post.ejs:

<article class="post"> <div class="post-title"> <h2 class="title"><%= page.title %></h2> </div> <div class="post-meta"> <span class="post-time"><%- date(page.date, "YYYY-MM-DD") %></span> </div> <div class="post-content"> <%- page.content %> </div> </article>

由於這里是文章的模板,所以變量 page 表示的是文章的數據,而不是首頁的文章數據集合。

添加歸檔頁

創建歸檔頁使用的模板文件 archive.ejs:

<section class="archive"> <ul class="post-archive"> <% page.posts.each(function (post) { %> <li class="post-item"> <span class="post-date"><%= date(post.date, "YYYY-MM-DD") %></span> <a class="post-title" href="<%- url_for(post.path) %>"><%= post.title %></a> </li> <% }) %> </ul> </section> <%- partial('_partial/paginator') %>

其實結構跟首頁差不多,只是不顯示文章內容而已。添加歸檔頁的樣式:

css/_partial/archive.styl:

.archive { margin: 1em auto; padding: 30px 50px; background-color: #fff; border: 1px solid #ddd; box-shadow: 0 0 2px #ddd; .post-archive { list-style: none; padding: 0; .post-item { margin: 5px 0; .post-date { display: inline-block; margin-right: 10px; color: #BABABA; } .post-title { color: #368CCB; text-decoration: none; } } } }

國際化

還記得我們一開始創建的 languages 文件夾嗎?沒錯,它是用來添加多種語言,用於 i18n 的。站點的語言設置為站點配置文件中的 language

當該字段為空時,默認使用的是 languages/default.yml 這個文件。那么現在我們來添加這個文件,我們決定主題的默認語言是英文:

Menu: Home: Home Archives: Archives Github: Github Paginator: Prev: Prev Next: Next

目前我們需要主題根據選擇的語言自動修改的有上面這些,接着我們需要修改 header.ejs 與 paginator.ejs 這兩個文件:

_partial/header.ejs

<header class="header"> <div class="blog-title"> <a href="<%- url_for() %>" class="logo"><%= config.title %></a> </div> <nav class="navbar"> <ul class="menu"> <% for (name in theme.menu) { %> <li class="menu-item"> <a href="<%- url_for(theme.menu[name]) %>" class="menu-item-link"><%- __('Menu.' + name) %></a> </li> <% } %> </ul> </nav> </header>

_partial/paginator.ejs:

<% if (page.total > 1){ %> <nav class="page-nav"> <%- paginator({ prev_text: "&laquo;" + __('Paginator.Prev'), next_text: __('Paginator.Next') + "&raquo;" }) %> </nav> <% } %>

修改之后其實與之前相比沒有什么變化,起碼看起來是。現在我們添加一個中文的文件:

languages/zh-CN.yml

Menu: Home: 首頁 Archives: 歸檔 Github: 交友 Paginator: Prev: 上一頁 Next: 下一頁

然后我們將站點配置文件中的 language 字段修改為 zh-CN(與 zh-CN.yml 文件名相同)。再次訪問站點之后就會發現導航與分頁部分的文字變成了中文。

hexo函數

<%- __('Menu.' + name) %>

__下划線函數在 hexo 變量 可以查看 Lodash 函數,專門用於json取值

最后總結

如果你有耐心看我廢話了這么多的話,恭喜你,你應該對怎么去寫一個 Hexo 主題有了一定的了解。其實說白了,Hexo 就是把那些 Markdown 文件按照不同的布局模板,填上對應的數據生成 HTML 頁面,復制 source 中的到生成的 public 文件夾中,中間過程會把需要編譯的 stylus/less/sass 等文件編譯。

本文並沒有提及有關頁面 JavaScript 的部分,實際上與寫 CSS 樣式相同。在 source/js 中寫 JavaScript 腳本,然后在模板中引入即可。

感謝閱讀,希望對你有所幫助。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM