Hexo 博客主题定制指南
blog
本文字数:3.2k 字 | 阅读时长 ≈ 14 min

Hexo 博客主题定制指南

blog
本文字数:3.2k 字 | 阅读时长 ≈ 14 min

1. 前言

本文将从零开始编写一个简单的 Hexo 博客主题,帮助读者了解 Hexo 主题的构成和开发方法

1.1 前置知识

开始前,你需要了解:

1.2 Hexo 官方文档

关于自定义主题的官方文档介绍,可以参考 Hexo 官方文档

1.3 Hexo 初始化

首先新建一个 test 文件夹,然后执行 hexo init 初始化为 hexo 博客

➜  test hexo init
INFO  Cloning hexo-starter https://github.com/hexojs/hexo-starter.git
INFO  Install dependencies
INFO  Start blogging with Hexo!

之后可以初始化出当前列表

.
├── _config.landscape.yml
├── _config.yml
├── .github/
├── .gitignore
├── node_modules/
├── package.json
├── package-lock.json
├── scaffolds/
├── source/
└── themes/

同时, hexo-blog 目录下会生成以下文件:

然后执行 sudo npm install 进行依赖包的安装

2. 主题基础结构

2.1 目录结构

在 themes 目录下新建 iwiki 文件夹作为主题目录。一个 Hexo 主题主要包含以下目录:

2.2 局部模板

常见博客网站主要由三部分组成:

每次页面跳转时,顶部导航栏和底部信息是不变的,只有中间内容区域需要重新渲染。因此,我们将通用部分抽离为局部模板。

在 layout 目录下新建_partial 目录,创建以下文件:

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>标题</title>
</head>

layout/_partial/header.ejs 中:

<header>我是导航栏</header>

layout/_partial/footer.ejs 中:

<footer>我是底部信息</footer>

我们在 layout 中创建 layout.ejs,并引入 head.ejs,header/ejs 和 footer.ejs 文件,layout.ejs 文件是通用的布局文件模板,我们在后面新增的 ejs 文件都会继承 layout.ejs,并将其内容填充到 body 中。

在 layout 目录中创建 layout.ejs 作为主布局文件。这个文件将作为所有页面的基础模板,其他页面模板都会继承它。我们在这个文件中引入之前创建的 head.ejsheader.ejsfooter.ejs 局部模板,新创建的页面内容将被注入到 <%- body %> 的位置。

创建主布局文件 layout/layout.ejs

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

2.3 第一个首页

局部模板设置完毕后,我们开始正式的主页的开发

首页是网站加载完毕后的第一个页面。创建 layout/index.ejs

<h1>Hello World</h1>

修改站点配置文件中的主题配置,使用我们刚刚创建的 iwiki 主题:

# Extensions
theme: iwiki

运行以下命令在本地服务器进行预览: hexo server 服务启动后,通过访问 http://localhost:4000 即可预览网站。内容如下

图 1: Hexo 博客预览效果

3. 主题开发步骤

在开始主题开发之前,开发者需要深入理解以下两个核心文档,它们是 Hexo 主题开发的基础:

3.1 核心文档

开发主题前,建议先熟悉以下两个重要文档:

  1. Hexo 变量文档 - 包含全局变量、页面变量等系统内置变量,用于在模板中获取数据
  2. Hexo 辅助函数文档 - 提供 URL 处理、HTML 生成等常用函数,用于简化模板开发

3.2 更新导航栏和底部信息

修改下面三个文件
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>

layout/_partial/header.ejs 中:

<header class="header">
    <div class="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="/categories" class="menu-item-link">Categories</a>
            </li>
            <li class="menu-item">
                <a href="/tags" class="menu-item-link">Tags</a>
            </li>
            <li class="menu-item">
                <a href="/archives" class="menu-item-link">Archives</a>
            </li>
        </ul>
    </nav>
</header>

layout/_partial/footer.ejs 中:

<footer>
    <p>Theme is <a href="/" target="_blank">Theme-example</a> by <a href="<%= config.url %>" target="_blank"><%= config.author %></a></p>
    <p>Powered by <a href="https://hexo.io/" target="_blank" rel="nofollow">hexo</a> &copy; <%- date(Date.now(), 'YYYY') %></p>
</footer>

这样,我们就得到了一个包含导航栏和底部信息的简单页面

图 2: Hexo 博客更改 header 和 footer

3.3 添加文章列表

实际上我们需要让导航菜单根据我们的需要显示不同的项,上面这种写法不方便修改。所以我们会在主题的配置文件中添加导航菜单的配置。在 iwiki 下的配置文件 _config.yml,在其中添加需要配置的字段。然后可以通过 theme 这个变量来拿到该配置文件中的配置。

修改 iwiki/_config.yml

menu:
  home: /
  categories: /categories
  tags: /tags
  archives: /archives

这样我们就可以在 header.ejs 中使用 theme.menu 获取到导航菜单的设置。将 header.ejs 修改为:

<header class="header">
    <div class="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>

接下来我们添加文章列表,这里我们会使用 page 变量的 posts 属性拿到文章数据的集合。编辑 layout/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 提供的时间处理的辅助函数。由于首页显示文章内容时使用的是 post.content,即文章的全部内容。所以首页会显示每一篇文章的内容,实际上我们并不想在首页显示那么多内容,只想显示文章的摘录。Hexo 提供了 excerpt 属性来获取文章的摘录部分,不过这里需要在文章中添加一个 <!--more--> 标记。添加了这个标记之后,post.excerpt 将会获取到标记之前的内容。如果没有这个标记,那么 post.excerpt 会是空的。所以我们可以把首页文章内容部分的 post.content 替换成 post.excerpt

这里我们将默认的 hello word 文章中加入一个 <!--more-->, 如下

图 3: Hello World 添加 <!--more--> 标记

3.4 美化主题页面

到目前为止,我们完成了首页的整体页面结构,不过由于没添加 css 样式,因此整体页面非常难看,所以我们需要给页面加上一些样式来美化一下我们的页面。

在 css 文件夹中创建 style.css,编写一些基础的样式,并把所有样式 import 到这个文件。所以最终编译之后只会有 css/style.css 一个文件。创建 css/partial/header.csscss/partial/index.css 存放页面导航以及文章的样式,并且在 style.css 中 import 这两个文件。

css/style.css

@import "./partial/header.css";
@import "./partial/index.css";

body {
    background-color: #F2F2F2;
    font-size: 1.25rem;
    line-height: 1.5;
}

.container {
    max-width: 960px;
    margin: 0 auto;
}

css/partial/header.css

.header {
    margin-top: 2em;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
}

.header .blog-title .logo {
    color: #AAA;
    font-size: 2em;
    font-family: "Comic Sans MS", cursive, LiSu, sans-serif;
    text-decoration: none;
}

.header .menu {
    margin: 0;
    padding: 0;
}

.header .menu .menu-item {
    display: inline-block;
    margin-right: 10px;
}

.header .menu .menu-item-link {
    color: #AAA;
    text-decoration: none;
}

.header .menu .menu-item-link:hover {
    color: #368CCB;
} 

css/partial/index.css

.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;
}

.posts .post-title {
    font-size: 1.5em;
}

.posts .post-title .post-title-link {
    color: #368CCB;
    text-decoration: none;
}

.posts .post-content a {
    color: #368CCB;
    text-decoration: none;
}

.posts .post-meta {
    color: #BABABA;
}

注意,这里要创建的文件是 partial,而不是 _partial,以下划线(_)开头的文件夹默认会被 Hexo 忽略,导致最终生成的 public 文件夹中无法包含 index.css 和 header.css 两个文件

themes/iwiki/source/css/
├── style.css
└── partial/
    ├── header.css
    └── index.css

最终展示效果如下

图 4: 美化主题

一些其他的参数解释

博客的 page.post

在 Hexo 中,page.posts 通常用于引用与当前页面相关的文章集合。这个变量特别用于那些需要列出文章的页面,如博客的首页、分类页面或标签页面等。

在 Hexo 中,文章常存放在 source/_posts 目录下。当你使用命令 hexo new "post title" 创建一篇新文章时,Hexo 会自动在这个目录下生成一个新的 Markdown 文件。这个文件的文件名通常是文章标题的小写形式,并用短横线(-)替换空格。

例如,如果你创建一篇标题为 “My First Post” 的文章,Hexo 将在 source/_posts 目录下创建一个名为 my-first-post.md 的文件。你可以在这个文件中编写你的文章内容,然后使用 hexo generate 命令生成静态页面,或使用 hexo server 在本地预览你的网站。

如何使用 page.posts

在你的主题模板文件中,可以使用 page.posts 来访问当前页面相关的文章数据。这使得模板能够动态地列出文章,例如在博客的首页或者分类页显示文章列表。这里是一个简单的例子,展示如何在模板中使用 page.posts

<ul>
  {% for post in page.posts %}
    
  • {{ post.title }}

    {{ post.date.format('YYYY-MM-DD') }}

    {{ post.excerpt }}

  • {% endfor %} </ul>

    这段代码会遍历 page.posts 中的所有文章,并为每篇文章生成一个包含标题、发布日期和摘要的列表项。

    总结来说,source/_posts 是存放文章的默认录,而 page.posts 是在模板中用来引用这些文章的变量,用于生成文章列表等功能。

    12月 14, 2023
    8月 10, 2022
    10月 06, 2021