当在GitHub Pages上使用Minimal Mistakes作为Jekyll主题时,会遇到中文字数统计错误的问题,一整段话被统计为1个字。本篇文章将会简单说明问题的来源和解决方案。

问题来源

Minimal Mistakes在_includes/page__meta.html中,使用了document.content | strip_html | number_of_words来计算文章字数(相关代码),这一步将document.content去除HTML标签,然后调用number_of_words函数计算字数。

number_of_words函数由Jekyll实现。GitHub Pages使用的Jekyll版本为3.9.0,根据其实现,计算字数的代码仅仅为input.split.length,根据Ruby文档,将会根据空格分割文本,然后输出分割后的文本数量。也就是说,会根据空格的数量来确定字数。这样的做法对于英文文章来说自然问题不大,但并不适合中文。

解决方案

解决这个问题有多种方案,前2个方案无法在GitHub Pages上独立完成,需要搭配GitHub Action或其他CI;最后1种方案可以在纯GitHub Pages的环境中使用。

如果修改了Minimal Mistakes的文件,将其放在自己仓库下便可覆盖默认文件。

自定义插件

这是最优雅的方法,通过自定义插件可以在不覆盖Minimal Mistakes文件的情况下修复问题。

下载这个文件放置于_plugins/number_of_words.rb便可。

升级Jekyll

这是最简单直接的方法,在4.1.0版本的Jekyll中,这个问题被修复了。

当然,除了升级以外还需要将_includes/page__meta.html中的number_of_words修改为number_of_words: "auto"或者number_of_words: "cjk"才能正常生效。

覆盖主题文件

这个方法使用了Liquid模板引擎的语法,可以不依赖任何CI,直接在GitHub Pages上使用。

用以下代码替换_includes/page__meta.html中的{% assign words = document.content | strip_html | number_of_words %}

      {% assign content0 = document.content | strip_html %}
      {% assign content_size = content0 | size | minus: 1 %}
      {% assign pre_is_letter = false %}
      {% assign words = 0 %}
      {% for i in (0..content_size) %}
        {% assign character = content0 | slice: i %}
        {% case character %}
          {% when "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" %}
            {% assign pre_is_letter = true %}
          {% when "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" %}
            {% assign pre_is_letter = true %}
          {% when "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" %}
            {% assign pre_is_letter = true %}
          {% when " ", "\t", "\r", "\n", "!", ".", "?", ",", "!", "。", "?", ",", "/", "、", ":", ":", "(", "(", ")", ")", ";", ";", "_", "—", "-" %}
            {% if pre_is_letter %}
              {% assign words = words | plus: 1 %}
            {% endif %}
            {% assign pre_is_letter = false %}
          {% else %}
            {% if pre_is_letter %}
              {% assign words = words | plus: 1 %}
            {% endif %}
            {% assign pre_is_letter = false %}
            {% assign words = words | plus: 1 %}
        {% endcase %}
      {% endfor %}

这部分代码是作者自己编写的,欢迎多多交流。

感谢

最后特别感谢iBug引导了修复方向。


xfl03
1 声望0 粉丝

擅长Java