Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monkey patch ToHtmlCrossref to modify ref links #297

Merged
merged 1 commit into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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