rdoc 7.1.0 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CONTRIBUTING.md +3 -4
- data/LICENSE.rdoc +4 -0
- data/README.md +43 -2
- data/doc/markup_reference/markdown.md +104 -3
- data/lib/rdoc/code_object/alias.rb +2 -8
- data/lib/rdoc/code_object/any_method.rb +11 -6
- data/lib/rdoc/code_object/attr.rb +12 -6
- data/lib/rdoc/code_object/class_module.rb +62 -32
- data/lib/rdoc/code_object/constant.rb +29 -3
- data/lib/rdoc/code_object/context/section.rb +30 -43
- data/lib/rdoc/code_object/context.rb +53 -37
- data/lib/rdoc/code_object/method_attr.rb +9 -15
- data/lib/rdoc/code_object/mixin.rb +3 -0
- data/lib/rdoc/code_object/top_level.rb +11 -3
- data/lib/rdoc/code_object.rb +2 -4
- data/lib/rdoc/comment.rb +1 -66
- data/lib/rdoc/cross_reference.rb +8 -30
- data/lib/rdoc/encoding.rb +3 -3
- data/lib/rdoc/generator/aliki.rb +17 -0
- data/lib/rdoc/generator/darkfish.rb +12 -6
- data/lib/rdoc/generator/json_index.rb +2 -2
- data/lib/rdoc/generator/markup.rb +56 -31
- data/lib/rdoc/generator/template/aliki/DESIGN.md +536 -0
- data/lib/rdoc/generator/template/aliki/_aside_toc.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_head.rhtml +6 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_extends.rhtml +8 -6
- data/lib/rdoc/generator/template/aliki/_sidebar_includes.rhtml +8 -6
- data/lib/rdoc/generator/template/aliki/_sidebar_installed.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +2 -2
- data/lib/rdoc/generator/template/aliki/_sidebar_sections.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/_sidebar_toggle.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/class.rhtml +61 -51
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +365 -147
- data/lib/rdoc/generator/template/aliki/index.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/js/aliki.js +28 -20
- data/lib/rdoc/generator/template/aliki/js/bash_highlighter.js +167 -0
- data/lib/rdoc/generator/template/aliki/js/search_controller.js +1 -1
- data/lib/rdoc/generator/template/aliki/page.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +1 -1
- data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +2 -2
- data/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +8 -6
- data/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +8 -6
- data/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +1 -1
- data/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +5 -5
- data/lib/rdoc/generator/template/darkfish/class.rhtml +18 -21
- data/lib/rdoc/generator/template/darkfish/css/rdoc.css +0 -1
- data/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml +3 -3
- data/lib/rdoc/i18n/text.rb +3 -3
- data/lib/rdoc/markdown.kpeg +36 -17
- data/lib/rdoc/markdown.rb +324 -125
- data/lib/rdoc/markup/document.rb +2 -2
- data/lib/rdoc/markup/formatter.rb +128 -115
- data/lib/rdoc/markup/heading.rb +3 -6
- data/lib/rdoc/markup/indented_paragraph.rb +1 -1
- data/lib/rdoc/markup/inline_parser.rb +312 -0
- data/lib/rdoc/markup/list.rb +2 -2
- data/lib/rdoc/markup/list_item.rb +2 -2
- data/lib/rdoc/markup/parser.rb +1 -1
- data/lib/rdoc/markup/pre_process.rb +0 -25
- data/lib/rdoc/markup/to_ansi.rb +52 -5
- data/lib/rdoc/markup/to_bs.rb +23 -43
- data/lib/rdoc/markup/to_html.rb +279 -226
- data/lib/rdoc/markup/to_html_crossref.rb +122 -136
- data/lib/rdoc/markup/to_html_snippet.rb +65 -65
- data/lib/rdoc/markup/to_joined_paragraph.rb +0 -5
- data/lib/rdoc/markup/to_label.rb +22 -23
- data/lib/rdoc/markup/to_markdown.rb +62 -38
- data/lib/rdoc/markup/to_rdoc.rb +88 -28
- data/lib/rdoc/markup/to_table_of_contents.rb +1 -1
- data/lib/rdoc/markup/to_test.rb +9 -1
- data/lib/rdoc/markup/to_tt_only.rb +10 -23
- data/lib/rdoc/markup/verbatim.rb +1 -1
- data/lib/rdoc/markup.rb +8 -30
- data/lib/rdoc/options.rb +36 -51
- data/lib/rdoc/parser/c.rb +7 -6
- data/lib/rdoc/parser/changelog.rb +21 -0
- data/lib/rdoc/parser/rbs.rb +275 -0
- data/lib/rdoc/parser/ruby.rb +955 -2067
- data/lib/rdoc/parser/ruby_colorizer.rb +253 -0
- data/lib/rdoc/parser.rb +3 -2
- data/lib/rdoc/rbs_helper.rb +186 -0
- data/lib/rdoc/rdoc.rb +196 -24
- data/lib/rdoc/ri/driver.rb +8 -2
- data/lib/rdoc/ri/paths.rb +1 -1
- data/lib/rdoc/{servlet.rb → ri/servlet.rb} +5 -5
- data/lib/rdoc/ri.rb +4 -3
- data/lib/rdoc/rubygems_hook.rb +11 -11
- data/lib/rdoc/server.rb +460 -0
- data/lib/rdoc/stats.rb +147 -124
- data/lib/rdoc/store.rb +212 -4
- data/lib/rdoc/task.rb +16 -15
- data/lib/rdoc/text.rb +24 -117
- data/lib/rdoc/token_stream.rb +11 -33
- data/lib/rdoc/version.rb +1 -1
- data/lib/rdoc.rb +35 -7
- data/lib/rubygems_plugin.rb +2 -11
- data/rdoc-logo.svg +43 -0
- data/rdoc.gemspec +6 -4
- metadata +37 -23
- data/lib/rdoc/code_object/anon_class.rb +0 -10
- data/lib/rdoc/code_object/ghost_method.rb +0 -6
- data/lib/rdoc/code_object/meta_method.rb +0 -6
- data/lib/rdoc/markup/attr_changer.rb +0 -22
- data/lib/rdoc/markup/attr_span.rb +0 -35
- data/lib/rdoc/markup/attribute_manager.rb +0 -432
- data/lib/rdoc/markup/attributes.rb +0 -70
- data/lib/rdoc/markup/regexp_handling.rb +0 -40
- data/lib/rdoc/parser/prism_ruby.rb +0 -1100
- data/lib/rdoc/parser/ripper_state_lex.rb +0 -302
- data/lib/rdoc/parser/ruby_tools.rb +0 -163
data/lib/rdoc/markup/to_html.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require 'cgi/escape'
|
|
3
3
|
require 'cgi/util' unless defined?(CGI::EscapeExt)
|
|
4
|
+
require 'prism'
|
|
4
5
|
|
|
5
6
|
##
|
|
6
7
|
# Outputs RDoc markup as HTML.
|
|
@@ -40,22 +41,104 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
40
41
|
|
|
41
42
|
# :section:
|
|
42
43
|
|
|
44
|
+
# Maps an encoding to a Hash of characters properly transcoded for that
|
|
45
|
+
# encoding.
|
|
46
|
+
#
|
|
47
|
+
# See also encode_fallback.
|
|
48
|
+
|
|
49
|
+
TO_HTML_CHARACTERS = Hash.new do |h, encoding|
|
|
50
|
+
h[encoding] = {
|
|
51
|
+
close_dquote: encode_fallback('”', encoding, '"'),
|
|
52
|
+
close_squote: encode_fallback('’', encoding, '\''),
|
|
53
|
+
copyright: encode_fallback('©', encoding, '(c)'),
|
|
54
|
+
ellipsis: encode_fallback('…', encoding, '...'),
|
|
55
|
+
dot_ellipsis: encode_fallback('.…', encoding, '....'),
|
|
56
|
+
em_dash: encode_fallback('—', encoding, '---'),
|
|
57
|
+
en_dash: encode_fallback('–', encoding, '--'),
|
|
58
|
+
open_dquote: encode_fallback('“', encoding, '"'),
|
|
59
|
+
open_squote: encode_fallback('‘', encoding, '\''),
|
|
60
|
+
trademark: encode_fallback('®', encoding, '(r)'),
|
|
61
|
+
}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
HTML_CHARACTER_ALIASES = {
|
|
65
|
+
'(c)' => :copyright,
|
|
66
|
+
'(C)' => :copyright,
|
|
67
|
+
'(r)' => :trademark,
|
|
68
|
+
'(R)' => :trademark,
|
|
69
|
+
'---' => :em_dash,
|
|
70
|
+
'--' => :en_dash,
|
|
71
|
+
'....' => :dot_ellipsis,
|
|
72
|
+
'...' => :ellipsis,
|
|
73
|
+
'``' => :open_dquote,
|
|
74
|
+
"''" => :close_dquote,
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Transcodes +character+ to +encoding+ with a +fallback+ character.
|
|
78
|
+
|
|
79
|
+
def self.encode_fallback(character, encoding, fallback)
|
|
80
|
+
character.encode(
|
|
81
|
+
encoding,
|
|
82
|
+
fallback: { character => fallback },
|
|
83
|
+
undef: :replace,
|
|
84
|
+
replace: fallback
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Converts ascii quote pairs to multibyte quote characters
|
|
89
|
+
class QuoteConverter
|
|
90
|
+
|
|
91
|
+
def initialize
|
|
92
|
+
@in_dquote = false
|
|
93
|
+
@in_squote = false
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def convert(quote, after_word:)
|
|
97
|
+
case quote
|
|
98
|
+
when '"'
|
|
99
|
+
type = @in_dquote ? :close_dquote : :open_dquote
|
|
100
|
+
@in_dquote = !@in_dquote
|
|
101
|
+
when "'"
|
|
102
|
+
if @in_squote
|
|
103
|
+
type = :close_squote
|
|
104
|
+
@in_squote = false
|
|
105
|
+
elsif after_word
|
|
106
|
+
# Mary's dog, my parents' house: do not start paired quotes
|
|
107
|
+
type = :close_squote
|
|
108
|
+
else
|
|
109
|
+
type = :open_squote
|
|
110
|
+
@in_squote = true
|
|
111
|
+
end
|
|
112
|
+
when '`'
|
|
113
|
+
# Opening quote of <tt>`quoted sentence'</tt>.
|
|
114
|
+
# This will conflict with code blocks <tt>`puts('hello')`</tt> in the future.
|
|
115
|
+
if !@in_squote && !after_word
|
|
116
|
+
type = :open_squote
|
|
117
|
+
@in_squote = true
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
TO_HTML_CHARACTERS[quote.encoding][type] if type
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
43
124
|
##
|
|
44
125
|
# Creates a new formatter that will output HTML
|
|
45
126
|
|
|
46
|
-
def initialize(
|
|
47
|
-
super
|
|
127
|
+
def initialize(pipe: false, output_decoration: true)
|
|
128
|
+
super()
|
|
48
129
|
|
|
130
|
+
@pipe = pipe
|
|
131
|
+
@output_decoration = output_decoration
|
|
49
132
|
@code_object = nil
|
|
50
133
|
@from_path = ''
|
|
51
134
|
@in_list_entry = nil
|
|
52
135
|
@list = nil
|
|
53
136
|
@th = nil
|
|
137
|
+
@quote_converter = nil
|
|
138
|
+
@in_tidylink_label = false
|
|
54
139
|
@hard_break = "<br>\n"
|
|
55
140
|
|
|
56
141
|
init_regexp_handlings
|
|
57
|
-
|
|
58
|
-
init_tags
|
|
59
142
|
end
|
|
60
143
|
|
|
61
144
|
# :section: Regexp Handling
|
|
@@ -72,6 +155,15 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
72
155
|
# external links
|
|
73
156
|
@markup.add_regexp_handling(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)#{URL_CHARACTERS_REGEXP_STR}+\w/,
|
|
74
157
|
:HYPERLINK)
|
|
158
|
+
|
|
159
|
+
# suppress crossref: \#method \::method \ClassName \method_with_underscores
|
|
160
|
+
@markup.add_regexp_handling(/\\(?:[#:A-Z]|[a-z]+_[a-z0-9])/, :SUPPRESSED_CROSSREF)
|
|
161
|
+
|
|
162
|
+
@markup.add_regexp_handling(Regexp.union(HTML_CHARACTER_ALIASES.keys), :HTML_CHARACTERS)
|
|
163
|
+
|
|
164
|
+
@markup.add_regexp_handling(/\b['"`]/, :QUOTE_AFTER_WORD)
|
|
165
|
+
@markup.add_regexp_handling(/\B['"`]/, :QUOTE_NOT_AFTER_WORD)
|
|
166
|
+
|
|
75
167
|
init_link_notation_regexp_handlings
|
|
76
168
|
end
|
|
77
169
|
|
|
@@ -80,7 +172,6 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
80
172
|
|
|
81
173
|
def init_link_notation_regexp_handlings
|
|
82
174
|
add_regexp_handling_RDOCLINK
|
|
83
|
-
add_regexp_handling_TIDYLINK
|
|
84
175
|
end
|
|
85
176
|
|
|
86
177
|
def handle_RDOCLINK(url) # :nodoc:
|
|
@@ -88,6 +179,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
88
179
|
when /^rdoc-ref:/
|
|
89
180
|
CGI.escapeHTML($')
|
|
90
181
|
when /^rdoc-label:/
|
|
182
|
+
return CGI.escapeHTML(url) if in_tidylink_label?
|
|
91
183
|
text = $'
|
|
92
184
|
|
|
93
185
|
text = case text
|
|
@@ -113,11 +205,143 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
113
205
|
end
|
|
114
206
|
end
|
|
115
207
|
|
|
116
|
-
|
|
117
|
-
|
|
208
|
+
def handle_PLAIN_TEXT(text)
|
|
209
|
+
emit_inline(convert_string(text))
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
def handle_REGEXP_HANDLING_TEXT(text)
|
|
213
|
+
emit_inline(text)
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
def handle_BOLD(nodes)
|
|
217
|
+
emit_inline('<strong>')
|
|
218
|
+
super
|
|
219
|
+
emit_inline('</strong>')
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def handle_EM(nodes)
|
|
223
|
+
emit_inline('<em>')
|
|
224
|
+
super
|
|
225
|
+
emit_inline('</em>')
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def handle_BOLD_WORD(word)
|
|
229
|
+
emit_inline('<strong>')
|
|
230
|
+
super
|
|
231
|
+
emit_inline('</strong>')
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def handle_EM_WORD(word)
|
|
235
|
+
emit_inline('<em>')
|
|
236
|
+
super
|
|
237
|
+
emit_inline('</em>')
|
|
238
|
+
end
|
|
118
239
|
|
|
119
|
-
def
|
|
120
|
-
'<
|
|
240
|
+
def handle_TT(code)
|
|
241
|
+
emit_inline('<code>')
|
|
242
|
+
super
|
|
243
|
+
emit_inline('</code>')
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def handle_STRIKE(nodes)
|
|
247
|
+
emit_inline('<del>')
|
|
248
|
+
super
|
|
249
|
+
emit_inline('</del>')
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def handle_HARD_BREAK
|
|
253
|
+
emit_inline('<br>')
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def emit_inline(text)
|
|
257
|
+
@inline_output << text
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Returns true if we are processing inside a tidy link label.
|
|
261
|
+
|
|
262
|
+
def in_tidylink_label?
|
|
263
|
+
@in_tidylink_label
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
# Special handling for tidy link labels.
|
|
267
|
+
# When a tidy link is <tt>{rdoc-image:path/to/image.jpg:alt text}[http://example.com]</tt>,
|
|
268
|
+
# label part is normally considered RDOCLINK <tt>rdoc-image:path/to/image.jpg:alt</tt> and a text <tt>" text"</tt>
|
|
269
|
+
# but RDoc's test code expects the whole label part to be treated as RDOCLINK only in tidy link label.
|
|
270
|
+
# When a tidy link is <tt>{^1}[url]</tt> or <tt>{*1}[url]</tt>, the label part needs to drop leading * or ^.
|
|
271
|
+
# TODO: reconsider this workaround.
|
|
272
|
+
|
|
273
|
+
def apply_tidylink_label_special_handling(label, url)
|
|
274
|
+
# ^1 *1 will be converted to just 1 in tidy link label.
|
|
275
|
+
return label[1..] if label.match?(/\A[*^]\d+\z/)
|
|
276
|
+
|
|
277
|
+
# rdoc-image in label specially allows spaces in alt text.
|
|
278
|
+
return handle_RDOCLINK(label) if label.start_with?('rdoc-image:')
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def handle_TIDYLINK(label_part, url)
|
|
282
|
+
# When url is an image, ignore label part (maybe bug?) and just generate img tag.
|
|
283
|
+
if url.match?(/\Ahttps?:\/\/.+\.(png|gif|jpg|jpeg|bmp)\z/)
|
|
284
|
+
emit_inline("<img src=\"#{CGI.escapeHTML(url)}\" />")
|
|
285
|
+
return
|
|
286
|
+
elsif url.match?(/\Ardoc-image:/)
|
|
287
|
+
emit_inline(handle_RDOCLINK(url))
|
|
288
|
+
return
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
if label_part.size == 1 && String === label_part[0]
|
|
292
|
+
raw_label = label_part[0]
|
|
293
|
+
|
|
294
|
+
@in_tidylink_label = true
|
|
295
|
+
special = apply_tidylink_label_special_handling(raw_label, url)
|
|
296
|
+
@in_tidylink_label = false
|
|
297
|
+
|
|
298
|
+
if special
|
|
299
|
+
tag = gen_url(CGI.escapeHTML(url), special)
|
|
300
|
+
unless tag.empty?
|
|
301
|
+
emit_inline(tag)
|
|
302
|
+
return
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
tag = gen_url(CGI.escapeHTML(url), '')
|
|
308
|
+
open_tag, close_tag = tag.split(/(?=<\/a>)/, 2)
|
|
309
|
+
valid_tag = open_tag && close_tag
|
|
310
|
+
emit_inline(open_tag) if valid_tag
|
|
311
|
+
@in_tidylink_label = true
|
|
312
|
+
traverse_inline_nodes(label_part)
|
|
313
|
+
@in_tidylink_label = false
|
|
314
|
+
emit_inline(close_tag) if valid_tag
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def handle_inline(text) # :nodoc:
|
|
318
|
+
@inline_output = +''
|
|
319
|
+
@quote_converter = QuoteConverter.new
|
|
320
|
+
super
|
|
321
|
+
out = @inline_output
|
|
322
|
+
@inline_output = nil
|
|
323
|
+
@quote_converter = nil
|
|
324
|
+
out
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
# Converts <tt>(c), (r), --, --- , ..., ...., ``, ''</tt> to HTML characters.
|
|
328
|
+
def handle_regexp_HTML_CHARACTERS(text)
|
|
329
|
+
name = HTML_CHARACTER_ALIASES[text]
|
|
330
|
+
TO_HTML_CHARACTERS[text.encoding][name] if name
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def handle_regexp_QUOTE_NOT_AFTER_WORD(text)
|
|
334
|
+
@quote_converter.convert(text, after_word: false) || convert_string(text)
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def handle_regexp_QUOTE_AFTER_WORD(text)
|
|
338
|
+
@quote_converter.convert(text, after_word: true) || convert_string(text)
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# Converts suppressed cross-reference +text+ to HTML by removing the leading backslash.
|
|
342
|
+
|
|
343
|
+
def handle_regexp_SUPPRESSED_CROSSREF(text)
|
|
344
|
+
convert_string(text.delete_prefix('\\'))
|
|
121
345
|
end
|
|
122
346
|
|
|
123
347
|
##
|
|
@@ -132,9 +356,10 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
132
356
|
# <tt>link:</tt>::
|
|
133
357
|
# Reference to a local file relative to the output directory.
|
|
134
358
|
|
|
135
|
-
def handle_regexp_HYPERLINK(
|
|
136
|
-
|
|
359
|
+
def handle_regexp_HYPERLINK(text)
|
|
360
|
+
return convert_string(text) if in_tidylink_label?
|
|
137
361
|
|
|
362
|
+
url = CGI.escapeHTML(text)
|
|
138
363
|
gen_url url, url
|
|
139
364
|
end
|
|
140
365
|
|
|
@@ -147,27 +372,8 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
147
372
|
# For the +rdoc-label+ scheme the footnote and label prefixes are stripped
|
|
148
373
|
# when creating a link. All other contents will be linked verbatim.
|
|
149
374
|
|
|
150
|
-
def handle_regexp_RDOCLINK(
|
|
151
|
-
handle_RDOCLINK
|
|
152
|
-
end
|
|
153
|
-
|
|
154
|
-
##
|
|
155
|
-
# This +target+ is a link where the label is different from the URL
|
|
156
|
-
# <tt>label[url]</tt> or <tt>{long label}[url]</tt>
|
|
157
|
-
|
|
158
|
-
def handle_regexp_TIDYLINK(target)
|
|
159
|
-
text = target.text
|
|
160
|
-
|
|
161
|
-
if tidy_link_capturing?
|
|
162
|
-
return finish_tidy_link(text)
|
|
163
|
-
end
|
|
164
|
-
|
|
165
|
-
if text.start_with?('{') && !text.include?('}')
|
|
166
|
-
start_tidy_link text
|
|
167
|
-
return ''
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
convert_complete_tidy_link(text)
|
|
375
|
+
def handle_regexp_RDOCLINK(text)
|
|
376
|
+
handle_RDOCLINK text
|
|
171
377
|
end
|
|
172
378
|
|
|
173
379
|
# :section: Visitor
|
|
@@ -181,6 +387,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
181
387
|
@res = []
|
|
182
388
|
@in_list_entry = []
|
|
183
389
|
@list = []
|
|
390
|
+
@heading_ids = {}
|
|
184
391
|
end
|
|
185
392
|
|
|
186
393
|
##
|
|
@@ -209,13 +416,22 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
209
416
|
def accept_paragraph(paragraph)
|
|
210
417
|
@res << "\n<p>"
|
|
211
418
|
text = paragraph.text @hard_break
|
|
212
|
-
text = text.gsub(/(#{SPACE_SEPARATED_LETTER_CLASS})?\K
|
|
419
|
+
text = text.gsub(/(#{SPACE_SEPARATED_LETTER_CLASS})?\K(?:\r?\n)+(?=(?(1)(#{SPACE_SEPARATED_LETTER_CLASS})?))/o) {
|
|
213
420
|
defined?($2) && ' '
|
|
214
421
|
}
|
|
215
422
|
@res << to_html(text)
|
|
216
423
|
@res << "</p>\n"
|
|
217
424
|
end
|
|
218
425
|
|
|
426
|
+
# Generate syntax highlighted html for ruby-like text.
|
|
427
|
+
|
|
428
|
+
def parsable_text_to_html(text)
|
|
429
|
+
tokens = RDoc::Parser::RubyColorizer.colorize(text)
|
|
430
|
+
result = RDoc::TokenStream.to_html tokens
|
|
431
|
+
result = result + "\n" unless result.end_with?("\n")
|
|
432
|
+
result
|
|
433
|
+
end
|
|
434
|
+
|
|
219
435
|
##
|
|
220
436
|
# Adds +verbatim+ to the output
|
|
221
437
|
|
|
@@ -223,29 +439,19 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
223
439
|
text = verbatim.text.rstrip
|
|
224
440
|
format = verbatim.format
|
|
225
441
|
|
|
226
|
-
klass = nil
|
|
227
|
-
|
|
228
442
|
# Apply Ruby syntax highlighting if
|
|
229
443
|
# - explicitly marked as Ruby (via ruby? which accepts :ruby or :rb)
|
|
230
444
|
# - no format specified but the text is parseable as Ruby
|
|
231
445
|
# Otherwise, add language class when applicable and skip Ruby highlighting
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
CGI.escapeHTML text
|
|
242
|
-
end
|
|
243
|
-
else
|
|
244
|
-
klass = " class=\"#{format}\"" if format
|
|
245
|
-
CGI.escapeHTML text
|
|
246
|
-
end
|
|
247
|
-
|
|
248
|
-
if @options.pipe then
|
|
446
|
+
if verbatim.ruby? || (format.nil? && parseable?(text))
|
|
447
|
+
content = parsable_text_to_html(text)
|
|
448
|
+
klass = ' class="ruby"'
|
|
449
|
+
else
|
|
450
|
+
content = CGI.escapeHTML text
|
|
451
|
+
klass = " class=\"#{format}\"" if format
|
|
452
|
+
end
|
|
453
|
+
|
|
454
|
+
if @pipe
|
|
249
455
|
@res << "\n<pre><code>#{CGI.escapeHTML text}\n</code></pre>\n"
|
|
250
456
|
else
|
|
251
457
|
@res << "\n<pre#{klass}>#{content}</pre>\n"
|
|
@@ -311,22 +517,22 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
311
517
|
def accept_heading(heading)
|
|
312
518
|
level = [6, heading.level].min
|
|
313
519
|
|
|
314
|
-
label = heading.label
|
|
315
|
-
legacy_label = heading.legacy_label
|
|
520
|
+
label = deduplicate_heading_id(heading.label(@code_object))
|
|
521
|
+
legacy_label = deduplicate_heading_id(heading.legacy_label(@code_object))
|
|
316
522
|
|
|
317
523
|
# Add legacy anchor before the heading for backward compatibility.
|
|
318
524
|
# This allows old links with label- prefix to still work.
|
|
319
|
-
if @
|
|
525
|
+
if @output_decoration && !@pipe
|
|
320
526
|
@res << "\n<span id=\"#{legacy_label}\" class=\"legacy-anchor\"></span>"
|
|
321
527
|
end
|
|
322
528
|
|
|
323
|
-
@res << if @
|
|
529
|
+
@res << if @output_decoration
|
|
324
530
|
"\n<h#{level} id=\"#{label}\">"
|
|
325
531
|
else
|
|
326
532
|
"\n<h#{level}>"
|
|
327
533
|
end
|
|
328
534
|
|
|
329
|
-
if @
|
|
535
|
+
if @pipe
|
|
330
536
|
@res << to_html(heading.text)
|
|
331
537
|
else
|
|
332
538
|
@res << "<a href=\"##{label}\">#{to_html(heading.text)}</a>"
|
|
@@ -367,6 +573,20 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
367
573
|
|
|
368
574
|
# :section: Utilities
|
|
369
575
|
|
|
576
|
+
##
|
|
577
|
+
# Returns a unique heading ID, appending -1, -2, etc. for duplicates.
|
|
578
|
+
# Matches GitHub's behavior for duplicate heading anchors.
|
|
579
|
+
|
|
580
|
+
def deduplicate_heading_id(id)
|
|
581
|
+
if @heading_ids.key?(id)
|
|
582
|
+
@heading_ids[id] += 1
|
|
583
|
+
"#{id}-#{@heading_ids[id]}"
|
|
584
|
+
else
|
|
585
|
+
@heading_ids[id] = 0
|
|
586
|
+
id
|
|
587
|
+
end
|
|
588
|
+
end
|
|
589
|
+
|
|
370
590
|
##
|
|
371
591
|
# CGI-escapes +text+
|
|
372
592
|
|
|
@@ -415,16 +635,6 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
415
635
|
tags[open_tag ? 0 : 1]
|
|
416
636
|
end
|
|
417
637
|
|
|
418
|
-
##
|
|
419
|
-
# Maps attributes to HTML tags
|
|
420
|
-
|
|
421
|
-
def init_tags
|
|
422
|
-
add_tag :BOLD, "<strong>", "</strong>"
|
|
423
|
-
add_tag :TT, "<code>", "</code>"
|
|
424
|
-
add_tag :EM, "<em>", "</em>"
|
|
425
|
-
add_tag :STRIKE, "<del>", "</del>"
|
|
426
|
-
end
|
|
427
|
-
|
|
428
638
|
##
|
|
429
639
|
# Returns the HTML tag for +list_type+, possible using a label from
|
|
430
640
|
# +list_item+
|
|
@@ -460,170 +670,13 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
460
670
|
# Returns true if text is valid ruby syntax
|
|
461
671
|
|
|
462
672
|
def parseable?(text)
|
|
463
|
-
|
|
464
|
-
catch(:valid) do
|
|
465
|
-
eval("BEGIN { throw :valid, true }\n#{text}")
|
|
466
|
-
end
|
|
467
|
-
rescue SyntaxError
|
|
468
|
-
false
|
|
469
|
-
ensure
|
|
470
|
-
$VERBOSE = verbose
|
|
673
|
+
Prism.parse_success?(text)
|
|
471
674
|
end
|
|
472
675
|
|
|
473
676
|
##
|
|
474
677
|
# Converts +item+ to HTML using RDoc::Text#to_html
|
|
475
678
|
|
|
476
679
|
def to_html(item)
|
|
477
|
-
|
|
478
|
-
end
|
|
479
|
-
|
|
480
|
-
private
|
|
481
|
-
|
|
482
|
-
def convert_flow(flow_items)
|
|
483
|
-
res = []
|
|
484
|
-
|
|
485
|
-
flow_items.each do |item|
|
|
486
|
-
case item
|
|
487
|
-
when String
|
|
488
|
-
append_flow_fragment res, convert_string(item)
|
|
489
|
-
when RDoc::Markup::AttrChanger
|
|
490
|
-
off_tags res, item
|
|
491
|
-
on_tags res, item
|
|
492
|
-
when RDoc::Markup::RegexpHandling
|
|
493
|
-
append_flow_fragment res, convert_regexp_handling(item)
|
|
494
|
-
else
|
|
495
|
-
raise "Unknown flow element: #{item.inspect}"
|
|
496
|
-
end
|
|
497
|
-
end
|
|
498
|
-
|
|
499
|
-
res.join
|
|
500
|
-
end
|
|
501
|
-
|
|
502
|
-
def append_flow_fragment(res, fragment)
|
|
503
|
-
return if fragment.nil? || fragment.empty?
|
|
504
|
-
|
|
505
|
-
emit_tidy_link_fragment(res, fragment)
|
|
506
|
-
end
|
|
507
|
-
|
|
508
|
-
def append_to_tidy_label(fragment)
|
|
509
|
-
@tidy_link_buffer << fragment
|
|
510
|
-
end
|
|
511
|
-
|
|
512
|
-
##
|
|
513
|
-
# Matches an entire tidy link with a braced label "{label}[url]".
|
|
514
|
-
#
|
|
515
|
-
# Capture 1: label contents.
|
|
516
|
-
# Capture 2: URL text.
|
|
517
|
-
# Capture 3: trailing content.
|
|
518
|
-
TIDY_LINK_WITH_BRACES = /\A\{(.*?)\}\[(.*?)\](.*)\z/
|
|
519
|
-
|
|
520
|
-
##
|
|
521
|
-
# Matches the tail of a braced tidy link when the opening brace was
|
|
522
|
-
# consumed earlier while accumulating the label text.
|
|
523
|
-
#
|
|
524
|
-
# Capture 1: remaining label content.
|
|
525
|
-
# Capture 2: URL text.
|
|
526
|
-
# Capture 3: trailing content.
|
|
527
|
-
TIDY_LINK_WITH_BRACES_TAIL = /\A(.*?)\}\[(.*?)\](.*)\z/
|
|
528
|
-
|
|
529
|
-
##
|
|
530
|
-
# Matches a tidy link with a single-word label "label[url]".
|
|
531
|
-
#
|
|
532
|
-
# Capture 1: the single-word label (no whitespace).
|
|
533
|
-
# Capture 2: URL text between the brackets.
|
|
534
|
-
TIDY_LINK_SINGLE_WORD = /\A(\S+)\[(.*?)\](.*)\z/
|
|
535
|
-
|
|
536
|
-
def convert_complete_tidy_link(text)
|
|
537
|
-
return text unless
|
|
538
|
-
text =~ TIDY_LINK_WITH_BRACES or text =~ TIDY_LINK_SINGLE_WORD
|
|
539
|
-
|
|
540
|
-
label = $1
|
|
541
|
-
url = CGI.escapeHTML($2)
|
|
542
|
-
|
|
543
|
-
label_html = if /^rdoc-image:/ =~ label
|
|
544
|
-
handle_RDOCLINK(label)
|
|
545
|
-
else
|
|
546
|
-
render_tidy_link_label(label)
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
gen_url url, label_html
|
|
550
|
-
end
|
|
551
|
-
|
|
552
|
-
def emit_tidy_link_fragment(res, fragment)
|
|
553
|
-
if tidy_link_capturing?
|
|
554
|
-
append_to_tidy_label fragment
|
|
555
|
-
else
|
|
556
|
-
res << fragment
|
|
557
|
-
end
|
|
558
|
-
end
|
|
559
|
-
|
|
560
|
-
def finish_tidy_link(text)
|
|
561
|
-
label_tail, url, trailing = extract_tidy_link_parts(text)
|
|
562
|
-
append_to_tidy_label CGI.escapeHTML(label_tail) unless label_tail.empty?
|
|
563
|
-
|
|
564
|
-
return '' unless url
|
|
565
|
-
|
|
566
|
-
label_html = @tidy_link_buffer
|
|
567
|
-
@tidy_link_buffer = nil
|
|
568
|
-
link = gen_url(url, label_html)
|
|
569
|
-
|
|
570
|
-
return link if trailing.empty?
|
|
571
|
-
|
|
572
|
-
link + CGI.escapeHTML(trailing)
|
|
573
|
-
end
|
|
574
|
-
|
|
575
|
-
def extract_tidy_link_parts(text)
|
|
576
|
-
if text =~ TIDY_LINK_WITH_BRACES
|
|
577
|
-
[$1, CGI.escapeHTML($2), $3]
|
|
578
|
-
elsif text =~ TIDY_LINK_WITH_BRACES_TAIL
|
|
579
|
-
[$1, CGI.escapeHTML($2), $3]
|
|
580
|
-
elsif text =~ TIDY_LINK_SINGLE_WORD
|
|
581
|
-
[$1, CGI.escapeHTML($2), $3]
|
|
582
|
-
else
|
|
583
|
-
[text, nil, '']
|
|
584
|
-
end
|
|
585
|
-
end
|
|
586
|
-
|
|
587
|
-
def on_tags(res, item)
|
|
588
|
-
each_attr_tag(item.turn_on) do |tag|
|
|
589
|
-
emit_tidy_link_fragment(res, annotate(tag.on))
|
|
590
|
-
@in_tt += 1 if tt? tag
|
|
591
|
-
end
|
|
592
|
-
end
|
|
593
|
-
|
|
594
|
-
def off_tags(res, item)
|
|
595
|
-
each_attr_tag(item.turn_off, true) do |tag|
|
|
596
|
-
emit_tidy_link_fragment(res, annotate(tag.off))
|
|
597
|
-
@in_tt -= 1 if tt? tag
|
|
598
|
-
end
|
|
599
|
-
end
|
|
600
|
-
|
|
601
|
-
def start_tidy_link(text)
|
|
602
|
-
@tidy_link_buffer = String.new
|
|
603
|
-
append_to_tidy_label CGI.escapeHTML(text.delete_prefix('{'))
|
|
604
|
-
end
|
|
605
|
-
|
|
606
|
-
def tidy_link_capturing?
|
|
607
|
-
!!@tidy_link_buffer
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
def render_tidy_link_label(label)
|
|
611
|
-
RDoc::Markup::LinkLabelToHtml.render(label, @options, @from_path)
|
|
612
|
-
end
|
|
613
|
-
end
|
|
614
|
-
|
|
615
|
-
##
|
|
616
|
-
# Formatter dedicated to rendering tidy link labels without mutating the
|
|
617
|
-
# calling formatter's state.
|
|
618
|
-
|
|
619
|
-
class RDoc::Markup::LinkLabelToHtml < RDoc::Markup::ToHtml
|
|
620
|
-
def self.render(label, options, from_path)
|
|
621
|
-
new(options, from_path).to_html(label)
|
|
622
|
-
end
|
|
623
|
-
|
|
624
|
-
def initialize(options, from_path = nil)
|
|
625
|
-
super(options)
|
|
626
|
-
|
|
627
|
-
self.from_path = from_path if from_path
|
|
680
|
+
handle_inline(item)
|
|
628
681
|
end
|
|
629
682
|
end
|