Skip to content

Commit c5a3294

Browse files
Merge pull request #287 from jonathanhefner/h1-unify
Generate uniform <h1> headings for all modules
2 parents 947abf9 + 41cd675 commit c5a3294

File tree

10 files changed

+157
-88
lines changed

10 files changed

+157
-88
lines changed

lib/rdoc/generator/template/rails/_context.rhtml

+16-21
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
<div id="context">
22
<% unless (description = context.description).empty? %>
3-
<% unless context.comment_title %>
4-
<h1><%= context.title %></h1>
5-
<% end %>
63
<div class="description">
74
<%= description %>
85
</div>
96
<% end %>
107

118

9+
<%# File only: requires %>
1210
<% unless context.requires.empty? %>
13-
<!-- File only: requires -->
1411
<div class="content__divider">Required Files</div>
1512
<ul>
1613
<% context.requires.each do |req| %>
@@ -20,6 +17,20 @@
2017
<% end %>
2118

2219

20+
<%# Module only: ancestors %>
21+
<% unless context.is_a?(RDoc::TopLevel) || (ancestors = module_ancestors(context)).empty? %>
22+
<div class="content__divider">Inherits From</div>
23+
<ul>
24+
<% ancestors.each do |kind, ancestor| %>
25+
<li>
26+
<span class="kind"><%= kind %></span>
27+
<%= ancestor.is_a?(String) ? full_name(ancestor) : link_to(ancestor) %>
28+
</li>
29+
<% end %>
30+
</ul>
31+
<% end %>
32+
33+
2334
<% sections = context.sections.select { |s| s.title }.sort_by{ |s| s.title.to_s } %>
2435
<% unless sections.empty? then %>
2536
<!-- Sections -->
@@ -51,22 +62,6 @@
5162
</dl>
5263
<% end %>
5364

54-
<% unless context.includes.empty? %>
55-
<!-- Includes -->
56-
<div class="content__divider">Included Modules</div>
57-
<ul>
58-
<% context.includes.each do |inc| %>
59-
<li>
60-
<% if inc.module.is_a?(String) %>
61-
<%= full_name inc.name %>
62-
<% else %>
63-
<%= link_to inc.module %>
64-
<% end %>
65-
</li>
66-
<% end %>
67-
</ul>
68-
<% end %>
69-
7065

7166

7267
<% context.each_section do |section, constants, attributes| %>
@@ -185,7 +180,7 @@
185180
<ul>
186181
<% (context.modules.sort + context.classes.sort).each do |mod| %>
187182
<li>
188-
<span class="type"><%= mod.type.upcase %></span>
183+
<span class="kind"><%= mod.type %></span>
189184
<%= link_to mod %>
190185
</li>
191186
<% end %>

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

+3-8
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,9 @@
1919
<%= include_template '_panel.rhtml' %>
2020

2121
<main id="content">
22-
<div class="content__full-name">
23-
<span class="qualifier"><%= klass.type %></span>
24-
<%= module_breadcrumbs klass %>
25-
<% if !klass.module? && superclass = klass.superclass %>
26-
<span class="qualifier">&lt;</span>
27-
<%= superclass.is_a?(String) ? full_name(superclass) : link_to(superclass) %>
28-
<% end %>
29-
</div>
22+
<hgroup class="content__title">
23+
<h1><span class="kind"><%= klass.type %></span> <%= module_breadcrumbs klass %></h1>
24+
</hgroup>
3025

3126
<%= include_template '_context.rhtml', {:context => klass} %>
3227

lib/rdoc/generator/template/rails/file.rhtml

+3-4
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@
1616
<%= include_template '_panel.rhtml' %>
1717

1818
<main id="content">
19-
<h1 class="content__full-name">
20-
<span class="qualifier">File</span>
21-
<%= full_name file %>
22-
</h1>
19+
<hgroup class="content__title">
20+
<h1><span class="kind">File</span> <%= full_name file %></h1>
21+
</hgroup>
2322

2423
<% if source_url = github_url(file.relative_name) %>
2524
<p><%= link_to_external "View on GitHub", source_url %></p>

lib/rdoc/generator/template/rails/resources/css/main.css

+23-9
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,6 @@ a {
5555
a:has(> code:only-child) {
5656
text-decoration: none;
5757
}
58-
code a {
59-
text-decoration: none;
60-
}
6158

6259
/* TODO: Remove this hack when Firefox supports `:has()` */
6360
a code {
@@ -74,6 +71,15 @@ a code {
7471
display: none;
7572
}
7673

74+
.kind {
75+
font-family: monospace;
76+
font-weight: bold;
77+
}
78+
79+
.kind::after {
80+
content: " "; /* Ensure trailing space has width of 1 monospace char */
81+
}
82+
7783
table {
7884
border-collapse: collapse;
7985
}
@@ -380,18 +386,22 @@ html {
380386
font-style: normal;
381387
}
382388

383-
.content__full-name {
384-
font-family: monospace;
385-
font-size: 1.4em;
389+
.content__title :is(h1, p) {
390+
font-size: 1.6em;
386391
line-height: 1.25;
387-
padding: 0.125em 0;
392+
}
393+
394+
.content__title h1 {
395+
font-weight: normal;
388396

389397
margin-left: 1em;
390398
text-indent: -1em;
391399
}
392400

393-
.content__full-name .qualifier {
394-
font-weight: bold;
401+
.content__title p {
402+
font-style: italic;
403+
404+
margin-top: 0;
395405
}
396406

397407
.content__section-title {
@@ -513,6 +523,10 @@ html {
513523
* Description of method or module
514524
*/
515525

526+
#context > .description {
527+
margin-top: var(--space-lg);
528+
}
529+
516530
.description :is(h1, h2, h3, h4, h5, h6) {
517531
line-height: 1.25;
518532
padding: 0.125em 0;

lib/sdoc/generator.rb

-10
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,6 @@ class RDoc::Options
2727
attr_accessor :search_index
2828
end
2929

30-
module RDoc::Generator::Markup
31-
def comment_title
32-
@comment_title ||= @comment.to_s.match(/\A[=#] (.*)$/) {|match| match[1] }
33-
end
34-
35-
def title
36-
comment_title || full_name
37-
end
38-
end
39-
4030
class RDoc::Generator::SDoc
4131
RDoc::RDoc.add_generator self
4232

lib/sdoc/helpers.rb

+11
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,17 @@ def module_breadcrumbs(rdoc_module)
127127
"<code>#{crumbs.join("::<wbr>")}</code>"
128128
end
129129

130+
def module_ancestors(rdoc_module)
131+
ancestors = rdoc_module.includes.map { |inc| ["module", inc.module] }
132+
133+
if !rdoc_module.module? && superclass = rdoc_module.superclass
134+
superclass_name = superclass.is_a?(String) ? superclass : superclass.full_name
135+
ancestors.unshift(["class", superclass]) unless superclass_name == "Object"
136+
end
137+
138+
ancestors
139+
end
140+
130141
def method_signature(rdoc_method)
131142
if rdoc_method.call_seq
132143
rdoc_method.call_seq.split(/\n+/).map do |line|

lib/sdoc/postprocessor.rb

+10
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ def process(rendered)
1313
version_rails_guides_urls!(document)
1414
unlink_unintentional_ref_links!(document)
1515
style_ref_links!(document)
16+
unify_h1_headings!(document)
1617
highlight_code_blocks!(document)
1718

1819
document.to_s
@@ -88,6 +89,15 @@ def style_ref_links!(document)
8889
end
8990
end
9091

92+
def unify_h1_headings!(document)
93+
if h1 = document.at_css("#context > .description h1:first-child")
94+
if hgroup = document.at_css("#content > hgroup")
95+
h1.remove
96+
hgroup.add_child(%(<p>#{h1.inner_html}</p>))
97+
end
98+
end
99+
end
100+
91101
def highlight_code_blocks!(document)
92102
document.css(".description pre > code, .method__source pre > code").each do |element|
93103
code = element.inner_text

spec/helpers_spec.rb

+38
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,44 @@ module Foo; module Bar; module Qux; end; end; end
523523
end
524524
end
525525

526+
describe "#module_ancestors" do
527+
it "returns a list with the base class (if applicable) and included modules" do
528+
# RDoc chokes on ";" when parsing includes, so replace with "\n".
529+
top_level = rdoc_top_level_for <<~RUBY.gsub(";", "\n")
530+
module M1; end
531+
module M2; end
532+
class C1; end
533+
534+
module Foo; include M1; include M2; end
535+
class Bar < C1; include M2; include M1; end
536+
class Qux < Cx; include Foo; include Mx; end
537+
RUBY
538+
539+
m1, m2, c1, foo, bar, qux = %w[M1 M2 C1 Foo Bar Qux].map { |name| top_level.find_module_named(name) }
540+
541+
_(@helpers.module_ancestors(foo)).must_equal [["module", m1], ["module", m2]]
542+
_(@helpers.module_ancestors(bar)).must_equal [["class", c1], ["module", m2], ["module", m1]]
543+
_(@helpers.module_ancestors(qux)).must_equal [["class", "Cx"], ["module", foo], ["module", "Mx"]]
544+
end
545+
546+
it "excludes the default base class (Object) from the result" do
547+
# RDoc chokes on ";" when parsing includes, so replace with "\n".
548+
top_level = rdoc_top_level_for <<~RUBY.gsub(";", "\n")
549+
class Object; end
550+
class Foo; include M1; end
551+
RUBY
552+
553+
_(@helpers.module_ancestors(top_level.find_module_named("Object"))).must_equal [["class", "BasicObject"]]
554+
_(@helpers.module_ancestors(top_level.find_module_named("Foo"))).must_equal [["module", "M1"]]
555+
556+
top_level = rdoc_top_level_for <<~RUBY.gsub(";", "\n")
557+
class Foo; include M1; end
558+
RUBY
559+
560+
_(@helpers.module_ancestors(top_level.find_module_named("Foo"))).must_equal [["module", "M1"]]
561+
end
562+
end
563+
526564
describe "#method_signature" do
527565
it "returns the method signature wrapped in <code>" do
528566
method = rdoc_top_level_for(<<~RUBY).find_module_named("Foo").find_method("bar", false)

spec/postprocessor_spec.rb

+53
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,59 @@
124124
_(SDoc::Postprocessor.process(rendered)).must_include expected
125125
end
126126

127+
it "unifies <h1> headings for a context" do
128+
rendered = <<~HTML
129+
<div id="content">
130+
<hgroup><h1>module Foo</h1></hgroup>
131+
132+
<div id="context">
133+
<div class="description"><h1>The Foo</h1><p>Lorem ipsum.</p></div>
134+
</div>
135+
</div>
136+
HTML
137+
138+
expected = <<~HTML
139+
<div id="content">
140+
<hgroup><h1>module Foo</h1><p>The Foo</p></hgroup>
141+
142+
<div id="context">
143+
<div class="description"><p>Lorem ipsum.</p></div>
144+
</div>
145+
</div>
146+
HTML
147+
148+
_(SDoc::Postprocessor.process(rendered)).must_include expected
149+
end
150+
151+
it "does not relocate non-leading <h1> headings" do
152+
rendered = <<~HTML
153+
<div id="content">
154+
<hgroup><h1>module Foo</h1></hgroup>
155+
156+
<div id="context">
157+
<div class="description"><p>Lorem ipsum.</p><h1>Red Herring</h1></div>
158+
<div class="method">
159+
<div class="description"><h1>Red Herring</h1></div>
160+
</div>
161+
</div>
162+
</div>
163+
HTML
164+
165+
_(SDoc::Postprocessor.process(rendered)).must_include rendered
166+
end
167+
168+
it "does not relocate <h1> headings when <hgroup> is not present" do
169+
rendered = <<~HTML
170+
<div id="content">
171+
<div id="context">
172+
<div class="description"><h1>Main Page</h1></div>
173+
</div>
174+
</div>
175+
HTML
176+
177+
_(SDoc::Postprocessor.process(rendered)).must_include rendered
178+
end
179+
127180
it "highlights code blocks" do
128181
rendered = <<~HTML
129182
<div class="description">

spec/rdoc_generator_markup_spec.rb

-36
This file was deleted.

0 commit comments

Comments
 (0)