Решение на Пета задача от Венета Денчева

Обратно към всички решения

Към профила на Венета Денчева

Резултати

  • 8 точки от тестове
  • 0 бонус точки
  • 8 точки общо
  • 56 успешни тест(а)
  • 1 неуспешни тест(а)

Код

module BlockFormatter
def self.format_headings(text)
text.gsub(/^([ \t]*)(\#{1,4})\s+(\S.+)$/) do |match|
unless $1 == ' '
length = $2.length.to_s
match = '<h' + length + '>' + $3.strip + '</h' + length + '>'
end
match
end
end
def self.format_code(text)
text.gsub(/(^ {4}.*(\n|$))+/) do |match|
match = match.gsub(/^ {4}/, '')
'<pre><code>' + match.sub(/(\n?)\z/, '</code></pre>\1')
end
end
def self.format_quote(text)
text.gsub(/(^([ \t]*)>\s.*(\n|$))+/) do |match|
unless $1 == ' '
match = match.gsub(/^[ \t]*>\s/, '')
match = self.format_olists(self.format_ulists(match))
match = self.format_paragraphs(self.format_headings(match))
match = '<blockquote>' + match.sub(/(\n?)\z/, "</blockquote>\n")
end
match
end
end
def self.format_paragraphs(text)
text.gsub(/(\A|(<\/.+?>\n+))([^<>]+?)(\z|(\n+<.+?>))/m) do
open_group = $1
close_group = $4
matched_group = $3.strip.gsub(/((\A|(^$)+)\n*)(.+?)(\n*(\z|(^$)+))/m) do
$1 + '<p>' + $4.strip + '</p>' + $5
end
open_group + matched_group + close_group
end
end
def self.format_ulists(text)
text.gsub(/(^[ \t]*\*\s+\S.*(\n|$))+/) do |match|
match = match.gsub(/^[ \t]*\*\s+(\S.*)(\n|$)/) { " <li>" + $1.strip + "</li>\n" }
"<ul>\n" + match + "</ul>\n"
end
end
def self.format_olists(text)
text.gsub(/(^[ \t]*\d\.\s+\S.*(\n|$))+/) do |match|
match = match.gsub(/^[ \t]*\d\.\s+(\S.*)(\n|$)/) { " <li>" + $1.strip + "</li>\n" }
"<ol>\n" + match + "</ol>\n"
end
end
end
module TextFormatter
def self.escape_special_chars(text)
text = text.gsub(/&/, '&amp;')
text = text.gsub(/</, '&lt;')
text = text.gsub(/(?<=.)>/, '\1&gt;')
text = text.gsub(/"/, '&quot;')
end
def self.format_links(text)
text.gsub(/^(.*?)\[([^\]]+)\]\(([^\)]+)\)(.*)$/) do
$1 + '<a href="' + $3 + '">' + $2 + '</a>' + $4
end
end
def self.format_text(text)
text.gsub(/^(.*?)((\*{2}.+?\*{2})|(_.+?_))(.*)$/) do |match|
self.format_text_line(match, 0)
end
end
def self.format_text_line(text, position)
max_pos = text.length
em_pos = text.index('_', position) || max_pos
strong_pos = text.index('**', position) || max_pos
text = self.add_strong_emphasize(text, position, em_pos, strong_pos, max_pos)
next_pos = [em_pos, strong_pos].min + 1
if next_pos < max_pos && text =~ /^(.*?)((\*{2}.+?\*{2})|(_.+?_))(.*)$/
text = self.format_text_line(text, next_pos)
end
text
end
def self.add_strong_emphasize(text, pos, em_pos, strong_pos, max_pos)
if em_pos < max_pos && em_pos < strong_pos
text = self.emphasize(text, pos, max_pos)
elsif strong_pos < max_pos
text = self.add_strong(text, pos, max_pos)
end
text
end
def self.emphasize(text, pos, max_pos)
result_text = pos > 0 ? text[0..(pos-1)] : ''
result_text += text[pos..(max_pos-1)].sub(/^(.*?)_(.+?)_(.*)$/) do |match|
unless $2.index('</strong>')
match = $1 + '<em>' + $2 + '</em>' + $3
end
match
end
result_text
end
def self.add_strong(text, pos, max_pos)
result_text = pos > 0 ? text[0..(pos-1)] : ''
result_text += text[pos..(max_pos-1)].sub(/^(.*?)\*{2}(.+?)\*{2}(.*)$/) do |match|
unless $2.index('</em>')
match = $1 + '<strong>' + $2 + '</strong>' + $3
end
match
end
result_text
end
end
class Formatter
def initialize(raw_text)
@plain_text = raw_text
@formated_text = @plain_text
@formatted = false
end
def add_formatting(text)
text = BlockFormatter.format_quote(text)
text = BlockFormatter.format_headings(text)
text = BlockFormatter.format_ulists(text)
text = BlockFormatter.format_olists(text)
text = BlockFormatter.format_paragraphs(text)
text = TextFormatter.format_links(text)
text = TextFormatter.format_text(text)
end
def to_html
if (!@formatted)
@formated_text = TextFormatter.escape_special_chars(@formated_text)
@formated_text = BlockFormatter.format_code(@formated_text)
@formated_text = @formated_text.gsub(/(\A|(<\/pre>\n+))([^<]+?)(\z|(\n+<pre>))/m) do
$1 + add_formatting($3) + $4
end
@formated_text = @formated_text.rstrip
@formatted = true
end
@formated_text
end
def to_s
to_html
end
def inspect
@plain_text
end
end

Лог от изпълнението

.......................F.................................

Failures:

  1) Formatter links allows multiple links on a single line
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>We have <a href=\"some-url\">a first</a> and <a href=\"another-url\">Second</a>.</p>"
            got: "<p>We have <a href=\"some-url\">a first</a> and [Second](another-url).</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-wsscv/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-wsscv/spec.rb:286:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/homework/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.61418 seconds
57 examples, 1 failure

Failed examples:

rspec /tmp/d20111129-16859-wsscv/spec.rb:285 # Formatter links allows multiple links on a single line

История (1 версия и 0 коментара)

Венета обнови решението на 20.11.2011 22:43 (преди над 12 години)

+module BlockFormatter
+ def self.format_headings(text)
+ text.gsub(/^([ \t]*)(\#{1,4})\s+(\S.+)$/) do |match|
+ unless $1 == ' '
+ length = $2.length.to_s
+ match = '<h' + length + '>' + $3.strip + '</h' + length + '>'
+ end
+ match
+ end
+ end
+
+ def self.format_code(text)
+ text.gsub(/(^ {4}.*(\n|$))+/) do |match|
+ match = match.gsub(/^ {4}/, '')
+ '<pre><code>' + match.sub(/(\n?)\z/, '</code></pre>\1')
+ end
+ end
+
+ def self.format_quote(text)
+ text.gsub(/(^([ \t]*)>\s.*(\n|$))+/) do |match|
+ unless $1 == ' '
+ match = match.gsub(/^[ \t]*>\s/, '')
+ match = self.format_olists(self.format_ulists(match))
+ match = self.format_paragraphs(self.format_headings(match))
+ match = '<blockquote>' + match.sub(/(\n?)\z/, "</blockquote>\n")
+ end
+ match
+ end
+ end
+
+ def self.format_paragraphs(text)
+ text.gsub(/(\A|(<\/.+?>\n+))([^<>]+?)(\z|(\n+<.+?>))/m) do
+ open_group = $1
+ close_group = $4
+ matched_group = $3.strip.gsub(/((\A|(^$)+)\n*)(.+?)(\n*(\z|(^$)+))/m) do
+ $1 + '<p>' + $4.strip + '</p>' + $5
+ end
+ open_group + matched_group + close_group
+ end
+ end
+
+ def self.format_ulists(text)
+ text.gsub(/(^[ \t]*\*\s+\S.*(\n|$))+/) do |match|
+ match = match.gsub(/^[ \t]*\*\s+(\S.*)(\n|$)/) { " <li>" + $1.strip + "</li>\n" }
+ "<ul>\n" + match + "</ul>\n"
+ end
+ end
+
+ def self.format_olists(text)
+ text.gsub(/(^[ \t]*\d\.\s+\S.*(\n|$))+/) do |match|
+ match = match.gsub(/^[ \t]*\d\.\s+(\S.*)(\n|$)/) { " <li>" + $1.strip + "</li>\n" }
+ "<ol>\n" + match + "</ol>\n"
+ end
+ end
+end
+
+module TextFormatter
+ def self.escape_special_chars(text)
+ text = text.gsub(/&/, '&amp;')
+ text = text.gsub(/</, '&lt;')
+ text = text.gsub(/(?<=.)>/, '\1&gt;')
+ text = text.gsub(/"/, '&quot;')
+ end
+
+ def self.format_links(text)
+ text.gsub(/^(.*?)\[([^\]]+)\]\(([^\)]+)\)(.*)$/) do
+ $1 + '<a href="' + $3 + '">' + $2 + '</a>' + $4
+ end
+ end
+
+ def self.format_text(text)
+ text.gsub(/^(.*?)((\*{2}.+?\*{2})|(_.+?_))(.*)$/) do |match|
+ self.format_text_line(match, 0)
+ end
+ end
+
+ def self.format_text_line(text, position)
+ max_pos = text.length
+ em_pos = text.index('_', position) || max_pos
+ strong_pos = text.index('**', position) || max_pos
+ text = self.add_strong_emphasize(text, position, em_pos, strong_pos, max_pos)
+ next_pos = [em_pos, strong_pos].min + 1
+ if next_pos < max_pos && text =~ /^(.*?)((\*{2}.+?\*{2})|(_.+?_))(.*)$/
+ text = self.format_text_line(text, next_pos)
+ end
+
+ text
+ end
+
+ def self.add_strong_emphasize(text, pos, em_pos, strong_pos, max_pos)
+ if em_pos < max_pos && em_pos < strong_pos
+ text = self.emphasize(text, pos, max_pos)
+ elsif strong_pos < max_pos
+ text = self.add_strong(text, pos, max_pos)
+ end
+
+ text
+ end
+
+ def self.emphasize(text, pos, max_pos)
+ result_text = pos > 0 ? text[0..(pos-1)] : ''
+ result_text += text[pos..(max_pos-1)].sub(/^(.*?)_(.+?)_(.*)$/) do |match|
+ unless $2.index('</strong>')
+ match = $1 + '<em>' + $2 + '</em>' + $3
+ end
+ match
+ end
+
+ result_text
+ end
+
+ def self.add_strong(text, pos, max_pos)
+ result_text = pos > 0 ? text[0..(pos-1)] : ''
+ result_text += text[pos..(max_pos-1)].sub(/^(.*?)\*{2}(.+?)\*{2}(.*)$/) do |match|
+ unless $2.index('</em>')
+ match = $1 + '<strong>' + $2 + '</strong>' + $3
+ end
+ match
+ end
+
+ result_text
+ end
+end
+
+class Formatter
+ def initialize(raw_text)
+ @plain_text = raw_text
+ @formated_text = @plain_text
+ @formatted = false
+ end
+
+ def add_formatting(text)
+ text = BlockFormatter.format_quote(text)
+ text = BlockFormatter.format_headings(text)
+ text = BlockFormatter.format_ulists(text)
+ text = BlockFormatter.format_olists(text)
+ text = BlockFormatter.format_paragraphs(text)
+ text = TextFormatter.format_links(text)
+ text = TextFormatter.format_text(text)
+ end
+
+ def to_html
+ if (!@formatted)
+ @formated_text = TextFormatter.escape_special_chars(@formated_text)
+ @formated_text = BlockFormatter.format_code(@formated_text)
+ @formated_text = @formated_text.gsub(/(\A|(<\/pre>\n+))([^<]+?)(\z|(\n+<pre>))/m) do
+ $1 + add_formatting($3) + $4
+ end
+ @formated_text = @formated_text.rstrip
+ @formatted = true
+ end
+ @formated_text
+ end
+
+ def to_s
+ to_html
+ end
+
+ def inspect
+ @plain_text
+ end
+end