summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-25 02:43:03 +0000
committerdrbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2008-09-25 02:43:03 +0000
commit858362e761a41e7d96efbcb9b38ae815b1e388d7 (patch)
treeb47a0968d921320591f9218bc746e11a7922c53f
parent00b4a3f9c4aaf5aa038a9530ec515e1718ae1c42 (diff)
Import RDoc 2.2.1 r185
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19537 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog4
-rwxr-xr-xbin/ri3
-rw-r--r--lib/rdoc.rb190
-rw-r--r--lib/rdoc/code_objects.rb86
-rw-r--r--lib/rdoc/diagram.rb32
-rw-r--r--lib/rdoc/generator.rb36
-rw-r--r--lib/rdoc/generator/chm/chm.rb2
-rw-r--r--lib/rdoc/generator/html.rb226
-rw-r--r--lib/rdoc/generator/html/common.rb24
-rw-r--r--lib/rdoc/generator/html/frameless.rb759
-rw-r--r--lib/rdoc/generator/html/hefss.rb358
-rw-r--r--lib/rdoc/generator/html/html.rb383
-rw-r--r--lib/rdoc/generator/html/kilmer.rb329
-rw-r--r--lib/rdoc/generator/html/kilmerfactory.rb427
-rw-r--r--lib/rdoc/generator/html/one_page_html.rb11
-rw-r--r--lib/rdoc/generator/texinfo.rb9
-rw-r--r--lib/rdoc/generator/texinfo/class.texinfo.erb4
-rw-r--r--lib/rdoc/generator/xml.rb11
-rw-r--r--lib/rdoc/generator/xml/xml.rb30
-rw-r--r--lib/rdoc/markup.rb95
-rw-r--r--lib/rdoc/markup/inline.rb2
-rw-r--r--lib/rdoc/markup/to_html.rb15
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb88
-rw-r--r--lib/rdoc/markup/to_texinfo.rb2
-rw-r--r--lib/rdoc/options.rb9
-rw-r--r--lib/rdoc/parser.rb23
-rw-r--r--lib/rdoc/parser/c.rb64
-rw-r--r--lib/rdoc/parser/perl.rb165
-rw-r--r--lib/rdoc/parser/ruby.rb12
-rw-r--r--lib/rdoc/parser/simple.rb2
-rw-r--r--lib/rdoc/rdoc.rb6
-rw-r--r--lib/rdoc/ri/cache.rb11
-rw-r--r--lib/rdoc/ri/descriptions.rb3
-rw-r--r--lib/rdoc/ri/display.rb201
-rw-r--r--lib/rdoc/ri/driver.rb522
-rw-r--r--lib/rdoc/ri/formatter.rb2
-rw-r--r--lib/rdoc/ri/paths.rb13
-rw-r--r--lib/rdoc/ri/reader.rb6
-rw-r--r--lib/rdoc/ri/util.rb2
-rw-r--r--test/rdoc/binary.datbin0 -> 1024 bytes
-rw-r--r--test/rdoc/rdoc_markup_to_html_crossref_reference.rb31
-rw-r--r--test/rdoc/test_attribute_manager.rb73
-rw-r--r--test/rdoc/test_rdoc_info_formatting.rb12
-rw-r--r--test/rdoc/test_rdoc_info_sections.rb4
-rw-r--r--test/rdoc/test_rdoc_markup_attribute_manager.rb28
-rw-r--r--test/rdoc/test_rdoc_markup_to_html.rb18
-rw-r--r--test/rdoc/test_rdoc_markup_to_html_crossref.rb284
-rw-r--r--test/rdoc/test_rdoc_parser.rb18
-rw-r--r--test/rdoc/test_rdoc_parser_c.rb31
-rw-r--r--test/rdoc/test_rdoc_parser_perl.rb72
-rw-r--r--test/rdoc/test_rdoc_parser_ruby.rb212
-rw-r--r--test/rdoc/test_rdoc_ri_default_display.rb53
-rw-r--r--test/rdoc/test_rdoc_ri_driver.rb2
-rw-r--r--test/rdoc/test_rdoc_ri_formatter.rb2
54 files changed, 2816 insertions, 2191 deletions
diff --git a/ChangeLog b/ChangeLog
index e3ec2b2294b..b9f6fcdac86 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Thu Sep 25 11:22:51 2008
+
+ * lib/rdoc*: Update to RDoc 2.2.1 r185.
+
Thu Sep 25 02:08:47 2008 Tanaka Akira <akr@fsij.org>
* io.c (rb_io_mode_enc): make it static.
diff --git a/bin/ri b/bin/ri
index 0d4e3304d89..243557403c6 100755
--- a/bin/ri
+++ b/bin/ri
@@ -1,6 +1,5 @@
-#!/usr//bin/env ruby
+#!/usr/bin/env ruby
require 'rdoc/ri/driver'
RDoc::RI::Driver.run ARGV
-
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
index 53b72241f88..797b119fbf3 100644
--- a/lib/rdoc.rb
+++ b/lib/rdoc.rb
@@ -1,14 +1,14 @@
$DEBUG_RDOC = nil
##
-# RDoc - Ruby Documentation System
+# = \RDoc - Ruby Documentation System
#
# This package contains RDoc and RDoc::Markup. RDoc is an application that
-# produces documentation for one or more Ruby source files. We work similarly
+# produces documentation for one or more Ruby source files. It works similarly
# to JavaDoc, parsing the source, and extracting the definition for classes,
-# modules, and methods (along with includes and requires). We associate with
+# modules, and methods (along with includes and requires). It associates with
# these optional documentation contained in the immediately preceding comment
-# block, and then render the result using a pluggable output formatter.
+# block, and then renders the result using a pluggable output formatter.
# RDoc::Markup is a library that converts plain text into various output
# formats. The markup library is used to interpret the comment blocks that
# RDoc uses to document methods, classes, and so on.
@@ -18,8 +18,6 @@ $DEBUG_RDOC = nil
# * If you want to use RDoc to create documentation for your Ruby source files,
# read on.
# * If you want to include extensions written in C, see RDoc::Parser::C
-# * For information on the various markups available in comment blocks, see
-# RDoc::Markup.
# * If you want to drive RDoc programmatically, see RDoc::RDoc.
# * If you want to use the library to format text blocks into HTML, have a look
# at RDoc::Markup.
@@ -28,21 +26,21 @@ $DEBUG_RDOC = nil
#
# == Summary
#
-# Once installed, you can create documentation using the 'rdoc' command
-# (the command is 'rdoc.bat' under Windows)
+# Once installed, you can create documentation using the +rdoc+ command
#
# % rdoc [options] [names...]
#
-# Type "rdoc --help" for an up-to-date option summary.
+# For an up-to-date option summary, type
+# % rdoc --help
#
# A typical use might be to generate documentation for a package of Ruby
-# source (such as rdoc itself).
+# source (such as RDoc itself).
#
# % rdoc
#
# This command generates documentation for all the Ruby and C source
# files in and below the current directory. These will be stored in a
-# documentation tree starting in the subdirectory 'doc'.
+# documentation tree starting in the subdirectory +doc+.
#
# You can make this slightly more useful for your readers by having the
# index page contain the documentation for the primary file. In our
@@ -54,20 +52,46 @@ $DEBUG_RDOC = nil
# in comment blocks in the documentation this generates.
#
# RDoc uses file extensions to determine how to process each file. File names
-# ending +.rb+ and <tt>.rbw</tt> are assumed to be Ruby source. Files
+# ending +.rb+ and +.rbw+ are assumed to be Ruby source. Files
# ending +.c+ are parsed as C files. All other files are assumed to
# contain just Markup-style markup (with or without leading '#' comment
# markers). If directory names are passed to RDoc, they are scanned
# recursively for C and Ruby source files only.
#
-# = Markup
+# == \Options
+# rdoc can be passed a variety of command-line options. In addition,
+# options can be specified via the +RDOCOPT+ environment variable, which
+# functions similarly to the +RUBYOPT+ environment variable.
#
-# For information on how to make lists, hyperlinks, etc. with RDoc, see
-# RDoc::Markup.
+# % export RDOCOPT="-S"
#
-# Comment blocks can be written fairly naturally, either using '#' on
+# will make rdoc default to inline method source code. Command-line options
+# always will override those in +RDOCOPT+.
+#
+# Run
+#
+# % rdoc --help
+#
+# for full details on rdoc's options.
+#
+# Here are some of the most commonly used options.
+# [-d, --diagram]
+# Generate diagrams showing modules and
+# classes. You need dot V1.8.6 or later to
+# use the --diagram option correctly. Dot is
+# available from http://graphviz.org
+#
+# [-S, --inline-source]
+# Show method source code inline, rather than via a popup link.
+#
+# [-T, --template=NAME]
+# Set the template used when generating output.
+#
+# == Documenting Source Code
+#
+# Comment blocks can be written fairly naturally, either using +#+ on
# successive lines of the comment, or by including the comment in
-# an =begin/=end block. If you use the latter form, the =begin line must be
+# a =begin/=end block. If you use the latter form, the =begin line must be
# flagged with an RDoc tag:
#
# =begin rdoc
@@ -93,7 +117,7 @@ $DEBUG_RDOC = nil
# # ...
# end
#
-# Names of classes, source files, and any method names containing an
+# Names of classes, files, and any method names containing an
# underscore or preceded by a hash character are automatically hyperlinked
# from comment text to their description.
#
@@ -124,15 +148,109 @@ $DEBUG_RDOC = nil
# +:yields:+ is an example of a documentation directive. These appear
# immediately after the start of the document element they are modifying.
#
+# == \Markup
+#
+# * The markup engine looks for a document's natural left margin. This is
+# used as the initial margin for the document.
+#
+# * Consecutive lines starting at this margin are considered to be a
+# paragraph.
+#
+# * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
+# taken to be the start of a list. The margin in increased to be the first
+# non-space following the list start flag. Subsequent lines should be
+# indented to this new margin until the list ends. For example:
+#
+# * this is a list with three paragraphs in
+# the first item. This is the first paragraph.
+#
+# And this is the second paragraph.
+#
+# 1. This is an indented, numbered list.
+# 2. This is the second item in that list
+#
+# This is the third conventional paragraph in the
+# first list item.
+#
+# * This is the second item in the original list
+#
+# * You can also construct labeled lists, sometimes called description
+# or definition lists. Do this by putting the label in square brackets
+# and indenting the list body:
+#
+# [cat] a small furry mammal
+# that seems to sleep a lot
+#
+# [ant] a little insect that is known
+# to enjoy picnics
+#
+# A minor variation on labeled lists uses two colons to separate the
+# label from the list body:
+#
+# cat:: a small furry mammal
+# that seems to sleep a lot
+#
+# ant:: a little insect that is known
+# to enjoy picnics
+#
+# This latter style guarantees that the list bodies' left margins are
+# aligned: think of them as a two column table.
+#
+# * Any line that starts to the right of the current margin is treated
+# as verbatim text. This is useful for code listings. The example of a
+# list above is also verbatim text.
+#
+# * A line starting with an equals sign (=) is treated as a
+# heading. Level one headings have one equals sign, level two headings
+# have two,and so on.
+#
+# * A line starting with three or more hyphens (at the current indent)
+# generates a horizontal rule. The more hyphens, the thicker the rule
+# (within reason, and if supported by the output device)
+#
+# * You can use markup within text (except verbatim) to change the
+# appearance of parts of that text. Out of the box, RDoc::Markup
+# supports word-based and general markup.
+#
+# Word-based markup uses flag characters around individual words:
+#
+# [\*word*] displays word in a *bold* font
+# [\_word_] displays word in an _emphasized_ font
+# [\+word+] displays word in a +code+ font
+#
+# General markup affects text between a start delimiter and and end
+# delimiter. Not surprisingly, these delimiters look like HTML markup.
+#
+# [\<b>text...</b>] displays word in a *bold* font
+# [\<em>text...</em>] displays word in an _emphasized_ font
+# [\\<i>text...</i>] displays word in an <i>italicized</i> font
+# [\<tt>text...</tt>] displays word in a +code+ font
+#
+# Unlike conventional Wiki markup, general markup can cross line
+# boundaries. You can turn off the interpretation of markup by
+# preceding the first character with a backslash. This only works for
+# simple markup, not HTML-style markup.
+#
+# * Hyperlinks to the web starting http:, mailto:, ftp:, or www. are
+# recognized. An HTTP url that references an external image file is
+# converted into an inline <IMG..>. Hyperlinks starting 'link:' are
+# assumed to refer to local files whose path is relative to the --op
+# directory.
+#
+# Hyperlinks can also be of the form <tt>label</tt>[url], in which
+# case the label is used in the displayed text, and +url+ is
+# used as the target. If +label+ contains multiple words,
+# put it in braces: <em>{multi word label}[</em>url<em>]</em>.
+#
# == Directives
#
# [+:nodoc:+ / +:nodoc:+ all]
-# Don't include this element in the documentation. For classes
-# and modules, the methods, aliases, constants, and attributes
-# directly within the affected class or module will also be
-# omitted. By default, though, modules and classes within that
-# class of module _will_ be documented. This is turned off by
-# adding the +all+ modifier.
+# This directive prevents documentation for the element from
+# being generated. For classes and modules, the methods, aliases,
+# constants, and attributes directly within the affected class or
+# module also will be omitted. By default, though, modules and
+# classes within that class of module _will_ be documented. This is
+# turned off by adding the +all+ modifier.
#
# module MyModule # :nodoc:
# class Input
@@ -144,22 +262,22 @@ $DEBUG_RDOC = nil
# end
# end
#
-# In the above code, only class +MyModule::Input+ will be documented.The
-# The :nodoc: directive is global across all files the class or module
-# appears in, so use :stopdoc:/:startdoc: to only omit documentation for a
-# particular set of methods, etc.
+# In the above code, only class <tt>MyModule::Input</tt> will be documented.
+# The +:nodoc:+ directive is global across all files for the class or module
+# to which it applies, so use +:stopdoc:+/+:startdoc:+ to suppress
+# documentation only for a particular set of methods, etc.
#
# [+:doc:+]
-# Force a method or attribute to be documented even if it wouldn't otherwise
-# be. Useful if, for example, you want to include documentation of a
+# Forces a method or attribute to be documented even if it wouldn't be
+# otherwise. Useful if, for example, you want to include documentation of a
# particular private method.
#
# [+:notnew:+]
# Only applicable to the +initialize+ instance method. Normally RDoc
-# assumes that the documentation and parameters for #initialize are
-# actually for the ::new method, and so fakes out a ::new for the class.
-# The :notnew: modifier stops this. Remember that #initialize is protected,
-# so you won't see the documentation unless you use the -a command line
+# assumes that the documentation and parameters for +initialize+ are
+# actually for the +new+ method, and so fakes out a +new+ for the class.
+# The +:notnew:+ modifier stops this. Remember that +initialize+ is private,
+# so you won't see the documentation unless you use the +-a+ command line
# option.
#
# Comment blocks can contain other directives:
@@ -209,7 +327,7 @@ $DEBUG_RDOC = nil
# last. If you don't specify a +:startdoc:+ by the end of the container,
# disables documentation for the entire class or module.
#
-# = Other stuff
+# == Other stuff
#
# RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>
#
@@ -254,7 +372,7 @@ module RDoc
##
# RDoc version you are using
- VERSION = "2.1.0"
+ VERSION = "2.2.1"
##
# Name of the dotfile that contains the description of files to be processed
diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb
index fbdb612b92e..0916b033986 100644
--- a/lib/rdoc/code_objects.rb
+++ b/lib/rdoc/code_objects.rb
@@ -220,6 +220,22 @@ module RDoc
end
##
+ # return the classes Hash (only to be used internally)
+
+ def classes_hash
+ @classes
+ end
+ protected :classes_hash
+
+ ##
+ # return the modules Hash (only to be used internally)
+
+ def modules_hash
+ @modules
+ end
+ protected :modules_hash
+
+ ##
# Change the default visibility for new methods
def ongoing_visibility=(vis)
@@ -272,7 +288,24 @@ module RDoc
end
def add_class(class_type, name, superclass)
- add_class_or_module @classes, class_type, name, superclass
+ klass = add_class_or_module @classes, class_type, name, superclass
+
+ #
+ # If the parser encounters Container::Item before encountering
+ # Container, then it assumes that Container is a module. This
+ # may not be the case, so remove Container from the module list
+ # if present and transfer any contained classes and modules to
+ # the new class.
+ #
+ mod = @modules.delete(name)
+
+ if mod then
+ klass.classes_hash.update(mod.classes_hash)
+ klass.modules_hash.update(mod.modules_hash)
+ klass.method_list.concat(mod.method_list)
+ end
+
+ return klass
end
def add_module(class_type, name)
@@ -282,25 +315,41 @@ module RDoc
def add_method(a_method)
a_method.visibility = @visibility
add_to(@method_list, a_method)
+
+ unmatched_alias_list = @unmatched_alias_lists[a_method.name]
+ if unmatched_alias_list then
+ unmatched_alias_list.each do |unmatched_alias|
+ add_alias_impl unmatched_alias, a_method
+ @aliases.delete unmatched_alias
+ end
+
+ @unmatched_alias_lists.delete a_method.name
+ end
end
def add_attribute(an_attribute)
add_to(@attributes, an_attribute)
end
+ def add_alias_impl(an_alias, meth)
+ new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
+ new_meth.is_alias_for = meth
+ new_meth.singleton = meth.singleton
+ new_meth.params = meth.params
+ new_meth.comment = "Alias for \##{meth.name}"
+ meth.add_alias(new_meth)
+ add_method(new_meth)
+ end
+
def add_alias(an_alias)
meth = find_instance_method_named(an_alias.old_name)
if meth then
- new_meth = AnyMethod.new(an_alias.text, an_alias.new_name)
- new_meth.is_alias_for = meth
- new_meth.singleton = meth.singleton
- new_meth.params = meth.params
- new_meth.comment = "Alias for \##{meth.name}"
- meth.add_alias(new_meth)
- add_method(new_meth)
+ add_alias_impl(an_alias, meth)
else
add_to(@aliases, an_alias)
+ unmatched_alias_list = @unmatched_alias_lists[an_alias.old_name] ||= []
+ unmatched_alias_list.push(an_alias)
end
an_alias
@@ -360,6 +409,10 @@ module RDoc
@requires = []
@includes = []
@constants = []
+
+ # This Hash maps a method name to a list of unmatched
+ # aliases (aliases of a method not yet encountered).
+ @unmatched_alias_lists = {}
end
# and remove classes and modules when we see a :nodoc: all
@@ -374,9 +427,12 @@ module RDoc
# Find a named module
def find_module_named(name)
- return self if self.name == name
+ # First check the enclosed modules, then check the module itself,
+ # then check the enclosing modules (this mirrors the check done by
+ # the Ruby parser)
res = @modules[name] || @classes[name]
return res if res
+ return self if self.name == name
find_enclosing_module_named(name)
end
@@ -435,6 +491,7 @@ module RDoc
unless modules.empty? then
module_name = modules.shift
result = find_module_named(module_name)
+
if result then
modules.each do |name|
result = result.find_module_named(name)
@@ -573,9 +630,18 @@ module RDoc
cls = all[name]
- unless cls then
+ if !cls then
cls = class_type.new name, superclass
all[name] = cls unless @done_documenting
+ else
+ # If the class has been encountered already, check that its
+ # superclass has been set (it may not have been, depending on
+ # the context in which it was encountered).
+ if class_type == NormalClass
+ if !cls.superclass then
+ cls.superclass = superclass
+ end
+ end
end
collection[name] = cls unless @done_documenting
diff --git a/lib/rdoc/diagram.rb b/lib/rdoc/diagram.rb
index e235e043dc2..4aa2ec56563 100644
--- a/lib/rdoc/diagram.rb
+++ b/lib/rdoc/diagram.rb
@@ -311,28 +311,30 @@ module RDoc
# inclusion on the page
def wrap_in_image_map(src, dot)
- res = %{<map id="map" name="map">\n}
+ res = ""
dot_map = `dot -Tismap #{src}`
- dot_map.split($/).each do |area|
- unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
- $stderr.puts "Unexpected output from dot:\n#{area}"
- return nil
- end
+
+ if(!dot_map.empty?)
+ res << %{<map id="map" name="map">\n}
+ dot_map.split($/).each do |area|
+ unless area =~ /^rectangle \((\d+),(\d+)\) \((\d+),(\d+)\) ([\/\w.]+)\s*(.*)/
+ $stderr.puts "Unexpected output from dot:\n#{area}"
+ return nil
+ end
- xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
- url, area_name = $5, $6
+ xs, ys = [$1.to_i, $3.to_i], [$2.to_i, $4.to_i]
+ url, area_name = $5, $6
- res << %{ <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
- res << %{ href="#{url}" alt="#{area_name}" />\n}
+ res << %{ <area shape="rect" coords="#{xs.min},#{ys.min},#{xs.max},#{ys.max}" }
+ res << %{ href="#{url}" alt="#{area_name}" />\n}
+ end
+ res << "</map>\n"
end
- res << "</map>\n"
-# map_file = src.sub(/.dot/, '.map')
-# system("dot -Timap #{src} -o #{map_file}")
- res << %{<img src="#{dot}" usemap="#map" border="0" alt="#{dot}">}
+
+ res << %{<img src="#{dot}" usemap="#map" alt="#{dot}" />}
return res
end
end
end
-
diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb
index fbc08c4e209..d695e661d16 100644
--- a/lib/rdoc/generator.rb
+++ b/lib/rdoc/generator.rb
@@ -127,7 +127,7 @@ module RDoc::Generator
# * a complete list of all hyperlinkable terms (file, class, module, and
# method names)
- def self.build_indicies(toplevels, options)
+ def self.build_indices(toplevels, options)
files = []
classes = []
@@ -215,7 +215,7 @@ module RDoc::Generator
@methods.sort.map do |meth|
{
"name" => CGI.escapeHTML(meth.name),
- "aref" => "#{path_prefix}\##{meth.aref}"
+ "aref" => "##{meth.aref}"
}
end
end
@@ -614,9 +614,9 @@ module RDoc::Generator
def class_attribute_values
h_name = CGI.escapeHTML(name)
- @values["path"] = @path
+ @values["href"] = @path
@values["classmod"] = @is_module ? "Module" : "Class"
- @values["title"] = "#{@values['classmod']}: #{h_name}"
+ @values["title"] = "#{@values['classmod']}: #{h_name} [#{@options.title}]"
c = @context
c = c.parent while c and not c.diagram
@@ -704,7 +704,7 @@ module RDoc::Generator
def filename_to_label
@context.file_relative_name.gsub(/%|\/|\?|\#/) do
- '%%%x' % $&[0].unpack('C')
+ ('%%%x' % $&[0]).unpack('C')
end
end
@@ -791,7 +791,7 @@ module RDoc::Generator
full_path = @context.file_absolute_name
short_name = ::File.basename full_path
- @values["title"] = CGI.escapeHTML("File: #{short_name}")
+ @values["title"] = CGI.escapeHTML("File: #{short_name} [#{@options.title}]")
if @context.diagram then
@values["diagram"] = diagram_reference(@context.diagram)
@@ -821,18 +821,18 @@ module RDoc::Generator
attr_reader :img_url
attr_reader :source_code
- @@seq = "M000000"
-
- @@all_methods = []
-
def self.all_methods
@@all_methods
end
def self.reset
@@all_methods = []
+ @@seq = "M000000"
end
+ # Initialize the class variables.
+ self.reset
+
def initialize(context, html_class, options)
# TODO: rethink the class hierarchy here...
@context = context
@@ -1043,12 +1043,18 @@ module RDoc::Generator
first = $1.to_i - 1
last = first + src.count("\n")
size = last.to_s.length
- real_fmt = "%#{size}d: "
- fmt = " " * (size+2)
+ fmt = "%#{size}d: "
+ is_first_line = true
+ line_num = first
src.gsub!(/^/) do
- res = sprintf(fmt, first)
- first += 1
- fmt = real_fmt
+ if is_first_line then
+ is_first_line = false
+ res = " " * (size+2)
+ else
+ res = sprintf(fmt, line_num)
+ end
+
+ line_num += 1
res
end
end
diff --git a/lib/rdoc/generator/chm/chm.rb b/lib/rdoc/generator/chm/chm.rb
index 0a17a9e1eaa..cceeca5dfc0 100644
--- a/lib/rdoc/generator/chm/chm.rb
+++ b/lib/rdoc/generator/chm/chm.rb
@@ -6,6 +6,8 @@ module RDoc::Generator::CHM::CHM
HTML = RDoc::Generator::HTML::HTML
INDEX = HTML::INDEX
+
+ STYLE = HTML::STYLE
CLASS_INDEX = HTML::CLASS_INDEX
CLASS_PAGE = HTML::CLASS_PAGE
diff --git a/lib/rdoc/generator/html.rb b/lib/rdoc/generator/html.rb
index a9e030a8965..d136de7b00c 100644
--- a/lib/rdoc/generator/html.rb
+++ b/lib/rdoc/generator/html.rb
@@ -68,7 +68,6 @@ class RDoc::Generator::HTML
def initialize(options) #:not-new:
@options = options
load_html_template
- @main_page_path = nil
end
##
@@ -94,6 +93,15 @@ class RDoc::Generator::HTML
# If the template name contains a slash, use it literally
def load_html_template
+ #
+ # If the template is not a path, first look for it
+ # in rdoc's HTML template directory. Perhaps this behavior should
+ # be reversed (first try to include the template and, only if that
+ # fails, try to include it in the default template directory).
+ # One danger with reversing the behavior, however, is that
+ # if something like require 'html' could load up an
+ # unrelated file in the standard library or in a gem.
+ #
template = @options.template
unless template =~ %r{/|\\} then
@@ -101,14 +109,25 @@ class RDoc::Generator::HTML
template)
end
- require template
-
- @template = self.class.const_get @options.template.upcase
- @options.template_class = @template
+ begin
+ require template
+
+ @template = self.class.const_get @options.template.upcase
+ @options.template_class = @template
+ rescue LoadError => e
+ #
+ # The template did not exist in the default template directory, so
+ # see if require can find the template elsewhere (in a gem, for
+ # instance).
+ #
+ if(e.message[template] && template != @options.template)
+ template = @options.template
+ retry
+ end
- rescue LoadError
- $stderr.puts "Could not find HTML template '#{template}'"
- exit 99
+ $stderr.puts "Could not find HTML template '#{template}': #{e.message}"
+ exit 99
+ end
end
##
@@ -146,14 +165,16 @@ class RDoc::Generator::HTML
end
def build_indices
- @files, @classes = RDoc::Generator::Context.build_indicies(@toplevels,
- @options)
+ @files, @classes = RDoc::Generator::Context.build_indices(@toplevels,
+ @options)
end
##
# Generate all the HTML
def generate_html
+ @main_url = main_url
+
# the individual descriptions for files and classes
gen_into(@files)
gen_into(@classes)
@@ -165,23 +186,50 @@ class RDoc::Generator::HTML
gen_main_index
# this method is defined in the template file
- write_extra_pages if defined? write_extra_pages
+ values = {
+ 'title_suffix' => CGI.escapeHTML("[#{@options.title}]"),
+ 'charset' => @options.charset,
+ 'style_url' => style_url('', @options.css),
+ }
+
+ @template.write_extra_pages(values) if @template.respond_to?(:write_extra_pages)
end
def gen_into(list)
- @file_list ||= index_to_links @files
- @class_list ||= index_to_links @classes
- @method_list ||= index_to_links RDoc::Generator::Method.all_methods
+ #
+ # The file, class, and method lists technically should be regenerated
+ # for every output file, in order that the relative links be correct
+ # (we are worried here about frameless templates, which need this
+ # information for every generated page). Doing this is a bit slow,
+ # however. For a medium-sized gem, this increased rdoc's runtime by
+ # about 5% (using the 'time' command-line utility). While this is not
+ # necessarily a problem, I do not want to pessimize rdoc for large
+ # projects, however, and so we only regenerate the lists when the
+ # directory of the output file changes, which seems like a reasonable
+ # optimization.
+ #
+ file_list = {}
+ class_list = {}
+ method_list = {}
+ prev_op_dir = nil
list.each do |item|
next unless item.document_self
op_file = item.path
+ op_dir = File.dirname(op_file)
+
+ if(op_dir != prev_op_dir)
+ file_list = index_to_links op_file, @files
+ class_list = index_to_links op_file, @classes
+ method_list = index_to_links op_file, RDoc::Generator::Method.all_methods
+ end
+ prev_op_dir = op_dir
- FileUtils.mkdir_p File.dirname(op_file)
+ FileUtils.mkdir_p op_dir
open op_file, 'w' do |io|
- item.write_on io, @file_list, @class_list, @method_list
+ item.write_on io, file_list, class_list, method_list
end
end
end
@@ -211,8 +259,9 @@ class RDoc::Generator::HTML
values = {
"entries" => res,
+ 'title' => CGI.escapeHTML("#{title} [#{@options.title}]"),
'list_title' => CGI.escapeHTML(title),
- 'index_url' => main_url,
+ 'index_url' => @main_url,
'charset' => @options.charset,
'style_url' => style_url('', @options.css),
}
@@ -230,47 +279,55 @@ class RDoc::Generator::HTML
def gen_main_index
if @template.const_defined? :FRAMELESS then
- main = @files.find do |file|
- @main_page == file.name
- end
-
- if main.nil? then
- main = @classes.find do |klass|
- main_page == klass.context.full_name
- end
+ #
+ # If we're using a template without frames, then just redirect
+ # to it from index.html.
+ #
+ # One alternative to this, expanding the main page's template into
+ # index.html, is tricky because the relative URLs will be different
+ # (since index.html is located in at the site's root,
+ # rather than within a files or a classes subdirectory).
+ #
+ open 'index.html', 'w' do |f|
+ f.puts(%{<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">})
+ f.puts(%{<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+ lang="en">})
+ f.puts(%{<head>})
+ f.puts(%{<title>#{CGI.escapeHTML(@options.title)}</title>})
+ f.puts(%{<meta http-equiv="refresh" content="0; url=#{@main_url}" />})
+ f.puts(%{</head>})
+ f.puts(%{<body></body>})
+ f.puts(%{</html>})
end
else
main = RDoc::TemplatePage.new @template::INDEX
- end
- open 'index.html', 'w' do |f|
- style_url = style_url '', @options.css
+ open 'index.html', 'w' do |f|
+ style_url = style_url '', @options.css
+
+ classes = @classes.sort.map { |klass| klass.value_hash }
+
+ values = {
+ 'initial_page' => @main_url,
+ 'style_url' => style_url('', @options.css),
+ 'title' => CGI.escapeHTML(@options.title),
+ 'charset' => @options.charset,
+ 'classes' => classes,
+ }
+
+ values['inline_source'] = @options.inline_source
- classes = @classes.sort.map { |klass| klass.value_hash }
-
- values = {
- 'main_page' => @main_page,
- 'initial_page' => main_url,
- 'style_url' => style_url('', @options.css),
- 'title' => CGI.escapeHTML(@options.title),
- 'charset' => @options.charset,
- 'classes' => classes,
- }
-
- values['inline_source'] = @options.inline_source
-
- if main.respond_to? :write_on then
- main.write_on f, @file_list, @class_list, @method_list, values
- else
main.write_html_on f, values
end
end
end
- def index_to_links(collection)
+ def index_to_links(output_path, collection)
collection.sort.map do |f|
next unless f.document_self
- { "href" => f.path, "name" => f.index_name }
+ { "href" => RDoc::Markup::ToHtml.gen_relative_url(output_path, f.path),
+ "name" => f.index_name }
end.compact
end
@@ -278,32 +335,48 @@ class RDoc::Generator::HTML
# Returns the url of the main page
def main_url
- @main_page = @options.main_page
- @main_page_ref = nil
-
- if @main_page then
- @main_page_ref = RDoc::Generator::AllReferences[@main_page]
-
- if @main_page_ref then
- @main_page_path = @main_page_ref.path
+ main_page = @options.main_page
+
+ #
+ # If a main page has been specified (--main), then search for it
+ # in the AllReferences array. This allows either files or classes
+ # to be used for the main page.
+ #
+ if main_page then
+ main_page_ref = RDoc::Generator::AllReferences[main_page]
+
+ if main_page_ref then
+ return main_page_ref.path
else
- $stderr.puts "Could not find main page #{@main_page}"
+ $stderr.puts "Could not find main page #{main_page}"
end
end
- unless @main_page_path then
- file = @files.find { |context| context.document_self }
- @main_page_path = file.path if file
+ #
+ # No main page has been specified, so just use the README.
+ #
+ @files.each do |file|
+ if file.name =~ /^README/ then
+ return file.path
+ end
end
- unless @main_page_path then
- $stderr.puts "Couldn't find anything to document"
- $stderr.puts "Perhaps you've used :stopdoc: in all classes"
- exit 1
+ #
+ # There's no README (shame! shame!). Just use the first file
+ # that will be documented.
+ #
+ @files.each do |file|
+ if file.document_self then
+ return file.path
+ end
end
- @main_page_path
+ #
+ # There are no files to be documented... Something seems very wrong.
+ #
+ raise RDoc::Error, "Couldn't find anything to document (perhaps :stopdoc: has been used in all classes)!"
end
+ private :main_url
end
@@ -349,12 +422,9 @@ class RDoc::Generator::HTMLInOne < RDoc::Generator::HTML
'charset' => @options.charset,
'files' => gen_into(@files),
'classes' => gen_into(@classes),
- 'title' => CGI.escapeHTML(@options.title),
+ 'title' => CGI.escapeHTML(@options.title),
}
- # this method is defined in the template file
- write_extra_pages if defined? write_extra_pages
-
template = RDoc::TemplatePage.new @template::ONE_PAGE
if @options.op_name
@@ -372,26 +442,4 @@ class RDoc::Generator::HTMLInOne < RDoc::Generator::HTML
end
res
end
-
- def gen_file_index
- gen_an_index(@files, 'Files')
- end
-
- def gen_class_index
- gen_an_index(@classes, 'Classes')
- end
-
- def gen_method_index
- gen_an_index(RDoc::Generator::Method.all_methods, 'Methods')
- end
-
- def gen_an_index(collection, title)
- return {
- "entries" => index_to_links(collection),
- 'list_title' => title,
- 'index_url' => main_url,
- }
- end
-
end
-
diff --git a/lib/rdoc/generator/html/common.rb b/lib/rdoc/generator/html/common.rb
new file mode 100644
index 00000000000..b25f009a72f
--- /dev/null
+++ b/lib/rdoc/generator/html/common.rb
@@ -0,0 +1,24 @@
+#
+# The templates require further refactoring. In particular,
+# * Some kind of HTML generation library should be used.
+#
+# Also, all of the templates require some TLC from a designer.
+#
+# Right now, this file contains some constants that are used by all
+# of the templates.
+#
+module RDoc::Generator::HTML::Common
+ XHTML_STRICT_PREAMBLE = <<-EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+EOF
+
+ XHTML_FRAME_PREAMBLE = <<-EOF
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
+EOF
+
+ HTML_ELEMENT = <<-EOF
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+EOF
+end
diff --git a/lib/rdoc/generator/html/frameless.rb b/lib/rdoc/generator/html/frameless.rb
index 2af890ce041..0375fee313d 100644
--- a/lib/rdoc/generator/html/frameless.rb
+++ b/lib/rdoc/generator/html/frameless.rb
@@ -1,15 +1,16 @@
-require 'rdoc/generator/html'
-require 'rdoc/generator/html/one_page_html'
+require 'rdoc/generator/html/html'
##
# = CSS2 RDoc HTML template
#
-# This is a template for RDoc that uses XHTML 1.0 Transitional and dictates a
+# This is a template for RDoc that uses XHTML 1.0 Strict and dictates a
# bit more of the appearance of the output to cascading stylesheets than the
# default. It was designed for clean inline code display, and uses DHTMl to
# toggle the visbility of each method's source with each click on the '[source]'
# link.
#
+# Frameless basically is the html template without frames.
+#
# == Authors
#
# * Michael Granger <ged@FaerieMUD.org>
@@ -25,692 +26,47 @@ module RDoc::Generator::HTML::FRAMELESS
FRAMELESS = true
- FONTS = "Verdana,Arial,Helvetica,sans-serif"
-
- STYLE = <<-EOF
-body {
- font-family: #{FONTS};
- font-size: 90%;
- margin: 0;
- margin-left: 40px;
- padding: 0;
- background: white;
-}
-
-h1, h2, h3, h4 {
- margin: 0;
- color: #efefef;
- background: transparent;
-}
-
-h1 {
- font-size: 150%;
-}
-
-h2,h3,h4 {
- margin-top: 1em;
-}
-
-:link, :visited {
- background: #eef;
- color: #039;
- text-decoration: none;
-}
-
-:link:hover, :visited:hover {
- background: #039;
- color: #eef;
-}
-
-/* Override the base stylesheet's Anchor inside a table cell */
-td > :link, td > :visited {
- background: transparent;
- color: #039;
- text-decoration: none;
-}
-
-/* and inside a section title */
-.section-title > :link, .section-title > :visited {
- background: transparent;
- color: #eee;
- text-decoration: none;
-}
-
-/* === Structural elements =================================== */
-
-.index {
- margin: 0;
- margin-left: -40px;
- padding: 0;
- font-size: 90%;
-}
-
-.index :link, .index :visited {
- margin-left: 0.7em;
-}
-
-.index .section-bar {
- margin-left: 0px;
- padding-left: 0.7em;
- background: #ccc;
- font-size: small;
-}
-
-#classHeader, #fileHeader {
- width: auto;
- color: white;
- padding: 0.5em 1.5em 0.5em 1.5em;
- margin: 0;
- margin-left: -40px;
- border-bottom: 3px solid #006;
-}
-
-#classHeader :link, #fileHeader :link,
-#classHeader :visited, #fileHeader :visited {
- background: inherit;
- color: white;
-}
-
-#classHeader td, #fileHeader td {
- background: inherit;
- color: white;
-}
-
-#fileHeader {
- background: #057;
-}
-
-#classHeader {
- background: #048;
-}
-
-.class-name-in-header {
- font-size: 180%;
- font-weight: bold;
-}
-
-#bodyContent {
- padding: 0 1.5em 0 1.5em;
-}
-
-#description {
- padding: 0.5em 1.5em;
- background: #efefef;
- border: 1px dotted #999;
-}
-
-#description h1, #description h2, #description h3,
-#description h4, #description h5, #description h6 {
- color: #125;
- background: transparent;
-}
-
-#copyright {
- color: #333;
- background: #efefef;
- font: 0.75em sans-serif;
- margin-top: 5em;
- margin-bottom: 0;
- padding: 0.5em 2em;
-}
-
-/* === Classes =================================== */
-
-table.header-table {
- color: white;
- font-size: small;
-}
-
-.type-note {
- font-size: small;
- color: #dedede;
-}
-
-.xxsection-bar {
- background: #eee;
- color: #333;
- padding: 3px;
-}
-
-.section-bar {
- color: #333;
- border-bottom: 1px solid #999;
- margin-left: -20px;
-}
-
-.section-title {
- background: #79a;
- color: #eee;
- padding: 3px;
- margin-top: 2em;
- margin-left: -30px;
- border: 1px solid #999;
-}
-
-.top-aligned-row {
- vertical-align: top
-}
-
-.bottom-aligned-row {
- vertical-align: bottom
-}
-
-/* --- Context section classes ----------------------- */
-
-.context-row { }
-
-.context-item-name {
- font-family: monospace;
- font-weight: bold;
- color: black;
-}
-
-.context-item-value {
- font-size: small;
- color: #448;
-}
-
-.context-item-desc {
- color: #333;
- padding-left: 2em;
-}
-
-/* --- Method classes -------------------------- */
-
-.method-detail {
- background: #efefef;
- padding: 0;
- margin-top: 0.5em;
- margin-bottom: 1em;
- border: 1px dotted #ccc;
-}
-
-.method-heading {
- color: black;
- background: #ccc;
- border-bottom: 1px solid #666;
- padding: 0.2em 0.5em 0 0.5em;
-}
-
-.method-signature {
- color: black;
- background: inherit;
-}
-
-.method-name {
- font-weight: bold;
-}
-
-.method-args {
- font-style: italic;
-}
+ FONTS = RDoc::Generator::HTML::HTML::FONTS
-.method-description {
- padding: 0 0.5em 0 0.5em;
-}
+ STYLE = RDoc::Generator::HTML::HTML::STYLE
-/* --- Source code sections -------------------- */
-
-:link.source-toggle, :visited.source-toggle {
- font-size: 90%;
-}
-
-div.method-source-code {
- background: #262626;
- color: #ffdead;
- margin: 1em;
- padding: 0.5em;
- border: 1px dashed #999;
- overflow: hidden;
-}
-
-div.method-source-code pre {
- color: #ffdead;
- overflow: hidden;
-}
-
-/* --- Ruby keyword styles --------------------- */
-
-.standalone-code {
- background: #221111;
- color: #ffdead;
- overflow: hidden;
-}
-
-.ruby-constant {
- color: #7fffd4;
- background: transparent;
-}
-
-.ruby-keyword {
- color: #00ffff;
- background: transparent;
-}
-
-.ruby-ivar {
- color: #eedd82;
- background: transparent;
-}
-
-.ruby-operator {
- color: #00ffee;
- background: transparent;
-}
-
-.ruby-identifier {
- color: #ffdead;
- background: transparent;
-}
-
-.ruby-node {
- color: #ffa07a;
- background: transparent;
-}
-
-.ruby-comment {
- color: #b22222;
- font-weight: bold;
- background: transparent;
-}
-
-.ruby-regexp {
- color: #ffa07a;
- background: transparent;
-}
-
-.ruby-value {
- color: #7fffd4;
- background: transparent;
-}
-
-EOF
-
- ##
- # Header template
-
- XHTML_PREAMBLE = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- EOF
-
- HEADER = XHTML_PREAMBLE + <<-EOF
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
- <meta http-equiv="Content-Script-Type" content="text/javascript" />
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
- <script type="text/javascript">
- // <![CDATA[
-
- function popupCode( url ) {
- window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
- }
-
- function toggleCode( id ) {
- if ( document.getElementById )
- elem = document.getElementById( id );
- else if ( document.all )
- elem = eval( "document.all." + id );
- else
- return false;
-
- elemStyle = elem.style;
-
- if ( elemStyle.display != "block" ) {
- elemStyle.display = "block"
- } else {
- elemStyle.display = "none"
- }
-
- return true;
- }
-
- // Make codeblocks hidden by default
- document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }</style>" )
-
- // ]]>
- </script>
-
-</head>
-<body>
-EOF
-
- ##
- # Context content template
-
- CONTEXT_CONTENT = %{
-}
-
- ##
- # Footer template
+ HEADER = RDoc::Generator::HTML::HTML::HEADER
FOOTER = <<-EOF
<div id="popupmenu" class="index">
- <ul>
- <li class="index-entries section-bar">Classes
+ <br />
+ <h1 class="index-entries section-bar">Files</h1>
<ul>
-<% values["class_list"].each do |klass| %>
- <li><a href="<%= klass["href"] %>"><%= klass["name"] %></a>
+<% values["file_list"].each do |file| %>
+ <li><a href="<%= file["href"] %>"><%= file["name"] %></a></li>
<% end %>
</ul>
- </li>
- <li class="index-entries section-bar">Methods
+ <br />
+ <h1 class="index-entries section-bar">Classes</h1>
<ul>
-<% values["method_list"].each do |file| %>
- <li><a href="<%= file["href"] %>"><%= file["name"] %></a>
+<% values["class_list"].each do |klass| %>
+ <li><a href="<%= klass["href"] %>"><%= klass["name"] %></a></li>
<% end %>
</ul>
- </li>
- <li class="index-entries section-bar">Files
+ <br />
+ <h1 class="index-entries section-bar">Methods</h1>
<ul>
-<% values["file_list"].each do |file| %>
- <li><a href="<%= file["href"] %>"><%= file["name"] %></a>
+<% values["method_list"].each do |method| %>
+ <li><a href="<%= method["href"] %>"><%= method["name"] %></a></li>
<% end %>
</ul>
- </li>
- </ul>
- </li>
-
+ </div>
</body>
</html>
EOF
- ##
- # File page header template
-
- FILE_PAGE = <<-EOF
- <div id="fileHeader">
- <h1><%= values["short_name"] %></h1>
-
- <table class="header-table">
- <tr class="top-aligned-row">
- <td><strong>Path:</strong></td>
- <td><%= values["full_path"] %>
-<% if values["cvsurl"] then %>
- &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- </td>
- </tr>
-
- <tr class="top-aligned-row">
- <td><strong>Last Update:</strong></td>
- <td><%= values["dtm_modified"] %></td>
- </tr>
- </table>
- </div>
- EOF
-
- ##
- # Class page header template
-
- CLASS_PAGE = <<-EOF
- <div id="classHeader">
- <table class="header-table">
- <tr class="top-aligned-row">
- <td><strong><%= values["classmod"] %></strong></td>
- <td class="class-name-in-header"><%= values["full_name"] %></td>
- </tr>
-
- <tr class="top-aligned-row">
- <td><strong>In:</strong></td>
- <td>
-<% values["infiles"].each do |infiles| %>
-<% if infiles["full_path_url"] then %>
- <a href="<%= infiles["full_path_url"] %>">
-<% end %>
- <%= infiles["full_path"] %>
-<% if infiles["full_path_url"] then %>
- </a>
-<% end %>
-<% if infiles["cvsurl"] then %>
- &nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- <br />
-<% end %><%# values["infiles"] %>
- </td>
- </tr>
-
-<% if values["parent"] then %>
- <tr class="top-aligned-row">
- <td><strong>Parent:</strong></td>
- <td>
-<% if values["par_url"] then %>
- <a href="<%= values["par_url"] %>">
-<% end %>
- <%= values["parent"] %>
-<% if values["par_url"] then %>
- </a>
-<% end %>
- </td>
- </tr>
-<% end %>
- </table>
- </div>
- EOF
-
- ##
- # Method list template
-
- METHOD_LIST = <<-EOF
-
- <div id="contextContent">
-<% if values["diagram"] then %>
- <div id="diagram">
- <%= values["diagram"] %>
- </div>
-<% end %>
-
-<% if values["description"] then %>
- <div id="description">
- <%= values["description"] %>
- </div>
-<% end %>
-
-<% if values["requires"] then %>
- <div id="requires-list">
- <h3 class="section-bar">Required files</h3>
-
- <div class="name-list">
-<% values["requires"].each do |requires| %>
- <%= href requires["aref"], requires["name"] %>&nbsp;&nbsp;
-<% end %><%# values["requires"] %>
- </div>
- </div>
-<% end %>
-
-<% if values["toc"] then %>
- <div id="contents-list">
- <h3 class="section-bar">Contents</h3>
- <ul>
-<% values["toc"].each do |toc| %>
- <li><a href="#<%= values["href"] %>"><%= values["secname"] %></a></li>
-<% end %><%# values["toc"] %>
- </ul>
-<% end %>
- </div>
-
-<% if values["methods"] then %>
- <div id="method-list">
- <h3 class="section-bar">Methods</h3>
+ FILE_PAGE = RDoc::Generator::HTML::HTML::FILE_PAGE
- <div class="name-list">
-<% values["methods"].each do |methods| %>
- <%= href methods["aref"], methods["name"] %>&nbsp;&nbsp;
-<% end %><%# values["methods"] %>
- </div>
- </div>
-<% end %>
+ CLASS_PAGE = RDoc::Generator::HTML::HTML::CLASS_PAGE
- </div>
-
-
- <!-- if includes -->
-<% if values["includes"] then %>
- <div id="includes">
- <h3 class="section-bar">Included Modules</h3>
-
- <div id="includes-list">
-<% values["includes"].each do |includes| %>
- <span class="include-name"><%= href includes["aref"], includes["name"] %></span>
-<% end %><%# values["includes"] %>
- </div>
- </div>
-<% end %>
-
-<% values["sections"].each do |sections| %>
- <div id="section">
-<% if sections["sectitle"] then %>
- <h2 class="section-title"><a name="<%= sections["secsequence"] %>"><%= sections["sectitle"] %></a></h2>
-<% if sections["seccomment"] then %>
- <div class="section-comment">
- <%= sections["seccomment"] %>
- </div>
-<% end %>
-<% end %>
-
-<% if values["classlist"] then %>
- <div id="class-list">
- <h3 class="section-bar">Classes and Modules</h3>
-
- <%= values["classlist"] %>
- </div>
-<% end %>
-
-<% if values["constants"] then %>
- <div id="constants-list">
- <h3 class="section-bar">Constants</h3>
-
- <div class="name-list">
- <table summary="Constants">
-<% values["constants"].each do |constants| %>
- <tr class="top-aligned-row context-row">
- <td class="context-item-name"><%= constants["name"] %></td>
- <td>=</td>
- <td class="context-item-value"><%= constants["value"] %></td>
-<% if values["desc"] then %>
- <td width="3em">&nbsp;</td>
- <td class="context-item-desc"><%= constants["desc"] %></td>
-<% end %>
- </tr>
-<% end %><%# values["constants"] %>
- </table>
- </div>
- </div>
-<% end %>
-
-<% if values["aliases"] then %>
- <div id="aliases-list">
- <h3 class="section-bar">External Aliases</h3>
-
- <div class="name-list">
- <table summary="aliases">
-<% values["aliases"].each do |aliases| $stderr.puts({ :aliases => aliases }.inspect) %>
- <tr class="top-aligned-row context-row">
- <td class="context-item-name"><%= values["old_name"] %></td>
- <td>-&gt;</td>
- <td class="context-item-value"><%= values["new_name"] %></td>
- </tr>
-<% if values["desc"] then %>
- <tr class="top-aligned-row context-row">
- <td>&nbsp;</td>
- <td colspan="2" class="context-item-desc"><%= values["desc"] %></td>
- </tr>
-<% end %>
-<% end %><%# values["aliases"] %>
- </table>
- </div>
- </div>
-<% end %>
-
-
-<% if values["attributes"] then %>
- <div id="attribute-list">
- <h3 class="section-bar">Attributes</h3>
-
- <div class="name-list">
- <table>
-<% values["attributes"].each do |attributes| $stderr.puts({ :attributes => attributes }.inspect) %>
- <tr class="top-aligned-row context-row">
- <td class="context-item-name"><%= values["name"] %></td>
-<% if values["rw"] then %>
- <td class="context-item-value">&nbsp;[<%= values["rw"] %>]&nbsp;</td>
-<% end %>
-<% unless values["rw"] then %>
- <td class="context-item-value">&nbsp;&nbsp;</td>
-<% end %>
- <td class="context-item-desc"><%= values["a_desc"] %></td>
- </tr>
-<% end %><%# values["attributes"] %>
- </table>
- </div>
- </div>
-<% end %>
-
- <!-- if method_list -->
-<% if sections["method_list"] then %>
- <div id="methods">
-<% sections["method_list"].each do |method_list| %>
-<% if method_list["methods"] then %>
- <h3 class="section-bar"><%= method_list["type"] %> <%= method_list["category"] %> methods</h3>
-
-<% method_list["methods"].each do |methods| %>
- <div id="method-<%= methods["aref"] %>" class="method-detail">
- <a name="<%= methods["aref"] %>"></a>
-
- <div class="method-heading">
-<% if methods["codeurl"] then %>
- <a href="<%= methods["codeurl"] %>" target="Code" class="method-signature"
- onclick="popupCode('<%= methods["codeurl"] %>');return false;">
-<% end %>
-<% if methods["sourcecode"] then %>
- <a href="#<%= methods["aref"] %>" class="method-signature">
-<% end %>
-<% if methods["callseq"] then %>
- <span class="method-name"><%= methods["callseq"] %></span>
-<% end %>
-<% unless methods["callseq"] then %>
- <span class="method-name"><%= methods["name"] %></span><span class="method-args"><%= methods["params"] %></span>
-<% end %>
-<% if methods["codeurl"] then %>
- </a>
-<% end %>
-<% if methods["sourcecode"] then %>
- </a>
-<% end %>
- </div>
-
- <div class="method-description">
-<% if methods["m_desc"] then %>
- <%= methods["m_desc"] %>
-<% end %>
-<% if methods["sourcecode"] then %>
- <p><a class="source-toggle" href="#"
- onclick="toggleCode('<%= methods["aref"] %>-source');return false;">[Source]</a></p>
- <div class="method-source-code" id="<%= methods["aref"] %>-source">
-<pre>
-<%= methods["sourcecode"] %>
-</pre>
- </div>
-<% end %>
- </div>
- </div>
-
-<% end %><%# method_list["methods"] %>
-<% end %>
-<% end %><%# sections["method_list"] %>
-
- </div>
-<% end %>
-<% end %><%# values["sections"] %>
- EOF
-
- ##
- # Body template
+ METHOD_LIST = RDoc::Generator::HTML::HTML::METHOD_LIST
BODY = HEADER + %{
@@ -724,72 +80,13 @@ EOF
} + FOOTER
- ##
- # Source code template
-
- SRC_PAGE = XHTML_PREAMBLE + <<-EOF
-<html>
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
-</head>
-<body class="standalone-code">
- <pre><%= values["code"] %></pre>
-</body>
-</html>
- EOF
-
- ##
- # Index file templates
-
- FR_INDEX_BODY = %{
-<%= template_include %>
-}
+ SRC_PAGE = RDoc::Generator::HTML::HTML::SRC_PAGE
- FILE_INDEX = XHTML_PREAMBLE + <<-EOF
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <title><%= values["list_title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" />
- <base target="docwin" />
-</head>
-<body>
-<div class="index">
- <h1 class="section-bar"><%= values["list_title"] %></h1>
- <div class="index-entries">
-<% values["entries"].each do |entries| %>
- <a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
-<% end %><%# values["entries"] %>
- </div>
-</div>
-</body>
-</html>
- EOF
+ FR_INDEX_BODY = RDoc::Generator::HTML::HTML::FR_INDEX_BODY
- CLASS_INDEX = FILE_INDEX
- METHOD_INDEX = FILE_INDEX
+ FILE_INDEX = RDoc::Generator::HTML::HTML::FILE_INDEX
- INDEX = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
-</head>
-<frameset rows="20%, 80%">
- <frameset cols="45%,55%">
- <frame src="fr_class_index.html" name="Classes" />
- <frame src="fr_method_index.html" name="Methods" />
- </frameset>
- <frame src="<%= values["initial_page"] %>" name="docwin" />
-</frameset>
-</html>
- EOF
+ CLASS_INDEX = RDoc::Generator::HTML::HTML::CLASS_INDEX
+ METHOD_INDEX = RDoc::Generator::HTML::HTML::METHOD_INDEX
end
-
diff --git a/lib/rdoc/generator/html/hefss.rb b/lib/rdoc/generator/html/hefss.rb
index e186a403843..540c23d869a 100644
--- a/lib/rdoc/generator/html/hefss.rb
+++ b/lib/rdoc/generator/html/hefss.rb
@@ -1,16 +1,16 @@
require 'rdoc/generator/html'
-require 'rdoc/generator/html/html'
+require 'rdoc/generator/html/kilmerfactory'
module RDoc::Generator::HTML::HEFSS
FONTS = "Verdana, Arial, Helvetica, sans-serif"
-STYLE = <<-EOF
-body,p { font-family: Verdana, Arial, Helvetica, sans-serif;
+ CENTRAL_STYLE = <<-EOF
+body,p { font-family: <%= values["fonts"] %>;
color: #000040; background: #BBBBBB;
}
-td { font-family: Verdana, Arial, Helvetica, sans-serif;
+td { font-family: <%= values["fonts"] %>;
color: #000040;
}
@@ -21,16 +21,20 @@ td { font-family: Verdana, Arial, Helvetica, sans-serif;
}
.big-title-font { color: white;
- font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-family: <%= values["fonts"] %>;
font-size: large;
height: 50px}
.small-title-font { color: purple;
- font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-family: <%= values["fonts"] %>;
font-size: small; }
.aqua { color: purple }
+#diagram img {
+ border: 0;
+}
+
.method-name, attr-name {
font-family: monospace; font-weight: bold;
}
@@ -75,241 +79,6 @@ td { font-family: Verdana, Arial, Helvetica, sans-serif;
color: #0000AA;
}
-.column-title {
- font-size: medium;
- font-weight: bold;
- text_decoration: none;
- padding: 3px 3px 3px 20px;
- color: #3333CC;
- }
-
-.variable-name {
- font-family: monospace;
- font-size: medium;
- text_decoration: none;
- padding: 3px 3px 3px 20px;
- color: #0000AA;
-}
-
-.row-name {
- font-size: medium;
- font-weight: medium;
- font-family: monospace;
- text_decoration: none;
- padding: 3px 3px 3px 20px;
-}
-
-.paramsig {
- font-size: small;
-}
-
-.srcbut { float: right }
-
- EOF
-
- BODY = <<-EOF
-<html><head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
- <script type="text/javascript" language="JavaScript">
- <!--
- function popCode(url) {
- parent.frames.source.location = url
- }
- //-->
- </script>
-</head>
-<body bgcolor="#BBBBBB">
-
-<%= template_include %> <!-- banner header -->
-
-<% if values["diagram"] then %>
-<table width="100%"><tr><td align="center">
-<%= values["diagram"] %>
-</td></tr></table>
-<% end %>
-
-<% if values["description"] then %>
-<div class="description"><%= values["description"] %></div>
-<% end %>
-
-<% if values["requires"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Required files</td></tr>
-</table><br />
-<div class="name-list">
-<% values["requires"].each do |requires| %>
-<%= href requires["aref"], requires["name"] %>
-<% end %><%# values["requires"] %>
-<% end %>
-</div>
-
-<% if values["sections"] then %>
-<% values["sections"].each do |sections| %>
-<% if sections["method_list"] then %>
-<% sections["method_list"].each do |method_list| %>
-<% if method_list["methods"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Subroutines and Functions</td></tr>
-</table><br />
-<div class="name-list">
-<% method_list["methods"].each do |methods| %>
-<a href="<%= methods["codeurl"] %>" target="source"><%= methods["name"] %></a>
-<% end %><%# values["methods"] %>
-</div>
-<% end %>
-<% end %><%# values["method_list"] %>
-<% end %>
-
-<% if sections["attributes"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Arguments</td></tr>
-</table><br />
-<table cellspacing="5">
-<% sections["attributes"].each do |attributes| %>
- <tr valign="top">
-<% if attributes["rw"] then %>
- <td align="center" class="attr-rw">&nbsp;[<%= attributes["rw"] %>]&nbsp;</td>
-<% end %>
-<% unless attributes["rw"] then %>
- <td></td>
-<% end %>
- <td class="attr-name"><%= attributes["name"] %></td>
- <td><%= attributes["a_desc"] %></td>
- </tr>
-<% end %><%# values["attributes"] %>
-</table>
-<% end %>
-<% end %><%# values["sections"] %>
-<% end %>
-
-<% if values["classlist"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Modules</td></tr>
-</table><br />
-<%= values["classlist"] %><br />
-<% end %>
-
- <%= template_include %> <!-- method descriptions -->
-
-</body>
-</html>
- EOF
-
- FILE_PAGE = <<-EOF
-<table width="100%">
- <tr class="title-row">
- <td><table width="100%"><tr>
- <td class="big-title-font" colspan="2"><font size="-3"><b>File</b><br /></font><%= values["short_name"] %></td>
- <td align="right"><table cellspacing="0" cellpadding="2">
- <tr>
- <td class="small-title-font">Path:</td>
- <td class="small-title-font"><%= values["full_path"] %>
-<% if values["cvsurl"] then %>
- &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- </td>
- </tr>
- <tr>
- <td class="small-title-font">Modified:</td>
- <td class="small-title-font"><%= values["dtm_modified"] %></td>
- </tr>
- </table>
- </td></tr></table></td>
- </tr>
-</table><br />
- EOF
-
- CLASS_PAGE = <<-EOF
-<table width="100%" border="0" cellspacing="0">
- <tr class="title-row">
- <td class="big-title-font">
- <font size="-3"><b><%= values["classmod"] %></b><br /></font><%= values["full_name"] %>
- </td>
- <td align="right">
- <table cellspacing="0" cellpadding="2">
- <tr valign="top">
- <td class="small-title-font">In:</td>
- <td class="small-title-font">
-<% values["infiles"].each do |infiles| %>
-<%= href infiles["full_path_url"], infiles["full_path"] %>
-<% if infiles["cvsurl"] then %>
-&nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
-<% end %><%# values["infiles"] %>
- </td>
- </tr>
-<% if values["parent"] then %>
- <tr>
- <td class="small-title-font">Parent:</td>
- <td class="small-title-font">
-<% if values["par_url"] then %>
- <a href="<%= values["par_url"] %>" class="cyan">
-<% end %>
-<%= values["parent"] %>
-<% if values["par_url"] then %>
- </a>
-<% end %>
- </td>
- </tr>
-<% end %>
- </table>
- </td>
- </tr>
-</table><br />
- EOF
-
- METHOD_LIST = <<-EOF
-<% if values["includes"] then %>
-<div class="tablesubsubtitle">Uses</div><br />
-<div class="name-list">
-<% values["includes"].each do |includes| %>
- <span class="method-name"><%= href includes["aref"], includes["name"] %></span>
-<% end %><%# values["includes"] %>
-</div>
-<% end %>
-
-<% if values["sections"] then %>
-<% values["sections"].each do |sections| %>
-<% if sections["method_list"] then %>
-<% sections["method_list"].each do |method_list| %>
-<% if method_list["methods"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle"><%= method_list["type"] %> <%= method_list["category"] %> methods</td></tr>
-</table>
-<% method_list["methods"].each do |methods| %>
-<table width="100%" cellspacing="0" cellpadding="5" border="0">
-<tr><td class="methodtitle">
-<a name="<%= methods["aref"] %>">
-<b><%= methods["name"] %></b><%= methods["params"] %>
-<% if methods["codeurl"] then %>
-<a href="<%= methods["codeurl"] %>" target="source" class="srclink">src</a>
-<% end %>
-</a></td></tr>
-</table>
-<% if method_list["m_desc"] then %>
-<div class="description">
-<%= method_list["m_desc"] %>
-</div>
-<% end %>
-<% end %><%# method_list["methods"] %>
-<% end %>
-<% end %><%# sections["method_list"] %>
-<% end %>
-<% end %><%# values["sections"] %>
-<% end %>
- EOF
-
- SRC_PAGE = <<-EOF
-<html>
-<head><title><%= values["title"] %></title>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style type="text/css">
- .kw { color: #3333FF; font-weight: bold }
- .cmt { color: green; font-style: italic }
- .str { color: #662222; font-style: italic }
- .re { color: #662222; }
.ruby-comment { color: green; font-style: italic }
.ruby-constant { color: #4433aa; font-weight: bold; }
.ruby-identifier { color: #222222; }
@@ -319,35 +88,23 @@ td { font-family: Verdana, Arial, Helvetica, sans-serif;
.ruby-operator { color: #111111; }
.ruby-regexp { color: #662222; }
.ruby-value { color: #662222; font-style: italic }
-</style>
-</head>
-<body bgcolor="#BBBBBB">
-<pre><%= values["code"] %></pre>
-</body>
-</html>
+
+.srcbut { float: right }
EOF
- FR_INDEX_BODY = %{
-<%= template_include %>
+ INDEX_STYLE = <<-EOF
+body {
+ background-color: #bbbbbb;
+ font-family: #{FONTS};
+ font-size: 11px;
+ font-style: normal;
+ line-height: 14px;
+ color: #000040;
}
- FILE_INDEX = <<-EOF
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style type="text/css">
-<!--
- body {
-background-color: #bbbbbb;
- font-family: #{FONTS};
- font-size: 11px;
- font-style: normal;
- line-height: 14px;
- color: #000040;
- }
div.banner {
background: #bbbbcc;
- color: white;
+ color: white;
padding: 1;
margin: 0;
font-size: 90%;
@@ -356,59 +113,38 @@ div.banner {
text-align: center;
width: 100%;
}
+EOF
--->
-</style>
-<base target="docwin">
-</head>
-<body>
-<div class="banner"><%= values["list_title"] %></div>
-<% values["entries"].each do |entries| %>
-<a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
-<% end %><%# values["entries"] %>
-</body></html>
- EOF
+ FACTORY = RDoc::Generator::HTML::
+ KilmerFactory.new(:central_css => CENTRAL_STYLE,
+ :index_css => INDEX_STYLE,
+ :method_list_heading => "Subroutines and Functions",
+ :class_and_module_list_heading => "Classes and Modules",
+ :attribute_list_heading => "Arguments")
- CLASS_INDEX = FILE_INDEX
- METHOD_INDEX = FILE_INDEX
+ STYLE = FACTORY.get_STYLE()
- INDEX = <<-EOF
-<html>
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-</head>
+ METHOD_LIST = FACTORY.get_METHOD_LIST()
+
+ BODY = FACTORY.get_BODY()
+
+ FILE_PAGE = FACTORY.get_FILE_PAGE()
-<frameset cols="20%,*">
- <frameset rows="15%,35%,50%">
- <frame src="fr_file_index.html" title="Files" name="Files">
- <frame src="fr_class_index.html" name="Modules">
- <frame src="fr_method_index.html" name="Subroutines and Functions">
- </frameset>
- <frameset rows="80%,20%">
- <frame src="<%= values["initial_page"] %>" name="docwin">
- <frame src="blank.html" name="source">
- </frameset>
- <noframes>
- <body bgcolor="#BBBBBB">
- Click <a href="html/index.html">here</a> for a non-frames
- version of this page.
- </body>
- </noframes>
-</frameset>
+ CLASS_PAGE = FACTORY.get_CLASS_PAGE()
-</html>
- EOF
+ SRC_PAGE = FACTORY.get_SRC_PAGE()
- # Blank page to use as a target
- BLANK = %{
-<html><body bgcolor="#BBBBBB"></body></html>
-}
+ FR_INDEX_BODY = FACTORY.get_FR_INDEX_BODY()
- def write_extra_pages
- template = TemplatePage.new(BLANK)
- File.open("blank.html", "w") { |f| template.write_html_on(f, {}) }
- end
+ FILE_INDEX = FACTORY.get_FILE_INDEX()
-end
+ CLASS_INDEX = FACTORY.get_CLASS_INDEX()
+
+ METHOD_INDEX = FACTORY.get_METHOD_INDEX()
+ INDEX = FACTORY.get_INDEX()
+
+ def self.write_extra_pages(values)
+ FACTORY.write_extra_pages(values)
+ end
+end
diff --git a/lib/rdoc/generator/html/html.rb b/lib/rdoc/generator/html/html.rb
index 1ab90c62641..823d8056e7a 100644
--- a/lib/rdoc/generator/html/html.rb
+++ b/lib/rdoc/generator/html/html.rb
@@ -1,15 +1,17 @@
require 'rdoc/generator/html'
-require 'rdoc/generator/html/one_page_html'
+require 'rdoc/generator/html/common'
##
# = CSS2 RDoc HTML template
#
-# This is a template for RDoc that uses XHTML 1.0 Transitional and dictates a
+# This is a template for RDoc that uses XHTML 1.0 Strict and dictates a
# bit more of the appearance of the output to cascading stylesheets than the
# default. It was designed for clean inline code display, and uses DHTMl to
# toggle the visibility of each method's source with each click on the
# '[source]' link.
#
+# This template *also* forms the basis of the frameless template.
+#
# == Authors
#
# * Michael Granger <ged@FaerieMUD.org>
@@ -23,34 +25,54 @@ require 'rdoc/generator/html/one_page_html'
module RDoc::Generator::HTML::HTML
+ include RDoc::Generator::HTML::Common
+
FONTS = "Verdana,Arial,Helvetica,sans-serif"
STYLE = <<-EOF
body {
- font-family: Verdana,Arial,Helvetica,sans-serif;
- font-size: 90%;
- margin: 0;
- margin-left: 40px;
- padding: 0;
- background: white;
+ font-family: #{FONTS};
+ font-size: 90%;
+ margin: 0;
+ margin-left: 40px;
+ padding: 0;
+ background: white;
+ color: black;
+}
+
+h1, h2, h3, h4 {
+ margin: 0;
+ background: transparent;
+}
+
+h1 {
+ font-size: 150%;
}
-h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
-h1 { font-size: 150%; }
-h2,h3,h4 { margin-top: 1em; }
+h2,h3,h4 {
+ margin-top: 1em;
+}
-a { background: #eef; color: #039; text-decoration: none; }
-a:hover { background: #039; color: #eef; }
+:link, :visited {
+ background: #eef;
+ color: #039;
+ text-decoration: none;
+}
+
+:link:hover, :visited:hover {
+ background: #039;
+ color: #eef;
+}
/* Override the base stylesheet's Anchor inside a table cell */
-td > a {
+td > :link, td > :visited {
background: transparent;
color: #039;
text-decoration: none;
}
/* and inside a section title */
-.section-title > a {
+.section-title > :link, .section-title > :visited {
background: transparent;
color: #eee;
text-decoration: none;
@@ -58,181 +80,255 @@ td > a {
/* === Structural elements =================================== */
-div#index {
- margin: 0;
- margin-left: -40px;
- padding: 0;
- font-size: 90%;
+.index {
+ margin: 0;
+ margin-left: -40px;
+ padding: 0;
+ font-size: 90%;
}
-
-div#index a {
- margin-left: 0.7em;
+.index :link, .index :visited {
+ margin-left: 0.7em;
}
-div#index .section-bar {
- margin-left: 0px;
- padding-left: 0.7em;
- background: #ccc;
- font-size: small;
+.index .section-bar {
+ margin-left: 0px;
+ padding-left: 0.7em;
+ background: #ccc;
+ font-size: small;
}
-
-div#classHeader, div#fileHeader {
- width: auto;
- color: white;
- padding: 0.5em 1.5em 0.5em 1.5em;
- margin: 0;
- margin-left: -40px;
- border-bottom: 3px solid #006;
+#classHeader, #fileHeader {
+ width: auto;
+ color: white;
+ padding: 0.5em 1.5em 0.5em 1.5em;
+ margin: 0;
+ margin-left: -40px;
+ border-bottom: 3px solid #006;
}
-div#classHeader a, div#fileHeader a {
- background: inherit;
- color: white;
+#classHeader :link, #fileHeader :link,
+#classHeader :visited, #fileHeader :visited {
+ background: inherit;
+ color: white;
}
-div#classHeader td, div#fileHeader td {
- background: inherit;
- color: white;
+#classHeader td, #fileHeader td {
+ background: inherit;
+ color: white;
}
-
-div#fileHeader {
- background: #057;
+#fileHeader {
+ background: #057;
}
-div#classHeader {
- background: #048;
+#classHeader {
+ background: #048;
}
-
.class-name-in-header {
font-size: 180%;
font-weight: bold;
}
-
-div#bodyContent {
- padding: 0 1.5em 0 1.5em;
+#bodyContent {
+ padding: 0 1.5em 0 1.5em;
}
-div#description {
- padding: 0.5em 1.5em;
- background: #efefef;
- border: 1px dotted #999;
+#description {
+ padding: 0.5em 1.5em;
+ background: #efefef;
+ border: 1px dotted #999;
}
-div#description h1,h2,h3,h4,h5,h6 {
- color: #125;;
- background: transparent;
+#description h1, #description h2, #description h3,
+#description h4, #description h5, #description h6 {
+ color: #125;
+ background: transparent;
}
-div#validator-badges {
- text-align: center;
+#validator-badges {
+ text-align: center;
}
-div#validator-badges img { border: 0; }
-div#copyright {
- color: #333;
- background: #efefef;
- font: 0.75em sans-serif;
- margin-top: 5em;
- margin-bottom: 0;
- padding: 0.5em 2em;
+#validator-badges img {
+ border: 0;
}
+#copyright {
+ color: #333;
+ background: #efefef;
+ font: 0.75em sans-serif;
+ margin-top: 5em;
+ margin-bottom: 0;
+ padding: 0.5em 2em;
+}
/* === Classes =================================== */
table.header-table {
- color: white;
- font-size: small;
+ color: white;
+ font-size: small;
}
.type-note {
- font-size: small;
- color: #DEDEDE;
+ font-size: small;
+ color: #dedede;
}
-.xxsection-bar {
- background: #eee;
- color: #333;
- padding: 3px;
+.section-bar {
+ color: #333;
+ border-bottom: 1px solid #999;
+ margin-left: -20px;
}
-.section-bar {
- color: #333;
- border-bottom: 1px solid #999;
- margin-left: -20px;
+.section-title {
+ background: #79a;
+ color: #eee;
+ padding: 3px;
+ margin-top: 2em;
+ margin-left: -30px;
+ border: 1px solid #999;
}
+.top-aligned-row {
+ vertical-align: top
+}
-.section-title {
- background: #79a;
- color: #eee;
- padding: 3px;
- margin-top: 2em;
- margin-left: -30px;
- border: 1px solid #999;
+.bottom-aligned-row {
+ vertical-align: bottom
}
-.top-aligned-row { vertical-align: top }
-.bottom-aligned-row { vertical-align: bottom }
+#diagram img {
+ border: 0;
+}
/* --- Context section classes ----------------------- */
.context-row { }
-.context-item-name { font-family: monospace; font-weight: bold; color: black; }
-.context-item-value { font-size: small; color: #448; }
-.context-item-desc { color: #333; padding-left: 2em; }
+
+.context-item-name {
+ font-family: monospace;
+ font-weight: bold;
+ color: black;
+}
+
+.context-item-value {
+ font-size: small;
+ color: #448;
+}
+
+.context-item-desc {
+ color: #333;
+ padding-left: 2em;
+}
/* --- Method classes -------------------------- */
+
.method-detail {
- background: #efefef;
- padding: 0;
- margin-top: 0.5em;
- margin-bottom: 1em;
- border: 1px dotted #ccc;
+ background: #efefef;
+ padding: 0;
+ margin-top: 0.5em;
+ margin-bottom: 1em;
+ border: 1px dotted #ccc;
}
+
.method-heading {
color: black;
background: #ccc;
border-bottom: 1px solid #666;
padding: 0.2em 0.5em 0 0.5em;
}
-.method-signature { color: black; background: inherit; }
-.method-name { font-weight: bold; }
-.method-args { font-style: italic; }
-.method-description { padding: 0 0.5em 0 0.5em; }
+
+.method-signature {
+ color: black;
+ background: inherit;
+}
+
+.method-name {
+ font-weight: bold;
+}
+
+.method-args {
+ font-style: italic;
+}
+
+.method-description {
+ padding: 0 0.5em 0 0.5em;
+}
/* --- Source code sections -------------------- */
-a.source-toggle { font-size: 90%; }
+:link.source-toggle, :visited.source-toggle {
+ font-size: 90%;
+}
+
div.method-source-code {
- background: #262626;
- color: #ffdead;
- margin: 1em;
- padding: 0.5em;
- border: 1px dashed #999;
- overflow: hidden;
+ background: #262626;
+ color: #ffdead;
+ margin: 1em;
+ padding: 0.5em;
+ border: 1px dashed #999;
+ overflow: auto;
}
-div.method-source-code pre { color: #ffdead; overflow: hidden; }
+div.method-source-code pre {
+ color: #ffdead;
+}
/* --- Ruby keyword styles --------------------- */
-.standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
-
-.ruby-constant { color: #7fffd4; background: transparent; }
-.ruby-keyword { color: #00ffff; background: transparent; }
-.ruby-ivar { color: #eedd82; background: transparent; }
-.ruby-operator { color: #00ffee; background: transparent; }
-.ruby-identifier { color: #ffdead; background: transparent; }
-.ruby-node { color: #ffa07a; background: transparent; }
-.ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
-.ruby-regexp { color: #ffa07a; background: transparent; }
-.ruby-value { color: #7fffd4; background: transparent; }
+.standalone-code {
+ background: #221111;
+ color: #ffdead;
+ overflow: auto;
+}
+
+.ruby-constant {
+ color: #7fffd4;
+ background: transparent;
+}
+
+.ruby-keyword {
+ color: #00ffff;
+ background: transparent;
+}
+
+.ruby-ivar {
+ color: #eedd82;
+ background: transparent;
+}
+
+.ruby-operator {
+ color: #00ffee;
+ background: transparent;
+}
+
+.ruby-identifier {
+ color: #ffdead;
+ background: transparent;
+}
+
+.ruby-node {
+ color: #ffa07a;
+ background: transparent;
+}
+
+.ruby-comment {
+ color: #b22222;
+ font-weight: bold;
+ background: transparent;
+}
+
+.ruby-regexp {
+ color: #ffa07a;
+ background: transparent;
+}
+
+.ruby-value {
+ color: #7fffd4;
+ background: transparent;
+}
EOF
@@ -240,15 +336,7 @@ EOF
### H E A D E R T E M P L A T E
#####################################################################
- XHTML_PREAMBLE = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- EOF
-
- HEADER = XHTML_PREAMBLE + <<-EOF
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ HEADER = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + <<-EOF
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
@@ -281,7 +369,7 @@ EOF
}
// Make codeblocks hidden by default
- document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }</style>" )
+ document.writeln( "<style type=\\"text/css\\">div.method-source-code { display: none }<\\/style>" )
// ]]>
</script>
@@ -291,13 +379,6 @@ EOF
EOF
#####################################################################
-### C O N T E X T C O N T E N T T E M P L A T E
-#####################################################################
-
- CONTEXT_CONTENT = %{
-}
-
-#####################################################################
### F O O T E R T E M P L A T E
#####################################################################
@@ -480,8 +561,8 @@ EOF
<td class="context-item-name"><%= constants["name"] %></td>
<td>=</td>
<td class="context-item-value"><%= constants["value"] %></td>
-<% if sections["desc"] then %>
- <td width="3em">&nbsp;</td>
+<% if constants["desc"] then %>
+ <td>&nbsp;</td>
<td class="context-item-desc"><%= constants["desc"] %></td>
<% end %>
</tr>
@@ -616,8 +697,7 @@ EOF
### S O U R C E C O D E T E M P L A T E
#####################################################################
- SRC_PAGE = XHTML_PREAMBLE + <<-EOF
-<html>
+ SRC_PAGE = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + <<-EOF
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
@@ -634,25 +714,22 @@ EOF
### I N D E X F I L E T E M P L A T E S
#####################################################################
- FR_INDEX_BODY = %{
-<%= template_include %>
-}
+ FR_INDEX_BODY = %{<%= template_include %>}
- FILE_INDEX = XHTML_PREAMBLE + <<-EOF
+ FILE_INDEX = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + <<-EOF
<!--
- <%= values["list_title"] %>
+ <%= values["title"] %>
-->
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
- <title><%= values["list_title"] %></title>
+ <title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
<link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" />
<base target="docwin" />
</head>
<body>
-<div id="index">
+<div class="index">
<h1 class="section-bar"><%= values["list_title"] %></h1>
<div id="index-entries">
<% values["entries"].each do |entries| %>
@@ -667,18 +744,12 @@ EOF
CLASS_INDEX = FILE_INDEX
METHOD_INDEX = FILE_INDEX
- INDEX = <<-EOF
-<?xml version="1.0" encoding="<%= values["charset"] %>"?>
-<!DOCTYPE html
- PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
-
+ INDEX = XHTML_FRAME_PREAMBLE + HTML_ELEMENT + <<-EOF
<!--
<%= values["title"] %>
-->
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
diff --git a/lib/rdoc/generator/html/kilmer.rb b/lib/rdoc/generator/html/kilmer.rb
index 6479abaf8b9..4c5a9ee8b0d 100644
--- a/lib/rdoc/generator/html/kilmer.rb
+++ b/lib/rdoc/generator/html/kilmer.rb
@@ -1,10 +1,11 @@
require 'rdoc/generator/html'
+require 'rdoc/generator/html/kilmerfactory'
module RDoc::Generator::HTML::KILMER
FONTS = "Verdana, Arial, Helvetica, sans-serif"
- STYLE = <<-EOF
+ CENTRAL_STYLE = <<-EOF
body,td,p { font-family: <%= values["fonts"] %>;
color: #000040;
}
@@ -30,6 +31,10 @@ body,td,p { font-family: <%= values["fonts"] %>;
.aqua { color: black }
+#diagram img {
+ border: 0;
+}
+
.method-name, .attr-name {
font-family: font-family: <%= values["fonts"] %>;
font-weight: bold;
@@ -67,7 +72,7 @@ body,td,p { font-family: <%= values["fonts"] %>;
font-weight: bold;
text-decoration: none;
color: #000033;
- background-color: white;
+ background: #ccc;
}
.srclink {
@@ -78,232 +83,8 @@ body,td,p { font-family: <%= values["fonts"] %>;
background-color: white;
}
-.paramsig {
- font-size: small;
-}
-
.srcbut { float: right }
- EOF
-
- BODY = <<-EOF
-<html><head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
- <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
- <script type="text/javascript" language="JavaScript">
- <!--
- function popCode(url) {
- parent.frames.source.location = url
- }
- //-->
- </script>
-</head>
-<body bgcolor="white">
-
-<%= template_include %> <!-- banner header -->
-
-<% if values["diagram"] then %>
-<table width="100%"><tr><td align="center">
-<%= values["diagram"] %>
-</td></tr></table>
-<% end %>
-
-<% if values["description"] then %>
-<div class="description"><%= values["description"] %></div>
-<% end %>
-
-<% if values["requires"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Required files</td></tr>
-</table><br />
-<div class="name-list">
-<% values["requires"].each do |requires| %>
-<%= href requires["aref"], requires["name"] %>
-<% end %><%# values["requires"] %>
-<% end %>
-</div>
-
-<% if values["methods"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Methods</td></tr>
-</table><br />
-<div class="name-list">
-<% values["methods"].each do |methods| %>
-<%= href methods["aref"], methods["name"] %>,
-<% end %><%# values["methods"] %>
-</div>
-<% end %>
-
-
-<% values["sections"].each do |sections| %>
- <div id="section">
-<% if sections["sectitle"] then %>
- <h2 class="section-title"><a name="<%= sections["secsequence"] %>"><%= sections["sectitle"] %></a></h2>
-<% if sections["seccomment"] then %>
- <div class="section-comment">
- <%= sections["seccomment"] %>
- </div>
-<% end %>
-<% end %>
-
-<% if sections["attributes"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Attributes</td></tr>
-</table><br />
-<table cellspacing="5">
-<% sections["attributes"].each do |attributes| %>
- <tr valign="top">
-<% if attributes["rw"] then %>
- <td align="center" class="attr-rw">&nbsp;[<%= attributes["rw"] %>]&nbsp;</td>
-<% end %>
-<% unless attributes["rw"] then %>
- <td></td>
-<% end %>
- <td class="attr-name"><%= attributes["name"] %></td>
- <td><%= attributes["a_desc"] %></td>
- </tr>
-<% end %><%# sections["attributes"] %>
-</table>
-<% end %>
-
-<% if sections["classlist"] then %>
-<table cellpadding="5" width="100%">
-<tr><td class="tablesubtitle">Classes and Modules</td></tr>
-</table><br />
-<%= sections["classlist"] %><br />
-<% end %>
-
- <%= template_include %> <!-- method descriptions -->
-
-<% end %><%# values["sections"] %>
-
-</body>
-</html>
- EOF
-
- FILE_PAGE = <<-EOF
-<table width="100%">
- <tr class="title-row">
- <td><table width="100%"><tr>
- <td class="big-title-font" colspan="2"><font size="-3"><b>File</b><br /></font><%= values["short_name"] %></td>
- <td align="right"><table cellspacing="0" cellpadding="2">
- <tr>
- <td class="small-title-font">Path:</td>
- <td class="small-title-font"><%= values["full_path"] %>
-<% if values["cvsurl"] then %>
- &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
- </td>
- </tr>
- <tr>
- <td class="small-title-font">Modified:</td>
- <td class="small-title-font"><%= values["dtm_modified"] %></td>
- </tr>
- </table>
- </td></tr></table></td>
- </tr>
-</table><br />
- EOF
-
- CLASS_PAGE = <<-EOF
-<table width="100%" border="0" cellspacing="0">
- <tr class="title-row">
- <td class="big-title-font">
- <font size="-3"><b><%= values["classmod"] %></b><br /></font><%= values["full_name"] %>
- </td>
- <td align="right">
- <table cellspacing="0" cellpadding="2">
- <tr valign="top">
- <td class="small-title-font">In:</td>
- <td class="small-title-font">
-<% values["infiles"].each do |infiles| %>
-<%= href infiles["full_path_url"], infiles["full_path"] %>
-<% if infiles["cvsurl"] then %>
-&nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
-<% end %>
-<% end %><%# values["infiles"] %>
- </td>
- </tr>
-<% if values["parent"] then %>
- <tr>
- <td class="small-title-font">Parent:</td>
- <td class="small-title-font">
-<% if values["par_url"] then %>
- <a href="<%= values["par_url"] %>" class="cyan">
-<% end %>
-<%= values["parent"] %>
-<% if values["par_url"] then %>
- </a>
-<% end %>
- </td>
- </tr>
-<% end %>
- </table>
- </td>
- </tr>
-</table><br />
- EOF
- METHOD_LIST = <<-EOF
-<% if values["includes"] then %>
-<div class="tablesubsubtitle">Included modules</div><br />
-<div class="name-list">
-<% values["includes"].each do |includes| %>
- <span class="method-name"><%= href includes["aref"], includes["name"] %></span>
-<% end %><%# values["includes"] %>
-</div>
-<% end %>
-
-<% if values["method_list"] then %>
-<% values["method_list"].each do |method_list| $stderr.puts({ :method_list => method_list }.inspect) %>
-<% if values["methods"] then %>
-<table cellpadding=5 width="100%">
-<tr><td class="tablesubtitle"><%= values["type"] %> <%= values["category"] %> methods</td></tr>
-</table>
-<% values["methods"].each do |methods| $stderr.puts({ :methods => methods }.inspect) %>
-<table width="100%" cellspacing="0" cellpadding="5" border="0">
-<tr><td class="methodtitle">
-<a name="<%= values["aref"] %>">
-<% if values["callseq"] then %>
-<b><%= values["callseq"] %></b>
-<% end %>
-<% unless values["callseq"] then %>
- <b><%= values["name"] %></b><%= values["params"] %>
-<% end %>
-<% if values["codeurl"] then %>
-<a href="<%= values["codeurl"] %>" target="source" class="srclink">src</a>
-<% end %>
-</a></td></tr>
-</table>
-<% if values["m_desc"] then %>
-<div class="description">
-<%= values["m_desc"] %>
-</div>
-<% end %>
-<% if values["aka"] then %>
-<div class="aka">
-This method is also aliased as
-<% values["aka"].each do |aka| $stderr.puts({ :aka => aka }.inspect) %>
-<a href="<%= values["aref"] %>"><%= values["name"] %></a>
-<% end %><%# values["aka"] %>
-</div>
-<% end %>
-<% if values["sourcecode"] then %>
-<pre class="source">
-<%= values["sourcecode"] %>
-</pre>
-<% end %>
-<% end %><%# values["methods"] %>
-<% end %>
-<% end %><%# values["method_list"] %>
-<% end %>
- EOF
-
- SRC_PAGE = <<-EOF
-<html>
-<head><title><%= values["title"] %></title>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style type="text/css">
.ruby-comment { color: green; font-style: italic }
.ruby-constant { color: #4433aa; font-weight: bold; }
.ruby-identifier { color: #222222; }
@@ -313,28 +94,9 @@ This method is also aliased as
.ruby-operator { color: #111111; }
.ruby-regexp { color: #662222; }
.ruby-value { color: #662222; font-style: italic }
- .kw { color: #3333FF; font-weight: bold }
- .cmt { color: green; font-style: italic }
- .str { color: #662222; font-style: italic }
- .re { color: #662222; }
-</style>
-</head>
-<body bgcolor="white">
-<pre><%= values["code"] %></pre>
-</body>
-</html>
EOF
- FR_INDEX_BODY = %{
-<%= template_include %>
-}
-
- FILE_INDEX = <<-EOF
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-<style>
-<!--
+ INDEX_STYLE = <<-EOF
body {
background-color: #ddddff;
font-family: #{FONTS};
@@ -355,64 +117,35 @@ div.banner {
text-align: center;
width: 100%;
}
+EOF
--->
-</style>
-<base target="docwin">
-</head>
-<body>
-<div class="banner"><%= values["list_title"] %></div>
-<% values["entries"].each do |entries| %>
-<a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
-<% end %><%# values["entries"] %>
-</body></html>
- EOF
+ FACTORY = RDoc::Generator::HTML::
+ KilmerFactory.new(:central_css => CENTRAL_STYLE,
+ :index_css => INDEX_STYLE)
- CLASS_INDEX = FILE_INDEX
- METHOD_INDEX = FILE_INDEX
+ STYLE = FACTORY.get_STYLE()
- INDEX = <<-EOF
-<html>
-<head>
- <title><%= values["title"] %></title>
- <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>">
-</head>
+ METHOD_LIST = FACTORY.get_METHOD_LIST()
+
+ BODY = FACTORY.get_BODY()
+
+ FILE_PAGE = FACTORY.get_FILE_PAGE()
-<frameset cols="20%,*">
- <frameset rows="15%,35%,50%">
- <frame src="fr_file_index.html" title="Files" name="Files">
- <frame src="fr_class_index.html" name="Classes">
- <frame src="fr_method_index.html" name="Methods">
- </frameset>
-<% if values["inline_source"] then %>
- <frame src="<%= values["initial_page"] %>" name="docwin">
-<% end %>
-<% unless values["inline_source"] then %>
- <frameset rows="80%,20%">
- <frame src="<%= values["initial_page"] %>" name="docwin">
- <frame src="blank.html" name="source">
- </frameset>
-<% end %>
- <noframes>
- <body bgcolor="white">
- Click <a href="html/index.html">here</a> for a non-frames
- version of this page.
- </body>
- </noframes>
-</frameset>
+ CLASS_PAGE = FACTORY.get_CLASS_PAGE()
-</html>
- EOF
+ SRC_PAGE = FACTORY.get_SRC_PAGE()
- # A blank page to use as a target
- BLANK = %{
-<html><body bgcolor="white"></body></html>
-}
+ FR_INDEX_BODY = FACTORY.get_FR_INDEX_BODY()
- def write_extra_pages
- template = TemplatePage.new(BLANK)
- File.open("blank.html", "w") { |f| template.write_html_on(f, {}) }
- end
+ FILE_INDEX = FACTORY.get_FILE_INDEX()
-end
+ CLASS_INDEX = FACTORY.get_CLASS_INDEX()
+ METHOD_INDEX = FACTORY.get_METHOD_INDEX()
+
+ INDEX = FACTORY.get_INDEX()
+
+ def self.write_extra_pages(values)
+ FACTORY.write_extra_pages(values)
+ end
+end
diff --git a/lib/rdoc/generator/html/kilmerfactory.rb b/lib/rdoc/generator/html/kilmerfactory.rb
new file mode 100644
index 00000000000..ef6f3f3b4d5
--- /dev/null
+++ b/lib/rdoc/generator/html/kilmerfactory.rb
@@ -0,0 +1,427 @@
+require 'rdoc/generator/html'
+require 'rdoc/generator/html/common'
+
+#
+# This class generates Kilmer-style templates. Right now,
+# rdoc is shipped with two such templates:
+# * kilmer
+# * hefss
+#
+# Kilmer-style templates use frames. The left side of the page has
+# three frames stacked on top of each other: one lists
+# files, one lists classes, and one lists methods. If source code
+# is not inlined, an additional frame runs across the bottom of
+# the page and will be used to display method source code.
+# The central (and largest frame) display class and file
+# pages.
+#
+# The constructor of this class accepts a Hash containing stylistic
+# attributes. Then, a get_BLAH instance method of this class returns a
+# value for the template's BLAH constant. get_BODY, for instance, returns
+# the value of the template's BODY constant.
+#
+class RDoc::Generator::HTML::KilmerFactory
+
+ include RDoc::Generator::HTML::Common
+
+ #
+ # The contents of the stylesheet that should be used for the
+ # central frame (for the class and file pages).
+ #
+ # This must be specified in the Hash passed to the constructor.
+ #
+ attr_reader :central_css
+
+ #
+ # The contents of the stylesheet that should be used for the
+ # index pages.
+ #
+ # This must be specified in the Hash passed to the constructor.
+ #
+ attr_reader :index_css
+
+ #
+ # The heading that should be displayed before listing methods.
+ #
+ # If not supplied, this defaults to "Methods".
+ #
+ attr_reader :method_list_heading
+
+ #
+ # The heading that should be displayed before listing classes and
+ # modules.
+ #
+ # If not supplied, this defaults to "Classes and Modules".
+ #
+ attr_reader :class_and_module_list_heading
+
+ #
+ # The heading that should be displayed before listing attributes.
+ #
+ # If not supplied, this defaults to "Attributes".
+ #
+ attr_reader :attribute_list_heading
+
+ #
+ # ====Description:
+ # This method constructs a KilmerFactory instance, which
+ # can be used to build Kilmer-style template classes.
+ # The +style_attributes+ argument is a Hash that contains the
+ # values of the classes attributes (Symbols mapped to Strings).
+ #
+ # ====Parameters:
+ # [style_attributes]
+ # A Hash describing the appearance of the Kilmer-style.
+ #
+ def initialize(style_attributes)
+ @central_css = style_attributes[:central_css]
+ if(!@central_css)
+ raise ArgumentError, "did not specify a value for :central_css"
+ end
+
+ @index_css = style_attributes[:index_css]
+ if(!@index_css)
+ raise ArgumentError, "did not specify a value for :index_css"
+ end
+
+ @method_list_heading = style_attributes[:method_list_heading]
+ if(!@method_list_heading)
+ @method_list_heading = "Methods"
+ end
+
+ @class_and_module_list_heading = style_attributes[:class_and_module_list_heading]
+ if(!@class_and_module_list_heading)
+ @class_and_module_list_heading = "Classes and Modules"
+ end
+
+ @attribute_list_heading = style_attributes[:attribute_list_heading]
+ if(!@attribute_list_heading)
+ @attribute_list_heading = "Attributes"
+ end
+ end
+
+ def get_STYLE
+ return @central_css
+ end
+
+ def get_METHOD_LIST
+ return %{
+<% if values["diagram"] then %>
+<div id="diagram">
+<table width="100%"><tr><td align="center">
+<%= values["diagram"] %>
+</td></tr></table>
+</div>
+<% end %>
+
+<% if values["description"] then %>
+<div class="description"><%= values["description"] %></div>
+<% end %>
+
+<% if values["requires"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">Required files</td></tr>
+</table><br />
+<div class="name-list">
+<% values["requires"].each do |requires| %>
+<%= href requires["aref"], requires["name"] %>
+<% end %><%# values["requires"] %>
+</div>
+<% end %>
+
+<% if values["methods"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">#{@method_list_heading}</td></tr>
+</table><br />
+<div class="name-list">
+<% values["methods"].each do |methods| %>
+<%= href methods["aref"], methods["name"] %>,
+<% end %><%# values["methods"] %>
+</div>
+<% end %>
+
+<% if values["includes"] then %>
+<div class="tablesubsubtitle">Included modules</div><br />
+<div class="name-list">
+<% values["includes"].each do |includes| %>
+ <span class="method-name"><%= href includes["aref"], includes["name"] %></span>
+<% end %><%# values["includes"] %>
+</div>
+<% end %>
+
+<% values["sections"].each do |sections| %>
+ <div id="section">
+<% if sections["sectitle"] then %>
+ <h2 class="section-title"><a name="<%= sections["secsequence"] %>"><%= sections["sectitle"] %></a></h2>
+<% if sections["seccomment"] then %>
+ <div class="section-comment">
+ <%= sections["seccomment"] %>
+ </div>
+<% end %>
+<% end %>
+<% if sections["attributes"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">#{@attribute_list_heading}</td></tr>
+</table><br />
+<table cellspacing="5">
+<% sections["attributes"].each do |attributes| %>
+ <tr valign="top">
+<% if attributes["rw"] then %>
+ <td align="center" class="attr-rw">&nbsp;[<%= attributes["rw"] %>]&nbsp;</td>
+<% end %>
+<% unless attributes["rw"] then %>
+ <td></td>
+<% end %>
+ <td class="attr-name"><%= attributes["name"] %></td>
+ <td><%= attributes["a_desc"] %></td>
+ </tr>
+<% end %><%# sections["attributes"] %>
+</table>
+<% end %>
+
+<% if sections["classlist"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle">#{@class_and_module_list_heading}</td></tr>
+</table><br />
+<%= sections["classlist"] %><br />
+<% end %>
+
+<% if sections["method_list"] then %>
+<% sections["method_list"].each do |method_list| %>
+<% if method_list["methods"] then %>
+<table cellpadding="5" width="100%">
+<tr><td class="tablesubtitle"><%= method_list["type"] %> <%= method_list["category"] %> methods</td></tr>
+</table>
+<% method_list["methods"].each do |methods| %>
+<table width="100%" cellspacing="0" cellpadding="5" border="0">
+<tr><td class="methodtitle">
+<a name="<%= methods["aref"] %>">
+<% if methods["callseq"] then %>
+<b><%= methods["callseq"] %></b>
+<% end %>
+<% unless methods["callseq"] then %>
+ <b><%= methods["name"] %></b><%= methods["params"] %>
+<% end %>
+</a>
+<% if methods["codeurl"] then %>
+<a href="<%= methods["codeurl"] %>" target="source" class="srclink">src</a>
+<% end %>
+</td></tr>
+</table>
+<% if methods["m_desc"] then %>
+<div class="description">
+<%= methods["m_desc"] %>
+</div>
+<% end %>
+<% if methods["aka"] then %>
+<div class="aka">
+This method is also aliased as
+<% methods["aka"].each do |aka| %>
+<a href="<%= methods["aref"] %>"><%= methods["name"] %></a>
+<% end %><%# methods["aka"] %>
+</div>
+<% end %>
+<% if methods["sourcecode"] then %>
+<pre class="source">
+<%= methods["sourcecode"] %>
+</pre>
+<% end %>
+<% end %><%# method_list["methods"] %>
+<% end %>
+<% end %><%# sections["method_list"] %>
+<% end %>
+
+<% end %><%# values["sections"] %>
+</div>
+}
+ end
+
+ def get_BODY
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head>
+ <title><%= values["title"] %></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+ <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
+ <script type="text/javascript">
+ <!--
+ function popCode(url) {
+ parent.frames.source.location = url
+ }
+ //-->
+ </script>
+</head>
+<body>
+<div class="bodyContent">
+<%= template_include %> <!-- banner header -->
+
+#{get_METHOD_LIST()}
+</div>
+</body>
+</html>
+}
+ end
+
+def get_FILE_PAGE
+ return %{
+<table width="100%">
+ <tr class="title-row">
+ <td><table width="100%"><tr>
+ <td class="big-title-font" colspan="2">File<br /><%= values["short_name"] %></td>
+ <td align="right"><table cellspacing="0" cellpadding="2">
+ <tr>
+ <td class="small-title-font">Path:</td>
+ <td class="small-title-font"><%= values["full_path"] %>
+<% if values["cvsurl"] then %>
+ &nbsp;(<a href="<%= values["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+<% end %>
+ </td>
+ </tr>
+ <tr>
+ <td class="small-title-font">Modified:</td>
+ <td class="small-title-font"><%= values["dtm_modified"] %></td>
+ </tr>
+ </table>
+ </td></tr></table></td>
+ </tr>
+</table><br />
+}
+end
+
+def get_CLASS_PAGE
+ return %{
+<table width="100%" border="0" cellspacing="0">
+ <tr class="title-row">
+ <td class="big-title-font">
+ <%= values["classmod"] %><br /><%= values["full_name"] %>
+ </td>
+ <td align="right">
+ <table cellspacing="0" cellpadding="2">
+ <tr valign="top">
+ <td class="small-title-font">In:</td>
+ <td class="small-title-font">
+<% values["infiles"].each do |infiles| %>
+<%= href infiles["full_path_url"], infiles["full_path"] %>
+<% if infiles["cvsurl"] then %>
+&nbsp;(<a href="<%= infiles["cvsurl"] %>"><acronym title="Concurrent Versioning System">CVS</acronym></a>)
+<% end %>
+<% end %><%# values["infiles"] %>
+ </td>
+ </tr>
+<% if values["parent"] then %>
+ <tr>
+ <td class="small-title-font">Parent:</td>
+ <td class="small-title-font">
+<% if values["par_url"] then %>
+ <a href="<%= values["par_url"] %>" class="cyan">
+<% end %>
+<%= values["parent"] %>
+<% if values["par_url"] then %>
+ </a>
+<% end %>
+ </td>
+ </tr>
+<% end %>
+ </table>
+ </td>
+ </tr>
+</table><br />
+}
+end
+
+def get_SRC_PAGE
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head><title><%= values["title"] %></title>
+<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+<link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
+</head>
+<body>
+<pre><%= values["code"] %></pre>
+</body>
+</html>
+}
+end
+
+def get_FR_INDEX_BODY
+ return %{<%= template_include %>}
+end
+
+def get_FILE_INDEX
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head>
+<title><%= values["title"] %></title>
+<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+<style type="text/css">
+<!--
+#{@index_css}
+-->
+</style>
+<base target="docwin" />
+</head>
+<body>
+<div class="index">
+<div class="banner"><%= values["list_title"] %></div>
+<% values["entries"].each do |entries| %>
+<a href="<%= entries["href"] %>"><%= entries["name"] %></a><br />
+<% end %><%# values["entries"] %>
+</div>
+</body></html>
+}
+end
+
+def get_CLASS_INDEX
+ return get_FILE_INDEX
+end
+
+def get_METHOD_INDEX
+ return get_FILE_INDEX
+end
+
+def get_INDEX
+ return XHTML_FRAME_PREAMBLE + HTML_ELEMENT + %{
+<head>
+ <title><%= values["title"] %></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+</head>
+
+<frameset cols="20%,*">
+ <frameset rows="15%,35%,50%">
+ <frame src="fr_file_index.html" title="Files" name="Files" />
+ <frame src="fr_class_index.html" name="Classes" />
+ <frame src="fr_method_index.html" name="Methods" />
+ </frameset>
+<% if values["inline_source"] then %>
+ <frame src="<%= values["initial_page"] %>" name="docwin" />
+<% end %>
+<% unless values["inline_source"] then %>
+ <frameset rows="80%,20%">
+ <frame src="<%= values["initial_page"] %>" name="docwin" />
+ <frame src="blank.html" name="source" />
+ </frameset>
+<% end %>
+</frameset>
+
+</html>
+}
+end
+
+def get_BLANK
+ # This will be displayed in the source code frame before
+ # any source code has been selected.
+ return XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
+<head>
+ <title>Source Code Frame <%= values["title_suffix"] %></title>
+ <meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
+ <link rel="stylesheet" href="<%= values["style_url"] %>" type="text/css" media="screen" />
+</head>
+<body>
+</body>
+</html>
+}
+end
+
+def write_extra_pages(values)
+ template = RDoc::TemplatePage.new(get_BLANK())
+ File.open("blank.html", "w") { |f| template.write_html_on(f, values) }
+end
+
+end
diff --git a/lib/rdoc/generator/html/one_page_html.rb b/lib/rdoc/generator/html/one_page_html.rb
index c4dd95529de..51ae32351ad 100644
--- a/lib/rdoc/generator/html/one_page_html.rb
+++ b/lib/rdoc/generator/html/one_page_html.rb
@@ -1,7 +1,10 @@
require 'rdoc/generator/html'
+require 'rdoc/generator/html/common'
module RDoc::Generator::HTML::ONE_PAGE_HTML
+ include RDoc::Generator::HTML::Common
+
CONTENTS_XML = <<-EOF
<% if defined? classes and classes["description"] then %>
<%= classes["description"] %>
@@ -76,16 +79,14 @@ module RDoc::Generator::HTML::ONE_PAGE_HTML
<% end %>
EOF
- ONE_PAGE = %{
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-<html>
+ ONE_PAGE = XHTML_STRICT_PREAMBLE + HTML_ELEMENT + %{
<head>
<title><%= values["title"] %></title>
<meta http-equiv="Content-Type" content="text/html; charset=<%= values["charset"] %>" />
</head>
<body>
<% values["files"].each do |files| %>
-<h2>File: <%= files["short_name"] %></h2>
+<h2>File: <a name="<%= files["href"] %>"><%= files["short_name"] %></a></h2>
<table>
<tr><td>Path:</td><td><%= files["full_path"] %></td></tr>
<tr><td>Modified:</td><td><%= files["dtm_modified"] %></td></tr>
@@ -97,7 +98,7 @@ module RDoc::Generator::HTML::ONE_PAGE_HTML
<h2>Classes</h2>
<% values["classes"].each do |classes| %>
<% if classes["parent"] then %>
-<h3><%= classes["classmod"] %> <%= classes["full_name"] %> &lt; <%= href classes["par_url"], classes["parent"] %></h3>
+<h3><%= classes["classmod"] %> <a name="<%= classes["href"] %>"><%= classes["full_name"] %></a> &lt; <%= href classes["par_url"], classes["parent"] %></h3>
<% end %>
<% unless classes["parent"] then %>
<h3><%= classes["classmod"] %> <%= classes["full_name"] %></h3>
diff --git a/lib/rdoc/generator/texinfo.rb b/lib/rdoc/generator/texinfo.rb
index 0b79820228a..70db875af99 100644
--- a/lib/rdoc/generator/texinfo.rb
+++ b/lib/rdoc/generator/texinfo.rb
@@ -3,13 +3,10 @@ require 'rdoc/generator'
require 'rdoc/markup/to_texinfo'
module RDoc
- RDoc::GENERATORS['texinfo'] = RDoc::Generator.new("rdoc/generator/texinfo",
- :Texinfo,
- 'texinfo')
module Generator
# This generates Texinfo files for viewing with GNU Info or Emacs
# from RDoc extracted from Ruby source files.
- class Texinfo
+ class TEXINFO
# What should the .info file be named by default?
DEFAULT_INFO_FILENAME = 'rdoc.info'
@@ -26,8 +23,8 @@ module RDoc
# Generate the +texinfo+ files
def generate(toplevels)
@toplevels = toplevels
- @files, @classes = ::RDoc::Generator::Context.build_indicies(@toplevels,
- @options)
+ @files, @classes = ::RDoc::Generator::Context.build_indices(@toplevels,
+ @options)
(@files + @classes).each { |x| x.value_hash }
diff --git a/lib/rdoc/generator/texinfo/class.texinfo.erb b/lib/rdoc/generator/texinfo/class.texinfo.erb
index 07f17eaef24..74ecc59f7da 100644
--- a/lib/rdoc/generator/texinfo/class.texinfo.erb
+++ b/lib/rdoc/generator/texinfo/class.texinfo.erb
@@ -38,7 +38,7 @@ Methods
<% (method_list["methods"] || []).uniq.each do |method| %>
<%= TexinfoTemplate.new(@v.merge({'method' => method, 'list' => method_list}),
'method.texinfo.erb').render %><% end %>
-<% end # section["method_list"] %>
-<% end %>
+<% end %>
+<% end # if section["method_list"] %>
<% end # @v['class']["sections"] %>
<% end %>
diff --git a/lib/rdoc/generator/xml.rb b/lib/rdoc/generator/xml.rb
index 3335f2ce7c3..0d4c5a7ea13 100644
--- a/lib/rdoc/generator/xml.rb
+++ b/lib/rdoc/generator/xml.rb
@@ -34,15 +34,15 @@ class RDoc::Generator::XML < RDoc::Generator::HTML
##
# Generate:
#
- # * a list of HtmlFile objects for each TopLevel object.
- # * a list of HtmlClass objects for each first level
+ # * a list of File objects for each TopLevel object.
+ # * a list of Class objects for each first level
# class or module in the TopLevel objects
# * a complete list of all hyperlinkable terms (file,
# class, module, and method names)
def build_indices
@info.each do |toplevel|
- @files << RDoc::Generator::HtmlFile.new(toplevel, @options, RDoc::Generator::FILE_DIR)
+ @files << RDoc::Generator::File.new(toplevel, @options, RDoc::Generator::FILE_DIR)
end
RDoc::TopLevel.all_classes_and_modules.each do |cls|
@@ -51,7 +51,7 @@ class RDoc::Generator::XML < RDoc::Generator::HTML
end
def build_class_list(from, html_file, class_dir)
- @classes << RDoc::Generator::HtmlClass.new(from, html_file, class_dir, @options)
+ @classes << RDoc::Generator::Class.new(from, html_file, class_dir, @options)
from.each_classmodule do |mod|
build_class_list(mod, html_file, class_dir)
end
@@ -68,9 +68,6 @@ class RDoc::Generator::XML < RDoc::Generator::HTML
'classes' => gen_into(@classes)
}
- # this method is defined in the template file
- write_extra_pages if defined? write_extra_pages
-
template = RDoc::TemplatePage.new @template::ONE_PAGE
if @options.op_name
diff --git a/lib/rdoc/generator/xml/xml.rb b/lib/rdoc/generator/xml/xml.rb
index ffb1329c4e7..4b54e7350f8 100644
--- a/lib/rdoc/generator/xml/xml.rb
+++ b/lib/rdoc/generator/xml/xml.rb
@@ -17,11 +17,23 @@ module RDoc::Generator::XML::XML
href="<%= requires["aref"] %>"
<% end %>
/>
-<% end # files["requires"] %>
+<% end %><%# files["requires"] %>
</required-file-list>
<% end %>
<% if defined? classes and classes["sections"] then %>
<% classes["sections"].each do |sections| %>
+<% if sections["constants"] then %>
+ <constant-list>
+<% sections["constants"].each do |constant| %>
+ <constant name="<%= constant["name"] %>">
+<% if constant["value"] then %>
+ <value><%= constant["value"] %></value>
+<% end %>
+ <description><%= constant["a_desc"] %></description>
+ </constant>
+<% end %><%# sections["constants"] %>
+ </constant-list>
+<% end %>
<% if sections["attributes"] then %>
<attribute-list>
<% sections["attributes"].each do |attributes| %>
@@ -31,7 +43,7 @@ module RDoc::Generator::XML::XML
<% end %>
<description><%= attributes["a_desc"] %></description>
</attribute>
-<% end # sections["attributes"] %>
+<% end %><%# sections["attributes"] %>
</attribute-list>
<% end %>
<% if sections["method_list"] then %>
@@ -52,12 +64,12 @@ module RDoc::Generator::XML::XML
</source-code-listing>
<% end %>
</method>
-<% end # method_list["methods"] %>
+<% end %><%# method_list["methods"] %>
<% end %>
-<% end # sections["method_list"] %>
+<% end %><%# sections["method_list"] %>
</method-list>
<% end %>
-<% end # classes["sections"] %>
+<% end %><%# classes["sections"] %>
<% end %>
<% if defined? classes and classes["includes"] then %>
<included-module-list>
@@ -67,7 +79,7 @@ module RDoc::Generator::XML::XML
href="<%= includes["aref"] %>"
<% end %>
/>
-<% end # classes["includes"] %>
+<% end %><%# classes["includes"] %>
</included-module-list>
<% end %>
</contents>
@@ -84,7 +96,7 @@ module RDoc::Generator::XML::XML
</file-info>
} + CONTENTS_XML + %{
</file>
-<% end # values["files"] %>
+<% end %><%# values["files"] %>
</file-list>
<class-module-list>
<% values["classes"].each do |classes| %>
@@ -94,7 +106,7 @@ module RDoc::Generator::XML::XML
<infiles>
<% classes["infiles"].each do |infiles| %>
<infile><%= href infiles["full_path_url"], infiles["full_path"] %></infile>
-<% end # classes["infiles"] %>
+<% end %><%# classes["infiles"] %>
</infiles>
<% end %>
<% if classes["parent"] then %>
@@ -103,7 +115,7 @@ module RDoc::Generator::XML::XML
</classmod-info>
} + CONTENTS_XML + %{
</<%= classes["classmod"] %>>
-<% end # values["classes"] %>
+<% end %><%# values["classes"] %>
</class-module-list>
</rdoc>
}
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
index 0e1b5962555..9d22b389460 100644
--- a/lib/rdoc/markup.rb
+++ b/lib/rdoc/markup.rb
@@ -20,101 +20,6 @@ require 'rdoc'
# RDoc::Markup could be the basis for formatting RDoc style comment blocks,
# Wiki entries, and online FAQs.
#
-# = Basic Formatting
-#
-# * RDoc::Markup looks for a document's natural left margin. This is
-# used as the initial margin for the document.
-#
-# * Consecutive lines starting at this margin are considered to be a
-# paragraph.
-#
-# * If a paragraph starts with a "*", "-", or with "<digit>.", then it is
-# taken to be the start of a list. The margin in increased to be the first
-# non-space following the list start flag. Subsequent lines should be
-# indented to this \new margin until the list ends. For example:
-#
-# * this is a list with three paragraphs in
-# the first item. This is the first paragraph.
-#
-# And this is the second paragraph.
-#
-# 1. This is an indented, numbered list.
-# 2. This is the second item in that list
-#
-# This is the third conventional paragraph in the
-# first list item.
-#
-# * This is the second item in the original list
-#
-# * You can also construct labeled lists, sometimes called description
-# or definition lists. Do this by putting the label in square brackets
-# and indenting the list body:
-#
-# [cat] a small furry mammal
-# that seems to sleep a lot
-#
-# [ant] a little insect that is known
-# to enjoy picnics
-#
-# A minor variation on labeled lists uses two colons to separate the
-# label from the list body:
-#
-# cat:: a small furry mammal
-# that seems to sleep a lot
-#
-# ant:: a little insect that is known
-# to enjoy picnics
-#
-# This latter style guarantees that the list bodies' left margins are
-# aligned: think of them as a two column table.
-#
-# * Any line that starts to the right of the current margin is treated
-# as verbatim text. This is useful for code listings. The example of a
-# list above is also verbatim text.
-#
-# * A line starting with an equals sign (=) is treated as a
-# heading. Level one headings have one equals sign, level two headings
-# have two,and so on.
-#
-# * A line starting with three or more hyphens (at the current indent)
-# generates a horizontal rule. The more hyphens, the thicker the rule
-# (within reason, and if supported by the output device)
-#
-# * You can use markup within text (except verbatim) to change the
-# appearance of parts of that text. Out of the box, RDoc::Markup
-# supports word-based and general markup.
-#
-# Word-based markup uses flag characters around individual words:
-#
-# [\*word*] displays word in a *bold* font
-# [\_word_] displays word in an _emphasized_ font
-# [\+word+] displays word in a +code+ font
-#
-# General markup affects text between a start delimiter and and end
-# delimiter. Not surprisingly, these delimiters look like HTML markup.
-#
-# [\<b>text...</b>] displays word in a *bold* font
-# [\<em>text...</em>] displays word in an _emphasized_ font
-# [\<i>text...</i>] displays word in an _emphasized_ font
-# [\<tt>text...</tt>] displays word in a +code+ font
-#
-# Unlike conventional Wiki markup, general markup can cross line
-# boundaries. You can turn off the interpretation of markup by
-# preceding the first character with a backslash, so \\\<b>bold
-# text</b> and \\\*bold* produce \<b>bold text</b> and \*bold*
-# respectively.
-#
-# * Hyperlinks to the web starting http:, mailto:, ftp:, or www. are
-# recognized. An HTTP url that references an external image file is
-# converted into an inline <IMG..>. Hyperlinks starting 'link:' are
-# assumed to refer to local files whose path is relative to the --op
-# directory.
-#
-# Hyperlinks can also be of the form <tt>label</tt>[url], in which
-# case the label is used in the displayed text, and <tt>url</tt> is
-# used as the target. If <tt>label</tt> contains multiple words,
-# put it in braces: <em>{multi word label}[</em>url<em>]</em>.
-#
# == Synopsis
#
# This code converts +input_string+ to HTML. The conversion takes place in
diff --git a/lib/rdoc/markup/inline.rb b/lib/rdoc/markup/inline.rb
index ee77679a112..46c9b5822c0 100644
--- a/lib/rdoc/markup/inline.rb
+++ b/lib/rdoc/markup/inline.rb
@@ -47,7 +47,7 @@ class RDoc::Markup
class AttrChanger
def to_s
- "Attr: +#{Attribute.as_string(@turn_on)}/-#{Attribute.as_string(@turn_on)}"
+ "Attr: +#{Attribute.as_string(turn_on)}/-#{Attribute.as_string(turn_on)}"
end
end
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
index ca29373db1d..dce7a69b129 100644
--- a/lib/rdoc/markup/to_html.rb
+++ b/lib/rdoc/markup/to_html.rb
@@ -57,7 +57,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
##
# Generate a hyperlink for url, labeled with text. Handle the
- # special cases for img: and link: described under handle_special_HYPEDLINK
+ # special cases for img: and link: described under handle_special_HYPERLINK
def gen_url(url, text)
if url =~ /([A-Za-z]+):(.*)/ then
@@ -304,9 +304,12 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# some of these patterns are taken from SmartyPants...
def convert_string_fancy(item)
- # convert -- to em-dash, (-- to en-dash)
- item.gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
+ # convert ampersand before doing anything else
+ item.gsub(/&/, '&amp;').
+ # convert -- to em-dash, (-- to en-dash)
+ gsub(/---?/, '&#8212;'). #gsub(/--/, '&#8211;').
+
# convert ... to elipsis (and make sure .... becomes .<elipsis>)
gsub(/\.\.\.\./, '.&#8230;').gsub(/\.\.\./, '&#8230;').
@@ -318,15 +321,15 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
gsub(/'/, '&#8216;').
# convert double closing quote
- gsub(%r{([^ \t\r\n\[\{\(])\'(?=\W)}, '\1&#8221;'). # }
+ gsub(%r{([^ \t\r\n\[\{\(])\"(?=\W)}, '\1&#8221;'). # }
# convert double opening quote
- gsub(/'/, '&#8220;').
+ gsub(/"/, '&#8220;').
# convert copyright
gsub(/\(c\)/, '&#169;').
- # convert and registered trademark
+ # convert registered trademark
gsub(/\(r\)/, '&#174;')
end
diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
index a6f29c5c2cf..dc64b30da15 100644
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ b/lib/rdoc/markup/to_html_crossref.rb
@@ -9,6 +9,68 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
attr_accessor :context
+ # Regular expressions to match class and method references.
+ #
+ # 1.) There can be a '\' in front of text to suppress
+ # any cross-references (note, however, that the single '\'
+ # is written as '\\\\' in order to escape it twice, once
+ # in the Ruby String literal and once in the regexp).
+ # 2.) There can be a '::' in front of class names to reference
+ # from the top-level namespace.
+ # 3.) The method can be followed by parenthesis,
+ # which may or may not have things inside (this
+ # apparently is allowed for Fortran 95, but I also think that this
+ # is a good idea for Ruby, as it is very reasonable to want to
+ # reference a call with arguments).
+ #
+ # NOTE: In order to support Fortran 95 properly, the [A-Z] below
+ # should be changed to [A-Za-z]. This slows down rdoc significantly,
+ # however, and the Fortran 95 support is broken in any case due to
+ # the return in handle_special_CROSSREF if the token consists
+ # entirely of lowercase letters.
+ #
+ # The markup/cross-referencing engine needs a rewrite for
+ # Fortran 95 to be supported properly.
+ CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)'
+ METHOD_REGEXP_STR = '(\w+[!?=]?)(?:\([\.\w+\*\/\+\-\=\<\>]*\))?'
+
+ # Regular expressions matching text that should potentially have
+ # cross-reference links generated are passed to add_special.
+ # Note that these expressions are meant to pick up text for which
+ # cross-references have been suppressed, since the suppression
+ # characters are removed by the code that is triggered.
+ CROSSREF_REGEXP = /(
+ # A::B::C.meth
+ #{CLASS_REGEXP_STR}[\.\#]#{METHOD_REGEXP_STR}
+
+ # Stand-alone method (proceeded by a #)
+ | \\?\##{METHOD_REGEXP_STR}
+
+ # A::B::C
+ # The stuff after CLASS_REGEXP_STR is a
+ # nasty hack. CLASS_REGEXP_STR unfortunately matches
+ # words like dog and cat (these are legal "class"
+ # names in Fortran 95). When a word is flagged as a
+ # potential cross-reference, limitations in the markup
+ # engine suppress other processing, such as typesetting.
+ # This is particularly noticeable for contractions.
+ # In order that words like "can't" not
+ # be flagged as potential cross-references, only
+ # flag potential class cross-references if the character
+ # after the cross-referece is a space or sentence
+ # punctuation.
+ | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;]|\z)
+
+ # Things that look like filenames
+ # The key thing is that there must be at least
+ # one special character (period, slash, or
+ # underscore).
+ | [\/\w]+[_\/\.][\w\/\.]+
+
+ # Things that have markup suppressed
+ | \\[^\s]
+ )/x
+
##
# We need to record the html path of our caller so we can generate
# correct relative paths for any hyperlinks that we find
@@ -17,18 +79,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
super()
- # class names, variable names, or instance variables
- @markup.add_special(/(
- # A::B.meth(**) (for operator in Fortran95)
- \w+(::\w+)*[.\#]\w+(\([\.\w+\*\/\+\-\=\<\>]+\))?
- # meth(**) (for operator in Fortran95)
- | \#\w+(\([.\w\*\/\+\-\=\<\>]+\))?
- | \b([A-Z]\w*(::\w+)*[.\#]\w+) # A::B.meth
- | \b([A-Z]\w+(::\w+)*) # A::B
- | \#\w+[!?=]? # #meth_name
- | \\?\b\w+([_\/\.]+\w+)*[!?=]? # meth_name
- )/x,
- :CROSSREF)
+ @markup.add_special(CROSSREF_REGEXP, :CROSSREF)
@from_path = from_path
@context = context
@@ -48,6 +99,9 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
def handle_special_CROSSREF(special)
name = special.text
+ # This ensures that words entirely consisting of lowercase letters will
+ # not have cross-references generated (to suppress lots of
+ # erroneous cross-references to "new" in text, for instance)
return name if name =~ /\A[a-z]*\z/
return @seen[name] if @seen.include? name
@@ -70,14 +124,7 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
# (in which case it would match the last pattern, which just checks
# whether the string as a whole is a known symbol).
- if /([A-Z][\w:]*)[.\#](\w+[!?=]?)/ =~ lookup then
- container = $1
- method = $2
- ref = @context.find_symbol container, method
- end
-
- if !ref and
- /([A-Za-z][\w:]*)[.\#](\w+(\([\.\w+\*\/\+\-\=\<\>]+\))?)/ =~ lookup then
+ if /#{CLASS_REGEXP_STR}[\.\#]#{METHOD_REGEXP_STR}/ =~ lookup then
container = $1
method = $2
ref = @context.find_symbol container, method
@@ -99,4 +146,3 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
end
end
-
diff --git a/lib/rdoc/markup/to_texinfo.rb b/lib/rdoc/markup/to_texinfo.rb
index 533d3e34a03..65a1608c4d0 100644
--- a/lib/rdoc/markup/to_texinfo.rb
+++ b/lib/rdoc/markup/to_texinfo.rb
@@ -30,7 +30,7 @@ class RDoc::Markup::ToTexInfo < RDoc::Markup::Formatter
def accept_heading(attributes, text)
heading = ['@majorheading', '@chapheading'][text.head_level - 1] || '@heading'
- @text << "#{heading}{#{format(text)}}"
+ @text << "#{heading} #{format(text)}"
end
def accept_list_start(attributes, text)
diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb
index d683a140224..1d92bd4748e 100644
--- a/lib/rdoc/options.rb
+++ b/lib/rdoc/options.rb
@@ -184,7 +184,7 @@ class RDoc::Options
@css = nil
@webcvs = nil
- @charset = 'iso-8859-1'
+ @charset = 'utf-8'
end
##
@@ -196,6 +196,7 @@ class RDoc::Options
opts = OptionParser.new do |opt|
opt.program_name = File.basename $0
opt.version = RDoc::VERSION
+ opt.release = nil
opt.summary_indent = ' ' * 4
opt.banner = <<-EOF
Usage: #{opt.program_name} [options] [names...]
@@ -257,7 +258,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.separator nil
opt.on("--charset=CHARSET", "-c",
- "Specifies the HTML character-set.") do |value|
+ "Specifies the output HTML character-set.") do |value|
@charset = value
end
@@ -283,9 +284,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.on("--exclude=PATTERN", "-x", Regexp,
"Do not process files or directories",
- "matching PATTERN. Files given explicitly",
- "on the command line will never be",
- "excluded.") do |value|
+ "matching PATTERN.") do |value|
@exclude << value
end
diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
index 794fad00e9c..6855cfcfc59 100644
--- a/lib/rdoc/parser.rb
+++ b/lib/rdoc/parser.rb
@@ -63,10 +63,31 @@ class RDoc::Parser
end
##
+ # Shamelessly stolen from the ptools gem (since RDoc cannot depend on
+ # the gem).
+
+ def self.binary?(file)
+ s = (File.read(file, File.stat(file).blksize) || "").split(//)
+ ((s.size - s.grep(" ".."~").size) / s.size.to_f) > 0.30
+ end
+ private_class_method :binary?
+
+ ##
# Return a parser that can handle a particular extension
def self.can_parse(file_name)
- RDoc::Parser.parsers.find { |regexp, parser| regexp =~ file_name }.last
+ parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
+
+ #
+ # The default parser should *NOT* parse binary files.
+ #
+ if parser == RDoc::Parser::Simple then
+ if binary? file_name then
+ return nil
+ end
+ end
+
+ return parser
end
##
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 43bb767da93..a5b06c2b041 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -120,7 +120,7 @@ class RDoc::Parser::C < RDoc::Parser
@stats.add_alias as
end
- end
+ end
def do_classes
@content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
@@ -155,7 +155,7 @@ class RDoc::Parser::C < RDoc::Parser
\(
\s*(\w+),
\s*"(\w+)",
- \s*(\w+)\s*
+ \s*([\w\*\s\(\)\.\->]+)\s* # for SWIG
\s*\)/mx) do |var_name, in_module, class_name, parent|
handle_class_module(var_name, "class", class_name, parent, in_module)
end
@@ -251,7 +251,7 @@ class RDoc::Parser::C < RDoc::Parser
handle_method("method", "rb_mFileTest", meth_name, meth_body, param_count)
handle_method("singleton_method", "rb_cFile", meth_name, meth_body, param_count)
end
- end
+ end
def find_attr_comment(attr_name)
if @content =~ %r{((?>/\*.*?\*/\s+))
@@ -267,10 +267,10 @@ class RDoc::Parser::C < RDoc::Parser
##
# Find the C code corresponding to a Ruby method
- def find_body(meth_name, meth_obj, body, quiet = false)
+ def find_body(class_name, meth_name, meth_obj, body, quiet = false)
case body
- when %r"((?>/\*.*?\*/\s*))(?:static\s+)?VALUE\s+#{meth_name}
- \s*(\([^)]*\))\s*\{.*?^\}"xm
+ when %r"((?>/\*.*?\*/\s*)*)(?:(?:static|SWIGINTERN)\s+)?(?:intern\s+)?VALUE\s+#{meth_name}
+ \s*(\([^)]*\))([^;]|$)"xm
comment, params = $1, $2
body_text = $&
@@ -279,9 +279,7 @@ class RDoc::Parser::C < RDoc::Parser
# see if we can find the whole body
re = Regexp.escape(body_text) + '[^(]*^\{.*?^\}'
- if Regexp.new(re, Regexp::MULTILINE).match(body)
- body_text = $&
- end
+ body_text = $& if /#{re}/m =~ body
# The comment block may have been overridden with a 'Document-method'
# block. This happens in the interpreter when multiple methods are
@@ -289,7 +287,7 @@ class RDoc::Parser::C < RDoc::Parser
# distinct (for example Kernel.hash and Kernel.object_id share the same
# implementation
- override_comment = find_override_comment(meth_obj.name)
+ override_comment = find_override_comment(class_name, meth_obj.name)
comment = override_comment if override_comment
find_modifiers(comment, meth_obj) if comment
@@ -300,18 +298,18 @@ class RDoc::Parser::C < RDoc::Parser
meth_obj.comment = mangle_comment(comment)
when %r{((?>/\*.*?\*/\s*))^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
comment = $1
- find_body($2, meth_obj, body, true)
+ find_body(class_name, $2, meth_obj, body, true)
find_modifiers(comment, meth_obj)
meth_obj.comment = mangle_comment(comment) + meth_obj.comment
when %r{^\s*\#\s*define\s+#{meth_name}\s+(\w+)}m
- unless find_body($1, meth_obj, body, true)
+ unless find_body(class_name, $1, meth_obj, body, true)
warn "No definition for #{meth_name}" unless @options.quiet
return false
end
else
# No body, but might still have an override comment
- comment = find_override_comment(meth_obj.name)
+ comment = find_override_comment(class_name, meth_obj.name)
if comment
find_modifiers(comment, meth_obj)
@@ -367,10 +365,10 @@ class RDoc::Parser::C < RDoc::Parser
def find_class_comment(class_name, class_meth)
comment = nil
if @content =~ %r{((?>/\*.*?\*/\s+))
- (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi
+ (static\s+)?void\s+Init_#{class_name}\s*(?:_\(\s*)?\(\s*(?:void\s*)\)}xmi then
+ comment = $1
+ elsif @content =~ %r{Document-(?:class|module):\s#{class_name}\s*?(?:<\s+[:,\w]+)?\n((?>.*?\*/))}m
comment = $1
- elsif @content =~ %r{Document-(class|module):\s#{class_name}\s*?\n((?>.*?\*/))}m
- comment = $2
else
if @content =~ /rb_define_(class|module)/m then
class_name = class_name.split("::").last
@@ -424,9 +422,11 @@ class RDoc::Parser::C < RDoc::Parser
end
end
- def find_override_comment(meth_name)
+ def find_override_comment(class_name, meth_name)
name = Regexp.escape(meth_name)
- if @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m
+ if @content =~ %r{Document-method:\s+#{class_name}(?:\.|::)#{name}\s*?\n((?>.*?\*/))}m then
+ $1
+ elsif @content =~ %r{Document-method:\s#{name}\s*?\n((?>.*?\*/))}m then
$1
end
end
@@ -480,6 +480,10 @@ class RDoc::Parser::C < RDoc::Parser
end
if class_mod == "class" then
+ full_name = enclosure.full_name.to_s + "::#{class_name}"
+ if @content =~ %r{Document-class:\s+#{full_name}\s*<\s+([:,\w]+)} then
+ parent_name = $1
+ end
cm = enclosure.add_class RDoc::NormalClass, class_name, parent_name
@stats.add_class cm
else
@@ -562,18 +566,16 @@ class RDoc::Parser::C < RDoc::Parser
return unless class_name
- class_obj = find_class(var_name, class_name)
+ class_obj = find_class var_name, class_name
- if class_obj
- if meth_name == "initialize"
+ if class_obj then
+ if meth_name == "initialize" then
meth_name = "new"
type = "singleton_method"
end
- meth_obj = RDoc::AnyMethod.new("", meth_name)
- meth_obj.singleton =
- %w{singleton_method module_function}.include?(type)
- @stats.add_method meth_obj
+ meth_obj = RDoc::AnyMethod.new '', meth_name
+ meth_obj.singleton = %w[singleton_method module_function].include? type
p_count = (Integer(param_count) rescue -1)
@@ -585,14 +587,16 @@ class RDoc::Parser::C < RDoc::Parser
meth_obj.params = "(" + (1..p_count).map{|i| "p#{i}"}.join(", ") + ")"
end
- if source_file
+ if source_file then
file_name = File.join(@file_dir, source_file)
body = (@@known_bodies[source_file] ||= File.read(file_name))
else
body = @content
end
- if find_body(meth_body, meth_obj, body) and meth_obj.document_self
- class_obj.add_method(meth_obj)
+
+ if find_body(class_name, meth_body, meth_obj, body) and meth_obj.document_self then
+ class_obj.add_method meth_obj
+ @stats.add_method meth_obj
end
end
end
@@ -628,8 +632,8 @@ class RDoc::Parser::C < RDoc::Parser
end
def remove_private_comments(comment)
- comment.gsub!(/\/?\*--(.*?)\/?\*\+\+/m, '')
- comment.sub!(/\/?\*--.*/m, '')
+ comment.gsub!(/\/?\*--\n(.*?)\/?\*\+\+/m, '')
+ comment.sub!(/\/?\*--\n.*/m, '')
end
##
diff --git a/lib/rdoc/parser/perl.rb b/lib/rdoc/parser/perl.rb
new file mode 100644
index 00000000000..43d1e9ff692
--- /dev/null
+++ b/lib/rdoc/parser/perl.rb
@@ -0,0 +1,165 @@
+require 'rdoc/parser'
+
+##
+#
+# This is an attamept to write a basic parser for Perl's
+# POD (Plain old Documentation) format. Ruby code must
+# co-exist with Perl, and some tasks are easier in Perl
+# than Ruby because of existing libraries.
+#
+# One difficult is that Perl POD has no means of identifying
+# the classes (packages) and methods (subs) with which it
+# is associated, it is more like literate programming in so
+# far as it just happens to be in the same place as the code,
+# but need not be.
+#
+# We would like to support all the markup the POD provides
+# so that it will convert happily to HTML. At the moment
+# I don't think I can do that: time constraints.
+#
+
+class RDoc::Parser::PerlPOD < RDoc::Parser
+
+ parse_files_matching(/.p[lm]$/)
+
+ ##
+ # Prepare to parse a perl file
+
+ def initialize(top_level, file_name, content, options, stats)
+ super
+
+ preprocess = RDoc::Markup::PreProcess.new @file_name, @options.rdoc_include
+
+ preprocess.handle @content do |directive, param|
+ warn "Unrecognized directive '#{directive}' in #{@file_name}"
+ end
+ end
+
+ ##
+ # Extract the Pod(-like) comments from the code.
+ # At its most basic there will ne no need to distinguish
+ # between the different types of header, etc.
+ #
+ # This uses a simple finite state machine, in a very
+ # procedural pattern. I could "replace case with polymorphism"
+ # but I think it would obscure the intent, scatter the
+ # code all over tha place. This machine is necessary
+ # because POD requires that directives be preceded by
+ # blank lines, so reading line by line is necessary,
+ # and preserving state about what is seen is necesary.
+
+ def scan
+
+ @top_level.comment ||= ""
+ state=:code_blank
+ line_number = 0
+ line = nil
+
+ # This started out as a really long nested case statement,
+ # which also led to repetitive code. I'd like to avoid that
+ # so I'm using a "table" instead.
+
+ # Firstly we need some procs to do the transition and processing
+ # work. Because these are procs they are closures, and they can
+ # use variables in the local scope.
+ #
+ # First, the "nothing to see here" stuff.
+ code_noop = lambda do
+ if line =~ /^\s+$/
+ state = :code_blank
+ end
+ end
+
+ pod_noop = lambda do
+ if line =~ /^\s+$/
+ state = :pod_blank
+ end
+ @top_level.comment += filter(line)
+ end
+
+ begin_noop = lambda do
+ if line =~ /^\s+$/
+ state = :begin_blank
+ end
+ @top_level.comment += filter(line)
+ end
+
+ # Now for the blocks that process code and comments...
+
+ transit_to_pod = lambda do
+ case line
+ when /^=(?:pod|head\d+)/
+ state = :pod_no_blank
+ @top_level.comment += filter(line)
+ when /^=over/
+ state = :over_no_blank
+ @top_level.comment += filter(line)
+ when /^=(?:begin|for)/
+ state = :begin_no_blank
+ end
+ end
+
+ process_pod = lambda do
+ case line
+ when /^\s*$/
+ state = :pod_blank
+ @top_level.comment += filter(line)
+ when /^=cut/
+ state = :code_no_blank
+ when /^=end/
+ $stderr.puts "'=end' unexpected at #{line_number} in #{@file_name}"
+ else
+ @top_level.comment += filter(line)
+ end
+ end
+
+
+ process_begin = lambda do
+ case line
+ when /^\s*$/
+ state = :begin_blank
+ @top_level.comment += filter(line)
+ when /^=end/
+ state = :code_no_blank
+ when /^=cut/
+ $stderr.puts "'=cut' unexpected at #{line_number} in #{@file_name}"
+ else
+ @top_level.comment += filter(line)
+ end
+
+ end
+
+
+ transitions = { :code_no_blank => code_noop,
+ :code_blank => transit_to_pod,
+ :pod_no_blank => pod_noop,
+ :pod_blank => process_pod,
+ :begin_no_blank => begin_noop,
+ :begin_blank => process_begin}
+ @content.each_line do |l|
+ line = l
+ line_number += 1
+ transitions[state].call
+ end # each line
+
+ @top_level
+ end
+
+ # Filter the perl markup that does the same as the rdoc
+ # filtering. Only basic for now. Will probably need a
+ # proper parser to cope with C<<...>> etc
+ def filter(comment)
+ return '' if comment =~ /^=pod\s*$/
+ comment.gsub!(/^=pod/, '==')
+ comment.gsub!(/^=head(\d+)/) do
+ "=" * $1.to_i
+ end
+ comment.gsub!(/=item/, '');
+ comment.gsub!(/C<(.*?)>/, '<tt>\1</tt>');
+ comment.gsub!(/I<(.*?)>/, '<i>\1</i>');
+ comment.gsub!(/B<(.*?)>/, '<b>\1</b>');
+ comment
+ end
+
+end
+
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index abbc85bde7c..865cb79d398 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -134,7 +134,7 @@ module RDoc::RubyToken
TokenDefinitions = [
[:TkCLASS, TkKW, "class", EXPR_CLASS],
- [:TkMODULE, TkKW, "module", EXPR_BEG],
+ [:TkMODULE, TkKW, "module", EXPR_CLASS],
[:TkDEF, TkKW, "def", EXPR_FNAME],
[:TkUNDEF, TkKW, "undef", EXPR_FNAME],
[:TkBEGIN, TkKW, "begin", EXPR_BEG],
@@ -1945,9 +1945,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
case tk
when TkSEMICOLON
break
- when TkLPAREN, TkfLPAREN
+ when TkLPAREN, TkfLPAREN, TkLBRACE, TkLBRACK, TkDO
nest += 1
- when TkRPAREN
+ when TkRPAREN, TkRBRACE, TkRBRACK, TkEND
nest -= 1
when TkCOMMENT
if nest <= 0 && @scanner.lex_state == EXPR_END
@@ -1955,7 +1955,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
break
end
when TkNL
- if (@scanner.lex_state == EXPR_END and nest <= 0) || !@scanner.continue
+ if (nest <= 0) && ((@scanner.lex_state == EXPR_END) || (!@scanner.continue))
unget_tk(tk)
break
end
@@ -2683,8 +2683,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
def remove_private_comments(comment)
- comment.gsub!(/^#--.*?^#\+\+/m, '')
- comment.sub!(/^#--.*/m, '')
+ comment.gsub!(/^#--\n.*?^#\+\+/m, '')
+ comment.sub!(/^#--\n.*/m, '')
end
def remove_token_listener(obj)
diff --git a/lib/rdoc/parser/simple.rb b/lib/rdoc/parser/simple.rb
index 6e123a46558..cdfe6867187 100644
--- a/lib/rdoc/parser/simple.rb
+++ b/lib/rdoc/parser/simple.rb
@@ -31,7 +31,7 @@ class RDoc::Parser::Simple < RDoc::Parser
end
def remove_private_comments(comment)
- comment.gsub(/^--[^-].*?^\+\+/m, '').sub(/^--.*/m, '')
+ comment.gsub(/^--\n.*?^\+\+/m, '').sub(/^--\n.*/m, '')
end
end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index bc0a32f4076..ce1cb1a93f3 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -7,6 +7,7 @@ require 'rdoc/parser/simple'
require 'rdoc/parser/ruby'
require 'rdoc/parser/c'
require 'rdoc/parser/f95'
+require 'rdoc/parser/perl'
require 'rdoc/stats'
require 'rdoc/options'
@@ -189,11 +190,11 @@ module RDoc
def parse_files(options)
@stats = Stats.new options.verbosity
-
+
files = options.files
files = ["."] if files.empty?
- file_list = normalized_file_list(options, files, true)
+ file_list = normalized_file_list(options, files, true, options.exclude)
return [] if file_list.empty?
@@ -288,6 +289,5 @@ module RDoc
end
end
end
-
end
diff --git a/lib/rdoc/ri/cache.rb b/lib/rdoc/ri/cache.rb
index 2e267d95fb6..06177a00def 100644
--- a/lib/rdoc/ri/cache.rb
+++ b/lib/rdoc/ri/cache.rb
@@ -14,7 +14,7 @@ class RDoc::RI::ClassEntry
@inferior_classes = []
end
- # We found this class in more tha one place, so add
+ # We found this class in more than one place, so add
# in the name from there.
def add_path(path)
@path_names << path
@@ -37,10 +37,10 @@ class RDoc::RI::ClassEntry
if name =~ /^(.*?)-(c|i).yaml$/
external_name = $1
is_class_method = $2 == "c"
- internal_name = RiWriter.external_to_internal(external_name)
+ internal_name = RDoc::RI::Writer.external_to_internal(external_name)
list = is_class_method ? @class_methods : @instance_methods
path = File.join(dir, name)
- list << MethodEntry.new(path, internal_name, is_class_method, self)
+ list << RDoc::RI::MethodEntry.new(path, internal_name, is_class_method, self)
else
full_name = File.join(dir, name)
if File.directory?(full_name)
@@ -48,7 +48,7 @@ class RDoc::RI::ClassEntry
if inf_class
inf_class.add_path(full_name)
else
- inf_class = ClassEntry.new(full_name, name, self)
+ inf_class = RDoc::RI::ClassEntry.new(full_name, name, self)
@inferior_classes << inf_class
end
inf_class.load_from(full_name)
@@ -168,7 +168,7 @@ class RDoc::RI::MethodEntry
end
##
-# We represent everything know about all 'ri' files accessible to this program
+# We represent everything known about all 'ri' files accessible to this program
class RDoc::RI::Cache
@@ -185,4 +185,3 @@ class RDoc::RI::Cache
end
end
-
diff --git a/lib/rdoc/ri/descriptions.rb b/lib/rdoc/ri/descriptions.rb
index 0d8560323ae..467b7de2a92 100644
--- a/lib/rdoc/ri/descriptions.rb
+++ b/lib/rdoc/ri/descriptions.rb
@@ -77,7 +77,9 @@ end
class RDoc::RI::ModuleDescription < RDoc::RI::Description
attr_accessor :class_methods
+ attr_accessor :class_method_extensions
attr_accessor :instance_methods
+ attr_accessor :instance_method_extensions
attr_accessor :attributes
attr_accessor :constants
attr_accessor :includes
@@ -148,6 +150,7 @@ class RDoc::RI::MethodDescription < RDoc::RI::Description
attr_accessor :aliases
attr_accessor :is_alias_for
attr_accessor :params
+ attr_accessor :source_path
end
diff --git a/lib/rdoc/ri/display.rb b/lib/rdoc/ri/display.rb
index 379cef11b39..05a7cf253da 100644
--- a/lib/rdoc/ri/display.rb
+++ b/lib/rdoc/ri/display.rb
@@ -1,5 +1,15 @@
require 'rdoc/ri'
+# readline support might not be present, so be careful
+# when requiring it.
+begin
+ require('readline')
+ require('abbrev')
+ CAN_USE_READLINE = true
+rescue
+ CAN_USE_READLINE = false
+end
+
##
# This is a kind of 'flag' module. If you want to write your own 'ri' display
# module (perhaps because you're writing an IDE), you write a class which
@@ -41,7 +51,7 @@ class RDoc::RI::DefaultDisplay
# Display information about +klass+. Fetches additional information from
# +ri_reader+ as necessary.
- def display_class_info(klass, ri_reader)
+ def display_class_info(klass)
page do
superclass = klass.superclass_string
@@ -61,17 +71,11 @@ class RDoc::RI::DefaultDisplay
@formatter.blankline
@formatter.display_heading("Includes:", 2, "")
incs = []
+
klass.includes.each do |inc|
- inc_desc = ri_reader.find_class_by_name(inc.name)
- if inc_desc
- str = inc.name + "("
- str << inc_desc.instance_methods.map{|m| m.name}.join(", ")
- str << ")"
- incs << str
- else
- incs << inc.name
- end
- end
+ incs << inc.name
+ end
+
@formatter.wrap(incs.sort.join(', '))
end
@@ -82,42 +86,19 @@ class RDoc::RI::DefaultDisplay
constants = klass.constants.sort_by { |constant| constant.name }
constants.each do |constant|
+ @formatter.wrap "#{constant.name} = #{constant.value}"
if constant.comment then
- @formatter.wrap "#{constant.name}:"
-
@formatter.indent do
@formatter.display_flow constant.comment
end
else
- @formatter.wrap constant.name
+ @formatter.break_to_newline
end
end
end
- class_data = [
- :class_methods,
- :class_method_extensions,
- :instance_methods,
- :instance_method_extensions,
- ]
-
- class_data.each do |data_type|
- data = klass.send data_type
-
- unless data.empty? then
- @formatter.blankline
-
- heading = data_type.to_s.split('_').join(' ').capitalize << ':'
- @formatter.display_heading heading, 2, ''
-
- data = data.map { |item| item.name }.sort.join ', '
- @formatter.wrap data
- end
- end
-
unless klass.attributes.empty? then
@formatter.blankline
-
@formatter.display_heading 'Attributes:', 2, ''
attributes = klass.attributes.sort_by { |attribute| attribute.name }
@@ -130,11 +111,119 @@ class RDoc::RI::DefaultDisplay
end
else
@formatter.wrap "#{attribute.name} (#{attribute.rw})"
+ @formatter.break_to_newline
end
end
end
+
+ return display_class_method_list(klass)
end
end
+
+ ##
+ # Given a Hash mapping a class' methods to method types (returned by
+ # display_class_method_list), this method allows the user to
+ # choose one of the methods.
+
+ def get_class_method_choice(method_map)
+ if CAN_USE_READLINE
+ # prepare abbreviations for tab completion
+ abbreviations = method_map.keys.abbrev
+ Readline.completion_proc = proc do |string|
+ abbreviations.values.uniq.grep(/^#{string}/)
+ end
+ end
+
+ @formatter.raw_print_line "\nEnter the method name you want.\n"
+ @formatter.raw_print_line "Class methods can be preceeded by '::' and instance methods by '#'.\n"
+
+ if CAN_USE_READLINE
+ @formatter.raw_print_line "You can use tab to autocomplete.\n"
+ @formatter.raw_print_line "Enter a blank line to exit.\n"
+
+ choice_string = Readline.readline(">> ").strip
+ else
+ @formatter.raw_print_line "Enter a blank line to exit.\n"
+ @formatter.raw_print_line ">> "
+ choice_string = $stdin.gets.strip
+ end
+
+ if choice_string == ''
+ return nil
+ else
+ class_or_instance = method_map[choice_string]
+
+ if class_or_instance
+ # If the user's choice is not preceeded by a '::' or a '#', figure
+ # out whether they want a class or an instance method and decorate
+ # the choice appropriately.
+ if(choice_string =~ /^[a-zA-Z]/)
+ if(class_or_instance == :class)
+ choice_string = "::#{choice_string}"
+ else
+ choice_string = "##{choice_string}"
+ end
+ end
+
+ return choice_string
+ else
+ @formatter.raw_print_line "No method matched '#{choice_string}'.\n"
+ return nil
+ end
+ end
+ end
+
+
+ ##
+ # Display methods on +klass+
+ # Returns a hash mapping method name to method contents (HACK?)
+
+ def display_class_method_list(klass)
+ method_map = {}
+
+ class_data = [
+ :class_methods,
+ :class_method_extensions,
+ :instance_methods,
+ :instance_method_extensions,
+ ]
+
+ class_data.each do |data_type|
+ data = klass.send data_type
+
+ unless data.nil? or data.empty? then
+ @formatter.blankline
+
+ heading = data_type.to_s.split('_').join(' ').capitalize << ':'
+ @formatter.display_heading heading, 2, ''
+
+ method_names = []
+ data.each do |item|
+ method_names << item.name
+
+ if(data_type == :class_methods ||
+ data_type == :class_method_extensions) then
+ method_map["::#{item.name}"] = :class
+ method_map[item.name] = :class
+ else
+ #
+ # Since we iterate over instance methods after class methods,
+ # an instance method always will overwrite the unqualified
+ # class method entry for a class method of the same name.
+ #
+ method_map["##{item.name}"] = :instance
+ method_map[item.name] = :instance
+ end
+ end
+ method_names.sort!
+
+ @formatter.wrap method_names.join(',')
+ end
+ end
+
+ method_map
+ end
+ private :display_class_method_list
##
# Display an Array of RDoc::Markup::Flow objects, +flow+.
@@ -172,10 +261,42 @@ class RDoc::RI::DefaultDisplay
def display_method_list(methods)
page do
@formatter.wrap "More than one method matched your request. You can refine your search by asking for information on one of:"
+ @formatter.blankline
+ methods.each do |method|
+ @formatter.raw_print_line "#{method.full_name} [#{method.source_path}]\n"
+ end
+ end
+ end
+
+ ##
+ # Display a list of +methods+ and allow the user to select one of them.
+
+ def display_method_list_choice(methods)
+ page do
+ @formatter.wrap "More than one method matched your request. Please choose one of the possible matches."
@formatter.blankline
- @formatter.wrap methods.map { |m| m.full_name }.join(", ")
+ methods.each_with_index do |method, index|
+ @formatter.raw_print_line "%3d %s [%s]\n" % [index + 1, method.full_name, method.source_path]
+ end
+
+ @formatter.raw_print_line ">> "
+
+ choice = $stdin.gets.strip!
+
+ if(choice == '')
+ return
+ end
+
+ choice = choice.to_i
+
+ if ((choice == 0) || (choice > methods.size)) then
+ @formatter.raw_print_line "Invalid choice!\n"
+ else
+ method = methods[choice - 1]
+ display_method_info(method)
+ end
end
end
@@ -198,10 +319,8 @@ class RDoc::RI::DefaultDisplay
@formatter.break_to_newline
end
- if method.source_path then
- @formatter.blankline
- @formatter.wrap("Extension from #{method.source_path}")
- end
+ @formatter.blankline
+ @formatter.wrap("From #{method.source_path}")
end
##
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index dfc5f2f98a1..0c91232b701 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -11,29 +11,33 @@ require 'rdoc/markup/to_flow'
class RDoc::RI::Driver
- class Hash < ::Hash
- def self.convert(hash)
- hash = new.update hash
-
- hash.each do |key, value|
- hash[key] = case value
- when ::Hash then
- convert value
- when Array then
- value = value.map do |v|
- ::Hash === v ? convert(v) : v
- end
- value
- else
- value
- end
- end
-
- hash
- end
+ #
+ # This class offers both Hash and OpenStruct functionality.
+ # We convert from the Core Hash to this before calling any of
+ # the display methods, in order to give the display methods
+ # a cleaner API for accessing the data.
+ #
+ class OpenStructHash < Hash
+ #
+ # This method converts from a Hash to an OpenStructHash.
+ #
+ def self.convert(object)
+ case object
+ when Hash then
+ new_hash = new # Convert Hash -> OpenStructHash
+
+ object.each do |key, value|
+ new_hash[key] = convert(value)
+ end
- def method_missing method, *args
- self[method.to_s]
+ new_hash
+ when Array then
+ object.map do |element|
+ convert(element)
+ end
+ else
+ object
+ end
end
def merge_enums(other)
@@ -57,6 +61,10 @@ class RDoc::RI::Driver
end
end
end
+
+ def method_missing method, *args
+ self[method.to_s]
+ end
end
class Error < RDoc::RI::Error; end
@@ -69,25 +77,31 @@ class RDoc::RI::Driver
attr_accessor :homepath # :nodoc:
- def self.process_args(argv)
+ def self.default_options
options = {}
options[:use_stdout] = !$stdout.tty?
options[:width] = 72
options[:formatter] = RDoc::RI::Formatter.for 'plain'
- options[:list_classes] = false
- options[:list_names] = false
+ options[:interactive] = false
+ options[:use_cache] = true
+
+ # By default all standard paths are used.
+ options[:use_system] = true
+ options[:use_site] = true
+ options[:use_home] = true
+ options[:use_gems] = true
+ options[:extra_doc_dirs] = []
+
+ return options
+ end
- # By default all paths are used. If any of these are true, only those
- # directories are used.
- use_system = false
- use_site = false
- use_home = false
- use_gems = false
- doc_dirs = []
+ def self.process_args(argv)
+ options = default_options
opts = OptionParser.new do |opt|
opt.program_name = File.basename $0
opt.version = RDoc::VERSION
+ opt.release = nil
opt.summary_indent = ' ' * 4
directories = [
@@ -142,86 +156,114 @@ Options may also be set in the 'RI' environment variable.
opt.separator "Options:"
opt.separator nil
- opt.on("--classes", "-c",
- "Display the names of classes and modules we",
- "know about.") do |value|
- options[:list_classes] = value
+ opt.on("--fmt=FORMAT", "--format=FORMAT", "-f",
+ RDoc::RI::Formatter::FORMATTERS.keys,
+ "Format to use when displaying output:",
+ " #{RDoc::RI::Formatter.list}",
+ "Use 'bs' (backspace) with most pager",
+ "programs. To use ANSI, either disable the",
+ "pager or tell the pager to allow control",
+ "characters.") do |value|
+ options[:formatter] = RDoc::RI::Formatter.for value
end
opt.separator nil
opt.on("--doc-dir=DIRNAME", "-d", Array,
- "List of directories to search for",
- "documentation. If not specified, we search",
- "the standard rdoc/ri directories. May be",
- "repeated.") do |value|
+ "List of directories from which to source",
+ "documentation in addition to the standard",
+ "directories. May be repeated.") do |value|
value.each do |dir|
unless File.directory? dir then
raise OptionParser::InvalidArgument, "#{dir} is not a directory"
end
+
+ options[:extra_doc_dirs] << File.expand_path(dir)
end
+ end
+
+ opt.separator nil
- doc_dirs.concat value
+ opt.on("--[no-]use-cache",
+ "Whether or not to use ri's cache.",
+ "True by default.") do |value|
+ options[:use_cache] = value
end
opt.separator nil
- opt.on("--fmt=FORMAT", "--format=FORMAT", "-f",
- RDoc::RI::Formatter::FORMATTERS.keys,
- "Format to use when displaying output:",
- " #{RDoc::RI::Formatter.list}",
- "Use 'bs' (backspace) with most pager",
- "programs. To use ANSI, either disable the",
- "pager or tell the pager to allow control",
- "characters.") do |value|
- options[:formatter] = RDoc::RI::Formatter.for value
+ opt.on("--no-standard-docs",
+ "Do not include documentation from",
+ "the Ruby standard library, site_lib,",
+ "installed gems, or ~/.rdoc.",
+ "Equivalent to specifying",
+ "the options --no-system, --no-site, --no-gems,",
+ "and --no-home") do
+ options[:use_system] = false
+ options[:use_site] = false
+ options[:use_gems] = false
+ options[:use_home] = false
end
opt.separator nil
- unless RDoc::RI::Paths::GEMDIRS.empty? then
- opt.on("--[no-]gems",
- "Include documentation from RubyGems.") do |value|
- use_gems = value
- end
+ opt.on("--[no-]system",
+ "Include documentation from Ruby's standard",
+ "library. Defaults to true.") do |value|
+ options[:use_system] = value
end
opt.separator nil
- opt.on("--[no-]home",
- "Include documentation stored in ~/.rdoc.") do |value|
- use_home = value
+ opt.on("--[no-]site",
+ "Include documentation from libraries",
+ "installed in site_lib.",
+ "Defaults to true.") do |value|
+ options[:use_site] = value
end
opt.separator nil
- opt.on("--[no-]list-names", "-l",
- "List all the names known to RDoc, one per",
- "line.") do |value|
- options[:list_names] = value
+ opt.on("--[no-]gems",
+ "Include documentation from RubyGems.",
+ "Defaults to true.") do |value|
+ options[:use_gems] = value
end
opt.separator nil
- opt.on("--no-pager", "-T",
- "Send output directly to stdout.") do |value|
- options[:use_stdout] = !value
+ opt.on("--[no-]home",
+ "Include documentation stored in ~/.rdoc.",
+ "Defaults to true.") do |value|
+ options[:use_home] = value
end
opt.separator nil
- opt.on("--[no-]site",
- "Include documentation from libraries",
- "installed in site_lib.") do |value|
- use_site = value
+ opt.on("--list-doc-dirs",
+ "List the directories from which ri will",
+ "source documentation on stdout and exit.") do
+ options[:list_doc_dirs] = true
end
opt.separator nil
- opt.on("--[no-]system",
- "Include documentation from Ruby's standard",
- "library.") do |value|
- use_system = value
+ opt.on("--no-pager", "-T",
+ "Send output directly to stdout,",
+ "rather than to a pager.") do
+ options[:use_stdout] = true
+ end
+
+ opt.on("--interactive", "-i",
+ "This makes ri go into interactive mode.",
+ "When ri is in interactive mode it will",
+ "allow the user to disambiguate lists of",
+ "methods in case multiple methods match",
+ "against a method search string. It also",
+ "will allow the user to enter in a method",
+ "name (with auto-completion, if readline",
+ "is supported) when viewing a class.") do
+ options[:interactive] = true
end
opt.separator nil
@@ -238,10 +280,10 @@ Options may also be set in the 'RI' environment variable.
options[:names] = argv
- options[:path] = RDoc::RI::Paths.path(use_system, use_site, use_home,
- use_gems, *doc_dirs)
- options[:raw_path] = RDoc::RI::Paths.raw_path(use_system, use_site,
- use_home, use_gems, *doc_dirs)
+ options[:formatter] ||= RDoc::RI::Formatter.for('plain')
+ options[:use_stdout] ||= !$stdout.tty?
+ options[:use_stdout] ||= options[:interactive]
+ options[:width] ||= 72
options
@@ -258,22 +300,30 @@ Options may also be set in the 'RI' environment variable.
ri.run
end
- def initialize(options={})
- options[:formatter] ||= RDoc::RI::Formatter.for('plain')
- options[:use_stdout] ||= !$stdout.tty?
- options[:width] ||= 72
- @names = options[:names]
+ def initialize(initial_options={})
+ options = self.class.default_options.update(initial_options)
+ @names = options[:names]
@class_cache_name = 'classes'
- @all_dirs = RDoc::RI::Paths.path(true, true, true, true)
+
+ @doc_dirs = RDoc::RI::Paths.path(options[:use_system],
+ options[:use_site],
+ options[:use_home],
+ options[:use_gems],
+ options[:extra_doc_dirs])
+
@homepath = RDoc::RI::Paths.raw_path(false, false, true, false).first
@homepath = @homepath.sub(/\.rdoc/, '.ri')
- @sys_dirs = RDoc::RI::Paths.raw_path(true, false, false, false)
+ @sys_dir = RDoc::RI::Paths.raw_path(true, false, false, false).first
+ @list_doc_dirs = options[:list_doc_dirs]
FileUtils.mkdir_p cache_file_path unless File.directory? cache_file_path
+ @cache_doc_dirs_path = File.join cache_file_path, ".doc_dirs"
+ @use_cache = options[:use_cache]
@class_cache = nil
+ @interactive = options[:interactive]
@display = RDoc::RI::DefaultDisplay.new(options[:formatter],
options[:width],
options[:use_stdout])
@@ -282,30 +332,92 @@ Options may also be set in the 'RI' environment variable.
def class_cache
return @class_cache if @class_cache
- newest = map_dirs('created.rid', :all) do |f|
+ # Get the documentation directories used to make the cache in order to see
+ # whether the cache is valid for the current ri instantiation.
+ if(File.readable?(@cache_doc_dirs_path))
+ cache_doc_dirs = IO.read(@cache_doc_dirs_path).split("\n")
+ else
+ cache_doc_dirs = []
+ end
+
+ newest = map_dirs('created.rid') do |f|
File.mtime f if test ?f, f
end.max
+ # An up to date cache file must have been created more recently than
+ # the last modification of any of the documentation directories. It also
+ # must have been created with the same documentation directories
+ # as those from which ri currently is sourcing documentation.
up_to_date = (File.exist?(class_cache_file_path) and
- newest and newest < File.mtime(class_cache_file_path))
+ newest and newest < File.mtime(class_cache_file_path) and
+ (cache_doc_dirs == @doc_dirs))
+
+ if up_to_date and @use_cache then
+ open class_cache_file_path, 'rb' do |fp|
+ begin
+ @class_cache = Marshal.load fp.read
+ rescue
+ #
+ # This shouldn't be necessary, since the up_to_date logic above
+ # should force the cache to be recreated when a new version of
+ # rdoc is installed. This seems like a worthwhile enhancement
+ # to ri's robustness, however.
+ #
+ $stderr.puts "Error reading the class cache; recreating the class cache!"
+ @class_cache = create_class_cache
+ end
+ end
+ else
+ @class_cache = create_class_cache
+ end
+
+ @class_cache
+ end
- @class_cache = if up_to_date then
- load_cache_for @class_cache_name
- else
- class_cache = RDoc::RI::Driver::Hash.new
+ def create_class_cache
+ class_cache = OpenStructHash.new
- classes = map_dirs('**/cdesc*.yaml', :sys) { |f| Dir[f] }
- populate_class_cache class_cache, classes
+ if(@use_cache)
+ # Dump the documentation directories to a file in the cache, so that
+ # we only will use the cache for future instantiations with identical
+ # documentation directories.
+ File.open @cache_doc_dirs_path, "wb" do |fp|
+ fp << @doc_dirs.join("\n")
+ end
+ end
- classes = map_dirs('**/cdesc*.yaml') { |f| Dir[f] }
- warn "Updating class cache with #{classes.size} classes..."
+ classes = map_dirs('**/cdesc*.yaml') { |f| Dir[f] }
+ warn "Updating class cache with #{classes.size} classes..."
+ populate_class_cache class_cache, classes
- populate_class_cache class_cache, classes, true
- write_cache class_cache, class_cache_file_path
- end
+ write_cache class_cache, class_cache_file_path
- @class_cache = RDoc::RI::Driver::Hash.convert @class_cache
- @class_cache
+ class_cache
+ end
+
+ def populate_class_cache(class_cache, classes, extension = false)
+ classes.each do |cdesc|
+ desc = read_yaml cdesc
+ klassname = desc["full_name"]
+
+ unless class_cache.has_key? klassname then
+ desc["display_name"] = "Class"
+ desc["sources"] = [cdesc]
+ desc["instance_method_extensions"] = []
+ desc["class_method_extensions"] = []
+ class_cache[klassname] = desc
+ else
+ klass = class_cache[klassname]
+
+ if extension then
+ desc["instance_method_extensions"] = desc.delete "instance_methods"
+ desc["class_method_extensions"] = desc.delete "class_methods"
+ end
+
+ klass.merge_enums desc
+ klass["sources"] << cdesc
+ end
+ end
end
def class_cache_file_path
@@ -322,8 +434,11 @@ Options may also be set in the 'RI' environment variable.
def display_class(name)
klass = class_cache[name]
- klass = RDoc::RI::Driver::Hash.convert klass
- @display.display_class_info klass, class_cache
+ @display.display_class_info klass
+ end
+
+ def display_method(method)
+ @display.display_method_info method
end
def get_info_for(arg)
@@ -337,48 +452,74 @@ Options may also be set in the 'RI' environment variable.
cache = nil
if File.exist? path and
- File.mtime(path) >= File.mtime(class_cache_file_path) then
+ File.mtime(path) >= File.mtime(class_cache_file_path) and
+ @use_cache then
open path, 'rb' do |fp|
- cache = Marshal.load fp.read
+ begin
+ cache = Marshal.load fp.read
+ rescue
+ #
+ # The cache somehow is bad. Recreate the cache.
+ #
+ $stderr.puts "Error reading the cache for #{klassname}; recreating the cache!"
+ cache = create_cache_for klassname, path
+ end
end
else
- class_cache = nil
+ cache = create_cache_for klassname, path
+ end
- open class_cache_file_path, 'rb' do |fp|
- class_cache = Marshal.load fp.read
- end
+ cache
+ end
- klass = class_cache[klassname]
- return nil unless klass
-
- method_files = klass["sources"]
- cache = RDoc::RI::Driver::Hash.new
-
- sys_dir = @sys_dirs.first
- method_files.each do |f|
- system_file = f.index(sys_dir) == 0
- Dir[File.join(File.dirname(f), "*")].each do |yaml|
- next unless yaml =~ /yaml$/
- next if yaml =~ /cdesc-[^\/]+yaml$/
- method = read_yaml yaml
- name = method["full_name"]
- ext_path = f
- ext_path = "gem #{$1}" if f =~ %r%gems/[\d.]+/doc/([^/]+)%
- method["source_path"] = ext_path unless system_file
- cache[name] = RDoc::RI::Driver::Hash.convert method
+ def create_cache_for(klassname, path)
+ klass = class_cache[klassname]
+ return nil unless klass
+
+ method_files = klass["sources"]
+ cache = OpenStructHash.new
+
+ method_files.each do |f|
+ system_file = f.index(@sys_dir) == 0
+ Dir[File.join(File.dirname(f), "*")].each do |yaml|
+ next unless yaml =~ /yaml$/
+ next if yaml =~ /cdesc-[^\/]+yaml$/
+
+ method = read_yaml yaml
+
+ if system_file then
+ method["source_path"] = "Ruby #{RDoc::RI::Paths::VERSION}"
+ else
+ if(f =~ %r%gems/[\d.]+/doc/([^/]+)%) then
+ ext_path = "gem #{$1}"
+ else
+ ext_path = f
+ end
+
+ method["source_path"] = ext_path
end
- end
- write_cache cache, path
+ name = method["full_name"]
+ cache[name] = method
+ end
end
- RDoc::RI::Driver::Hash.convert cache
+ write_cache cache, path
end
##
# Finds the next ancestor of +orig_klass+ after +klass+.
def lookup_ancestor(klass, orig_klass)
+ # This is a bit hacky, but ri will go into an infinite
+ # loop otherwise, since Object has an Object ancestor
+ # for some reason. Depending on the documentation state, I've seen
+ # Kernel as an ancestor of Object and not as an ancestor of Object.
+ if ((orig_klass == "Object") &&
+ ((klass == "Kernel") || (klass == "Object")))
+ return nil
+ end
+
cache = class_cache[orig_klass]
return nil unless cache
@@ -386,10 +527,13 @@ Options may also be set in the 'RI' environment variable.
ancestors = [orig_klass]
ancestors.push(*cache.includes.map { |inc| inc['name'] })
ancestors << cache.superclass
+
+ ancestor_index = ancestors.index(klass)
- ancestor = ancestors[ancestors.index(klass) + 1]
-
- return ancestor if ancestor
+ if ancestor_index
+ ancestor = ancestors[ancestors.index(klass) + 1]
+ return ancestor if ancestor
+ end
lookup_ancestor klass, cache.superclass
end
@@ -406,18 +550,8 @@ Options may also be set in the 'RI' environment variable.
method
end
- def map_dirs(file_name, system=false)
- dirs = if system == :all then
- @all_dirs
- else
- if system then
- @sys_dirs
- else
- @all_dirs - @sys_dirs
- end
- end
-
- dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
+ def map_dirs(file_name)
+ @doc_dirs.map { |dir| yield File.join(dir, file_name) }.flatten.compact
end
##
@@ -436,83 +570,66 @@ Options may also be set in the 'RI' environment variable.
[klass, meth]
end
- def populate_class_cache(class_cache, classes, extension = false)
- classes.each do |cdesc|
- desc = read_yaml cdesc
- klassname = desc["full_name"]
-
- unless class_cache.has_key? klassname then
- desc["display_name"] = "Class"
- desc["sources"] = [cdesc]
- desc["instance_method_extensions"] = []
- desc["class_method_extensions"] = []
- class_cache[klassname] = desc
- else
- klass = class_cache[klassname]
-
- if extension then
- desc["instance_method_extensions"] = desc.delete "instance_methods"
- desc["class_method_extensions"] = desc.delete "class_methods"
- end
-
- klass = RDoc::RI::Driver::Hash.convert klass
-
- klass.merge_enums desc
- klass["sources"] << cdesc
- end
- end
- end
-
def read_yaml(path)
data = File.read path
+
+ # Necessary to be backward-compatible with documentation generated
+ # by earliar RDoc versions.
data = data.gsub(/ \!ruby\/(object|struct):(RDoc::RI|RI).*/, '')
data = data.gsub(/ \!ruby\/(object|struct):SM::(\S+)/,
' !ruby/\1:RDoc::Markup::\2')
- YAML.load data
+ OpenStructHash.convert(YAML.load(data))
end
def run
- if @names.empty? then
+ if(@list_doc_dirs)
+ puts @doc_dirs.join("\n")
+ elsif @names.empty? then
@display.list_known_classes class_cache.keys.sort
else
@names.each do |name|
- case name
- when /::|\#|\./ then
- if class_cache.key? name then
- display_class name
- else
- klass, = parse_name name
+ if class_cache.key? name then
+ method_map = display_class name
+ if(@interactive)
+ method_name = @display.get_class_method_choice(method_map)
+
+ if(method_name != nil)
+ method = lookup_method "#{name}#{method_name}", name
+ display_method method
+ end
+ end
+ elsif name =~ /::|\#|\./ then
+ klass, = parse_name name
- orig_klass = klass
- orig_name = name
+ orig_klass = klass
+ orig_name = name
- until klass == 'Kernel' do
- method = lookup_method name, klass
+ loop do
+ method = lookup_method name, klass
- break method if method
+ break method if method
- ancestor = lookup_ancestor klass, orig_klass
+ ancestor = lookup_ancestor klass, orig_klass
- break unless ancestor
+ break unless ancestor
- name = name.sub klass, ancestor
- klass = ancestor
- end
+ name = name.sub klass, ancestor
+ klass = ancestor
+ end
- raise NotFoundError, orig_name unless method
+ raise NotFoundError, orig_name unless method
- @display.display_method_info method
- end
+ display_method method
else
- if class_cache.key? name then
- display_class name
- else
- methods = select_methods(/^#{name}/)
+ methods = select_methods(/#{name}/)
- if methods.size == 0
- raise NotFoundError, name
- elsif methods.size == 1
- @display.display_method_info methods.first
+ if methods.size == 0
+ raise NotFoundError, name
+ elsif methods.size == 1
+ display_method methods[0]
+ else
+ if(@interactive)
+ @display.display_method_list_choice methods
else
@display.display_method_list methods
end
@@ -540,12 +657,13 @@ Options may also be set in the 'RI' environment variable.
end
def write_cache(cache, path)
- File.open path, "wb" do |cache_file|
- Marshal.dump cache, cache_file
+ if(@use_cache)
+ File.open path, "wb" do |cache_file|
+ Marshal.dump cache, cache_file
+ end
end
cache
end
end
-
diff --git a/lib/rdoc/ri/formatter.rb b/lib/rdoc/ri/formatter.rb
index 0a0c3f73802..933882abc4f 100644
--- a/lib/rdoc/ri/formatter.rb
+++ b/lib/rdoc/ri/formatter.rb
@@ -93,7 +93,7 @@ class RDoc::RI::Formatter
end
def raw_print_line(txt)
- @output.puts txt
+ @output.print txt
end
##
diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
index b4b6c64925c..2f72b9dfd5b 100644
--- a/lib/rdoc/ri/paths.rb
+++ b/lib/rdoc/ri/paths.rb
@@ -26,9 +26,9 @@ module RDoc::RI::Paths
DOC_DIR = "doc/rdoc"
- version = RbConfig::CONFIG['ruby_version']
+ VERSION = RbConfig::CONFIG['ruby_version']
- base = File.join(RbConfig::CONFIG['datadir'], "ri", version)
+ base = File.join(RbConfig::CONFIG['datadir'], "ri", VERSION)
SYSDIR = File.join(base, "system")
SITEDIR = File.join(base, "site")
homedir = ENV['HOME'] || ENV['USERPROFILE'] || ENV['HOMEPATH']
@@ -39,9 +39,6 @@ module RDoc::RI::Paths
HOMEDIR = nil
end
- # This is the search path for 'ri'
- PATH = [ SYSDIR, SITEDIR, HOMEDIR ].find_all {|p| p && File.directory?(p)}
-
begin
require 'rubygems' unless defined?(Gem) and defined?(Gem::Enable) and
Gem::Enable
@@ -67,7 +64,6 @@ module RDoc::RI::Paths
end
GEMDIRS = ri_paths.map { |k,v| v.last }.sort
- GEMDIRS.each { |dir| PATH << dir }
rescue LoadError
GEMDIRS = []
end
@@ -85,9 +81,6 @@ module RDoc::RI::Paths
# found.
def self.raw_path(use_system, use_site, use_home, use_gems, *extra_dirs)
- return PATH unless use_system or use_site or use_home or use_gems or
- not extra_dirs.empty?
-
path = []
path << extra_dirs unless extra_dirs.empty?
path << SYSDIR if use_system
@@ -97,6 +90,4 @@ module RDoc::RI::Paths
return path.flatten.compact
end
-
end
-
diff --git a/lib/rdoc/ri/reader.rb b/lib/rdoc/ri/reader.rb
index 986bb75954f..de3c8d9afad 100644
--- a/lib/rdoc/ri/reader.rb
+++ b/lib/rdoc/ri/reader.rb
@@ -45,7 +45,7 @@ class RDoc::RI::Reader
def get_method(method_entry)
path = method_entry.path_name
- File.open(path) { |f| RI::Description.deserialize(f) }
+ File.open(path) { |f| RDoc::RI::Description.deserialize(f) }
end
##
@@ -54,8 +54,8 @@ class RDoc::RI::Reader
def get_class(class_entry)
result = nil
for path in class_entry.path_names
- path = RiWriter.class_desc_path(path, class_entry)
- desc = File.open(path) {|f| RI::Description.deserialize(f) }
+ path = RDoc::RI::Writer.class_desc_path(path, class_entry)
+ desc = File.open(path) {|f| RDoc::RI::Description.deserialize(f) }
if result
result.merge_in(desc)
else
diff --git a/lib/rdoc/ri/util.rb b/lib/rdoc/ri/util.rb
index 34277f2594c..4e91eb978d3 100644
--- a/lib/rdoc/ri/util.rb
+++ b/lib/rdoc/ri/util.rb
@@ -1,7 +1,5 @@
require 'rdoc/ri'
-class RDoc::RI::Error < RuntimeError; end
-
##
# Break argument into its constituent class or module names, an
# optional method type, and a method name
diff --git a/test/rdoc/binary.dat b/test/rdoc/binary.dat
new file mode 100644
index 00000000000..371950efe69
--- /dev/null
+++ b/test/rdoc/binary.dat
Binary files differ
diff --git a/test/rdoc/rdoc_markup_to_html_crossref_reference.rb b/test/rdoc/rdoc_markup_to_html_crossref_reference.rb
new file mode 100644
index 00000000000..cbf6734b283
--- /dev/null
+++ b/test/rdoc/rdoc_markup_to_html_crossref_reference.rb
@@ -0,0 +1,31 @@
+#
+# This file is parsed by test_rdoc_markup_to_html_crossref.rb
+# during its tests.
+#
+class Ref_Class1
+end
+
+class Ref_Class2
+ class Ref_Class3
+ def method
+ end
+
+ class Helper1
+ def method?
+ end
+ end
+ end
+end
+
+class Ref_Class3
+ class Helper1
+ end
+
+ class Helper2
+ end
+end
+
+class Ref_Class4
+ class Ref_Class4
+ end
+end
diff --git a/test/rdoc/test_attribute_manager.rb b/test/rdoc/test_attribute_manager.rb
new file mode 100644
index 00000000000..298eca01410
--- /dev/null
+++ b/test/rdoc/test_attribute_manager.rb
@@ -0,0 +1,73 @@
+require 'test/unit'
+require 'rdoc/markup/attribute_manager'
+
+class TestAttributeManager < Test::Unit::TestCase
+
+ def setup
+ @am = RDoc::Markup::AttributeManager.new
+ @klass = RDoc::Markup::AttributeManager
+ end
+
+ def teardown
+ silently do
+ @klass.const_set(:MATCHING_WORD_PAIRS, {})
+ @klass.const_set(:WORD_PAIR_MAP, {})
+ @klass.const_set(:HTML_TAGS, {})
+ end
+ end
+
+ def test_initial_word_pairs
+ word_pairs = @klass::MATCHING_WORD_PAIRS
+ assert word_pairs.is_a?(Hash)
+ assert_equal(3, word_pairs.size)
+ end
+
+ def test_initial_html
+ html_tags = @klass::HTML_TAGS
+ assert html_tags.is_a?(Hash)
+ assert_equal(5, html_tags.size)
+ end
+
+ def test_add_matching_word_pair
+ @am.add_word_pair("x","x", :TEST)
+ word_pairs = @klass::MATCHING_WORD_PAIRS
+ assert_equal(4,word_pairs.size)
+ assert(word_pairs.has_key?("x"))
+ end
+
+ def test_add_invalid_word_pair
+ assert_raise ArgumentError do
+ @am.add_word_pair("<", "<", :TEST)
+ end
+ end
+
+ def test_add_word_pair_map
+ @am.add_word_pair("x", "y", :TEST)
+ word_pair_map = @klass::WORD_PAIR_MAP
+ assert_equal(1,word_pair_map.size)
+ assert_equal(word_pair_map. keys.first.source, "(x)(\\S+)(y)")
+ end
+
+ def test_add_html_tag
+ @am.add_html("Test", :TEST)
+ tags = @klass::HTML_TAGS
+ assert_equal(6, tags.size)
+ assert(tags.has_key?("test"))
+ end
+
+ def test_add_special
+ @am.add_special("WikiWord", :WIKIWORD)
+ specials = @klass::SPECIAL
+ assert_equal(1,specials.size)
+ assert(specials.has_key?("WikiWord"))
+ end
+
+ def silently(&block)
+ warn_level = $VERBOSE
+ $VERBOSE = nil
+ result = block.call
+ $VERBOSE = warn_level
+ result
+ end
+
+end
diff --git a/test/rdoc/test_rdoc_info_formatting.rb b/test/rdoc/test_rdoc_info_formatting.rb
index 6c024f74544..b18cdf2931b 100644
--- a/test/rdoc/test_rdoc_info_formatting.rb
+++ b/test/rdoc/test_rdoc_info_formatting.rb
@@ -5,7 +5,7 @@ require 'test/unit'
require 'rdoc/generator/texinfo'
# From chapter 18 of the Pickaxe 3rd ed. and the TexInfo manual.
-class TestRdocInfoFormatting < Test::Unit::TestCase
+class TestRDocInfoFormatting < Test::Unit::TestCase
def setup
@output_dir = File.join Dir.tmpdir, "test_rdoc_info_formatting_#{$$}"
@output_file = File.join @output_dir, 'rdoc.texinfo'
@@ -19,7 +19,7 @@ class TestRdocInfoFormatting < Test::Unit::TestCase
end
def teardown
- FileUtils.rm_rf @output_dir
+ # FileUtils.rm_rf @output_dir
end
# Make sure tags like *this* do not make HTML
@@ -73,10 +73,10 @@ class TestRdocInfoFormatting < Test::Unit::TestCase
# === Everything deeper becomes a regular @heading
# ====== Regardless of its nesting level
def test_headings
- assert_match(/@majorheading\{Huge heading should be a @@majorheading\}/)
- assert_match(/@chapheading\{There is also @@chapheading\}/)
- assert_match(/@heading\{Everything deeper becomes a regular @@heading\}/)
- assert_match(/@heading\{Regardless of its nesting level\}/)
+ assert_match(/@majorheading Huge heading should be a @@majorheading/)
+ assert_match(/@chapheading There is also @@chapheading/)
+ assert_match(/@heading Everything deeper becomes a regular @@heading/)
+ assert_match(/@heading Regardless of its nesting level/)
end
# * list item
diff --git a/test/rdoc/test_rdoc_info_sections.rb b/test/rdoc/test_rdoc_info_sections.rb
index cceba186c14..6825d37a7d0 100644
--- a/test/rdoc/test_rdoc_info_sections.rb
+++ b/test/rdoc/test_rdoc_info_sections.rb
@@ -6,10 +6,10 @@ require 'tmpdir'
require 'rdoc/generator/texinfo'
# give us access to check this stuff before it's rendered
-class RDoc::Generator::Texinfo; attr_reader :files, :classes; end
+class RDoc::Generator::TEXINFO; attr_reader :files, :classes; end
class RDoc::RDoc; attr_reader :options; attr_reader :gen; end
-class TestRdocInfoSections < Test::Unit::TestCase
+class TestRDocInfoSections < Test::Unit::TestCase
def setup
@output_dir = File.join Dir.tmpdir, "test_rdoc_info_sections_#{$$}"
diff --git a/test/rdoc/test_rdoc_markup_attribute_manager.rb b/test/rdoc/test_rdoc_markup_attribute_manager.rb
index 8ba9d7440a1..eea87822a8d 100644
--- a/test/rdoc/test_rdoc_markup_attribute_manager.rb
+++ b/test/rdoc/test_rdoc_markup_attribute_manager.rb
@@ -1,5 +1,6 @@
require "test/unit"
require "rdoc/markup/inline"
+require "rdoc/markup/to_html_crossref"
class TestRDocMarkupAttributeManager < Test::Unit::TestCase
@@ -201,24 +202,23 @@ class TestRDocMarkupAttributeManager < Test::Unit::TestCase
end
def test_special
- # class names, variable names, file names, or instance variables
- @am.add_special(/(
- \b([A-Z]\w+(::\w+)*)
- | \#\w+[!?=]?
- | \b\w+([_\/\.]+\w+)+[!?=]?
- )/x,
- :CROSSREF)
+ @am.add_special(RDoc::Markup::ToHtmlCrossref::CROSSREF_REGEXP, :CROSSREF)
- assert_equal(["cat"], @am.flow("cat"))
+ #
+ # The apostrophes in "cats'" and "dogs'" suppress the flagging of these
+ # words as potential cross-references, which is necessary for the unit
+ # tests. Unfortunately, the markup engine right now does not actually
+ # check whether a cross-reference is valid before flagging it.
+ #
+ assert_equal(["cats'"], @am.flow("cats'"))
- assert_equal(["cat ", crossref("#fred"), " dog"].flatten,
- @am.flow("cat #fred dog"))
+ assert_equal(["cats' ", crossref("#fred"), " dogs'"].flatten,
+ @am.flow("cats' #fred dogs'"))
- assert_equal([crossref("#fred"), " dog"].flatten,
- @am.flow("#fred dog"))
+ assert_equal([crossref("#fred"), " dogs'"].flatten,
+ @am.flow("#fred dogs'"))
- assert_equal(["cat ", crossref("#fred")].flatten, @am.flow("cat #fred"))
+ assert_equal(["cats' ", crossref("#fred")].flatten, @am.flow("cats' #fred"))
end
end
-
diff --git a/test/rdoc/test_rdoc_markup_to_html.rb b/test/rdoc/test_rdoc_markup_to_html.rb
index 463228cc4ad..05fb9f23758 100644
--- a/test/rdoc/test_rdoc_markup_to_html.rb
+++ b/test/rdoc/test_rdoc_markup_to_html.rb
@@ -2,7 +2,7 @@ require 'test/unit'
require 'rdoc/markup'
require 'rdoc/markup/to_html'
-class TestRdocMarkupToHtml < Test::Unit::TestCase
+class TestRDocMarkupToHtml < Test::Unit::TestCase
def setup
@am = RDoc::Markup::AttributeManager.new
@@ -10,11 +10,23 @@ class TestRdocMarkupToHtml < Test::Unit::TestCase
end
def test_tt_formatting
- assert_equal "<p>\n<tt>--</tt> &#8212; <tt>(c)</tt> &#169;\n</p>\n",
- util_format("<tt>--</tt> -- <tt>(c)</tt> (c)")
+ assert_equal "<p>\n<tt>--</tt> &#8212; <tt>cats'</tt> cats&#8217;\n</p>\n",
+ util_format("<tt>--</tt> -- <tt>cats'</tt> cats'")
assert_equal "<p>\n<b>&#8212;</b>\n</p>\n", util_format("<b>--</b>")
end
+ def test_convert_string_fancy
+ #
+ # The HTML typesetting is broken in a number of ways, but I have fixed
+ # the most glaring issues for single and double quotes. Note that
+ # "strange" symbols (periods or dashes) need to be at the end of the
+ # test case strings in order to suppress cross-references.
+ #
+ assert_equal "<p>\n&#8220;cats&#8221;.\n</p>\n", util_format("\"cats\".")
+ assert_equal "<p>\n&#8216;cats&#8217;.\n</p>\n", util_format("\'cats\'.")
+ assert_equal "<p>\ncat&#8217;s-\n</p>\n", util_format("cat\'s-")
+ end
+
def util_fragment(text)
RDoc::Markup::Fragment.new 0, nil, nil, text
end
diff --git a/test/rdoc/test_rdoc_markup_to_html_crossref.rb b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
index ab4c3e7e9c4..de99a58b751 100644
--- a/test/rdoc/test_rdoc_markup_to_html_crossref.rb
+++ b/test/rdoc/test_rdoc_markup_to_html_crossref.rb
@@ -2,17 +2,287 @@ require 'test/unit'
require 'rdoc/generator'
require 'rdoc/markup/to_html_crossref'
-class TestRdocMarkupToHtmlCrossref < Test::Unit::TestCase
+require 'pathname'
- def setup
- @xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', nil, nil
+class TestRDocMarkupToHtmlCrossref < Test::Unit::TestCase
+
+ #
+ # This method parses a source file and returns a Hash mapping
+ # class names (Strings) to RDoc::Generator::Class instances
+ # (classes), which can be used to create RDoc::Markup::ToHtmlCrossref
+ # instances. The unit tests only test against classes starting with
+ # Ref_, so this method only includes such classes in the Hash.
+ #
+ def create_class_hash
+ # The relative gem would help here...
+ # @source_file_name must be cleaned because rdoc does not deal
+ # well with paths containing "." or "..".
+ curr_file = Pathname.new(__FILE__)
+ @source_file_name = curr_file.dirname + "rdoc_markup_to_html_crossref_reference.rb"
+ @source_file_name = @source_file_name.cleanpath.to_s
+
+ RDoc::TopLevel.reset
+
+ # Reset RDoc::Generator::Method so that the method sequence number starts
+ # at 1, making the method sequence numbers for the methods in the Ref_
+ # predicable.
+ RDoc::Generator::Method.reset
+ top_level = RDoc::TopLevel.new @source_file_name
+
+ options = RDoc::Options.new
+ options.quiet = true
+
+ # If this is false, then RDoc::Generator::Method will attempt to create
+ # an HTML file containing the method source code when being instantiated,
+ # which does not work in the context of this unit test.
+ #
+ # RDoc::Generator::Method needs to be refactored so that this does *not*
+ # happen as part of instantiation.
+ options.inline_source = true
+
+ stats = RDoc::Stats.new 0
+
+ parser = RDoc::Parser::Ruby.new(top_level,
+ @source_file_name,
+ IO.read(@source_file_name),
+ options,
+ stats)
+ top_levels = []
+ top_levels.push(parser.scan())
+
+ files, classes = RDoc::Generator::Context.build_indices(top_levels, options)
+
+ class_hash = {}
+ classes.each do |klass|
+ if(klass.name.include?("Ref_"))
+ class_hash[klass.name] = klass
+ end
+ end
+
+ return class_hash
end
- def test_handle_special_CROSSREF_no_underscore
- out = @xref.convert 'foo'
+ #
+ # This method uses xref to cross-reference String reference and
+ # asserts that xref.convert(reference) is equal
+ # to String expected_result.
+ #
+ def verify_convert(xref, reference, expected_result)
+ # Everything converted in the tests will be within paragraph markup, so
+ # add paragraph markup to the expected result.
+ actual_expected_result = "<p>\n#{expected_result}\n</p>\n"
+
+ result = xref.convert(reference)
+
+ # RDoc::Markup::ToHtml word-wraps lines. It is tricky to predict where
+ # a line will be wrapped except that it will happen on a space, so replace
+ # all newlines with spaces in order to not have to worry about this.
+ actual_expected_result.gsub!(/\n/, " ")
+ result.gsub!(/\n/, " ")
- assert_equal "<p>\nfoo\n</p>\n", out
+ assert_equal actual_expected_result, result
end
-end
+ #
+ # This method verifies that xref generates no cross-reference link for
+ # String reference.
+ #
+ def verify_no_crossref(xref, reference)
+ if(reference[0, 1] == "\\") # Remove the markup suppression character
+ expected_result = reference[1, reference.length() - 1]
+ else
+ expected_result = reference
+ end
+
+ verify_convert(xref, reference, expected_result)
+ end
+
+ #
+ # This method verifies that xref generates a cross-reference link to
+ # class_name (String) for String reference.
+ #
+ def verify_class_crossref(xref, reference, class_name)
+ class_file_name = class_name.gsub(/::/, "/")
+
+ result = "<a href=\"../classes/#{class_file_name}.html\">#{reference}</a>"
+
+ verify_convert xref, reference, result
+ end
+ #
+ # This method verifies that xref generates a cross-reference link to method
+ # method_seq (String, e.g, "M000001") in class_name (String) for
+ # String reference.
+ #
+ def verify_method_crossref(xref, reference, class_name, method_seq)
+ class_file_name = class_name.gsub(/::/, "/")
+
+ result = "<a href=\"../classes/#{class_file_name}.html##{method_seq}\">#{reference}</a>"
+
+ verify_convert xref, reference, result
+ end
+
+ #
+ # This method verifies that xref generates a cross-reference link to
+ # file_name (String) for String reference.
+ #
+ def verify_file_crossref(xref, reference, file_name)
+ generated_document_path = Pathname.new("../files/#{file_name.gsub(/\./, '_')}.html").cleanpath.to_s
+ result = "<a href=\"#{generated_document_path}\">#{reference}</a>"
+
+ verify_convert xref, reference, result
+ end
+
+ #
+ # This method verifies that several invariant cross-references are
+ # (or are not) generated.
+ #
+ def verify_invariant_crossrefs(xref)
+ # bogus does not exist and so no cross-reference should be generated.
+ verify_no_crossref xref, "bogus"
+ verify_no_crossref xref, "\\bogus"
+
+ # Ref_Class1 is in the top-level namespace, and so a cross-reference always
+ # should be generated, unless markup is suppressed.
+ verify_class_crossref xref, "Ref_Class1", "Ref_Class1"
+ verify_no_crossref xref, "\\Ref_Class1"
+
+ # Ref_Class2 is in the top-level namespace, and so a cross-reference always
+ # should be generated for it and for its nested classes.
+ verify_class_crossref xref, "Ref_Class2", "Ref_Class2"
+ verify_class_crossref xref, "Ref_Class2::Ref_Class3", "Ref_Class2::Ref_Class3"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3#method()", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3.method()", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3.method(*)", "Ref_Class2::Ref_Class3", "M000001"
+ verify_class_crossref xref, "Ref_Class2::Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_method_crossref xref, "Ref_Class2::Ref_Class3::Helper1#method?", "Ref_Class2::Ref_Class3::Helper1", "M000002"
+
+ # The hyphen character is not a valid class/method separator character, so
+ # rdoc just generates a class cross-reference (perhaps it should not
+ # generate anything?).
+ result = "<a href=\"../classes/Ref_Class2/Ref_Class3.html\">Ref_Class2::Ref_Class3</a>;method(*)"
+ verify_convert xref, "Ref_Class2::Ref_Class3;method(*)", result
+
+ # There is one Ref_Class3 nested in Ref_Class2 and one defined in the
+ # top-level namespace; regardless, ::Ref_Class3 (Ref_Class3 relative
+ # to the top-level namespace) always should generate a link to the
+ # top-level Ref_Class3 (unless of course cross-references are suppressed).
+ verify_class_crossref xref, "::Ref_Class3", "Ref_Class3"
+ verify_no_crossref xref, "\\::Ref_Class3"
+ verify_class_crossref xref, "::Ref_Class3::Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "::Ref_Class3::Helper2", "Ref_Class3::Helper2"
+
+ #
+ # Ref_Class3::Helper1 does not have method method.
+ #
+ verify_no_crossref xref, "::Ref_Class3::Helper1#method"
+ verify_no_crossref xref, "\\::Ref_Class3::Helper1#method"
+
+ # References to Ref_Class2 relative to the top-level namespace always should
+ # generate links to Ref_Class2.
+ verify_method_crossref xref, "::Ref_Class2::Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "::Ref_Class2::Ref_Class3#method()", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "::Ref_Class2::Ref_Class3#method(*)", "Ref_Class2::Ref_Class3", "M000001"
+ verify_class_crossref xref, "::Ref_Class2::Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_no_crossref xref, "\\::Ref_Class2::Ref_Class3#method(*)"
+
+ # Suppressing cross-references always should suppress the generation of
+ # links.
+ verify_no_crossref xref, "\\#method"
+ verify_no_crossref xref, "\\#method()"
+ verify_no_crossref xref, "\\#method(*)"
+
+ # Links never should be generated for words solely consisting of lowercase
+ # letters, because too many links would get generated by mistake (i.e., the
+ # word "new" always would be a link).
+ verify_no_crossref xref, "method"
+
+ # A link always should be generated for a file name.
+ verify_file_crossref xref, @source_file_name, @source_file_name
+
+ # References should be generated correctly for a class scoped within
+ # a class of the same name.
+ verify_class_crossref xref, "Ref_Class4::Ref_Class4", "Ref_Class4::Ref_Class4"
+ end
+
+ def test_handle_special_CROSSREF_no_underscore
+ class_hash = create_class_hash
+
+ # Note that we instruct the ToHtmlCrossref instance to show hashes so that
+ # an exception won't have to be made for words starting with a '#'.
+ # I'm also not convinced that the current behavior of the rdoc code
+ # is correct since, without this, it strips the leading # from all
+ # words, whether or not they end up as cross-references.
+ #
+ # After the behavior has been sorted out, this can be changed.
+ #
+ # Create a variety of RDoc::Markup::ToHtmlCrossref instances, for
+ # different classes, and test the cross-references generated by
+ # each.
+ klass = class_hash["Ref_Class1"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class3"
+ verify_no_crossref xref, "Ref_Class3#method"
+ verify_no_crossref xref, "#method"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class3::Helper2", "Ref_Class3::Helper2"
+ verify_no_crossref xref, "Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ klass = class_hash["Ref_Class2"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class2::Ref_Class3"
+ verify_method_crossref xref, "Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_no_crossref xref, "#method"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ # This one possibly is an rdoc bug...
+ # Ref_Class2 has a nested Ref_Class3, but
+ # Ref_Class2::Ref_Class3::Helper2 does not exist.
+ # On the other hand, there is a Ref_Class3::Helper2
+ # in the top-level namespace... Should rdoc stop
+ # looking if it finds one class match?
+ verify_no_crossref xref, "Ref_Class3::Helper2"
+ verify_no_crossref xref, "Helper1"
+
+ klass = class_hash["Ref_Class2::Ref_Class3"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class2::Ref_Class3"
+ verify_method_crossref xref, "Ref_Class3#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_method_crossref xref, "#method", "Ref_Class2::Ref_Class3", "M000001"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_no_crossref xref, "Ref_Class3::Helper2"
+ verify_class_crossref xref, "Helper1", "Ref_Class2::Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ klass = class_hash["Ref_Class3"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ verify_class_crossref xref, "Ref_Class3", "Ref_Class3"
+ verify_no_crossref xref, "Ref_Class3#method"
+ verify_no_crossref xref, "#method"
+ verify_class_crossref xref, "Ref_Class3::Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class3::Helper2", "Ref_Class3::Helper2"
+ verify_class_crossref xref, "Helper1", "Ref_Class3::Helper1"
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4"
+
+ klass = class_hash["Ref_Class4"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ # A Ref_Class4 reference inside a Ref_Class4 class containing a
+ # Ref_Class4 class should resolve to the contained class.
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4::Ref_Class4"
+
+ klass = class_hash["Ref_Class4::Ref_Class4"]
+ xref = RDoc::Markup::ToHtmlCrossref.new 'from_path', klass, true
+ verify_invariant_crossrefs xref
+ # A Ref_Class4 reference inside a Ref_Class4 class contained within
+ # a Ref_Class4 class should resolve to the inner Ref_Class4 class.
+ verify_class_crossref xref, "Ref_Class4", "Ref_Class4::Ref_Class4"
+ end
+end
diff --git a/test/rdoc/test_rdoc_parser.rb b/test/rdoc/test_rdoc_parser.rb
new file mode 100644
index 00000000000..4f71974a5f1
--- /dev/null
+++ b/test/rdoc/test_rdoc_parser.rb
@@ -0,0 +1,18 @@
+require 'rdoc/parser'
+
+class TestRDocParser < Test::Unit::TestCase
+ def test_can_parse
+ assert_equal(RDoc::Parser.can_parse(__FILE__), RDoc::Parser::Ruby)
+
+ readme_file_name = File.join(File.dirname(__FILE__), "..", "README.txt")
+
+ unless File.exist? readme_file_name then
+ readme_file_name = File.join File.dirname(__FILE__), '..', '..', 'README'
+ end
+
+ assert_equal(RDoc::Parser.can_parse(readme_file_name), RDoc::Parser::Simple)
+
+ binary_file_name = File.join(File.dirname(__FILE__), "binary.dat")
+ assert_equal(RDoc::Parser.can_parse(binary_file_name), nil)
+ end
+end
diff --git a/test/rdoc/test_rdoc_parser_c.rb b/test/rdoc/test_rdoc_parser_c.rb
index fd750070d8e..9387a030c0e 100644
--- a/test/rdoc/test_rdoc_parser_c.rb
+++ b/test/rdoc/test_rdoc_parser_c.rb
@@ -10,7 +10,7 @@ class RDoc::Parser::C
public :do_classes, :do_constants
end
-class TestRdocParserC < Test::Unit::TestCase
+class TestRDocParserC < Test::Unit::TestCase
def setup
@tempfile = Tempfile.new self.class.name
@@ -244,9 +244,36 @@ Init_Foo(void) {
assert_equal " \n a comment for class Foo on Init\n \n", klass.comment
end
+ def test_define_method
+ content = <<-EOF
+/*Method Comment! */
+static VALUE
+rb_io_s_read(argc, argv, io)
+ int argc;
+ VALUE *argv;
+ VALUE io;
+{
+}
+
+void
+Init_IO(void) {
+ /*
+ * a comment for class Foo on rb_define_class
+ */
+ VALUE rb_cIO = rb_define_class("IO", rb_cObject);
+ rb_define_singleton_method(rb_cIO, "read", rb_io_s_read, -1);
+}
+ EOF
+
+ klass = util_get_class content, 'rb_cIO'
+ read_method = klass.method_list.first
+ assert_equal "read", read_method.name
+ assert_equal " Method Comment! \n", read_method.comment
+ end
+
def util_get_class(content, name)
parser = util_parser content
- parser.do_classes
+ parser.scan
parser.classes[name]
end
diff --git a/test/rdoc/test_rdoc_parser_perl.rb b/test/rdoc/test_rdoc_parser_perl.rb
new file mode 100644
index 00000000000..458e32745e8
--- /dev/null
+++ b/test/rdoc/test_rdoc_parser_perl.rb
@@ -0,0 +1,72 @@
+require 'stringio'
+require 'tempfile'
+require 'test/unit'
+require 'rdoc/options'
+require 'rdoc/parser/perl'
+
+class TestRdocParserPerlPOD < Test::Unit::TestCase
+
+ def setup
+ @tempfile = Tempfile.new self.class.name
+ filename = @tempfile.path
+
+ @top_level = RDoc::TopLevel.new filename
+ @fn = filename
+ @options = RDoc::Options.new
+ @stats = RDoc::Stats.new 0
+ end
+
+ def teardown
+ @tempfile.close
+ end
+
+ def test_uncommented_perl
+ content = <<-EOF
+while (<>) {
+ tr/a-z/A-Z;
+ print
+}
+ EOF
+
+ comment = util_get_comment content
+ assert_equal "", comment
+ end
+
+ def test_perl_without_pod
+ content = <<-EOF
+#!/usr/local/bin/perl
+#
+#This is a pointless perl program because it does -p.
+#
+while(<>) {print;}:
+ EOF
+
+ comment = util_get_comment content
+ assert_equal "", comment
+ end
+
+ def test_simple_pod_no_structure
+ content = <<-EOF
+=begin pod
+
+This just contains plain old documentation
+
+=end
+ EOF
+ comment = util_get_comment content
+ assert_equal "\nThis just contains plain old documentation\n\n", comment
+ end
+
+ # Get the comment of the @top_level when it has processed the input.
+ def util_get_comment(content)
+ parser = util_parser content
+ parser.scan.comment
+ end
+
+ # create a new parser with the supplied content.
+ def util_parser(content)
+ RDoc::Parser::PerlPOD.new @top_level, @fn, content, @options, @stats
+ end
+
+end
+
diff --git a/test/rdoc/test_rdoc_parser_ruby.rb b/test/rdoc/test_rdoc_parser_ruby.rb
index 77d8bd24fc8..30ab3f84f59 100644
--- a/test/rdoc/test_rdoc_parser_ruby.rb
+++ b/test/rdoc/test_rdoc_parser_ruby.rb
@@ -6,12 +6,16 @@ require 'rdoc/options'
require 'rdoc/parser/ruby'
require 'rdoc/stats'
-class TestRdocParserRuby < Test::Unit::TestCase
+class TestRDocParserRuby < Test::Unit::TestCase
def setup
@tempfile = Tempfile.new self.class.name
@filename = @tempfile.path
+ # Some tests need two paths.
+ @tempfile2 = Tempfile.new self.class.name
+ @filename2 = @tempfile2.path
+
util_toplevel
@options = RDoc::Options.new
@options.quiet = true
@@ -20,6 +24,7 @@ class TestRdocParserRuby < Test::Unit::TestCase
def teardown
@tempfile.close
+ @tempfile2.close
end
def test_look_for_directives_in_commented
@@ -158,6 +163,105 @@ class TestRdocParserRuby < Test::Unit::TestCase
assert_equal 'Super', bar.superclass
end
+ def test_parse_module
+ comment = "##\n# my module\n"
+
+ util_parser 'module Foo; end'
+
+ tk = @parser.get_tk
+
+ @parser.parse_module @top_level, RDoc::Parser::Ruby::NORMAL, tk, comment
+
+ foo = @top_level.modules.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal comment, foo.comment
+ end
+
+ def test_parse_class_mistaken_for_module
+#
+# The code below is not strictly legal Ruby (Foo must have been defined
+# before Foo::Bar is encountered), but RDoc might encounter Foo::Bar before
+# Foo if they live in different files.
+#
+ code = <<-EOF
+class Foo::Bar
+end
+
+module Foo::Baz
+end
+
+class Foo
+end
+EOF
+
+ util_parser code
+
+ @parser.scan()
+
+ assert(@top_level.modules.empty?)
+ foo = @top_level.classes.first
+ assert_equal 'Foo', foo.full_name
+
+ bar = foo.classes.first
+ assert_equal 'Foo::Bar', bar.full_name
+
+ baz = foo.modules.first
+ assert_equal 'Foo::Baz', baz.full_name
+ end
+
+ def test_parse_class_definition_encountered_after_class_reference
+#
+# The code below is not strictly legal Ruby (Foo must have been defined
+# before Foo.bar is encountered), but RDoc might encounter Foo.bar before
+# Foo if they live in different files.
+#
+ code = <<-EOF
+def Foo.bar
+end
+
+class Foo < IO
+end
+EOF
+
+ util_parser code
+
+ @parser.scan()
+
+ assert(@top_level.modules.empty?)
+
+ foo = @top_level.classes.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal 'IO', foo.superclass
+
+ bar = foo.method_list.first
+ assert_equal 'bar', bar.name
+ end
+
+ def test_parse_module_relative_to_top_level_namespace
+ comment = <<-EOF
+#
+# Weirdly named module
+#
+EOF
+
+ code = comment + <<-EOF
+module ::Foo
+ class Helper
+ end
+end
+EOF
+
+ util_parser code
+ @parser.scan()
+
+ foo = @top_level.modules.first
+ assert_equal 'Foo', foo.full_name
+ assert_equal comment, foo.comment
+
+ helper = foo.classes.first
+ assert_equal 'Foo::Helper', helper.full_name
+ end
+
def test_parse_comment
content = <<-EOF
class Foo
@@ -416,9 +520,107 @@ end
@parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+ foo = @top_level.classes.first.method_list[0]
+ assert_equal 'foo', foo.name
+
foo2 = @top_level.classes.first.method_list.last
assert_equal 'foo2', foo2.name
assert_equal 'foo', foo2.is_alias_for.name
+ assert @top_level.classes.first.aliases.empty?
+ end
+
+ def test_parse_statements_identifier_alias_method_before_original_method
+ # This is not strictly legal Ruby code, but it simulates finding an alias
+ # for a method before finding the original method, which might happen
+ # to rdoc if the alias is in a different file than the original method
+ # and rdoc processes the alias' file first.
+ content = <<-EOF
+class Foo
+ alias_method :foo2, :foo
+
+ alias_method :foo3, :foo
+
+ def foo()
+ end
+
+ alias_method :foo4, :foo
+
+ alias_method :foo5, :unknown
+end
+EOF
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ foo = @top_level.classes.first.method_list[0]
+ assert_equal 'foo', foo.name
+
+ foo2 = @top_level.classes.first.method_list[1]
+ assert_equal 'foo2', foo2.name
+ assert_equal 'foo', foo2.is_alias_for.name
+
+ foo3 = @top_level.classes.first.method_list[2]
+ assert_equal 'foo3', foo3.name
+ assert_equal 'foo', foo3.is_alias_for.name
+
+ foo4 = @top_level.classes.first.method_list.last
+ assert_equal 'foo4', foo4.name
+ assert_equal 'foo', foo4.is_alias_for.name
+
+ assert_equal 'unknown', @top_level.classes.first.aliases[0].old_name
+ end
+
+ def test_parse_statements_identifier_constant
+ content = <<-EOF
+class Foo
+ FIRST_CONSTANT = 5
+
+ SECOND_CONSTANT = [
+ 1,
+ 2,
+ 3
+ ]
+
+ THIRD_CONSTANT = {
+ :foo => 'bar',
+ :x => 'y'
+ }
+
+ FOURTH_CONSTANT = SECOND_CONSTANT.map do |element|
+ element + 1
+ element + 2
+ end
+
+ FIFTH_CONSTANT = SECOND_CONSTANT.map { |element| element + 1 }
+end
+EOF
+
+ util_parser content
+
+ @parser.parse_statements @top_level, RDoc::Parser::Ruby::NORMAL, nil, ''
+
+ constants = @top_level.classes.first.constants
+
+ constant = constants[0]
+ assert_equal 'FIRST_CONSTANT', constant.name
+ assert_equal '5', constant.value
+
+ constant = constants[1]
+ assert_equal 'SECOND_CONSTANT', constant.name
+ assert_equal '[ 1, 2, 3 ]', constant.value
+
+ constant = constants[2]
+ assert_equal 'THIRD_CONSTANT', constant.name
+ assert_equal "{ :foo => 'bar', :x => 'y' }", constant.value
+
+ constant = constants[3]
+ assert_equal 'FOURTH_CONSTANT', constant.name
+ assert_equal 'SECOND_CONSTANT.map do |element| element + 1 element + 2 end', constant.value
+
+ constant = constants.last
+ assert_equal 'FIFTH_CONSTANT', constant.name
+ assert_equal 'SECOND_CONSTANT.map { |element| element + 1 }', constant.value
end
def test_parse_statements_identifier_attr
@@ -530,9 +732,17 @@ end
@stats
end
+ def util_two_parsers(first_file_content, second_file_content)
+ util_parser first_file_content
+
+ @parser2 = RDoc::Parser::Ruby.new @top_level2, @filename,
+ second_file_content, @options, @stats
+ end
+
def util_toplevel
RDoc::TopLevel.reset
@top_level = RDoc::TopLevel.new @filename
+ @top_level2 = RDoc::TopLevel.new @filename2
end
end
diff --git a/test/rdoc/test_rdoc_ri_default_display.rb b/test/rdoc/test_rdoc_ri_default_display.rb
index 97fa6c94ae2..266b501ebb3 100644
--- a/test/rdoc/test_rdoc_ri_default_display.rb
+++ b/test/rdoc/test_rdoc_ri_default_display.rb
@@ -4,7 +4,7 @@ require 'rdoc/ri/formatter'
require 'rdoc/ri/display'
require 'rdoc/ri/driver'
-class TestRdocRiDefaultDisplay < Test::Unit::TestCase
+class TestRDocRiDefaultDisplay < Test::Unit::TestCase
def setup
@output = StringIO.new
@@ -27,7 +27,6 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
end
def test_display_class_info
- ri_reader = nil
klass = h \
'attributes' => [
{ 'name' => 'attribute', 'rw' => 'RW',
@@ -43,9 +42,9 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
],
'comment' => [RDoc::Markup::Flow::P.new('SomeClass comment')],
'constants' => [
- { 'name' => 'CONSTANT', 'value' => '"value"',
+ { 'name' => 'CONSTANT', 'value' => '"value1"',
'comment' => [RDoc::Markup::Flow::P.new('CONSTANT value')] },
- { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value"',
+ { 'name' => 'CONSTANT_NOCOMMENT', 'value' => '"value2"',
'comment' => nil },
],
'display_name' => 'Class',
@@ -59,7 +58,7 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
],
'superclass_string' => 'Object'
- @dd.display_class_info klass, ri_reader
+ @dd.display_class_info klass
expected = <<-EOF
---------------------------------------------------- Class: SomeClass < Object
@@ -71,10 +70,19 @@ class TestRdocRiDefaultDisplay < Test::Unit::TestCase
Constants:
----------
- CONSTANT:
+ CONSTANT = "value1"
CONSTANT value
- CONSTANT_NOCOMMENT
+ CONSTANT_NOCOMMENT = "value2"
+
+
+Attributes:
+-----------
+
+ attribute (RW):
+ attribute comment
+
+ attribute_no_comment (RW)
Class methods:
@@ -99,15 +107,6 @@ Instance method extensions:
---------------------------
instance_method_extension
-
-
-Attributes:
------------
-
- attribute (RW):
- attribute comment
-
- attribute_no_comment (RW)
EOF
assert_equal expected, @output.string
@@ -140,7 +139,7 @@ Attributes:
-------------------------------------------------------- SomeClass#some_method
some_method(arg1, arg2) {|block_param| ...}
- Extension from /nonexistent
+ From /nonexistent
------------------------------------------------------------------------------
some comment
@@ -152,7 +151,7 @@ Attributes:
end
def test_display_method_info_singleton
- method = RDoc::RI::Driver::Hash.new.update \
+ method = RDoc::RI::Driver::OpenStructHash.new.update \
'aliases' => [],
'block_params' => nil,
'comment' => nil,
@@ -167,6 +166,8 @@ Attributes:
expected = <<-EOF
------------------------------------------------------- SomeClass::some_method
SomeClass::some_method(arg1, arg2)
+
+ From
------------------------------------------------------------------------------
[no description]
EOF
@@ -176,7 +177,7 @@ Attributes:
def test_display_method_list
methods = [
- RDoc::RI::Driver::Hash.new.update(
+ RDoc::RI::Driver::OpenStructHash.new.update(
"aliases" => [],
"block_params" => nil,
"comment" => nil,
@@ -186,7 +187,7 @@ Attributes:
"params" => "()",
"visibility" => "public"
),
- RDoc::RI::Driver::Hash.new.update(
+ RDoc::RI::Driver::OpenStructHash.new.update(
"aliases" => [],
"block_params" => nil,
"comment" => nil,
@@ -204,7 +205,8 @@ Attributes:
More than one method matched your request. You can refine your search by
asking for information on one of:
- SomeClass#some_method, SomeClass#some_other_method
+SomeClass#some_method []
+SomeClass#some_other_method []
EOF
assert_equal expected, @output.string
@@ -216,7 +218,7 @@ Attributes:
expected = <<-EOF
some_method(arg1, arg2) {|block_param| ...}
- Extension from /nonexistent
+ From /nonexistent
EOF
assert_equal expected, @output.string
@@ -234,7 +236,7 @@ some_method(start, length)
some_method(index)
some_method(start, length)
- Extension from /nonexistent
+ From /nonexistent
EOF
assert_equal expected, @output.string
@@ -249,7 +251,7 @@ some_method(start, length)
expected = <<-EOF
SomeClass::some_method(arg1, arg2) {|block_param| ...}
- Extension from /nonexistent
+ From /nonexistent
EOF
assert_equal expected, @output.string
@@ -289,8 +291,7 @@ install an additional package, or ask the packager to enable ri generation.
end
def h(hash)
- RDoc::RI::Driver::Hash.convert hash
+ RDoc::RI::Driver::OpenStructHash.convert hash
end
end
-
diff --git a/test/rdoc/test_rdoc_ri_driver.rb b/test/rdoc/test_rdoc_ri_driver.rb
index cddd4e60d12..22643d61d36 100644
--- a/test/rdoc/test_rdoc_ri_driver.rb
+++ b/test/rdoc/test_rdoc_ri_driver.rb
@@ -14,7 +14,7 @@ class TestRDocRIDriver < Test::Unit::TestCase
FileUtils.mkdir_p @home_ri
FileUtils.mkdir_p @cache_dir
- @driver = RDoc::RI::Driver.new
+ @driver = RDoc::RI::Driver.new(RDoc::RI::Driver.process_args([]))
@driver.homepath = @home_ri
end
diff --git a/test/rdoc/test_rdoc_ri_formatter.rb b/test/rdoc/test_rdoc_ri_formatter.rb
index ed2ccba22d0..539359033e7 100644
--- a/test/rdoc/test_rdoc_ri_formatter.rb
+++ b/test/rdoc/test_rdoc_ri_formatter.rb
@@ -245,7 +245,7 @@ class TestRDocRIFormatter < Test::Unit::TestCase
def test_raw_print_line
@f.raw_print_line 'a b c'
- assert_equal "a b c\n", @output.string
+ assert_equal "a b c", @output.string
end
def test_strip_attributes_b