1# frozen_string_literal: true
2##
3# Handle common RDoc::Markup tasks for various CodeObjects
4#
5# This module is loaded by generators.  It allows RDoc's CodeObject tree to
6# avoid loading generator code to improve startup time for +ri+.
7
8module RDoc::Generator::Markup
9
10  ##
11  # Generates a relative URL from this object's path to +target_path+
12
13  def aref_to(target_path)
14    RDoc::Markup::ToHtml.gen_relative_url path, target_path
15  end
16
17  ##
18  # Generates a relative URL from +from_path+ to this object's path
19
20  def as_href(from_path)
21    RDoc::Markup::ToHtml.gen_relative_url from_path, path
22  end
23
24  ##
25  # Handy wrapper for marking up this object's comment
26
27  def description
28    markup @comment
29  end
30
31  ##
32  # Creates an RDoc::Markup::ToHtmlCrossref formatter
33
34  def formatter
35    return @formatter if defined? @formatter
36
37    options = @store.rdoc.options
38    this = RDoc::Context === self ? self : @parent
39
40    @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this
41    @formatter.code_object = self
42    @formatter
43  end
44
45  ##
46  # Build a webcvs URL starting for the given +url+ with +full_path+ appended
47  # as the destination path.  If +url+ contains '%s' +full_path+ will be
48  # will replace the %s using sprintf on the +url+.
49
50  def cvs_url(url, full_path)
51    if /%s/ =~ url then
52      sprintf url, full_path
53    else
54      url + full_path
55    end
56  end
57
58end
59
60class RDoc::CodeObject
61
62  include RDoc::Generator::Markup
63
64end
65
66class RDoc::MethodAttr
67
68  ##
69  # Prepend +src+ with line numbers.  Relies on the first line of a source
70  # code listing having:
71  #
72  #   # File xxxxx, line dddd
73  #
74  # If it has this comment then line numbers are added to +src+ and the <tt>,
75  # line dddd</tt> portion of the comment is removed.
76
77  def add_line_numbers(src)
78    return unless src.sub!(/\A(.*)(, line (\d+))/, '\1')
79    first = $3.to_i - 1
80    last  = first + src.count("\n")
81    size = last.to_s.length
82
83    line = first
84    src.gsub!(/^/) do
85      res = if line == first then
86              " " * (size + 1)
87            else
88              "<span class=\"line-num\">%2$*1$d</span> " % [size, line]
89            end
90
91      line += 1
92      res
93    end
94  end
95
96  ##
97  # Turns the method's token stream into HTML.
98  #
99  # Prepends line numbers if +options.line_numbers+ is true.
100
101  def markup_code
102    return '' unless @token_stream
103
104    src = RDoc::TokenStream.to_html @token_stream
105
106    # dedent the source
107    indent = src.length
108    lines = src.lines.to_a
109    lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment
110    lines.each do |line|
111      if line =~ /^ *(?=\S)/
112        n = $&.length
113        indent = n if n < indent
114        break if n == 0
115      end
116    end
117    src.gsub!(/^#{' ' * indent}/, '') if indent > 0
118
119    add_line_numbers(src) if options.line_numbers
120
121    src
122  end
123
124end
125
126class RDoc::ClassModule
127
128  ##
129  # Handy wrapper for marking up this class or module's comment
130
131  def description
132    markup @comment_location
133  end
134
135end
136
137class RDoc::Context::Section
138
139  include RDoc::Generator::Markup
140
141end
142
143class RDoc::TopLevel
144
145  ##
146  # Returns a URL for this source file on some web repository.  Use the -W
147  # command line option to set.
148
149  def cvs_url
150    url = @store.rdoc.options.webcvs
151
152    if /%s/ =~ url then
153      url % @relative_name
154    else
155      url + @relative_name
156    end
157  end
158
159end
160
161