Николай обнови решението на 23.11.2011 07:15 (преди около 13 години)
+class Extra
+ def self.html_entities(string)
+ string.gsub!(/&/, '&')
+ string.gsub!(/</, '<')
+ string.gsub!(/>/, '>')
+ string.gsub!(/"/, '"')
+ string
+ end
+
+ def self.stripper(string)
+ out = ""
+ string.split(/\n/).each do
+ |row|
+ if row.match(/^\s{4,4}/) || row.match(/^>\s+/)
+ out += row + "\n"
+ else
+ out += row.strip + "\n"
+ end
+ end
+ out.chomp
+ end
+
+ def self.cleaner(string)
+ string.gsub!(/<\/blockquote>\n<blockquote>/, "\n")
+ string.gsub!(/<blockquote><\/blockquote>/, "")
+ string.gsub!(/<p><\/p>/, "")
+ string.gsub!(/<\/p>\n<p>/, "\n")
+ string.gsub!(/<\/code><\/pre>\n<pre><code>/, "\n")
+ string.gsub!(/\n<\/ol>\n<ol>/, "")
+ string.gsub!(/\n<\/ul>\n<ul>/, "")
+ string.strip
+ end
+end
+
+class Elements
+ def self.code_block(string)
+ "<pre><code>" + Extra.html_entities(string.sub(/^\s{4,4}/, '')) + "</code></pre>\n"
+ end
+
+ def self.quote(string)
+ "<blockquote>" + Formatter.new.to_html(string.sub(/^>\s+/, '')) + "</blockquote>\n"
+ end
+
+ def self.header(string)
+ out = string.sub(/^\#{1,4}\s+/, '')
+ type = string.match(/^\#{1,4}/).to_s.length.to_s
+ "<h" + type + ">" + Elements.inner_elems(out) + "</h" + type + ">\n"
+ end
+
+ def self.paragraph(string)
+ "<p>" + Elements.inner_elems(string.chomp) + "</p>\n"
+ end
+
+ def self.inner_elems(string)
+ string = Extra.html_entities(string)
+ string = links(string)
+ string = strong_em(string)
+ string
+ end
+
+ def self.links(string)
+ string.gsub(/\[(.+?)\]\((.+?)\)/, '<a href="\2">\1</a>')
+ end
+
+ def self.strong_em(string)
+ out = ''
+ while matched = /(\*\*.+?\*\*)|(_.+?_)/.match(string)
+ out += matched.pre_match
+ if (matched[1])
+ out += '<strong>' + strong_em(matched[1][2..-3]) + '</strong>'
+ else
+ out += '<em>' + strong_em(matched[2][1..-2]) + '</em>'
+ end
+ string = matched.post_match
+ end
+ out + string
+ end
+
+ def self.lists(string)
+ out = ''
+ matched = /(^\d\.\s)|(^\*\s)/.match(string)
+ if (matched[1])
+ out = "<ol>\n <li>" + Elements.inner_elems(matched.post_match) + "</li>\n</ol>\n"
+ elsif (matched[2])
+ out = "<ul>\n <li>" + Elements.inner_elems(matched.post_match) + "</li>\n</ul>\n"
+ else
+ out = string
+ end
+ out
+ end
+end
+
+class Formatter
+ attr_accessor :text
+
+ def initialize(text = '')
+ @text = text
+ end
+
+ def matcher(row)
+ if row.match(/^\s{4,4}/) then output = Elements.code_block(row)
+ elsif row.match(/^>\s+/) then output = Elements.quote(row)
+ elsif row.match(/^\#{1,4}\s+/) then output = Elements.header(row)
+ elsif row.match(/(^\d\.\s)|(^\*\s)/) then output = Elements.lists(row)
+ else output = Elements.paragraph(row)
+ end
+ output
+ end
+
+ def to_html(input = @text)
+ output = ""
+ Extra.stripper(input).split(/\n/).each { |row| output += matcher(row) }
+ Extra.cleaner(output.chomp)
+ end
+
+ def to_s
+ to_html(@text)
+ end
+
+ def inspect
+ @text
+ end
+end