在Ruby中以Github Markdown风格解释换行符为<br>

16

我在我的网站上使用Markdown来进行评论,并希望用户能够通过按 Enter 键创建换行,而不是像 space space enter 那样(详情请参见此meta问题)。

我该如何在Ruby中实现这个功能?你可能认为Github Flavored Markdown正是我需要的,但(令人惊讶的是),它相当有缺陷。

这是它们的实现方式

# in very clear cases, let newlines become <br /> tags
text.gsub!(/^[\w\<][^\n]*\n+/) do |x|
  x =~ /\n{2}/ ? x : (x.strip!; x << "  \n")
end

这个逻辑要求行以\w开头,并在末尾换行以创建<br>。 这个要求的原因是不希望影响列表:(但请参见下面的编辑;我甚至不确定这是否有意义)

* 我们不想要<br>
* 在这两个列表项之间

然而,在以下情况下,该逻辑会出现问题:

[some](http://google.com)
[links](http://google.com)
*this line is in italics*
another line
> the start of a blockquote!
another line

也就是说,在所有这些情况下,第一行末尾都应该有一个<br>,但GFM没有添加。

奇怪的是,在GFM的javascript版本中,这个问题被解决了

是否有人在Ruby中有“将换行符转换为<br>”的实现?

编辑:更让人困惑的是!

如果您查看Github的官方Github Flavored Markdown存储库,您将找到另一个换行符转<br>的正则表达式!

# in very clear cases, let newlines become <br /> tags
text.gsub!(/(\A|^$\n)(^\w[^\n]*\n)(^\w[^\n]*$)+/m) do |x|
  x.gsub(/^(.+)$/, "\\1  ")
end

我不知道这个正则表达式是什么意思,但它在上面的测试用例中表现并不比其他解决方案更好。

而且,似乎“不要干扰列表”的理由,要求行以单词字符开头并不成立。也就是说,标准的Markdown列表语义不会因为你添加了2个尾随空格而改变。例如,这里:

  • item 1
  • item 2
  • item 3

在这个问题的源代码中,“item 1”后面有2个尾随空格,但是如果你查看HTML,就不会看到多余的<br>标签。

这让我想到将换行符转换为<br>标签的最佳正则表达式只需简单地写为:

text.gsub!(/^[^\n]+\n+/) do |x|
  x =~ /\n{2}/ ? x : (x.strip!; x << "  \n")
end

有什么想法?


1
“你有什么想法?”我认为你忘记了提出一个问题,明确你想允许哪些情况和你想避免哪些情况。 - Phrogz
4
这里的要求真的不明确吗?在 Markdown 中将 <br> 解释为换行符是一种很流行的梗(在 Meta、Github、Coding Horror 等地方已经被广泛讨论过)。我并不知道所有的细节情况,我更想知道是否有人成功实现了这个想法。 - Tom Lehman
为什么不能直接使用Markdown或Textile? - kikito
@egarcia 因为Markdown不会将换行解释为<br>(您需要在标准Markdown中输入SPACE SPACE ENTER才能创建<br>)。 - Tom Lehman
你有检查过演示页面的脚本吗?那个JavaScript版本使用了Showdown(来自http://attacklab.net/showdown/),它是Markdown Perl版本的移植。它与GitHub提供的Ruby代码有很大不同。我注意到WMD,即所见即所得的Markdown编辑器(也来自Attacklab.net),存在你所描述的逻辑问题。 - IIsi 50MHz
2个回答

2

我不确定这是否有所帮助,但我只是使用ActionView::Helpers::TextHelper中的simple_format()方法。

ActionView simple_format

my_text = "Here is some basic text...\n...with a line break."

simple_format(my_text)

output => "<p>Here is some basic text...\n<br />...with a line break.</p>"

即使它不符合您的规格,查看simple_format()源代码中的.gsub!方法可能会帮助您编写自己所需的Markdown版本。

2

可能有些晚了,但对其他人可能有用。我已经通过使用正则表达式预处理文本来使其工作(但没有进行全面测试),如下所示。由于缺少零宽度回溯,它看起来很丑陋,但没关系。

# Append two spaces to a simple line, if it ends in newline, to render the
# markdown properly. Note: do not do this for lists, instead insert two newlines. Also, leave double newlines
# alone.
text.gsub! /^ ([\*\+\-]\s+|\d+\s+)? (.+?) (\ \ )? \r?\n (\r?\n|[\*\+\-]\s+|\d+\s+)? /xi do
  full, pre, line, spaces, post = $~.to_a
  if post != "\n" && pre.blank? && post.blank? && spaces.blank?
    "#{pre}#{line}  \n#{post}"
  elsif pre.present? || post.present?
    "#{pre}#{line}\n\n#{post}"
  else
    full
  end
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接