1. 准备工作

1
2
3
4
5
6
7
8
9
# 新建站点
hugo new site hugo-geekdoc

# 进入站点路径下
cd hugo-geekdoc

# 安装主题
mkdir -p themes/hugo-geekdoc/
curl -L <https://github.com/thegeeklab/hugo-geekdoc/releases/latest/download/hugo-geekdoc.tar.gz> | tar -xz -C themes/hugo-geekdoc/ --strip-components=1

修改根目目下的config.toml进行简单配置:

1
2
3
4
5
baseURL = "<http://example.org/>"
languageCode = "en-us"
title = "JDK8源码阅读笔记"
# 指定主题
theme = "hugo-geekdoc"

此时便可以启动了:

1
hugo server

如果一切顺利的话,启动后在1313端口便可看到页面了。

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-init.png

左侧标识导航的位置即为菜单,它也是整个文档的基本骨架,我们将在下一节对其进行详细的学习。

2. 搭建基本骨架

基本骨架也即菜单,有两种组织形式:

  • 文件树菜单
  • 绑定菜单

2.1 文件树菜单

顾名思义,文件树菜单就是根据文件树来形成的菜单。

例如,我们构建一个文件树:

1
2
3
4
5
6
7
hugo new 第一章/_index.md
hugo new 第一章/第一节.md
hugo new 第二章/_index.md
hugo new 第二章/第一节.md
hugo new 第二章/第二节.md
hugo new 第二章/第三节/_index.md
hugo new 第二章/第三节/2.3.1小节.md

此时我们使用hugo server -D命令启动服务,可以看到效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-filetree.png

可能你会发现,左侧的菜单都无法点击,这是正常的,因为他们目前都是“空文件”,往里写入了内容之后,“非空”的菜单就可点击了。

但是,问题是怎么“第三节”跑到了“第二节”上面?同时,哪来的“2.3”,我创建此小节的命令明明是hugo new 第二章/第三节/2.3.1小节.md啊?

章节顺序问题,我也没搞清楚。但是章节名被删减的问题,应该是hugo new的过程中造成的。我们可以打开文件“2.3.1小节.md”,发现其中的内容如下:

1
2
3
4
5
---
title: "2.3"
date: 2021-07-17T14:34:42+08:00
draft: true
---

这说明,在创建这个文件时,title截取了文件名的一部分造成的,此处的截取规则没有深究。手动调整title即可解决这个问题。

而对于菜单排列顺序问题,可以在文章md文件头中添加weight属性来进行排序,该值越大越往后。

1
2
3
4
5
6
---
title: "第三节"
date: 2021-07-17T14:34:42+08:00
draft: false
weight: 5
---

2.2 绑定菜单

geekdoc主题还提供了另一种组织菜单的方式:绑定菜单。也就是通过一个文件来组织菜单,对每个章节都做强绑定。这样的话,我们对菜单的掌控度大大提高了。

我们继续用上面创建好的文件,并创建一个菜单文件来把那些文件组织在一起。

首先,我们要在config.toml中添加配置:

1
2
[params]
  geekdocMenuBundle = true

然后,创建一个文件:data/menu/main.yml

1
2
mkdir data/menu
touch data/menu/main.yml

修改这个文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
---
main:
  - name: "第一章"
    ref: "第一章"
    sub:
      - name: "第一节"
        ref: "第一章/第一节.md"
  - name: "第二章"
    ref: "第二章"
    sub:
      - name: "第一节"
        ref: "第二章/第一节.md"
      - name: "第二节"
        ref: "第二章/第二节.md"
      - name: "第三节"
        ref: "第二章/第三节"
        sub:
          - name: "2.3.1小节"
            ref: "第二章/第三节/2.3.1小节.md"

重启服务后,可以看到效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-bundle-menu.png

好,下面开始技术总结:

  1. 开头三根横线不要忘
  2. name就是展示在导航模块的菜单名字
  3. name前面有一条横线和空格不要忘
  4. ref就是这个菜单对应的是哪个文件,如果当前菜单是个目录,则其对应的文件是该目录下的_index.md文件,但是这个_index.md可以省略,例如“第一章”的ref我们也可以写成:ref: "第一章/_index.md"
  5. sub用来指定下一级菜单

3. 进行内容创作

这一步就无需多言了,使用Markdown语法编写内容即可。

此处,我们编写”2.3.1小节.md“文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
---
title: "2.3"
date: 2021-07-17T14:34:42+08:00
draft: true
---

# public ArrayList(int initialCapacity)
这是行内代码:`public`。
构造一个具有指定初始容量的空列表。
源码如下:
```java
public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        // 指定容量大于0,初始化一个指定容量的数组赋值给elementData
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        // 指定容量等于0,elementData直接取空数组
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        // 指定容量小于0,抛出异常
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}
```

(记得手动修改title哦,我们生成好之后,它的原值为2.3

效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-init-code.png

基本功能实现了,可是太丑了。局座说过:”颜值就是战斗力“,这么丑不能忍,接下来就是对其进行美化。

4. 美化

我也只是个做后端开发(Java)的理工直男,以下仅针对我个人的喜好进行”美化“。

首先,这个代码高亮太丑,在不同模式下效果差异较大。

调整配置文件config.toml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# 增加如下配置
[markup]
  [markup.highlight]
    anchorLineNos = false
    codeFences = true
    guessSyntax = false
    hl_Lines = ""
    lineAnchors = ""
    lineNoStart = 1
    lineNos = false
    lineNumbersInTable = true
    noClasses = true
    style = "xcode"
    tabWidth = 4

我挑选的风格是xcode,你可以在这里面去挑选自己喜欢的风格。

关于heightlight的默认配置项如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[markup]
  [markup.highlight]
    # 是否为代码行标开启锚链接,开启后,每一行代码都有锚链接,但是可能会重复
    # 例如第12行代码的链接:<http://localhost:1313/test/#12>
    anchorLineNos = false
    # 其实就是是否开启按不同语言显示不同的高亮效果,置为false后,代码全是灰的,没有高亮效果
    codeFences = true
    # 当Markdown文件中对代码块未指定语言时,是否自动推测语言
    guessSyntax = false
    # 高亮的行,一般不会做全局设置,如果想设置某一行或某几行高亮的话,可以在代码块单独设置
    hl_Lines = ""
    # 在生成行号的锚链接时添加前缀,例如如果设置该属性为”xxx“的话
    # 则第12行代码的链接可能是:<http://localhost:1313/test/#xxx-12>
    lineAnchors = ""
    # 开始的行号,一般是从1开始,此设置也可以在代码块单独设置
    lineNoStart = 1
    # 是否展示行号
    lineNos = false
    # 是否将行号置为独立的table内,而不是和代码行在一起,和代码行在一起时,复制多行代码时行号也会被复制
    lineNumbersInTable = true
    noClasses = true
    # 指定代码高亮的风格
    style = "monokai"
    # tab键的宽度
    tabWidth = 4

现在有一个问题是:当开启展示代码行号且lineNumbersInTable置为false时,代码与行号之间有间隔但很小,效果很好。但是如果将复制多行代码时,会连行号也一并复制。如果将lineNumbersInTable置为true的话,此时复制就不会复制到行号了,但是新的问题出现:行号就站在代码的左侧,却像隔着银河。

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-init-code2.png

在网上找了下解决方案,大概有两种。两种方式都是通过自定义样式来实现,也即在”custom.css“中重写部分样式。一种是不开启将行号放入单独的列,也就是lineNumbersInTable = false,然后为了解决复制代码时不复制行号,重写行号列的样式,设置其不可选中。第二种解决方式是开启将行号放入单独的列,然后通过重写相关样式,缩短行号和代码之间的距离。

看了下页面的代码之后发现两种方案对我这个后端同学来说有点难,那就先这样吧,等前端技术精进一些的时候再搞。

对于行内代码几乎看不出来的问题,以及代码的字体问题,我们可以通过自定义样式来修改。

首先,在根目录的”static“目录下创建文件”custom.css“。

然后使用浏览器的查找元素功能定位到行内代码,提取到它的特征:它是gdoc-markdown类下p标签下的code标签包裹的,那么我们就可以编辑”custom.css“了:

1
2
3
4
5
6
7
/* 定制化行内代码样式 */
.gdoc-markdown p code {
    /* 设置颜色 */
    color: #FF6A6A;
    /* 设置字体加粗 */
    font-weight: bold;
}

如果对代码的字体不满意,还可以设置代码字体:

1
2
3
4
/* 定制化代码样式,包括行内代码和代码块 */
.gdoc-markdown code {
    font-family: Consolas,Monaco,Menlo,dejavu sans mono,bitstream vera sans mono,courier new,monospace
}

经过如上设置后,页面的效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-init-code3.png

5. 其他配置

5.1 设置点击目录类的菜单后展示该菜单下的文件树

例如,我们对”第二章“增加此效果。

目前,我们点击”第二章“,其几乎是个空白页面,什么都没有。

编辑”第二章/_index.md“:

1
2
3
4
5
6
7
---
title: "第二章"
date: 2021-07-17T14:34:42+08:00
draft: true
---

{{< toc-tree >}}

此时,我们再点击”第二章“效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-toctree.png

5.2 为菜单指定icon

我们可以为菜单设定icon,这些icon会展示在菜单名字前。

首先是哪些icon可以使用,geekdoc主题自带了一些,可以在这儿找到。

使用方式为修改data/menu/main.yml文件:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
---
main:
  - name: "第一章"
    ref: "第一章"
    icon: "gdoc_heart"
    sub:
      - name: "第一节"
        ref: "第一章/第一节.md"
        icon: "gdoc_person"
  - name: "第二章"
    ref: "第二章"
    sub:
      - name: "第一节"
        ref: "第二章/第一节.md"
      - name: "第二节"
        ref: "第二章/第二节.md"
      - name: "第三节"
        ref: "第二章/第三节"
        sub:
          - name: "2.3.1小节"
            ref: "第二章/第三节/2.3.1小节.md"

使用icon字段进行设置即可,上面我们仅设置了”第一章“和其下的”第一节“。

除了主题自带的icon之外,我们也可以自己写svg文件,作为icon使用,只需满足主题对svg文件的要求即可。

下面,我们使用IntelliJ IDEA中的某些svg文件。

IDEA中的某些svg文件如下:

  • package.svg
1
2
3
<svg xmlns="<http://www.w3.org/2000/svg>" width="16" height="16" viewBox="0 0 16 16">
  <path fill="#9AA7B0" fill-opacity=".8" fill-rule="evenodd" d="M6,10.4951 C4.896,10.4951 4.001,9.6001 4,8.4981 C3.999,7.3941 4.894,6.5001 5.997,6.5001 C7.102,6.5001 7.997,7.3941 7.998,8.4981 C7.999,9.6001 7.104,10.4951 6,10.4951 Z M7.984,4.0001 L6.696,2.7111 C6.305,2.3201 5.532,2.0001 4.979,2.0001 L1.051,2.0001 C1.023,2.0001 1,2.0231 1,2.0511 L1,13.0001 L15,13.0001 L15,4.0001 L7.984,4.0001 Z"/>
</svg>
  • class.svg
1
2
3
4
5
6
<svg xmlns="<http://www.w3.org/2000/svg>" width="16" height="16" viewBox="0 0 16 16">
  <g fill="none" fill-rule="evenodd">
    <path fill="#40B6E0" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/>
    <path fill="#231F20" fill-opacity=".7" d="M5,4.28253174 C4.53,4.74153174 4.028,4.978 3.1,5 C2.061,5.022 1,4.2794 1,3.0004 C1,1.7124 1.971,1 3.1,1 C3.94833171,1 4.54833171,1.18475342 4.9,1.55426025 L5.5162,0.836730957 C4.8293999,0.270175195 4.28826904,0.0004 3.0982,0.0004 C1.3402,0.0004 0.0002,1.3584 0.0002,3.0004 C0.0002,4.6824 1.3642,6.0004 3.0022,6.0004 C4.29284668,6.0004 5.0232,5.5934 5.6162,4.9814 C5.2054,4.51548783 5,4.28253174 5,4.28253174 Z" transform="translate(5 5)"/>
  </g>
</svg>
  • interface.svg
1
2
3
4
5
6
<svg xmlns="<http://www.w3.org/2000/svg>" width="16" height="16" viewBox="0 0 16 16">
  <g fill="none" fill-rule="evenodd">
    <path fill="#62B543" fill-opacity=".6" d="M15,8 C15,11.866 11.866,15 8,15 C4.134,15 1,11.866 1,8 C1,4.134 4.134,1 8,1 C11.866,1 15,4.134 15,8"/>
    <polygon fill="#231F20" fill-opacity=".7" points="8.5 10 8.5 6 9.5 5.664 9.5 5 6.5 5 6.5 5.664 7.5 6 7.5 10 6.5 10.344 6.5 11 9.5 11 9.5 10.344"/>
  </g>
</svg>

第一步,将svg文件放至本site根目录下的/assets/sprites下。

第二步,修改svg文件,主要包括如下修改点:

  • 为svg标签添加类:class="svg-sprite",不然,这个icon会在首页顶部展示
  • 为svg指定id:id="interface",这一步是为了使用icon时能找到,使用时即:icon: "interface"
  • 去除svg文件中关于大小的设定,例如:widthheight

第三步,在main.yml中使用这些svg,方法与使用主题自带的icon一致。

按上述调整后,我们的main.yml如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
---
main:
  - name: "第一章"
    ref: "第一章"
    icon: "gdoc_heart"
    sub:
      - name: "第一节"
        ref: "第一章/第一节.md"
        icon: "gdoc_person"
  - name: "第二章"
    ref: "第二章"
    icon: "package"
    sub:
      - name: "第一节"
        ref: "第二章/第一节.md"
        icon: "interface"
      - name: "第二节"
        ref: "第二章/第二节.md"
        icon: "interface"
      - name: "第三节"
        ref: "第二章/第三节"
        icon: "package"
        sub:
          - name: "2.3.1小节"
            ref: "第二章/第三节/2.3.1小节.md"
            icon: "class"

效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-icon.png

5.3 折叠菜单

首先在配置文件中设置可折叠:

1
2
3
# 添加如下配置
[params]
  geekdocCollapseSection = true

然后在要折叠起来的目录对应的Markdown文件(也就是_index.md)中添加:geekdocCollapseSection: true,届时,某_index.md的头内容可能如下:

1
2
3
4
5
6
---
title: "第二章"
date: 2021-07-17T14:34:42+08:00
draft: true
geekdocCollapseSection: true
---

效果如下:

https://img.hongmao.run/blog/2021/07/hugo-geekdoc-collapse.png

5.4 自定义原型模板以优化创建文件夹时的操作

如果像我们之前那样创建文件夹、创建内容文件是十分麻烦的,我们需要做如下操作:

  1. 创建目录及文件(hugo new xxx/_index.md
  2. 修改_index.md,在头部设置可折叠(geekdocCollapseSection: true
  3. 修改_index.md,使其内容包含文件树(添加:{{< toc-tree >}}

其实这些操作可以通过自定义原型文件来一步到位的。操作步骤如下:

  1. 在项目根目录下的”archetypes“下创建一个文件夹,名字可自定义,此处我定义为dir,这个文件夹的名字也就是将来使用hugo new命令创建文件时的类型。

  2. 在刚创建的文件夹内新建文件_index.md,内容为我们设定好的,大体如下:

    1
    2
    3
    4
    5
    6
    7
    8
    
    ---
    title: "{{ replace .Name "-" " " | title }}"
    date: {{ .Date }}
    draft: true
    geekdocCollapseSection: true
    ---
    
    {{< toc-tree >}}
    
  3. 创建一个文件夹时使用命令:hugo new --kind dir 目录路径,例如我们在”content“目录下新建”第三章“这个目录,可以使用命令:hugo new --kind dir 第三章

6. 常见问题解决

6.1 使用{{< toc >}}生成文章内目录不生效

Hugo默认的纳入目录的标题级别为二级和三级,可以检查下是否自己使用的是一级标题,进而导致未生成目录,如果需要一级标题,可通过如下配置进行调整。

1
2
3
4
5
6
7
8
9
[markup]
  # 目录相关
  [markup.tableOfContents]
    # 纳入目录的最小标题级别,默认为3
    endLevel = 3
    # 是否排序,其实就是是否在目录的前面添加序号“1. ”、"2. "等等
    ordered = false
    # 纳入目录的最大标题级别,默认为2
    startLevel = 2

6.2 使用原生Markdown语法添加图片后,图片不居中

看了下本主题的官方文档,其支持使用Shortcode来添加图片,而且可设置项也有很多,但是貌似不支持网络图片,需要你将图片放置在项目对应的目录下。但是,这个问题也有解决方案。

解决方案一,通过嵌入HTML代码来插入图片,但是在这之前,需要通过配置来设置可嵌入HTML代码:

1
2
3
[markup.goldmark]
  [markup.goldmark.renderer]
    unsafe = true

然后,便可以通过如下HTML代码来添加图片:

1
2
3
<div style="text-align: center">
    <img alt="" src="">
</div>

解决方案二,通过自定义简码实现,具体可参考自定义简码