summaryrefslogtreecommitdiff
path: root/ruby_2_2/lib/rdoc/markup/to_html.rb
diff options
context:
space:
mode:
Diffstat (limited to 'ruby_2_2/lib/rdoc/markup/to_html.rb')
-rw-r--r--ruby_2_2/lib/rdoc/markup/to_html.rb398
1 files changed, 398 insertions, 0 deletions
diff --git a/ruby_2_2/lib/rdoc/markup/to_html.rb b/ruby_2_2/lib/rdoc/markup/to_html.rb
new file mode 100644
index 0000000000..2b1216ef2a
--- /dev/null
+++ b/ruby_2_2/lib/rdoc/markup/to_html.rb
@@ -0,0 +1,398 @@
+require 'cgi'
+
+##
+# Outputs RDoc markup as HTML.
+
+class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
+
+ include RDoc::Text
+
+ # :section: Utilities
+
+ ##
+ # Maps RDoc::Markup::Parser::LIST_TOKENS types to HTML tags
+
+ LIST_TYPE_TO_HTML = {
+ :BULLET => ['<ul>', '</ul>'],
+ :LABEL => ['<dl class="rdoc-list label-list">', '</dl>'],
+ :LALPHA => ['<ol style="list-style-type: lower-alpha">', '</ol>'],
+ :NOTE => ['<dl class="rdoc-list note-list">', '</dl>'],
+ :NUMBER => ['<ol>', '</ol>'],
+ :UALPHA => ['<ol style="list-style-type: upper-alpha">', '</ol>'],
+ }
+
+ attr_reader :res # :nodoc:
+ attr_reader :in_list_entry # :nodoc:
+ attr_reader :list # :nodoc:
+
+ ##
+ # The RDoc::CodeObject HTML is being generated for. This is used to
+ # generate namespaced URI fragments
+
+ attr_accessor :code_object
+
+ ##
+ # Path to this document for relative links
+
+ attr_accessor :from_path
+
+ # :section:
+
+ ##
+ # Creates a new formatter that will output HTML
+
+ def initialize options, markup = nil
+ super
+
+ @code_object = nil
+ @from_path = ''
+ @in_list_entry = nil
+ @list = nil
+ @th = nil
+ @hard_break = "<br>\n"
+
+ # external links
+ @markup.add_special(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/,
+ :HYPERLINK)
+
+ add_special_RDOCLINK
+ add_special_TIDYLINK
+
+ init_tags
+ end
+
+ # :section: Special Handling
+ #
+ # These methods handle special markup added by RDoc::Markup#add_special.
+
+ def handle_RDOCLINK url # :nodoc:
+ case url
+ when /^rdoc-ref:/
+ $'
+ when /^rdoc-label:/
+ text = $'
+
+ text = case text
+ when /\Alabel-/ then $'
+ when /\Afootmark-/ then $'
+ when /\Afoottext-/ then $'
+ else text
+ end
+
+ gen_url url, text
+ when /^rdoc-image:/
+ "<img src=\"#{$'}\">"
+ else
+ url =~ /\Ardoc-[a-z]+:/
+
+ $'
+ end
+ end
+
+ ##
+ # +special+ is a <code><br></code>
+
+ def handle_special_HARD_BREAK special
+ '<br>'
+ end
+
+ ##
+ # +special+ is a potential link. The following schemes are handled:
+ #
+ # <tt>mailto:</tt>::
+ # Inserted as-is.
+ # <tt>http:</tt>::
+ # Links are checked to see if they reference an image. If so, that image
+ # gets inserted using an <tt><img></tt> tag. Otherwise a conventional
+ # <tt><a href></tt> is used.
+ # <tt>link:</tt>::
+ # Reference to a local file relative to the output directory.
+
+ def handle_special_HYPERLINK(special)
+ url = special.text
+
+ gen_url url, url
+ end
+
+ ##
+ # +special+ is an rdoc-schemed link that will be converted into a hyperlink.
+ #
+ # For the +rdoc-ref+ scheme the named reference will be returned without
+ # creating a link.
+ #
+ # For the +rdoc-label+ scheme the footnote and label prefixes are stripped
+ # when creating a link. All other contents will be linked verbatim.
+
+ def handle_special_RDOCLINK special
+ handle_RDOCLINK special.text
+ end
+
+ ##
+ # This +special+ is a link where the label is different from the URL
+ # <tt>label[url]</tt> or <tt>{long label}[url]</tt>
+
+ def handle_special_TIDYLINK(special)
+ text = special.text
+
+ return text unless
+ text =~ /^\{(.*)\}\[(.*?)\]$/ or text =~ /^(\S+)\[(.*?)\]$/
+
+ label = $1
+ url = $2
+
+ label = handle_RDOCLINK label if /^rdoc-image:/ =~ label
+
+ gen_url url, label
+ end
+
+ # :section: Visitor
+ #
+ # These methods implement the HTML visitor.
+
+ ##
+ # Prepares the visitor for HTML generation
+
+ def start_accepting
+ @res = []
+ @in_list_entry = []
+ @list = []
+ end
+
+ ##
+ # Returns the generated output
+
+ def end_accepting
+ @res.join
+ end
+
+ ##
+ # Adds +block_quote+ to the output
+
+ def accept_block_quote block_quote
+ @res << "\n<blockquote>"
+
+ block_quote.parts.each do |part|
+ part.accept self
+ end
+
+ @res << "</blockquote>\n"
+ end
+
+ ##
+ # Adds +paragraph+ to the output
+
+ def accept_paragraph paragraph
+ @res << "\n<p>"
+ text = paragraph.text @hard_break
+ text = text.gsub(/\r?\n/, ' ')
+ @res << wrap(to_html(text))
+ @res << "</p>\n"
+ end
+
+ ##
+ # Adds +verbatim+ to the output
+
+ def accept_verbatim verbatim
+ text = verbatim.text.rstrip
+
+ klass = nil
+
+ content = if verbatim.ruby? or parseable? text then
+ begin
+ tokens = RDoc::RubyLex.tokenize text, @options
+ klass = ' class="ruby"'
+
+ RDoc::TokenStream.to_html tokens
+ rescue RDoc::RubyLex::Error
+ CGI.escapeHTML text
+ end
+ else
+ CGI.escapeHTML text
+ end
+
+ if @options.pipe then
+ @res << "\n<pre><code>#{CGI.escapeHTML text}</code></pre>\n"
+ else
+ @res << "\n<pre#{klass}>#{content}</pre>\n"
+ end
+ end
+
+ ##
+ # Adds +rule+ to the output
+
+ def accept_rule rule
+ @res << "<hr>\n"
+ end
+
+ ##
+ # Prepares the visitor for consuming +list+
+
+ def accept_list_start(list)
+ @list << list.type
+ @res << html_list_name(list.type, true)
+ @in_list_entry.push false
+ end
+
+ ##
+ # Finishes consumption of +list+
+
+ def accept_list_end(list)
+ @list.pop
+ if tag = @in_list_entry.pop
+ @res << tag
+ end
+ @res << html_list_name(list.type, false) << "\n"
+ end
+
+ ##
+ # Prepares the visitor for consuming +list_item+
+
+ def accept_list_item_start(list_item)
+ if tag = @in_list_entry.last
+ @res << tag
+ end
+
+ @res << list_item_start(list_item, @list.last)
+ end
+
+ ##
+ # Finishes consumption of +list_item+
+
+ def accept_list_item_end(list_item)
+ @in_list_entry[-1] = list_end_for(@list.last)
+ end
+
+ ##
+ # Adds +blank_line+ to the output
+
+ def accept_blank_line(blank_line)
+ # @res << annotate("<p />") << "\n"
+ end
+
+ ##
+ # Adds +heading+ to the output. The headings greater than 6 are trimmed to
+ # level 6.
+
+ def accept_heading heading
+ level = [6, heading.level].min
+
+ label = heading.label @code_object
+
+ @res << if @options.output_decoration
+ "\n<h#{level} id=\"#{label}\">"
+ else
+ "\n<h#{level}>"
+ end
+ @res << to_html(heading.text)
+ unless @options.pipe then
+ @res << "<span><a href=\"##{label}\">&para;</a>"
+ @res << " <a href=\"#top\">&uarr;</a></span>"
+ end
+ @res << "</h#{level}>\n"
+ end
+
+ ##
+ # Adds +raw+ to the output
+
+ def accept_raw raw
+ @res << raw.parts.join("\n")
+ end
+
+ # :section: Utilities
+
+ ##
+ # CGI-escapes +text+
+
+ def convert_string(text)
+ CGI.escapeHTML text
+ end
+
+ ##
+ # Generate a link to +url+ with content +text+. Handles the special cases
+ # for img: and link: described under handle_special_HYPERLINK
+
+ def gen_url url, text
+ scheme, url, id = parse_url url
+
+ if %w[http https link].include?(scheme) and
+ url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
+ "<img src=\"#{url}\" />"
+ else
+ text = text.sub %r%^#{scheme}:/*%i, ''
+ text = text.sub %r%^[*\^](\d+)$%, '\1'
+
+ link = "<a#{id} href=\"#{url}\">#{text}</a>"
+
+ link = "<sup>#{link}</sup>" if /"foot/ =~ id
+
+ link
+ end
+ end
+
+ ##
+ # Determines the HTML list element for +list_type+ and +open_tag+
+
+ def html_list_name(list_type, open_tag)
+ tags = LIST_TYPE_TO_HTML[list_type]
+ raise RDoc::Error, "Invalid list type: #{list_type.inspect}" unless tags
+ tags[open_tag ? 0 : 1]
+ end
+
+ ##
+ # Maps attributes to HTML tags
+
+ def init_tags
+ add_tag :BOLD, "<strong>", "</strong>"
+ add_tag :TT, "<code>", "</code>"
+ add_tag :EM, "<em>", "</em>"
+ end
+
+ ##
+ # Returns the HTML tag for +list_type+, possible using a label from
+ # +list_item+
+
+ def list_item_start(list_item, list_type)
+ case list_type
+ when :BULLET, :LALPHA, :NUMBER, :UALPHA then
+ "<li>"
+ when :LABEL, :NOTE then
+ Array(list_item.label).map do |label|
+ "<dt>#{to_html label}\n"
+ end.join << "<dd>"
+ else
+ raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
+ end
+ end
+
+ ##
+ # Returns the HTML end-tag for +list_type+
+
+ def list_end_for(list_type)
+ case list_type
+ when :BULLET, :LALPHA, :NUMBER, :UALPHA then
+ "</li>"
+ when :LABEL, :NOTE then
+ "</dd>"
+ else
+ raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
+ end
+ end
+
+ ##
+ # Returns true if text is valid ruby syntax
+
+ def parseable? text
+ eval("BEGIN {return true}\n#{text}")
+ rescue SyntaxError
+ false
+ end
+
+ ##
+ # Converts +item+ to HTML using RDoc::Text#to_html
+
+ def to_html item
+ super convert_flow @am.flow item
+ end
+
+end
+