123456789_123456789_123456789_123456789_123456789_

Class: RDoc::Markup::ToHtml

Relationships & Source Files
Namespace Children
Classes:
Extension / Inclusion / Inheritance Descendants
Subclasses:
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
self, Formatter
Instance Chain:
Inherits: RDoc::Markup::Formatter
Defined in: lib/rdoc/markup/to_html.rb

Overview

Outputs RDoc markup as HTML.

Constant Summary

::RDoc::Text - Included

MARKUP_FORMAT, SPACE_SEPARATED_LETTER_CLASS

Utilities

Regexp Handling

Visitor

Class Method Summary

Formatter - Inherited

.gen_relative_url

Converts a target url to one that is relative to a given path.

.new

Creates a new Formatter.

Instance Attribute Summary

::RDoc::Text - Included

#language

The language for this text.

Instance Method Summary

::RDoc::Text - Included

#flush_left

Flush text left based on the shortest line.

#markup

Convert a string in markup format into HTML.

#normalize_comment

Strips hashes, expands tabs then flushes text to the left.

#parse

Normalizes text then builds a Document from it.

#snippet

The first limit characters of text as HTML.

#strip_hashes

Strips leading # characters from text

#strip_newlines

Strips leading and trailing \n characters from text

#strip_stars

Strips /* */ style comments.

#wrap

Wraps txt to line_len

Formatter - Inherited

#accept_document

Adds document to the output.

#add_regexp_handling_RDOCLINK

Adds a regexp handling for links of the form rdoc-...:

#annotate

Allows tag to be decorated with additional information.

#apply_regexp_handling

Applies regexp handling to text and returns an array of [text, converted?] pairs.

#convert

Marks up content

#convert_string

Converts a string to be fancier if desired.

#handle_BOLD

Called when processing bold nodes while traversing inline nodes from handle_inline.

#handle_BOLD_WORD

Called when processing bold word nodes while traversing inline nodes from handle_inline.

#handle_EM

Called when processing emphasis nodes while traversing inline nodes from handle_inline.

#handle_EM_WORD

Called when processing emphasis word nodes while traversing inline nodes from handle_inline.

#handle_HARD_BREAK

Called when processing a hard break while traversing inline nodes from handle_inline.

#handle_inline

Parses inline text, traverse the resulting nodes, and calls the appropriate handler methods.

#handle_PLAIN_TEXT

Called when processing plain text while traversing inline nodes from handle_inline.

#handle_REGEXP_HANDLING_TEXT

Called when processing regexp-handling-processed text while traversing inline nodes from handle_inline.

#handle_STRIKE

Called when processing strike nodes while traversing inline nodes from handle_inline.

#handle_TEXT

Called when processing text node while traversing inline nodes from handle_inline.

#handle_TIDYLINK

Called when processing tidylink nodes while traversing inline nodes from handle_inline.

#handle_TT

Called when processing tt nodes while traversing inline nodes from handle_inline.

#ignore

Use ignore in your subclass to ignore the content of a node.

#parse_url

Extracts and a scheme, url and an anchor id from url and returns them.

#traverse_inline_nodes

Traverses nodes and calls the appropriate handler methods Nodes formats are described in InlineParser#parse

#tt?

Is tag a tt tag?

Constructor Details

.new(pipe: false, output_decoration: true) ⇒ ToHtml

Creates a new formatter that will output HTML

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 127

def initialize(pipe: false, output_decoration: true)
  super()

  @pipe = pipe
  @output_decoration = output_decoration
  @code_object = nil
  @from_path = ''
  @in_list_entry = nil
  @list = nil
  @th = nil
  @quote_converter = nil
  @in_tidylink_label = false
  @hard_break = "<br>\n"

  init_regexp_handlings
end

Class Method Details

.encode_fallback(character, encoding, fallback)

Transcodes character to encoding with a fallback character.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 79

def self.encode_fallback(character, encoding, fallback)
  character.encode(
    encoding,
    fallback: { character => fallback },
    undef: :replace,
    replace: fallback
  )
end

Instance Attribute Details

#code_object (rw)

The ::RDoc::CodeObject HTML is being generated for. This is used to generate namespaced URI fragments

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 35

attr_accessor :code_object

#from_path (rw)

Path to this document for relative links

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 40

attr_accessor :from_path

#in_list_entry (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 28

attr_reader :in_list_entry # :nodoc:

#list (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 29

attr_reader :list # :nodoc:

#res (readonly)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 27

attr_reader :res # :nodoc:

Instance Method Details

#accept_blank_line(blank_line)

Adds blank_line to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 509

def accept_blank_line(blank_line)
  # @res << annotate("<p />") << "\n"
end

#accept_block_quote(block_quote)

Adds block_quote to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 403

def accept_block_quote(block_quote)
  @res << "\n<blockquote>"

  block_quote.parts.each do |part|
    part.accept self
  end

  @res << "</blockquote>\n"
end

#accept_heading(heading)

Adds heading to the output. The headings greater than 6 are trimmed to level 6.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 517

def accept_heading(heading)
  level = [6, heading.level].min

  label = deduplicate_heading_id(heading.label(@code_object))
  legacy_label = deduplicate_heading_id(heading.legacy_label(@code_object))

  # Add legacy anchor before the heading for backward compatibility.
  # This allows old links with label- prefix to still work.
  if @output_decoration && !@pipe
    @res << "\n<span id=\"#{legacy_label}\" class=\"legacy-anchor\"></span>"
  end

  @res << if @output_decoration
            "\n<h#{level} id=\"#{label}\">"
          else
            "\n<h#{level}>"
          end

  if @pipe
    @res << to_html(heading.text)
  else
    @res << "<a href=\"##{label}\">#{to_html(heading.text)}</a>"
  end

  @res << "</h#{level}>\n"
end

#accept_list_end(list)

Finishes consumption of #list

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 480

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

#accept_list_item_end(list_item)

Finishes consumption of list_item

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 502

def accept_list_item_end(list_item)
  @in_list_entry[-1] = list_end_for(@list.last)
end

#accept_list_item_start(list_item)

Prepares the visitor for consuming list_item

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 491

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

#accept_list_start(list)

Prepares the visitor for consuming #list

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 471

def accept_list_start(list)
  @list << list.type
  @res << html_list_name(list.type, true)
  @in_list_entry.push false
end

#accept_paragraph(paragraph)

Adds paragraph to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 416

def accept_paragraph(paragraph)
  @res << "\n<p>"
  text = paragraph.text @hard_break
  text = text.gsub(/(#{SPACE_SEPARATED_LETTER_CLASS})?\K(?:\r?\n)+(?=(?(1)(#{SPACE_SEPARATED_LETTER_CLASS})?))/o) {
    defined?($2) && ' '
  }
  @res << to_html(text)
  @res << "</p>\n"
end

#accept_raw(raw)

Adds raw to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 547

def accept_raw(raw)
  @res << raw.parts.join("\n")
end

#accept_rule(rule)

Adds rule to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 464

def accept_rule(rule)
  @res << "<hr>\n"
end

#accept_table(header, body, aligns)

Adds table to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 554

def accept_table(header, body, aligns)
  @res << "\n<table role=\"table\">\n<thead>\n<tr>\n"
  header.zip(aligns) do |text, align|
    @res << '<th'
    @res << ' align="' << align << '"' if align
    @res << '>' << to_html(text) << "</th>\n"
  end
  @res << "</tr>\n</thead>\n<tbody>\n"
  body.each do |row|
    @res << "<tr>\n"
    row.zip(aligns) do |text, align|
      @res << '<td'
      @res << ' align="' << align << '"' if align
      @res << '>' << to_html(text) << "</td>\n"
    end
    @res << "</tr>\n"
  end
  @res << "</tbody>\n</table>\n"
end

#accept_verbatim(verbatim)

Adds verbatim to the output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 438

def accept_verbatim(verbatim)
  text = verbatim.text.rstrip
  format = verbatim.format

  # Apply Ruby syntax highlighting if
  # - explicitly marked as Ruby (via ruby? which accepts :ruby or :rb)
  # - no format specified but the text is parseable as Ruby
  # Otherwise, add language class when applicable and skip Ruby highlighting
  if verbatim.ruby? || (format.nil? && parseable?(text))
    content = parsable_text_to_html(text)
    klass = ' class="ruby"'
  else
    content = CGI.escapeHTML text
    klass = " class=\"#{format}\"" if format
  end

  if @pipe
    @res << "\n<pre><code>#{CGI.escapeHTML text}\n</code></pre>\n"
  else
    @res << "\n<pre#{klass}>#{content}</pre>\n"
  end
end

#convert_string(text)

CGI-escapes text

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 593

def convert_string(text)
  CGI.escapeHTML text
end

#deduplicate_heading_id(id)

Returns a unique heading ID, appending -1, -2, etc. for duplicates. Matches GitHub's behavior for duplicate heading anchors.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 580

def deduplicate_heading_id(id)
  if @heading_ids.key?(id)
    @heading_ids[id] += 1
    "#{id}-#{@heading_ids[id]}"
  else
    @heading_ids[id] = 0
    id
  end
end

#emit_inline(text)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 256

def emit_inline(text)
  @inline_output << text
end

#end_accepting

Returns the generated output

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 396

def end_accepting
  @res.join
end

#gen_url(url, text)

Generates an HTML link or image tag for the given url and text.

  • Image URLs (http/https/link ending in .gif, .png, .jpg, .jpeg, .bmp) become tags
  • File references (.rb, .rdoc, .md) are converted to .html paths
  • Anchor URLs (#foo) pass through unchanged for GitHub-style header linking
  • Footnote links get wrapped in tags
[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 606

def gen_url(url, text)
  scheme, url, id = parse_url url

  if %w[http https link].include?(scheme) && url =~ /\.(gif|png|jpg|jpeg|bmp)\z/
    "<img src=\"#{url}\" />"
  else
    if scheme != 'link' and %r%\A((?!https?:)(?:[^/#]*/)*)([^/#])\.(rb|rdoc|md)(?=\z|#)%i =~ url
      url = "#$1#{$2.tr('.', '_')}_#$3.html#$'"
    end

    text = text.sub %r%^#{scheme}:/*%i, ''
    text = text.sub %r%^[*\^](\d+)$%,   '\1'

    link = "<a#{id} href=\"#{url}\">#{text}</a>"

    if /"foot/.match?(id)
      "<sup>#{link}</sup>"
    else
      link
    end
  end
end

#handle_BOLD(nodes)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 216

def handle_BOLD(nodes)
  emit_inline('<strong>')
  super
  emit_inline('</strong>')
end

#handle_BOLD_WORD(word)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 228

def handle_BOLD_WORD(word)
  emit_inline('<strong>')
  super
  emit_inline('</strong>')
end

#handle_EM(nodes)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 222

def handle_EM(nodes)
  emit_inline('<em>')
  super
  emit_inline('</em>')
end

#handle_EM_WORD(word)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 234

def handle_EM_WORD(word)
  emit_inline('<em>')
  super
  emit_inline('</em>')
end

#handle_HARD_BREAK

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 252

def handle_HARD_BREAK
  emit_inline('<br>')
end

#handle_inline(text)

This method is for internal use only.
[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 317

def handle_inline(text) # :nodoc:
  @inline_output = +''
  @quote_converter = QuoteConverter.new
  super
  out = @inline_output
  @inline_output = nil
  @quote_converter = nil
  out
end

#handle_PLAIN_TEXT(text)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 208

def handle_PLAIN_TEXT(text)
  emit_inline(convert_string(text))
end

#handle_REGEXP_HANDLING_TEXT(text)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 212

def handle_REGEXP_HANDLING_TEXT(text)
  emit_inline(text)
end

#handle_regexp_HTML_CHARACTERS(text)

Converts (c), (r), --, --- , ..., ...., ``, '' to HTML characters.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 328

def handle_regexp_HTML_CHARACTERS(text)
  name = HTML_CHARACTER_ALIASES[text]
  TO_HTML_CHARACTERS[text.encoding][name] if name
end

#handle_regexp_QUOTE_AFTER_WORD(text)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 337

def handle_regexp_QUOTE_AFTER_WORD(text)
  @quote_converter.convert(text, after_word: true) || convert_string(text)
end

#handle_regexp_QUOTE_NOT_AFTER_WORD(text)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 333

def handle_regexp_QUOTE_NOT_AFTER_WORD(text)
  @quote_converter.convert(text, after_word: false) || convert_string(text)
end

#handle_regexp_SUPPRESSED_CROSSREF(text)

Converts suppressed cross-reference text to HTML by removing the leading backslash.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 343

def handle_regexp_SUPPRESSED_CROSSREF(text)
  convert_string(text.delete_prefix('\\'))
end

#handle_STRIKE(nodes)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 246

def handle_STRIKE(nodes)
  emit_inline('<del>')
  super
  emit_inline('</del>')
end

#handle_TT(code)

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 240

def handle_TT(code)
  emit_inline('<code>')
  super
  emit_inline('</code>')
end

#html_list_name(list_type, open_tag)

Determines the HTML list element for list_type and open_tag

Raises:

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 632

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

#init_regexp_handlings

Adds regexp handlings.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 154

def init_regexp_handlings
  # external links
  @markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)#{URL_CHARACTERS_REGEXP_STR}+\w/,
                              :HYPERLINK)

  # suppress crossref: \#method \::method \ClassName \method_with_underscores
  @markup.add_regexp_handling(/\\(?:[#:A-Z]|[a-z]+_[a-z0-9])/, :SUPPRESSED_CROSSREF)

  @markup.add_regexp_handling(Regexp.union(HTML_CHARACTER_ALIASES.keys), :HTML_CHARACTERS)

  @markup.add_regexp_handling(/\b['"`]/, :QUOTE_AFTER_WORD)
  @markup.add_regexp_handling(/\B['"`]/, :QUOTE_NOT_AFTER_WORD)

  init_link_notation_regexp_handlings
end

#list_end_for(list_type)

Returns the HTML end-tag for list_type

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 658

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

#list_item_start(list_item, list_type)

Returns the HTML tag for list_type, possible using a label from list_item

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 642

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}</dt>\n"
    end.join << "<dd>"
  else
    raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
  end
end

#parsable_text_to_html(text)

Generate syntax highlighted html for ruby-like text.

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 428

def parsable_text_to_html(text)
  tokens = RDoc::Parser::RubyColorizer.colorize(text)
  result = RDoc::TokenStream.to_html tokens
  result = result + "\n" unless result.end_with?("\n")
  result
end

#parseable?(text) ⇒ Boolean

Returns true if text is valid ruby syntax

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 672

def parseable?(text)
  Prism.parse_success?(text)
end

#start_accepting

Prepares the visitor for HTML generation

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 386

def start_accepting
  @res = []
  @in_list_entry = []
  @list = []
  @heading_ids = {}
end

#to_html(item)

Converts item to HTML using RDoc::Text#to_html

[ GitHub ]

  
# File 'lib/rdoc/markup/to_html.rb', line 679

def to_html(item)
  handle_inline(item)
end