2 require 'syntax/convertors/html'
3 RUBY2HTML = Syntax::Convertors::HTML.for_syntax "ruby"
7 # ruby/html content. Initialize with the full
8 # <ruby>...</ruby> string
9 class RubyHtml < String
10 def initialize(content)
11 @content = remove_ruby_tags(content)
15 def to_s; @content.to_s; end
19 '<pre class="ruby"><code>' + RUBY2HTML.convert(self.content.to_s, false) + '</code></pre>'
23 "<notextile>" + self.to_html + "</notextile>"
27 def remove_ruby_tags(content_with_tags)
28 content_with_tags.gsub!(/<ruby>\s*/n, "")
29 content_with_tags.gsub!(/<\/ruby>/, "")
33 # ruby/html content. Initialize with
34 # <ruby file="..." /> or <ruby file="..."/>
35 class RubyHtmlFile < RubyHtml
36 def initialize(content)
37 @content = find_file_contents(remove_ruby_tag(content))
41 def remove_ruby_tag(content_with_tag)
42 content_with_tag.gsub(/<ruby\sfile\=\"(.*?)\"\s*\/>/, '\1')
45 def find_file_contents(filename)
47 if !File.exists?(filename)
48 if filename[0...1] == "~"
49 filename = File.expand_path(filename)
51 # points to spec/doc/ with an absolute path
52 # notice the extra slash at the end. This is there because
53 # the docs, as they stand now assume the added slash
54 # the added / *probably* should come out later,
55 # depending on what David & Aslak think, since they are
56 # the ones generating the docs
57 filename = File.expand_path(File.dirname(__FILE__) + "/../#{filename}")
62 raise "Given file <#{filename}> does not exist"
69 class RSpecContent < String
70 # Will parse the content for <ruby>...</ruby> html tags and
71 # <ruby file="..." />. Note that all other content will
72 # be assumed to be textile.
73 def initialize(content)
74 @original_content = content
75 @content = parse_to_redcloth_content(content)
78 attr_reader :original_content
80 alias :to_redcloth :content
83 redcloth_to_html(@content)
87 alias :inspect :content
90 #once you start some *real* html, can't provide redcloth or
91 # ruby tags inside an <tag>...</tag> entity.
92 # the content parser does not allow <ruby file='' />, only
93 # <ruby file="">. please modify this at your will
94 def parse_to_redcloth_content(content)
95 return "" if content.nil? || content.empty?
97 pre_match, redcloth_content, post_match = match_content(content)
99 parse_to_redcloth_content(pre_match) +
101 parse_to_redcloth_content(post_match)
104 def match_content(content)
105 if real_content = content.match(/<ruby>(.|\n)*?<\/ruby>/)
106 redcloth_content = RubyHtml.new(real_content[0]).to_redcloth
107 elsif real_content = content.match(/<ruby file\=\".+?\"\s*\/>/)
108 redcloth_content = RubyHtmlFile.new(real_content[0]).to_redcloth
109 elsif invalid_content = content.match(/<ruby.*>/)
110 raise "Invalid Ruby HTML tag. The Ruby Html tag must be declared in one of " +
111 "the two following ways: \n" +
112 " 1. <ruby>...inline_ruby...</ruby>\n" +
113 " 2. <ruby filename=\"filename\" />\n" +
114 "But it was declared as #{invalid_content[0]}\n"
116 return [nil, content, nil]
119 return [real_content.pre_match, redcloth_content, real_content.post_match]
122 def redcloth_to_html(content)
123 return "" if content.nil? || content.empty?
125 RedCloth.new( content ).to_html
126 rescue Exception => e
127 raise "Error converting Textile text to HTML: #{e.message}"