分享到朋友圈 1. 点击导航栏右侧按钮。
2. 选择 发送给朋友 或 分享到朋友圈。
收起 捐款给作者

Cherysun’s Tech Café

从 Jekyll 的摘要中删除脚注

最近在使用 Jekyll 创建博客并撰写文章的时候发现一个问题,如果在文章中使用 Markdown 中的 (fn) 语法添加了脚注(footnotes),而同时又使用 excerpt_separator 启用了 Jekyll 的文章摘要(post excerpts),那么在首页浏览时就会遇到脚注被显示在了文章摘要下方的情况。

Post excerpts with footnotes

正常地,我们只希望访问者在点击某篇文章查看全文时能够在文章的末尾看到脚注内容;而在首页浏览数篇文章的标题和摘要时并不会受到脚注细节的干扰。所希望达成的效果是:

  1. 在首页引用摘要时,去掉引用参考旁的脚注上标标记。
  2. 在首页引用摘要时,去掉摘要末尾的脚注内容。

这样的改变并不会影响阅读全文时的脚注效果,只改善首页引用摘要时的显示效果。下面图片所显示的首页效果就要比上面的图片好很多。

Post excerpts without footnotes

启用摘要与自定义摘要内容1

在 Jekyll 中,变量 post.content 用以保存和引用一篇文章的正文内容,这其中就包括了脚注。默认地,Jekyll 的 index.html 文件会使用变量 post.content 将全文输出显示在首页,如果要启用文章摘要,需要用变量 post.excerpt 替换变量 post.content ,其效果类似于此:

<ul>
  {% for post in site.posts %}
    <li>
      <a href="{{ post.url }}">{{ post.title }}</a>
      <p>{{ post.excerpt }}</p>
    </li>
  {% endfor %}
</ul>

在第 5 行,已经将原有的变量 post.content 替换为了变量 post.excerpt。默认地,Jekyll 会自动生成摘要,摘要内容即为文章的第一个段落的内容。如果不希望使用 Jekyll 自动生成的摘要,也可以在文章的 YAML 头信息中增加 excerpt 来覆盖,这样可以自行撰写摘要内容。或者在 YAML 头信息中自定义一个 excerpt_separator

---
excerpt_separator: <!--more-->
---

Excerpt
<!--more-->
Out-of-excerpt

这意味着我们在正文中可以使用 <!-- more --> 标签来设定摘要内容,放置 <!-- more --> 标签以上的内容会被用作该篇文章的摘要。

同时,也可以在 _config.yml 文件中全局声明 excerpt_separator,来确定 Jekyll 的创建摘要的默认行为2

从摘要中删除脚注

如前文所说,如果在 Jekyll 中启用了文章摘要,那么 kramdown 会自动将脚注添加到摘要内容中进行显示。要想讲其删除,我们需要新增一个 Jekyll 插件(plugin)来过滤掉用于显示脚注的 <div> 标签。所使用到的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
require 'nokogiri'

module Jekyll
  module StripFootnotesFilter

    def strip_footnotes(raw)
      doc = Nokogiri::HTML.fragment(raw.encode('UTF-8', :invalid => :replace, :undef => :replace, :replace => ''))

      for block in ['div', 'sup', 'a'] do
        doc.css(block).each do |ele|
          ele.remove if (ele['class'] == 'footnotes' or ele['class'] == 'footnote')
        end
      end

      doc.inner_html

    end
  end
end

Liquid::Template.register_filter(Jekyll::StripFootnotesFilter)

在这段代码中,我们先使用 nokogiri3 gem 读入一段 HTML 代码片段来进行处理。在显示脚注时,kramdown 会将脚注内容放置在一个类名为“footnotes”的 <div> 标签中,其中也包括了脚注中所引用的链接 <a> 标签。使用 for 循环在读入的 HTML 代码片段中删除所有符合特定条件的标签名和类名的块级元素(block-level elements)4

所谓“符合特定条件的”主要是指:

  1. 文章末尾的脚注内容,其一般以 <div class="footnotes">...</div> 的形式进行包裹。
  2. 文章中引用参考旁的脚注上标标记,其一般以 <sup id="fnref:1"><a href="#fn:1" class="footnote">...</a></sup> 的形式进行包裹。

将上述代码保存为 _plugins/stripfootnotes.rb

想要使用该段代码为文章摘要去除脚注时,则只需要将引用的 {{ post.excerpt }} 替换为 {{ post.excerpt | strip_footnotes }} 即可。

...
  <p>{{ post.excerpt | strip_footnotes }}</p>
...
  1. Jekyll 官方文档对 post excerpts 的解释:https://jekyllrb.com/docs/posts/#post-excerpts 

  2. 如果要完全禁用文章摘要,可以设置成:excerpt_separator: ""。 

  3. Nokogiri (鋸) is an HTML, XML, SAX, and Reader parser. Among Nokogiri’s many features is the ability to search documents via XPath or CSS3 selectors: https://rubygems.org/gems/nokogiri/versions/1.6.8 

  4. Mozilla Developer Network 有关于 block-level elements(块级元素)和 inline elements(行内元素)的解释:https://developer.mozilla.org/zh-CN/docs/Web/HTML/Block-level_elements 

在微信中扫描二维码,然后发送给朋友分享到朋友圈

感谢您的支持与贡献

您的捐款将使您阅读到的内容变得更好。

支持微信支付和支付宝。

在微信中扫描二维码 在支付宝中扫描二维码

感谢您的支持与贡献

您的捐款将使您阅读到的内容变得更好。

触摸并按住二维码,选择识别图中二维码

触摸并按住二维码