Skip to content

Commit

Permalink
Merge pull request #297 from jonathanhefner/ref-links-monkey-patch
Browse files Browse the repository at this point in the history
Monkey patch `ToHtmlCrossref` to modify ref links
  • Loading branch information
jonathanhefner authored Sep 1, 2023
2 parents bb1482c + 6895a9a commit 671db85
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 94 deletions.
12 changes: 3 additions & 9 deletions lib/sdoc/generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,12 @@
require 'fileutils'
require 'json'

require "rdoc"
require_relative "rdoc_monkey_patches"

require 'sdoc/templatable'
require 'sdoc/helpers'
require 'sdoc/version'
require 'rdoc'

RDoc::TopLevel.prepend(Module.new do
attr_writer :path

def path
@path ||= super
end
end)

class RDoc::ClassModule
def with_documentation?
Expand Down
19 changes: 0 additions & 19 deletions lib/sdoc/postprocessor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ def process(rendered)

rebase_urls!(document)
version_rails_guides_urls!(document)
unlink_unintentional_ref_links!(document)
style_ref_links!(document)
unify_h1_headings!(document)
highlight_code_blocks!(document)

Expand Down Expand Up @@ -72,23 +70,6 @@ def version_url(url, version)
uri.to_s
end

def unlink_unintentional_ref_links!(document)
document.css(".description a[href^='classes/'] > code:only-child > text()").each do |text_node|
if text_node.inner_text.match?(/\A[A-Z](?:[A-Z]+|[a-z]+)\z/)
text_node.parent.parent.replace(text_node)
end
end
end

def style_ref_links!(document)
document.css(".description a[href^='classes/']:has(> text():only-child)").each do |element|
text = element.inner_text
if !text.include?(" ") || text.match?(/\S\(/)
element.inner_html = "<code>#{element.inner_html}</code>"
end
end
end

def unify_h1_headings!(document)
if h1 = document.at_css("#context > .description h1:first-child")
if hgroup = document.at_css("#content > hgroup")
Expand Down
24 changes: 24 additions & 0 deletions lib/sdoc/rdoc_monkey_patches.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require "rdoc"

RDoc::TopLevel.prepend(Module.new do
attr_writer :path

def path
@path ||= super
end
end)


RDoc::Markup::ToHtmlCrossref.prepend(Module.new do
def cross_reference(name, text = nil, code = true)
if text
# Style ref links that look like code, such as `{Rails}[rdoc-ref:Rails]`.
code ||= !text.include?(" ") || text.match?(/\S\(/)
elsif name.match?(/\A[A-Z](?:[A-Z]+|[a-z]+)\z/)
# Prevent unintentional ref links, such as `Rails` or `ERB`.
return name
end

super
end
end)
66 changes: 0 additions & 66 deletions spec/postprocessor_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,72 +58,6 @@
end
end

it "unlinks unintentional autolinked code ref links in descriptions" do
rendered = <<~HTML
<base href="../" data-current-path="classes/Foo.html">
<div class="description">
<a href="Rails.html"><code>Rails</code></a>
<a href="ERB.html"><code>ERB</code></a>
<a href="Rails.html"><code>::Rails</code></a>
<a href="FooBar.html"><code>FooBar</code></a>
</div>
<a href="Nav.html"><code>Nav</code></a>
HTML

expected = <<~HTML
<div class="description">
Rails
ERB
<a href="classes/Rails.html"><code>::Rails</code></a>
<a href="classes/FooBar.html"><code>FooBar</code></a>
</div>
<a href="classes/Nav.html"><code>Nav</code></a>
HTML

_(SDoc::Postprocessor.process(rendered)).must_include expected
end

it "styles unstyled code ref links in descriptions" do
rendered = <<~HTML
<base href="../" data-current-path="classes/Foo.html">
<div class="description">
<a href="/classes/Bar/Qux.html">Qux</a>
<a href="Bar/Qux.html">Qux</a>
<a href="#method-i-bar-3F.html">Foo#bar?(qux, &amp;block)</a>
<a href="#method-i-2A_bar-21.html">*_bar!</a>
<a href="https://example.com/Qux.html">Qux</a>
<a href="Bar/Qux.html">Not Code</a>
<a href="Bar/Qux.html">(also) not code</a>
</div>
<a href="/classes/Permalink.html">Permalink</a>
HTML

expected = <<~HTML
<div class="description">
<a href="classes/Bar/Qux.html"><code>Qux</code></a>
<a href="classes/Bar/Qux.html"><code>Qux</code></a>
<a href="classes/Foo.html#method-i-bar-3F.html"><code>Foo#bar?(qux, &amp;block)</code></a>
<a href="classes/Foo.html#method-i-2A_bar-21.html"><code>*_bar!</code></a>
<a href="https://example.com/Qux.html">Qux</a>
<a href="classes/Bar/Qux.html">Not Code</a>
<a href="classes/Bar/Qux.html">(also) not code</a>
</div>
<a href="classes/Permalink.html">Permalink</a>
HTML

_(SDoc::Postprocessor.process(rendered)).must_include expected
end

it "unifies <h1> headings for a context" do
rendered = <<~HTML
<div id="content">
Expand Down
50 changes: 50 additions & 0 deletions spec/rdoc_monkey_patches_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require "spec_helper"

describe "RDoc monkey patches" do
describe RDoc::TopLevel do
it "supports setting #path" do
top_level = rdoc_top_level_for("class Foo; end")

_(top_level.path).wont_be_nil

top_level.path = "some/path"
_(top_level.path).must_equal "some/path"
end
end

describe RDoc::Markup::ToHtmlCrossref do
it "prevents unintentional ref links" do
description = rdoc_top_level_for(<<~RUBY).find_module_named("CoolApp").description
module ERB; end
module Rails; end
# CoolApp uses Rails and ERB. See ::Rails. See also ::ERB.
module CoolApp; end
RUBY

_(description).must_match %r"<a href=.+?><code>CoolApp</code></a> uses Rails and ERB"
_(description).must_match %r"See <a href=.+?><code>::Rails</code></a>"
_(description).must_match %r"See also <a href=.+?><code>::ERB</code></a>"
end

it "styles ref links that look like code" do
description = rdoc_top_level_for(<<~RUBY).find_module_named("Foo").description
# Some of {Foo}[rdoc-ref:Foo]'s methods can be called with multiple
# arguments, such as {bar(x, y)}[rdoc-ref:#bar].
#
# But {baz cannot}[rdoc-ref:#baz] and {qux (also) cannot}[rdoc-ref:#qux].
class Foo
def bar(x, y); end
def baz; end
def qux; end
end
RUBY

_(description).must_match %r"Some of <a href=.+?><code>Foo</code></a>"
_(description).must_match %r"such as <a href=.+?><code>bar\(x, y\)</code></a>"

_(description).must_match %r"But <a href=.+?>baz cannot</a>"
_(description).must_match %r"and <a href=.+?>qux \(also\) cannot</a>"
end
end
end

0 comments on commit 671db85

Please sign in to comment.