Chen Yufei's Blog

Programming Language, Apple, Linux

解决 Markdown 转 HTML 中文换行变空格的问题

在 Vim 里编辑文件时我设置行宽不超过 80 个字符,因此编辑 Markdown 文件时一段话里会有多个换行。我用 Octopress 默认配置的 rdiscount 来生成 HTML 文件,这些换行都会保留在最后生成的 HTML 文件中。

浏览器对换行的处理是转成空格,这对英文来说很自然,但对中文就很讨厌了。我在 Stack Overflow 上提了这个问题,从这个详细的回答来看,这是一个历史遗留问题,短期内不会解决。

所以还是自己动手吧。解决办法是在生成 HTML 前把所有连续的中文行转成一行。(修改 Markdown 的实现也可以,但 rdiscount 用了 C 写的 Markdown 实现 discount,hack 起来比较麻烦。) 在 Ruby 1.9 中,连接中文行可以很方便的用正则表达式实现,注意开头的 #encoding: UTF-8 是必须的。

1
2
3
4
5
6
7
8
9
10
11
#encoding: UTF-8

class String
  def join_chinese
    unless @chinese_regex
      han = '\p{Han}|[,。?;:‘’“”、!……()]'
      @chinese_regex = Regexp.new("(#{han}) *\n *(#{han})", Regexp::MULTILINE)
    end
    gsub(@chinese_regex, '\1\2')
  end
end

可以用来转换文件的代码在 gist 上,但我不希望把 Markdown 源文件变成有着巨长行的文本,所以我修改了 jekyll,在调用 rdiscount 前对内容调用 join_chinese 方法。需要修改 lib/jekyll/converters/markdown.rb,patch 如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
--- bak-markdown.rb 2011-12-23 20:14:24.000000000 +0800
+++ markdown.rb  2011-12-23 20:13:19.000000000 +0800
@@ -1,3 +1,15 @@
+#encoding: UTF-8
+
+class String
+  def join_chinese
+    unless @chinese_regex
+      han = '\p{Han}|[,。?;:‘’“”、!……()]'
+      @chinese_regex = Regexp.new("(#{han})\n(#{han})", Regexp::MULTILINE)
+    end
+    gsub(@chinese_regex, '\1\2')
+  end
+end
+
 module Jekyll

   class MarkdownConverter < Converter
@@ -115,7 +127,7 @@
             }).to_html
           end
         when 'rdiscount'
-          RDiscount.new(content, *@rdiscount_extensions).to_html
+          RDiscount.new(content.join_chinese, *@rdiscount_extensions).to_html
         when 'maruku'
           Maruku.new(content).to_html
       end

用 Markdown 来写这种类型的 blog 真是舒服多了。

Comments