rdoc 7.0.1 → 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 (44) 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 +49 -11
  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/darkfish.rb +3 -1
  10. data/lib/rdoc/generator/template/aliki/_sidebar_pages.rhtml +1 -1
  11. data/lib/rdoc/generator/template/aliki/class.rhtml +10 -8
  12. data/lib/rdoc/generator/template/aliki/css/rdoc.css +20 -1
  13. data/lib/rdoc/generator/template/aliki/index.rhtml +1 -1
  14. data/lib/rdoc/generator/template/aliki/js/aliki.js +24 -17
  15. data/lib/rdoc/generator/template/aliki/js/c_highlighter.js +1 -1
  16. data/lib/rdoc/generator/template/aliki/js/search_controller.js +9 -0
  17. data/lib/rdoc/generator/template/aliki/page.rhtml +1 -1
  18. data/lib/rdoc/generator/template/aliki/servlet_not_found.rhtml +1 -1
  19. data/lib/rdoc/generator/template/aliki/servlet_root.rhtml +1 -1
  20. data/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +1 -1
  21. data/lib/rdoc/generator/template/darkfish/class.rhtml +8 -6
  22. data/lib/rdoc/generator/template/darkfish/css/rdoc.css +19 -0
  23. data/lib/rdoc/markdown.kpeg +1 -5
  24. data/lib/rdoc/markdown.rb +1 -5
  25. data/lib/rdoc/markup/attribute_manager.rb +28 -1
  26. data/lib/rdoc/markup/blank_line.rb +25 -23
  27. data/lib/rdoc/markup/element.rb +21 -0
  28. data/lib/rdoc/markup/hard_break.rb +30 -27
  29. data/lib/rdoc/markup/heading.rb +166 -77
  30. data/lib/rdoc/markup/raw.rb +52 -55
  31. data/lib/rdoc/markup/table.rb +48 -40
  32. data/lib/rdoc/markup/to_html.rb +31 -11
  33. data/lib/rdoc/markup/to_html_crossref.rb +24 -5
  34. data/lib/rdoc/markup/to_label.rb +11 -1
  35. data/lib/rdoc/markup/verbatim.rb +1 -1
  36. data/lib/rdoc/markup.rb +3 -2
  37. data/lib/rdoc/parser/changelog.rb +8 -0
  38. data/lib/rdoc/text.rb +15 -0
  39. data/lib/rdoc/token_stream.rb +4 -8
  40. data/lib/rdoc/version.rb +1 -1
  41. data/rdoc.gemspec +2 -2
  42. metadata +6 -7
  43. data/ExampleMarkdown.md +0 -39
  44. 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
@@ -807,11 +843,13 @@ class RDoc::ClassModule < RDoc::Context
807
843
  cm_alias = cm.dup
808
844
  cm_alias.name = const.name
809
845
 
810
- # Don't move top-level aliases under Object, they look ugly there
811
- unless RDoc::TopLevel === cm_alias.parent then
846
+ if full_name == 'Object'
847
+ # Don't move top-level aliases under Object, they look ugly there
848
+ cm_alias.parent = top_level
849
+ else
812
850
  cm_alias.parent = self
813
- cm_alias.full_name = nil # force update for new parent
814
851
  end
852
+ cm_alias.full_name = nil # force update for new parent
815
853
 
816
854
  cm_alias.aliases.clear
817
855
  cm_alias.is_alias_for = cm
@@ -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.\/]+$/
@@ -356,7 +356,9 @@ class RDoc::Generator::Darkfish
356
356
 
357
357
  current = nil
358
358
 
359
- @classes.each do |klass|
359
+ # Document files are generated only for non-alias classes/modules
360
+ @classes.reject(&:is_alias_for).each do |klass|
361
+
360
362
  current = klass
361
363
 
362
364
  generate_class klass, template_file
@@ -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>
@@ -3,7 +3,7 @@
3
3
  <%= render '_header.rhtml' %>
4
4
  <%= render '_sidebar_toggle.rhtml' %>
5
5
 
6
- <nav id="navigation" role="navigation">
6
+ <nav id="navigation" role="navigation" hidden>
7
7
  <%= render '_sidebar_pages.rhtml' %>
8
8
  <%= render '_sidebar_sections.rhtml' %>
9
9
  <%= render '_sidebar_ancestors.rhtml' %>
@@ -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">
@@ -110,10 +112,10 @@
110
112
  </section>
111
113
  <%- end %>
112
114
 
113
- <%- klass.methods_by_type(section).each do |type, visibilities|
114
- next if visibilities.empty?
115
- visibilities.each do |visibility, methods|
116
- next if methods.empty? %>
115
+ <%- klass.methods_by_type(section).each do |type, visibilities| %>
116
+ <%- next if visibilities.empty? %>
117
+ <%- visibilities.each do |visibility, methods| %>
118
+ <%- next if methods.empty? %>
117
119
  <section id="<%= visibility %>-<%= type %>-<%= section.aref %>-method-details" class="method-section anchor-link">
118
120
  <header>
119
121
  <h3 id="<%= visibility %>-<%= type %>-methods"><a href="#<%= visibility %>-<%= type %>-methods"><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</a></h3>
@@ -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
 
@@ -206,8 +208,8 @@
206
208
 
207
209
  <%- end %>
208
210
  </section>
209
- <%- end
210
- end %>
211
+ <%- end %>
212
+ <%- end %>
211
213
  </section>
212
214
  <%- end %>
213
215
  </main>
@@ -690,7 +690,6 @@ nav ul li {
690
690
  }
691
691
 
692
692
  nav ul li a {
693
- padding: var(--space-1) 0;
694
693
  transition:
695
694
  color var(--transition-fast),
696
695
  transform var(--transition-fast),
@@ -1191,6 +1190,26 @@ main .anchor-link:target {
1191
1190
  scroll-margin-top: calc(var(--layout-header-height) + 2rem);
1192
1191
  }
1193
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
+
1194
1213
 
1195
1214
  /* Utility Classes */
1196
1215
  .hide { display: none !important; }
@@ -3,7 +3,7 @@
3
3
  <%= render '_header.rhtml' %>
4
4
  <%= render '_sidebar_toggle.rhtml' %>
5
5
 
6
- <nav id="navigation" role="navigation">
6
+ <nav id="navigation" role="navigation" hidden>
7
7
  <%= render '_sidebar_pages.rhtml' %>
8
8
  <%= render '_sidebar_classes.rhtml' %>
9
9
  </nav>
@@ -67,15 +67,7 @@ function createSearchInstance(input, result) {
67
67
  }
68
68
 
69
69
  search.select = function(result) {
70
- let href = result.firstChild.firstChild.href;
71
- const query = this.input.value;
72
- if (query) {
73
- const url = new URL(href, window.location.origin);
74
- url.searchParams.set('q', query);
75
- url.searchParams.set('nav', '0');
76
- href = url.toString();
77
- }
78
- window.location.href = href;
70
+ window.location.href = result.firstChild.firstChild.href;
79
71
  }
80
72
 
81
73
  search.scrollIntoView = search.scrollInWindow;
@@ -97,15 +89,27 @@ function hookSearch() {
97
89
  const search = createSearchInstance(input, result);
98
90
  if (!search) return;
99
91
 
92
+ // Hide search results when clicking outside the search area
93
+ document.addEventListener('click', (e) => {
94
+ if (!e.target.closest('.navbar-search-desktop')) {
95
+ search.hide();
96
+ }
97
+ });
98
+
99
+ // Show search results when focusing on input (if there's a query)
100
+ input.addEventListener('focus', () => {
101
+ if (input.value.trim()) {
102
+ search.show();
103
+ }
104
+ });
105
+
100
106
  // Check for ?q= URL parameter and trigger search automatically
101
107
  if (typeof URLSearchParams !== 'undefined') {
102
108
  const urlParams = new URLSearchParams(window.location.search);
103
109
  const queryParam = urlParams.get('q');
104
110
  if (queryParam) {
105
- const navParam = urlParams.get('nav');
106
- const autoSelect = navParam !== '0';
107
111
  input.value = queryParam;
108
- search.search(queryParam, autoSelect);
112
+ search.search(queryParam, false);
109
113
  }
110
114
  }
111
115
  }
@@ -158,9 +162,12 @@ function hookSidebar() {
158
162
  });
159
163
 
160
164
  const isSmallViewport = window.matchMedia("(max-width: 1023px)").matches;
161
- if (isSmallViewport) {
162
- closeNav();
163
165
 
166
+ // The sidebar is hidden by default with the `hidden` attribute
167
+ // On large viewports, we display the sidebar with JavaScript
168
+ // This is better than the opposite approach of hiding it with JavaScript
169
+ // because it avoids flickering the sidebar when the page is loaded, especially on mobile devices
170
+ if (isSmallViewport) {
164
171
  // Close nav when clicking links inside it
165
172
  document.addEventListener('click', (e) => {
166
173
  if (e.target.closest('#navigation a')) {
@@ -176,6 +183,8 @@ function hookSidebar() {
176
183
  closeNav();
177
184
  }
178
185
  });
186
+ } else {
187
+ openNav();
179
188
  }
180
189
  }
181
190
 
@@ -378,9 +387,7 @@ function hookSearchModal() {
378
387
  if (queryParam && isSmallViewport) {
379
388
  openSearchModal();
380
389
  searchInput.value = queryParam;
381
- const navParam = urlParams.get('nav');
382
- const autoSelect = navParam !== '0';
383
- mobileSearch.search(queryParam, autoSelect);
390
+ mobileSearch.search(queryParam, false);
384
391
  }
385
392
  }
386
393
  }
@@ -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') {
@@ -116,5 +116,14 @@ SearchController.prototype = Object.assign({}, SearchNavigation, new function()
116
116
  });
117
117
  }
118
118
 
119
+ this.hide = function() {
120
+ this.result.setAttribute('aria-expanded', 'false');
121
+ this.setNavigationActive(false);
122
+ }
123
+
124
+ this.show = function() {
125
+ this.result.setAttribute('aria-expanded', 'true');
126
+ this.setNavigationActive(true);
127
+ }
119
128
  });
120
129
 
@@ -3,7 +3,7 @@
3
3
  <%= render '_header.rhtml' %>
4
4
  <%= render '_sidebar_toggle.rhtml' %>
5
5
 
6
- <nav id="navigation" role="navigation">
6
+ <nav id="navigation" role="navigation" hidden>
7
7
  <%= render '_sidebar_pages.rhtml' %>
8
8
  <%= render '_sidebar_classes.rhtml' %>
9
9
  </nav>
@@ -1,7 +1,7 @@
1
1
  <body role="document">
2
2
  <%= render '_sidebar_toggle.rhtml' %>
3
3
 
4
- <nav id="navigation" role="navigation">
4
+ <nav id="navigation" role="navigation" hidden>
5
5
  <%= render '_sidebar_pages.rhtml' %>
6
6
  <%= render '_sidebar_classes.rhtml' %>
7
7
  </nav>
@@ -1,7 +1,7 @@
1
1
  <body role="document">
2
2
  <%= render '_sidebar_toggle.rhtml' %>
3
3
 
4
- <nav id="navigation" role="navigation">
4
+ <nav id="navigation" role="navigation" hidden>
5
5
  <div id="project-navigation">
6
6
  <div id="home-section" class="nav-section">
7
7
  <h2>
@@ -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">
@@ -117,10 +119,10 @@
117
119
  </section>
118
120
  <%- end %>
119
121
 
120
- <%- klass.methods_by_type(section).each do |type, visibilities|
121
- next if visibilities.empty?
122
- visibilities.each do |visibility, methods|
123
- next if methods.empty? %>
122
+ <%- klass.methods_by_type(section).each do |type, visibilities| %>
123
+ <%- next if visibilities.empty? %>
124
+ <%- visibilities.each do |visibility, methods| %>
125
+ <%- next if methods.empty? %>
124
126
  <section id="<%= visibility %>-<%= type %>-<%= section.aref %>-method-details" class="method-section anchor-link">
125
127
  <header>
126
128
  <h3><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
@@ -213,8 +215,8 @@
213
215
 
214
216
  <%- end %>
215
217
  </section>
216
- <%- end
217
- end %>
218
+ <%- end %>
219
+ <%- end %>
218
220
  </section>
219
221
  <%- end %>
220
222
  </main>
@@ -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