Skip to content

Commit 1298786

Browse files
st0012claude
andcommitted
Fix lint issues and legacy anchor casing bug
- Change legacy anchor elements from <a> to <span> to fix lint errors (accessibility: <a> elements require href attribute) - Fix legacy anchor casing: use legacy_aref for context prefix to preserve original casing (e.g., module-RDoc instead of module-rdoc) - Add regression tests for legacy anchor casing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 12e6393 commit 1298786

8 files changed

Lines changed: 56 additions & 21 deletions

File tree

lib/rdoc/generator/template/aliki/class.rhtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
</ol>
3030
<% end %>
3131

32-
<a id="<%= h klass.legacy_aref %>" class="legacy-anchor"></a>
32+
<span id="<%= h klass.legacy_aref %>" class="legacy-anchor"></span>
3333
<h1 id="<%= h klass.aref %>" class="anchor-link <%= klass.type %>">
3434
<%= klass.type %> <%= klass.full_name %>
3535
</h1>
@@ -39,7 +39,7 @@
3939
</section>
4040

4141
<%- klass.each_section do |section, constants, attributes| %>
42-
<a id="<%= section.legacy_aref %>" class="legacy-anchor"></a>
42+
<span id="<%= section.legacy_aref %>" class="legacy-anchor"></span>
4343
<section id="<%= section.aref %>" class="documentation-section anchor-link">
4444
<%- if section.title then %>
4545
<header class="documentation-section-title">

lib/rdoc/generator/template/darkfish/class.rhtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
</ol>
3434
<% end %>
3535

36-
<a id="<%= h klass.legacy_aref %>" class="legacy-anchor"></a>
36+
<span id="<%= h klass.legacy_aref %>" class="legacy-anchor"></span>
3737
<h1 id="<%= h klass.aref %>" class="anchor-link <%= klass.type %>">
3838
<%= klass.type %> <%= klass.full_name %>
3939
</h1>
@@ -43,7 +43,7 @@
4343
</section>
4444

4545
<%- klass.each_section do |section, constants, attributes| %>
46-
<a id="<%= section.legacy_aref %>" class="legacy-anchor"></a>
46+
<span id="<%= section.legacy_aref %>" class="legacy-anchor"></span>
4747
<section id="<%= section.aref %>" class="documentation-section anchor-link">
4848
<%- if section.title then %>
4949
<header class="documentation-section-title">

lib/rdoc/markup/heading.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -125,13 +125,17 @@ def label(context = nil)
125125
# "Hello World" -> "label-Hello+World"
126126
#
127127
# Examples (with context being class Foo):
128-
# "hello" -> "class-foo-label-hello"
129-
# "Hello World" -> "class-foo-label-Hello+World"
128+
# "hello" -> "class-Foo-label-hello"
129+
# "Hello World" -> "class-Foo-label-Hello+World"
130130
#
131131
#: (RDoc::Context?) -> String
132132
def legacy_label(context = nil)
133133
result = +""
134-
result << "#{context.aref}-" if context&.respond_to?(:aref)
134+
if context&.respond_to?(:legacy_aref)
135+
result << "#{context.legacy_aref}-"
136+
elsif context&.respond_to?(:aref)
137+
result << "#{context.aref}-"
138+
end
135139
result << legacy_aref
136140
result
137141
end

lib/rdoc/markup/to_html.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -317,7 +317,7 @@ def accept_heading(heading)
317317
# Add legacy anchor before the heading for backward compatibility.
318318
# This allows old links with label- prefix to still work.
319319
if legacy_label && @options.output_decoration && !@options.pipe
320-
@res << "\n<a id=\"#{legacy_label}\" class=\"legacy-anchor\"></a>"
320+
@res << "\n<span id=\"#{legacy_label}\" class=\"legacy-anchor\"></span>"
321321
end
322322

323323
@res << if @options.output_decoration

test/rdoc/generator/darkfish_test.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ def test_generate
126126
)
127127

128128
# GitHub-style: heading-1 (lowercase, dot removed)
129-
assert_match(/<a id="class-klass-label-Heading\+1" class="legacy-anchor"><\/a>\s*<h1 id="class-klass-heading-1"><a href="#class-klass-heading-1">Heading 1<\/a>(?!\.)/,
129+
# Legacy anchor preserves original casing (class-Klass), while new anchor is lowercase (class-klass)
130+
assert_match(/<span id="class-Klass-label-Heading\+1" class="legacy-anchor"><\/span>\s*<h1 id="class-klass-heading-1"><a href="#class-klass-heading-1">Heading 1<\/a>(?!\.)/,
130131
klass[%r[<section class=\"description\">.*</section>]m])
131132
toc = File.binread('table_of_contents.html')
132133
assert_match(
@@ -173,7 +174,7 @@ def test_generate_index_with_main_page
173174

174175
assert_include index_html, "<h3>Table of Contents</h3>"
175176
# GitHub-style: heading-1 (lowercase, space to hyphen)
176-
assert_include index_html, '<a id="label-Heading+1" class="legacy-anchor"></a>
177+
assert_include index_html, '<span id="label-Heading+1" class="legacy-anchor"></span>
177178
<h1 id="heading-1"><a href="#heading-1">Heading 1</a>'
178179
# When there's a main page, the default description should not be shown
179180
assert_not_include index_html, 'This is the API documentation for My awesome Ruby project.'

test/rdoc/generator/markup_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ def test_description
3939
@comment = '= Hello'
4040

4141
# When there's no context (self returns nil for aref), there's no context prefix in the legacy label
42-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h1 id=\"hello\"><a href=\"#hello\">Hello</a></h1>\n", description
42+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h1 id=\"hello\"><a href=\"#hello\">Hello</a></h1>\n", description
4343
end
4444

4545
def test_formatter

test/rdoc/markup/heading_test.rb

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,36 @@ def test_label
2424
assert_equal 'class-foo-hello-friend', @h.label(context)
2525
end
2626

27+
def test_legacy_aref
28+
# Legacy style: label- prefix, original casing, + for spaces
29+
# Note: *Friend* markup is stripped, ! becomes %21 which becomes -21
30+
assert_equal 'label-Hello+Friend-21', @h.legacy_aref
31+
end
32+
33+
def test_legacy_label
34+
# Legacy style without context
35+
assert_equal 'label-Hello+Friend-21', @h.legacy_label
36+
assert_equal 'label-Hello+Friend-21', @h.legacy_label(nil)
37+
38+
# Legacy style with context - context should preserve original casing (class-Foo, not class-foo)
39+
context = RDoc::NormalClass.new 'Foo'
40+
assert_equal 'class-Foo-label-Hello+Friend-21', @h.legacy_label(context)
41+
end
42+
43+
def test_legacy_label_preserves_context_casing
44+
# Verify that legacy_label uses legacy_aref for the context prefix (preserving original casing)
45+
# This is a regression test for a bug where legacy_label incorrectly lowercased the context prefix
46+
h = RDoc::Markup::Heading.new 1, 'Credits'
47+
context = RDoc::NormalModule.new 'RDoc'
48+
assert_equal 'module-RDoc-label-Credits', h.legacy_label(context)
49+
50+
# Nested module example
51+
parent = RDoc::NormalModule.new 'Foo'
52+
context = RDoc::NormalClass.new 'Bar'
53+
context.parent = parent
54+
assert_equal 'class-Foo::Bar-label-Credits', h.legacy_label(context)
55+
end
56+
2757
def test_plain_html
2858
assert_equal 'Hello <strong>Friend</strong>!', @h.plain_html
2959
end

test/rdoc/markup/to_html_test.rb

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,34 +24,34 @@ def accept_document
2424
end
2525

2626
def accept_heading
27-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h5 id=\"hello\"><a href=\"#hello\">Hello</a></h5>\n", @to.res.join
27+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h5 id=\"hello\"><a href=\"#hello\">Hello</a></h5>\n", @to.res.join
2828
end
2929

3030
def accept_heading_1
31-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h1 id=\"hello\"><a href=\"#hello\">Hello</a></h1>\n", @to.res.join
31+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h1 id=\"hello\"><a href=\"#hello\">Hello</a></h1>\n", @to.res.join
3232
end
3333

3434
def accept_heading_2
35-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h2 id=\"hello\"><a href=\"#hello\">Hello</a></h2>\n", @to.res.join
35+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h2 id=\"hello\"><a href=\"#hello\">Hello</a></h2>\n", @to.res.join
3636
end
3737

3838
def accept_heading_3
39-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h3 id=\"hello\"><a href=\"#hello\">Hello</a></h3>\n", @to.res.join
39+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h3 id=\"hello\"><a href=\"#hello\">Hello</a></h3>\n", @to.res.join
4040
end
4141

4242
def accept_heading_4
43-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h4 id=\"hello\"><a href=\"#hello\">Hello</a></h4>\n", @to.res.join
43+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h4 id=\"hello\"><a href=\"#hello\">Hello</a></h4>\n", @to.res.join
4444
end
4545

4646
def accept_heading_b
4747
inner = "<strong>Hello</strong>"
4848

49-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h1 id=\"hello\"><a href=\"#hello\">#{inner}</a></h1>\n",
49+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h1 id=\"hello\"><a href=\"#hello\">#{inner}</a></h1>\n",
5050
@to.res.join
5151
end
5252

5353
def accept_heading_suppressed_crossref
54-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h1 id=\"hello\"><a href=\"#hello\">Hello</a></h1>\n", @to.res.join
54+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h1 id=\"hello\"><a href=\"#hello\">Hello</a></h1>\n", @to.res.join
5555
end
5656

5757
def accept_list_end_bullet
@@ -327,7 +327,7 @@ def test_accept_heading_7
327327

328328
@to.accept_heading @RM::Heading.new(7, 'Hello')
329329

330-
assert_equal "\n<a id=\"label-Hello\" class=\"legacy-anchor\"></a>\n<h6 id=\"hello\"><a href=\"#hello\">Hello</a></h6>\n", @to.res.join
330+
assert_equal "\n<span id=\"label-Hello\" class=\"legacy-anchor\"></span>\n<h6 id=\"hello\"><a href=\"#hello\">Hello</a></h6>\n", @to.res.join
331331
end
332332

333333
def test_accept_heading_aref_class
@@ -336,7 +336,7 @@ def test_accept_heading_aref_class
336336

337337
@to.accept_heading head(1, 'Hello')
338338

339-
assert_equal "\n<a id=\"class-foo-label-Hello\" class=\"legacy-anchor\"></a>\n<h1 id=\"class-foo-hello\"><a href=\"#class-foo-hello\">Hello</a></h1>\n",
339+
assert_equal "\n<span id=\"class-Foo-label-Hello\" class=\"legacy-anchor\"></span>\n<h1 id=\"class-foo-hello\"><a href=\"#class-foo-hello\">Hello</a></h1>\n",
340340
@to.res.join
341341
end
342342

@@ -346,7 +346,7 @@ def test_accept_heading_aref_method
346346

347347
@to.accept_heading @RM::Heading.new(1, 'Hello')
348348

349-
assert_equal "\n<a id=\"method-i-foo-label-Hello\" class=\"legacy-anchor\"></a>\n<h1 id=\"method-i-foo-hello\"><a href=\"#method-i-foo-hello\">Hello</a></h1>\n",
349+
assert_equal "\n<span id=\"method-i-foo-label-Hello\" class=\"legacy-anchor\"></span>\n<h1 id=\"method-i-foo-hello\"><a href=\"#method-i-foo-hello\">Hello</a></h1>\n",
350350
@to.res.join
351351
end
352352

0 commit comments

Comments
 (0)