Skip to content

Commit

Permalink
Added link handling to RDoc output
Browse files Browse the repository at this point in the history
Implementing RDoc -> Markdown link handling was missed making conversion
from RDoc to Markdown involve manual labor.  Now tidylinks and rdoc-*:
links are handled.

Fixes ruby#160
  • Loading branch information
drbrain committed Dec 16, 2012
1 parent 2d1a29f commit 89702e2
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 71 deletions.
7 changes: 6 additions & 1 deletion History.rdoc
@@ -1,4 +1,4 @@
=== 4.0.0.preview2.1 / 2012-12-14
=== 4.0.0.preview3 / ??

As a preview release, please file bugs for any problems you have with rdoc at
https://github.com/rdoc/rdoc/issues
Expand All @@ -10,6 +10,11 @@ Notable feature additions are markdown support and an WEBrick servlet that can
serve HTML from an ri store. (This means that RubyGems 2.0+ no longer needs
to build HTML documentation when installing gems.)

* Bug fixes
* Added link handling to Markdown output. Bug #160 by burningTyger.

=== 4.0.0.preview2.1 / 2012-12-14

* Minor enhancements
* Added --page-dir option to give pretty names for a FAQ, guides, or other
documentation you write that is not stored in the project root. For
Expand Down
73 changes: 73 additions & 0 deletions lib/rdoc/markup/formatter.rb
Expand Up @@ -17,6 +17,30 @@ class RDoc::Markup::Formatter

InlineTag = Struct.new(:bit, :on, :off)

##
# Converts a target url to one that is relative to a given path

def self.gen_relative_url path, target
from = File.dirname path
to, to_file = File.split target

from = from.split "/"
to = to.split "/"

from.delete '.'
to.delete '.'

while from.size > 0 and to.size > 0 and from[0] == to[0] do
from.shift
to.shift
end

from.fill ".."
from.concat to
from << to_file
File.join(*from)
end

##
# Creates a new Formatter

Expand All @@ -35,6 +59,7 @@ def initialize options, markup = nil
@tt_bit = @attributes.bitmap_for :TT

@hard_break = ''
@from_path = '.'
end

##
Expand All @@ -51,6 +76,26 @@ def accept_document document
end
end

##
# Adds a special for links of the form rdoc-...:

def add_special_RDOCLINK
@markup.add_special(/rdoc-[a-z]+:\S+/, :RDOCLINK)
end

##
# Adds a special for links of the form {<text>}[<url>] and <word>[<url>]

def add_special_TIDYLINK
@markup.add_special(/(?:
\{.*?\} | # multi-word label
\b[^\s{}]+? # single-word label
)
\[\S+?\] # link target
/x, :TIDYLINK)
end

##
# Add a new set of tags for an attribute. We allow separate start and end
# tags for flexibility
Expand Down Expand Up @@ -178,6 +223,34 @@ def off_tags res, item
end
end

##
# Extracts and a scheme, url and an anchor id from +url+ and returns them.

def parse_url url
if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then
scheme = 'link'
path = "##{$1}"
id = " id=\"#{$2}\"" if $2
elsif url =~ /([A-Za-z]+):(.*)/ then
scheme = $1.downcase
path = $2
else
scheme = 'http'
path = url
url = "http://#{url}"
end

if scheme == 'link' then
url = if path[0, 1] == '#' then # is this meaningful?
path
else
self.class.gen_relative_url @from_path, path
end
end

[scheme, url, id]
end

##
# Is +tag+ a tt tag?

Expand Down
62 changes: 5 additions & 57 deletions lib/rdoc/markup/to_html.rb
Expand Up @@ -36,30 +36,6 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter

attr_accessor :from_path

##
# Converts a target url to one that is relative to a given path

def self.gen_relative_url(path, target)
from = File.dirname path
to, to_file = File.split target

from = from.split "/"
to = to.split "/"

from.delete '.'
to.delete '.'

while from.size > 0 and to.size > 0 and from[0] == to[0] do
from.shift
to.shift
end

from.fill ".."
from.concat to
from << to_file
File.join(*from)
end

# :section:

##
Expand All @@ -79,17 +55,8 @@ def initialize options, markup = nil
@markup.add_special(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/,
:HYPERLINK)

# internal links
@markup.add_special(/rdoc-[a-z]+:\S+/, :RDOCLINK)

# and links of the form <text>[<url>]
@markup.add_special(/(?:
\{.*?\} | # multi-word label
\b[^\s{}]+? # single-word label
)
\[\S+?\] # link target
/x, :TIDYLINK)
add_special_RDOCLINK
add_special_TIDYLINK

init_tags
end
Expand Down Expand Up @@ -325,32 +292,13 @@ def convert_string(text)
# for img: and link: described under handle_special_HYPERLINK

def gen_url url, text
if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then
type = "link"
path = "##{$1}"
id = " id=\"#{$2}\"" if $2
elsif url =~ /([A-Za-z]+):(.*)/ then
type = $1
path = $2
else
type = "http"
path = url
url = "http://#{url}"
end

if type == "link" then
url = if path[0, 1] == '#' then # is this meaningful?
path
else
self.class.gen_relative_url @from_path, path
end
end
scheme, url, id = parse_url url

if (type == "http" or type == "https" or type == "link") and
if %w[http https link].include?(scheme) and
url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
"<img src=\"#{url}\" />"
else
"<a#{id} href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
"<a#{id} href=\"#{url}\">#{text.sub(%r{^#{scheme}:/*}i, '')}</a>"
end
end

Expand Down
46 changes: 46 additions & 0 deletions lib/rdoc/markup/to_markdown.rb
Expand Up @@ -18,6 +18,9 @@ def initialize markup = nil
@headings[5] = ['##### ', '']
@headings[6] = ['###### ', '']

add_special_RDOCLINK
add_special_TIDYLINK

@hard_break = " \n"
end

Expand Down Expand Up @@ -130,5 +133,48 @@ def accept_verbatim verbatim
@res << "\n" unless @res =~ /\n\z/
end

##
# Creates a Markdown-style URL from +url+ with +text+.

def gen_url url, text
scheme, url, = parse_url url

"[#{text.sub(%r{^#{scheme}:/*}i, '')}](#{url})"
end

##
# Converts the RDoc markup tidylink into a Markdown.style link.

def handle_special_TIDYLINK special
text = special.text

return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/

label = $1
url = $2

gen_url url, label
end

##
# Converts the rdoc-...: links into a Markdown.style links.

def handle_special_RDOCLINK special
url = special.text

case url
when /\Ardoc-ref:/ then
$'
when /\Ardoc-label:footmark-/ then
"[^#{$'}]"
when /\Ardoc-label:foottext-/ then
"[^#{$'}]: "
when /\Ardoc-label:label-/ then
gen_url url, $'
when /\Ardoc-[a-z]+:/ then
$'
end
end

end

83 changes: 83 additions & 0 deletions test/test_rdoc_markup_formatter.rb
Expand Up @@ -48,6 +48,89 @@ def setup
@tt = @attributes.bitmap_for :TT
end

def test_class_gen_relative_url
def gen(from, to)
RDoc::Markup::ToHtml.gen_relative_url from, to
end

assert_equal 'a.html', gen('a.html', 'a.html')
assert_equal 'b.html', gen('a.html', 'b.html')

assert_equal 'd.html', gen('a/c.html', 'a/d.html')
assert_equal '../a.html', gen('a/c.html', 'a.html')
assert_equal 'a/c.html', gen('a.html', 'a/c.html')
end

def special_names
@attribute_manager.special.map do |_, mask|
@attributes.as_string mask
end
end

def test_add_special_RDOCLINK
@to.add_special_RDOCLINK

assert_includes special_names, 'RDOCLINK'
end

def test_add_special_TIDYLINK
@to.add_special_TIDYLINK

assert_includes special_names, 'TIDYLINK'
end

def test_parse_url
scheme, url, id = @to.parse_url 'example/foo'

assert_equal 'http', scheme
assert_equal 'http://example/foo', url
assert_equal nil, id
end

def test_parse_link
scheme, url, id = @to.parse_url 'link:README.txt'

assert_equal 'link', scheme
assert_equal 'README.txt', url
assert_equal nil, id
end

def test_parse_link_id
scheme, url, id = @to.parse_url 'link:README.txt#label-foo'

assert_equal 'link', scheme
assert_equal 'README.txt#label-foo', url
assert_equal nil, id
end

def test_parse_url_rdoc_label
scheme, url, id = @to.parse_url 'rdoc-label:foo'

assert_equal 'link', scheme
assert_equal '#foo', url
assert_equal nil, id

scheme, url, id = @to.parse_url 'rdoc-label:foo:bar'

assert_equal 'link', scheme
assert_equal '#foo', url
assert_equal ' id="bar"', id
end

def test_parse_url_scheme
scheme, url, id = @to.parse_url 'http://example/foo'

assert_equal 'http', scheme
assert_equal 'http://example/foo', url
assert_equal nil, id

scheme, url, id = @to.parse_url 'https://example/foo'

assert_equal 'https', scheme
assert_equal 'https://example/foo', url
assert_equal nil, id
end

def test_convert_tt_special
converted = @to.convert '<code>AAA</code>'

Expand Down
13 changes: 0 additions & 13 deletions test/test_rdoc_markup_to_html.rb
Expand Up @@ -10,19 +10,6 @@ def setup
@to = RDoc::Markup::ToHtml.new @options
end

def test_class_gen_relative_url
def gen(from, to)
RDoc::Markup::ToHtml.gen_relative_url from, to
end

assert_equal 'a.html', gen('a.html', 'a.html')
assert_equal 'b.html', gen('a.html', 'b.html')

assert_equal 'd.html', gen('a/c.html', 'a/d.html')
assert_equal '../a.html', gen('a/c.html', 'a.html')
assert_equal 'a/c.html', gen('a.html', 'a/c.html')
end

def accept_blank_line
assert_empty @to.res.join
end
Expand Down

0 comments on commit 89702e2

Please sign in to comment.