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

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

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

Резултати

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

Код

# encoding: utf-8
class Formatter
attr_reader :plain
def initialize(plain)
@plain = plain
@html = @plain.dup.rstrip()
end
def tags_compose
Header.compose(@html)
OrderedList.compose(@html)
UnOrderedList.compose(@html)
BlockQuote.compose(@html)
HyperLink.compose(@html)
end
def to_html
WhiteSpaceCleaner.clean(@html)
SpecialSymbols.compose(@html)
CodeBlock.compose(@html)
TagWrapper.wrap(EmAndStrong, @html, ['pre'])
tags_compose
TagWrapper.wrap(Paragraph, @html, ['h','pre','blockquote','ul','ol'])
TagCleaner.clean(@html)
paragraphs_in_blockquote
end
def paragraphs_in_blockquote
tag_order = []
@html.gsub!(/(?<=<blockquote>)(.+?)(?=<\/blockquote>$)/m) { |m| Paragraph.compose(m) }
TagCleaner.clean(@html)
@html
end
alias :to_s :to_html
def inspect
@plain
end
end
class CodeBlock
def self.compose(text)
text.gsub!(/^[ ]{4,}.*/) { |m| m.gsub!($&, "<pre><code>#{$&[4..-1]}</code></pre>") }
end
end
class BlockQuote
def self.compose(text)
text.gsub!(/^>[ ]+(.*)/) do |m|
m.gsub!($&, "<blockquote>#{$1.strip()}</blockquote>")
end
end
end
class Header
def self.compose(text)
text.gsub!(/^([#]{1,4})\s+(.+)/) do |m|
m.gsub!($&, "<h#{$1.size}>#{$2.strip()}</h#{$1.size}>")
end
end
end
class HyperLink
def self.compose(text)
text.gsub!(/\[(.+)\]\((.+)\)/) do |m|
m.gsub!($&, "<a href=\"#{$2}\">#{$1}</a>")
end
end
end
class OrderedList
def self.compose(text)
text.gsub!(/^\d\.\s+(.+)/) do |m|
m.gsub!($&, "<ol>\n <li>#{$1.strip()}</li>\n</ol>")
end
end
end
class UnOrderedList
def self.compose(text)
text.gsub!(/^\*\s+(.+)/) do |m|
m.gsub!($&, "<ul>\n <li>#{$1.strip()}</li>\n</ul>")
end
end
end
class Strong
def self.regex
/.*?(\*{2}(.+?)\*{2}).*/
end
def self.compose(text)
text.gsub!(self.regex) { |m| m.gsub!($1, "<strong>#{$2.strip()}</strong>") }
end
end
class Em
def self.regex
/_(.+?)_/
end
def self.compose(text)
text.gsub!(self.regex) { |m| m.gsub!($&, "<em>#{$1.strip()}</em>") }
end
end
class EmAndStrong
def self.compose(text)
Strong.compose(text)
Em.compose(text)
end
end
class SpecialSymbols
def self.compose(text)
text.gsub!("&","&amp;")
text.gsub!("<", "&lt;")
text.gsub!(/(.+)(>)/) { |m| m.gsub!($2, "&gt;") }
text.gsub!('"',"&quot;")
end
end
class TagCleaner
def self.clean(text)
2.times do # First for </pre><pre>, then for </code><code>
text.scan(/<\/([^<]+?)>$/).each do |m|
text.gsub!("</#{m.first}>\n<#{m.first}>","\n")
end
end
text.gsub!("</li>\n\n","</li>")
end
end
class Paragraph
def self.compose(text)
text.gsub!(/^[^\$\n].+/) { |m| m.gsub!(m, "<p>#{m.strip()}</p>") }
end
end
class Collapser
def self.extract_tags(text, tags)
@@tags_order = []
tags.each_with_index do | tag, idx |
tag_seq = []
text.gsub!(/<#{tag}.+?<\/#{tag}\d?>$/m) do |m|
tag_seq << m.dup
m.replace("$#{idx}")
end
@@tags_order[idx] = tag_seq
end
end
def self.put_tags_back(text, tags)
raise RuntimeError, "You must perform extract_tags first" if @@tags_order.empty?
tags.each_with_index do | tag, idx |
next if @@tags_order[idx].nil?
@@tags_order[idx].each { |m| text.sub!(/\$#{idx}/, m) }
#if tag == 'blockquote'
# m.gsub!(/<\/?blockquote>/,"")
# Paragraph.compose(m)
# m.replace("<blockquote>#{m}</blockquote>")
# end
end
end
end
class WhiteSpaceCleaner
def self.clean(text)
text.gsub!(/^[ \t]{,3}(?=[^ \t])/,"")
text.gsub!(/\A\n+/,"")
end
end
class TagWrapper
def self.wrap(class_type, text, tags)
Collapser.extract_tags(text, tags)
class_type.compose(text)
Collapser.put_tags_back(text, tags)
end
end

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

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

Failures:

  1) Formatter links allows multiple links on a single line
     Failure/Error: Formatter.new(plain).to_html.should eq formatted.strip
       
       expected: "<p>We have <a href=\"some-url\">a first</a> and <a href=\"another-url\">Second</a>.</p>"
            got: "<p>We have <a href=\"another-url\">a first](some-url) and [Second</a>.</p>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1mmn3xx/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1mmn3xx/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)>'

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

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

  4) 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: "<pre><code>Simple code blk</code></pre>"
       
       (compared using ==)
     # /tmp/d20111129-16859-1mmn3xx/spec.rb:660:in `expect_transformation'
     # /tmp/d20111129-16859-1mmn3xx/spec.rb:665:in `block in expect_transformations'
     # /tmp/d20111129-16859-1mmn3xx/spec.rb:664:in `each'
     # /tmp/d20111129-16859-1mmn3xx/spec.rb:664:in `expect_transformations'
     # /tmp/d20111129-16859-1mmn3xx/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)>'

Finished in 0.67787 seconds
57 examples, 4 failures

Failed examples:

rspec /tmp/d20111129-16859-1mmn3xx/spec.rb:285 # Formatter links allows multiple links on a single line
rspec /tmp/d20111129-16859-1mmn3xx/spec.rb:298 # Formatter links does not render them in code blocks
rspec /tmp/d20111129-16859-1mmn3xx/spec.rb:495 # Formatter bold and italic text rendering does not allow parial overlapping
rspec /tmp/d20111129-16859-1mmn3xx/spec.rb:558 # Formatter whitespace does not touch trailing whitespace in code blocks

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

Мартин обнови решението на 23.11.2011 22:49 (преди над 12 години)

+# encoding: utf-8
+class Formatter
+ attr_reader :plain
+
+ def initialize(plain)
+ @plain = plain
+ @html = @plain.dup.rstrip()
+ end
+
+ def tags_compose
+ Header.compose(@html)
+ OrderedList.compose(@html)
+ UnOrderedList.compose(@html)
+ BlockQuote.compose(@html)
+ HyperLink.compose(@html)
+ end
+
+ def to_html
+ WhiteSpaceCleaner.clean(@html)
+ SpecialSymbols.compose(@html)
+ CodeBlock.compose(@html)
+ TagWrapper.wrap(EmAndStrong, @html, ['pre'])
+ tags_compose
+ TagWrapper.wrap(Paragraph, @html, ['h','pre','blockquote','ul','ol'])
+ TagCleaner.clean(@html)
+ paragraphs_in_blockquote
+ end
+
+ def paragraphs_in_blockquote
+ tag_order = []
+ @html.gsub!(/(?<=<blockquote>)(.+?)(?=<\/blockquote>$)/m) { |m| Paragraph.compose(m) }
+ TagCleaner.clean(@html)
+ @html
+ end
+
+ alias :to_s :to_html
+
+ def inspect
+ @plain
+ end
+end
+
+ class CodeBlock
+ def self.compose(text)
+ text.gsub!(/^[ ]{4,}.*/) { |m| m.gsub!($&, "<pre><code>#{$&[4..-1]}</code></pre>") }
+ end
+ end
+
+ class BlockQuote
+ def self.compose(text)
+ text.gsub!(/^>[ ]+(.*)/) do |m|
+ m.gsub!($&, "<blockquote>#{$1.strip()}</blockquote>")
+ end
+ end
+ end
+
+ class Header
+ def self.compose(text)
+ text.gsub!(/^([#]{1,4})\s+(.+)/) do |m|
+ m.gsub!($&, "<h#{$1.size}>#{$2.strip()}</h#{$1.size}>")
+ end
+ end
+ end
+
+ class HyperLink
+ def self.compose(text)
+ text.gsub!(/\[(.+)\]\((.+)\)/) do |m|
+ m.gsub!($&, "<a href=\"#{$2}\">#{$1}</a>")
+ end
+ end
+ end
+
+ class OrderedList
+ def self.compose(text)
+ text.gsub!(/^\d\.\s+(.+)/) do |m|
+ m.gsub!($&, "<ol>\n <li>#{$1.strip()}</li>\n</ol>")
+ end
+ end
+ end
+
+ class UnOrderedList
+ def self.compose(text)
+ text.gsub!(/^\*\s+(.+)/) do |m|
+ m.gsub!($&, "<ul>\n <li>#{$1.strip()}</li>\n</ul>")
+ end
+ end
+ end
+
+ class Strong
+ def self.regex
+ /.*?(\*{2}(.+?)\*{2}).*/
+ end
+
+ def self.compose(text)
+ text.gsub!(self.regex) { |m| m.gsub!($1, "<strong>#{$2.strip()}</strong>") }
+ end
+ end
+
+ class Em
+ def self.regex
+ /_(.+?)_/
+ end
+
+ def self.compose(text)
+ text.gsub!(self.regex) { |m| m.gsub!($&, "<em>#{$1.strip()}</em>") }
+ end
+ end
+
+ class EmAndStrong
+ def self.compose(text)
+ Strong.compose(text)
+ Em.compose(text)
+ end
+ end
+
+ class SpecialSymbols
+ def self.compose(text)
+ text.gsub!("&","&amp;")
+ text.gsub!("<", "&lt;")
+ text.gsub!(/(.+)(>)/) { |m| m.gsub!($2, "&gt;") }
+ text.gsub!('"',"&quot;")
+ end
+ end
+
+ class TagCleaner
+ def self.clean(text)
+ 2.times do # First for </pre><pre>, then for </code><code>
+ text.scan(/<\/([^<]+?)>$/).each do |m|
+ text.gsub!("</#{m.first}>\n<#{m.first}>","\n")
+ end
+ end
+ text.gsub!("</li>\n\n","</li>")
+ end
+ end
+
+ class Paragraph
+ def self.compose(text)
+ text.gsub!(/^[^\$\n].+/) { |m| m.gsub!(m, "<p>#{m.strip()}</p>") }
+ end
+ end
+
+ class Collapser
+
+ def self.extract_tags(text, tags)
+ @@tags_order = []
+ tags.each_with_index do | tag, idx |
+ tag_seq = []
+ text.gsub!(/<#{tag}.+?<\/#{tag}\d?>$/m) do |m|
+ tag_seq << m.dup
+ m.replace("$#{idx}")
+ end
+ @@tags_order[idx] = tag_seq
+ end
+ end
+
+ def self.put_tags_back(text, tags)
+ raise RuntimeError, "You must perform extract_tags first" if @@tags_order.empty?
+ tags.each_with_index do | tag, idx |
+ next if @@tags_order[idx].nil?
+ @@tags_order[idx].each { |m| text.sub!(/\$#{idx}/, m) }
+ #if tag == 'blockquote'
+ # m.gsub!(/<\/?blockquote>/,"")
+ # Paragraph.compose(m)
+ # m.replace("<blockquote>#{m}</blockquote>")
+ # end
+ end
+ end
+ end
+
+ class WhiteSpaceCleaner
+ def self.clean(text)
+ text.gsub!(/^[ \t]{,3}(?=[^ \t])/,"")
+ text.gsub!(/\A\n+/,"")
+ end
+ end
+
+ class TagWrapper
+ def self.wrap(class_type, text, tags)
+ Collapser.extract_tags(text, tags)
+ class_type.compose(text)
+ Collapser.put_tags_back(text, tags)
+ end
+ end