短代码

两部分构成:① 短代码本身 ② 调用短代码

使用原理:在正常html(layout/shortcodes)处写一次短代码 mycodename.html,然后在正常文档中(content/xxx.md)可多次使用

<mycodename> 想让它成为此样式的部分 </mycodename>

注:有两种,一种是有首尾的 ⬆,一种不用比如嵌入video

toc

补:
2023.11.18 实现此功能

实现方法

hugo有内置的方法.TableOfContents,可以直接用。
此部分的id = TableOfContents,写样式的时候 就#TableOfContents { }
此时 toc.html内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{{ if .IsPage }}
  {{ if and (.Site.Params.toc.enable) (gt .WordCount .Site.Params.toc.wordCount) }}
    <div id="toc" class="sidebar-toc">
      <header>
        <span class="toc-header">- CATALOG -</span>
      </header>
      {{ .TableOfContents }} 
    </div>
  {{end}}
{{ $built := resources.Get "js/toc.js" | js.Build "js/toc.js" }}
<script type="text/javascript" src="{{ $built.RelPermalink }}" defer></script>

{{end}}

给头部加了一个判断,给toc加了一个标题。
但是这时toc不能自动跟随文章内容,需要自己写js。
如果要写,有一个很方便的地方就是hugo已经自动生成了文章正文TOC的H1-H6部分的id。可以拿来用。


网上搜了一个插件,tocbot。它的方便之处是全给你写好了。虽然不那么自由,但还是记录一下好不容易成功的用法。
这个插件不需要TableOfContents,它是直接根据文章正文内容生成新的toc,所以要去掉这部分。
此外script引用一定要放在body最底端,放在toc.html会没用。我放在footer.html里面了。
此时toc.html内容:

{{ if .IsPage }}
  {{ if and (.Site.Params.toc.enable) (gt .WordCount .Site.Params.toc.wordCount) }}
    <div id="toc" class="sidebar-toc">
    </div>
  {{end}}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.11.1/tocbot.css">
{{end}}

同时footer.html添加

<script src="https://cdnjs.cloudflare.com/ajax/libs/tocbot/4.5.0/tocbot.min.js" ></script>
<script>
    tocbot.init({
        tocSelector: '#toc',
        contentSelector: '.post-content',
        hasInnerContainers: true 
    });
</script> 

英文注释实为迷惑,待我释义:
tocSelector 指的是,要生成toc的地方。如上面所说,此插件是直接用文章内容生成全新toc,所以只用给它留地方就行了。
contentSelector 指的是,文章正文内容。同理,需要文章正文位置。
其它参数还没研究。


此外还在中文网上发现一版实现样式,在hugo内,但不用tablesofcontents,而是自己实现toc,用正则式提取标题内容,好几个blog提到,中文起源是一个blog叫《AllinOne》的姑娘。root起源是一个github的issue。这个姑娘不是程序员却改的很细致,很厉害。

但是我没有使用此方法。
一是因为她说hugo内置方法不能使用H1?可能是版本更新,hugo现在是支持更改选择标题的,在hugo的config里设置就行了。

[markup]
  [markup.tableOfContents]
    startLevel = 2
    endLevel = 4
    #ordered = true
    

上面意思就是从h2-h4。orderde=true打开之后,每个标题块的标签就从改为了

其次我看到好几个人用这个方法,都说对中文的识别有点问题。

最后是我发现,它的逻辑是,如果有子标题的话,标签包了一群,这样写js逻辑的时候非常难受。
正常的,以及Hugo内置toc的逻辑是,每一层级是一个,每个标题文本是一个包含一个,如果有子标题,再包含一个块。这样层级逻辑比较清楚。

我的实现

我选择了hugo内置,自己写js跟随的方法。研究了一下js,略跪门闩。

上面的代码实现完了之后,目录可以展示出来。但是还需添加跟随功能,计算高亮路径,自动展开缩起功能。

跟随功能学习了其他人的笔记。看了一下实现的思想,大概是硬计算当前位置和其它header的位置差,来确定当前toc位置。还有给当前toc位置添加active的class的功能。后面写样式要用到这个class。

实现了之后,又想让当前标题的父标题也一起高亮。我才想到,有些实现是直接将父active的块在js里一起标记了,我看到写的比较规整的是这位秋染蒹葭
的toc实现。但是我实在不想再改js啦。其实是不熟。 于是就在css里实现了。

基本逻辑是,active的块(一般是标签)的子,也就是当前标题高亮,这个没得说;同时如果当前块的后代,只要有active类,它的就也高亮。代码如下:

    .mytoc li.toc-active > a,
    .mytoc li:has( li.toc-active) > a {
        // 想设的样式
    }

然后,因为我设了三层目录,所以又想实现没滚到的部分的目录缩起来,滚到它再展开。
这部分核心思想是,展开就设display:block,将当前目录,及同级目录,及他们的所有直系祖先,当做一块。不active的就是除了一层目录,其它所有都display:none

如果在js里实现的话,就需要两个变量,当前目录标记active,父目录也需要标记一个不同的active。这样css就只用给active添加样式就行了。上面的秋染蒹葭就这样实现。
如果用css实现的话,逻辑一样的。只是由于我只有当前标题一个active,所以相对关系都以这一个为参照原点。子孙有激活的,当前的就block;当前激活的,它的子,以及这个的子就block。后者是满足,此有子标题,但是滚轮还没滑进子标题时,子标题也展开,这种情况。
代码:

    .mytoc nav > ul ul{
        display: none;
    }
    
    .mytoc nav ul:has( li.toc-active),
    .mytoc li.toc-active > ul,
    .mytoc li.toc-active > ul > li
   {
        display: block;
    }

为了(并不存在的)通用,这里都没起具体class,尽量直接用实现。然后再copy一份版的就更兼容了。

然后又顺手添加微弱发光。嘿嘿。

最后没有实现平滑滚动。瞬移也挺酷的。

问题

一是想给section的_index.md文章,即list类的,也加toc。但是list类没有tableofcontent。

结果发现是我没搞清,尴尬。是可以自己写逻辑筛选谁可以生成toc的。然后去修改了逻辑。

然后发现有几个页面仍然不能生成。发现是该文章内容,我调皮了,在正文部分打了等标签,它好像依据标签捕获heading的。于是它捕获的为空于是报错。更改一波js逻辑。


二是如果全局设定链接在新标签点开,点目录或回到顶部,也会在新页面点开。这个不行。应该永远在原页面点开。

这个用render-hook解决。
在layout的_default/markup下添加render-link.htmlrender-heading.html。具体看官网。

换行换段 字符集和好看样式

代码高亮

初次看攻略的时候都略过这部分,但扫过好多篇都把这部分单独写一小节,还以为要配什么惊天复杂配置。结果好像没有,就是加载custom.js或者设置hugo默认配置。但仍然存在一些细节疑惑的解惑需要记录在这里。所以我也单开了一part(。

秉着如无必要不增实体的原则,先使用hugo默认配置,如有需要之后再加js。

hugo默认配置highlight

几乎所有人又又又都在抄一份相同的[markup.highlight],将所有默认属性遍历了一遍。

其实只需要设置style,然后选自己喜好的style。所有高亮部分的配置包括:

[markup]
  [markup.highlight]
    style = "monokai"

为什么。
是这样的。其它大部分配置不写,我试了,它都是默认那样子的。那个人只不过翻译了一遍。
我自己只有两个属性,其实是一个属性需要考虑,linenos,行号。说一个属性,是hugo好像update了linenos的值不仅有truefalse,还添加了行号样式tableinline。之前好像有单独的linenosintable=true这种属性。
hugo默认是不开行号的。但是我需要分开这两种,比如👆这个配置,我并不想要行号。

此外,tableinline的区别是,在渲染出来的html中,代码部分,inline解析,table解析,由两组构成,一组为行号,一组为内容。这样据说是因为table属性可以复制代码的时候不复制行号,但是我试了inline复制,也并没有复制行号。而且默认table的样式,丑的要命。只好自己修改样式。

那么怎么动态设置要不要行号,以及如何设置不同的样式呢。

在三个反引号之后加上特定的语言名字,的外层会多一块class=“highlight"的,而不加就没有这个。这样就方便我在css里自己调整它的样式了。
而在语言名字之后设置linenos,就可以控制要不要行号。当然也可以在这里设置其它的markup.highlight属性。
我的方案是,在config里就不写,于是默认为没行号。此时我有一个默认的样式。当要写特定语言时,再开行号。整体样貌就像:

```go {linenos=table} 
// 这里是你的代码

以上。再修改下css就大功告成。

但是这样简单配置就没有代码自动折叠和一键复制功能。我恨。