Решение на Пета задача от Мартин Асенов

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

Към профила на Мартин Асенов

Резултати

  • 4 точки от тестове
  • 0 бонус точки
  • 4 точки общо
  • 25 успешни тест(а)
  • 32 неуспешни тест(а)

Код

class Regex
HEADER = /^(\#{1,4})\s(\S.+)$/
BOLD = /(\*\*)(.+?)(\*\*)/
REPLACE_BOLD = /\*\*/
ITALIC = /(_)(.+?)(_)/
REPLACE_ITALIC = /_/
URL = /\[(.+)\]\((.+)\)/
OL_UNIT = /^(\d\.\s)(.+)$/
REPLACE_OL_UNIT = /\d\.\s/
WRAP_OL_UNIT = /<li>.+<\/li>/
end
class Pattern
attr_reader :pattern
def initialize(pattern)
@pattern = pattern
end
end
class Matcher
def initialize(pattern)
@pattern = pattern
end
def decorate(string, opening_tag, closing_tag)
copy = String.new string
scan_array = string.scan(@pattern.pattern)
scan_array.each do |match|
if should_decorate(match)
copy.sub!(scan_to_s(match),opening_tag + scan_to_s(match).strip + closing_tag)
end
end
copy
end
def replace_all(string,replacement)
copy = String.new string
copy.gsub!(@pattern.pattern,replacement)
copy
end
def match(text)
text.match @pattern.pattern
end
private
def should_decorate(line)
scanned_line = scan_to_s(line)
result = !scanned_line.match(/<h\d>.+/) && !scanned_line.match(/<ol>/)
result = result && !scanned_line.match(/<\/ol>/) && !scanned_line.match(/<li>/)
result = result && !scanned_line.match(/<\/li>/) && !scanned_line.match(/<ul>/)
result = result && !scanned_line.match(/<\/ul>/)
result
end
def scan_to_s(scan_array)
if scan_array.kind_of? String
return scan_array
else
result = String.new
end
scan_array.each do |match|
if match
result += match
end
end
result.end_with?("\n") ? result.chop! : result
end
end
class MarkupParser
def initialize(text)
copy = String.new text
@result = String.new
for line in copy.each_line
@result += parse_line(line)
end
@result = parse_ol(@result)
@result = parse_paragraphs(@result)
if @result.end_with?("\n")
@result.chop!
end
end
def parse_line(line)
converted_line = escape_special(line)
converted_line = parse_headers(converted_line)
converted_line = parse_url(converted_line)
converted_line = parse_text_weight(converted_line)
converted_line = parse_italic(converted_line)
end
def parse_paragraphs(text)
paragraphs_pattern = Pattern.new /(^.+$)|((.+\n)+(.+)?)/
paragraphs_matcher = Matcher.new paragraphs_pattern
paragraphs_matcher.decorate(text,"<p>","</p>")
end
def parse_ol(text)
ol_pattern = Pattern.new Regex::OL_UNIT
ol_matcher = Matcher.new ol_pattern
result = ol_matcher.decorate(text," <li>","</li>")
ol_replace_pattern = Pattern.new Regex::REPLACE_OL_UNIT
ol_replace_matcher = Matcher.new ol_replace_pattern
ol_replace_matcher.replace_all(result,"")
end
def parse_headers(line)
result = String.new
if line.match Regex::HEADER
h_type = $1.length.to_s
result = line.sub(Regex::HEADER, "<h" + h_type + ">" + $2 + "</h" + h_type + ">")
else
result += line
end
result
end
def escape_special(line)
result = String.new
replace_hash = { /&/ => "&amp;", /</ => "&lt;", />/ => "&gt;", /"/ => "&quot;" }
replace_hash.each do |pattern, repl|
if line.match pattern
line.gsub!(pattern,repl)
end
result = line
end
result
end
def parse_text_weight(line)
bold_pattern = Pattern.new Regex::BOLD
bold_matcher = Matcher.new bold_pattern
res = bold_matcher.decorate(line,"<strong>","</strong>")
bold_replace_pattern = Pattern.new Regex::REPLACE_BOLD
bold_replace_matcher = Matcher.new bold_replace_pattern
bold_replace_matcher.replace_all(res,"")
end
def parse_italic(line)
italic_pattern = Pattern.new Regex::ITALIC
italic_matcher = Matcher.new italic_pattern
res = italic_matcher.decorate(line,"<em>","</em>")
italic_replace_pattern = Pattern.new Regex::REPLACE_ITALIC
italic_replace_matcher = Matcher.new italic_replace_pattern
italic_replace_matcher.replace_all(res,"")
end
def parse_url(line)
result = String.new
if line.match Regex::URL
result = line.sub(Regex::URL, '<a href="' + $2 + '">' + $1 + "</a>")
else
result = line
end
result
end
def html
@result
end
end
class Formatter
def initialize(text)
@text = text
markup_parser = MarkupParser.new(text)
@text_to_html = markup_parser.html
end
def inspect
@text
end
def to_html
@text_to_html
end
def to_s
@text_to_html
end
end

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

..F....F..FFFFFFFFFFF..F.F..FFFFFF...FF.FF.F...FF.FFF...F

Failures:

  1) Formatter paragraphs renders multiline paragraps
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>First line.\nSecond line.\nThird line.</p>\n\n<p>Last line, of course.</p>"
            got: "<p>First line.</p>\n<p>Second line.</p>\n<p>Third line.</p>\n\n<p>Last line, of course.</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
       -<p>First line.
       -Second line.
       -Third line.</p>
       +<p>First line.</p>
       +<p>Second line.</p>
       +<p>Third line.</p>
        
        <p>Last line, of course.</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:45: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)>'

  2) Formatter headers renders tricky ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<h2>Leading wsp</h2>"
            got: "<p>## Leading wsp</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:106: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)>'

  3) Formatter code blocks renders simple blocks
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>This one is a simple code block</code></pre>"
            got: "<p>This one is a simple code block</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:124: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)>'

  4) Formatter code blocks renders multiline blocks with empty lines
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>require 'gravity'\n\n# I'm flying! Just like in Python!</code></pre>"
            got: "<p>require 'gravity'</p>\n<p></p>\n<p># I'm flying! Just like in Python!</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
       -<pre><code>require 'gravity'
       -
       -# I'm flying! Just like in Python!</code></pre>
       +<p>require 'gravity'</p>
       +<p></p>
       +<p># I'm flying! Just like in Python!</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:140: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)>'

  5) Formatter code blocks renders multiple ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>First code-block</code></pre>\n\n<pre><code>Second block of code</code></pre>"
            got: "<p>First code-block</p>\n\n<p>Second block of code</p>"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,4 +1,4 @@
       -<pre><code>First code-block</code></pre>
       +<p>First code-block</p>
        
       -<pre><code>Second block of code</code></pre>
       +<p>Second block of code</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:156: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)>'

  6) Formatter code blocks escapes special entities
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>quote = &quot;Simple &amp; efficient&quot;;</code></pre>"
            got: "<p>quote = &quot;Simple &amp; efficient&quot;;</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:160: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)>'

  7) Formatter code blocks renders properly a longer example with tabs and Unicode
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>// \u041F\u0440\u0438\u043C\u0435\u0440 \u0437\u0430 \u0431\u043B\u043E\u043A \u0441 \u043A\u043E\u0434.\n// \u0412 \u043D\u0435\u0433\u043E \u0432\u0441\u0435\u043A\u0438 \u0440\u0435\u0434, \u0434\u043E\u0440\u0438 \u043F\u0440\u0430\u0437\u043D\u0438\u0442\u0435, \u0435 \u043F\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0430\u043D \u043E\u0442 \u0442\u043E\u0447\u043D\u043E \u0447\u0435\u0442\u0438\u0440\u0438 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B\u0430.\ninclude &lt;stdio.h&gt;\n\nint main(int, char**) {\n\t// Whitespace \u0441\u043B\u0435\u0434 \u0447\u0435\u0442\u0438\u0440\u0438\u0442\u0435 \u0437\u0430\u0434\u044A\u043B\u0436\u0438\u0442\u0435\u043B\u043D\u0438 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B\u0430 \u0432 \u043D\u0430\u0447\u0430\u043B\u043E\u0442\u043E, \u0441\u0435 \u0437\u0430\u043F\u0430\u0437\u0432\u0430 \u0432\u0438\u043D\u0430\u0433\u0438.\n\treturn 42;\n}</code></pre>"
            got: "<p>// \u041F\u0440\u0438\u043C\u0435\u0440 \u0437\u0430 \u0431\u043B\u043E\u043A \u0441 \u043A\u043E\u0434.</p>\n<p>// \u0412 \u043D\u0435\u0433\u043E \u0432\u0441\u0435\u043A\u0438 \u0440\u0435\u0434, \u0434\u043E\u0440\u0438 \u043F\u0440\u0430\u0437\u043D\u0438\u0442\u0435, \u0435 \u043F\u0440\u0435\u0434\u0448\u0435\u0441\u0442\u0432\u0430\u043D \u043E\u0442 \u0442\u043E\u0447\u043D\u043E \u0447\u0435\u0442\u0438\u0440\u0438 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B\u0430.</p>\n<p>include &lt;stdio.h&gt;</p>\n<p></p>\n<p>int main(int, char) {</p>\n<p>// Whitespace \u0441\u043B\u0435\u0434 \u0447\u0435\u0442\u0438\u0440\u0438\u0442\u0435 \u0437\u0430\u0434\u044A\u043B\u0436\u0438\u0442\u0435\u043B\u043D\u0438 \u0438\u043D\u0442\u0435\u0440\u0432\u0430\u043B\u0430 \u0432 \u043D\u0430\u0447\u0430\u043B\u043E\u0442\u043E, \u0441\u0435 \u0437\u0430\u043F\u0430\u0437\u0432\u0430 \u0432\u0438\u043D\u0430\u0433\u0438.</p>\n<p>return 42;</p>\n<p>}</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,9 +1,9 @@
       -<pre><code>// Пример за блок с код.
       -// В него всеки ред, дори празните, е предшестван от точно четири интервала.
       -include &lt;stdio.h&gt;
       -
       -int main(int, char**) {
       -	// Whitespace след четирите задължителни интервала в началото, се запазва винаги.
       -	return 42;
       -}</code></pre>
       +<p>// Пример за блок с код.</p>
       +<p>// В него всеки ред, дори празните, е предшестван от точно четири интервала.</p>
       +<p>include &lt;stdio.h&gt;</p>
       +<p></p>
       +<p>int main(int, char) {</p>
       +<p>// Whitespace след четирите задължителни интервала в началото, се запазва винаги.</p>
       +<p>return 42;</p>
       +<p>}</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:186: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)>'

  8) Formatter code blocks renders properly with mixed content
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<h1>This is a header</h1>\n\n<p>Some parahraphs here</p>\n\n<pre><code>Some clean code\nWhich is also beautiful\nAnd maybe also compiles!</code></pre>\n\n<p>More paragraphs there?</p>"
            got: "<h1>This is a header</h1>\n\n<p>Some parahraphs here</p>\n\n<p>Some clean code</p>\n<p>Which is also beautiful</p>\n<p>And maybe also compiles!</p>\n\n<p>More paragraphs there?</p>"
       
       (compared using ==)
       
       Diff:
       @@ -2,9 +2,9 @@
        
        <p>Some parahraphs here</p>
        
       -<pre><code>Some clean code
       -Which is also beautiful
       -And maybe also compiles!</code></pre>
       +<p>Some clean code</p>
       +<p>Which is also beautiful</p>
       +<p>And maybe also compiles!</p>
        
        <p>More paragraphs there?</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:214: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)>'

  9) Formatter blockquotes renders simple ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p>Simple quote</p></blockquote>"
            got: "<p>&gt; Simple quote</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:220: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)>'

  10) Formatter blockquotes renders multiline ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p>First line.\nSecond line.\nThird line.</p></blockquote>"
            got: "<p>&gt; First line.</p>\n<p>&gt; Second line.</p>\n<p>&gt; Third line.</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
       -<blockquote><p>First line.
       -Second line.
       -Third line.</p></blockquote>
       +<p>&gt; First line.</p>
       +<p>&gt; Second line.</p>
       +<p>&gt; Third line.</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:236: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)>'

  11) Formatter blockquotes renders multiple ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p>First quote.</p></blockquote>\n\n<blockquote><p>Second quote.</p></blockquote>"
            got: "<p>&gt; First quote.</p>\n\n<p>&gt; Second quote.</p>"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,4 +1,4 @@
       -<blockquote><p>First quote.</p></blockquote>
       +<p>&gt; First quote.</p>
        
       -<blockquote><p>Second quote.</p></blockquote>
       +<p>&gt; Second quote.</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:252: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)>'

  12) Formatter blockquotes renders multiline ones with multiple paragraphs
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p>First quote.</p>\n\n<p>Second quote.</p></blockquote>"
            got: "<p><p>&gt;</p>First quote.</p>\n&gt; \n<p>&gt; Second quote.</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
       -<blockquote><p>First quote.</p>
       -
       -<p>Second quote.</p></blockquote>
       +<p><p>&gt;</p>First quote.</p>
       +&gt; 
       +<p>&gt; Second quote.</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:268: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)>'

  13) Formatter blockquotes escapes special entities
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p>Cuttin &amp; Pastin, w/o Quotin (&quot;)</p></blockquote>"
            got: "<p>&gt; Cuttin &amp; Pastin, w/o Quotin (&quot;)</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:272: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)>'

  14) 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=\"another-url\">a first](some-url) and [Second</a>.</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/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)>'

  15) Formatter links does not render them in code blocks
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>This one [is a link](in-a-code-block) - keep as-is.</code></pre>"
            got: "<p>This one <a href=\"in-a-code-block\">is a link</a> - keep as-is.</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:299: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)>'

  16) Formatter lists renders simple unordered lists
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ul>\n  <li>\u0415\u0434\u043D\u043E.</li>\n  <li>\u0414\u0440\u0443\u0433\u043E.</li>\n  <li>\u0422\u0440\u0435\u0442\u043E...</li>\n</ul>"
            got: "<p>* \u0415\u0434\u043D\u043E.</p>\n<p>* \u0414\u0440\u0443\u0433\u043E.</p>\n<p>* \u0422\u0440\u0435\u0442\u043E...</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,4 @@
       -<ul>
       -  <li>Едно.</li>
       -  <li>Друго.</li>
       -  <li>Трето...</li>
       -</ul>
       +<p>* Едно.</p>
       +<p>* Друго.</p>
       +<p>* Трето...</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:330: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)>'

  17) Formatter lists renders simple ordered lists
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ol>\n  <li>\u041F\u044A\u0440\u0432\u043E.</li>\n  <li>\u0412\u0442\u043E\u0440\u043E.</li>\n  <li>\u0422\u0440\u0435\u0442\u043E...</li>\n</ol>"
            got: "  <li>\u041F\u044A\u0440\u0432\u043E.</li>\n  <li>\u0412\u0442\u043E\u0440\u043E.</li>\n  <li>\u0422\u0440\u0435\u0442\u043E...</li>"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,6 +1,4 @@
       -<ol>
          <li>Първо.</li>
          <li>Второ.</li>
          <li>Трето...</li>
       -</ol>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:348: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)>'

  18) Formatter lists renders lists with a single item
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ul>\n  <li>Single item.</li>\n</ul>"
            got: "<p>* Single item.</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,2 @@
       -<ul>
       -  <li>Single item.</li>
       -</ul>
       +<p>* Single item.</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:362: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)>'

  19) Formatter lists does not choke on malformed lists
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>1) \u041F\u044A\u0440\u0432\u043E.\n2 \u0412\u0442\u043E\u0440\u043E.\n3.\u0422\u0440\u0435\u0442\u043E</p>\n<ol>\n  <li>\u0427\u0435\u0442\u0432\u044A\u0440\u0442\u043E</li>\n</ol>"
            got: "<p>1) \u041F\u044A\u0440\u0432\u043E.</p>\n<p>2 \u0412\u0442\u043E\u0440\u043E.</p>\n<p>3.\u0422\u0440\u0435\u0442\u043E</p>\n  <li>\u0427\u0435\u0442\u0432\u044A\u0440\u0442\u043E</li>"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,7 +1,5 @@
       -<p>1) Първо.
       -2 Второ.
       -3.Трето</p>
       -<ol>
       +<p>1) Първо.</p>
       +<p>2 Второ.</p>
       +<p>3.Трето</p>
          <li>Четвърто</li>
       -</ol>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:394: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)>'

  20) Formatter lists escapes special entities in the list elements
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ul>\n  <li>The &amp;&amp; and || are logical operators</li>\n  <li>The `&quot;` symbol</li>\n</ul>"
            got: "<p>* The &amp;&amp; and || are logical operators</p>\n<p>* The `&quot;` symbol</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,5 +1,3 @@
       -<ul>
       -  <li>The &amp;&amp; and || are logical operators</li>
       -  <li>The `&quot;` symbol</li>
       -</ul>
       +<p>* The &amp;&amp; and || are logical operators</p>
       +<p>* The `&quot;` symbol</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:410: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)>'

  21) Formatter lists allows links in list elements
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ul>\n  <li>A <a href=\" here \">simple link</a> or there?</li>\n</ul>"
            got: "<p>* A <a href=\" here \">simple link</a> or there?</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,2 @@
       -<ul>
       -  <li>A <a href=" here ">simple link</a> or there?</li>
       -</ul>
       +<p>* A <a href=" here ">simple link</a> or there?</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:424: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)>'

  22) Formatter bold and italic text rendering works in blockquotes
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p><em>Simplest</em> case</p></blockquote>"
            got: "<p>&gt; <em>Simplest</em> case</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:455: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)>'

  23) Formatter bold and italic text rendering does not render in code blocks
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>Some _more words_ _to be_ **emphasized**?</code></pre>"
            got: "<p>Some <em>more words</em> <em>to be</em> <strong>emphasized</strong>?</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:459: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)>'

  24) Formatter bold and italic text rendering works in list elements
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ul>\n  <li>Some <em>more words</em> <em>to be</em> <strong>emphasized</strong></li>\n</ul>"
            got: "<p>* Some <em>more words</em> <em>to be</em> <strong>emphasized</strong></p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,2 @@
       -<ul>
       -  <li>Some <em>more words</em> <em>to be</em> <strong>emphasized</strong></li>
       -</ul>
       +<p>* Some <em>more words</em> <em>to be</em> <strong>emphasized</strong></p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:476: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)>'

  25) Formatter bold and italic text rendering works in links in list elements
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<ul>\n  <li>Some <a href=\"okay\"><em>more words</em> <em>to be</em> <strong>emphasized</strong></a>!</li>\n</ul>"
            got: "<p>* Some <a href=\"okay\"><em>more words</em> <em>to be</em> <strong>emphasized</strong></a>!</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,2 @@
       -<ul>
       -  <li>Some <a href="okay"><em>more words</em> <em>to be</em> <strong>emphasized</strong></a>!</li>
       -</ul>
       +<p>* Some <a href="okay"><em>more words</em> <em>to be</em> <strong>emphasized</strong></a>!</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:487: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)>'

  26) Formatter bold and italic text rendering does not allow parial overlapping
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>Some <em>more words **to be</em> emphasized**!</p>"
            got: "<p>Some <em>more words <strong>to be</em> emphasized</strong>!</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:496: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)>'

  27) Formatter special entities escapes them in code blocks
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>brand = &quot;Black &amp; Decker&quot;!</code></pre>"
            got: "<p>brand = &quot;Black &amp; Decker&quot;!</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:524: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)>'

  28) Formatter special entities escapes them in blockquotes
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<blockquote><p>&quot;Black &amp; Decker&quot;!</p></blockquote>"
            got: "<p>&gt; &quot;Black &amp; Decker&quot;!</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:530: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)>'

  29) Formatter whitespace removes excess leading and trailing whitespace
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>Some txt</p>"
            got: "\n\n<p>Some txt</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,4 @@
       +
       +
        <p>Some txt</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:547: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)>'

  30) Formatter whitespace ignores leading and trailing whitespace of lines whenever possible
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<h1>Test with a header</h1>"
            got: "<p>#    Test with a header</p>\n"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,2 @@
       -<h1>Test with a header</h1>
       +<p>#    Test with a header</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:555: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)>'

  31) Formatter whitespace does not touch trailing whitespace in code blocks
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<pre><code>Simple code blk  </code></pre>"
            got: "<p>Simple code blk</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:563: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)>'

  32) Formatter mixed, complex input renders properly
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<h1>\u0426\u044F\u043B\u043E\u0441\u0442\u0435\u043D \u043F\u0440\u0438\u043C\u0435\u0440</h1>\n<p>\u0422\u0443\u043A \u0449\u0435 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0438\u0440\u0430\u043C\u0435 \u043D\u0430\u043A\u0440\u0430\u0442\u043A\u043E \u0432\u044A\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u0438\u0442\u0435 \u043D\u0430 \u043D\u0430\u0448\u0438\u044F \u043F\u0440\u043E\u0441\u0442 Markdown-\u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0432\u0430\u0442\u0435\u043B.</p>\n\n<h2><em>\u0424\u0438\u043B\u043E\u0441\u043E\u0444\u0438\u044F</em> \u043D\u0430 <a href=\"http://daringfireball.net/projects/markdown/syntax#philosophy\">Markdown</a></h2>\n\n<p>\u041A\u0440\u0430\u0442\u044A\u043A \u0446\u0438\u0442\u0430\u0442 \u043E\u0442\u043D\u043E\u0441\u043D\u043E \u0444\u0438\u043B\u043E\u0441\u043E\u0444\u0438\u044F\u0442\u0430 \u043D\u0430 Markdown:</p>\n<blockquote><p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>\n\n<p>Readability, however, is emphasized above all else. A Markdown-formatted document should be publishable as-is, as plain text, without looking like it\u2019s been marked up with tags or formatting instructions.</p></blockquote>\n<p>\u041F\u043E\u0432\u0435\u0447\u0435 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043C\u043E\u0436\u0435 \u0434\u0430 \u043D\u0430\u043C\u0435\u0440\u0438\u0442\u0435 \u043D\u0430 <a href=\"http://daringfireball.net/projects/markdown\">\u0441\u0430\u0439\u0442\u0430 \u043D\u0430 <strong>Markdown</strong></a>.</p>\n\n<h2>\u041F\u0440\u0435\u0434\u0438\u043C\u0441\u0442\u0432\u0430</h2>\n\n<p>\u0421\u044A\u0437\u0434\u0430\u0432\u0430\u043D\u0435\u0442\u043E \u043D\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430\u043D\u0438\u0435 \u0432\u044A\u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0430 Markdown \u0438\u043C\u0430 \u043C\u043D\u043E\u0436\u0435\u0441\u0442\u0432\u043E \u043F\u0440\u0435\u0434\u0438\u043C\u0441\u0442\u0432\u0430.</p>\n\n<p>\u0415\u0442\u043E \u043D\u044F\u043A\u043E\u0438 \u043E\u0442 \u0442\u044F\u0445:</p>\n<ul>\n  <li>\u041B\u0435\u0441\u043D\u043E \u0447\u0435\u0442\u0438\u043C \u0432 <em>\u0441\u0443\u0440\u043E\u0432</em> \u0432\u0438\u0434</li>\n  <li>\u0411\u0435\u0437 &quot;\u0441\u043A\u0440\u0438\u0442\u0438&quot; \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u0430\u0449\u0438 \u0442\u0430\u0433\u043E\u0432\u0435 \u2014 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u0430\u043D\u0435\u0442\u043E \u0432\u0438 \u043D\u0438\u043A\u043E\u0433\u0430 \u043D\u0435 \u0441\u0435 \u0447\u0443\u043F\u0438</li>\n  <li>\u0421\u043B\u0435\u0434 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043C\u043E\u0436\u0435 \u0434\u0430 \u0438\u0437\u0433\u043B\u0435\u0436\u0434\u0430 \u043C\u043D\u043E\u0433\u043E \u0434\u043E\u0431\u0440\u0435</li>\n</ul>\n\n<h2>\u041F\u043E\u0434\u0434\u0440\u044A\u0436\u043A\u0430 \u0432 <em>Ruby</em></h2>\n\n<p>\u0412 <strong>Ruby</strong> \u0438\u043C\u0430 \u043C\u043D\u043E\u0436\u0435\u0441\u0442\u0432\u043E Gem-\u043E\u0432\u0435, \u043A\u043E\u0438\u0442\u043E \u043C\u043E\u0433\u0430\u0442 \u0434\u0430 \u0432\u0438 \u043F\u043E\u043C\u043E\u0433\u043D\u0430\u0442 \u0437\u0430 \u0434\u0430 \u043F\u0440\u0435\u0445\u0432\u044A\u0440\u043B\u044F\u0442\u0435 Markdown-\u0441\u044A\u0434\u044A\u0440\u0436\u0430\u043D\u0438\u0435 \u0432 HTML-\u0444\u043E\u0440\u043C\u0430\u0442.\n\u041A\u043E\u0434\u044A\u0442, \u043A\u043E\u0439\u0442\u043E \u0432\u0438\u0435 \u0441\u044A\u0437\u0434\u0430\u0432\u0430\u0442\u0435, \u0441\u044A\u0449\u043E \u043C\u043E\u0436\u0435 \u0434\u0430 \u0432\u044A\u0440\u0448\u0438 \u0442\u043E\u0432\u0430 \u0434\u043E \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430 \u0441\u0442\u0435\u043F\u0435\u043D.</p>\n\n<p>\u041F\u0440\u0438\u043C\u0435\u0440 \u0437\u0430 \u0443\u043F\u043E\u0442\u0440\u0435\u0431\u0430 \u043D\u0430 \u0432\u0430\u0448\u0438\u044F \u043A\u043E\u0434:</p>\n\n<pre><code># \u041C\u043D\u043E\u0433\u043E \u043F\u0440\u043E\u0441\u0442\u043E\nformatter = Formatter.new &quot;## My Markdown&quot;\nputs formatter.to_html</code></pre>"
            got: "<h1>\u0426\u044F\u043B\u043E\u0441\u0442\u0435\u043D \u043F\u0440\u0438\u043C\u0435\u0440</h1>\n<p>\u0422\u0443\u043A \u0449\u0435 \u0434\u0435\u043C\u043E\u043D\u0441\u0442\u0440\u0438\u0440\u0430\u043C\u0435 \u043D\u0430\u043A\u0440\u0430\u0442\u043A\u043E \u0432\u044A\u0437\u043C\u043E\u0436\u043D\u043E\u0441\u0442\u0438\u0442\u0435 \u043D\u0430 \u043D\u0430\u0448\u0438\u044F \u043F\u0440\u043E\u0441\u0442 Markdown-\u043F\u0440\u0435\u043E\u0431\u0440\u0430\u0437\u0443\u0432\u0430\u0442\u0435\u043B.</p>\n\n<h2><em>\u0424\u0438\u043B\u043E\u0441\u043E\u0444\u0438\u044F</em> \u043D\u0430 <a href=\"http://daringfireball.net/projects/markdown/syntax#philosophy\">Markdown</a></h2>\n\n<p>\u041A\u0440\u0430\u0442\u044A\u043A \u0446\u0438\u0442\u0430\u0442 \u043E\u0442\u043D\u043E\u0441\u043D\u043E \u0444\u0438\u043B\u043E\u0441\u043E\u0444\u0438\u044F\u0442\u0430 \u043D\u0430 Markdown:</p>\n<p><p>&gt;</p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>\n&gt; \n<p>&gt; Readability, however, is emphasized above all else. A Markdown-formatted document should be publishable as-is, as plain text, without looking like it\u2019s been marked up with tags or formatting instructions.</p>\n<p>\u041F\u043E\u0432\u0435\u0447\u0435 \u0438\u043D\u0444\u043E\u0440\u043C\u0430\u0446\u0438\u044F \u043C\u043E\u0436\u0435 \u0434\u0430 \u043D\u0430\u043C\u0435\u0440\u0438\u0442\u0435 \u043D\u0430 <a href=\"http://daringfireball.net/projects/markdown\">\u0441\u0430\u0439\u0442\u0430 \u043D\u0430 <strong>Markdown</strong></a>.</p>\n\n<h2>\u041F\u0440\u0435\u0434\u0438\u043C\u0441\u0442\u0432\u0430</h2>\n\n<p>\u0421\u044A\u0437\u0434\u0430\u0432\u0430\u043D\u0435\u0442\u043E \u043D\u0430 \u0441\u044A\u0434\u044A\u0440\u0436\u0430\u043D\u0438\u0435 \u0432\u044A\u0432 \u0444\u043E\u0440\u043C\u0430\u0442\u0430 Markdown \u0438\u043C\u0430 \u043C\u043D\u043E\u0436\u0435\u0441\u0442\u0432\u043E \u043F\u0440\u0435\u0434\u0438\u043C\u0441\u0442\u0432\u0430.</p>\n\n<p>\u0415\u0442\u043E \u043D\u044F\u043A\u043E\u0438 \u043E\u0442 \u0442\u044F\u0445:</p>\n<p>* \u041B\u0435\u0441\u043D\u043E \u0447\u0435\u0442\u0438\u043C \u0432 <em>\u0441\u0443\u0440\u043E\u0432</em> \u0432\u0438\u0434</p>\n<p>* \u0411\u0435\u0437 &quot;\u0441\u043A\u0440\u0438\u0442\u0438&quot; \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u0430\u0449\u0438 \u0442\u0430\u0433\u043E\u0432\u0435 \u2014 \u0444\u043E\u0440\u043C\u0430\u0442\u0438\u0440\u0430\u043D\u0435\u0442\u043E \u0432\u0438 \u043D\u0438\u043A\u043E\u0433\u0430 \u043D\u0435 \u0441\u0435 \u0447\u0443\u043F\u0438</p>\n<p>* \u0421\u043B\u0435\u0434 \u043E\u0431\u0440\u0430\u0431\u043E\u0442\u043A\u0430 \u043C\u043E\u0436\u0435 \u0434\u0430 \u0438\u0437\u0433\u043B\u0435\u0436\u0434\u0430 \u043C\u043D\u043E\u0433\u043E \u0434\u043E\u0431\u0440\u0435</p>\n\n<h2>\u041F\u043E\u0434\u0434\u0440\u044A\u0436\u043A\u0430 \u0432 <em>Ruby</em></h2>\n\n<p>\u0412 <strong>Ruby</strong> \u0438\u043C\u0430 \u043C\u043D\u043E\u0436\u0435\u0441\u0442\u0432\u043E Gem-\u043E\u0432\u0435, \u043A\u043E\u0438\u0442\u043E \u043C\u043E\u0433\u0430\u0442 \u0434\u0430 \u0432\u0438 \u043F\u043E\u043C\u043E\u0433\u043D\u0430\u0442 \u0437\u0430 \u0434\u0430 \u043F\u0440\u0435\u0445\u0432\u044A\u0440\u043B\u044F\u0442\u0435 Markdown-\u0441\u044A\u0434\u044A\u0440\u0436\u0430\u043D\u0438\u0435 \u0432 HTML-\u0444\u043E\u0440\u043C\u0430\u0442.</p>\n<p>\u041A\u043E\u0434\u044A\u0442, \u043A\u043E\u0439\u0442\u043E \u0432\u0438\u0435 \u0441\u044A\u0437\u0434\u0430\u0432\u0430\u0442\u0435, \u0441\u044A\u0449\u043E \u043C\u043E\u0436\u0435 \u0434\u0430 \u0432\u044A\u0440\u0448\u0438 \u0442\u043E\u0432\u0430 \u0434\u043E \u0438\u0437\u0432\u0435\u0441\u0442\u043D\u0430 \u0441\u0442\u0435\u043F\u0435\u043D.</p>\n\n<p>\u041F\u0440\u0438\u043C\u0435\u0440 \u0437\u0430 \u0443\u043F\u043E\u0442\u0440\u0435\u0431\u0430 \u043D\u0430 \u0432\u0430\u0448\u0438\u044F \u043A\u043E\u0434:</p>\n\n<p># \u041C\u043D\u043E\u0433\u043E \u043F\u0440\u043E\u0441\u0442\u043E</p>\n<p>formatter = Formatter.new &quot;## My Markdown&quot;</p>\n<p>puts formatter.tohtml</p>"
       
       (compared using ==)
       
       Diff:
       @@ -4,9 +4,9 @@
        <h2><em>Философия</em> на <a href="http://daringfireball.net/projects/markdown/syntax#philosophy">Markdown</a></h2>
        
        <p>Кратък цитат относно философията на Markdown:</p>
       -<blockquote><p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>
       -
       -<p>Readability, however, is emphasized above all else. A Markdown-formatted document should be publishable as-is, as plain text, without looking like it’s been marked up with tags or formatting instructions.</p></blockquote>
       +<p><p>&gt;</p>Markdown is intended to be as easy-to-read and easy-to-write as is feasible.</p>
       +&gt; 
       +<p>&gt; Readability, however, is emphasized above all else. A Markdown-formatted document should be publishable as-is, as plain text, without looking like it’s been marked up with tags or formatting instructions.</p>
        <p>Повече информация може да намерите на <a href="http://daringfireball.net/projects/markdown">сайта на <strong>Markdown</strong></a>.</p>
        
        <h2>Предимства</h2>
       
       
       @@ -14,20 +14,18 @@
        <p>Създаването на съдържание във формата Markdown има множество предимства.</p>
        
        <p>Ето някои от тях:</p>
       -<ul>
       -  <li>Лесно четим в <em>суров</em> вид</li>
       -  <li>Без &quot;скрити&quot; форматиращи тагове — форматирането ви никога не се чупи</li>
       -  <li>След обработка може да изглежда много добре</li>
       -</ul>
       +<p>* Лесно четим в <em>суров</em> вид</p>
       +<p>* Без &quot;скрити&quot; форматиращи тагове — форматирането ви никога не се чупи</p>
       +<p>* След обработка може да изглежда много добре</p>
        
        <h2>Поддръжка в <em>Ruby</em></h2>
        
       -<p>В <strong>Ruby</strong> има множество Gem-ове, които могат да ви помогнат за да прехвърляте Markdown-съдържание в HTML-формат.
       -Кодът, който вие създавате, също може да върши това до известна степен.</p>
       +<p>В <strong>Ruby</strong> има множество Gem-ове, които могат да ви помогнат за да прехвърляте Markdown-съдържание в HTML-формат.</p>
       +<p>Кодът, който вие създавате, също може да върши това до известна степен.</p>
        
        <p>Пример за употреба на вашия код:</p>
        
       -<pre><code># Много просто
       -formatter = Formatter.new &quot;## My Markdown&quot;
       -puts formatter.to_html</code></pre>
       +<p># Много просто</p>
       +<p>formatter = Formatter.new &quot;## My Markdown&quot;</p>
       +<p>puts formatter.tohtml</p>
     # /tmp/d20111129-16859-1ig21z3/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1ig21z3/spec.rb:655: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.62976 seconds
57 examples, 32 failures

Failed examples:

rspec /tmp/d20111129-16859-1ig21z3/spec.rb:28 # Formatter paragraphs renders multiline paragraps
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:99 # Formatter headers renders tricky ones
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:123 # Formatter code blocks renders simple blocks
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:127 # Formatter code blocks renders multiline blocks with empty lines
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:143 # Formatter code blocks renders multiple ones
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:159 # Formatter code blocks escapes special entities
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:163 # Formatter code blocks renders properly a longer example with tabs and Unicode
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:189 # Formatter code blocks renders properly with mixed content
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:219 # Formatter blockquotes renders simple ones
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:223 # Formatter blockquotes renders multiline ones
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:239 # Formatter blockquotes renders multiple ones
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:255 # Formatter blockquotes renders multiline ones with multiple paragraphs
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:271 # Formatter blockquotes escapes special entities
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:285 # Formatter links allows multiple links on a single line
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:298 # Formatter links does not render them in code blocks
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:315 # Formatter lists renders simple unordered lists
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:333 # Formatter lists renders simple ordered lists
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:351 # Formatter lists renders lists with a single item
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:377 # Formatter lists does not choke on malformed lists
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:397 # Formatter lists escapes special entities in the list elements
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:413 # Formatter lists allows links in list elements
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:450 # Formatter bold and italic text rendering works in blockquotes
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:458 # Formatter bold and italic text rendering does not render in code blocks
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:468 # Formatter bold and italic text rendering works in list elements
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:479 # Formatter bold and italic text rendering works in links in list elements
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:495 # Formatter bold and italic text rendering does not allow parial overlapping
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:521 # Formatter special entities escapes them in code blocks
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:527 # Formatter special entities escapes them in blockquotes
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:541 # Formatter whitespace removes excess leading and trailing whitespace
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:550 # Formatter whitespace ignores leading and trailing whitespace of lines whenever possible
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:558 # Formatter whitespace does not touch trailing whitespace in code blocks
rspec /tmp/d20111129-16859-1ig21z3/spec.rb:586 # Formatter mixed, complex input renders properly

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

Мартин обнови решението на 23.11.2011 22:39 (преди около 13 години)

+class Regex
+ HEADER = /^(\#{1,4})\s(\S.+)$/
+ BOLD = /(\*\*)(.+?)(\*\*)/
+ REPLACE_BOLD = /\*\*/
+ ITALIC = /(_)(.+?)(_)/
+ REPLACE_ITALIC = /_/
+ URL = /\[(.+)\]\((.+)\)/
+ OL_UNIT = /^(\d\.\s)(.+)$/
+ REPLACE_OL_UNIT = /\d\.\s/
+ WRAP_OL_UNIT = /<li>.+<\/li>/
+end
+
+class Pattern
+ attr_reader :pattern
+ def initialize(pattern)
+ @pattern = pattern
+ end
+end
+
+class Matcher
+ def initialize(pattern)
+ @pattern = pattern
+ end
+
+ def decorate(string, opening_tag, closing_tag)
+ copy = String.new string
+ scan_array = string.scan(@pattern.pattern)
+ scan_array.each do |match|
+ if should_decorate(match)
+ copy.sub!(scan_to_s(match),opening_tag + scan_to_s(match).strip + closing_tag)
+ end
+ end
+ copy
+ end
+
+ def replace_all(string,replacement)
+ copy = String.new string
+ copy.gsub!(@pattern.pattern,replacement)
+ copy
+ end
+
+ def match(text)
+ text.match @pattern.pattern
+ end
+
+ private
+ def should_decorate(line)
+ scanned_line = scan_to_s(line)
+ result = !scanned_line.match(/<h\d>.+/) && !scanned_line.match(/<ol>/)
+ result = result && !scanned_line.match(/<\/ol>/) && !scanned_line.match(/<li>/)
+ result = result && !scanned_line.match(/<\/li>/) && !scanned_line.match(/<ul>/)
+ result = result && !scanned_line.match(/<\/ul>/)
+ result
+ end
+
+ def scan_to_s(scan_array)
+ if scan_array.kind_of? String
+ return scan_array
+ else
+ result = String.new
+ end
+ scan_array.each do |match|
+ if match
+ result += match
+ end
+ end
+ result.end_with?("\n") ? result.chop! : result
+ end
+
+end
+class MarkupParser
+ def initialize(text)
+ copy = String.new text
+ @result = String.new
+ for line in copy.each_line
+ @result += parse_line(line)
+ end
+ @result = parse_ol(@result)
+ @result = parse_paragraphs(@result)
+ if @result.end_with?("\n")
+ @result.chop!
+ end
+ end
+
+ def parse_line(line)
+ converted_line = escape_special(line)
+ converted_line = parse_headers(converted_line)
+ converted_line = parse_url(converted_line)
+ converted_line = parse_text_weight(converted_line)
+ converted_line = parse_italic(converted_line)
+ end
+
+ def parse_paragraphs(text)
+ paragraphs_pattern = Pattern.new /(^.+$)|((.+\n)+(.+)?)/
+ paragraphs_matcher = Matcher.new paragraphs_pattern
+ paragraphs_matcher.decorate(text,"<p>","</p>")
+ end
+
+ def parse_ol(text)
+ ol_pattern = Pattern.new Regex::OL_UNIT
+ ol_matcher = Matcher.new ol_pattern
+ result = ol_matcher.decorate(text," <li>","</li>")
+ ol_replace_pattern = Pattern.new Regex::REPLACE_OL_UNIT
+ ol_replace_matcher = Matcher.new ol_replace_pattern
+ ol_replace_matcher.replace_all(result,"")
+ end
+
+ def parse_headers(line)
+ result = String.new
+ if line.match Regex::HEADER
+ h_type = $1.length.to_s
+ result = line.sub(Regex::HEADER, "<h" + h_type + ">" + $2 + "</h" + h_type + ">")
+ else
+ result += line
+ end
+ result
+ end
+
+ def escape_special(line)
+ result = String.new
+ replace_hash = { /&/ => "&amp;", /</ => "&lt;", />/ => "&gt;", /"/ => "&quot;" }
+ replace_hash.each do |pattern, repl|
+ if line.match pattern
+ line.gsub!(pattern,repl)
+ end
+ result = line
+ end
+ result
+ end
+
+ def parse_text_weight(line)
+ bold_pattern = Pattern.new Regex::BOLD
+ bold_matcher = Matcher.new bold_pattern
+ res = bold_matcher.decorate(line,"<strong>","</strong>")
+ bold_replace_pattern = Pattern.new Regex::REPLACE_BOLD
+ bold_replace_matcher = Matcher.new bold_replace_pattern
+ bold_replace_matcher.replace_all(res,"")
+ end
+
+ def parse_italic(line)
+ italic_pattern = Pattern.new Regex::ITALIC
+ italic_matcher = Matcher.new italic_pattern
+ res = italic_matcher.decorate(line,"<em>","</em>")
+ italic_replace_pattern = Pattern.new Regex::REPLACE_ITALIC
+ italic_replace_matcher = Matcher.new italic_replace_pattern
+ italic_replace_matcher.replace_all(res,"")
+ end
+
+ def parse_url(line)
+ result = String.new
+ if line.match Regex::URL
+ result = line.sub(Regex::URL, '<a href="' + $2 + '">' + $1 + "</a>")
+ else
+ result = line
+ end
+ result
+ end
+
+ def html
+ @result
+ end
+end
+class Formatter
+ def initialize(text)
+ @text = text
+ markup_parser = MarkupParser.new(text)
+ @text_to_html = markup_parser.html
+ end
+
+ def inspect
+ @text
+ end
+
+ def to_html
+ @text_to_html
+ end
+
+ def to_s
+ @text_to_html
+ end
+end