更新:记录here's the implementation I ended up using。
这是我正在研究的解析器的精简版本。还有一些代码,但是应该很容易掌握这个解析器的基本概念。
class Markup
def initialize(markup)
@markup = markup
end
def to_html
@html ||= @markup.split(/(\r\n){2,}|\n{2,}/).map {|p| Paragraph.new(p).to_html }.join("\n")
end
class Paragraph
def initialize(paragraph)
@p = paragraph
end
def to_html
@p.gsub!(/'{3}([^']+)'{3}/, "<strong>\\1</strong>")
@p.gsub!(/'{2}([^']+)'{2}/, "<em>\\1</em>")
@p.gsub!(/`([^`]+)`/, "<code>\\1</code>")
case @p
when /^=/
level = (@p.count("=") / 2) + 1 # Starting on h2
@p.gsub!(/^[= ]+|[= ]+$/, "")
"<h#{level}>" + @p + "</h#{level}>"
when /^(\*|\#)/
# I'm parsing lists here. Quite a lot of code, and not relevant, so
# I'm leaving it out.
else
@p.gsub!("\n", "\n<br/>")
"<p>" + @p + "</p>"
end
end
end
end
p Markup.new("Here is `code` and ''emphasis'' and '''bold'''!
Baz").to_html
# => "<p>Here is <code>code</code> and <em>emphasis</em> and <strong>bold</strong>!</p>\n<p>Baz</p>"
因此,正如您所看到的,我将文本分成段落,每个段落都是标题,列表或常规段落。
是否可以为这样的解析器添加对nowiki标记的支持(其中&lt; nowiki&gt;&lt; / nowiki&gt;之间的所有内容都没有被解析)?随意回答“否”,并建议创建解析器的替代方法:)
作为旁注,您可以在Github上看到实际的解析器代码。 markup.rb和paragraph.rb
答案 0 :(得分:3)
如果你使用一个简单的标记化器,那么管理这类东西要容易得多。一种方法是创建一个可以捕获整个语法的单个正则表达式,但这可能会有问题。另一种方法是将文档拆分为需要重写的部分,以及应该跳过的部分,这可能是更简单的方法。
这是一个可以根据需要扩展的简单框架:
def wiki_subst(string)
buffer = string.dup
result = ''
while (m = buffer.match(/<\s*nowiki\s*>.*?<\s*\/\s*nowiki\s*>/i))
result << yield(m.pre_match)
result << m.to_s
buffer = m.post_match
end
result << yield(buffer)
result
end
example = "replace me<nowiki>but not me</nowiki>replace me too<NOWIKI>but not me either</nowiki>and me"
puts wiki_subst(example) { |s| s.upcase }
# => REPLACE ME<nowiki>but not me</nowiki>REPLACE ME TOO<NOWIKI>but not me either</nowiki>AND ME