diff options
Diffstat (limited to 'lib/rdoc/markup')
| -rw-r--r-- | lib/rdoc/markup/attribute_manager.rb | 317 | ||||
| -rw-r--r-- | lib/rdoc/markup/blank_line.rb | 19 | ||||
| -rw-r--r-- | lib/rdoc/markup/document.rb | 72 | ||||
| -rw-r--r-- | lib/rdoc/markup/formatter.rb | 143 | ||||
| -rw-r--r-- | lib/rdoc/markup/formatter_test_case.rb | 353 | ||||
| -rw-r--r-- | lib/rdoc/markup/heading.rb | 17 | ||||
| -rw-r--r-- | lib/rdoc/markup/inline.rb | 127 | ||||
| -rw-r--r-- | lib/rdoc/markup/list.rb | 78 | ||||
| -rw-r--r-- | lib/rdoc/markup/list_item.rb | 83 | ||||
| -rw-r--r-- | lib/rdoc/markup/paragraph.rb | 11 | ||||
| -rw-r--r-- | lib/rdoc/markup/parser.rb | 529 | ||||
| -rw-r--r-- | lib/rdoc/markup/preprocess.rb | 130 | ||||
| -rw-r--r-- | lib/rdoc/markup/raw.rb | 65 | ||||
| -rw-r--r-- | lib/rdoc/markup/rule.rb | 17 | ||||
| -rw-r--r-- | lib/rdoc/markup/to_ansi.rb | 72 | ||||
| -rw-r--r-- | lib/rdoc/markup/to_bs.rb | 74 | ||||
| -rw-r--r-- | lib/rdoc/markup/to_html.rb | 344 | ||||
| -rw-r--r-- | lib/rdoc/markup/to_html_crossref.rb | 148 | ||||
| -rw-r--r-- | lib/rdoc/markup/to_rdoc.rb | 247 | ||||
| -rw-r--r-- | lib/rdoc/markup/to_test.rb | 64 | ||||
| -rw-r--r-- | lib/rdoc/markup/verbatim.rb | 42 |
21 files changed, 0 insertions, 2952 deletions
diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb deleted file mode 100644 index e86e7f6812..0000000000 --- a/lib/rdoc/markup/attribute_manager.rb +++ /dev/null @@ -1,317 +0,0 @@ -## -# Manages changes of attributes in a block of text - -class RDoc::Markup::AttributeManager - - ## - # The NUL character - - NULL = "\000".freeze - - #-- - # We work by substituting non-printing characters in to the text. For now - # I'm assuming that I can substitute a character in the range 0..8 for a 7 - # bit character without damaging the encoded string, but this might be - # optimistic - #++ - - A_PROTECT = 004 # :nodoc: - - PROTECT_ATTR = A_PROTECT.chr # :nodoc: - - ## - # This maps delimiters that occur around words (such as *bold* or +tt+) - # where the start and end delimiters and the same. This lets us optimize - # the regexp - - attr_reader :matching_word_pairs - - ## - # And this is used when the delimiters aren't the same. In this case the - # hash maps a pattern to the attribute character - - attr_reader :word_pair_map - - ## - # This maps HTML tags to the corresponding attribute char - - attr_reader :html_tags - - ## - # A \ in front of a character that would normally be processed turns off - # processing. We do this by turning \< into <#{PROTECT} - - attr_reader :protectable - - ## - # And this maps _special_ sequences to a name. A special sequence is - # something like a WikiWord - - attr_reader :special - - ## - # Creates a new attribute manager that understands bold, emphasized and - # teletype text. - - def initialize - @html_tags = {} - @matching_word_pairs = {} - @protectable = %w[<\\] - @special = {} - @word_pair_map = {} - - add_word_pair "*", "*", :BOLD - add_word_pair "_", "_", :EM - add_word_pair "+", "+", :TT - - add_html "em", :EM - add_html "i", :EM - add_html "b", :BOLD - add_html "tt", :TT - add_html "code", :TT - end - - - ## - # Return an attribute object with the given turn_on and turn_off bits set - - def attribute(turn_on, turn_off) - RDoc::Markup::AttrChanger.new turn_on, turn_off - end - - def change_attribute(current, new) - diff = current ^ new - attribute(new & diff, current & diff) - end - - def changed_attribute_by_name(current_set, new_set) - current = new = 0 - current_set.each do |name| - current |= RDoc::Markup::Attribute.bitmap_for(name) - end - - new_set.each do |name| - new |= RDoc::Markup::Attribute.bitmap_for(name) - end - - change_attribute(current, new) - end - - def copy_string(start_pos, end_pos) - res = @str[start_pos...end_pos] - res.gsub!(/\000/, '') - res - end - - ## - # Map attributes like <b>text</b>to the sequence - # \001\002<char>\001\003<char>, where <char> is a per-attribute specific - # character - - def convert_attrs(str, attrs) - # first do matching ones - tags = @matching_word_pairs.keys.join("") - - re = /(^|[^\w#{NULL}])([#{tags}])([#:\\]?[\w.\/-]+?\S?)\2(\W|$)/ - - 1 while str.gsub!(re) do - attr = @matching_word_pairs[$2] - attrs.set_attrs($`.length + $1.length + $2.length, $3.length, attr) - $1 + NULL * $2.length + $3 + NULL * $2.length + $4 - end - - # then non-matching - unless @word_pair_map.empty? then - @word_pair_map.each do |regexp, attr| - str.gsub!(regexp) { - attrs.set_attrs($`.length + $1.length, $2.length, attr) - NULL * $1.length + $2 + NULL * $3.length - } - end - end - end - - ## - # Converts HTML tags to RDoc attributes - - def convert_html(str, attrs) - tags = @html_tags.keys.join '|' - - 1 while str.gsub!(/<(#{tags})>(.*?)<\/\1>/i) { - attr = @html_tags[$1.downcase] - html_length = $1.length + 2 - seq = NULL * html_length - attrs.set_attrs($`.length + html_length, $2.length, attr) - seq + $2 + seq + NULL - } - end - - ## - # Converts special sequences to RDoc attributes - - def convert_specials(str, attrs) - unless @special.empty? - @special.each do |regexp, attr| - str.scan(regexp) do - attrs.set_attrs($`.length, $&.length, - attr | RDoc::Markup::Attribute::SPECIAL) - end - end - end - end - - ## - # Escapes special sequences of text to prevent conversion to RDoc - - def mask_protected_sequences - @str.gsub!(/\\([#{Regexp.escape @protectable.join('')}])/, - "\\1#{PROTECT_ATTR}") - end - - ## - # Unescapes special sequences of text - - def unmask_protected_sequences - @str.gsub!(/(.)#{PROTECT_ATTR}/, "\\1\000") - end - - ## - # Adds a markup class with +name+ for words wrapped in the +start+ and - # +stop+ character. To make words wrapped with "*" bold: - # - # am.add_word_pair '*', '*', :BOLD - - def add_word_pair(start, stop, name) - raise ArgumentError, "Word flags may not start with '<'" if - start[0,1] == '<' - - bitmap = RDoc::Markup::Attribute.bitmap_for name - - if start == stop then - @matching_word_pairs[start] = bitmap - else - pattern = /(#{Regexp.escape start})(\S+)(#{Regexp.escape stop})/ - @word_pair_map[pattern] = bitmap - end - - @protectable << start[0,1] - @protectable.uniq! - end - - ## - # Adds a markup class with +name+ for words surrounded by HTML tag +tag+. - # To process emphasis tags: - # - # am.add_html 'em', :EM - - def add_html(tag, name) - @html_tags[tag.downcase] = RDoc::Markup::Attribute.bitmap_for name - end - - ## - # Adds a special handler for +pattern+ with +name+. A simple URL handler - # would be: - # - # @am.add_special(/((https?:)\S+\w)/, :HYPERLINK) - - def add_special(pattern, name) - @special[pattern] = RDoc::Markup::Attribute.bitmap_for name - end - - ## - # Processes +str+ converting attributes, HTML and specials - - def flow(str) - @str = str - - mask_protected_sequences - - @attrs = RDoc::Markup::AttrSpan.new @str.length - - convert_html @str, @attrs - convert_attrs @str, @attrs - convert_specials @str, @attrs - - unmask_protected_sequences - - split_into_flow - end - - ## - # Debug method that prints a string along with its attributes - - def display_attributes - puts - puts @str.tr(NULL, "!") - bit = 1 - 16.times do |bno| - line = "" - @str.length.times do |i| - if (@attrs[i] & bit) == 0 - line << " " - else - if bno.zero? - line << "S" - else - line << ("%d" % (bno+1)) - end - end - end - puts(line) unless line =~ /^ *$/ - bit <<= 1 - end - end - - def split_into_flow - res = [] - current_attr = 0 - - str_len = @str.length - - # skip leading invisible text - i = 0 - i += 1 while i < str_len and @str[i].chr == "\0" - start_pos = i - - # then scan the string, chunking it on attribute changes - while i < str_len - new_attr = @attrs[i] - if new_attr != current_attr - if i > start_pos - res << copy_string(start_pos, i) - start_pos = i - end - - res << change_attribute(current_attr, new_attr) - current_attr = new_attr - - if (current_attr & RDoc::Markup::Attribute::SPECIAL) != 0 then - i += 1 while - i < str_len and (@attrs[i] & RDoc::Markup::Attribute::SPECIAL) != 0 - - res << RDoc::Markup::Special.new(current_attr, - copy_string(start_pos, i)) - start_pos = i - next - end - end - - # move on, skipping any invisible characters - begin - i += 1 - end while i < str_len and @str[i].chr == "\0" - end - - # tidy up trailing text - if start_pos < str_len - res << copy_string(start_pos, str_len) - end - - # and reset to all attributes off - res << change_attribute(current_attr, 0) if current_attr != 0 - - res - end - -end - diff --git a/lib/rdoc/markup/blank_line.rb b/lib/rdoc/markup/blank_line.rb deleted file mode 100644 index a8c07c8e57..0000000000 --- a/lib/rdoc/markup/blank_line.rb +++ /dev/null @@ -1,19 +0,0 @@ -## -# An empty line - -class RDoc::Markup::BlankLine - - def == other # :nodoc: - self.class == other.class - end - - def accept visitor - visitor.accept_blank_line self - end - - def pretty_print q # :nodoc: - q.text 'blankline' - end - -end - diff --git a/lib/rdoc/markup/document.rb b/lib/rdoc/markup/document.rb deleted file mode 100644 index 7963e9afe1..0000000000 --- a/lib/rdoc/markup/document.rb +++ /dev/null @@ -1,72 +0,0 @@ -## -# A Document containing lists, headings, paragraphs, etc. - -class RDoc::Markup::Document - - ## - # The parts of the Document - - attr_reader :parts - - ## - # Creates a new Document with +parts+ - - def initialize *parts - @parts = [] - @parts.push(*parts) - end - - ## - # Appends +part+ to the document - - def << part - case part - when RDoc::Markup::Document then - unless part.empty? then - parts.push(*part.parts) - parts << RDoc::Markup::BlankLine.new - end - when String then - raise ArgumentError, - "expected RDoc::Markup::Document and friends, got String" unless - part.empty? - else - parts << part - end - end - - def == other # :nodoc: - self.class == other.class and @parts == other.parts - end - - def accept visitor - visitor.start_accepting - - @parts.each do |item| - item.accept visitor - end - - visitor.end_accepting - end - - def empty? - @parts.empty? - end - - def pretty_print q # :nodoc: - q.group 2, '[doc: ', ']' do - q.seplist @parts do |part| - q.pp part - end - end - end - - ## - # Appends +parts+ to the document - - def push *parts - self.parts.push(*parts) - end - -end - diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb deleted file mode 100644 index 993e523f0c..0000000000 --- a/lib/rdoc/markup/formatter.rb +++ /dev/null @@ -1,143 +0,0 @@ -require 'rdoc/markup' - -## -# Base class for RDoc markup formatters -# -# Formatters use a visitor pattern to convert content into output. - -class RDoc::Markup::Formatter - - InlineTag = Struct.new(:bit, :on, :off) - - ## - # Creates a new Formatter - - def initialize - @markup = RDoc::Markup.new - @am = @markup.attribute_manager - @attr_tags = [] - - @in_tt = 0 - @tt_bit = RDoc::Markup::Attribute.bitmap_for :TT - end - - ## - # Add a new set of tags for an attribute. We allow separate start and end - # tags for flexibility - - def add_tag(name, start, stop) - attr = RDoc::Markup::Attribute.bitmap_for name - @attr_tags << InlineTag.new(attr, start, stop) - end - - ## - # Allows +tag+ to be decorated with additional information. - - def annotate(tag) - tag - end - - ## - # Marks up +content+ - - def convert(content) - @markup.convert content, self - end - - ## - # Converts flow items +flow+ - - def convert_flow(flow) - res = [] - - flow.each do |item| - case item - when String then - res << convert_string(item) - when RDoc::Markup::AttrChanger then - off_tags res, item - on_tags res, item - when RDoc::Markup::Special then - res << convert_special(item) - else - raise "Unknown flow element: #{item.inspect}" - end - end - - res.join - end - - ## - # Converts added specials. See RDoc::Markup#add_special - - def convert_special(special) - handled = false - - RDoc::Markup::Attribute.each_name_of special.type do |name| - method_name = "handle_special_#{name}" - - if respond_to? method_name then - special.text = send method_name, special - handled = true - end - end - - raise "Unhandled special: #{special}" unless handled - - special.text - end - - ## - # Converts a string to be fancier if desired - - def convert_string string - string - end - - ## - # Are we currently inside tt tags? - - def in_tt? - @in_tt > 0 - end - - def on_tags res, item - attr_mask = item.turn_on - return if attr_mask.zero? - - @attr_tags.each do |tag| - if attr_mask & tag.bit != 0 then - res << annotate(tag.on) - @in_tt += 1 if tt? tag - end - end - end - - def off_tags res, item - attr_mask = item.turn_off - return if attr_mask.zero? - - @attr_tags.reverse_each do |tag| - if attr_mask & tag.bit != 0 then - @in_tt -= 1 if tt? tag - res << annotate(tag.off) - end - end - end - - ## - # Is +tag+ a tt tag? - - def tt? tag - tag.bit == @tt_bit - end - -end - -class RDoc::Markup - autoload :ToAnsi, 'rdoc/markup/to_ansi' - autoload :ToBs, 'rdoc/markup/to_bs' - autoload :ToHtml, 'rdoc/markup/to_html' - autoload :ToHtmlCrossref, 'rdoc/markup/to_html_crossref' - autoload :ToRdoc, 'rdoc/markup/to_rdoc' -end diff --git a/lib/rdoc/markup/formatter_test_case.rb b/lib/rdoc/markup/formatter_test_case.rb deleted file mode 100644 index 26c8d63332..0000000000 --- a/lib/rdoc/markup/formatter_test_case.rb +++ /dev/null @@ -1,353 +0,0 @@ -require 'minitest/unit' -require 'rdoc/markup/formatter' - -## -# Test case for creating new RDoc::Markup formatters. See -# test/test_rdoc_markup_to_*.rb for examples. - -class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase - - def setup - super - - @m = RDoc::Markup.new - @am = RDoc::Markup::AttributeManager.new - @RM = RDoc::Markup - - @bullet_list = @RM::List.new(:BULLET, - @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), - @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) - - @label_list = @RM::List.new(:LABEL, - @RM::ListItem.new('cat', @RM::Paragraph.new('cats are cool')), - @RM::ListItem.new('dog', @RM::Paragraph.new('dogs are cool too'))) - - @lalpha_list = @RM::List.new(:LALPHA, - @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), - @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) - - @note_list = @RM::List.new(:NOTE, - @RM::ListItem.new('cat', @RM::Paragraph.new('cats are cool')), - @RM::ListItem.new('dog', @RM::Paragraph.new('dogs are cool too'))) - - @number_list = @RM::List.new(:NUMBER, - @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), - @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) - - @ualpha_list = @RM::List.new(:UALPHA, - @RM::ListItem.new(nil, @RM::Paragraph.new('l1')), - @RM::ListItem.new(nil, @RM::Paragraph.new('l2'))) - end - - def self.add_visitor_tests - self.class_eval do - def test_start_accepting - @to.start_accepting - - start_accepting - end - - def test_end_accepting - @to.start_accepting - @to.res << 'hi' - - end_accepting - end - - def test_accept_blank_line - @to.start_accepting - - @to.accept_blank_line @RM::BlankLine.new - - accept_blank_line - end - - def test_accept_heading - @to.start_accepting - - @to.accept_heading @RM::Heading.new(5, 'Hello') - - accept_heading - end - - def test_accept_paragraph - @to.start_accepting - - @to.accept_paragraph @RM::Paragraph.new('hi') - - accept_paragraph - end - - def test_accept_verbatim - @to.start_accepting - - @to.accept_verbatim @RM::Verbatim.new(' ', 'hi', "\n", - ' ', 'world', "\n") - - accept_verbatim - end - - def test_accept_raw - @to.start_accepting - - @to.accept_raw @RM::Raw.new("<table>", - "<tr><th>Name<th>Count", - "<tr><td>a<td>1", - "<tr><td>b<td>2", - "</table>") - - accept_raw - end - - def test_accept_rule - @to.start_accepting - - @to.accept_rule @RM::Rule.new(4) - - accept_rule - end - - def test_accept_list_item_start_bullet - @to.start_accepting - - @to.accept_list_start @bullet_list - - @to.accept_list_item_start @bullet_list.items.first - - accept_list_item_start_bullet - end - - def test_accept_list_item_start_label - @to.start_accepting - - @to.accept_list_start @label_list - - @to.accept_list_item_start @label_list.items.first - - accept_list_item_start_label - end - - def test_accept_list_item_start_lalpha - @to.start_accepting - - @to.accept_list_start @lalpha_list - - @to.accept_list_item_start @lalpha_list.items.first - - accept_list_item_start_lalpha - end - - def test_accept_list_item_start_note - @to.start_accepting - - @to.accept_list_start @note_list - - @to.accept_list_item_start @note_list.items.first - - accept_list_item_start_note - end - - def test_accept_list_item_start_number - @to.start_accepting - - @to.accept_list_start @number_list - - @to.accept_list_item_start @number_list.items.first - - accept_list_item_start_number - end - - def test_accept_list_item_start_ualpha - @to.start_accepting - - @to.accept_list_start @ualpha_list - - @to.accept_list_item_start @ualpha_list.items.first - - accept_list_item_start_ualpha - end - - def test_accept_list_item_end_bullet - @to.start_accepting - - @to.accept_list_start @bullet_list - - @to.accept_list_item_start @bullet_list.items.first - - @to.accept_list_item_end @bullet_list.items.first - - accept_list_item_end_bullet - end - - def test_accept_list_item_end_label - @to.start_accepting - - @to.accept_list_start @label_list - - @to.accept_list_item_start @label_list.items.first - - @to.accept_list_item_end @label_list.items.first - - accept_list_item_end_label - end - - def test_accept_list_item_end_lalpha - @to.start_accepting - - @to.accept_list_start @lalpha_list - - @to.accept_list_item_start @lalpha_list.items.first - - @to.accept_list_item_end @lalpha_list.items.first - - accept_list_item_end_lalpha - end - - def test_accept_list_item_end_note - @to.start_accepting - - @to.accept_list_start @note_list - - @to.accept_list_item_start @note_list.items.first - - @to.accept_list_item_end @note_list.items.first - - accept_list_item_end_note - end - - def test_accept_list_item_end_number - @to.start_accepting - - @to.accept_list_start @number_list - - @to.accept_list_item_start @number_list.items.first - - @to.accept_list_item_end @number_list.items.first - - accept_list_item_end_number - end - - def test_accept_list_item_end_ualpha - @to.start_accepting - - @to.accept_list_start @ualpha_list - - @to.accept_list_item_start @ualpha_list.items.first - - @to.accept_list_item_end @ualpha_list.items.first - - accept_list_item_end_ualpha - end - - def test_accept_list_start_bullet - @to.start_accepting - - @to.accept_list_start @bullet_list - - accept_list_start_bullet - end - - def test_accept_list_start_label - @to.start_accepting - - @to.accept_list_start @label_list - - accept_list_start_label - end - - def test_accept_list_start_lalpha - @to.start_accepting - - @to.accept_list_start @lalpha_list - - accept_list_start_lalpha - end - - def test_accept_list_start_note - @to.start_accepting - - @to.accept_list_start @note_list - - accept_list_start_note - end - - def test_accept_list_start_number - @to.start_accepting - - @to.accept_list_start @number_list - - accept_list_start_number - end - - def test_accept_list_start_ualpha - @to.start_accepting - - @to.accept_list_start @ualpha_list - - accept_list_start_ualpha - end - - def test_accept_list_end_bullet - @to.start_accepting - - @to.accept_list_start @bullet_list - - @to.accept_list_end @bullet_list - - accept_list_end_bullet - end - - def test_accept_list_end_label - @to.start_accepting - - @to.accept_list_start @label_list - - @to.accept_list_end @label_list - - accept_list_end_label - end - - def test_accept_list_end_lalpha - @to.start_accepting - - @to.accept_list_start @lalpha_list - - @to.accept_list_end @lalpha_list - - accept_list_end_lalpha - end - - def test_accept_list_end_number - @to.start_accepting - - @to.accept_list_start @number_list - - @to.accept_list_end @number_list - - accept_list_end_number - end - - def test_accept_list_end_note - @to.start_accepting - - @to.accept_list_start @note_list - - @to.accept_list_end @note_list - - accept_list_end_note - end - - def test_accept_list_end_ualpha - @to.start_accepting - - @to.accept_list_start @ualpha_list - - @to.accept_list_end @ualpha_list - - accept_list_end_ualpha - end - end - end - -end - diff --git a/lib/rdoc/markup/heading.rb b/lib/rdoc/markup/heading.rb deleted file mode 100644 index 21e2574d68..0000000000 --- a/lib/rdoc/markup/heading.rb +++ /dev/null @@ -1,17 +0,0 @@ -## -# A heading with a level (1-6) and text - -class RDoc::Markup::Heading < Struct.new :level, :text - - def accept visitor - visitor.accept_heading self - end - - def pretty_print q # :nodoc: - q.group 2, "[head: #{level} ", ']' do - q.pp text - end - end - -end - diff --git a/lib/rdoc/markup/inline.rb b/lib/rdoc/markup/inline.rb deleted file mode 100644 index 1b5eac45ae..0000000000 --- a/lib/rdoc/markup/inline.rb +++ /dev/null @@ -1,127 +0,0 @@ -class RDoc::Markup - - ## - # We manage a set of attributes. Each attribute has a symbol name and a bit - # value. - - class Attribute - - ## - # Special attribute type. See RDoc::Markup#add_special - - SPECIAL = 1 - - @@name_to_bitmap = { :_SPECIAL_ => SPECIAL } - @@next_bitmap = 2 - - def self.bitmap_for(name) - bitmap = @@name_to_bitmap[name] - unless bitmap then - bitmap = @@next_bitmap - @@next_bitmap <<= 1 - @@name_to_bitmap[name] = bitmap - end - bitmap - end - - def self.as_string(bitmap) - return "none" if bitmap.zero? - res = [] - @@name_to_bitmap.each do |name, bit| - res << name if (bitmap & bit) != 0 - end - res.join(",") - end - - def self.each_name_of(bitmap) - @@name_to_bitmap.each do |name, bit| - next if bit == SPECIAL - yield name.to_s if (bitmap & bit) != 0 - end - end - - end - - AttrChanger = Struct.new :turn_on, :turn_off # :nodoc: - - ## - # An AttrChanger records a change in attributes. It contains a bitmap of the - # attributes to turn on, and a bitmap of those to turn off. - - class AttrChanger - def to_s # :nodoc: - "Attr: +#{Attribute.as_string turn_on}/-#{Attribute.as_string turn_on}" - end - end - - ## - # An array of attributes which parallels the characters in a string. - - class AttrSpan - - ## - # Creates a new AttrSpan for +length+ characters - - def initialize(length) - @attrs = Array.new(length, 0) - end - - ## - # Toggles +bits+ from +start+ to +length+ - def set_attrs(start, length, bits) - for i in start ... (start+length) - @attrs[i] |= bits - end - end - - ## - # Acccesses flags for character +n+ - - def [](n) - @attrs[n] - end - - end - - ## - # Hold details of a special sequence - - class Special - - ## - # Special type - - attr_reader :type - - ## - # Special text - - attr_accessor :text - - ## - # Creates a new special sequence of +type+ with +text+ - - def initialize(type, text) - @type, @text = type, text - end - - ## - # Specials are equal when the have the same text and type - - def ==(o) - self.text == o.text && self.type == o.type - end - - def inspect # :nodoc: - "#<RDoc::Markup::Special:0x%x @type=%p, name=%p @text=%p>" % [ - object_id, @type, RDoc::Markup::Attribute.as_string(type), text.dump] - end - - def to_s # :nodoc: - "Special: type=#{type}, name=#{RDoc::Markup::Attribute.as_string type}, text=#{text.dump}" - end - - end - -end - diff --git a/lib/rdoc/markup/list.rb b/lib/rdoc/markup/list.rb deleted file mode 100644 index 75326ed836..0000000000 --- a/lib/rdoc/markup/list.rb +++ /dev/null @@ -1,78 +0,0 @@ -## -# A List of ListItems - -class RDoc::Markup::List - - ## - # The list's type - - attr_accessor :type - - ## - # Items in the list - - attr_reader :items - - ## - # Creates a new list of +type+ with +items+ - - def initialize type = nil, *items - @type = type - @items = [] - @items.push(*items) - end - - ## - # Appends +item+ to the list - - def << item - @items << item - end - - def == other # :nodoc: - self.class == other.class and - @type == other.type and - @items == other.items - end - - def accept visitor - visitor.accept_list_start self - - @items.each do |item| - item.accept visitor - end - - visitor.accept_list_end self - end - - ## - # Is the list empty? - - def empty? - @items.empty? - end - - ## - # Returns the last item in the list - - def last - @items.last - end - - def pretty_print q # :nodoc: - q.group 2, "[list: #{@type} ", ']' do - q.seplist @items do |item| - q.pp item - end - end - end - - ## - # Appends +items+ to the list - - def push *items - @items.push(*items) - end - -end - diff --git a/lib/rdoc/markup/list_item.rb b/lib/rdoc/markup/list_item.rb deleted file mode 100644 index 500e814fe1..0000000000 --- a/lib/rdoc/markup/list_item.rb +++ /dev/null @@ -1,83 +0,0 @@ -## -# An item within a List that contains paragraphs, headings, etc. - -class RDoc::Markup::ListItem - - ## - # The label for the ListItem - - attr_accessor :label - - ## - # Parts of the ListItem - - attr_reader :parts - - ## - # Creates a new ListItem with an optional +label+ containing +parts+ - - def initialize label = nil, *parts - @label = label - @parts = [] - @parts.push(*parts) - end - - ## - # Appends +part+ to the ListItem - - def << part - @parts << part - end - - def == other # :nodoc: - self.class == other.class and - @label == other.label and - @parts == other.parts - end - - def accept visitor - visitor.accept_list_item_start self - - @parts.each do |part| - part.accept visitor - end - - visitor.accept_list_item_end self - end - - ## - # Is the ListItem empty? - - def empty? - @parts.empty? - end - - ## - # Length of parts in the ListItem - - def length - @parts.length - end - - def pretty_print q # :nodoc: - q.group 2, '[item: ', ']' do - if @label then - q.text @label - q.breakable - end - - q.seplist @parts do |part| - q.pp part - end - end - end - - ## - # Adds +parts+ to the ListItem - - def push *parts - @parts.push(*parts) - end - -end - diff --git a/lib/rdoc/markup/paragraph.rb b/lib/rdoc/markup/paragraph.rb deleted file mode 100644 index a9923ed24d..0000000000 --- a/lib/rdoc/markup/paragraph.rb +++ /dev/null @@ -1,11 +0,0 @@ -## -# A Paragraph of text - -class RDoc::Markup::Paragraph < RDoc::Markup::Raw - - def accept visitor - visitor.accept_paragraph self - end - -end - diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb deleted file mode 100644 index 9fba69dc29..0000000000 --- a/lib/rdoc/markup/parser.rb +++ /dev/null @@ -1,529 +0,0 @@ -require 'strscan' -require 'rdoc/text' - -## -# A recursive-descent parser for RDoc markup. -# -# The parser tokenizes an input string then parses the tokens into a Document. -# Documents can be converted into output formats by writing a visitor like -# RDoc::Markup::ToHTML. -# -# The parser only handles the block-level constructs Paragraph, List, -# ListItem, Heading, Verbatim, BlankLine and Rule. Inline markup such as -# <tt>\+blah\+</tt> is handled separately by RDoc::Markup::AttributeManager. -# -# To see what markup the Parser implements read RDoc. To see how to use -# RDoc markup to format text in your program read RDoc::Markup. - -class RDoc::Markup::Parser - - include RDoc::Text - - ## - # List token types - - LIST_TOKENS = [ - :BULLET, - :LABEL, - :LALPHA, - :NOTE, - :NUMBER, - :UALPHA, - ] - - ## - # Parser error subclass - - class Error < RuntimeError; end - - ## - # Raised when the parser is unable to handle the given markup - - class ParseError < Error; end - - ## - # Enables display of debugging information - - attr_accessor :debug - - ## - # Token accessor - - attr_reader :tokens - - ## - # Parsers +str+ into a Document - - def self.parse str - parser = new - #parser.debug = true - parser.tokenize str - RDoc::Markup::Document.new(*parser.parse) - end - - ## - # Returns a token stream for +str+, for testing - - def self.tokenize str - parser = new - parser.tokenize str - parser.tokens - end - - ## - # Creates a new Parser. See also ::parse - - def initialize - @tokens = [] - @current_token = nil - @debug = false - - @line = 0 - @line_pos = 0 - end - - ## - # Builds a Heading of +level+ - - def build_heading level - heading = RDoc::Markup::Heading.new level, text - skip :NEWLINE - - heading - end - - ## - # Builds a List flush to +margin+ - - def build_list margin - p :list_start => margin if @debug - - list = RDoc::Markup::List.new - - until @tokens.empty? do - type, data, column, = get - - case type - when :BULLET, :LABEL, :LALPHA, :NOTE, :NUMBER, :UALPHA then - list_type = type - - if column < margin then - unget - break - end - - if list.type and list.type != list_type then - unget - break - end - - list.type = list_type - - case type - when :NOTE, :LABEL then - _, indent, = get # SPACE - if :NEWLINE == peek_token.first then - get - peek_type, new_indent, peek_column, = peek_token - indent = new_indent if - peek_type == :INDENT and peek_column >= column - unget - end - else - data = nil - _, indent, = get - end - - list_item = build_list_item(margin + indent, data) - - list << list_item if list_item - else - unget - break - end - end - - p :list_end => margin if @debug - - return nil if list.empty? - - list - end - - ## - # Builds a ListItem that is flush to +indent+ with type +item_type+ - - def build_list_item indent, item_type = nil - p :list_item_start => [indent, item_type] if @debug - - list_item = RDoc::Markup::ListItem.new item_type - - until @tokens.empty? do - type, data, column = get - - if column < indent and - not type == :NEWLINE and - (type != :INDENT or data < indent) then - unget - break - end - - case type - when :INDENT then - unget - list_item.push(*parse(indent)) - when :TEXT then - unget - list_item << build_paragraph(indent) - when :HEADER then - list_item << build_heading(data) - when :NEWLINE then - list_item << RDoc::Markup::BlankLine.new - when *LIST_TOKENS then - unget - list_item << build_list(column) - else - raise ParseError, "Unhandled token #{@current_token.inspect}" - end - end - - p :list_item_end => [indent, item_type] if @debug - - return nil if list_item.empty? - - list_item.parts.shift if - RDoc::Markup::BlankLine === list_item.parts.first and - list_item.length > 1 - - list_item - end - - ## - # Builds a Paragraph that is flush to +margin+ - - def build_paragraph margin - p :paragraph_start => margin if @debug - - paragraph = RDoc::Markup::Paragraph.new - - until @tokens.empty? do - type, data, column, = get - - case type - when :INDENT then - next if data == margin and peek_token[0] == :TEXT - - unget - break - when :TEXT then - if column != margin then - unget - break - end - - paragraph << data - skip :NEWLINE - else - unget - break - end - end - - p :paragraph_end => margin if @debug - - paragraph - end - - ## - # Builds a Verbatim that is flush to +margin+ - - def build_verbatim margin - p :verbatim_begin => margin if @debug - verbatim = RDoc::Markup::Verbatim.new - - until @tokens.empty? do - type, data, column, = get - - case type - when :INDENT then - if margin >= data then - unget - break - end - - indent = data - margin - - verbatim << ' ' * indent - when :HEADER then - verbatim << '=' * data - - _, _, peek_column, = peek_token - peek_column ||= column + data - verbatim << ' ' * (peek_column - column - data) - when :RULE then - width = 2 + data - verbatim << '-' * width - - _, _, peek_column, = peek_token - peek_column ||= column + data + 2 - verbatim << ' ' * (peek_column - column - width) - when :TEXT then - verbatim << data - when *LIST_TOKENS then - if column <= margin then - unget - break - end - - list_marker = case type - when :BULLET then '*' - when :LABEL then "[#{data}]" - when :LALPHA, :NUMBER, :UALPHA then "#{data}." - when :NOTE then "#{data}::" - end - - verbatim << list_marker - - _, data, = get - - verbatim << ' ' * (data - list_marker.length) - when :NEWLINE then - verbatim << data - break unless [:INDENT, :NEWLINE].include? peek_token[0] - else - unget - break - end - end - - verbatim.normalize - - p :verbatim_end => margin if @debug - - verbatim - end - - ## - # Pulls the next token from the stream. - - def get - @current_token = @tokens.shift - p :get => @current_token if @debug - @current_token - end - - ## - # Parses the tokens into a Document - - def parse indent = 0 - p :parse_start => indent if @debug - - document = [] - - until @tokens.empty? do - type, data, column, = get - - if type != :INDENT and column < indent then - unget - break - end - - case type - when :HEADER then - document << build_heading(data) - when :INDENT then - if indent > data then - unget - break - elsif indent == data then - next - end - - unget - document << build_verbatim(indent) - when :NEWLINE then - document << RDoc::Markup::BlankLine.new - skip :NEWLINE, false - when :RULE then - document << RDoc::Markup::Rule.new(data) - skip :NEWLINE - when :TEXT then - unget - document << build_paragraph(indent) - - # we're done with this paragraph (indent mismatch) - break if peek_token[0] == :TEXT - when *LIST_TOKENS then - unget - - list = build_list(indent) - - document << list if list - - # we're done with this list (indent mismatch) - break if LIST_TOKENS.include? peek_token.first and indent > 0 - else - type, data, column, line = @current_token - raise ParseError, - "Unhandled token #{type} (#{data.inspect}) at #{line}:#{column}" - end - end - - p :parse_end => indent if @debug - - document - end - - ## - # Returns the next token on the stream without modifying the stream - - def peek_token - token = @tokens.first || [] - p :peek => token if @debug - token - end - - ## - # Skips a token of +token_type+, optionally raising an error. - - def skip token_type, error = true - type, = get - - return unless type # end of stream - - return @current_token if token_type == type - - unget - - raise ParseError, "expected #{token_type} got #{@current_token.inspect}" if - error - end - - ## - # Consumes tokens until NEWLINE and turns them back into text - - def text - text = '' - - loop do - type, data, = get - - text << case type - when :BULLET then - _, space, = get # SPACE - "*#{' ' * (space - 1)}" - when :LABEL then - _, space, = get # SPACE - "[#{data}]#{' ' * (space - data.length - 2)}" - when :LALPHA, :NUMBER, :UALPHA then - _, space, = get # SPACE - "#{data}.#{' ' * (space - 2)}" - when :NOTE then - _, space = get # SPACE - "#{data}::#{' ' * (space - data.length - 2)}" - when :TEXT then - data - when :NEWLINE then - unget - break - when nil then - break - else - raise ParseError, "unhandled token #{@current_token.inspect}" - end - end - - text - end - - ## - # Calculates the column and line of the current token based on +offset+. - - def token_pos offset - [offset - @line_pos, @line] - end - - ## - # Turns text +input+ into a stream of tokens - - def tokenize input - s = StringScanner.new input - - @line = 0 - @line_pos = 0 - - until s.eos? do - pos = s.pos - - @tokens << case - when s.scan(/\r?\n/) then - token = [:NEWLINE, s.matched, *token_pos(pos)] - @line_pos = s.pos - @line += 1 - token - when s.scan(/ +/) then - [:INDENT, s.matched_size, *token_pos(pos)] - when s.scan(/(=+)\s*/) then - level = s[1].length - level = 6 if level > 6 - @tokens << [:HEADER, level, *token_pos(pos)] - - pos = s.pos - s.scan(/.*/) - [:TEXT, s.matched, *token_pos(pos)] - when s.scan(/^(-{3,}) *$/) then - [:RULE, s[1].length - 2, *token_pos(pos)] - when s.scan(/([*-])\s+/) then - @tokens << [:BULLET, :BULLET, *token_pos(pos)] - [:SPACE, s.matched_size, *token_pos(pos)] - when s.scan(/([a-z]|\d+)\.[ \t]+\S/i) then - list_label = s[1] - width = s.matched_size - 1 - - s.pos -= 1 # unget \S - - list_type = case list_label - when /[a-z]/ then :LALPHA - when /[A-Z]/ then :UALPHA - when /\d/ then :NUMBER - else - raise ParseError, "BUG token #{list_label}" - end - - @tokens << [list_type, list_label, *token_pos(pos)] - [:SPACE, width, *token_pos(pos)] - when s.scan(/\[(.*?)\]( +|$)/) then - @tokens << [:LABEL, s[1], *token_pos(pos)] - [:SPACE, s.matched_size, *token_pos(pos)] - when s.scan(/(.*?)::( +|$)/) then - @tokens << [:NOTE, s[1], *token_pos(pos)] - [:SPACE, s.matched_size, *token_pos(pos)] - else s.scan(/.*/) - [:TEXT, s.matched, *token_pos(pos)] - end - end - - self - end - - ## - # Returns the current token or +token+ to the token stream - - def unget token = @current_token - p :unget => token if @debug - raise Error, 'too many #ungets' if token == @tokens.first - @tokens.unshift token if token - end - -end - -require 'rdoc/markup/blank_line' -require 'rdoc/markup/document' -require 'rdoc/markup/heading' -require 'rdoc/markup/list' -require 'rdoc/markup/list_item' -require 'rdoc/markup/raw' -require 'rdoc/markup/paragraph' -require 'rdoc/markup/rule' -require 'rdoc/markup/verbatim' - diff --git a/lib/rdoc/markup/preprocess.rb b/lib/rdoc/markup/preprocess.rb deleted file mode 100644 index cefb498916..0000000000 --- a/lib/rdoc/markup/preprocess.rb +++ /dev/null @@ -1,130 +0,0 @@ -require 'rdoc/markup' - -## -# Handle common directives that can occur in a block of text: -# -# : include : filename -# -# RDoc plugin authors can register additional directives to be handled through -# RDoc::Markup::PreProcess::register - -class RDoc::Markup::PreProcess - - @registered = {} - - ## - # Registers +directive+ as one handled by RDoc. If a block is given the - # directive will be replaced by the result of the block, otherwise the - # directive will be removed from the processed text. - - def self.register directive, &block - @registered[directive] = block - end - - ## - # Registered directives - - def self.registered - @registered - end - - ## - # Creates a new pre-processor for +input_file_name+ that will look for - # included files in +include_path+ - - def initialize(input_file_name, include_path) - @input_file_name = input_file_name - @include_path = include_path - end - - ## - # Look for directives in a chunk of +text+. - # - # Options that we don't handle are yielded. If the block returns false the - # directive is restored to the text. If the block returns nil or no block - # was given the directive is handled according to the registered directives. - # If a String was returned the directive is replaced with the string. - # - # If no matching directive was registered the directive is restored to the - # text. - # - # If +code_object+ is given and the param is set as metadata on the - # +code_object+. See RDoc::CodeObject#metadata - - def handle text, code_object = nil - text.gsub!(/^([ \t]*#?[ \t]*):(\w+):([ \t]*)(.+)?\n/) do - next $& if $3.empty? and $4 and $4[0, 1] == ':' - - prefix = $1 - directive = $2.downcase - param = $4 - - case directive - when 'include' then - filename = param.split[0] - include_file filename, prefix - - else - result = yield directive, param if block_given? - - case result - when nil then - code_object.metadata[directive] = param if code_object - if RDoc::Markup::PreProcess.registered.include? directive then - handler = RDoc::Markup::PreProcess.registered[directive] - result = handler.call directive, param if handler - else - result = "#{prefix}:#{directive}: #{param}\n" - end - when false then - result = "#{prefix}:#{directive}: #{param}\n" - end - - result - end - end - - text - end - - ## - # Include a file, indenting it correctly. - - def include_file(name, indent) - if full_name = find_include_file(name) then - content = if defined?(Encoding) then - File.binread full_name - else - File.read full_name - end - # HACK determine content type and force encoding - content = content.sub(/\A# .*coding[=:].*$/, '').lstrip - - # strip leading '#'s, but only if all lines start with them - if content =~ /^[^#]/ then - content.gsub(/^/, indent) - else - content.gsub(/^#?/, indent) - end - else - warn "Couldn't find file to include '#{name}' from #{@input_file_name}" - '' - end - end - - ## - # Look for the given file in the directory containing the current file, - # and then in each of the directories specified in the RDOC_INCLUDE path - - def find_include_file(name) - to_search = [File.dirname(@input_file_name)].concat @include_path - to_search.each do |dir| - full_name = File.join(dir, name) - stat = File.stat(full_name) rescue next - return full_name if stat.readable? - end - nil - end - -end - diff --git a/lib/rdoc/markup/raw.rb b/lib/rdoc/markup/raw.rb deleted file mode 100644 index 1124be7cc8..0000000000 --- a/lib/rdoc/markup/raw.rb +++ /dev/null @@ -1,65 +0,0 @@ -## -# A section of text that is added to the output document as-is - -class RDoc::Markup::Raw - - ## - # The component parts of the list - - attr_reader :parts - - ## - # Creates a new Raw containing +parts+ - - def initialize *parts - @parts = [] - @parts.push(*parts) - end - - ## - # Appends +text+ - - def << text - @parts << text - end - - def == other # :nodoc: - self.class == other.class and text == other.text - end - - def accept visitor - visitor.accept_raw self - end - - ## - # Appends +other+'s parts - - def merge other - @parts.push(*other.parts) - end - - def pretty_print q # :nodoc: - self.class.name =~ /.*::(\w{4})/i - - q.group 2, "[#{$1.downcase}: ", ']' do - q.seplist @parts do |part| - q.pp part - end - end - end - - ## - # Appends +texts+ onto this Paragraph - - def push *texts - self.parts.push(*texts) - end - - ## - # The raw text - - def text - @parts.join ' ' - end - -end diff --git a/lib/rdoc/markup/rule.rb b/lib/rdoc/markup/rule.rb deleted file mode 100644 index 4fcd040d2b..0000000000 --- a/lib/rdoc/markup/rule.rb +++ /dev/null @@ -1,17 +0,0 @@ -## -# A horizontal rule with a weight - -class RDoc::Markup::Rule < Struct.new :weight - - def accept visitor - visitor.accept_rule self - end - - def pretty_print q # :nodoc: - q.group 2, '[rule:', ']' do - q.pp weight - end - end - -end - diff --git a/lib/rdoc/markup/to_ansi.rb b/lib/rdoc/markup/to_ansi.rb deleted file mode 100644 index 9a5be8babb..0000000000 --- a/lib/rdoc/markup/to_ansi.rb +++ /dev/null @@ -1,72 +0,0 @@ -require 'rdoc/markup/inline' - -## -# Outputs RDoc markup with vibrant ANSI color! - -class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc - - def initialize - super - - @headings.clear - @headings[1] = ["\e[1;32m", "\e[m"] - @headings[2] = ["\e[4;32m", "\e[m"] - @headings[3] = ["\e[32m", "\e[m"] - end - - ## - # Maps attributes to ANSI sequences - - def init_tags - add_tag :BOLD, "\e[1m", "\e[m" - add_tag :TT, "\e[7m", "\e[m" - add_tag :EM, "\e[4m", "\e[m" - end - - def accept_list_item_end list_item - width = case @list_type.last - when :BULLET then - 2 - when :NOTE, :LABEL then - @res << "\n" - 2 - else - bullet = @list_index.last.to_s - @list_index[-1] = @list_index.last.succ - bullet.length + 2 - end - - @indent -= width - end - - def accept_list_item_start list_item - bullet = case @list_type.last - when :BULLET then - '*' - when :NOTE, :LABEL then - attributes(list_item.label) + ":\n" - else - @list_index.last.to_s + '.' - end - - case @list_type.last - when :NOTE, :LABEL then - @indent += 2 - @prefix = bullet + (' ' * @indent) - else - @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) - - width = bullet.gsub(/\e\[[\d;]*m/, '').length + 1 - - @indent += width - end - end - - def start_accepting - super - - @res = ["\e[0m"] - end - -end - diff --git a/lib/rdoc/markup/to_bs.rb b/lib/rdoc/markup/to_bs.rb deleted file mode 100644 index e7af129824..0000000000 --- a/lib/rdoc/markup/to_bs.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'rdoc/markup/inline' - -## -# Outputs RDoc markup with hot backspace action! You will probably need a -# pager to use this output format. -# -# This formatter won't work on 1.8.6 because it lacks String#chars. - -class RDoc::Markup::ToBs < RDoc::Markup::ToRdoc - - def initialize - super - - @in_b = false - @in_em = false - end - - ## - # Sets a flag that is picked up by #annotate to do the right thing in - # #convert_string - - def init_tags - add_tag :BOLD, '+b', '-b' - add_tag :EM, '+_', '-_' - end - - def accept_heading heading - use_prefix or @res << ' ' * @indent - @res << @headings[heading.level][0] - @in_b = true - @res << attributes(heading.text) - @in_b = false - @res << @headings[heading.level][1] - @res << "\n" - end - - ## - # Turns on or off special handling for +convert_string+ - - def annotate tag - case tag - when '+b' then @in_b = true - when '-b' then @in_b = false - when '+_' then @in_em = true - when '-_' then @in_em = false - end - - '' - end - - ## - # Calls convert_string on the result of convert_special - - def convert_special special - convert_string super - end - - ## - # Adds bold or underline mixed with backspaces - - def convert_string string - return string unless string.respond_to? :chars # your ruby is lame - return string unless @in_b or @in_em - chars = if @in_b then - string.chars.map do |char| "#{char}\b#{char}" end - elsif @in_em then - string.chars.map do |char| "_\b#{char}" end - end - - chars.join - end - -end - diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb deleted file mode 100644 index 74e3137eb2..0000000000 --- a/lib/rdoc/markup/to_html.rb +++ /dev/null @@ -1,344 +0,0 @@ -require 'rdoc/markup/formatter' -require 'rdoc/markup/inline' - -require 'cgi' - -## -# Outputs RDoc markup as HTML - -class RDoc::Markup::ToHtml < RDoc::Markup::Formatter - - ## - # Maps RDoc::Markup::Parser::LIST_TOKENS types to HTML tags - - LIST_TYPE_TO_HTML = { - :BULLET => ['<ul>', '</ul>'], - :LABEL => ['<dl>', '</dl>'], - :LALPHA => ['<ol style="display: lower-alpha">', '</ol>'], - :NOTE => ['<table>', '</table>'], - :NUMBER => ['<ol>', '</ol>'], - :UALPHA => ['<ol style="display: upper-alpha">', '</ol>'], - } - - attr_reader :res # :nodoc: - attr_reader :in_list_entry # :nodoc: - attr_reader :list # :nodoc: - - ## - # Converts a target url to one that is relative to a given path - - def self.gen_relative_url(path, target) - from = File.dirname path - to, to_file = File.split target - - from = from.split "/" - to = to.split "/" - - from.delete '.' - to.delete '.' - - while from.size > 0 and to.size > 0 and from[0] == to[0] do - from.shift - to.shift - end - - from.fill ".." - from.concat to - from << to_file - File.join(*from) - end - - def initialize - super - - @th = nil - @in_list_entry = nil - @list = nil - - # external hyperlinks - @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK) - - # and links of the form <text>[<url>] - @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\.\S+?\])/, :TIDYLINK) - - init_tags - end - - ## - # Maps attributes to HTML tags - - def init_tags - add_tag :BOLD, "<b>", "</b>" - add_tag :TT, "<tt>", "</tt>" - add_tag :EM, "<em>", "</em>" - end - - ## - # Generate a hyperlink for url, labeled with text. Handle the - # special cases for img: and link: described under handle_special_HYPERLINK - - def gen_url(url, text) - if url =~ /([A-Za-z]+):(.*)/ then - type = $1 - path = $2 - else - type = "http" - path = url - url = "http://#{url}" - end - - if type == "link" then - url = if path[0, 1] == '#' then # is this meaningful? - path - else - self.class.gen_relative_url @from_path, path - end - end - - if (type == "http" or type == "link") and - url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then - "<img src=\"#{url}\" />" - else - "<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>" - end - end - - ## - # And we're invoked with a potential external hyperlink mailto: - # just gets inserted. http: links are checked to see if they - # reference an image. If so, that image gets inserted using an - # <img> tag. Otherwise a conventional <a href> is used. We also - # support a special type of hyperlink, link:, which is a reference - # to a local file whose path is relative to the --op directory. - - def handle_special_HYPERLINK(special) - url = special.text - gen_url url, url - end - - ## - # Here's a hypedlink where the label is different to the URL - # <label>[url] or {long label}[url] - - def handle_special_TIDYLINK(special) - text = special.text - - return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/ - - label = $1 - url = $2 - gen_url url, label - end - - ## - # This is a higher speed (if messier) version of wrap - - def wrap(txt, line_len = 76) - res = [] - sp = 0 - ep = txt.length - - while sp < ep - # scan back for a space - p = sp + line_len - 1 - if p >= ep - p = ep - else - while p > sp and txt[p] != ?\s - p -= 1 - end - if p <= sp - p = sp + line_len - while p < ep and txt[p] != ?\s - p += 1 - end - end - end - res << txt[sp...p] << "\n" - sp = p - sp += 1 while sp < ep and txt[sp] == ?\s - end - - res.join - end - - ## - # :section: Visitor - - def start_accepting - @res = [] - @in_list_entry = [] - @list = [] - end - - def end_accepting - @res.join - end - - def accept_paragraph(paragraph) - @res << annotate("<p>") + "\n" - @res << wrap(convert_flow(@am.flow(paragraph.text))) - @res << annotate("</p>") + "\n" - end - - def accept_verbatim(verbatim) - @res << annotate("<pre>") << "\n" - @res << CGI.escapeHTML(verbatim.text) - @res << annotate("</pre>") << "\n" - end - - def accept_rule(rule) - size = rule.weight - size = 10 if size > 10 - @res << "<hr style=\"height: #{size}px\"></hr>" - end - - def accept_list_start(list) - @list << list.type - @res << html_list_name(list.type, true) << "\n" - @in_list_entry.push false - end - - def accept_list_end(list) - @list.pop - if tag = @in_list_entry.pop - @res << annotate(tag) << "\n" - end - @res << html_list_name(list.type, false) << "\n" - end - - def accept_list_item_start(list_item) - if tag = @in_list_entry.last - @res << annotate(tag) << "\n" - end - - @res << list_item_start(list_item, @list.last) - end - - def accept_list_item_end(list_item) - @in_list_entry[-1] = list_end_for(@list.last) - end - - def accept_blank_line(blank_line) - # @res << annotate("<p />") << "\n" - end - - def accept_heading(heading) - @res << convert_heading(heading.level, @am.flow(heading.text)) - end - - def accept_raw raw - @res << raw.parts.join("\n") - end - - private - - ## - # Converts string +item+ - - def convert_string(item) - in_tt? ? convert_string_simple(item) : convert_string_fancy(item) - end - - ## - # Escapes HTML in +item+ - - def convert_string_simple(item) - CGI.escapeHTML item - end - - ## - # Converts ampersand, dashes, elipsis, quotes, copyright and registered - # trademark symbols to HTML escaped Unicode. - - def convert_string_fancy(item) - # convert ampersand before doing anything else - item.gsub(/&/, '&'). - - # convert -- to em-dash, (-- to en-dash) - gsub(/---?/, '—'). #gsub(/--/, '–'). - - # convert ... to elipsis (and make sure .... becomes .<elipsis>) - gsub(/\.\.\.\./, '.…').gsub(/\.\.\./, '…'). - - # convert single closing quote - gsub(%r{([^ \t\r\n\[\{\(])\'}, '\1’'). # } - gsub(%r{\'(?=\W|s\b)}, '’'). - - # convert single opening quote - gsub(/'/, '‘'). - - # convert double closing quote - gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}, '\1”'). # } - - # convert double opening quote - gsub(/"/, '“'). - - # convert copyright - gsub(/\(c\)/, '©'). - - # convert registered trademark - gsub(/\(r\)/, '®') - end - - ## - # Converts headings to hN elements - - def convert_heading(level, flow) - [annotate("<h#{level}>"), - convert_flow(flow), - annotate("</h#{level}>\n")].join - end - - ## - # Determins 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 - annotate tags[open_tag ? 0 : 1] - end - - ## - # Starts a list item - - def list_item_start(list_item, list_type) - case list_type - when :BULLET, :LALPHA, :NUMBER, :UALPHA then - annotate("<li>") - - when :LABEL then - annotate("<dt>") + - convert_flow(@am.flow(list_item.label)) + - annotate("</dt>") + - annotate("<dd>") - - when :NOTE then - annotate("<tr>") + - annotate("<td valign=\"top\">") + - convert_flow(@am.flow(list_item.label)) + - annotate("</td>") + - annotate("<td>") - else - raise RDoc::Error, "Invalid list type: #{list_type.inspect}" - end - end - - ## - # Ends a list item - - def list_end_for(list_type) - case list_type - when :BULLET, :LALPHA, :NUMBER, :UALPHA then - "</li>" - when :LABEL then - "</dd>" - when :NOTE then - "</td></tr>" - else - raise RDoc::Error, "Invalid list type: #{list_type.inspect}" - end - end - -end - diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb deleted file mode 100644 index 44e71486fb..0000000000 --- a/lib/rdoc/markup/to_html_crossref.rb +++ /dev/null @@ -1,148 +0,0 @@ -require 'rdoc/markup/to_html' - -## -# Subclass of the RDoc::Markup::ToHtml class that supports looking up words -# from a context. Those that are found will be hyperlinked. - -class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml - - ## - # Regular expression to match class references - # - # 1) There can be a '\' in front of text to suppress any cross-references - # 2) There can be a '::' in front of class names to reference from the - # top-level namespace. - # 3) The method can be followed by parenthesis - - CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)' - - ## - # Regular expression to match method references. - # - # See CLASS_REGEXP_STR - - METHOD_REGEXP_STR = '([a-z]\w*[!?=]?)(?:\([\w.+*/=<>-]*\))?' - - ## - # Regular expressions matching text that should potentially have - # cross-reference links generated are passed to add_special. Note that - # these expressions are meant to pick up text for which cross-references - # have been suppressed, since the suppression characters are removed by the - # code that is triggered. - - CROSSREF_REGEXP = /( - # A::B::C.meth - #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} - - # Stand-alone method (proceeded by a #) - | \\?\##{METHOD_REGEXP_STR} - - # Stand-alone method (proceeded by ::) - | ::#{METHOD_REGEXP_STR} - - # A::B::C - # The stuff after CLASS_REGEXP_STR is a - # nasty hack. CLASS_REGEXP_STR unfortunately matches - # words like dog and cat (these are legal "class" - # names in Fortran 95). When a word is flagged as a - # potential cross-reference, limitations in the markup - # engine suppress other processing, such as typesetting. - # This is particularly noticeable for contractions. - # In order that words like "can't" not - # be flagged as potential cross-references, only - # flag potential class cross-references if the character - # after the cross-referece is a space or sentence - # punctuation. - | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;]|\z) - - # Things that look like filenames - # The key thing is that there must be at least - # one special character (period, slash, or - # underscore). - | (?:\.\.\/)*[-\/\w]+[_\/\.][-\w\/\.]+ - - # Things that have markup suppressed - | \\[^\s] - )/x - - ## - # RDoc::CodeObject for generating references - - attr_accessor :context - - ## - # Creates a new crossref resolver that generates links relative to +context+ - # which lives at +from_path+ in the generated files. '#' characters on - # references are removed unless +show_hash+ is true. - - def initialize(from_path, context, show_hash) - raise ArgumentError, 'from_path cannot be nil' if from_path.nil? - super() - - @markup.add_special(CROSSREF_REGEXP, :CROSSREF) - - @from_path = from_path - @context = context - @show_hash = show_hash - - @seen = {} - end - - ## - # We're invoked when any text matches the CROSSREF pattern. If we find the - # corresponding reference, generate a hyperlink. If the name we're looking - # for contains no punctuation, we look for it up the module/class chain. - # For example, HyperlinkHtml is found, even without the Generator:: prefix, - # because we look for it in module Generator first. - - def handle_special_CROSSREF(special) - name = special.text - - # This ensures that words entirely consisting of lowercase letters will - # not have cross-references generated (to suppress lots of erroneous - # cross-references to "new" in text, for instance) - return name if name =~ /\A[a-z]*\z/ - - return @seen[name] if @seen.include? name - - lookup = name - - name = name[0, 1] unless @show_hash if name[0, 1] == '#' - - # Find class, module, or method in class or module. - # - # Do not, however, use an if/elsif/else chain to do so. Instead, test - # each possible pattern until one matches. The reason for this is that a - # string like "YAML.txt" could be the txt() class method of class YAML (in - # which case it would match the first pattern, which splits the string - # into container and method components and looks up both) or a filename - # (in which case it would match the last pattern, which just checks - # whether the string as a whole is a known symbol). - - if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/ =~ lookup then - container = $1 - type = $2 - type = '#' if type == '.' - method = "#{type}#{$3}" - ref = @context.find_symbol container, method - end - - ref = @context.find_symbol lookup unless ref - - out = if lookup == '\\' then - lookup - elsif lookup =~ /^\\/ then - $' - elsif ref and ref.document_self then - "<a href=\"#{ref.as_href @from_path}\">#{name}</a>" - else - name - end - - @seen[name] = out - - out - end - -end - diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb deleted file mode 100644 index 867715bb1e..0000000000 --- a/lib/rdoc/markup/to_rdoc.rb +++ /dev/null @@ -1,247 +0,0 @@ -require 'rdoc/markup/inline' - -## -# Outputs RDoc markup as RDoc markup! (mostly) - -class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter - - attr_accessor :indent - attr_reader :list_index - attr_reader :list_type - attr_reader :list_width - attr_reader :prefix - attr_reader :res - - def initialize - super - - @markup.add_special(/\\[^\s]/, :SUPPRESSED_CROSSREF) - - @width = 78 - @prefix = '' - - init_tags - - @headings = {} - @headings.default = [] - - @headings[1] = ['= ', ''] - @headings[2] = ['== ', ''] - @headings[3] = ['=== ', ''] - @headings[4] = ['==== ', ''] - @headings[5] = ['===== ', ''] - @headings[6] = ['====== ', ''] - end - - ## - # Maps attributes to ANSI sequences - - def init_tags - add_tag :BOLD, "<b>", "</b>" - add_tag :TT, "<tt>", "</tt>" - add_tag :EM, "<em>", "</em>" - end - - def accept_blank_line blank_line - @res << "\n" - end - - def accept_heading heading - use_prefix or @res << ' ' * @indent - @res << @headings[heading.level][0] - @res << attributes(heading.text) - @res << @headings[heading.level][1] - @res << "\n" - end - - def accept_list_end list - @list_index.pop - @list_type.pop - @list_width.pop - end - - def accept_list_item_end list_item - width = case @list_type.last - when :BULLET then - 2 - when :NOTE, :LABEL then - @res << "\n" - 2 - else - bullet = @list_index.last.to_s - @list_index[-1] = @list_index.last.succ - bullet.length + 2 - end - - @indent -= width - end - - def accept_list_item_start list_item - bullet = case @list_type.last - when :BULLET then - '*' - when :NOTE, :LABEL then - attributes(list_item.label) + ":\n" - else - @list_index.last.to_s + '.' - end - - case @list_type.last - when :NOTE, :LABEL then - @indent += 2 - @prefix = bullet + (' ' * @indent) - else - @prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1) - - width = bullet.length + 1 - - @indent += width - end - end - - def accept_list_start list - case list.type - when :BULLET then - @list_index << nil - @list_width << 1 - when :LABEL, :NOTE then - @list_index << nil - @list_width << 2 - when :LALPHA then - @list_index << 'a' - @list_width << list.items.length.to_s.length - when :NUMBER then - @list_index << 1 - @list_width << list.items.length.to_s.length - when :UALPHA then - @list_index << 'A' - @list_width << list.items.length.to_s.length - else - raise RDoc::Error, "invalid list type #{list.type}" - end - - @list_type << list.type - end - - def accept_paragraph paragraph - wrap attributes(paragraph.text) - end - - def accept_raw raw - @res << raw.parts.join("\n") - end - - def accept_rule rule - use_prefix or @res << ' ' * @indent - @res << '-' * (@width - @indent) - @res << "\n" - end - - ## - # Outputs +verbatim+ flush left and indented 2 columns - - def accept_verbatim verbatim - indent = ' ' * (@indent + 2) - - lines = [] - current_line = [] - - # split into lines - verbatim.parts.each do |part| - current_line << part - - if part == "\n" then - lines << current_line - current_line = [] - end - end - - lines << current_line unless current_line.empty? - - # calculate margin - indented = lines.select { |line| line != ["\n"] } - margin = indented.map { |line| line.first.length }.min - - # flush left - indented.each { |line| line[0][0...margin] = '' } - - # output - use_prefix or @res << indent # verbatim is unlikely to have prefix - @res << lines.shift.join - - lines.each do |line| - @res << indent unless line == ["\n"] - @res << line.join - end - - @res << "\n" - end - - def attributes text - flow = @am.flow text.dup - convert_flow flow - end - - def end_accepting - @res.join - end - - def handle_special_SUPPRESSED_CROSSREF special - special.text.sub(/\\/, '') - end - - def start_accepting - @res = [""] - @indent = 0 - @prefix = nil - - @list_index = [] - @list_type = [] - @list_width = [] - end - - def use_prefix - prefix = @prefix - @prefix = nil - @res << prefix if prefix - - prefix - end - - def wrap text - return unless text && !text.empty? - - text_len = @width - @indent - - text_len = 20 if text_len < 20 - - re = /^(.{0,#{text_len}})[ \n]/ - next_prefix = ' ' * @indent - - prefix = @prefix || next_prefix - @prefix = nil - - @res << prefix - - while text.length > text_len - if text =~ re then - @res << $1 - text.slice!(0, $&.length) - else - @res << text.slice!(0, text_len) - end - - @res << "\n" << next_prefix - end - - if text.empty? then - @res.pop - @res.pop - else - @res << text - @res << "\n" - end - end - -end - diff --git a/lib/rdoc/markup/to_test.rb b/lib/rdoc/markup/to_test.rb deleted file mode 100644 index 0afdb96a18..0000000000 --- a/lib/rdoc/markup/to_test.rb +++ /dev/null @@ -1,64 +0,0 @@ -require 'rdoc/markup' -require 'rdoc/markup/formatter' - -## -# This Markup outputter is used for testing purposes. - -class RDoc::Markup::ToTest < RDoc::Markup::Formatter - - ## - # :section: Visitor - - def start_accepting - @res = [] - @list = [] - end - - def end_accepting - @res - end - - def accept_paragraph(paragraph) - @res << paragraph.text - end - - def accept_verbatim(verbatim) - @res << verbatim.text - end - - def accept_list_start(list) - @list << case list.type - when :BULLET then - '*' - when :NUMBER then - '1' - else - list.type - end - end - - def accept_list_end(list) - @list.pop - end - - def accept_list_item_start(list_item) - @res << "#{' ' * (@list.size - 1)}#{@list.last}: " - end - - def accept_list_item_end(list_item) - end - - def accept_blank_line(blank_line) - @res << "\n" - end - - def accept_heading(heading) - @res << "#{'=' * heading.level} #{heading.text}" - end - - def accept_rule(rule) - @res << '-' * rule.weight - end - -end - diff --git a/lib/rdoc/markup/verbatim.rb b/lib/rdoc/markup/verbatim.rb deleted file mode 100644 index c684d78765..0000000000 --- a/lib/rdoc/markup/verbatim.rb +++ /dev/null @@ -1,42 +0,0 @@ -## -# A section of verbatim text - -class RDoc::Markup::Verbatim < RDoc::Markup::Raw - - def accept visitor - visitor.accept_verbatim self - end - - ## - # Collapses 3+ newlines into two newlines - - def normalize - parts = [] - - newlines = 0 - - @parts.each do |part| - case part - when /\n/ then - newlines += 1 - parts << part if newlines <= 2 - else - newlines = 0 - parts << part - end - end - - parts.slice!(-1) if parts[-2..-1] == ["\n", "\n"] - - @parts = parts - end - - ## - # The text of the section - - def text - @parts.join - end - -end - |
