Class: RDoc::Markup::ToHtmlCrossref

Inherits:
ToHtml show all
Defined in:
lib/rdoc/markup/to_html_crossref.rb

Overview

Subclass of the RDoc::Markup::ToHtml class that supports looking up words from a context. Those that are found will be hyperlinked.

Constant Summary

CLASS_REGEXP_STR =

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)

'\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
METHOD_REGEXP_STR =

Regular expression to match method references.

See CLASS_REGEXP_STR

'([a-z]\w*[!?=]?)(?:\([\w.+*/=<>-]*\))?'
CROSSREF_REGEXP =

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.

/(
# 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 \<tt>, though.
# TODO: including < is a hack, not very satisfying.
| \\[^\s<]
)/x
ALL_CROSSREF_REGEXP =

Version of CROSSREF_REGEXP used when --hyperlink-all is specified.

/(
# 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

Constants inherited from ToHtml

RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML

Constants included from Text

Text::TO_HTML_CHARACTERS

Instance Attribute Summary (collapse)

Attributes inherited from ToHtml

#from_path, #in_list_entry, #list, #res

Instance Method Summary (collapse)

Methods inherited from ToHtml

#accept_blank_line, #accept_heading, #accept_list_end, #accept_list_item_end, #accept_list_item_start, #accept_list_start, #accept_paragraph, #accept_raw, #accept_rule, #accept_verbatim, #convert_string, #end_accepting, gen_relative_url, #gen_url, #handle_special_HYPERLINK, #handle_special_TIDYLINK, #html_list_name, #init_tags, #list_end_for, #list_item_start, #start_accepting, #to_html

Methods included from Text

encode_fallback, #expand_tabs, #flush_left, #markup, #normalize_comment, #parse, #strip_hashes, #strip_newlines, #strip_stars, #to_html, #wrap

Methods inherited from Formatter

#add_tag, #annotate, #convert, #convert_flow, #convert_special, #convert_string, #in_tt?, #off_tags, #on_tags, #tt?

Constructor Details

- (ToHtmlCrossref) initialize(from_path, context, show_hash, hyperlink_all = false)

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.

Raises:

  • (ArgumentError)


107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/rdoc/markup/to_html_crossref.rb', line 107

def initialize(from_path, context, show_hash, hyperlink_all = false)
  raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
  super()

  crossref_re = hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP

  @markup.add_special crossref_re, :CROSSREF

  @from_path = from_path
  @context = context
  @show_hash = show_hash
  @hyperlink_all = hyperlink_all

  @seen = {}
end

Instance Attribute Details

- (Object) context

RDoc::CodeObject for generating references



94
95
96
# File 'lib/rdoc/markup/to_html_crossref.rb', line 94

def context
  @context
end

- (Object) show_hash

Should we show '#' characters on method references?



99
100
101
# File 'lib/rdoc/markup/to_html_crossref.rb', line 99

def show_hash
  @show_hash
end

Instance Method Details

- (Object) handle_special_CROSSREF(special)

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.



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/rdoc/markup/to_html_crossref.rb', line 130

def handle_special_CROSSREF(special)
  name = special.text

  unless @hyperlink_all then
    # 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/
  end

  return @seen[name] if @seen.include? name

  lookup = name

  name = name[1..-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
    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

  if container then
    ref = container.find_local_symbol method

    unless ref || RDoc::TopLevel === container then
      ref = container.find_ancestor_local_symbol method
    end
  end

  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 <tt>
          ref ? $' : lookup
        elsif ref then
          if ref.document_self then
            "<a href=\"#{ref.as_href @from_path}\">#{name}</a>"
          else
            name
          end
        else
          lookup
        end

  @seen[lookup] = out

  out
end