rdoc 7.0.2 → 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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +9 -0
  3. data/README.md +70 -4
  4. data/doc/markup_reference/markdown.md +558 -0
  5. data/doc/markup_reference/rdoc.rdoc +1169 -0
  6. data/lib/rdoc/code_object/class_module.rb +44 -8
  7. data/lib/rdoc/code_object/context/section.rb +20 -1
  8. data/lib/rdoc/cross_reference.rb +30 -21
  9. data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +1 -1
  10. data/lib/rdoc/generator/template/aliki/class.rhtml +3 -1
  11. data/lib/rdoc/generator/template/aliki/css/rdoc.css +20 -0
  12. data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +1 -1
  13. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +1 -1
  14. data/lib/rdoc/generator/template/darkfish/class.rhtml +2 -0
  15. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +19 -0
  16. data/lib/rdoc/markdown.kpeg +1 -5
  17. data/lib/rdoc/markdown.rb +1 -5
  18. data/lib/rdoc/markup/attribute_manager.rb +28 -1
  19. data/lib/rdoc/markup/blank_line.rb +25 -23
  20. data/lib/rdoc/markup/element.rb +21 -0
  21. data/lib/rdoc/markup/hard_break.rb +30 -27
  22. data/lib/rdoc/markup/heading.rb +166 -77
  23. data/lib/rdoc/markup/raw.rb +52 -55
  24. data/lib/rdoc/markup/table.rb +48 -40
  25. data/lib/rdoc/markup/to_html.rb +31 -11
  26. data/lib/rdoc/markup/to_html_crossref.rb +24 -5
  27. data/lib/rdoc/markup/to_label.rb +11 -1
  28. data/lib/rdoc/markup/verbatim.rb +1 -1
  29. data/lib/rdoc/markup.rb +3 -2
  30. data/lib/rdoc/parser/changelog.rb +8 -0
  31. data/lib/rdoc/text.rb +15 -0
  32. data/lib/rdoc/token_stream.rb +4 -8
  33. data/lib/rdoc/version.rb +1 -1
  34. data/rdoc.gemspec +2 -2
  35. metadata +6 -7
  36. data/ExampleMarkdown.md +0 -39
  37. data/ExampleRDoc.rdoc +0 -210
@@ -30,7 +30,22 @@ class RDoc::ClassModule < RDoc::Context
30
30
  attr_accessor :constant_aliases
31
31
 
32
32
  ##
33
- # Comment and the location it came from. Use #add_comment to add comments
33
+ # An array of `[comment, location]` pairs documenting this class/module.
34
+ # Use #add_comment to add comments.
35
+ #
36
+ # Before marshalling:
37
+ # - +comment+ is a String
38
+ # - +location+ is an RDoc::TopLevel
39
+ #
40
+ # After unmarshalling:
41
+ # - +comment+ is an RDoc::Markup::Document
42
+ # - +location+ is a filename String
43
+ #
44
+ # These type changes are acceptable (for now) because:
45
+ # - +comment+: Both String and Document respond to #empty?, and #parse
46
+ # returns Document as-is (see RDoc::Text#parse)
47
+ # - +location+: Only used by #parse to set Document#file, which accepts
48
+ # both TopLevel (extracts relative_name) and String
34
49
 
35
50
  attr_accessor :comment_location
36
51
 
@@ -110,7 +125,7 @@ class RDoc::ClassModule < RDoc::Context
110
125
  @is_alias_for = nil
111
126
  @name = name
112
127
  @superclass = superclass
113
- @comment_location = [] # [[comment, location]]
128
+ @comment_location = [] # Array of [comment, location] pairs
114
129
 
115
130
  super()
116
131
  end
@@ -173,10 +188,26 @@ class RDoc::ClassModule < RDoc::Context
173
188
  end
174
189
 
175
190
  ##
176
- # HTML fragment reference for this module or class. See
177
- # RDoc::NormalClass#aref and RDoc::NormalModule#aref
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
178
197
 
179
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
180
211
  "#{aref_prefix}-#{full_name}"
181
212
  end
182
213
 
@@ -379,10 +410,10 @@ class RDoc::ClassModule < RDoc::Context
379
410
 
380
411
  @comment = RDoc::Comment.from_document document
381
412
 
382
- @comment_location = if RDoc::Markup::Document === document.parts.first then
383
- document
413
+ @comment_location = if document.parts.first.is_a?(RDoc::Markup::Document)
414
+ document.parts.map { |doc| [doc, doc.file] }
384
415
  else
385
- RDoc::Markup::Document.new document
416
+ [[document, document.file]]
386
417
  end
387
418
 
388
419
  array[5].each do |name, rw, visibility, singleton, file|
@@ -462,7 +493,12 @@ class RDoc::ClassModule < RDoc::Context
462
493
  document = document.merge other_document
463
494
 
464
495
  @comment = RDoc::Comment.from_document(document)
465
- @comment_location = document
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
466
502
  end
467
503
 
468
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
 
@@ -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 resolve_method(name)
143
+ def resolve_local_symbol(name)
138
144
  ref = nil
145
+ type = nil
146
+ container = nil
139
147
 
140
- if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
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
- method = $3
155
+ symbol = $3
144
156
  else
145
- method = "#{type}#{$3}"
157
+ symbol = "#{type}#{$3}"
146
158
  end
147
159
  container = @context.find_symbol_module($1)
148
- elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
160
+ when /^([.#]|::)#{METHOD_REGEXP_STR}/o then
149
161
  type = $1
150
162
  if '.' == type
151
- method = $2
163
+ symbol = $2
152
164
  else
153
- method = "#{type}#{$2}"
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' == method then # AnyClassName.new will be class method
165
- ref = container.find_local_symbol method
166
- ref = container.find_ancestor_local_symbol method unless ref
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 "::#{method}"
169
- ref = container.find_ancestor_local_symbol "::#{method}" unless ref
170
- ref = container.find_local_symbol "##{method}" unless ref
171
- ref = container.find_ancestor_local_symbol "##{method}" unless ref
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 method
175
- ref = container.find_ancestor_local_symbol method unless ref
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 = resolve_method name unless 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.\/]+$/
@@ -35,7 +35,7 @@
35
35
  <%= h f.page_name %>
36
36
  </a>
37
37
  </li>
38
- <%- next %>
38
+ <%- next -%>
39
39
  <%- end %>
40
40
 
41
41
  <li>
@@ -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 %>" data-language="<%= method.source_language %>"><%= method.markup_code %></pre>
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[data-language="c"]');
279
+ const codeBlocks = document.querySelectorAll('pre.c');
280
280
 
281
281
  codeBlocks.forEach(block => {
282
282
  if (block.getAttribute('data-highlighted') === 'true') {
@@ -13,7 +13,7 @@
13
13
  <%- f = files.shift %>
14
14
  <%- if files.empty? %>
15
15
  <li><a href="<%= rel_prefix %>/<%= h f.path %>"><%= h f.page_name %></a></li>
16
- <%- next %>
16
+ <%- next -%>
17
17
  <%- end %>
18
18
  <li><details<%= ' open' if dir == n %>><summary><%
19
19
  if n == f.page_name
@@ -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);
@@ -490,11 +490,7 @@
490
490
  # Wraps `text` in strike markup for rdoc inline formatting
491
491
 
492
492
  def strike text
493
- if text =~ /\A[a-z\d.\/-]+\z/i then
494
- "~#{text}~"
495
- else
496
- "<s>#{text}</s>"
497
- end
493
+ "<del>#{text}</del>"
498
494
  end
499
495
 
500
496
  ##
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
- if text =~ /\A[a-z\d.\/-]+\z/i then
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 = "[#{@matching_word_pairs.keys.join("")}](?!#{PROTECT_ATTR})"
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
 
@@ -1,27 +1,29 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # An empty line. This class is a singleton.
4
2
 
5
- class RDoc::Markup::BlankLine
6
-
7
- @instance = new
8
-
9
- ##
10
- # RDoc::Markup::BlankLine is a singleton
11
-
12
- def self.new
13
- @instance
3
+ module RDoc
4
+ class Markup
5
+ # An empty line
6
+ class BlankLine < Element
7
+ @instance = new
8
+
9
+ # RDoc::Markup::BlankLine is a singleton
10
+ #: () -> BlankLine
11
+ def self.new
12
+ @instance
13
+ end
14
+
15
+ # Calls #accept_blank_line on +visitor+
16
+ # @override
17
+ #: (untyped) -> void
18
+ def accept(visitor)
19
+ visitor.accept_blank_line(self)
20
+ end
21
+
22
+ # @override
23
+ #: (PP) -> void
24
+ def pretty_print(q) # :nodoc:
25
+ q.text("blankline")
26
+ end
27
+ end
14
28
  end
15
-
16
- ##
17
- # Calls #accept_blank_line on +visitor+
18
-
19
- def accept(visitor)
20
- visitor.accept_blank_line self
21
- end
22
-
23
- def pretty_print(q) # :nodoc:
24
- q.text 'blankline'
25
- end
26
-
27
29
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RDoc
4
+ class Markup
5
+ # Base class defining the interface for all markup elements found in documentation
6
+ # @abstract
7
+ class Element
8
+ # @abstract
9
+ #: (untyped) -> void
10
+ def accept(visitor)
11
+ raise NotImplementedError, "#{self.class} must implement the accept method"
12
+ end
13
+
14
+ # @abstract
15
+ #: (PP) -> void
16
+ def pretty_print(q)
17
+ raise NotImplementedError, "#{self.class} must implement the pretty_print method"
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,31 +1,34 @@
1
1
  # frozen_string_literal: true
2
- ##
3
- # A hard-break in the middle of a paragraph.
4
2
 
5
- class RDoc::Markup::HardBreak
6
-
7
- @instance = new
8
-
9
- ##
10
- # RDoc::Markup::HardBreak is a singleton
11
-
12
- def self.new
13
- @instance
14
- end
15
-
16
- ##
17
- # Calls #accept_hard_break on +visitor+
18
-
19
- def accept(visitor)
20
- visitor.accept_hard_break self
3
+ module RDoc
4
+ class Markup
5
+ # A hard-break in the middle of a paragraph.
6
+ class HardBreak < Element
7
+ @instance = new
8
+
9
+ # RDoc::Markup::HardBreak is a singleton
10
+ #: () -> HardBreak
11
+ def self.new
12
+ @instance
13
+ end
14
+
15
+ # Calls #accept_hard_break on +visitor+
16
+ # @override
17
+ #: (untyped) -> void
18
+ def accept(visitor)
19
+ visitor.accept_hard_break(self)
20
+ end
21
+
22
+ #: (top) -> bool
23
+ def ==(other) # :nodoc:
24
+ self.class === other
25
+ end
26
+
27
+ # @override
28
+ #: (PP) -> void
29
+ def pretty_print(q) # :nodoc:
30
+ q.text("[break]")
31
+ end
32
+ end
21
33
  end
22
-
23
- def ==(other) # :nodoc:
24
- self.class === other
25
- end
26
-
27
- def pretty_print(q) # :nodoc:
28
- q.text "[break]"
29
- end
30
-
31
34
  end