Instructions for creating a Hugo site

Date: May 24, 2018
Last Updated: Feb 27, 2019
Categories:
Playground Technique Web
Tags:
hugo blog markdown

Contents


背景

这是一篇中文教程,基于前人的经验,补全一些没有提到的技巧。首先我们可以阅读以下站点的教程:

一篇基础的、关于如何使用Hugo创建新站点,并托管到Github的流程

补全教程:关于如何理解、使用Hugo主题

然而,实际编写站点内容没有固定的套路,很多情况下能使用哪些功能取决于对应的主题。譬如有的主题支持HTML5,我们就能实现一些对应的技巧;而有些相对简单的主题不支持,我们就只能实现一些基本功能。共通的一些技巧可以查阅:

Hugo官方文档

本站使用的模板是Forty,这个模板支持HTML5。在做好所有的基础设置以后,我们可以用MarkDown写任何一篇内容。关于更高级的编写内容的技巧,可以查阅模板自带的Element范例。这些高级技巧无一例外需要通过HTML语法实现,包括但不限于分栏按钮图标表单下标 或者上标如此等等……

补全

套用模板来定制主页

Forty为例,下载后,其模板文档的关键结构如下:

forty
|---archetypes
|---exampleSite
|   |---archetypes
|   |---content
|   |   `---blogs
|   |       |---_index.md
|   |       `---blog1.md
|   |---static
|   |---config.toml
|   `---netlify.toml
|---images
|---layouts
|---static
|   |---img
|   `---elements.html
`---theme.toml

我们可以看到,Element就在static目录下,它不是由MarkDown渲染出的,而是静态网页,我们需要的参考都只能通过HTML的形式获取。图像文件都保存在static/img下,但是这里有不只一个static文件夹,我们稍后再讨论。现在我们需要关注的是exampleSite,它是一个模板自带的范例站点,通过调用

hugo server --buildDrafts --watch

可以直接渲染出该范例,它就是模板提供预览的Demo。在这个Demo里面,主页是由config.toml定制的,我们需要将它和netlify.toml拷贝到我们自己的站点根目录下,覆盖原有的文件,通过上述命令,我们可以直接看到,主页的定制生效在了我们自己的站点上。

config.toml是用Golang编写的,但是作为配置文件,它对于新手并不难懂,并且有丰富的注释。从[params]开始,该文件开始定义主页存在的要素,包括但不限于顶部的导航条(导航菜单)、主页Banner,精美的导航图片模块、联系方式以及底格的社交媒体按钮。通过替换图片文件、修改模块参数等方式,我们可以逐渐将范例的内容替换成我们自己的。

特别注意的是使用图标的技巧。这一套图标是来自Font Awesome Icons的开源协议,通过以下的按钮,我们可以查阅所有我们能使用的图标:

Font Awesome Icons

内容的基本结构

让我们来重点关注根目录下content的内容

.
|---archetypes
|---content
|   |---blogs
|   |   |---_index.md
|   |   `---blog1.md
|   `---about.md
|---static
|---config.toml
`---netlify.toml

一般来说,我们自定义的内容可以分成两种结构。第一种是直接从属于main 范畴下的页面,例如上述的about.md,其域名为形如http://site/about的形式。

另一种是二级页面,它由一个文件夹来构成,例如blogs,其主域名为http://site/blogs,但实际指向的是_index.md的内容;blogs下又从属许多页面,例如blog1.md,其域名为形如http://site/blogs/blog1/的形式。主页面_index.md除了提供标题、标题画面以及类型简介以外,不提供任何实质的内容。但是通过添加从页面,这些从页面的简介(包括标题图,如果存在的话)都会显示在主页面下。而每个从页面的简介在对应的文件里面定义,不需要重新声明在主页面里。

补全模板的缺失

模板自带的功能不支持两个关键的要素:Latex公式渲染和代码高亮。为了解决这一问题,我们需要进行一些额外的工作。

Latex渲染

渲染Latex公式需要使用MathJax,这需要我们略微修改模板。参考如下资料:

Setting MathJax with Hugo

注意,要使用文中的第二种方法(A second method)实现,亲测使用第一种方法里的Code无法正常实现渲染功能。

完成对应步骤后,测试行内公式:$\mathbf{A}_a = \theta_1$。

测试行间公式,麦克斯韦方程组:

\begin{equation} \begin{aligned} \frac{\partial\mathcal{D}}{\partial t} \quad & = \quad \nabla\times\mathcal{H}, & \quad \text{(Loi de Faraday)} \\[5pt] \frac{\partial\mathcal{B}}{\partial t} \quad & = \quad -\nabla\times\mathcal{E}, & \quad \text{(Loi d'Ampère)} \\[5pt] \nabla\cdot\mathcal{B} \quad & = \quad 0, & \quad \text{(Loi de Gauss)} \\[5pt] \nabla\cdot\mathcal{D} \quad & = \quad 0. & \quad \text{(Loi de Colomb)} \end{aligned} \end{equation}

代码高亮

直接查阅上述的基础流程,按照其中代码高亮的操作步骤修改模板即可。

弹出图片窗口

Forty模板自身不具备点击图片弹出(放大)窗口的功能。我们可以自行将它添加上。这一功能要求我们实现以下细节:

  • 每页的title图不能被点击放大;
  • 带有超链接的图不能被点击放大;
  • 除上述两条,所有的<img>标签都允许被点击放大。

基础功能(点击放大的实现在这里)。

扩展JS代码

为此,我们不妨关注这些不能被点击放大图的特性:

  • title图的父标签一定是<span class='image main'>
  • 带有超链接的图父标签一定是<a>

故而,可以通过筛选器,排除掉上述的两种情况,代码如下:

$('body').append('<div class="product-image-overlay"><span class="product-image-overlay-close"><i class="fa fa-times" aria-hidden="true"></i></span><img src="" /></div>');
var productParent = $('img').parent(':not(span.image.main):not(a)');
var productImage = productParent.find('img');
var productOverlay = $('.product-image-overlay');
var productOverlayImage = $('.product-image-overlay img');
productImage.addClass("show_img");

productImage.click(function () {
    var productImageSource = $(this).attr('src');
    productImage.removeClass("show_img");

    productOverlayImage.attr('src', productImageSource);
    productOverlay.fadeIn(300);
    $('body').css('overflow', 'hidden');

    $('.product-image-overlay-close').click(function () {
        productOverlay.fadeOut(300);
        productImage.addClass("show_img");
        $('body').css('overflow', 'auto');
    });
});

相比原始代码,这一改进包括:

  • 将字符X代表的关闭键替换成了
  • 取出所有<img>标签的直属父元素,并排除掉了span.image.maina两种父标签。
  • 增加了一个悬浮其上产生的效果。

将这一代码保存为jquery.images.js,并保存到模板的static/js目录下;

扩展CSS

同样,将参考资料提供的css代码保存为jq-images.css,保存到模板的static/css目录下。本站中对该css还进行了微调,这些改动包括:

  • 将按钮加粗,放置在右上角而不是屏幕左上角;
  • 配合悬浮状态的效果,提高图片的亮度。

具体实现的代码如下,替换掉原代码部分即可:

.product-image-overlay .product-image-overlay-close {
  display: block;
  position: absolute;
  top: 20px;
  left: 100%;
  margin-left: -60px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 3px solid #eee;
  line-height: 35px;
  font-size: 20px;
  color: #eee;
  text-align: center;
  cursor: pointer;
  transition: 0.3s;
}

.product-image-overlay .product-image-overlay-close:hover {
    color: #AAF;
    border: 3px solid #AAF;
}

.show_img {
    transition: 0.3s;
}

.show_img:hover {
    -webkit-filter: invert(5%) brightness(200%);
    filter: invert(5%) brightness(200%);
}

扩展模板的Layout文件

最后,为了使CSS和JS生效,需要修改模板layouts/partials目录下的如下两个文件:

  1. header.html: 在main.css所在的行下添加

    <link rel="stylesheet" href="{{ "css/jq-images.css" | absURL}}"/>
    
  2. js.html: 在任意空行下添加

    <script src="{{ "js/jquery.images.js"| absURL }}"></script>
    

该改动即可生效。类似地,如果我们还需要实现别的JQuery插件,同样也可以通过类似的步骤完成。

加入中文字体支持

Forty的默认字体是Source Sans Pro,该字体通过在线Google Fonts的服务取得,为了支持中文,我们同样可以调用在线字库思源宋体。为了防止非中文页面加载该字体过度占用资源,我们需要在Markdown顶端的参数里增加一项language,只有在设为Chinese的情况下才会请求并替换字体。具体步骤如下

扩展CSS

新建一个chinese.css文件,保存到模板的static/css目录下。内容如下:

@import url('https://fonts.googleapis.com/css?family=Noto+Serif+SC:400,600,700&subset=chinese-simplified');
/* Reset */
body, input, select, textarea {
    font-family: "Source Sans Pro", "Noto Serif SC", serif;
}
h1, h2 {
    font-weight: 700;
}
h3, h4, h5, h6 {
    font-weight: 600;
}
#header {
    font-weight: 700;
}
code {
    font-family: "Courier New", monospace, "Noto Serif SC";
}
pre {
    font-family: "Courier New", monospace, "Noto Serif SC";
}

扩展模板的Layout文件

接下来,修改模板layouts/partials目录下的header.html文件,在font-awesome.min.css的前一行下添加(注意,所添加的行必须在main.css下方,以便默认字体设置能被覆盖):

{{ if .Params.language }}{{ if eq .Params.language "Chinese" }}
<link rel="stylesheet" type="text/css" href="{{ "css/chinese.css" | absURL}}" />
{{ end }}{{ end }}

则模板修改完毕。

使用范例

实际使用的时候,对于想要开启中文字体的页面,在头部的配置部分,按如下方式:

---
title: "Instructions for creating a Hugo site"
date: 2018-05-24T16:13:10-05:00
draft: false
language: "Chinese"
...
---

这里指提及关键设置language: "Chinese",加上该行,则本页面将显示为中文字体。

高级技巧的范例

事实上,这些都可以在Element中查到,这里直接Copy一个例子(分栏与表单),当然,它是通过Copy HTML代码到MarkDown文件里实现的

电话

(000) 000-0000 x12387

住址

1234 Somewhere Road #5432
Nashville, TN 00000
United States of America

代码如下

<div id="wrapper">
  <section id="contact">
    <div class="inner">
      <section>
        <form method="post" action="#">
          <div class="field half first">
            <label for="name">姓名</label>
            <input type="text" name="name" id="name" />
          </div>
          <div class="field half">
            <label for="email">电邮</label>
            <input type="text" name="email" id="email" />
          </div>
          <div class="field">
            <label for="message">正文</label>
            <textarea name="message" id="message" rows="6"></textarea>
          </div>
          <ul class="actions">
            <li><input type="submit" value="发送" class="special" /></li>
            <li><input type="reset" value="清空" /></li>
          </ul>
        </form>
      </section>
      <section class="split">
        <section>
          <div class="contact-method">
            <span class="icon alt fa-envelope"></span>
            <h3>电邮</h3>
            <a href="#">information@untitled.tld</a>
          </div>
        </section>
        <section>
          <div class="contact-method">
            <span class="icon alt fa-phone"></span>
            <h3>电话</h3>
            <span>(000) 000-0000 x12387</span>
          </div>
        </section>
        <section>
          <div class="contact-method">
            <span class="icon alt fa-home"></span>
            <h3>住址</h3>
            <span>1234 Somewhere Road #5432<br />
            Nashville, TN 00000<br />
            United States of America</span>
          </div>
        </section>
      </section>
    </div>
  </section>
</div>