如何在 kramdown 中将永久链接添加到 headers?

How do I add permalinks to headers in kramdown?

我正在使用 Jekyll 构建一个网站,Github-Page 用 markdown 编写。我想让永久链接到 header 变得容易,就像大多数在线文档所做的那样。

我想在单击 header 时获得带有哈希的 URL。有没有一种简单的方法可以在 Kramdown 或 Jekyll 的配置中实现这一点?

Markdown 页面

#### A regular header

A regular sentence.

理想结果

<h4 id="a-regular-header"><a href="#a-regular-header">A regular header</a></h4>
<p>A regular sentence.</p>

如果没有 Jekyll 插件,从生成器的角度来看这是不可能的。由于您使用的是 GitHub 页面,因此无法实现,因为它们不支持自定义插件。

一个合理的解决方案是创建一个脚本,它可以找到所有带有 ID 的标题并将它们转换为 link 或附加一个 link 图标。

您可以在每个标题的 Markdown 中手动执行此操作:

#### [A regular header](#a-regular-header)

A regular sentence.

缺点是维护成本。另一种选择是通过将此添加到所选页面的底部来在客户端创建链接:

<script>
    var headings = document.querySelectorAll("h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]");

    for (var i = 0; i < headings.length; i++) {
        headings[i].innerHTML =
            '<a href="#' + headings[i].id + '">' +
                headings[i].innerText +
            '</a>';
    }
</script>

如果 JavaScript 依赖项不适合您的受众,您可以查看插件、修改后的 Markdown 解析器或类似 gulp.js 的任务运行程序,以便在构建时执行此操作。如果您希望 GitHub Pages 构建您的页面,则不能使用这些替代方法,但您可以在本地构建并提交输出。

您可以使用 Jekyll plugins 来覆盖标准行为。我把这个放在 _plugins/header.rb:

class Jekyll::MarkdownHeader < Jekyll::Converters::Markdown
    def convert(content)
        super.gsub(/<h(\d) id="(.*?)">/, '<h id=""><a href="#">§</a>')
    end
end

正则表达式将所有带有 ID 标记的 headers 替换为还添加了 link 的标记。这不是在一般情况下执行此操作的 fool-proof 方法(例如 <h2 class="foo" id="x") 将不起作用),但 Kramdown 输出相当可靠且一致,因此应该没问题。我用 Jekyll 3.8.4 和 Kramdown 1.17.0 添加了这个。

如果您 want/need 更强大的解决方案,那么您可以使用 HTML 解析器。不应该那么难。

这样做的好处是它不需要 JavaScript 在客户端。


或者如果您想 link 实际标题而不是前置 link:

class Jekyll::MarkdownHeader < Jekyll::Converters::Markdown
  def convert(content)
    super.gsub(/<h(\d) id="(.*?)">(.*)<\/h(\d)>/, '<h id=""><a href="#"></a></h>')
  end
end

如果你想要一个 GitHub 页面兼容的方式来做到这一点而不需要 JavaScript,你可以 crazy creative 与 Liquid 并小心地将渲染的 HTML 解析为字符串并对其进行操作。

或者您可以只使用这个代码段来完成此操作:https://github.com/allejo/jekyll-anchor-headings