From 89b601d176a64f1293a3d3b5195b6735cbf880af Mon Sep 17 00:00:00 2001 From: drbrain Date: Sun, 31 Jul 2011 00:19:00 +0000 Subject: * lib/rdoc: Update to RDoc 3.9. Fixed `ri []`, stopdoc creating an object reference, nodoc for class aliases, verbatim === lines. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32767 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/rdoc/markup/document.rb | 16 ++- lib/rdoc/markup/formatter.rb | 4 + lib/rdoc/markup/parser.rb | 18 ++-- lib/rdoc/markup/pre_process.rb | 137 ++++++++++++++++++------ lib/rdoc/markup/to_html.rb | 13 +-- lib/rdoc/markup/to_html_crossref.rb | 208 +++++++++++------------------------- 6 files changed, 201 insertions(+), 195 deletions(-) (limited to 'lib/rdoc/markup') diff --git a/lib/rdoc/markup/document.rb b/lib/rdoc/markup/document.rb index 6fbef33ae3..7077f357d3 100644 --- a/lib/rdoc/markup/document.rb +++ b/lib/rdoc/markup/document.rb @@ -71,9 +71,7 @@ class RDoc::Markup::Document # Does this document have no parts? def empty? - @parts.empty? or - (@parts.length == 1 and RDoc::Markup::Document === @parts.first and - @parts.first.empty?) + @parts.empty? or (@parts.length == 1 and merged? and @parts.first.empty?) end ## @@ -85,6 +83,11 @@ class RDoc::Markup::Document # The information in +other+ is preferred over the receiver def merge other + if empty? then + @parts = other.parts + return self + end + other.parts.each do |other_part| self.parts.delete_if do |self_part| self_part.file and self_part.file == other_part.file @@ -96,6 +99,13 @@ class RDoc::Markup::Document self end + ## + # Does this Document contain other Documents? + + def merged? + RDoc::Markup::Document === @parts.first + end + def pretty_print q # :nodoc: start = @file ? "[doc (#{@file}): " : '[doc: ' diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb index b6e12f82e7..bf904bba68 100644 --- a/lib/rdoc/markup/formatter.rb +++ b/lib/rdoc/markup/formatter.rb @@ -4,6 +4,10 @@ require 'rdoc/markup' # Base class for RDoc markup formatters # # Formatters use a visitor pattern to convert content into output. +# +# If you'd like to write your own Formatter use +# RDoc::Markup::FormatterTestCase. If you're writing a text-output formatter +# use RDoc::Markup::TextFormatterTestCase which provides extra test cases. class RDoc::Markup::Formatter diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb index 68616d7787..3ab72ee5d5 100644 --- a/lib/rdoc/markup/parser.rb +++ b/lib/rdoc/markup/parser.rb @@ -405,13 +405,19 @@ class RDoc::Markup::Parser @line += 1 token # === text => :HEADER then :TEXT - when s.scan(/(=+)\s*/) then + 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.sub(/\r$/, ''), *token_pos(pos)] + header = [:HEADER, level, *token_pos(pos)] + + if s[2] =~ /^\r?\n/ then + s.pos -= s[2].length + header + else + pos = s.pos + s.scan(/.*/) + @tokens << header + [:TEXT, s.matched.sub(/\r$/, ''), *token_pos(pos)] + end # --- (at least 3) and nothing else on the line => :RULE when s.scan(/(-{3,}) *$/) then [:RULE, s[1].length - 2, *token_pos(pos)] diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb index 03f919aa0e..53e8e38ec1 100644 --- a/lib/rdoc/markup/pre_process.rb +++ b/lib/rdoc/markup/pre_process.rb @@ -13,6 +13,8 @@ require 'rdoc/encoding' class RDoc::Markup::PreProcess + attr_accessor :options + @registered = {} ## @@ -38,6 +40,7 @@ class RDoc::Markup::PreProcess def initialize(input_file_name, include_path) @input_file_name = input_file_name @include_path = include_path + @options = nil end ## @@ -54,54 +57,120 @@ class RDoc::Markup::PreProcess # 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 + def handle text, code_object = nil, &block + encoding = if defined?(Encoding) then text.encoding else nil end # regexp helper (square brackets for optional) # $1 $2 $3 $4 $5 # [prefix][\]:directive:[spaces][param]newline - text.gsub!(/^([ \t]*#?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?\n/) do + text.gsub!(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?\n/) do # skip something like ':toto::' next $& if $4.empty? and $5 and $5[0, 1] == ':' # skip if escaped next "#$1:#$3:#$4#$5\n" unless $2.empty? - prefix = $1 - directive = $3.downcase - param = $5 - - case directive - when 'include' then - filename = param.split[0] - encoding = if defined?(Encoding) then text.encoding else nil end - include_file filename, prefix, encoding - when 'category' then - if RDoc::Context === code_object then - section = code_object.add_section param, '' - code_object.temporary_section = section - end + handle_directive $1, $3, $5, code_object, encoding, &block + end + + text + end + + #-- + # When 1.8.7 support is ditched prefix can be defaulted to '' + + def handle_directive prefix, directive, param, code_object = nil, + encoding = nil + blankline = "#{prefix.strip}\n" + directive = directive.downcase + + case directive + when 'arg', 'args' then + return blankline unless code_object + + code_object.params = param + + blankline + when 'category' then + if RDoc::Context === code_object then + section = code_object.add_section param, '' + code_object.temporary_section = section + end + + blankline # ignore category if we're not on an RDoc::Context + when 'doc' then + return blankline unless code_object + code_object.document_self = true + code_object.force_documentation = true + + blankline + when 'enddoc' then + return blankline unless code_object + code_object.done_documenting = true + + blankline + when 'include' then + filename = param.split.first + include_file filename, prefix, encoding + when 'main' then + @options.main_page = param if @options.respond_to? :main_page + + blankline + when 'nodoc' then + return blankline unless code_object + code_object.document_self = nil # notify nodoc + code_object.document_children = param !~ /all/i - '' # ignore category if we're not on an RDoc::Context - 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 + blankline + when 'notnew', 'not_new', 'not-new' then + return blankline unless RDoc::AnyMethod === code_object + + code_object.dont_rename_initialize = true + + blankline + when 'startdoc' then + return blankline unless code_object + + code_object.start_doc + code_object.force_documentation = true + + blankline + when 'stopdoc' then + return blankline unless code_object + + code_object.stop_doc + + blankline + when 'title' then + @options.default_title = param if @options.respond_to? :default_title= + + blankline + when 'yield', 'yields' then + return blankline unless code_object + # remove parameter &block + code_object.params.sub!(/,?\s*&\w+/, '') if code_object.params + + code_object.block_params = param + + blankline + 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 - - result + when false then + result = "#{prefix}:#{directive}: #{param}\n" end - end - text + result + end end ## diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb index b518fbf265..f87aabad6f 100644 --- a/lib/rdoc/markup/to_html.rb +++ b/lib/rdoc/markup/to_html.rb @@ -70,7 +70,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter @list = nil @from_path = '' - # external hyperlinks + # external links @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK) # and links of the form [] @@ -84,7 +84,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter # These methods handle special markup added by RDoc::Markup#add_special. ## - # +special+ is a potential hyperlink. The following schemes are handled: + # +special+ is a potential link. The following schemes are handled: # # mailto::: # Inserted as-is. @@ -97,12 +97,13 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter def handle_special_HYPERLINK(special) url = special.text + gen_url url, url end ## - # This +special+ is a hyperlink where the label is different from the URL - # label[url] or {long label}[url] + # This +special+ is a link where the label is different from the URL + # label[url] or {long label}[url] def handle_special_TIDYLINK(special) text = special.text @@ -232,8 +233,8 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter end ## - # Generate a hyperlink for +url+, labeled with +text+. Handles the special - # cases for img: and link: described under handle_special_HYPERLINK + # Generate a link for +url+, labeled with +text+. Handles the special cases + # for img: and link: described under handle_special_HYPERLINK def gen_url(url, text) if url =~ /([A-Za-z]+):(.*)/ then diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb index aeecc3f4d0..5175b79192 100644 --- a/lib/rdoc/markup/to_html_crossref.rb +++ b/lib/rdoc/markup/to_html_crossref.rb @@ -1,92 +1,19 @@ require 'rdoc/markup/to_html' +require 'rdoc/cross_reference' ## -# Subclass of the RDoc::Markup::ToHtml class that supports looking up words -# from a context. Those that are found will be hyperlinked. +# Subclass of the RDoc::Markup::ToHtml class that supports looking up method +# names, classes, etc to create links. RDoc::CrossReference is used to +# generate those links based on the current context. class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml - ## - # Regular expression to match class references - # - # 1. There can be a '\\' in front of text to suppress the cross-reference - # 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 (not recommended) - - 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 (preceded by a #) - | \\?\##{METHOD_REGEXP_STR} - - # Stand-alone method (preceded 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-reference is a space, sentence - # punctuation, tag start character, or attribute - # marker. - | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;<\000]|\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 - # Don't process things like '\<' in \, though. - # TODO: including < is a hack, not very satisfying. - | \\[^\s<] - )/x - - ## - # Version of CROSSREF_REGEXP used when --hyperlink-all is specified. - - ALL_CROSSREF_REGEXP = /( - # A::B::C.meth - #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} - - # Stand-alone method - | \\?#{METHOD_REGEXP_STR} - - # A::B::C - | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;<\000]|\z) - - # Things that look like filenames - | (?:\.\.\/)*[-\/\w]+[_\/\.][-\w\/\.]+ - - # Things that have markup suppressed - | \\[^\s<] - )/x + # :stopdoc: + ALL_CROSSREF_REGEXP = RDoc::CrossReference::ALL_CROSSREF_REGEXP + CLASS_REGEXP_STR = RDoc::CrossReference::CLASS_REGEXP_STR + CROSSREF_REGEXP = RDoc::CrossReference::CROSSREF_REGEXP + METHOD_REGEXP_STR = RDoc::CrossReference::METHOD_REGEXP_STR + # :startdoc: ## # RDoc::CodeObject for generating references @@ -102,7 +29,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml # 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. Only method names - # preceded by '#' or '::' are hyperlinked, unless +hyperlink_all+ is true. + # preceded by '#' or '::' are linked, unless +hyperlink_all+ is true. def initialize(from_path, context, show_hash, hyperlink_all = false, markup = nil) @@ -111,22 +38,36 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml crossref_re = hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP + @cross_reference = RDoc::CrossReference.new context + @markup.add_special crossref_re, :CROSSREF + @markup.add_special(/rdoc-ref:\S+\w/, :HYPERLINK) - @from_path = from_path - @context = context - @show_hash = show_hash + @from_path = from_path @hyperlink_all = hyperlink_all + @show_hash = show_hash + end + + ## + # Creates a link to the reference +name+ if the name exists. If +text+ is + # given it is used as the link text, otherwise +name+ is used. + + def cross_reference name, text = nil + lookup = name - @seen = {} + name = name[1..-1] unless @show_hash if name[0, 1] == '#' + + text = name unless text + + link lookup, text 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, ToHtml is found, even without the RDoc::Markup:: - # prefix, because we look for it in module Markup first. + # corresponding reference, generate a link. If the name we're looking for + # contains no punctuation, we look for it up the module/class chain. For + # example, ToHtml is found, even without the RDoc::Markup:: prefix, + # because we look for it in module Markup first. def handle_special_CROSSREF(special) name = special.text @@ -138,66 +79,41 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml return name if name =~ /\A[a-z]*\z/ end - return @seen[name] if @seen.include? name + cross_reference name + end - lookup = name + ## + # Handles rdoc-ref: scheme links and allows RDoc::Markup::ToHtml to + # handle other schemes. - name = name[1..-1] unless @show_hash if name[0, 1] == '#' + def handle_special_HYPERLINK special + return cross_reference $' if special.text =~ /\Ardoc-ref:/ - # 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 - type = $2 - type = '' if type == '.' # will find either #method or ::method - method = "#{type}#{$3}" - container = @context.find_symbol_module($1) - elsif /^([.#]|::)#{METHOD_REGEXP_STR}/ =~ lookup then - type = $1 - type = '' if type == '.' - method = "#{type}#{$2}" - container = @context - else - container = nil - end + super + end - if container then - ref = container.find_local_symbol method + ## + # Generates links for rdoc-ref: scheme URLs and allows + # RDoc::Markup::ToHtml to handle other schemes. - unless ref || RDoc::TopLevel === container then - ref = container.find_ancestor_local_symbol method - end - end + def gen_url url, text + super unless url =~ /\Ardoc-ref:/ - ref = @context.find_symbol lookup unless ref - ref = nil if RDoc::Alias === ref # external alias: can't link to it - - out = if lookup == '\\' then - lookup - elsif lookup =~ /^\\/ then - # we remove the \ only in front of what we know: - # other backslashes are treated later, only outside of - ref ? $' : lookup - elsif ref then - if ref.document_self then - "#{name}" - else - name - end - else - lookup - end - - @seen[lookup] = out - - out + cross_reference $', text + end + + ## + # Creates an HTML link to +name+ with the given +text+. + + def link name, text + ref = @cross_reference.resolve name, text + + case ref + when String then + ref + else + "#{text}" + end end end -- cgit v1.2.3