0

Hexo 模版初入门和指北

 2 years ago
source link: https://paugram.com/coding/hexo-template-learning-startup.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Hexo 模版初入门和指北

Hexo 模版初入门和指北

2021.08.31进击的码农 2 106

今天晚上直播 Hexo 主题初入门,主要目标是将我的 Typecho 老牌主题 Single 移植 Hexo,也就是 GitHub 上我新开的 Hingle 仓库。什么?你竟然不知道我在 B 站直播写代码?还不 赶紧关注

打开 Hexo 官网,进入眼帘的第一步,就是首先安装需要的命令行工具。

简单几条命令即可完成,hexo-cli 可以理解成方便你初始化和管理一个 Hexo 博客的命令行工具。

yarn global add hexo-cli
hexo init Hexo-Playground
cd Hexo-Playground
hexo server

如果过程出现错误,那大部分是因为 GitHub 访问不上导致的(阿里云的 Windows 服务器上死都拿不到,挂全局代理也不行,太坑了,也不知道为什么)

编写 Hexo 模板使用的是 EJS 语法,模板里面主要用到的写法,大概有这些:

<%= date() %> // 转义输出表达式返回的内容(纯文本)
<%- paginator() %> // 直接输出表达式返回的内容(一般是 HTML)

// JS 逻辑块(不得不说,这种写法下只能把 else 和两括号放一行了)
<% if (true) { %>
<% } else { %>
<% } %>

虽然没特别学习过 EJS,但总体来说和 PHP 还是大同小异,并不是很困难。

由于没有任何 Hexo 的开发经验,于是就从官方的文档一步一步开始看起。定位到 Hexo 目录的 themes,创建一个文件夹,这里以 hingle 为例。官方文档 的描述我就不详细扯了,以下是我对主题结构的个人理解和汇总:

如果你写过 Next.JS 项目,可以把 layout.ejs 理解成 _document.tsx 生成网站根结构。它放在 layouts 文件夹里面,是不是只看官方文档的话就会很懵逼呢?

- source(前端静态文件)
- languages(国际化,暂无需求先忽略)
- layouts(布局相关模板)
--- _partial(内容切片)
------ head.ejs(页头、CSS、Link 等标签)
------ header.ejs(页头,各种菜单等)
------ footer.ejs(页尾和 JS)
--- layout.ejs(放 HTML,根架构)
--- post.ejs(文章模版)
--- page.ejs(页面模板)
--- index.ejs(首页模版)
--- archive.ejs(归档页面模板)

这个架构我感觉 官方文档 也没详细说清楚,尤其是 layouts 文件夹里面要有个 layout.ejs 这个情况,我还是参考了 官方模板 才得出的结论。

期间我还错误的将 layouts.ejs 的内容放到了 index.ejs 里面(虽说刚开始也能用,但其实后续加了模板之后你会发现是错的)。

不得不说,官方中文文档的质量真的很一般。

引入主题资源

在输出页面之前,我需要引入主题的样式和 JS,分别放在 Header 和 Footer 里面,使用内置函数 css()script() 函数引入即可,支持字符串或数组形式。

<!-- Head -->
<head>
  <meta charset="UTF-8">
  <title><%= page.title %></title>
  <%- css("static/kico.css", "static/hingle.css") %>
</head>
<!-- Footer -->
<%- js(["static/kico.js", "static/hingle.js"]) %>

在我这个架构里面,head.ejs 输出 head 标签的内容,header.ejs 里面输出 header,是我比较常用的方式。虽说内置的 partial() 函数可以传参数实现「模块化」管理,实现各个小模块的切片(很像 React/Vue 的组件概念),但我现阶段还是以化繁为简为主,前期方便理解一些。

随后就是各个页面的函数替代工作,需要将 PHP 的输出换成对应的 EJS 语法。Hexo 的核心变量我们经常用到的,大概就这些:

名称用途site网站变量page页面变量(包括文章)config网站配置(Hexo 路径下的 _config.yml)theme主题配置(使用主题路径下的 _config.yml)

首先是网站首页,这个页面主要是将博文进行遍历和输出,这里使用 page.posts 全局变量完成。这个变量返回多个子对象,可以拿到文章的 title categories path excerpt date 等属性。

首页才有 page.posts 对象,如果是文章页面,这个对象估计就是不存在的了,所以需要注意判断和使用

  • config.title 站点名称
  • config.description 站点介绍

page 变量在不同页面情况下的值不相同,这个需要注意。这块 官网文档 都有详细说明,对照着来就行。

文章页有一处用户自定义的选项,叫做「作者信息」。这块需要使用到主题 theme 变量,这需要将主题路径的 _config.yml 配置起来才行。

author: 'Paul'
author_avatar: ''
author_text: ''

对应的输出:

<% if (theme.author && theme.author_text) { %>
    <section class="post-author">
    <% if (theme.author_avatar) { %>
        <figure class="author-avatar">
            <img src="<%- theme.author_avatar %>" alt="<%= theme.author %>" />
        </figure>
    <% } %>
        <div class="author-info">
            <h4><%= theme.author %></h4>
            <p><%- theme.author_text %></p>
        </div>
    </section>
<% } %>

代码片段,就是前面提到的 _partial 文件夹下的 Header Footer 了。这里面用到的属性基本上和前面提到的大同小异,但是有一些功能是不能直接用变量获取,需要一个叫做「辅助函数」的操作才能实现。

一些属性无法直接使用,需要配合“辅助函数”完成。最简单的例子就是你博客主页的文章分页器,这玩意儿总不可能自己遍历一次数组吧,DOM 结构自己拼一次也挺麻烦。这就是它存在的意义了。在我的 Hingle 主题里面,初步用到了这些函数:

  • list_posts 列出博文(List 的函数都是 A 链接形式)
  • list_categories 列出文章所属分类(支持传对象,不传就是全部,可以去掉列表结构)
  • list_tags 列出文章包含的标签
  • paginator 输出分页器(无法自定义结构)
  • tagcloud 输出标签云,随机大小
  • url_for 输出地址(空就是站点地址,带相对链接就转换为绝对链接)
  • url_for() 输出站点首页链接
  • url_for(post.path) 输出文章链接
  • date(new Date(), "YYYY.MM.DD") 格式化输出当前时间

它们可以帮你生成一个 ul 列表,或是一个全是 a 的序列等等,这些函数的使用情形放在侧边栏、页脚一类的地方比较合适,比你用 for 遍历是要方便不少。更多辅助函数,可以看看 官方文档
上的其他说明。

文档的大坑

直播过程中踩了个大坑,就是我文章页面底部位置需要调用上下两篇间隔文章,看文档的属性是 page.prevpage.next 没错,但是上面写着这个东西返回 string 或者 null

<%= page.prev %>

我用 EJS 直接输出它们是报错的,我尝试用 console.log 打印出来才发现这两个的实际返回类型是 Object,对象确实会更符合开发的使用情形,反倒字符串拿不到齐全有效的信息。

这个是 Hingle 模板里面完全复刻 Single 的实现方法:

<% if( page.prev !== undefined) { %>
    <li>上一篇: <a href="<%= url_for(page.prev.path) %>"><%= page.prev.title %></a></li>
<% } else { %>
    <li>上一篇: 看完啦 (つд⊂)</li>
<% } %>
<% if( page.next !== undefined) { %>
    <li>下一篇: <a href="<%= url_for(page.next.path) %>"><%= page.next.title %></a></li>
<% } else { %>
    <li>下一篇: 看完啦 (つд⊂)</li>
<% } %>

这样一搞我倒是发现了 Hexo 的 Debug 方法了,console.log 会打印在控制台里面。但是官方文档写错返回类型这个问题,对新手开发者难免还是不太友好。看起来官网是一个 Git 仓库,或许我可以提交一个 PR 改进一下?

尚未解决的问题

目前发现文章的代码块默认采用了 Highlight.JS,且修改 Hexo 项目下的 _config.yml 配置文件并重启服务之后依旧无效,无法关闭,具体原因不明。主要是这块和之前的 CSS 有些冲突,这才想让我先关闭取消的。

在 Hexo 平台下的评论支持也是一个没踩过的坑,还得后期看看其他人的解决方案...

我会陆陆续续把 Single 的逻辑进行移植,也可能会进行过程直播,希望大家持续关注!如果你也认为 Single 是一款值得移植的优秀主题,那么不妨去 GitHub 仓库下为我 点个赞 支持一下吧!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK