rdoc 7.0.3 → 7.1.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/README.md +70 -4
- data/doc/markup_reference/markdown.md +558 -0
- data/doc/markup_reference/rdoc.rdoc +1169 -0
- data/lib/rdoc/code_object/class_module.rb +24 -3
- data/lib/rdoc/code_object/context/section.rb +20 -1
- data/lib/rdoc/cross_reference.rb +30 -21
- data/lib/rdoc/generator/template/aliki/class.rhtml +3 -1
- data/lib/rdoc/generator/template/aliki/css/rdoc.css +20 -0
- data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +1 -1
- data/lib/rdoc/generator/template/darkfish/class.rhtml +2 -0
- data/lib/rdoc/generator/template/darkfish/css/rdoc.css +19 -0
- data/lib/rdoc/markdown.kpeg +1 -5
- data/lib/rdoc/markdown.rb +1 -5
- data/lib/rdoc/markup/attribute_manager.rb +28 -1
- data/lib/rdoc/markup/heading.rb +99 -27
- data/lib/rdoc/markup/to_html.rb +31 -11
- data/lib/rdoc/markup/to_html_crossref.rb +24 -5
- data/lib/rdoc/markup/to_label.rb +11 -1
- data/lib/rdoc/markup/verbatim.rb +1 -1
- data/lib/rdoc/markup.rb +2 -2
- data/lib/rdoc/parser/changelog.rb +8 -0
- data/lib/rdoc/text.rb +15 -0
- data/lib/rdoc/token_stream.rb +4 -8
- data/lib/rdoc/version.rb +1 -1
- data/rdoc.gemspec +2 -2
- metadata +5 -7
- data/ExampleMarkdown.md +0 -39
- data/ExampleRDoc.rdoc +0 -210
|
@@ -188,10 +188,26 @@ class RDoc::ClassModule < RDoc::Context
|
|
|
188
188
|
end
|
|
189
189
|
|
|
190
190
|
##
|
|
191
|
-
# HTML fragment reference for this module or class
|
|
192
|
-
#
|
|
191
|
+
# HTML fragment reference for this module or class using GitHub-style
|
|
192
|
+
# anchor format (lowercase, :: replaced with -).
|
|
193
|
+
#
|
|
194
|
+
# Examples:
|
|
195
|
+
# Foo -> class-foo
|
|
196
|
+
# Foo::Bar -> class-foo-bar
|
|
193
197
|
|
|
194
198
|
def aref
|
|
199
|
+
"#{aref_prefix}-#{full_name.downcase.gsub('::', '-')}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
##
|
|
203
|
+
# Legacy HTML fragment reference for backward compatibility.
|
|
204
|
+
# Returns the old RDoc-style anchor format.
|
|
205
|
+
#
|
|
206
|
+
# Examples:
|
|
207
|
+
# Foo -> class-Foo
|
|
208
|
+
# Foo::Bar -> class-Foo::Bar
|
|
209
|
+
|
|
210
|
+
def legacy_aref
|
|
195
211
|
"#{aref_prefix}-#{full_name}"
|
|
196
212
|
end
|
|
197
213
|
|
|
@@ -477,7 +493,12 @@ class RDoc::ClassModule < RDoc::Context
|
|
|
477
493
|
document = document.merge other_document
|
|
478
494
|
|
|
479
495
|
@comment = RDoc::Comment.from_document(document)
|
|
480
|
-
|
|
496
|
+
|
|
497
|
+
@comment_location = if document.parts.first.is_a?(RDoc::Markup::Document)
|
|
498
|
+
document.parts.map { |doc| [doc, doc.file] }
|
|
499
|
+
else
|
|
500
|
+
[[document, document.file]]
|
|
501
|
+
end
|
|
481
502
|
end
|
|
482
503
|
|
|
483
504
|
cm = class_module
|
|
@@ -70,11 +70,30 @@ class RDoc::Context::Section
|
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
##
|
|
73
|
-
# Anchor reference for linking to this section
|
|
73
|
+
# Anchor reference for linking to this section using GitHub-style format.
|
|
74
|
+
#
|
|
75
|
+
# Examples:
|
|
76
|
+
# "Section" -> "section"
|
|
77
|
+
# "One Two" -> "one-two"
|
|
78
|
+
# "[untitled]" -> "untitled"
|
|
74
79
|
|
|
75
80
|
def aref
|
|
76
81
|
title = @title || '[untitled]'
|
|
77
82
|
|
|
83
|
+
RDoc::Text.to_anchor(title)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
##
|
|
87
|
+
# Legacy anchor reference for backward compatibility.
|
|
88
|
+
#
|
|
89
|
+
# Examples:
|
|
90
|
+
# "Section" -> "section"
|
|
91
|
+
# "One Two" -> "one+two"
|
|
92
|
+
# "[untitled]" -> "5Buntitled-5D"
|
|
93
|
+
|
|
94
|
+
def legacy_aref
|
|
95
|
+
title = @title || '[untitled]'
|
|
96
|
+
|
|
78
97
|
CGI.escape(title).gsub('%', '-').sub(/^-/, '')
|
|
79
98
|
end
|
|
80
99
|
|
data/lib/rdoc/cross_reference.rb
CHANGED
|
@@ -132,47 +132,56 @@ class RDoc::CrossReference
|
|
|
132
132
|
end
|
|
133
133
|
|
|
134
134
|
##
|
|
135
|
-
# Returns a method reference to +name
|
|
135
|
+
# Returns a method, attribute or constant reference to +name+
|
|
136
|
+
# if it exists in the containing context object. It returns
|
|
137
|
+
# nil otherwise.
|
|
138
|
+
#
|
|
139
|
+
# For example, this method would decompose name = 'A::CONSTANT' into a
|
|
140
|
+
# container object A and a symbol 'CONSTANT', and it would try to find
|
|
141
|
+
# 'CONSTANT' in A.
|
|
136
142
|
|
|
137
|
-
def
|
|
143
|
+
def resolve_local_symbol(name)
|
|
138
144
|
ref = nil
|
|
145
|
+
type = nil
|
|
146
|
+
container = nil
|
|
139
147
|
|
|
140
|
-
|
|
148
|
+
case name
|
|
149
|
+
when /#{CLASS_REGEXP_STR}::([A-Z]\w*)\z/o then
|
|
150
|
+
symbol = $2
|
|
151
|
+
container = @context.find_symbol_module($1)
|
|
152
|
+
when /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o then
|
|
141
153
|
type = $2
|
|
142
154
|
if '.' == type # will find either #method or ::method
|
|
143
|
-
|
|
155
|
+
symbol = $3
|
|
144
156
|
else
|
|
145
|
-
|
|
157
|
+
symbol = "#{type}#{$3}"
|
|
146
158
|
end
|
|
147
159
|
container = @context.find_symbol_module($1)
|
|
148
|
-
|
|
160
|
+
when /^([.#]|::)#{METHOD_REGEXP_STR}/o then
|
|
149
161
|
type = $1
|
|
150
162
|
if '.' == type
|
|
151
|
-
|
|
163
|
+
symbol = $2
|
|
152
164
|
else
|
|
153
|
-
|
|
165
|
+
symbol = "#{type}#{$2}"
|
|
154
166
|
end
|
|
155
167
|
container = @context
|
|
156
|
-
else
|
|
157
|
-
type = nil
|
|
158
|
-
container = nil
|
|
159
168
|
end
|
|
160
169
|
|
|
161
170
|
if container then
|
|
162
171
|
unless RDoc::TopLevel === container then
|
|
163
172
|
if '.' == type then
|
|
164
|
-
if 'new' ==
|
|
165
|
-
ref = container.find_local_symbol
|
|
166
|
-
ref = container.find_ancestor_local_symbol
|
|
173
|
+
if 'new' == symbol then # AnyClassName.new will be class method
|
|
174
|
+
ref = container.find_local_symbol symbol
|
|
175
|
+
ref = container.find_ancestor_local_symbol symbol unless ref
|
|
167
176
|
else
|
|
168
|
-
ref = container.find_local_symbol "::#{
|
|
169
|
-
ref = container.find_ancestor_local_symbol "::#{
|
|
170
|
-
ref = container.find_local_symbol "##{
|
|
171
|
-
ref = container.find_ancestor_local_symbol "##{
|
|
177
|
+
ref = container.find_local_symbol "::#{symbol}"
|
|
178
|
+
ref = container.find_ancestor_local_symbol "::#{symbol}" unless ref
|
|
179
|
+
ref = container.find_local_symbol "##{symbol}" unless ref
|
|
180
|
+
ref = container.find_ancestor_local_symbol "##{symbol}" unless ref
|
|
172
181
|
end
|
|
173
182
|
else
|
|
174
|
-
ref = container.find_local_symbol
|
|
175
|
-
ref = container.find_ancestor_local_symbol
|
|
183
|
+
ref = container.find_local_symbol symbol
|
|
184
|
+
ref = container.find_ancestor_local_symbol symbol unless ref
|
|
176
185
|
end
|
|
177
186
|
end
|
|
178
187
|
end
|
|
@@ -197,7 +206,7 @@ class RDoc::CrossReference
|
|
|
197
206
|
@context.find_symbol name
|
|
198
207
|
end
|
|
199
208
|
|
|
200
|
-
ref =
|
|
209
|
+
ref = resolve_local_symbol name unless ref
|
|
201
210
|
|
|
202
211
|
# Try a page name
|
|
203
212
|
ref = @store.page name if not ref and name =~ /^[\w.\/]+$/
|
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
</ol>
|
|
30
30
|
<% end %>
|
|
31
31
|
|
|
32
|
+
<span id="<%= h klass.legacy_aref %>" class="legacy-anchor"></span>
|
|
32
33
|
<h1 id="<%= h klass.aref %>" class="anchor-link <%= klass.type %>">
|
|
33
34
|
<%= klass.type %> <%= klass.full_name %>
|
|
34
35
|
</h1>
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
</section>
|
|
39
40
|
|
|
40
41
|
<%- klass.each_section do |section, constants, attributes| %>
|
|
42
|
+
<span id="<%= section.legacy_aref %>" class="legacy-anchor"></span>
|
|
41
43
|
<section id="<%= section.aref %>" class="documentation-section anchor-link">
|
|
42
44
|
<%- if section.title then %>
|
|
43
45
|
<header class="documentation-section-title">
|
|
@@ -157,7 +159,7 @@
|
|
|
157
159
|
</details>
|
|
158
160
|
</div>
|
|
159
161
|
<div class="method-source-code" id="<%= method.html_name %>-source">
|
|
160
|
-
<pre class="<%= method.source_language %>"
|
|
162
|
+
<pre class="<%= method.source_language %>"><%= method.markup_code %></pre>
|
|
161
163
|
</div>
|
|
162
164
|
<%- end %>
|
|
163
165
|
|
|
@@ -1190,6 +1190,26 @@ main .anchor-link:target {
|
|
|
1190
1190
|
scroll-margin-top: calc(var(--layout-header-height) + 2rem);
|
|
1191
1191
|
}
|
|
1192
1192
|
|
|
1193
|
+
/* Legacy anchor for backward compatibility with old label- prefix links */
|
|
1194
|
+
.legacy-anchor {
|
|
1195
|
+
display: block;
|
|
1196
|
+
position: relative;
|
|
1197
|
+
visibility: hidden;
|
|
1198
|
+
scroll-margin-top: calc(var(--layout-header-height) + 2rem);
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
/* When a legacy anchor is targeted, highlight the next heading sibling */
|
|
1202
|
+
.legacy-anchor:target + h1,
|
|
1203
|
+
.legacy-anchor:target + h2,
|
|
1204
|
+
.legacy-anchor:target + h3,
|
|
1205
|
+
.legacy-anchor:target + h4,
|
|
1206
|
+
.legacy-anchor:target + h5,
|
|
1207
|
+
.legacy-anchor:target + h6 {
|
|
1208
|
+
margin-left: calc(-1 * var(--space-5));
|
|
1209
|
+
padding-left: calc(var(--space-5) / 2);
|
|
1210
|
+
border-left: calc(var(--space-5) / 2) solid var(--color-border-default);
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1193
1213
|
|
|
1194
1214
|
/* Utility Classes */
|
|
1195
1215
|
.hide { display: none !important; }
|
|
@@ -276,7 +276,7 @@
|
|
|
276
276
|
* Initialize C syntax highlighting on page load
|
|
277
277
|
*/
|
|
278
278
|
function initHighlighting() {
|
|
279
|
-
const codeBlocks = document.querySelectorAll('pre
|
|
279
|
+
const codeBlocks = document.querySelectorAll('pre.c');
|
|
280
280
|
|
|
281
281
|
codeBlocks.forEach(block => {
|
|
282
282
|
if (block.getAttribute('data-highlighted') === 'true') {
|
|
@@ -33,6 +33,7 @@
|
|
|
33
33
|
</ol>
|
|
34
34
|
<% end %>
|
|
35
35
|
|
|
36
|
+
<span id="<%= h klass.legacy_aref %>" class="legacy-anchor"></span>
|
|
36
37
|
<h1 id="<%= h klass.aref %>" class="anchor-link <%= klass.type %>">
|
|
37
38
|
<%= klass.type %> <%= klass.full_name %>
|
|
38
39
|
</h1>
|
|
@@ -42,6 +43,7 @@
|
|
|
42
43
|
</section>
|
|
43
44
|
|
|
44
45
|
<%- klass.each_section do |section, constants, attributes| %>
|
|
46
|
+
<span id="<%= section.legacy_aref %>" class="legacy-anchor"></span>
|
|
45
47
|
<section id="<%= section.aref %>" class="documentation-section anchor-link">
|
|
46
48
|
<%- if section.title then %>
|
|
47
49
|
<header class="documentation-section-title">
|
|
@@ -92,6 +92,25 @@ main .anchor-link:target {
|
|
|
92
92
|
scroll-margin-top: 1rem;
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/* Legacy anchor for backward compatibility with old label- prefix links */
|
|
96
|
+
.legacy-anchor {
|
|
97
|
+
display: block;
|
|
98
|
+
position: relative;
|
|
99
|
+
visibility: hidden;
|
|
100
|
+
scroll-margin-top: 1rem;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/* When a legacy anchor is targeted, highlight the next heading sibling */
|
|
104
|
+
.legacy-anchor:target + h1,
|
|
105
|
+
.legacy-anchor:target + h2,
|
|
106
|
+
.legacy-anchor:target + h3,
|
|
107
|
+
.legacy-anchor:target + h4,
|
|
108
|
+
.legacy-anchor:target + h5,
|
|
109
|
+
.legacy-anchor:target + h6 {
|
|
110
|
+
margin-left: -10px;
|
|
111
|
+
border-left: 10px solid var(--border-color);
|
|
112
|
+
}
|
|
113
|
+
|
|
95
114
|
/* 4. Links */
|
|
96
115
|
a {
|
|
97
116
|
color: var(--link-color);
|
data/lib/rdoc/markdown.kpeg
CHANGED
data/lib/rdoc/markdown.rb
CHANGED
|
@@ -875,11 +875,7 @@ class RDoc::Markdown
|
|
|
875
875
|
# Wraps `text` in strike markup for rdoc inline formatting
|
|
876
876
|
|
|
877
877
|
def strike text
|
|
878
|
-
|
|
879
|
-
"~#{text}~"
|
|
880
|
-
else
|
|
881
|
-
"<s>#{text}</s>"
|
|
882
|
-
end
|
|
878
|
+
"<del>#{text}</del>"
|
|
883
879
|
end
|
|
884
880
|
|
|
885
881
|
##
|
|
@@ -89,12 +89,21 @@ class RDoc::Markup::AttributeManager
|
|
|
89
89
|
add_word_pair "*", "*", :BOLD, true
|
|
90
90
|
add_word_pair "_", "_", :EM, true
|
|
91
91
|
add_word_pair "+", "+", :TT, true
|
|
92
|
+
add_word_pair "`", "`", :TT, true
|
|
92
93
|
|
|
93
94
|
add_html "em", :EM, true
|
|
94
95
|
add_html "i", :EM, true
|
|
95
96
|
add_html "b", :BOLD, true
|
|
96
97
|
add_html "tt", :TT, true
|
|
97
98
|
add_html "code", :TT, true
|
|
99
|
+
add_html "s", :STRIKE, true
|
|
100
|
+
add_html "del", :STRIKE, true
|
|
101
|
+
|
|
102
|
+
@word_pair_chars = @matching_word_pairs.keys.join
|
|
103
|
+
|
|
104
|
+
# Matches a word pair delimiter (*, _, +, `) that is NOT already protected.
|
|
105
|
+
# Used by #protect_code_markup to escape delimiters inside <code>/<tt> tags.
|
|
106
|
+
@unprotected_word_pair_regexp = /([#{@word_pair_chars}])(?!#{PROTECT_ATTR})/
|
|
98
107
|
end
|
|
99
108
|
|
|
100
109
|
##
|
|
@@ -164,7 +173,7 @@ class RDoc::Markup::AttributeManager
|
|
|
164
173
|
}.keys
|
|
165
174
|
return if tags.empty?
|
|
166
175
|
tags = "[#{tags.join("")}](?!#{PROTECT_ATTR})"
|
|
167
|
-
all_tags = "[#{@
|
|
176
|
+
all_tags = "[#{@word_pair_chars}](?!#{PROTECT_ATTR})"
|
|
168
177
|
|
|
169
178
|
re = /(?:^|\W|#{all_tags})\K(#{tags})(\1*[#\\]?[\w:#{PROTECT_ATTR}.\/\[\]-]+?\S?)\1(?!\1)(?=#{all_tags}|\W|$)/
|
|
170
179
|
|
|
@@ -245,6 +254,23 @@ class RDoc::Markup::AttributeManager
|
|
|
245
254
|
@str.gsub!(/\\(\\[#{Regexp.escape @protectable.join}])/m, "\\1")
|
|
246
255
|
end
|
|
247
256
|
|
|
257
|
+
##
|
|
258
|
+
# Protects word pair delimiters (*, _, +) inside
|
|
259
|
+
# <code> and <tt> tags from being processed as inline formatting.
|
|
260
|
+
# For example, *bold* in +*bold*+ will NOT be rendered as bold.
|
|
261
|
+
|
|
262
|
+
def protect_code_markup
|
|
263
|
+
@str.gsub!(/<(code|tt)>(.*?)<\/\1>/im) do
|
|
264
|
+
tag = $1
|
|
265
|
+
content = $2
|
|
266
|
+
# Protect word pair delimiters (*, _, +) from being processed
|
|
267
|
+
escaped = content.gsub(@unprotected_word_pair_regexp, "\\1#{PROTECT_ATTR}")
|
|
268
|
+
# Protect HTML-like tags from being processed (e.g., <del> inside code)
|
|
269
|
+
escaped = escaped.gsub(/<(?!#{PROTECT_ATTR})/, "<#{PROTECT_ATTR}")
|
|
270
|
+
"<#{tag}>#{escaped}</#{tag}>"
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
248
274
|
##
|
|
249
275
|
# Unescapes regexp handling sequences of text
|
|
250
276
|
|
|
@@ -308,6 +334,7 @@ class RDoc::Markup::AttributeManager
|
|
|
308
334
|
@str = str.dup
|
|
309
335
|
|
|
310
336
|
mask_protected_sequences
|
|
337
|
+
protect_code_markup
|
|
311
338
|
|
|
312
339
|
@attrs = RDoc::Markup::AttrSpan.new @str.length, @exclusive_bitmap
|
|
313
340
|
|
data/lib/rdoc/markup/heading.rb
CHANGED
|
@@ -2,6 +2,33 @@
|
|
|
2
2
|
|
|
3
3
|
module RDoc
|
|
4
4
|
class Markup
|
|
5
|
+
# IMPORTANT! This weird workaround is required to ensure that RDoc can correctly deserializing Marshal data from
|
|
6
|
+
# older rubies. Older rubies have `Heading` as a struct, so if we change it to a class, deserialization fails
|
|
7
|
+
if RUBY_VERSION.start_with?("4.")
|
|
8
|
+
class Heading < Element
|
|
9
|
+
#: String
|
|
10
|
+
attr_reader :text
|
|
11
|
+
|
|
12
|
+
#: Integer
|
|
13
|
+
attr_accessor :level
|
|
14
|
+
|
|
15
|
+
#: (Integer, String) -> void
|
|
16
|
+
def initialize(level, text)
|
|
17
|
+
super()
|
|
18
|
+
|
|
19
|
+
@level = level
|
|
20
|
+
@text = text
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
#: (Object) -> bool
|
|
24
|
+
def ==(other)
|
|
25
|
+
other.is_a?(Heading) && other.level == @level && other.text == @text
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
else
|
|
29
|
+
Heading = Struct.new(:level, :text)
|
|
30
|
+
end
|
|
31
|
+
|
|
5
32
|
# A heading with a level (1-6) and text
|
|
6
33
|
#
|
|
7
34
|
# RDoc syntax:
|
|
@@ -13,13 +40,8 @@ module RDoc
|
|
|
13
40
|
# # Heading 1
|
|
14
41
|
# ## Heading 2
|
|
15
42
|
# ### Heading 3
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
attr_reader :text
|
|
19
|
-
|
|
20
|
-
#: Integer
|
|
21
|
-
attr_accessor :level
|
|
22
|
-
|
|
43
|
+
#
|
|
44
|
+
class Heading
|
|
23
45
|
# A singleton RDoc::Markup::ToLabel formatter for headings.
|
|
24
46
|
#: () -> RDoc::Markup::ToLabel
|
|
25
47
|
def self.to_label
|
|
@@ -43,38 +65,88 @@ module RDoc
|
|
|
43
65
|
end
|
|
44
66
|
end
|
|
45
67
|
|
|
46
|
-
#: (Integer, String) -> void
|
|
47
|
-
def initialize(level, text)
|
|
48
|
-
super()
|
|
49
|
-
|
|
50
|
-
@level = level
|
|
51
|
-
@text = text
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
#: (Object) -> bool
|
|
55
|
-
def ==(other)
|
|
56
|
-
other.is_a?(Heading) && other.level == @level && other.text == @text
|
|
57
|
-
end
|
|
58
|
-
|
|
59
68
|
# @override
|
|
60
69
|
#: (untyped) -> void
|
|
61
70
|
def accept(visitor)
|
|
62
71
|
visitor.accept_heading(self)
|
|
63
72
|
end
|
|
64
73
|
|
|
65
|
-
# An HTML-safe anchor reference for this header
|
|
74
|
+
# An HTML-safe anchor reference for this header using GitHub-style formatting:
|
|
75
|
+
# - Lowercase
|
|
76
|
+
# - Spaces converted to hyphens
|
|
77
|
+
# - Special characters removed (except hyphens)
|
|
78
|
+
#
|
|
79
|
+
# Examples:
|
|
80
|
+
# "Hello" -> "hello"
|
|
81
|
+
# "Hello World" -> "hello-world"
|
|
82
|
+
# "Foo Bar Baz" -> "foo-bar-baz"
|
|
83
|
+
#
|
|
66
84
|
#: () -> String
|
|
67
85
|
def aref
|
|
68
|
-
|
|
86
|
+
self.class.to_label.convert text.dup
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# An HTML-safe anchor reference using legacy RDoc formatting:
|
|
90
|
+
# - Prefixed with "label-"
|
|
91
|
+
# - Original case preserved
|
|
92
|
+
# - Spaces converted to + (URL encoding style)
|
|
93
|
+
# - Special characters percent-encoded
|
|
94
|
+
#
|
|
95
|
+
# Returns nil if it would be the same as the GitHub-style aref (no alias needed).
|
|
96
|
+
#
|
|
97
|
+
# Examples:
|
|
98
|
+
# "hello" -> "label-hello" (different due to label- prefix)
|
|
99
|
+
# "Hello" -> "label-Hello"
|
|
100
|
+
# "Hello World" -> "label-Hello+World"
|
|
101
|
+
# "Foo Bar Baz" -> "label-Foo+Bar+Baz"
|
|
102
|
+
#
|
|
103
|
+
#: () -> String?
|
|
104
|
+
def legacy_aref
|
|
105
|
+
"label-#{self.class.to_label.convert_legacy text.dup}"
|
|
69
106
|
end
|
|
70
107
|
|
|
71
|
-
# Creates a fully-qualified label which
|
|
108
|
+
# Creates a fully-qualified label (GitHub-style) which includes the context's aref prefix.
|
|
109
|
+
# This helps keep IDs unique in HTML when headings appear within class/method documentation.
|
|
110
|
+
#
|
|
111
|
+
# Examples (without context):
|
|
112
|
+
# "Hello World" -> "hello-world"
|
|
113
|
+
#
|
|
114
|
+
# Examples (with context being class Foo):
|
|
115
|
+
# "Hello World" -> "class-foo-hello-world"
|
|
116
|
+
#
|
|
117
|
+
# Examples (with context being method #bar):
|
|
118
|
+
# "Hello World" -> "method-i-bar-hello-world"
|
|
119
|
+
#
|
|
72
120
|
#: (RDoc::Context?) -> String
|
|
73
121
|
def label(context = nil)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
122
|
+
result = +""
|
|
123
|
+
result << "#{context.aref}-" if context&.respond_to?(:aref)
|
|
124
|
+
result << aref
|
|
125
|
+
result
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
# Creates a fully-qualified legacy label for backward compatibility.
|
|
129
|
+
# This is used to generate a secondary ID attribute on the heading's inner anchor,
|
|
130
|
+
# allowing old-style links (e.g., #label-Hello+World) to continue working.
|
|
131
|
+
#
|
|
132
|
+
# Examples (without context):
|
|
133
|
+
# "hello" -> "label-hello"
|
|
134
|
+
# "Hello World" -> "label-Hello+World"
|
|
135
|
+
#
|
|
136
|
+
# Examples (with context being class Foo):
|
|
137
|
+
# "hello" -> "class-Foo-label-hello"
|
|
138
|
+
# "Hello World" -> "class-Foo-label-Hello+World"
|
|
139
|
+
#
|
|
140
|
+
#: (RDoc::Context?) -> String
|
|
141
|
+
def legacy_label(context = nil)
|
|
142
|
+
result = +""
|
|
143
|
+
if context&.respond_to?(:legacy_aref)
|
|
144
|
+
result << "#{context.legacy_aref}-"
|
|
145
|
+
elsif context&.respond_to?(:aref)
|
|
146
|
+
result << "#{context.aref}-"
|
|
147
|
+
end
|
|
148
|
+
result << legacy_aref
|
|
149
|
+
result
|
|
78
150
|
end
|
|
79
151
|
|
|
80
152
|
# HTML markup of the text of this label without the surrounding header element.
|
data/lib/rdoc/markup/to_html.rb
CHANGED
|
@@ -221,10 +221,15 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
221
221
|
|
|
222
222
|
def accept_verbatim(verbatim)
|
|
223
223
|
text = verbatim.text.rstrip
|
|
224
|
+
format = verbatim.format
|
|
224
225
|
|
|
225
226
|
klass = nil
|
|
226
227
|
|
|
227
|
-
|
|
228
|
+
# Apply Ruby syntax highlighting if
|
|
229
|
+
# - explicitly marked as Ruby (via ruby? which accepts :ruby or :rb)
|
|
230
|
+
# - no format specified but the text is parseable as Ruby
|
|
231
|
+
# Otherwise, add language class when applicable and skip Ruby highlighting
|
|
232
|
+
content = if verbatim.ruby? || (format.nil? && parseable?(text))
|
|
228
233
|
begin
|
|
229
234
|
tokens = RDoc::Parser::RipperStateLex.parse text
|
|
230
235
|
klass = ' class="ruby"'
|
|
@@ -236,6 +241,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
236
241
|
CGI.escapeHTML text
|
|
237
242
|
end
|
|
238
243
|
else
|
|
244
|
+
klass = " class=\"#{format}\"" if format
|
|
239
245
|
CGI.escapeHTML text
|
|
240
246
|
end
|
|
241
247
|
|
|
@@ -306,6 +312,13 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
306
312
|
level = [6, heading.level].min
|
|
307
313
|
|
|
308
314
|
label = heading.label @code_object
|
|
315
|
+
legacy_label = heading.legacy_label @code_object
|
|
316
|
+
|
|
317
|
+
# Add legacy anchor before the heading for backward compatibility.
|
|
318
|
+
# This allows old links with label- prefix to still work.
|
|
319
|
+
if @options.output_decoration && !@options.pipe
|
|
320
|
+
@res << "\n<span id=\"#{legacy_label}\" class=\"legacy-anchor\"></span>"
|
|
321
|
+
end
|
|
309
322
|
|
|
310
323
|
@res << if @options.output_decoration
|
|
311
324
|
"\n<h#{level} id=\"#{label}\">"
|
|
@@ -362,14 +375,18 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
362
375
|
end
|
|
363
376
|
|
|
364
377
|
##
|
|
365
|
-
#
|
|
366
|
-
#
|
|
378
|
+
# Generates an HTML link or image tag for the given +url+ and +text+.
|
|
379
|
+
#
|
|
380
|
+
# - Image URLs (http/https/link ending in .gif, .png, .jpg, .jpeg, .bmp)
|
|
381
|
+
# become <img> tags
|
|
382
|
+
# - File references (.rb, .rdoc, .md) are converted to .html paths
|
|
383
|
+
# - Anchor URLs (#foo) pass through unchanged for GitHub-style header linking
|
|
384
|
+
# - Footnote links get wrapped in <sup> tags
|
|
367
385
|
|
|
368
386
|
def gen_url(url, text)
|
|
369
387
|
scheme, url, id = parse_url url
|
|
370
388
|
|
|
371
|
-
if %w[http https link].include?(scheme)
|
|
372
|
-
url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
|
|
389
|
+
if %w[http https link].include?(scheme) && url =~ /\.(gif|png|jpg|jpeg|bmp)\z/
|
|
373
390
|
"<img src=\"#{url}\" />"
|
|
374
391
|
else
|
|
375
392
|
if scheme != 'link' and %r%\A((?!https?:)(?:[^/#]*/)*+)([^/#]+)\.(rb|rdoc|md)(?=\z|#)%i =~ url
|
|
@@ -381,9 +398,11 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
381
398
|
|
|
382
399
|
link = "<a#{id} href=\"#{url}\">#{text}</a>"
|
|
383
400
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
401
|
+
if /"foot/.match?(id)
|
|
402
|
+
"<sup>#{link}</sup>"
|
|
403
|
+
else
|
|
404
|
+
link
|
|
405
|
+
end
|
|
387
406
|
end
|
|
388
407
|
end
|
|
389
408
|
|
|
@@ -400,9 +419,10 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
|
|
|
400
419
|
# Maps attributes to HTML tags
|
|
401
420
|
|
|
402
421
|
def init_tags
|
|
403
|
-
add_tag :BOLD,
|
|
404
|
-
add_tag :TT,
|
|
405
|
-
add_tag :EM,
|
|
422
|
+
add_tag :BOLD, "<strong>", "</strong>"
|
|
423
|
+
add_tag :TT, "<code>", "</code>"
|
|
424
|
+
add_tag :EM, "<em>", "</em>"
|
|
425
|
+
add_tag :STRIKE, "<del>", "</del>"
|
|
406
426
|
end
|
|
407
427
|
|
|
408
428
|
##
|
|
@@ -169,14 +169,33 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
|
|
|
169
169
|
end
|
|
170
170
|
|
|
171
171
|
if label
|
|
172
|
+
# Convert label to GitHub-style anchor format
|
|
173
|
+
# First convert + to space (URL encoding), then apply GitHub-style rules
|
|
174
|
+
formatted_label = RDoc::Text.to_anchor(label.tr('+', ' '))
|
|
175
|
+
|
|
176
|
+
# Case 1: Path already has an anchor (e.g., method link)
|
|
177
|
+
# Input: C1#method@label -> path="C1.html#method-i-m"
|
|
178
|
+
# Output: C1.html#method-i-m-label
|
|
172
179
|
if path =~ /#/
|
|
173
|
-
path << "
|
|
174
|
-
|
|
175
|
-
|
|
180
|
+
path << "-#{formatted_label}"
|
|
181
|
+
|
|
182
|
+
# Case 2: Label matches a section title
|
|
183
|
+
# Input: C1@Section -> path="C1.html", section "Section" exists
|
|
184
|
+
# Output: C1.html#section (uses section.aref for GitHub-style)
|
|
185
|
+
elsif (section = ref&.sections&.find { |s| label.tr('+', ' ') == s.title })
|
|
186
|
+
path << "##{section.aref}"
|
|
187
|
+
|
|
188
|
+
# Case 3: Ref has an aref (class/module context)
|
|
189
|
+
# Input: C1@heading -> path="C1.html", ref=C1 class
|
|
190
|
+
# Output: C1.html#class-c1-heading
|
|
176
191
|
elsif ref.respond_to?(:aref)
|
|
177
|
-
path << "##{ref.aref}
|
|
192
|
+
path << "##{ref.aref}-#{formatted_label}"
|
|
193
|
+
|
|
194
|
+
# Case 4: No context, just the label (e.g., TopLevel/file)
|
|
195
|
+
# Input: README@section -> path="README_md.html"
|
|
196
|
+
# Output: README_md.html#section
|
|
178
197
|
else
|
|
179
|
-
path << "
|
|
198
|
+
path << "##{formatted_label}"
|
|
180
199
|
end
|
|
181
200
|
end
|
|
182
201
|
|
data/lib/rdoc/markup/to_label.rb
CHANGED
|
@@ -28,11 +28,21 @@ class RDoc::Markup::ToLabel < RDoc::Markup::Formatter
|
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
##
|
|
31
|
-
# Converts +text+ to an HTML-safe label
|
|
31
|
+
# Converts +text+ to an HTML-safe label using GitHub-style anchor formatting.
|
|
32
32
|
|
|
33
33
|
def convert(text)
|
|
34
34
|
label = convert_flow @am.flow text
|
|
35
35
|
|
|
36
|
+
RDoc::Text.to_anchor(label)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
##
|
|
40
|
+
# Converts +text+ to an HTML-safe label using legacy RDoc formatting.
|
|
41
|
+
# Used for generating backward-compatible anchor aliases.
|
|
42
|
+
|
|
43
|
+
def convert_legacy(text)
|
|
44
|
+
label = convert_flow @am.flow text
|
|
45
|
+
|
|
36
46
|
CGI.escape(label).gsub('%', '-').sub(/^-/, '')
|
|
37
47
|
end
|
|
38
48
|
|