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 method names, classes, etc to create links. RDoc::CrossReference is used to generate those links based on the current context.

Constant Summary collapse

ALL_CROSSREF_REGEXP =

:stopdoc:

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

Constants inherited from ToHtml

RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML, RDoc::Markup::ToHtml::URL_CHARACTERS_REGEXP_STR

Constants included from Text

Text::MARKUP_FORMAT, Text::SPACE_SEPARATED_LETTER_CLASS, Text::TO_HTML_CHARACTERS

Instance Attribute Summary collapse

Attributes inherited from ToHtml

#code_object, #from_path, #in_list_entry, #list, #res

Attributes included from Text

#language

Instance Method Summary collapse

Methods inherited from ToHtml

#accept_blank_line, #accept_block_quote, #accept_heading, #accept_list_end, #accept_list_item_end, #accept_list_item_start, #accept_list_start, #accept_paragraph, #accept_raw, #accept_rule, #accept_table, #accept_verbatim, #convert_string, #end_accepting, #handle_RDOCLINK, #handle_regexp_HARD_BREAK, #handle_regexp_TIDYLINK, #html_list_name, #init_regexp_handlings, #init_tags, #list_end_for, #list_item_start, #parseable?, #start_accepting, #to_html

Methods included from Text

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

Methods inherited from Formatter

#accept_document, #add_regexp_handling_RDOCLINK, #add_regexp_handling_TIDYLINK, #add_tag, #annotate, #convert, #convert_regexp_handling, #convert_string, #each_attr_tag, gen_relative_url, #ignore, #in_tt?, #off_tags, #on_tags, #parse_url, #tt?, #tt_tag?

Constructor Details

#initialize(options, from_path, context, markup = nil) ⇒ ToHtmlCrossref

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 linked, unless hyperlink_all is true.

Raises:

  • (ArgumentError)


32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/rdoc/markup/to_html_crossref.rb', line 32

def initialize(options, from_path, context, markup = nil)
  raise ArgumentError, 'from_path cannot be nil' if from_path.nil?

  super options, markup

  @context       = context
  @from_path     = from_path
  @hyperlink_all = @options.hyperlink_all
  @show_hash     = @options.show_hash

  @cross_reference = RDoc::CrossReference.new @context
end

Instance Attribute Details

#contextObject

RDoc::CodeObject for generating references



19
20
21
# File 'lib/rdoc/markup/to_html_crossref.rb', line 19

def context
  @context
end

#show_hashObject

Should we show ‘#’ characters on method references?



24
25
26
# File 'lib/rdoc/markup/to_html_crossref.rb', line 24

def show_hash
  @show_hash
end

Instance Method Details

#convert_flow(flow) ⇒ Object



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
# File 'lib/rdoc/markup/to_html_crossref.rb', line 185

def convert_flow(flow)
  res = []

  i = 0
  while i < flow.size
    item = flow[i]
    i += 1
    case item
    when RDoc::Markup::AttrChanger then
      # Make "+Class#method+" a cross reference
      if tt_tag?(item.turn_on) and
        String === (str = flow[i]) and
        RDoc::Markup::AttrChanger === flow[i+1] and
        tt_tag?(flow[i+1].turn_off, true) and
        (@options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP).match?(str) and
        (text = cross_reference str) != str
      then
        text = yield text, res if defined?(yield)
        res << text
        i += 2
        next
      end
      off_tags res, item
      on_tags res, item
    when String then
      text = convert_string(item)
      text = yield text, res if defined?(yield)
      res << text
    when RDoc::Markup::RegexpHandling then
      text = convert_regexp_handling(item)
      text = yield text, res if defined?(yield)
      res << text
    else
      raise "Unknown flow element: #{item.inspect}"
    end
  end

  res.join('')
end

#cross_reference(name, text = nil, code = true, rdoc_ref: false) ⇒ Object

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.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/rdoc/markup/to_html_crossref.rb', line 61

def cross_reference name, text = nil, code = true, rdoc_ref: false
  lookup = name

  name = name[1..-1] unless @show_hash if name[0, 1] == '#'

  if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
    text ||= [CGI.unescape($'), (" at <code>#{$1}</code>" if $~.begin(1))].join("")
    code = false
  else
    text ||= name
  end

  link lookup, text, code, rdoc_ref: rdoc_ref
end

#gen_url(url, text) ⇒ Object

Generates links for rdoc-ref: scheme URLs and allows RDoc::Markup::ToHtml to handle other schemes.



136
137
138
139
140
141
142
143
# File 'lib/rdoc/markup/to_html_crossref.rb', line 136

def gen_url url, text
  if url =~ /\Ardoc-ref:/
    name = $'
    cross_reference name, text, name == text, rdoc_ref: true
  else
    super
  end
end

#handle_regexp_CROSSREF(target) ⇒ Object

We’re invoked when any text matches the CROSSREF pattern. If we find the 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.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/rdoc/markup/to_html_crossref.rb', line 83

def handle_regexp_CROSSREF(target)
  name = target.text

  return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails

  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

  cross_reference name, rdoc_ref: false
end

Handles rdoc-ref: scheme links and allows RDoc::Markup::ToHtml to handle other schemes.



102
103
104
105
106
107
108
109
110
111
# File 'lib/rdoc/markup/to_html_crossref.rb', line 102

def handle_regexp_HYPERLINK target
  url = target.text

  case url
  when /\Ardoc-ref:/
    cross_reference $', rdoc_ref: true
  else
    super
  end
end

target is an rdoc-schemed link that will be converted into a hyperlink. For the rdoc-ref scheme the cross-reference will be looked up and the given name will be used.

All other contents are handled by the superclass



121
122
123
124
125
126
127
128
129
130
# File 'lib/rdoc/markup/to_html_crossref.rb', line 121

def handle_regexp_RDOCLINK target
  url = target.text

  case url
  when /\Ardoc-ref:/
    cross_reference $', rdoc_ref: true
  else
    super
  end
end

:nodoc:



46
47
48
49
50
51
52
53
54
55
# File 'lib/rdoc/markup/to_html_crossref.rb', line 46

def init_link_notation_regexp_handlings
  add_regexp_handling_RDOCLINK

  # The crossref must be linked before tidylink because Klass.method[:sym]
  # will be processed as a tidylink first and will be broken.
  crossref_re = @options.hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
  @markup.add_regexp_handling crossref_re, :CROSSREF

  add_regexp_handling_TIDYLINK
end

Creates an HTML link to name with the given text.



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
# File 'lib/rdoc/markup/to_html_crossref.rb', line 148

def link name, text, code = true, rdoc_ref: false
  if !(name.end_with?('+@', '-@')) and name =~ /(.*[^#:])?@/
    name = $1
    label = $'
  end

  ref = @cross_reference.resolve name, text if name

  case ref
  when String then
    if rdoc_ref && @options.warn_missing_rdoc_ref
      puts "#{@from_path}: `rdoc-ref:#{name}` can't be resolved for `#{text}`"
    end
    ref
  else
    path = ref ? ref.as_href(@from_path) : +""

    if code and RDoc::CodeObject === ref and !(RDoc::TopLevel === ref)
      text = "<code>#{CGI.escapeHTML text}</code>"
    end

    if label
      if path =~ /#/
        path << "-label-#{label}"
      elsif ref&.sections&.any? { |section| label == section.title }
        path << "##{label}"
      elsif ref.respond_to?(:aref)
        path << "##{ref.aref}-label-#{label}"
      else
        path << "#label-#{label}"
      end
    end

    "<a href=\"#{path}\">#{text}</a>"
  end
end