Hugo Shortcode 实现Markdown多标签页代码

笔者最近在优化自己的个人网站, 想要实现一些更复杂的页面组件, 比如同一算法不同语言的 Tab 页展示, 实现代码拷贝到剪贴板的功能等等. 笔者的网站是用 Hugo 写的, Hugo 支持自定义 Shortcode 来做一些特定的操作, 这篇文章将介绍如何使用 Hugo Shortcode 来实现一些常见的功能.

Code Tabs
ShortCode 样例

Hugo Shortcode 介绍

内置 Shortcode

Hugo 本身提供了一些内置的 Shortcode, 比如:

自定义 Shortcode

Hugo Shortcode 是一种特殊的 Markdown 语法, 用于在 Markdown 文档中插入自定义的内容. 使用流程如下:

  1. layouts/shortcodes 目录下创建一个文件, 文件名就是你的 Shortcode 名称, 比如 IncludeFile.html. 文件内容如下:

    下面的 ShortCode 需要一个path参数, 需要在调用的时候指定. path参数是相对于 content 目录的相对路径.

    {{ $path := .Get "path" }}
    {{ with readFile (printf "content/%s" $path) }}
        {{ .| markdownify  | safeHTML }}
    {{ end }}
  2. 在 Hugo 的 Markdown 中调用 shortcode:

    示例 Markdown 文件, 使用 shortcode 来引入一个文件内容:
    {{< IncludeFile path="column-content.txt" >}}
  3. 上面的 ShortCode 有什么用呢? 如果好几个文件存在相同的部分, 可以把这部分提取出来, 然后在 Markdown 中引入. 这样可以减少重复的代码, 提高代码的复用性. 比如我之前的 C++ Core Guidelines 系列, 有十几篇文章, 需要共享一个专栏目录. 如果不提取出来, 后续每增加一个新文档, 就要更新以前的所有文档, 这个是非常麻烦的. 而使用IncludeFile就非常方便, 只需要维护一个文件.

实现代码 Tabs

  1. 首先, 由于我的博客主题是我自己基于 DaisyUI 开发的, 我从 DaisyUI 中找到了适合我自己博客的代码 Tab 组件, 并以此为目标进行修改.

  2. 我设计的 Code Tabs 组件分为两层, 最外层负责生成外壳, 内层的 ShortCode 生成单个的 Tab 页. 所以有下面的短码:

    <div role="tablist" class="tabs tabs-lifted">
        {{- .Page.Store.Add "CodeTabsSeq" 1 -}}
    
        {{/* reset the index on every new CodeTabs */}}
        {{- .Page.Store.Set "CodeTabsIndex" 0 -}}
        {{ .Inner }}
    </div>
    {{- $title := .Get "title" | default "" -}}
    {{- $codeTabsSeq := .Page.Store.Get "CodeTabsSeq" | default 0 -}}
    {{- $codeBlockID := .Page.Store.Get "CodeTabsIndex" | default 0 -}}
    {{- .Page.Store.Add "CodeTabsIndex" 1 -}}
    {{- $isFirst := eq $codeBlockID 0 -}}
    <input type="radio" name="code_tabs_{{ $codeTabsSeq }}"
           class="tab" aria-label="{{ $title }}"
           {{ if $isFirst }} checked {{ end }}>
    
    <div role="tabpanel"
      class="tab-content bg-base-100 border-base-300">
      {{- .Inner | .Page.RenderString -}}
    </div>
  3. 使用 CodeTabs 组件的方法如下:

    {{< CodeTabs >}}
    {{< Code title="C++" >}}
    
    ```c++
    #include <iostream>
    
    int main() {
        std::cout << "Hello, World!" << std::endl;
        return 0;
    }
    ```
    
    {{< /Code >}}
    {{< Code title="Java"  >}}
    
    ```java
    public class HelloWorld {
        public static void main(String[] args) {
            System.out.println("Hello, World!");
        }
    }
    ```
    
    {{< /Code >}}
    {{< /CodeTabs  >}}

    实际效果如下:

    效果图

完整代码请参考我的Github 仓库.

更多样例

  1. 实现对特定行的高亮显示.
  2. 支持 Compiler Explorer 中运行.
sample

点击体验实际效果

Tags: