Skip to content

Commit 671db85

Browse files
Merge pull request #297 from jonathanhefner/ref-links-monkey-patch
Monkey patch `ToHtmlCrossref` to modify ref links
2 parents bb1482c + 6895a9a commit 671db85

File tree

5 files changed

+77
-94
lines changed

5 files changed

+77
-94
lines changed

lib/sdoc/generator.rb

+3-9
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,12 @@
33
require 'fileutils'
44
require 'json'
55

6+
require "rdoc"
7+
require_relative "rdoc_monkey_patches"
8+
69
require 'sdoc/templatable'
710
require 'sdoc/helpers'
811
require 'sdoc/version'
9-
require 'rdoc'
10-
11-
RDoc::TopLevel.prepend(Module.new do
12-
attr_writer :path
13-
14-
def path
15-
@path ||= super
16-
end
17-
end)
1812

1913
class RDoc::ClassModule
2014
def with_documentation?

lib/sdoc/postprocessor.rb

-19
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ def process(rendered)
1111

1212
rebase_urls!(document)
1313
version_rails_guides_urls!(document)
14-
unlink_unintentional_ref_links!(document)
15-
style_ref_links!(document)
1614
unify_h1_headings!(document)
1715
highlight_code_blocks!(document)
1816

@@ -72,23 +70,6 @@ def version_url(url, version)
7270
uri.to_s
7371
end
7472

75-
def unlink_unintentional_ref_links!(document)
76-
document.css(".description a[href^='classes/'] > code:only-child > text()").each do |text_node|
77-
if text_node.inner_text.match?(/\A[A-Z](?:[A-Z]+|[a-z]+)\z/)
78-
text_node.parent.parent.replace(text_node)
79-
end
80-
end
81-
end
82-
83-
def style_ref_links!(document)
84-
document.css(".description a[href^='classes/']:has(> text():only-child)").each do |element|
85-
text = element.inner_text
86-
if !text.include?(" ") || text.match?(/\S\(/)
87-
element.inner_html = "<code>#{element.inner_html}</code>"
88-
end
89-
end
90-
end
91-
9273
def unify_h1_headings!(document)
9374
if h1 = document.at_css("#context > .description h1:first-child")
9475
if hgroup = document.at_css("#content > hgroup")

lib/sdoc/rdoc_monkey_patches.rb

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
require "rdoc"
2+
3+
RDoc::TopLevel.prepend(Module.new do
4+
attr_writer :path
5+
6+
def path
7+
@path ||= super
8+
end
9+
end)
10+
11+
12+
RDoc::Markup::ToHtmlCrossref.prepend(Module.new do
13+
def cross_reference(name, text = nil, code = true)
14+
if text
15+
# Style ref links that look like code, such as `{Rails}[rdoc-ref:Rails]`.
16+
code ||= !text.include?(" ") || text.match?(/\S\(/)
17+
elsif name.match?(/\A[A-Z](?:[A-Z]+|[a-z]+)\z/)
18+
# Prevent unintentional ref links, such as `Rails` or `ERB`.
19+
return name
20+
end
21+
22+
super
23+
end
24+
end)

spec/postprocessor_spec.rb

-66
Original file line numberDiff line numberDiff line change
@@ -58,72 +58,6 @@
5858
end
5959
end
6060

61-
it "unlinks unintentional autolinked code ref links in descriptions" do
62-
rendered = <<~HTML
63-
<base href="../" data-current-path="classes/Foo.html">
64-
65-
<div class="description">
66-
<a href="Rails.html"><code>Rails</code></a>
67-
<a href="ERB.html"><code>ERB</code></a>
68-
69-
<a href="Rails.html"><code>::Rails</code></a>
70-
<a href="FooBar.html"><code>FooBar</code></a>
71-
</div>
72-
73-
<a href="Nav.html"><code>Nav</code></a>
74-
HTML
75-
76-
expected = <<~HTML
77-
<div class="description">
78-
Rails
79-
ERB
80-
81-
<a href="classes/Rails.html"><code>::Rails</code></a>
82-
<a href="classes/FooBar.html"><code>FooBar</code></a>
83-
</div>
84-
85-
<a href="classes/Nav.html"><code>Nav</code></a>
86-
HTML
87-
88-
_(SDoc::Postprocessor.process(rendered)).must_include expected
89-
end
90-
91-
it "styles unstyled code ref links in descriptions" do
92-
rendered = <<~HTML
93-
<base href="../" data-current-path="classes/Foo.html">
94-
95-
<div class="description">
96-
<a href="/classes/Bar/Qux.html">Qux</a>
97-
<a href="Bar/Qux.html">Qux</a>
98-
<a href="#method-i-bar-3F.html">Foo#bar?(qux, &amp;block)</a>
99-
<a href="#method-i-2A_bar-21.html">*_bar!</a>
100-
101-
<a href="https://example.com/Qux.html">Qux</a>
102-
<a href="Bar/Qux.html">Not Code</a>
103-
<a href="Bar/Qux.html">(also) not code</a>
104-
</div>
105-
106-
<a href="/classes/Permalink.html">Permalink</a>
107-
HTML
108-
109-
expected = <<~HTML
110-
<div class="description">
111-
<a href="classes/Bar/Qux.html"><code>Qux</code></a>
112-
<a href="classes/Bar/Qux.html"><code>Qux</code></a>
113-
<a href="classes/Foo.html#method-i-bar-3F.html"><code>Foo#bar?(qux, &amp;block)</code></a>
114-
<a href="classes/Foo.html#method-i-2A_bar-21.html"><code>*_bar!</code></a>
115-
116-
<a href="https://example.com/Qux.html">Qux</a>
117-
<a href="classes/Bar/Qux.html">Not Code</a>
118-
<a href="classes/Bar/Qux.html">(also) not code</a>
119-
</div>
120-
121-
<a href="classes/Permalink.html">Permalink</a>
122-
HTML
123-
124-
_(SDoc::Postprocessor.process(rendered)).must_include expected
125-
end
126-
12761
it "unifies <h1> headings for a context" do
12862
rendered = <<~HTML
12963
<div id="content">

spec/rdoc_monkey_patches_spec.rb

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
require "spec_helper"
2+
3+
describe "RDoc monkey patches" do
4+
describe RDoc::TopLevel do
5+
it "supports setting #path" do
6+
top_level = rdoc_top_level_for("class Foo; end")
7+
8+
_(top_level.path).wont_be_nil
9+
10+
top_level.path = "some/path"
11+
_(top_level.path).must_equal "some/path"
12+
end
13+
end
14+
15+
describe RDoc::Markup::ToHtmlCrossref do
16+
it "prevents unintentional ref links" do
17+
description = rdoc_top_level_for(<<~RUBY).find_module_named("CoolApp").description
18+
module ERB; end
19+
module Rails; end
20+
21+
# CoolApp uses Rails and ERB. See ::Rails. See also ::ERB.
22+
module CoolApp; end
23+
RUBY
24+
25+
_(description).must_match %r"<a href=.+?><code>CoolApp</code></a> uses Rails and ERB"
26+
_(description).must_match %r"See <a href=.+?><code>::Rails</code></a>"
27+
_(description).must_match %r"See also <a href=.+?><code>::ERB</code></a>"
28+
end
29+
30+
it "styles ref links that look like code" do
31+
description = rdoc_top_level_for(<<~RUBY).find_module_named("Foo").description
32+
# Some of {Foo}[rdoc-ref:Foo]'s methods can be called with multiple
33+
# arguments, such as {bar(x, y)}[rdoc-ref:#bar].
34+
#
35+
# But {baz cannot}[rdoc-ref:#baz] and {qux (also) cannot}[rdoc-ref:#qux].
36+
class Foo
37+
def bar(x, y); end
38+
def baz; end
39+
def qux; end
40+
end
41+
RUBY
42+
43+
_(description).must_match %r"Some of <a href=.+?><code>Foo</code></a>"
44+
_(description).must_match %r"such as <a href=.+?><code>bar\(x, y\)</code></a>"
45+
46+
_(description).must_match %r"But <a href=.+?>baz cannot</a>"
47+
_(description).must_match %r"and <a href=.+?>qux \(also\) cannot</a>"
48+
end
49+
end
50+
end

0 commit comments

Comments
 (0)