Решение на Пета задача от Деян Камбуров

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

Към профила на Деян Камбуров

Резултати

  • 5 точки от тестове
  • 0 бонус точки
  • 5 точки общо
  • 38 успешни тест(а)
  • 19 неуспешни тест(а)

Код

# encoding: ISO-8859-1
#използвам и този encoding и в тестовете иначе ми дава грешка
class Formatter
def initialize(unformatted_text)
@unformatted_text = unformatted_text
end
def to_html
begin_formating
create_headers_and_links
blockquotes
lists
italic_and_bold
@formatted_text = Code.scan(@formatted_text)
@formatted_text = Paragraph.ending(@formatted_text)
end
def inspect
@unformatted_text
end
alias to_s to_html
def begin_formating
@formatted_text = ClearWhitespace.from(@unformatted_text)
@formatted_text = ClearWhitespace.emptylines(@unformatted_text)
@formatted_text = SpecialSymbols.convert(@formatted_text)
@formatted_text = Paragraph.begining(@formatted_text)
end
def create_headers_and_links
@formatted_text = Headers.format(@formatted_text)
@formatted_text = Links.scan_for_links(@formatted_text)
end
def blockquotes
@formatted_text = Blockquotes.scan(@formatted_text)
@formatted_text = Blockquotes.fix_paragraph(@formatted_text)
end
def lists
@formatted_text = OrderedList.format(@formatted_text)
@formatted_text = UnorderedList.format(@formatted_text)
end
def italic_and_bold
@formatted_text = Italic.format(@formatted_text)
@formatted_text = Bold.format(@formatted_text)
end
end
class Paragraph
def self.begining(txt)
result = txt.gsub(/\A[^(>|*|\d|\s|\#]/) {|s| "<p>" + s}
result = result.gsub(/\A\*\*/) {|s| "<p>" + s}
end
def self.ending(txt)
match = /<\/(.*)>\Z/.match(txt)
if match.nil?
txt << "</p>"
else
txt << "</p>" unless match[1] =~ /blockquote|pre|ol|ul|h\d/
end
txt.to_s
end
end
class ClearWhitespace
def self.from(txt)
txt.gsub(/(^ {1,3}\S|(\s*)$)/) {|s| s.strip}
end
def self.emptylines(txt)
result = txt.sub(/\A(\n)*/, "")
result = result.sub(/(\n)*\Z/, "")
result
end
end
class OrderedList
def self.format(txt)
result = txt.gsub(/^[\d]\.\s(.*)/) {|s| " <li>" + s.gsub(/^\d\.\s/, "") + "</li>"}
result.gsub(/( <li>(.*)<\/li>\n?)+/) {|s| "<ol>\n" + s + "\n</ol>"}
end
end
class Italic
def self.format(txt)
txt.gsub(/(\b_(.*?)_\b)/) {|s| "<em>" + s.gsub(/_/, "") + "</em>"}
end
end
class Bold
def self.format(txt)
txt.gsub(/\*\*(.*?)\*\*/) {|s| "<strong>" + s.gsub(/\*\*/, "") + "</strong>"}
end
end
class UnorderedList
def self.format(txt)
result = txt.gsub(/^[*]\s(.*)/) {|s| " <li>" + s + "</li>"}
result = result.gsub(/( <li>[*]\s(.*)<\/li>\n?)+/) {|s| "<ul>\n" + s + "\n</ul>"}
result.gsub(/<li>[*]\s(.*)<\/li>/) {|s| s.gsub(/[*]\s/, "")}
end
end
class Blockquotes#fix
def self.scan(txt)
txt.gsub(/(^[">"](.*)\n?)+/) {|s| "<blockquote><p>" + self.format(s)}
end
def self.format(block)
if(block.end_with? "\n")
block.gsub(/^[">"]([ \t\r\f]*)/, "").insert(-2, "</p></blockquote>")
else
block.gsub(/^[">"]([ \t\r\f]*)/, "").insert(-1, "</p></blockquote>")
end
end
def self.fix_paragraph(block)
block.gsub(/\S\n\n+\S/) {|s| s[0] + "</p>" + s[1] + s[2] + "<p>" + s[3]}
end
end
class Code
def self.scan(txt)
txt.gsub(/(^( {4})(.*)\n?)+/) {|s| "<pre><code>" + self.format(s)}
end
def self.format(block)
if(block.end_with? "\n")
block.gsub(/^( {4})/, "") + "</code></pre>"
else
block.gsub(/^( {4})/, "") + "</code></pre>"
end
end
end
class SpecialSymbols
def self.amp(txt)
txt.gsub(/&/, "&amp;")
end
def self.quot(txt)
txt.gsub(/"/, "&quot;")
end
def self.lt(txt)
txt.gsub(/</, "&lt;")
end
def self.gt(txt)
txt.gsub(/(?<=^\n)>/, "&gt;")
end
def self.convert(txt)
converted_txt = self.amp(txt)
converted_txt = self.quot(converted_txt)
converted_txt = self.lt(converted_txt)
converted_txt = self.gt(converted_txt)
end
end
class Links
def self.scan_for_links(txt)
txt.gsub(/\[(.*)\]\((.*)\)/) {|s| self.format(s)}
end
def self.format(link)
"<a href=\""+self.address(link)+"\">"+self.name(link)+"</a>"
end
def self.name(link)
/\[(.*)\]\((.*)\)/.match(link)[1]
end
def self.address(link)
/\[(.*)\]\((.*)\)/.match(link)[2]
end
end
class H1
def self.scan_for_h1(txt)
txt.gsub(/^["#"](\s+)(.*)\n?/) {|s| self.format(s)}
end
def self.format(line)
if(line.end_with? "\n")
"<h1>"+remove_whitespace(line).insert(-2, "</h1>")
else
"<h1>"+remove_whitespace(line).insert(-1, "</h1>")
end
end
def self.remove_whitespace(string)
/^["#"](\s+)(.*)\n?/.match(string)[2]
end
end
class H2
def self.scan_for_h2(txt)
txt.gsub(/^["#"]{2}(\s+)(.*)\n?/) {|s| self.format(s)}
end
def self.format(line)
if(line.end_with? "\n")
"<h2>"+remove_whitespace(line).insert(-2, "</h2>")
else
"<h2>"+remove_whitespace(line).insert(-1, "</h2>")
end
end
def self.remove_whitespace(string)
/^["#"]{2}(\s+)(.*)\n?/.match(string)[2]
end
end
class H3
def self.scan_for_h3(txt)
txt.gsub(/^["#"]{3}(\s+)(.*)\n?/) {|s| self.format(s)}
end
def self.format(line)
if(line.end_with? "\n")
"<h3>"+remove_whitespace(line).insert(-2, "</h3>")
else
"<h3>"+remove_whitespace(line).insert(-1, "</h3>")
end
end
def self.remove_whitespace(string)
/^["#"]{3}(\s+)(.*)\n?/.match(string)[2]
end
end
class H4
def self.scan_for_h4(txt)
txt.gsub(/^["#"]{4}(\s+)(.*)\n?/) {|s| self.format(s)}
end
def self.format(line)
if(line.end_with? "\n")
"<h4>"+remove_whitespace(line).insert(-2, "</h4>")
else
"<h4>"+remove_whitespace(line).insert(-1, "</h4>")
end
end
def self.remove_whitespace(string)
/^["#"]{4}(\s+)(.*)\n?/.match(string)[2]
end
end
class Headers
def self.format(txt)
formatted_headers = H1.scan_for_h1(txt)
formatted_headers = H2.scan_for_h2(formatted_headers)
formatted_headers = H3.scan_for_h3(formatted_headers)
formatted_headers = H4.scan_for_h4(formatted_headers)
end
end

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

...FFF.FF...F.FF..F....F.FFF...F......F....F......FF....F

Failures:

  1) Formatter paragraphs does not render empty paragraphs
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: ""
            got: "</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:49: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 paragraphs breaks paragraphs with block-level elements
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>First line.</p>\n<h1>Header...</h1>\n<p>Third line.</p>\n\n<p>Separate line</p>"
            got: "<p>First line.\n<h1>Header..</h1>.Third line.</p>\n\n<p>Separate line</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,5 @@
       -<p>First line.</p>
       -<h1>Header...</h1>
       -<p>Third line.</p>
       +<p>First line.
       +<h1>Header..</h1>.Third line.</p>
        
        <p>Separate line</p>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:69: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 paragraphs escapes special entities
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>Cats &amp; Cash</p>\n\n<p>Cool, &lt;right&gt;?</p>"
            got: "<p>Cats &amp; Cash</p>\n\n<p>Cool, &lt;right>?</p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
        <p>Cats &amp; Cash</p>
        
       -<p>Cool, &lt;right&gt;?</p>
       +<p>Cool, &lt;right>?</p>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:85: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 headers renders tricky ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<h2>Leading wsp</h2>"
            got: "   ## Leading wsp</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `each'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  5) Formatter headers skips the malformed ones
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>#No whitespace!</p>"
            got: "#No whitespace!</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `each'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:114: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 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: "<pre><code>First code-block\n</code></pre>\n<pre><code>Second block of code</code></pre>"
       
       (compared using ==)
       
       Diff:
       @@ -1,4 +1,4 @@
       -<pre><code>First code-block</code></pre>
       -
       +<pre><code>First code-block
       +</code></pre>
        <pre><code>Second block of code</code></pre>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  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: "<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>\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>"
       
       (compared using ==)
       
       Diff:
       @@ -1,6 +1,6 @@
        <pre><code>// Пример за блок с код.
        // В него всеки ред, дори празните, е предшестван от точно четири интервала.
       -include &lt;stdio.h&gt;
       +include &lt;stdio.h>
        
        int main(int, char**) {
        	// Whitespace след четирите задължителни интервала в началото, се запазва винаги.
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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 heade</h1>r\nSome parahraphs here\n\n<pre><code>Some clean code\nWhich is also beautiful\nAnd maybe also compiles!</p>\n</code></pre>\n<p>More paragraphs there?</p>"
       
       (compared using ==)
       
       Diff:
       
       
       @@ -1,10 +1,9 @@
       -<h1>This is a header</h1>
       +<h1>This is a heade</h1>r
       +Some parahraphs here
        
       -<p>Some parahraphs here</p>
       -
        <pre><code>Some clean code
        Which is also beautiful
       -And maybe also compiles!</code></pre>
       -
       +And maybe also compiles!</p>
       +</code></pre>
        <p>More paragraphs there?</p>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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 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: "<blockquote><p>First quote.</p></blockquote></p>\n\n<p>&gt; Second quote.</p>"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,4 +1,4 @@
       -<blockquote><p>First quote.</p></blockquote>
       +<blockquote><p>First quote.</p></blockquote></p>
        
       -<blockquote><p>Second quote.</p></blockquote>
       +<p>&gt; Second quote.</p>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  10) 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-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  11) 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: "<pre><code>This one <a href=\"in-a-code-block\">is a link</a> - keep as-is.</code></pre>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  12) Formatter links escapes special entities in the link description
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>Also testing <a href=\"here\">special &amp; &quot;entities&quot; &lt;b&gt;</a>.</p>"
            got: "<p>Also testing <a href=\"here\">special &amp; &quot;entities&quot; &lt;b></a>.</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:304: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 links escapes special entities in the link URL
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>Or <a href=\"special &amp; &quot;entities&quot; &lt;b&gt;\">what if</a> are in the URL, eh?</p>"
            got: "<p>Or <a href=\"special &amp; &quot;entities&quot; &lt;b>\">what if</a> are in the URL, eh?</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:309: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 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: "1) \u041F\u044A\u0440\u0432\u043E.\n2 \u0412\u0442\u043E\u0440\u043E.\n3.\u0422\u0440\u0435\u0442\u043E\n<ol>\n  <li>\u0427\u0435\u0442\u0432\u044A\u0440\u0442\u043E</li>\n</ol>"
       
       (compared using ==)
       
       Diff:
       
       @@ -1,6 +1,6 @@
       -<p>1) Първо.
       +1) Първо.
        2 Второ.
       -3.Трето</p>
       +3.Трето
        <ol>
          <li>Четвърто</li>
        </ol>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  15) 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: "<pre><code>Some <em>more words</em> <em>to be</em> <strong>emphasized</strong>?</code></pre>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  16) 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-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  17) 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   Some txt   \n  \n  </p>"
       
       (compared using ==)
       
       Diff:
       @@ -1,2 +1,6 @@
       -<p>Some txt</p>
       +   
       +   
       +   Some txt   
       +  
       +  </p>
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `each'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  18) Formatter whitespace ignores leading and trailing whitespace of lines whenever possible
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>A line here</p>"
            got: "   A line here   </p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `each'
     # /tmp/d20111129-16859-xc0xi5/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-xc0xi5/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)>'

  19) 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</h1>\u0440\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<p><h2><em>\u0424\u0438\u043B\u043E\u0441\u043E\u0444\u0438\u044F</em> \u043D\u0430 <a href=\"http://daringfireball.net/projects/markdown/syntax#philosophy</h2>\">Markdown</a>\n\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:\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\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<p><h2>\u041F\u0440\u0435\u0434\u0438\u043C\u0441\u0442\u0432</h2>\u0430\n\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:\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</p></li>\n\n</ul>\n<p><h2>\u041F\u043E\u0434\u0434\u0440\u044A\u0436\u043A\u0430 \u0432 <em>Ruby</h2></em>\n\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:\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>"
       
       (compared using ==)
       
       Diff:
       
       
       
       
       
       
       
       @@ -1,31 +1,27 @@
       -<h1>Цялостен пример</h1>
       -<p>Тук ще демонстрираме накратко възможностите на нашия прост Markdown-преобразувател.</p>
       +<h1>Цялостен приме</h1>рТук ще демонстрираме накратко възможностите на нашия прост Markdown-преобразувател.</p>
        
       -<h2><em>Философия</em> на <a href="http://daringfireball.net/projects/markdown/syntax#philosophy">Markdown</a></h2>
       -
       -<p>Кратък цитат относно философията на Markdown:</p>
       +<p><h2><em>Философия</em> на <a href="http://daringfireball.net/projects/markdown/syntax#philosophy</h2>">Markdown</a>
       +Кратък цитат относно философията на Markdown:
        <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>Повече информация може да намерите на <a href="http://daringfireball.net/projects/markdown">сайта на <strong>Markdown</strong></a>.</p>
       +Повече информация може да намерите на <a href="http://daringfireball.net/projects/markdown">сайта на <strong>Markdown</strong></a>.</p>
        
       -<h2>Предимства</h2>
       +<p><h2>Предимств</h2>а
       +Създаването на съдържание във формата Markdown има множество предимства.</p>
        
       -<p>Създаването на съдържание във формата Markdown има множество предимства.</p>
       -
       -<p>Ето някои от тях:</p>
       +<p>Ето някои от тях:
        <ul>
          <li>Лесно четим в <em>суров</em> вид</li>
          <li>Без &quot;скрити&quot; форматиращи тагове — форматирането ви никога не се чупи</li>
       -  <li>След обработка може да изглежда много добре</li>
       -</ul>
       +  <li>След обработка може да изглежда много добре</p></li>
        
       -<h2>Поддръжка в <em>Ruby</em></h2>
       -
       -<p>В <strong>Ruby</strong> има множество Gem-ове, които могат да ви помогнат за да прехвърляте Markdown-съдържание в HTML-формат.
       +</ul>
       +<p><h2>Поддръжка в <em>Ruby</h2></em>
       +В <strong>Ruby</strong> има множество Gem-ове, които могат да ви помогнат за да прехвърляте Markdown-съдържание в HTML-формат.
        Кодът, който вие създавате, също може да върши това до известна степен.</p>
        
       -<p>Пример за употреба на вашия код:</p>
       +<p>Пример за употреба на вашия код:
        
        <pre><code># Много просто
        formatter = Formatter.new &quot;## My Markdown&quot;
     # /tmp/d20111129-16859-xc0xi5/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-xc0xi5/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.64882 seconds
57 examples, 19 failures

Failed examples:

rspec /tmp/d20111129-16859-xc0xi5/spec.rb:48 # Formatter paragraphs does not render empty paragraphs
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:52 # Formatter paragraphs breaks paragraphs with block-level elements
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:72 # Formatter paragraphs escapes special entities
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:99 # Formatter headers renders tricky ones
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:109 # Formatter headers skips the malformed ones
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:143 # Formatter code blocks renders multiple ones
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:163 # Formatter code blocks renders properly a longer example with tabs and Unicode
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:189 # Formatter code blocks renders properly with mixed content
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:239 # Formatter blockquotes renders multiple ones
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:285 # Formatter links allows multiple links on a single line
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:298 # Formatter links does not render them in code blocks
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:303 # Formatter links escapes special entities in the link description
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:308 # Formatter links escapes special entities in the link URL
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:377 # Formatter lists does not choke on malformed lists
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:458 # Formatter bold and italic text rendering does not render in code blocks
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:495 # Formatter bold and italic text rendering does not allow parial overlapping
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:541 # Formatter whitespace removes excess leading and trailing whitespace
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:550 # Formatter whitespace ignores leading and trailing whitespace of lines whenever possible
rspec /tmp/d20111129-16859-xc0xi5/spec.rb:586 # Formatter mixed, complex input renders properly

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

Деян обнови решението на 23.11.2011 23:55 (преди почти 13 години)

+# encoding: ISO-8859-1
+#използвам и този encoding и в тестовете иначе ми дава грешка
+class Formatter
+
+ def initialize(unformatted_text)
+ @unformatted_text = unformatted_text
+ end
+
+ def to_html
+ begin_formating
+ create_headers_and_links
+ blockquotes
+ lists
+ italic_and_bold
+ @formatted_text = Code.scan(@formatted_text)
+ @formatted_text = Paragraph.ending(@formatted_text)
+ end
+
+ def inspect
+ @unformatted_text
+ end
+
+ alias to_s to_html
+
+ def begin_formating
+ @formatted_text = ClearWhitespace.from(@unformatted_text)
+ @formatted_text = ClearWhitespace.emptylines(@unformatted_text)
+ @formatted_text = SpecialSymbols.convert(@formatted_text)
+ @formatted_text = Paragraph.begining(@formatted_text)
+ end
+
+ def create_headers_and_links
+ @formatted_text = Headers.format(@formatted_text)
+ @formatted_text = Links.scan_for_links(@formatted_text)
+ end
+
+ def blockquotes
+ @formatted_text = Blockquotes.scan(@formatted_text)
+ @formatted_text = Blockquotes.fix_paragraph(@formatted_text)
+ end
+
+ def lists
+ @formatted_text = OrderedList.format(@formatted_text)
+ @formatted_text = UnorderedList.format(@formatted_text)
+ end
+
+ def italic_and_bold
+ @formatted_text = Italic.format(@formatted_text)
+ @formatted_text = Bold.format(@formatted_text)
+ end
+end
+
+
+class Paragraph
+
+ def self.begining(txt)
+ result = txt.gsub(/\A[^(>|*|\d|\s|\#]/) {|s| "<p>" + s}
+ result = result.gsub(/\A\*\*/) {|s| "<p>" + s}
+ end
+
+
+ def self.ending(txt)
+ match = /<\/(.*)>\Z/.match(txt)
+ if match.nil?
+ txt << "</p>"
+ else
+ txt << "</p>" unless match[1] =~ /blockquote|pre|ol|ul|h\d/
+ end
+ txt.to_s
+ end
+
+end
+
+class ClearWhitespace
+
+ def self.from(txt)
+ txt.gsub(/(^ {1,3}\S|(\s*)$)/) {|s| s.strip}
+ end
+
+ def self.emptylines(txt)
+ result = txt.sub(/\A(\n)*/, "")
+ result = result.sub(/(\n)*\Z/, "")
+ result
+ end
+end
+
+class OrderedList
+
+ def self.format(txt)
+ result = txt.gsub(/^[\d]\.\s(.*)/) {|s| " <li>" + s.gsub(/^\d\.\s/, "") + "</li>"}
+ result.gsub(/( <li>(.*)<\/li>\n?)+/) {|s| "<ol>\n" + s + "\n</ol>"}
+ end
+
+end
+
+class Italic
+
+ def self.format(txt)
+ txt.gsub(/(\b_(.*?)_\b)/) {|s| "<em>" + s.gsub(/_/, "") + "</em>"}
+ end
+
+end
+
+class Bold
+
+ def self.format(txt)
+ txt.gsub(/\*\*(.*?)\*\*/) {|s| "<strong>" + s.gsub(/\*\*/, "") + "</strong>"}
+ end
+
+end
+
+class UnorderedList
+
+ def self.format(txt)
+ result = txt.gsub(/^[*]\s(.*)/) {|s| " <li>" + s + "</li>"}
+ result = result.gsub(/( <li>[*]\s(.*)<\/li>\n?)+/) {|s| "<ul>\n" + s + "\n</ul>"}
+ result.gsub(/<li>[*]\s(.*)<\/li>/) {|s| s.gsub(/[*]\s/, "")}
+ end
+
+end
+class Blockquotes#fix
+
+ def self.scan(txt)
+ txt.gsub(/(^[">"](.*)\n?)+/) {|s| "<blockquote><p>" + self.format(s)}
+ end
+
+ def self.format(block)
+ if(block.end_with? "\n")
+ block.gsub(/^[">"]([ \t\r\f]*)/, "").insert(-2, "</p></blockquote>")
+ else
+ block.gsub(/^[">"]([ \t\r\f]*)/, "").insert(-1, "</p></blockquote>")
+ end
+ end
+
+ def self.fix_paragraph(block)
+ block.gsub(/\S\n\n+\S/) {|s| s[0] + "</p>" + s[1] + s[2] + "<p>" + s[3]}
+ end
+
+end
+
+class Code
+
+ def self.scan(txt)
+ txt.gsub(/(^( {4})(.*)\n?)+/) {|s| "<pre><code>" + self.format(s)}
+ end
+
+ def self.format(block)
+ if(block.end_with? "\n")
+ block.gsub(/^( {4})/, "") + "</code></pre>"
+ else
+ block.gsub(/^( {4})/, "") + "</code></pre>"
+ end
+
+ end
+
+end
+
+class SpecialSymbols
+
+ def self.amp(txt)
+ txt.gsub(/&/, "&amp;")
+ end
+
+ def self.quot(txt)
+ txt.gsub(/"/, "&quot;")
+ end
+
+ def self.lt(txt)
+ txt.gsub(/</, "&lt;")
+ end
+
+ def self.gt(txt)
+ txt.gsub(/(?<=^\n)>/, "&gt;")
+ end
+
+ def self.convert(txt)
+ converted_txt = self.amp(txt)
+ converted_txt = self.quot(converted_txt)
+ converted_txt = self.lt(converted_txt)
+ converted_txt = self.gt(converted_txt)
+ end
+end
+
+class Links
+ def self.scan_for_links(txt)
+
+ txt.gsub(/\[(.*)\]\((.*)\)/) {|s| self.format(s)}
+ end
+
+ def self.format(link)
+ "<a href=\""+self.address(link)+"\">"+self.name(link)+"</a>"
+ end
+
+ def self.name(link)
+ /\[(.*)\]\((.*)\)/.match(link)[1]
+ end
+
+ def self.address(link)
+ /\[(.*)\]\((.*)\)/.match(link)[2]
+ end
+end
+
+class H1
+ def self.scan_for_h1(txt)
+ txt.gsub(/^["#"](\s+)(.*)\n?/) {|s| self.format(s)}
+ end
+
+ def self.format(line)
+ if(line.end_with? "\n")
+ "<h1>"+remove_whitespace(line).insert(-2, "</h1>")
+ else
+ "<h1>"+remove_whitespace(line).insert(-1, "</h1>")
+ end
+ end
+
+ def self.remove_whitespace(string)
+ /^["#"](\s+)(.*)\n?/.match(string)[2]
+ end
+
+end
+
+class H2
+ def self.scan_for_h2(txt)
+ txt.gsub(/^["#"]{2}(\s+)(.*)\n?/) {|s| self.format(s)}
+ end
+
+ def self.format(line)
+ if(line.end_with? "\n")
+ "<h2>"+remove_whitespace(line).insert(-2, "</h2>")
+ else
+ "<h2>"+remove_whitespace(line).insert(-1, "</h2>")
+ end
+ end
+
+ def self.remove_whitespace(string)
+ /^["#"]{2}(\s+)(.*)\n?/.match(string)[2]
+ end
+
+end
+
+class H3
+ def self.scan_for_h3(txt)
+ txt.gsub(/^["#"]{3}(\s+)(.*)\n?/) {|s| self.format(s)}
+ end
+
+ def self.format(line)
+ if(line.end_with? "\n")
+ "<h3>"+remove_whitespace(line).insert(-2, "</h3>")
+ else
+ "<h3>"+remove_whitespace(line).insert(-1, "</h3>")
+ end
+ end
+
+ def self.remove_whitespace(string)
+ /^["#"]{3}(\s+)(.*)\n?/.match(string)[2]
+ end
+
+end
+
+class H4
+ def self.scan_for_h4(txt)
+ txt.gsub(/^["#"]{4}(\s+)(.*)\n?/) {|s| self.format(s)}
+ end
+
+ def self.format(line)
+ if(line.end_with? "\n")
+ "<h4>"+remove_whitespace(line).insert(-2, "</h4>")
+ else
+ "<h4>"+remove_whitespace(line).insert(-1, "</h4>")
+ end
+ end
+
+ def self.remove_whitespace(string)
+ /^["#"]{4}(\s+)(.*)\n?/.match(string)[2]
+ end
+
+end
+
+class Headers
+
+ def self.format(txt)
+ formatted_headers = H1.scan_for_h1(txt)
+ formatted_headers = H2.scan_for_h2(formatted_headers)
+ formatted_headers = H3.scan_for_h3(formatted_headers)
+ formatted_headers = H4.scan_for_h4(formatted_headers)
+
+ end
+
+
+
+end