summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/rdoc.rb171
-rw-r--r--lib/rdoc/alias.rb2
-rw-r--r--lib/rdoc/anon_class.rb2
-rw-r--r--lib/rdoc/any_method.rb105
-rw-r--r--lib/rdoc/attr.rb59
-rw-r--r--lib/rdoc/class_module.rb267
-rw-r--r--lib/rdoc/code_object.rb70
-rw-r--r--lib/rdoc/code_objects.rb24
-rw-r--r--lib/rdoc/comment.rb232
-rw-r--r--lib/rdoc/constant.rb108
-rw-r--r--lib/rdoc/context.rb323
-rw-r--r--lib/rdoc/context/section.rb238
-rw-r--r--lib/rdoc/cross_reference.rb136
-rw-r--r--lib/rdoc/encoding.rb65
-rw-r--r--lib/rdoc/erb_partial.rb18
-rw-r--r--lib/rdoc/extend.rb117
-rw-r--r--lib/rdoc/generator.rb32
-rw-r--r--lib/rdoc/generator/darkfish.rb466
-rw-r--r--lib/rdoc/generator/json_index.rb248
-rw-r--r--lib/rdoc/generator/markup.rb87
-rw-r--r--lib/rdoc/generator/ri.rb70
-rw-r--r--lib/rdoc/generator/template/darkfish/_footer.rhtml5
-rw-r--r--lib/rdoc/generator/template/darkfish/_head.rhtml16
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml18
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml9
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml16
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml8
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml16
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml14
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml12
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml7
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml12
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml10
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml10
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml10
-rw-r--r--lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml13
-rw-r--r--lib/rdoc/generator/template/darkfish/class.rhtml179
-rw-r--r--lib/rdoc/generator/template/darkfish/classpage.rhtml321
-rw-r--r--lib/rdoc/generator/template/darkfish/filepage.rhtml124
-rwxr-xr-xlib/rdoc/generator/template/darkfish/images/add.pngbin0 -> 733 bytes
-rwxr-xr-xlib/rdoc/generator/template/darkfish/images/arrow_up.pngbin0 -> 372 bytes
-rwxr-xr-xlib/rdoc/generator/template/darkfish/images/delete.pngbin0 -> 715 bytes
-rwxr-xr-xlib/rdoc/generator/template/darkfish/images/tag_blue.pngbin0 -> 1880 bytes
-rw-r--r--lib/rdoc/generator/template/darkfish/images/transparent.pngbin0 -> 97 bytes
-rw-r--r--lib/rdoc/generator/template/darkfish/index.rhtml77
-rw-r--r--lib/rdoc/generator/template/darkfish/js/darkfish.js161
-rw-r--r--lib/rdoc/generator/template/darkfish/js/jquery.js44
-rw-r--r--lib/rdoc/generator/template/darkfish/js/quicksearch.js114
-rw-r--r--lib/rdoc/generator/template/darkfish/js/search.js94
-rw-r--r--lib/rdoc/generator/template/darkfish/js/thickbox-compressed.js10
-rw-r--r--lib/rdoc/generator/template/darkfish/page.rhtml18
-rw-r--r--lib/rdoc/generator/template/darkfish/rdoc.css487
-rw-r--r--lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml18
-rw-r--r--lib/rdoc/generator/template/darkfish/servlet_root.rhtml37
-rw-r--r--lib/rdoc/generator/template/darkfish/table_of_contents.rhtml55
-rw-r--r--lib/rdoc/generator/template/json_index/js/navigation.js142
-rw-r--r--lib/rdoc/generator/template/json_index/js/searcher.js228
-rw-r--r--lib/rdoc/ghost_method.rb2
-rw-r--r--lib/rdoc/include.rb43
-rw-r--r--lib/rdoc/markdown.rb16372
-rw-r--r--lib/rdoc/markdown/entities.rb2128
-rw-r--r--lib/rdoc/markdown/literals_1_9.rb417
-rw-r--r--lib/rdoc/markup.rb316
-rw-r--r--lib/rdoc/markup/attr_changer.rb22
-rw-r--r--lib/rdoc/markup/attr_span.rb29
-rw-r--r--lib/rdoc/markup/attribute_manager.rb37
-rw-r--r--lib/rdoc/markup/attributes.rb70
-rw-r--r--lib/rdoc/markup/block_quote.rb14
-rw-r--r--lib/rdoc/markup/document.rb45
-rw-r--r--lib/rdoc/markup/formatter.rb47
-rw-r--r--lib/rdoc/markup/formatter_test_case.rb120
-rw-r--r--lib/rdoc/markup/hard_break.rb31
-rw-r--r--lib/rdoc/markup/heading.rb44
-rw-r--r--lib/rdoc/markup/include.rb42
-rw-r--r--lib/rdoc/markup/indented_paragraph.rb14
-rw-r--r--lib/rdoc/markup/inline.rb145
-rw-r--r--lib/rdoc/markup/list.rb28
-rw-r--r--lib/rdoc/markup/list_item.rb21
-rw-r--r--lib/rdoc/markup/paragraph.rb14
-rw-r--r--lib/rdoc/markup/parser.rb189
-rw-r--r--lib/rdoc/markup/pre_process.rb88
-rw-r--r--lib/rdoc/markup/raw.rb10
-rw-r--r--lib/rdoc/markup/special.rb40
-rw-r--r--lib/rdoc/markup/text_formatter_test_case.rb2
-rw-r--r--lib/rdoc/markup/to_ansi.rb15
-rw-r--r--lib/rdoc/markup/to_bs.rb2
-rw-r--r--lib/rdoc/markup/to_html.rb178
-rw-r--r--lib/rdoc/markup/to_html_crossref.rb63
-rw-r--r--lib/rdoc/markup/to_html_snippet.rb284
-rw-r--r--lib/rdoc/markup/to_joined_paragraph.rb68
-rw-r--r--lib/rdoc/markup/to_label.rb74
-rw-r--r--lib/rdoc/markup/to_markdown.rb134
-rw-r--r--lib/rdoc/markup/to_rdoc.rb52
-rw-r--r--lib/rdoc/markup/to_table_of_contents.rb61
-rw-r--r--lib/rdoc/markup/to_test.rb3
-rw-r--r--lib/rdoc/markup/to_tt_only.rb16
-rw-r--r--lib/rdoc/markup/verbatim.rb38
-rw-r--r--lib/rdoc/meta_method.rb2
-rw-r--r--lib/rdoc/method_attr.rb81
-rw-r--r--lib/rdoc/normal_class.rb35
-rw-r--r--lib/rdoc/normal_module.rb17
-rw-r--r--lib/rdoc/options.rb341
-rw-r--r--lib/rdoc/parser.rb146
-rw-r--r--lib/rdoc/parser/c.rb494
-rw-r--r--lib/rdoc/parser/markdown.rb23
-rw-r--r--lib/rdoc/parser/rd.rb22
-rw-r--r--lib/rdoc/parser/ruby.rb312
-rw-r--r--lib/rdoc/parser/ruby_tools.rb11
-rw-r--r--lib/rdoc/parser/simple.rb30
-rw-r--r--lib/rdoc/parser/text.rb11
-rw-r--r--lib/rdoc/rd.rb99
-rw-r--r--lib/rdoc/rd/block_parser.rb1054
-rw-r--r--lib/rdoc/rd/inline.rb71
-rw-r--r--lib/rdoc/rd/inline_parser.rb1207
-rw-r--r--lib/rdoc/rdoc.rb172
-rw-r--r--lib/rdoc/require.rb2
-rw-r--r--lib/rdoc/ri.rb6
-rw-r--r--lib/rdoc/ri/driver.rb404
-rw-r--r--lib/rdoc/ri/paths.rb121
-rw-r--r--lib/rdoc/ri/store.rb356
-rw-r--r--lib/rdoc/ruby_lex.rb125
-rw-r--r--lib/rdoc/ruby_token.rb50
-rw-r--r--lib/rdoc/rubygems_hook.rb9
-rw-r--r--lib/rdoc/servlet.rb298
-rw-r--r--lib/rdoc/single_class.rb2
-rw-r--r--lib/rdoc/stats.rb58
-rw-r--r--lib/rdoc/store.rb881
-rw-r--r--lib/rdoc/task.rb30
-rw-r--r--lib/rdoc/test_case.rb162
-rw-r--r--lib/rdoc/text.rb75
-rw-r--r--lib/rdoc/token_stream.rb45
-rw-r--r--lib/rdoc/tom_doc.rb233
-rw-r--r--lib/rdoc/top_level.rb345
133 files changed, 30264 insertions, 3509 deletions
diff --git a/lib/rdoc.rb b/lib/rdoc.rb
index aaa1aaa092..5c2df18a0d 100644
--- a/lib/rdoc.rb
+++ b/lib/rdoc.rb
@@ -1,86 +1,55 @@
$DEBUG_RDOC = nil
-# :main: README.txt
+# :main: README.rdoc
##
-# RDoc is a Ruby documentation system which contains RDoc::RDoc for generating
-# documentation, RDoc::RI for interactive documentation and RDoc::Markup for
-# text markup.
+# RDoc produces documentation for Ruby source files by parsing the source and
+# extracting the definition for classes, modules, methods, includes and
+# requires. It associates these with optional documentation contained in an
+# immediately preceding comment block then renders the result using an output
+# formatter.
#
-# RDoc::RDoc produces documentation for Ruby source files. It works similarly
-# to JavaDoc, parsing the source and extracting the definition for classes,
-# modules, methods, includes and requires. It associates these with optional
-# documentation contained in an immediately preceding comment block then
-# renders the result using an output formatter.
-#
-# RDoc::Markup 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.
-#
-# RDoc::RI implements the +ri+ command-line tool which displays on-line
-# documentation for ruby classes, methods, etc. +ri+ features several output
-# formats and an interactive mode (<tt>ri -i</tt>). See <tt>ri --help</tt>
-# for further details.
+# For a simple introduction to writing or generating documentation using RDoc
+# see the README.
#
# == Roadmap
#
-# * If you want to use RDoc to create documentation for your Ruby source files,
-# see RDoc::Markup and refer to <tt>rdoc --help</tt> for command line
-# usage.
-# * If you want to write documentation for Ruby files see RDoc::Parser::Ruby
-# * If you want to write documentation for extensions written in C see
-# RDoc::Parser::C
-# * If you want to generate documentation using <tt>rake</tt> see RDoc::Task.
-# * If you want to drive RDoc programmatically, see RDoc::RDoc.
-# * If you want to use the library to format text blocks into HTML, look at
-# RDoc::Markup.
-# * If you want to make an RDoc plugin such as a generator or directive
-# handler see RDoc::RDoc.
-# * If you want to write your own output generator see RDoc::Generator.
-#
-# == Summary
+# If you think you found a bug in RDoc see DEVELOPERS@Bugs
#
-# Once installed, you can create documentation using the +rdoc+ command
+# If you want to use RDoc to create documentation for your Ruby source files,
+# see RDoc::Markup and refer to <tt>rdoc --help</tt> for command line usage.
#
-# % rdoc [options] [names...]
+# If you want to set the default markup format see
+# RDoc::Markup@Supported+Formats
#
-# For an up-to-date option summary, type
+# If you want to store rdoc configuration in your gem (such as the default
+# markup format) see RDoc::Options@Saved+Options
#
-# % rdoc --help
+# If you want to write documentation for Ruby files see RDoc::Parser::Ruby
#
-# A typical use might be to generate documentation for a package of Ruby
-# source (such as RDoc itself).
+# If you want to write documentation for extensions written in C see
+# RDoc::Parser::C
#
-# % rdoc
+# If you want to generate documentation using <tt>rake</tt> see RDoc::Task.
#
-# 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+.
+# If you want to drive RDoc programmatically, see RDoc::RDoc.
#
-# You can make this slightly more useful for your readers by having the
-# index page contain the documentation for the primary file. In our
-# case, we could type
+# If you want to use the library to format text blocks into HTML or other
+# formats, look at RDoc::Markup.
#
-# % rdoc --main README.txt
+# If you want to make an RDoc plugin such as a generator or directive handler
+# see RDoc::RDoc.
#
-# You'll find information on the various formatting tricks you can use
-# in comment blocks in the documentation this generates.
+# If you want to write your own output generator see RDoc::Generator.
#
-# RDoc uses file extensions to determine how to process each file. File names
-# 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.
+# If you want an overview of how RDoc works see DEVELOPERS
#
-# == Other stuff
+# == Credits
#
# RDoc is currently being maintained by Eric Hodel <drbrain@segment7.net>.
#
# Dave Thomas <dave@pragmaticprogrammer.com> is the original author of RDoc.
#
-# == Credits
-#
# * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding
# work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby
# parser for irb and the rtags package.
@@ -92,19 +61,10 @@ module RDoc
class Error < RuntimeError; end
- def self.const_missing const_name # :nodoc:
- if const_name.to_s == 'RDocError' then
- warn "RDoc::RDocError is deprecated"
- return Error
- end
-
- super
- end
-
##
# RDoc version you are using
- VERSION = '3.9.4'
+ VERSION = '4.0'
##
# Method visibilities
@@ -143,5 +103,80 @@ module RDoc
METHOD_MODIFIERS = GENERAL_MODIFIERS +
%w[arg args yield yields notnew not-new not_new doc]
+ ##
+ # Loads the best available YAML library.
+
+ def self.load_yaml
+ begin
+ gem 'psych'
+ rescue Gem::LoadError
+ end
+
+ begin
+ require 'psych'
+ rescue ::LoadError
+ ensure
+ require 'yaml'
+ end
+ end
+
+ autoload :RDoc, 'rdoc/rdoc'
+
+ autoload :TestCase, 'rdoc/test_case'
+
+ autoload :CrossReference, 'rdoc/cross_reference'
+ autoload :ERBIO, 'rdoc/erbio'
+ autoload :ERBPartial, 'rdoc/erb_partial'
+ autoload :Encoding, 'rdoc/encoding'
+ autoload :Generator, 'rdoc/generator'
+ autoload :Options, 'rdoc/options'
+ autoload :Parser, 'rdoc/parser'
+ autoload :Servlet, 'rdoc/servlet'
+ autoload :RI, 'rdoc/ri'
+ autoload :Stats, 'rdoc/stats'
+ autoload :Store, 'rdoc/store'
+ autoload :Task, 'rdoc/task'
+ autoload :Text, 'rdoc/text'
+
+ autoload :Markdown, 'rdoc/markdown'
+ autoload :Markup, 'rdoc/markup'
+ autoload :RD, 'rdoc/rd'
+ autoload :TomDoc, 'rdoc/tom_doc'
+
+ autoload :KNOWN_CLASSES, 'rdoc/known_classes'
+
+ autoload :RubyLex, 'rdoc/ruby_lex'
+ autoload :RubyToken, 'rdoc/ruby_token'
+ autoload :TokenStream, 'rdoc/token_stream'
+
+ autoload :Comment, 'rdoc/comment'
+
+ # code objects
+ #
+ # We represent the various high-level code constructs that appear in Ruby
+ # programs: classes, modules, methods, and so on.
+ autoload :CodeObject, 'rdoc/code_object'
+
+ autoload :Context, 'rdoc/context'
+ autoload :TopLevel, 'rdoc/top_level'
+
+ autoload :AnonClass, 'rdoc/anon_class'
+ autoload :ClassModule, 'rdoc/class_module'
+ autoload :NormalClass, 'rdoc/normal_class'
+ autoload :NormalModule, 'rdoc/normal_module'
+ autoload :SingleClass, 'rdoc/single_class'
+
+ autoload :Alias, 'rdoc/alias'
+ autoload :AnyMethod, 'rdoc/any_method'
+ autoload :MethodAttr, 'rdoc/method_attr'
+ autoload :GhostMethod, 'rdoc/ghost_method'
+ autoload :MetaMethod, 'rdoc/meta_method'
+ autoload :Attr, 'rdoc/attr'
+
+ autoload :Constant, 'rdoc/constant'
+ autoload :Include, 'rdoc/include'
+ autoload :Extend, 'rdoc/extend'
+ autoload :Require, 'rdoc/require'
+
end
diff --git a/lib/rdoc/alias.rb b/lib/rdoc/alias.rb
index fa433dc0a9..39d2694817 100644
--- a/lib/rdoc/alias.rb
+++ b/lib/rdoc/alias.rb
@@ -1,5 +1,3 @@
-require 'rdoc/code_object'
-
##
# Represent an alias, which is an old_name/new_name pair associated with a
# particular context
diff --git a/lib/rdoc/anon_class.rb b/lib/rdoc/anon_class.rb
index 63c09e11f1..c23d8e5d96 100644
--- a/lib/rdoc/anon_class.rb
+++ b/lib/rdoc/anon_class.rb
@@ -1,5 +1,3 @@
-require 'rdoc/class_module'
-
##
# An anonymous class like:
#
diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb
index c008edfe95..c3d68e87b4 100644
--- a/lib/rdoc/any_method.rb
+++ b/lib/rdoc/any_method.rb
@@ -1,12 +1,16 @@
-require 'rdoc/method_attr'
-require 'rdoc/token_stream'
-
##
# AnyMethod is the base class for objects representing methods
class RDoc::AnyMethod < RDoc::MethodAttr
- MARSHAL_VERSION = 1 # :nodoc:
+ ##
+ # 2::
+ # RDoc 4
+ # Added calls_super
+ # Added parent name and class
+ # Added section title
+
+ MARSHAL_VERSION = 2 # :nodoc:
##
# Don't rename \#initialize to \::new
@@ -28,6 +32,11 @@ class RDoc::AnyMethod < RDoc::MethodAttr
attr_accessor :params
+ ##
+ # If true this method uses +super+ to call a superclass version
+
+ attr_accessor :calls_super
+
include RDoc::TokenStream
##
@@ -39,6 +48,8 @@ class RDoc::AnyMethod < RDoc::MethodAttr
@c_function = nil
@dont_rename_initialize = false
@token_stream = nil
+ @calls_super = false
+ @superclass_method = nil
end
##
@@ -97,6 +108,10 @@ class RDoc::AnyMethod < RDoc::MethodAttr
aliases,
@params,
@file.absolute_name,
+ @calls_super,
+ @parent.name,
+ @parent.class,
+ @section.title,
]
end
@@ -107,34 +122,44 @@ class RDoc::AnyMethod < RDoc::MethodAttr
# * #full_name
# * #parent_name
- def marshal_load(array)
+ def marshal_load array
@dont_rename_initialize = nil
@is_alias_for = nil
@token_stream = nil
@aliases = []
-
- version = array[0]
- @name = array[1]
- @full_name = array[2]
- @singleton = array[3]
- @visibility = array[4]
- @comment = array[5]
- @call_seq = array[6]
- @block_params = array[7]
+ @parent = nil
+ @parent_name = nil
+ @parent_class = nil
+ @section = nil
+ @file = nil
+
+ version = array[0]
+ @name = array[1]
+ @full_name = array[2]
+ @singleton = array[3]
+ @visibility = array[4]
+ @comment = array[5]
+ @call_seq = array[6]
+ @block_params = array[7]
+ # 8 handled below
+ @params = array[9]
+ # 10 handled below
+ @calls_super = array[11]
+ @parent_name = array[12]
+ @parent_title = array[13]
+ @section_title = array[14]
array[8].each do |new_name, comment|
add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton)
end
- @params = array[9]
-
- @parent_name = if @full_name =~ /#/ then
- $`
- else
- name = @full_name.split('::')
- name.pop
- name.join '::'
- end
+ @parent_name ||= if @full_name =~ /#/ then
+ $`
+ else
+ name = @full_name.split('::')
+ name.pop
+ name.join '::'
+ end
@file = RDoc::TopLevel.new array[10] if version > 0
end
@@ -169,7 +194,9 @@ class RDoc::AnyMethod < RDoc::MethodAttr
return []
end
- params.gsub(/\s+/, '').split ','
+ params = params.gsub(/\s+/, '').split ','
+
+ params.map { |param| param.sub(/=.*/, '') }
end
##
@@ -181,10 +208,12 @@ class RDoc::AnyMethod < RDoc::MethodAttr
params = @call_seq.split("\n").last
params = params.sub(/[^( ]+/, '')
params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2')
- else
+ elsif @params then
params = @params.gsub(/\s*\#.*/, '')
params = params.tr("\n", " ").squeeze(" ")
params = "(#{params})" unless params[0] == ?(
+ else
+ params = ''
end
if @block_params then
@@ -203,5 +232,31 @@ class RDoc::AnyMethod < RDoc::MethodAttr
params
end
+ ##
+ # Sets the store for this method and its referenced code objects.
+
+ def store= store
+ super
+
+ @file = @store.add_file @file.full_name if @file
+ end
+
+ ##
+ # For methods that +super+, find the superclass method that would be called.
+
+ def superclass_method
+ return unless @calls_super
+ return @superclass_method if @superclass_method
+
+ parent.each_ancestor do |ancestor|
+ if method = ancestor.method_list.find { |m| m.name == @name } then
+ @superclass_method = method
+ break
+ end
+ end
+
+ @superclass_method
+ end
+
end
diff --git a/lib/rdoc/attr.rb b/lib/rdoc/attr.rb
index 5d9bc17831..0eb1c0d79b 100644
--- a/lib/rdoc/attr.rb
+++ b/lib/rdoc/attr.rb
@@ -1,12 +1,16 @@
-require 'rdoc/method_attr'
-
##
# An attribute created by \#attr, \#attr_reader, \#attr_writer or
# \#attr_accessor
class RDoc::Attr < RDoc::MethodAttr
- MARSHAL_VERSION = 2 # :nodoc:
+ ##
+ # 3::
+ # RDoc 4
+ # Added parent name and class
+ # Added section title
+
+ MARSHAL_VERSION = 3 # :nodoc:
##
# Is the attribute readable ('R'), writable ('W') or both ('RW')?
@@ -58,6 +62,16 @@ class RDoc::Attr < RDoc::MethodAttr
end
##
+ # Attributes never call super. See RDoc::AnyMethod#calls_super
+ #
+ # An RDoc::Attr can show up in the method list in some situations (see
+ # Gem::ConfigFile)
+
+ def calls_super # :nodoc:
+ false
+ end
+
+ ##
# Returns attr_reader, attr_writer or attr_accessor as appropriate.
def definition
@@ -93,6 +107,9 @@ class RDoc::Attr < RDoc::MethodAttr
parse(@comment),
singleton,
@file.absolute_name,
+ @parent.full_name,
+ @parent.class,
+ @section.title
]
end
@@ -104,17 +121,28 @@ class RDoc::Attr < RDoc::MethodAttr
# * #parent_name
def marshal_load array
- version = array[0]
- @name = array[1]
- @full_name = array[2]
- @rw = array[3]
- @visibility = array[4]
- @comment = array[5]
- @singleton = array[6] || false # MARSHAL_VERSION == 0
+ @aliases = []
+ @parent = nil
+ @parent_name = nil
+ @parent_class = nil
+ @section = nil
+ @file = nil
+
+ version = array[0]
+ @name = array[1]
+ @full_name = array[2]
+ @rw = array[3]
+ @visibility = array[4]
+ @comment = array[5]
+ @singleton = array[6] || false # MARSHAL_VERSION == 0
+ # 7 handled below
+ @parent_name = array[8]
+ @parent_class = array[9]
+ @section_title = array[10]
@file = RDoc::TopLevel.new array[7] if version > 1
- @parent_name = @full_name
+ @parent_name ||= @full_name.split('#', 2).first
end
def pretty_print q # :nodoc:
@@ -132,5 +160,14 @@ class RDoc::Attr < RDoc::MethodAttr
"#{definition} #{name} in: #{parent}"
end
+ ##
+ # Attributes do not have token streams.
+ #
+ # An RDoc::Attr can show up in the method list in some situations (see
+ # Gem::ConfigFile)
+
+ def token_stream # :nodoc:
+ end
+
end
diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb
index 27066d8bd7..04f0132b7d 100644
--- a/lib/rdoc/class_module.rb
+++ b/lib/rdoc/class_module.rb
@@ -1,5 +1,3 @@
-require 'rdoc/context'
-
##
# ClassModule is the base class for objects representing either a class or a
# module.
@@ -13,8 +11,17 @@ class RDoc::ClassModule < RDoc::Context
# * Added file to constants
# * Added file to includes
# * Added file to methods
-
- MARSHAL_VERSION = 1 # :nodoc:
+ # 2::
+ # RDoc 3.13
+ # * Added extends
+ # 3::
+ # RDoc 4.0
+ # * Added sections
+ # * Added in_files
+ # * Added parent name
+ # * Complete Constant dump
+
+ MARSHAL_VERSION = 3 # :nodoc:
##
# Constants that are aliases for this class or module
@@ -56,6 +63,7 @@ class RDoc::ClassModule < RDoc::Context
klass.external_aliases.concat mod.external_aliases
klass.constants.concat mod.constants
klass.includes.concat mod.includes
+ klass.extends.concat mod.extends
klass.methods_hash.update mod.methods_hash
klass.constants_hash.update mod.constants_hash
@@ -84,6 +92,7 @@ class RDoc::ClassModule < RDoc::Context
klass.external_aliases +
klass.constants +
klass.includes +
+ klass.extends +
klass.classes +
klass.modules).each do |obj|
obj.parent = klass
@@ -115,16 +124,32 @@ class RDoc::ClassModule < RDoc::Context
# across multiple runs.
def add_comment comment, location
- return if comment.empty? or not document_self
+ return unless document_self
original = comment
- comment = normalize_comment comment
+ comment = case comment
+ when RDoc::Comment then
+ comment.normalize
+ else
+ normalize_comment comment
+ end
@comment_location << [comment, location]
self.comment = original
end
+ def add_things my_things, other_things # :nodoc:
+ other_things.each do |group, things|
+ my_things[group].each { |thing| yield false, thing } if
+ my_things.include? group
+
+ things.each do |thing|
+ yield true, thing
+ end
+ end
+ end
+
##
# Ancestors list for this ClassModule: the list of included modules
# (classes will add their superclass if any).
@@ -142,6 +167,11 @@ class RDoc::ClassModule < RDoc::Context
end
##
+ # Ancestors of this class or module only
+
+ alias direct_ancestors ancestors
+
+ ##
# Clears the comment. Used by the ruby parser.
def clear_comment
@@ -155,9 +185,13 @@ class RDoc::ClassModule < RDoc::Context
# more like <tt>+=</tt>.
def comment= comment
- return if comment.empty?
+ comment = case comment
+ when RDoc::Comment then
+ comment.normalize
+ else
+ normalize_comment comment
+ end
- comment = normalize_comment comment
comment = "#{@comment}\n---\n#{comment}" unless @comment.empty?
super comment
@@ -166,7 +200,7 @@ class RDoc::ClassModule < RDoc::Context
##
# Prepares this ClassModule for use by a generator.
#
- # See RDoc::TopLevel::complete
+ # See RDoc::Store#complete
def complete min_visibility
update_aliases
@@ -176,12 +210,22 @@ class RDoc::ClassModule < RDoc::Context
end
##
+ # Does this ClassModule or any of its methods have document_self set?
+
+ def document_self_or_methods
+ document_self || method_list.any?{ |m| m.document_self }
+ end
+
+ ##
# Iterates the ancestors of this class or module for which an
# RDoc::ClassModule exists.
def each_ancestor # :yields: module
+ return enum_for __method__ unless block_given?
+
ancestors.each do |mod|
next if String === mod
+ next if self == mod
yield mod
end
end
@@ -215,8 +259,8 @@ class RDoc::ClassModule < RDoc::Context
# Return the fully qualified name of this class or module
def full_name
- @full_name ||= if RDoc::ClassModule === @parent then
- "#{@parent.full_name}::#{@name}"
+ @full_name ||= if RDoc::ClassModule === parent then
+ "#{parent.full_name}::#{@name}"
else
@name
end
@@ -250,13 +294,20 @@ class RDoc::ClassModule < RDoc::Context
@superclass,
parse(@comment_location),
attrs,
- constants.map do |const|
- [const.name, parse(const.comment), const.file_name]
- end,
+ constants,
includes.map do |incl|
[incl.name, parse(incl.comment), incl.file_name]
end,
method_types,
+ extends.map do |ext|
+ [ext.name, parse(ext.comment), ext.file_name]
+ end,
+ @sections.values,
+ @in_files.map do |tl|
+ tl.absolute_name
+ end,
+ parent.full_name,
+ parent.class,
]
end
@@ -268,6 +319,8 @@ class RDoc::ClassModule < RDoc::Context
@parent = nil
@temporary_section = nil
@visibility = nil
+ @classes = {}
+ @modules = {}
@name = array[1]
@full_name = array[2]
@@ -291,9 +344,14 @@ class RDoc::ClassModule < RDoc::Context
attr.record_location RDoc::TopLevel.new file
end
- array[6].each do |name, comment, file|
- const = add_constant RDoc::Constant.new(name, nil, comment)
- const.record_location RDoc::TopLevel.new file
+ array[6].each do |constant, comment, file|
+ case constant
+ when RDoc::Constant then
+ add_constant constant
+ else
+ constant = add_constant RDoc::Constant.new(constant, nil, comment)
+ constant.record_location RDoc::TopLevel.new file
+ end
end
array[7].each do |name, comment, file|
@@ -313,6 +371,27 @@ class RDoc::ClassModule < RDoc::Context
end
end
end
+
+ array[9].each do |name, comment, file|
+ ext = add_extend RDoc::Extend.new(name, comment)
+ ext.record_location RDoc::TopLevel.new file
+ end if array[9] # Support Marshal version 1
+
+ sections = (array[10] || []).map do |section|
+ [section.title, section]
+ end
+
+ @sections = Hash[*sections.flatten]
+ @current_section = add_section nil
+
+ @in_files = []
+
+ (array[11] || []).each do |filename|
+ record_location RDoc::TopLevel.new filename
+ end
+
+ @parent_name = array[12]
+ @parent_class = array[13]
end
##
@@ -321,6 +400,9 @@ class RDoc::ClassModule < RDoc::Context
# The data in +class_module+ is preferred over the receiver.
def merge class_module
+ @parent = class_module.parent
+ @parent_name = class_module.parent_name
+
other_document = parse class_module.comment_location
if other_document then
@@ -360,6 +442,18 @@ class RDoc::ClassModule < RDoc::Context
end
end
+ @includes.uniq! # clean up
+
+ merge_collections extends, cm.extends, other_files do |add, ext|
+ if add then
+ add_extend ext
+ else
+ @extends.delete ext
+ end
+ end
+
+ @extends.uniq! # clean up
+
merge_collections method_list, cm.method_list, other_files do |add, meth|
if add then
add_method meth
@@ -369,6 +463,8 @@ class RDoc::ClassModule < RDoc::Context
end
end
+ merge_sections cm
+
self
end
@@ -391,22 +487,46 @@ class RDoc::ClassModule < RDoc::Context
my_things = mine. group_by { |thing| thing.file }
other_things = other.group_by { |thing| thing.file }
- my_things.delete_if do |file, things|
- next false unless other_files.include? file
+ remove_things my_things, other_files, &block
+ add_things my_things, other_things, &block
+ end
- things.each do |thing|
- yield false, thing
- end
+ ##
+ # Merges the comments in this ClassModule with the comments in the other
+ # ClassModule +cm+.
- true
+ def merge_sections cm # :nodoc:
+ my_sections = sections.group_by { |section| section.title }
+ other_sections = cm.sections.group_by { |section| section.title }
+
+ other_files = cm.in_files
+
+ remove_things my_sections, other_files do |_, section|
+ @sections.delete section.title
end
- other_things.each do |file, things|
- my_things[file].each { |thing| yield false, thing } if
- my_things.include?(file)
+ other_sections.each do |group, sections|
+ if my_sections.include? group
+ my_sections[group].each do |my_section|
+ other_section = cm.sections_hash[group]
- things.each do |thing|
- yield true, thing
+ my_comments = my_section.comments
+ other_comments = other_section.comments
+
+ other_files = other_section.in_files
+
+ merge_collections my_comments, other_comments, other_files do |add, comment|
+ if add then
+ my_section.add_comment comment
+ else
+ my_section.remove_comment comment
+ end
+ end
+ end
+ else
+ sections.each do |section|
+ add_section group, section.comments
+ end
end
end
end
@@ -438,11 +558,15 @@ class RDoc::ClassModule < RDoc::Context
when Array then
docs = comment_location.map do |comment, location|
doc = super comment
- doc.file = location.absolute_name
+ doc.file = location
doc
end
RDoc::Markup::Document.new(*docs)
+ when RDoc::Comment then
+ doc = super comment_location.text, comment_location.format
+ doc.file = comment_location.location
+ doc
when RDoc::Markup::Document then
return comment_location
else
@@ -451,10 +575,10 @@ class RDoc::ClassModule < RDoc::Context
end
##
- # Path to this class or module
+ # Path to this class or module for use with HTML generator output.
def path
- http_url RDoc::RDoc.current.generator.class_dir
+ http_url @store.rdoc.generator.class_dir
end
##
@@ -488,21 +612,61 @@ class RDoc::ClassModule < RDoc::Context
modules_hash.each_key do |name|
full_name = prefix + name
- modules_hash.delete name unless RDoc::TopLevel.all_modules_hash[full_name]
+ modules_hash.delete name unless @store.modules_hash[full_name]
end
classes_hash.each_key do |name|
full_name = prefix + name
- classes_hash.delete name unless RDoc::TopLevel.all_classes_hash[full_name]
+ classes_hash.delete name unless @store.classes_hash[full_name]
end
end
+ def remove_things my_things, other_files # :nodoc:
+ my_things.delete_if do |file, things|
+ next false unless other_files.include? file
+
+ things.each do |thing|
+ yield false, thing
+ end
+
+ true
+ end
+ end
+
+ ##
+ # Search record used by RDoc::Generator::JsonIndex
+
+ def search_record
+ [
+ name,
+ full_name,
+ full_name,
+ '',
+ path,
+ '',
+ snippet(@comment_location),
+ ]
+ end
+
+ ##
+ # Sets the store for this class or module and its contained code objects.
+
+ def store= store
+ super
+
+ @attributes .each do |attr| attr.store = store end
+ @constants .each do |const| const.store = store end
+ @includes .each do |incl| incl.store = store end
+ @extends .each do |ext| ext.store = store end
+ @method_list.each do |meth| meth.store = store end
+ end
+
##
# Get the superclass of this class. Attempts to retrieve the superclass
# object, returns the name if it is not known.
def superclass
- RDoc::TopLevel.find_class_named(@superclass) || @superclass
+ @store.find_class_named(@superclass) || @superclass
end
##
@@ -533,7 +697,7 @@ class RDoc::ClassModule < RDoc::Context
# aliases through a constant.
#
# The aliased module/class is replaced in the children and in
- # RDoc::TopLevel::all_modules_hash or RDoc::TopLevel::all_classes_hash
+ # RDoc::Store#modules_hash or RDoc::Store#classes_hash
# by a copy that has <tt>RDoc::ClassModule#is_alias_for</tt> set to
# the aliased module/class, and this copy is added to <tt>#aliases</tt>
# of the aliased module/class.
@@ -548,16 +712,21 @@ class RDoc::ClassModule < RDoc::Context
next unless cm = const.is_alias_for
cm_alias = cm.dup
cm_alias.name = const.name
- cm_alias.parent = self
- cm_alias.full_name = nil # force update for new parent
+
+ # Don't move top-level aliases under Object, they look ugly there
+ unless RDoc::TopLevel === cm_alias.parent then
+ cm_alias.parent = self
+ cm_alias.full_name = nil # force update for new parent
+ end
+
cm_alias.aliases.clear
cm_alias.is_alias_for = cm
if cm.module? then
- RDoc::TopLevel.all_modules_hash[cm_alias.full_name] = cm_alias
+ @store.modules_hash[cm_alias.full_name] = cm_alias
modules_hash[const.name] = cm_alias
else
- RDoc::TopLevel.all_classes_hash[cm_alias.full_name] = cm_alias
+ @store.classes_hash[cm_alias.full_name] = cm_alias
classes_hash[const.name] = cm_alias
end
@@ -574,8 +743,26 @@ class RDoc::ClassModule < RDoc::Context
def update_includes
includes.reject! do |include|
mod = include.module
- !(String === mod) && RDoc::TopLevel.all_modules_hash[mod.full_name].nil?
+ !(String === mod) && @store.modules_hash[mod.full_name].nil?
end
+
+ includes.uniq!
+ end
+
+ ##
+ # Deletes from #extends those whose module has been removed from the
+ # documentation.
+ #--
+ # FIXME: like update_includes, extends are not reliably removed
+
+ def update_extends
+ extends.reject! do |ext|
+ mod = ext.module
+
+ !(String === mod) && @store.modules_hash[mod.full_name].nil?
+ end
+
+ extends.uniq!
end
end
diff --git a/lib/rdoc/code_object.rb b/lib/rdoc/code_object.rb
index 54826fffbd..e2d9d909da 100644
--- a/lib/rdoc/code_object.rb
+++ b/lib/rdoc/code_object.rb
@@ -1,6 +1,3 @@
-require 'rdoc'
-require 'rdoc/text'
-
##
# Base class for the RDoc code tree.
#
@@ -78,9 +75,9 @@ class RDoc::CodeObject
attr_accessor :offset
##
- # Our parent CodeObject
+ # Sets the parent CodeObject
- attr_accessor :parent
+ attr_writer :parent
##
# Did we ever receive a +:nodoc:+ directive?
@@ -88,9 +85,14 @@ class RDoc::CodeObject
attr_reader :received_nodoc
##
- # Which section are we in
+ # Set the section this CodeObject is in
- attr_accessor :section
+ attr_writer :section
+
+ ##
+ # The RDoc::Store for this object.
+
+ attr_accessor :store
##
# We are the model of the code, but we know that at some point we will be
@@ -103,11 +105,16 @@ class RDoc::CodeObject
# Creates a new CodeObject that will document itself and its children
def initialize
- @metadata = {}
- @comment = ''
- @parent = nil
- @file = nil
- @full_name = nil
+ @metadata = {}
+ @comment = ''
+ @parent = nil
+ @parent_name = nil # for loading
+ @parent_class = nil # for loading
+ @section = nil
+ @section_title = nil # for loading
+ @file = nil
+ @full_name = nil
+ @store = nil
@document_children = true
@document_self = true
@@ -124,11 +131,11 @@ class RDoc::CodeObject
@comment = case comment
when NilClass then ''
when RDoc::Markup::Document then comment
+ when RDoc::Comment then comment.normalize
else
if comment and not comment.empty? then
normalize_comment comment
else
- # TODO is this sufficient?
# HACK correct fix is to have #initialize create @comment
# with the correct encoding
if String === @comment and
@@ -216,7 +223,7 @@ class RDoc::CodeObject
##
# Force the documentation of this object unless documentation
- # has been turned off by :endoc:
+ # has been turned off by :enddoc:
#--
# HACK untested, was assigning to an ivar
@@ -262,6 +269,29 @@ class RDoc::CodeObject
end
##
+ # Our parent CodeObject. The parent may be missing for classes loaded from
+ # legacy RI data stores.
+
+ def parent
+ return @parent if @parent
+ return nil unless @parent_name
+
+ if @parent_class == RDoc::TopLevel then
+ @parent = @store.add_file @parent_name
+ else
+ @parent = @store.find_class_or_module @parent_name
+
+ return @parent if @parent
+
+ begin
+ @parent = @store.load_class @parent_name
+ rescue RDoc::Store::MissingFileError
+ nil
+ end
+ end
+ end
+
+ ##
# File name of our parent
def parent_file_name
@@ -284,8 +314,18 @@ class RDoc::CodeObject
end
##
+ # The section this CodeObject is in. Sections allow grouping of constants,
+ # attributes and methods inside a class or module.
+
+ def section
+ return @section if @section
+
+ @section = parent.add_section @section_title if parent
+ end
+
+ ##
# Enable capture of documentation unless documentation has been
- # turned off by :endoc:
+ # turned off by :enddoc:
def start_doc
return if @done_documenting
diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb
index c60dad92df..f1a626cd2e 100644
--- a/lib/rdoc/code_objects.rb
+++ b/lib/rdoc/code_objects.rb
@@ -1,23 +1,5 @@
-# We represent the various high-level code constructs that appear in Ruby
-# programs: classes, modules, methods, and so on.
+# This file was used to load all the RDoc::CodeObject subclasses at once. Now
+# autoload handles this.
-require 'rdoc/code_object'
-require 'rdoc/context'
-require 'rdoc/top_level'
-
-require 'rdoc/class_module'
-require 'rdoc/normal_class'
-require 'rdoc/normal_module'
-require 'rdoc/anon_class'
-require 'rdoc/single_class'
-
-require 'rdoc/any_method'
-require 'rdoc/alias'
-require 'rdoc/ghost_method'
-require 'rdoc/meta_method'
-
-require 'rdoc/attr'
-require 'rdoc/constant'
-require 'rdoc/require'
-require 'rdoc/include'
+require 'rdoc'
diff --git a/lib/rdoc/comment.rb b/lib/rdoc/comment.rb
new file mode 100644
index 0000000000..25e7c966c8
--- /dev/null
+++ b/lib/rdoc/comment.rb
@@ -0,0 +1,232 @@
+##
+# A comment holds the text comment for a RDoc::CodeObject and provides a
+# unified way of cleaning it up and parsing it into an RDoc::Markup::Document.
+#
+# Each comment may have a different markup format set by #format=. By default
+# 'rdoc' is used. The :markup: directive tells RDoc which format to use.
+#
+# See RDoc::Markup@Other+directives for instructions on adding an alternate
+# format.
+
+class RDoc::Comment
+
+ include RDoc::Text
+
+ ##
+ # The format of this comment. Defaults to RDoc::Markup
+
+ attr_reader :format
+
+ ##
+ # The RDoc::TopLevel this comment was found in
+
+ attr_accessor :location
+
+ ##
+ # For duck-typing when merging classes at load time
+
+ alias file location # :nodoc:
+
+ ##
+ # The text for this comment
+
+ attr_reader :text
+
+ ##
+ # Overrides the content returned by #parse. Use when there is no #text
+ # source for this comment
+
+ attr_writer :document
+
+ ##
+ # Creates a new comment with +text+ that is found in the RDoc::TopLevel
+ # +location+.
+
+ def initialize text = nil, location = nil
+ @location = location
+ @text = text
+
+ @document = nil
+ @format = 'rdoc'
+ @normalized = false
+ end
+
+ ##
+ #--
+ # TODO deep copy @document
+
+ def initialize_copy copy # :nodoc:
+ @text = copy.text.dup
+ end
+
+ def == other # :nodoc:
+ self.class === other and
+ other.text == @text and other.location == @location
+ end
+
+ ##
+ # Look for a 'call-seq' in the comment to override the normal parameter
+ # handling. The :call-seq: is indented from the baseline. All lines of the
+ # same indentation level and prefix are consumed.
+ #
+ # For example, all of the following will be used as the :call-seq:
+ #
+ # # :call-seq:
+ # # ARGF.readlines(sep=$/) -> array
+ # # ARGF.readlines(limit) -> array
+ # # ARGF.readlines(sep, limit) -> array
+ # #
+ # # ARGF.to_a(sep=$/) -> array
+ # # ARGF.to_a(limit) -> array
+ # # ARGF.to_a(sep, limit) -> array
+
+ def extract_call_seq method
+ # we must handle situations like the above followed by an unindented first
+ # comment. The difficulty is to make sure not to match lines starting
+ # with ARGF at the same indent, but that are after the first description
+ # paragraph.
+ if @text =~ /^\s*:?call-seq:(.*?(?:\S).*?)^\s*$/m then
+ all_start, all_stop = $~.offset(0)
+ seq_start, seq_stop = $~.offset(1)
+
+ # we get the following lines that start with the leading word at the
+ # same indent, even if they have blank lines before
+ if $1 =~ /(^\s*\n)+^(\s*\w+)/m then
+ leading = $2 # ' * ARGF' in the example above
+ re = %r%
+ \A(
+ (^\s*\n)+
+ (^#{Regexp.escape leading}.*?\n)+
+ )+
+ ^\s*$
+ %xm
+
+ if @text[seq_stop..-1] =~ re then
+ all_stop = seq_stop + $~.offset(0).last
+ seq_stop = seq_stop + $~.offset(1).last
+ end
+ end
+
+ seq = @text[seq_start..seq_stop]
+ seq.gsub!(/^\s*(\S|\n)/m, '\1')
+ @text.slice! all_start...all_stop
+
+ method.call_seq = seq.chomp
+
+ elsif @text.sub!(/^\s*:?call-seq:(.*?)(^\s*$|\z)/m, '') then
+ seq = $1
+ seq.gsub!(/^\s*/, '')
+ method.call_seq = seq
+ end
+ #elsif @text.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '') then
+ # method.call_seq = $1.strip
+ #end
+
+ method
+ end
+
+ ##
+ # A comment is empty if its text String is empty.
+
+ def empty?
+ @text.empty?
+ end
+
+ ##
+ # HACK dubious
+
+ def force_encoding encoding
+ @text.force_encoding encoding
+ end
+
+ ##
+ # Sets the format of this comment and resets any parsed document
+
+ def format= format
+ @format = format
+ @document = nil
+ end
+
+ def inspect # :nodoc:
+ location = @location ? @location.absolute_name : '(unknown)'
+
+ "#<%s:%x %s %p>" % [self.class, object_id, location, @text]
+ end
+
+ ##
+ # Normalizes the text. See RDoc::Text#normalize_comment for details
+
+ def normalize
+ return self unless @text
+ return self if @normalized # TODO eliminate duplicate normalization
+
+ @text = normalize_comment @text
+
+ @normalized = true
+
+ self
+ end
+
+ ##
+ # Was this text normalized?
+
+ def normalized? # :nodoc:
+ @normalized
+ end
+
+ ##
+ # Parses the comment into an RDoc::Markup::Document. The parsed document is
+ # cached until the text is changed.
+
+ def parse
+ return @document if @document
+
+ @document = super @text, @format
+ @document.file = @location
+ @document
+ end
+
+ ##
+ # Removes private sections from this comment. Private sections are flush to
+ # the comment marker and start with <tt>--</tt> and end with <tt>++</tt>.
+ # For C-style comments, a private marker may not start at the opening of the
+ # comment.
+ #
+ # /*
+ # *--
+ # * private
+ # *++
+ # * public
+ # */
+
+ def remove_private
+ # Workaround for gsub encoding for Ruby 1.9.2 and earlier
+ empty = ''
+ empty.force_encoding @text.encoding if Object.const_defined? :Encoding
+
+ @text = @text.gsub(%r%^\s*([#*]?)--.*?^\s*(\1)\+\+\n?%m, empty)
+ @text = @text.sub(%r%^\s*[#*]?--.*%m, '')
+ end
+
+ ##
+ # Replaces this comment's text with +text+ and resets the parsed document.
+ #
+ # An error is raised if the comment contains a document but no text.
+
+ def text= text
+ raise RDoc::Error, 'replacing document-only comment is not allowed' if
+ @text.nil? and @document
+
+ @document = nil
+ @text = text
+ end
+
+ ##
+ # Returns true if this comment is in TomDoc format.
+
+ def tomdoc?
+ @format == 'tomdoc'
+ end
+
+end
+
diff --git a/lib/rdoc/constant.rb b/lib/rdoc/constant.rb
index 056ce130be..d9fcf021ed 100644
--- a/lib/rdoc/constant.rb
+++ b/lib/rdoc/constant.rb
@@ -1,16 +1,14 @@
-require 'rdoc/code_object'
-
##
# A constant
class RDoc::Constant < RDoc::CodeObject
+ MARSHAL_VERSION = 0 # :nodoc:
+
##
- # If this constant is an alias for a module or class,
- # this is the RDoc::ClassModule it is an alias for.
- # +nil+ otherwise.
+ # Sets the module or class this is constant is an alias for.
- attr_accessor :is_alias_for
+ attr_writer :is_alias_for
##
# The constant's name
@@ -23,13 +21,22 @@ class RDoc::Constant < RDoc::CodeObject
attr_accessor :value
##
+ # The constant's visibility
+
+ attr_accessor :visibility
+
+ ##
# Creates a new constant with +name+, +value+ and +comment+
def initialize(name, value, comment)
super()
- @name = name
+
+ @name = name
@value = value
+
@is_alias_for = nil
+ @visibility = nil
+
self.comment = comment
end
@@ -59,6 +66,27 @@ class RDoc::Constant < RDoc::CodeObject
super or is_alias_for && is_alias_for.documented?
end
+ ##
+ # Full constant name including namespace
+
+ def full_name
+ @full_name ||= "#{parent_name}::#{@name}"
+ end
+
+ ##
+ # The module or class this constant is an alias for
+
+ def is_alias_for
+ case @is_alias_for
+ when String then
+ found = @store.find_class_or_module @is_alias_for
+ @is_alias_for = found if found
+ @is_alias_for
+ else
+ @is_alias_for
+ end
+ end
+
def inspect # :nodoc:
"#<%s:0x%x %s::%s>" % [
self.class, object_id,
@@ -67,12 +95,76 @@ class RDoc::Constant < RDoc::CodeObject
end
##
- # Path to this constant
+ # Dumps this Constant for use by ri. See also #marshal_load
+
+ def marshal_dump
+ alias_name = case found = is_alias_for
+ when RDoc::CodeObject then found.full_name
+ else found
+ end
+
+ [ MARSHAL_VERSION,
+ @name,
+ full_name,
+ @visibility,
+ alias_name,
+ parse(@comment),
+ @file.absolute_name,
+ parent.name,
+ parent.class,
+ section.title,
+ ]
+ end
+
+ ##
+ # Loads this Constant from +array+. For a loaded Constant the following
+ # methods will return cached values:
+ #
+ # * #full_name
+ # * #parent_name
+
+ def marshal_load array
+ initialize array[1], nil, array[5]
+
+ @full_name = array[2]
+ @visibility = array[3]
+ @is_alias_for = array[4]
+ # 5 handled above
+ # 6 handled below
+ @parent_name = array[7]
+ @parent_class = array[8]
+ @section_title = array[9]
+
+ @file = RDoc::TopLevel.new array[6]
+ end
+
+ ##
+ # Path to this constant for use with HTML generator output.
def path
"#{@parent.path}##{@name}"
end
+ def pretty_print q # :nodoc:
+ q.group 2, "[#{self.class.name} #{full_name}", "]" do
+ unless comment.empty? then
+ q.breakable
+ q.text "comment:"
+ q.breakable
+ q.pp @comment
+ end
+ end
+ end
+
+ ##
+ # Sets the store for this class or module and its contained code objects.
+
+ def store= store
+ super
+
+ @file = @store.add_file @file.full_name if @file
+ end
+
def to_s # :nodoc:
parent_name = parent ? parent.full_name : '(unknown)'
if is_alias_for
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
index abdab2026d..6f9deae4a8 100644
--- a/lib/rdoc/context.rb
+++ b/lib/rdoc/context.rb
@@ -1,4 +1,4 @@
-require 'rdoc/code_object'
+require 'cgi'
##
# A Context is something that can hold modules, classes, methods, attributes,
@@ -15,6 +15,12 @@ class RDoc::Context < RDoc::CodeObject
TYPES = %w[class instance]
##
+ # If a context has these titles it will be sorted in this order.
+
+ TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc:
+ TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc:
+
+ ##
# Class/module aliases
attr_reader :aliases
@@ -25,6 +31,11 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :attributes
##
+ # Block params to be used in the next MethodAttr parsed under this context
+
+ attr_accessor :block_params
+
+ ##
# Constants defined
attr_reader :constants
@@ -45,6 +56,11 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :includes
##
+ # Modules this context is extended with
+
+ attr_reader :extends
+
+ ##
# Methods defined in this context
attr_reader :method_list
@@ -72,7 +88,7 @@ class RDoc::Context < RDoc::CodeObject
attr_accessor :unmatched_alias_lists
##
- # Aliases that could not eventually be resolved.
+ # Aliases that could not be resolved.
attr_reader :external_aliases
@@ -88,121 +104,14 @@ class RDoc::Context < RDoc::CodeObject
attr_reader :methods_hash
##
- # Hash of registered constants.
+ # Params to be used in the next MethodAttr parsed under this context
- attr_reader :constants_hash
+ attr_accessor :params
##
- # A section of documentation like:
- #
- # # :section: The title
- # # The body
- #
- # Sections can be referenced multiple times and will be collapsed into a
- # single section.
-
- class Section
-
- include RDoc::Text
-
- ##
- # Section comment
-
- attr_reader :comment
-
- ##
- # Context this Section lives in
-
- attr_reader :parent
-
- ##
- # Section title
-
- attr_reader :title
-
- @@sequence = "SEC00000"
-
- ##
- # Creates a new section with +title+ and +comment+
-
- def initialize parent, title, comment
- @parent = parent
- @title = title ? title.strip : title
-
- @@sequence.succ!
- @sequence = @@sequence.dup
-
- @comment = extract_comment comment
- end
-
- ##
- # Sections are equal when they have the same #title
-
- def == other
- self.class === other and @title == other.title
- end
-
- ##
- # Anchor reference for linking to this section
-
- def aref
- title = @title || '[untitled]'
-
- CGI.escape(title).gsub('%', '-').sub(/^-/, '')
- end
-
- ##
- # Appends +comment+ to the current comment separated by a rule.
-
- def comment= comment
- comment = extract_comment comment
-
- return if comment.empty?
-
- if @comment then
- @comment += "\n# ---\n#{comment}"
- else
- @comment = comment
- end
- end
-
- ##
- # Extracts the comment for this section from the original comment block.
- # If the first line contains :section:, strip it and use the rest.
- # Otherwise remove lines up to the line containing :section:, and look
- # for those lines again at the end and remove them. This lets us write
- #
- # # :section: The title
- # # The body
-
- def extract_comment comment
- if comment =~ /^#[ \t]*:section:.*\n/ then
- start = $`
- rest = $'
-
- if start.empty? then
- rest
- else
- rest.sub(/#{start.chomp}\Z/, '')
- end
- else
- comment
- end
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %p>" % [self.class, object_id, title]
- end
-
- ##
- # Section sequence number (deprecated)
-
- def sequence
- warn "RDoc::Context::Section#sequence is deprecated, use #aref"
- @sequence
- end
+ # Hash of registered constants.
- end
+ attr_reader :constants_hash
##
# Creates an unnamed empty context with public current visibility
@@ -235,6 +144,7 @@ class RDoc::Context < RDoc::CodeObject
@aliases = []
@requires = []
@includes = []
+ @extends = []
@constants = []
@external_aliases = []
@@ -242,8 +152,12 @@ class RDoc::Context < RDoc::CodeObject
# a method not yet encountered).
@unmatched_alias_lists = {}
- @methods_hash = {}
+ @methods_hash = {}
@constants_hash = {}
+
+ @params = nil
+
+ @store ||= nil
end
##
@@ -366,12 +280,12 @@ class RDoc::Context < RDoc::CodeObject
if full_name =~ /^(.+)::(\w+)$/ then
name = $2
ename = $1
- enclosing = RDoc::TopLevel.classes_hash[ename] ||
- RDoc::TopLevel.modules_hash[ename]
+ enclosing = @store.classes_hash[ename] || @store.modules_hash[ename]
# HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming)
unless enclosing then
# try the given name at top level (will work for the above example)
- enclosing = RDoc::TopLevel.classes_hash[given_name] || RDoc::TopLevel.modules_hash[given_name]
+ enclosing = @store.classes_hash[given_name] ||
+ @store.modules_hash[given_name]
return enclosing if enclosing
# not found: create the parent(s)
names = ename.split('::')
@@ -410,7 +324,7 @@ class RDoc::Context < RDoc::CodeObject
end
# did we believe it was a module?
- mod = RDoc::TopLevel.modules_hash.delete superclass
+ mod = @store.modules_hash.delete superclass
upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod
@@ -418,7 +332,7 @@ class RDoc::Context < RDoc::CodeObject
superclass = nil if superclass == full_name
end
- klass = RDoc::TopLevel.classes_hash[full_name]
+ klass = @store.classes_hash[full_name]
if klass then
# if TopLevel, it may not be registered in the classes:
@@ -435,7 +349,7 @@ class RDoc::Context < RDoc::CodeObject
end
else
# this is a new class
- mod = RDoc::TopLevel.modules_hash.delete full_name
+ mod = @store.modules_hash.delete full_name
if mod then
klass = upgrade_to_class mod, RDoc::NormalClass, enclosing
@@ -445,10 +359,12 @@ class RDoc::Context < RDoc::CodeObject
klass = class_type.new name, superclass
enclosing.add_class_or_module(klass, enclosing.classes_hash,
- RDoc::TopLevel.classes_hash)
+ @store.classes_hash)
end
end
+ klass.parent = self
+
klass
end
@@ -463,6 +379,7 @@ class RDoc::Context < RDoc::CodeObject
mod.section = current_section # TODO declaring context? something is
# wrong here...
mod.parent = self
+ mod.store = @store
unless @done_documenting then
self_hash[mod.name] = mod
@@ -504,13 +421,21 @@ class RDoc::Context < RDoc::CodeObject
# Adds included module +include+ which should be an RDoc::Include
def add_include include
- add_to @includes, include unless
- @includes.map { |i| i.full_name }.include? include.full_name
+ add_to @includes, include
include
end
##
+ # Adds extension module +ext+ which should be an RDoc::Extend
+
+ def add_extend ext
+ add_to @extends, ext
+
+ ext
+ end
+
+ ##
# Adds +method+ if not already there. If it is (as method or attribute),
# updates the comment if it was empty.
@@ -523,6 +448,10 @@ class RDoc::Context < RDoc::CodeObject
if known then
known.comment = method.comment if known.comment.empty?
+ previously = ", previously in #{known.file}" unless
+ method.file == known.file
+ @store.rdoc.options.warn \
+ "Duplicate method #{known.full_name} in #{method.file}#{previously}"
else
@methods_hash[key] = method
method.visibility = @visibility
@@ -542,9 +471,9 @@ class RDoc::Context < RDoc::CodeObject
return mod if mod
full_name = child_name name
- mod = RDoc::TopLevel.modules_hash[full_name] || class_type.new(name)
+ mod = @store.modules_hash[full_name] || class_type.new(name)
- add_class_or_module(mod, @modules, RDoc::TopLevel.modules_hash)
+ add_class_or_module mod, @modules, @store.modules_hash
end
##
@@ -554,31 +483,34 @@ class RDoc::Context < RDoc::CodeObject
def add_module_alias from, name, file
return from if @done_documenting
- to_name = child_name(name)
+ to_name = child_name name
# if we already know this name, don't register an alias:
# see the metaprogramming in lib/active_support/basic_object.rb,
- # where we already know BasicObject as a class when we find
+ # where we already know BasicObject is a class when we find
# BasicObject = BlankSlate
- return from if RDoc::TopLevel.find_class_or_module(to_name)
+ return from if @store.find_class_or_module to_name
- if from.module? then
- RDoc::TopLevel.modules_hash[to_name] = from
- @modules[name] = from
+ to = from.dup
+ to.name = name
+ to.full_name = nil
+
+ if to.module? then
+ @store.modules_hash[to_name] = to
+ @modules[name] = to
else
- RDoc::TopLevel.classes_hash[to_name] = from
- @classes[name] = from
+ @store.classes_hash[to_name] = to
+ @classes[name] = to
end
- # HACK: register a constant for this alias:
- # constant value and comment will be updated after,
- # when the Ruby parser adds the constant
- const = RDoc::Constant.new name, nil, ''
+ # Registers a constant for this alias. The constant value and comment
+ # will be updated later, when the Ruby parser adds the constant
+ const = RDoc::Constant.new name, nil, to.comment
const.record_location file
const.is_alias_for = from
add_constant const
- from
+ to
end
##
@@ -602,9 +534,9 @@ class RDoc::Context < RDoc::CodeObject
#
# See also RDoc::Context::Section
- def add_section title, comment
+ def add_section title, comment = nil
if section = @sections[title] then
- section.comment = comment
+ section.add_comment comment if comment
else
section = Section.new self, title, comment
@sections[title] = section
@@ -616,9 +548,11 @@ class RDoc::Context < RDoc::CodeObject
##
# Adds +thing+ to the collection +array+
- def add_to(array, thing)
+ def add_to array, thing
array << thing if @document_self
- thing.parent = self
+
+ thing.parent = self
+ thing.store = @store if @store
thing.section = current_section
end
@@ -628,7 +562,7 @@ class RDoc::Context < RDoc::CodeObject
# This means any of: comment, aliases, methods, attributes, external
# aliases, require, constant.
#
- # Includes are also checked unless <tt>includes == false</tt>.
+ # Includes and extends are also checked unless <tt>includes == false</tt>.
def any_content(includes = true)
@any_content ||= !(
@@ -640,7 +574,7 @@ class RDoc::Context < RDoc::CodeObject
@requires.empty? &&
@constants.empty?
)
- @any_content || (includes && !@includes.empty?)
+ @any_content || (includes && !(@includes + @extends).empty? )
end
##
@@ -723,6 +657,9 @@ class RDoc::Context < RDoc::CodeObject
##
# Iterator for ancestors for duck-typing. Does nothing. See
# RDoc::ClassModule#each_ancestor.
+ #
+ # This method exists to make it easy to work with Context subclasses that
+ # aren't part of RDoc.
def each_ancestor # :nodoc:
end
@@ -756,10 +693,19 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Iterator for extension modules
+
+ def each_extend # :yields: extend
+ @extends.each do |e| yield e end
+ end
+
+ ##
# Iterator for methods
def each_method # :yields: method
- @method_list.sort.each {|m| yield m}
+ return enum_for __method__ unless block_given?
+
+ @method_list.sort.each { |m| yield m }
end
##
@@ -773,13 +719,15 @@ class RDoc::Context < RDoc::CodeObject
# NOTE: Do not edit collections yielded by this method
def each_section # :yields: section, constants, attributes
- constants = @constants.group_by do |constant| constant.section end
- constants.default = []
+ return enum_for __method__ unless block_given?
+ constants = @constants.group_by do |constant| constant.section end
attributes = @attributes.group_by do |attribute| attribute.section end
+
+ constants.default = []
attributes.default = []
- @sections.sort_by { |title, _| title.to_s }.each do |_, section|
+ sort_sections.each do |section|
yield section, constants[section].sort, attributes[section].sort
end
end
@@ -851,8 +799,8 @@ class RDoc::Context < RDoc::CodeObject
##
# Finds a file with +name+ in this context
- def find_file_named(name)
- top_level.class.find_file_named(name)
+ def find_file_named name
+ @store.find_file_named name
end
##
@@ -922,21 +870,21 @@ class RDoc::Context < RDoc::CodeObject
# look for a class or module 'symbol'
case symbol
when /^::/ then
- result = RDoc::TopLevel.find_class_or_module(symbol)
+ result = @store.find_class_or_module symbol
when /^(\w+):+(.+)$/
suffix = $2
top = $1
searched = self
- loop do
+ while searched do
mod = searched.find_module_named(top)
break unless mod
- result = RDoc::TopLevel.find_class_or_module(mod.full_name + '::' + suffix)
+ result = @store.find_class_or_module "#{mod.full_name}::#{suffix}"
break if result || searched.is_a?(RDoc::TopLevel)
searched = searched.parent
end
else
searched = self
- loop do
+ while searched do
result = searched.find_module_named(symbol)
break if result || searched.is_a?(RDoc::TopLevel)
searched = searched.parent
@@ -985,6 +933,8 @@ class RDoc::Context < RDoc::CodeObject
##
# Instance methods
+ #--
+ # TODO rename to instance_methods
def instance_method_list
@instance_method_list ||= method_list.reject { |a| a.singleton }
@@ -1098,24 +1048,23 @@ class RDoc::Context < RDoc::CodeObject
##
# Only called when min_visibility == :public or :private
- def remove_invisible_in(array, min_visibility) # :nodoc:
- if min_visibility == :public
+ def remove_invisible_in array, min_visibility # :nodoc:
+ if min_visibility == :public then
array.reject! { |e|
e.visibility != :public and not e.force_documentation
}
else
array.reject! { |e|
- e.visibility == :private and
- not e.force_documentation
+ e.visibility == :private and not e.force_documentation
}
end
end
##
- # Tries to resolve unmatched aliases when a method
- # or attribute has just been added.
+ # Tries to resolve unmatched aliases when a method or attribute has just
+ # been added.
- def resolve_aliases(added)
+ def resolve_aliases added
# resolve any pending unmatched aliases
key = added.pretty_name
unmatched_alias_list = @unmatched_alias_lists[key]
@@ -1128,6 +1077,31 @@ class RDoc::Context < RDoc::CodeObject
end
##
+ # Returns RDoc::Context::Section objects referenced in this context for use
+ # in a table of contents.
+
+ def section_contents
+ used_sections = {}
+
+ each_method do |method|
+ next unless method.display?
+
+ used_sections[method.section] = true
+ end
+
+ # order found sections
+ sections = sort_sections.select do |section|
+ used_sections[section]
+ end
+
+ # only the default section is used
+ return [] if
+ sections.length == 1 and not sections.first.title
+
+ sections
+ end
+
+ ##
# Sections in this context
def sections
@@ -1155,6 +1129,26 @@ class RDoc::Context < RDoc::CodeObject
end
end
+ ##
+ # Sorts sections alphabetically (default) or in TomDoc fashion (none,
+ # Public, Internal, Deprecated)
+
+ def sort_sections
+ titles = @sections.map { |title, _| title }
+
+ if titles.length > 1 and
+ TOMDOC_TITLES_SORT ==
+ (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then
+ @sections.values_at(*TOMDOC_TITLES).compact
+ else
+ @sections.sort_by { |title, _|
+ title.to_s
+ }.map { |_, section|
+ section
+ }
+ end
+ end
+
def to_s # :nodoc:
"#{self.class.name} #{self.full_name}"
end
@@ -1179,13 +1173,16 @@ class RDoc::Context < RDoc::CodeObject
enclosing.modules_hash.delete mod.name
klass = RDoc::ClassModule.from_module class_type, mod
+ klass.store = @store
# if it was there, then we keep it even if done_documenting
- RDoc::TopLevel.classes_hash[mod.full_name] = klass
- enclosing.classes_hash[mod.name] = klass
+ @store.classes_hash[mod.full_name] = klass
+ enclosing.classes_hash[mod.name] = klass
klass
end
+ autoload :Section, 'rdoc/context/section'
+
end
diff --git a/lib/rdoc/context/section.rb b/lib/rdoc/context/section.rb
new file mode 100644
index 0000000000..580f07deff
--- /dev/null
+++ b/lib/rdoc/context/section.rb
@@ -0,0 +1,238 @@
+##
+# A section of documentation like:
+#
+# # :section: The title
+# # The body
+#
+# Sections can be referenced multiple times and will be collapsed into a
+# single section.
+
+class RDoc::Context::Section
+
+ include RDoc::Text
+
+ MARSHAL_VERSION = 0 # :nodoc:
+
+ ##
+ # Section comment
+
+ attr_reader :comment
+
+ ##
+ # Section comments
+
+ attr_reader :comments
+
+ ##
+ # Context this Section lives in
+
+ attr_reader :parent
+
+ ##
+ # Section title
+
+ attr_reader :title
+
+ @@sequence = "SEC00000"
+
+ ##
+ # Creates a new section with +title+ and +comment+
+
+ def initialize parent, title, comment
+ @parent = parent
+ @title = title ? title.strip : title
+
+ @@sequence.succ!
+ @sequence = @@sequence.dup
+
+ @comments = []
+
+ add_comment comment
+ end
+
+ ##
+ # Sections are equal when they have the same #title
+
+ def == other
+ self.class === other and @title == other.title
+ end
+
+ ##
+ # Adds +comment+ to this section
+
+ def add_comment comment
+ comment = extract_comment comment
+
+ return if comment.empty?
+
+ case comment
+ when RDoc::Comment then
+ @comments << comment
+ when RDoc::Markup::Document then
+ @comments.concat comment.parts
+ when Array then
+ @comments.concat comment
+ else
+ raise TypeError, "unknown comment type: #{comment.inspect}"
+ end
+ end
+
+ ##
+ # Anchor reference for linking to this section
+
+ def aref
+ title = @title || '[untitled]'
+
+ CGI.escape(title).gsub('%', '-').sub(/^-/, '')
+ end
+
+ ##
+ # Extracts the comment for this section from the original comment block.
+ # If the first line contains :section:, strip it and use the rest.
+ # Otherwise remove lines up to the line containing :section:, and look
+ # for those lines again at the end and remove them. This lets us write
+ #
+ # # :section: The title
+ # # The body
+
+ def extract_comment comment
+ case comment
+ when Array then
+ comment.map do |c|
+ extract_comment c
+ end
+ when nil
+ RDoc::Comment.new ''
+ when RDoc::Comment then
+ if comment.text =~ /^#[ \t]*:section:.*\n/ then
+ start = $`
+ rest = $'
+
+ comment.text = if start.empty? then
+ rest
+ else
+ rest.sub(/#{start.chomp}\Z/, '')
+ end
+ end
+
+ comment
+ when RDoc::Markup::Document then
+ comment
+ else
+ raise TypeError, "unknown comment #{comment.inspect}"
+ end
+ end
+
+ def inspect # :nodoc:
+ "#<%s:0x%x %p>" % [self.class, object_id, title]
+ end
+
+ ##
+ # The files comments in this section come from
+
+ def in_files
+ return [] if @comments.empty?
+
+ case @comments
+ when Array then
+ @comments.map do |comment|
+ comment.file
+ end
+ when RDoc::Markup::Document then
+ @comment.parts.map do |document|
+ document.file
+ end
+ else
+ raise RDoc::Error, "BUG: unknown comment class #{@comments.class}"
+ end
+ end
+
+ ##
+ # Serializes this Section. The title and parsed comment are saved, but not
+ # the section parent which must be restored manually.
+
+ def marshal_dump
+ [
+ MARSHAL_VERSION,
+ @title,
+ parse,
+ ]
+ end
+
+ ##
+ # De-serializes this Section. The section parent must be restored manually.
+
+ def marshal_load array
+ @parent = nil
+
+ @title = array[1]
+ @comments = array[2]
+ end
+
+ ##
+ # Parses +comment_location+ into an RDoc::Markup::Document composed of
+ # multiple RDoc::Markup::Documents with their file set.
+
+ def parse
+ case @comments
+ when String then
+ super
+ when Array then
+ docs = @comments.map do |comment, location|
+ doc = super comment
+ doc.file = location if location
+ doc
+ end
+
+ RDoc::Markup::Document.new(*docs)
+ when RDoc::Comment then
+ doc = super @comments.text, comments.format
+ doc.file = @comments.location
+ doc
+ when RDoc::Markup::Document then
+ return @comments
+ else
+ raise ArgumentError, "unknown comment class #{comments.class}"
+ end
+ end
+
+ ##
+ # The section's title, or 'Top Section' if the title is nil.
+ #
+ # This is used by the table of contents template so the name is silly.
+
+ def plain_html
+ @title || 'Top Section'
+ end
+
+ ##
+ # Removes a comment from this section if it is from the same file as
+ # +comment+
+
+ def remove_comment comment
+ return if @comments.empty?
+
+ case @comments
+ when Array then
+ @comments.delete_if do |my_comment|
+ my_comment.file == comment.file
+ end
+ when RDoc::Markup::Document then
+ @comments.parts.delete_if do |document|
+ document.file == comment.file.name
+ end
+ else
+ raise RDoc::Error, "BUG: unknown comment class #{@comments.class}"
+ end
+ end
+
+ ##
+ # Section sequence number (deprecated)
+
+ def sequence
+ warn "RDoc::Context::Section#sequence is deprecated, use #aref"
+ @sequence
+ end
+
+end
+
diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb
index adeef2661a..c6f127387c 100644
--- a/lib/rdoc/cross_reference.rb
+++ b/lib/rdoc/cross_reference.rb
@@ -18,7 +18,7 @@ class RDoc::CrossReference
#
# See CLASS_REGEXP_STR
- METHOD_REGEXP_STR = '([a-z]\w*[!?=]?)(?:\([\w.+*/=<>-]*\))?'
+ METHOD_REGEXP_STR = '([a-z]\w*[!?=]?|%)(?:\([\w.+*/=<>-]*\))?'
##
# Regular expressions matching text that should potentially have
@@ -27,63 +27,79 @@ class RDoc::CrossReference
# 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 (preceded by a #)
- | \\?\##{METHOD_REGEXP_STR}
-
- # Stand-alone method (preceded by ::)
- | ::#{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-reference is a space, sentence
- # punctuation, tag start character, or attribute
- # marker.
- | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;<\000]|\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
- # Don't process things like '\<' in \<tt>, though.
- # TODO: including < is a hack, not very satisfying.
- | \\[^\s<]
- )/x
+ CROSSREF_REGEXP = /(?:^|\s)
+ (
+ (?:
+ # A::B::C.meth
+ #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
+
+ # Stand-alone method (preceded by a #)
+ | \\?\##{METHOD_REGEXP_STR}
+
+ # Stand-alone method (preceded by ::)
+ | ::#{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-reference is a space, sentence
+ # punctuation, tag start character, or attribute
+ # marker.
+ | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\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
+ # Don't process things like '\<' in \<tt>, though.
+ # TODO: including < is a hack, not very satisfying.
+ | \\[^\s<]
+ )
+
+ # labels for headings
+ (?:@[\w+%-]+(?:\.[\w|%-]+)?)?
+ )/x
##
# Version of CROSSREF_REGEXP used when <tt>--hyperlink-all</tt> is specified.
- ALL_CROSSREF_REGEXP = /(
- # A::B::C.meth
- #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
+ ALL_CROSSREF_REGEXP = /
+ (?:^|\s)
+ (
+ (?:
+ # A::B::C.meth
+ #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR}
- # Stand-alone method
- | \\?#{METHOD_REGEXP_STR}
+ # Stand-alone method
+ | \\?#{METHOD_REGEXP_STR}
- # A::B::C
- | #{CLASS_REGEXP_STR}(?=[\s\)\.\?\!\,\;<\000]|\z)
+ # A::B::C
+ | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z)
- # Things that look like filenames
- | (?:\.\.\/)*[-\/\w]+[_\/\.][-\w\/\.]+
+ # Things that look like filenames
+ | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+
- # Things that have markup suppressed
- | \\[^\s<]
- )/x
+ # Things that have markup suppressed
+ | \\[^\s<]
+ )
+
+ # labels for headings
+ (?:@[\w+%-]+)?
+ )/x
+
+ ##
+ # Hash of references that have been looked-up to their replacements
attr_accessor :seen
@@ -93,6 +109,7 @@ class RDoc::CrossReference
def initialize context
@context = context
+ @store = context.store
@seen = {}
end
@@ -107,16 +124,6 @@ class RDoc::CrossReference
def resolve name, text
return @seen[name] if @seen.include? name
- # Find class, module, or method in class or module.
- #
- # Do not, however, use an if/elsif/else chain to do so. Instead, test
- # each possible pattern until one matches. The reason for this is that a
- # string like "YAML.txt" could be the txt() class method of class YAML (in
- # which case it would match the first pattern, which splits the string
- # into container and method components and looks up both) or a filename
- # (in which case it would match the last pattern, which just checks
- # whether the string as a whole is a known symbol).
-
if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then
type = $2
type = '' if type == '.' # will find either #method or ::method
@@ -141,12 +148,15 @@ class RDoc::CrossReference
ref = case name
when /^\\(#{CLASS_REGEXP_STR})$/o then
- ref = @context.find_symbol $1
+ @context.find_symbol $1
else
- ref = @context.find_symbol name
+ @context.find_symbol name
end unless ref
- ref = nil if RDoc::Alias === ref # external alias: can't link to it
+ # Try a page name
+ ref = @store.page name if not ref and name =~ /^\w+$/
+
+ ref = nil if RDoc::Alias === ref # external alias, can't link to it
out = if name == '\\' then
name
diff --git a/lib/rdoc/encoding.rb b/lib/rdoc/encoding.rb
index ab752ee665..0b1ec6728e 100644
--- a/lib/rdoc/encoding.rb
+++ b/lib/rdoc/encoding.rb
@@ -1,7 +1,5 @@
# coding: US-ASCII
-require 'rdoc'
-
##
# This class is a wrapper around File IO and Encoding that helps RDoc load
# files and convert them to the correct encoding.
@@ -27,26 +25,40 @@ module RDoc::Encoding
RDoc::Encoding.set_encoding content
if Object.const_defined? :Encoding then
- encoding ||= Encoding.default_external
- orig_encoding = content.encoding
-
- if utf8 then
- content.force_encoding Encoding::UTF_8
- content.encode! encoding
- else
- # assume the content is in our output encoding
- content.force_encoding encoding
- end
-
- unless content.valid_encoding? then
- # revert and try to transcode
- content.force_encoding orig_encoding
- content.encode! encoding
- end
-
- unless content.valid_encoding? then
- warn "unable to convert #{filename} to #{encoding}, skipping"
- content = nil
+ begin
+ encoding ||= Encoding.default_external
+ orig_encoding = content.encoding
+
+ if utf8 then
+ content.force_encoding Encoding::UTF_8
+ content.encode! encoding
+ else
+ # assume the content is in our output encoding
+ content.force_encoding encoding
+ end
+
+ unless content.valid_encoding? then
+ # revert and try to transcode
+ content.force_encoding orig_encoding
+ content.encode! encoding
+ end
+
+ unless content.valid_encoding? then
+ warn "unable to convert #{filename} to #{encoding}, skipping"
+ content = nil
+ end
+ rescue Encoding::InvalidByteSequenceError,
+ Encoding::UndefinedConversionError => e
+ if force_transcode then
+ content.force_encoding orig_encoding
+ content.encode!(encoding,
+ :invalid => :replace, :undef => :replace,
+ :replace => '?')
+ return content
+ else
+ warn "unable to convert #{e.message} for #{filename}, skipping"
+ return nil
+ end
end
end
@@ -55,15 +67,6 @@ module RDoc::Encoding
raise unless e.message =~ /unknown encoding name - (.*)/
warn "unknown encoding name \"#{$1}\" for #{filename}, skipping"
nil
- rescue Encoding::UndefinedConversionError => e
- if force_transcode then
- content.force_encoding orig_encoding
- content.encode! encoding, :undef => :replace, :replace => '?'
- content
- else
- warn "unable to convert #{e.message} for #{filename}, skipping"
- nil
- end
rescue Errno::EISDIR, Errno::ENOENT
nil
end
diff --git a/lib/rdoc/erb_partial.rb b/lib/rdoc/erb_partial.rb
new file mode 100644
index 0000000000..910d1e0351
--- /dev/null
+++ b/lib/rdoc/erb_partial.rb
@@ -0,0 +1,18 @@
+##
+# Allows an ERB template to be rendered in the context (binding) of an
+# existing ERB template evaluation.
+
+class RDoc::ERBPartial < ERB
+
+ ##
+ # Overrides +compiler+ startup to set the +eoutvar+ to an empty string only
+ # if it isn't already set.
+
+ def set_eoutvar compiler, eoutvar = '_erbout'
+ super
+
+ compiler.pre_cmd = ["#{eoutvar} ||= ''"]
+ end
+
+end
+
diff --git a/lib/rdoc/extend.rb b/lib/rdoc/extend.rb
new file mode 100644
index 0000000000..2bccfba084
--- /dev/null
+++ b/lib/rdoc/extend.rb
@@ -0,0 +1,117 @@
+##
+# A Module extension in a class with \#extend
+
+class RDoc::Extend < RDoc::CodeObject
+
+ ##
+ # Name of extension module
+
+ attr_accessor :name
+
+ ##
+ # Creates a new Extend for +name+ with +comment+
+
+ def initialize(name, comment)
+ super()
+ @name = name
+ self.comment = comment
+ @module = nil # cache for module if found
+ end
+
+ ##
+ # Extends are sorted by name
+
+ def <=> other
+ return unless self.class === other
+
+ name <=> other.name
+ end
+
+ def == other # :nodoc:
+ self.class === other and @name == other.name
+ end
+
+ alias eql? ==
+
+ ##
+ # Full name based on #module
+
+ def full_name
+ m = self.module
+ RDoc::ClassModule === m ? m.full_name : @name
+ end
+
+ def hash # :nodoc:
+ [@name, self.module].hash
+ end
+
+ def inspect # :nodoc:
+ "#<%s:0x%x %s.extend %s>" % [
+ self.class,
+ object_id,
+ parent_name, @name,
+ ]
+ end
+
+ ##
+ # Attempts to locate the extend module object. Returns the name if not
+ # known.
+ #
+ # The scoping rules of Ruby to resolve the name of an extension module are:
+ # - first look into the children of the current context;
+ # - if not found, look into the children of extension modules,
+ # in reverse extend order;
+ # - if still not found, go up the hierarchy of names.
+ #
+ # This method has <code>O(n!)</code> behavior when the module calling
+ # extend is referencing nonexistent modules. Avoid calling #module until
+ # after all the files are parsed. This behavior is due to ruby's constant
+ # lookup behavior.
+
+ def module
+ return @module if @module
+
+ # search the current context
+ return @name unless parent
+ full_name = parent.child_name(@name)
+ @module = @store.modules_hash[full_name]
+ return @module if @module
+ return @name if @name =~ /^::/
+
+ # search the includes before this one, in reverse order
+ searched = parent.extends.take_while { |i| i != self }.reverse
+ searched.each do |i|
+ ext = i.module
+ next if String === ext
+ full_name = ext.child_name(@name)
+ @module = @store.modules_hash[full_name]
+ return @module if @module
+ end
+
+ # go up the hierarchy of names
+ up = parent.parent
+ while up
+ full_name = up.child_name(@name)
+ @module = @store.modules_hash[full_name]
+ return @module if @module
+ up = up.parent
+ end
+
+ @name
+ end
+
+ ##
+ # Sets the store for this class or module and its contained code objects.
+
+ def store= store
+ super
+
+ @file = @store.add_file @file.full_name if @file
+ end
+
+ def to_s # :nodoc:
+ "extend #@name in: #{parent}"
+ end
+
+end
+
diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb
index 2fa891f533..9051f8a658 100644
--- a/lib/rdoc/generator.rb
+++ b/lib/rdoc/generator.rb
@@ -1,12 +1,10 @@
-require 'rdoc'
-
##
# RDoc uses generators to turn parsed source code in the form of an
# RDoc::CodeObject tree into some form of output. RDoc comes with the HTML
# generator RDoc::Generator::Darkfish and an ri data generator
# RDoc::Generator::RI.
#
-# = Registering a Generator
+# == Registering a Generator
#
# Generators are registered by calling RDoc::RDoc.add_generator with the class
# of the generator:
@@ -15,26 +13,38 @@ require 'rdoc'
# RDoc::RDoc.add_generator self
# end
#
-# = Adding Options to +rdoc+
+# == Adding Options to +rdoc+
#
# Before option processing in +rdoc+, RDoc::Options will call ::setup_options
# on the generator class with an RDoc::Options instance. The generator can
# use RDoc::Options#option_parser to add command-line options to the +rdoc+
-# tool. See OptionParser for details on how to add options.
+# tool. See RDoc::Options@Custom+Options for an example and see OptionParser
+# for details on how to add options.
#
# You can extend the RDoc::Options instance with additional accessors for your
# generator.
#
-# = Generator Instantiation
+# == Generator Instantiation
#
# After parsing, RDoc::RDoc will instantiate a generator by calling
-# #initialize with an RDoc::Options instance.
+# #initialize with an RDoc::Store instance and an RDoc::Options instance.
+#
+# The RDoc::Store instance holds documentation for parsed source code. In
+# RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading
+# a generator from RDoc 3 and earlier you should only need to replace
+# RDoc::TopLevel with the store instance.
#
-# RDoc will then call #generate on the generator instance and pass in an Array
-# of RDoc::TopLevel instances, each representing a parsed file. You can use
-# the various class methods on RDoc::TopLevel and in the RDoc::CodeObject tree
-# to create your desired output format.
+# RDoc will then call #generate on the generator instance. You can use the
+# various methods on RDoc::Store and in the RDoc::CodeObject tree to create
+# your desired output format.
module RDoc::Generator
+
+ autoload :Markup, 'rdoc/generator/markup'
+
+ autoload :Darkfish, 'rdoc/generator/darkfish'
+ autoload :JsonIndex, 'rdoc/generator/json_index'
+ autoload :RI, 'rdoc/generator/ri'
+
end
diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb
index a3ffea0ce8..bd0f617d84 100644
--- a/lib/rdoc/generator/darkfish.rb
+++ b/lib/rdoc/generator/darkfish.rb
@@ -1,9 +1,8 @@
# -*- mode: ruby; ruby-indent-level: 2; tab-width: 2 -*-
-require 'pathname'
+require 'erb'
require 'fileutils'
-require 'rdoc/erbio'
-
+require 'pathname'
require 'rdoc/generator/markup'
##
@@ -46,6 +45,11 @@ require 'rdoc/generator/markup'
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# == Attributions
+#
+# Darkfish uses the {Silk Icons}[http://www.famfamfam.com/lab/icons/silk/] set
+# by Mark James.
class RDoc::Generator::Darkfish
@@ -53,6 +57,7 @@ class RDoc::Generator::Darkfish
include ERB::Util
+ ##
# Path to this file's parent directory. Used to find templates and other
# resources.
@@ -61,7 +66,7 @@ class RDoc::Generator::Darkfish
##
# Release Version
- VERSION = '2'
+ VERSION = '3'
##
# Description of this generator
@@ -69,19 +74,58 @@ class RDoc::Generator::Darkfish
DESCRIPTION = 'HTML generator, written by Michael Granger'
##
- # Initialize a few instance variables before we start
+ # The relative path to style sheets and javascript. By default this is set
+ # the same as the rel_prefix.
- def initialize options
- @options = options
+ attr_accessor :asset_rel_path
- @template_dir = Pathname.new options.template_dir
- @template_cache = {}
+ ##
+ # The path to generate files into, combined with <tt>--op</tt> from the
+ # options for a full path.
- @files = nil
- @classes = nil
+ attr_reader :base_dir
- @basedir = Pathname.pwd.expand_path
- end
+ ##
+ # Classes and modules to be used by this generator, not necessarily
+ # displayed. See also #modsort
+
+ attr_reader :classes
+
+ ##
+ # No files will be written when dry_run is true.
+
+ attr_accessor :dry_run
+
+ ##
+ # When false the generate methods return a String instead of writing to a
+ # file. The default is true.
+
+ attr_accessor :file_output
+
+ ##
+ # Files to be displayed by this generator
+
+ attr_reader :files
+
+ ##
+ # The JSON index generator for this Darkfish generator
+
+ attr_reader :json_index
+
+ ##
+ # Methods to be displayed by this generator
+
+ attr_reader :methods
+
+ ##
+ # Sorted list of classes and modules to be displayed by this generator
+
+ attr_reader :modsort
+
+ ##
+ # The RDoc::Store that is the source of the generated content
+
+ attr_reader :store
##
# The output directory
@@ -89,6 +133,29 @@ class RDoc::Generator::Darkfish
attr_reader :outputdir
##
+ # Initialize a few instance variables before we start
+
+ def initialize store, options
+ @store = store
+ @options = options
+
+ @asset_rel_path = ''
+ @base_dir = Pathname.pwd.expand_path
+ @dry_run = @options.dry_run
+ @file_output = true
+ @template_dir = Pathname.new options.template_dir
+ @template_cache = {}
+
+ @classes = nil
+ @context = nil
+ @files = nil
+ @methods = nil
+ @modsort = nil
+
+ @json_index = RDoc::Generator::JsonIndex.new self, options
+ end
+
+ ##
# Output progress information if debugging is enabled
def debug_msg *msg
@@ -126,7 +193,7 @@ class RDoc::Generator::Darkfish
def write_style_sheet
debug_msg "Copying static files"
- options = { :verbose => $DEBUG_RDOC, :noop => @options.dry_run }
+ options = { :verbose => $DEBUG_RDOC, :noop => @dry_run }
FileUtils.cp @template_dir + 'rdoc.css', '.', options
@@ -134,7 +201,7 @@ class RDoc::Generator::Darkfish
next if File.directory? path
next if File.basename(path) =~ /^\./
- dst = Pathname.new(path).relative_path_from @template_dir
+ dst = Pathname.new(path).relative_path_from @template_dir
# I suck at glob
dst_dir = dst.dirname
@@ -148,19 +215,17 @@ class RDoc::Generator::Darkfish
# Build the initial indices and output objects based on an array of TopLevel
# objects containing the extracted information.
- def generate top_levels
- @outputdir = Pathname.new(@options.op_dir).expand_path(@basedir)
-
- @files = top_levels.sort
- @classes = RDoc::TopLevel.all_classes_and_modules.sort
- @methods = @classes.map { |m| m.method_list }.flatten.sort
- @modsort = get_sorted_module_list(@classes)
+ def generate
+ setup
- # Now actually write the output
write_style_sheet
generate_index
generate_class_files
generate_file_files
+ generate_table_of_contents
+ @json_index.generate
+
+ copy_static
rescue => e
debug_msg "%s: %s\n %s" % [
@@ -170,42 +235,64 @@ class RDoc::Generator::Darkfish
raise
end
- protected
-
##
- # Return a list of the documented modules sorted by salience first, then
- # by name.
+ # Copies static files from the static_path into the output directory
+
+ def copy_static
+ return if @options.static_path.empty?
- def get_sorted_module_list(classes)
- nscounts = classes.inject({}) do |counthash, klass|
- top_level = klass.full_name.gsub(/::.*/, '')
- counthash[top_level] ||= 0
- counthash[top_level] += 1
+ fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run }
- counthash
+ @options.static_path.each do |path|
+ unless File.directory? path then
+ FileUtils.install path, @outputdir, fu_options.merge(:mode => 0644)
+ next
+ end
+
+ Dir.chdir path do
+ Dir[File.join('**', '*')].each do |entry|
+ dest_file = @outputdir + entry
+
+ if File.directory? entry then
+ FileUtils.mkdir_p entry, fu_options
+ else
+ FileUtils.install entry, dest_file, fu_options.merge(:mode => 0644)
+ end
+ end
+ end
end
+ end
- # Sort based on how often the top level namespace occurs, and then on the
- # name of the module -- this works for projects that put their stuff into
- # a namespace, of course, but doesn't hurt if they don't.
- classes.sort_by do |klass|
- top_level = klass.full_name.gsub( /::.*/, '' )
- [nscounts[top_level] * -1, klass.full_name]
- end.select do |klass|
+ ##
+ # Return a list of the documented modules sorted by salience first, then
+ # by name.
+
+ def get_sorted_module_list classes
+ classes.select do |klass|
klass.display?
- end
+ end.sort
end
##
# Generate an index page which lists all the classes which are documented.
def generate_index
+ setup
+
template_file = @template_dir + 'index.rhtml'
return unless template_file.exist?
debug_msg "Rendering the index page..."
- out_file = @basedir + @options.op_dir + 'index.html'
+ out_file = @base_dir + @options.op_dir + 'index.html'
+ rel_prefix = @outputdir.relative_path_from out_file.dirname
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
+ # suppress 1.9.3 warning
+ asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path
+
+ @title = @options.title
render_template template_file, out_file do |io| binding end
rescue => e
@@ -217,10 +304,40 @@ class RDoc::Generator::Darkfish
end
##
- # Generate a documentation file for each class
+ # Generates a class file for +klass+
+
+ def generate_class klass, template_file = nil
+ setup
+
+ current = klass
+
+ template_file ||= @template_dir + 'class.rhtml'
+
+ debug_msg " working on %s (%s)" % [klass.full_name, klass.path]
+ out_file = @outputdir + klass.path
+ rel_prefix = @outputdir.relative_path_from out_file.dirname
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
+ # suppress 1.9.3 warning
+ asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path
+ svninfo = svninfo = get_svninfo(current)
+
+ @title = "#{klass.type} #{klass.full_name} - #{@options.title}"
+
+ debug_msg " rendering #{out_file}"
+ render_template template_file, out_file do |io| binding end
+ end
+
+ ##
+ # Generate a documentation file for each class and module
def generate_class_files
- template_file = @template_dir + 'classpage.rhtml'
+ setup
+
+ template_file = @template_dir + 'class.rhtml'
+ template_file = @template_dir + 'classpage.rhtml' unless
+ template_file.exist?
return unless template_file.exist?
debug_msg "Generating class documentation in #{@outputdir}"
@@ -228,14 +345,8 @@ class RDoc::Generator::Darkfish
@classes.each do |klass|
current = klass
- debug_msg " working on %s (%s)" % [klass.full_name, klass.path]
- out_file = @outputdir + klass.path
- # suppress 1.9.3 warning
- rel_prefix = rel_prefix = @outputdir.relative_path_from(out_file.dirname)
- svninfo = svninfo = self.get_svninfo(klass)
- debug_msg " rendering #{out_file}"
- render_template template_file, out_file do |io| binding end
+ generate_class klass, template_file
end
rescue => e
error = RDoc::Error.new \
@@ -249,19 +360,56 @@ class RDoc::Generator::Darkfish
# Generate a documentation file for each file
def generate_file_files
- template_file = @template_dir + 'filepage.rhtml'
- return unless template_file.exist?
+ setup
+
+ page_file = @template_dir + 'page.rhtml'
+ fileinfo_file = @template_dir + 'fileinfo.rhtml'
+
+ # for legacy templates
+ filepage_file = @template_dir + 'filepage.rhtml' unless
+ page_file.exist? or fileinfo_file.exist?
+
+ return unless
+ page_file.exist? or fileinfo_file.exist? or filepage_file.exist?
+
debug_msg "Generating file documentation in #{@outputdir}"
out_file = nil
+ current = nil
@files.each do |file|
- out_file = @outputdir + file.path
+ current = file
+
+ if file.text? and page_file.exist? then
+ generate_page file
+ next
+ end
+
+ template_file = nil
+ out_file = @outputdir + file.path
debug_msg " working on %s (%s)" % [file.full_name, out_file]
+ rel_prefix = @outputdir.relative_path_from out_file.dirname
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
# suppress 1.9.3 warning
- rel_prefix = rel_prefix = @outputdir.relative_path_from(out_file.dirname)
+ asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path
+
+ unless filepage_file then
+ if file.text? then
+ next unless page_file.exist?
+ template_file = page_file
+ @title = file.page_name
+ else
+ next unless fileinfo_file.exist?
+ template_file = fileinfo_file
+ @title = "File: #{file.base_name}"
+ end
+ end
+
+ @title += " - #{@options.title}"
+ template_file ||= filepage_file
- debug_msg " rendering #{out_file}"
render_template template_file, out_file do |io| binding end
end
rescue => e
@@ -273,6 +421,134 @@ class RDoc::Generator::Darkfish
end
##
+ # Generate a page file for +file+
+
+ def generate_page file
+ setup
+
+ template_file = @template_dir + 'page.rhtml'
+
+ out_file = @outputdir + file.path
+ debug_msg " working on %s (%s)" % [file.full_name, out_file]
+ rel_prefix = @outputdir.relative_path_from out_file.dirname
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
+ # suppress 1.9.3 warning
+ current = current = file
+ asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path
+
+ @title = "#{file.page_name} - #{@options.title}"
+
+ debug_msg " rendering #{out_file}"
+ render_template template_file, out_file do |io| binding end
+ end
+
+ ##
+ # Generates the 404 page for the RDoc servlet
+
+ def generate_servlet_not_found path
+ setup
+
+ template_file = @template_dir + 'servlet_not_found.rhtml'
+ return unless template_file.exist?
+
+ debug_msg "Rendering the servlet root page..."
+
+ rel_prefix = rel_prefix = ''
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
+ # suppress 1.9.3 warning
+ asset_rel_prefix = asset_rel_prefix = ''
+
+ @title = 'Not Found'
+
+ render_template template_file do |io| binding end
+ rescue => e
+ error = RDoc::Error.new \
+ "error generating servlet_root: #{e.message} (#{e.class})"
+ error.set_backtrace e.backtrace
+
+ raise error
+ end
+
+ ##
+ # Generates the servlet root page for the RDoc servlet
+
+ def generate_servlet_root installed
+ setup
+
+ template_file = @template_dir + 'servlet_root.rhtml'
+ return unless template_file.exist?
+
+ debug_msg 'Rendering the servlet root page...'
+
+ rel_prefix = rel_prefix = ''
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
+ # suppress 1.9.3 warning
+ asset_rel_prefix = asset_rel_prefix = ''
+
+ @title = 'Local RDoc Documentation'
+
+ render_template template_file do |io| binding end
+ rescue => e
+ error = RDoc::Error.new \
+ "error generating servlet_root: #{e.message} (#{e.class})"
+ error.set_backtrace e.backtrace
+
+ raise error
+ end
+
+ ##
+ # Generate an index page which lists all the classes which are documented.
+
+ def generate_table_of_contents
+ setup
+
+ template_file = @template_dir + 'table_of_contents.rhtml'
+ return unless template_file.exist?
+
+ debug_msg "Rendering the Table of Contents..."
+
+ out_file = @outputdir + 'table_of_contents.html'
+ rel_prefix = @outputdir.relative_path_from out_file.dirname
+ search_index_rel_prefix = rel_prefix
+ search_index_rel_prefix += @asset_rel_path if @file_output
+
+ # suppress 1.9.3 warning
+ asset_rel_prefix = asset_rel_prefix = rel_prefix + @asset_rel_path
+
+ @title = "Table of Contents - #{@options.title}"
+
+ render_template template_file, out_file do |io| binding end
+ rescue => e
+ error = RDoc::Error.new \
+ "error generating table_of_contents.html: #{e.message} (#{e.class})"
+ error.set_backtrace e.backtrace
+
+ raise error
+ end
+
+ ##
+ # Prepares for generation of output from the current directory
+
+ def setup
+ return if instance_variable_defined? :@outputdir
+
+ @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir
+
+ return unless @store
+
+ @classes = @store.all_classes_and_modules.sort
+ @files = @store.all_files.sort
+ @methods = @classes.map { |m| m.method_list }.flatten.sort
+ @modsort = get_sorted_module_list @classes
+ end
+
+ ##
# Return a string describing the amount of time in the given number of
# seconds in terms a human can understand easily.
@@ -325,6 +601,46 @@ class RDoc::Generator::Darkfish
end
##
+ # Creates a template from its components and the +body_file+.
+ #
+ # For backwards compatibility, if +body_file+ contains "<html" the body is
+ # used directly.
+
+ def assemble_template body_file
+ body = body_file.read
+ return body if body =~ /<html/
+
+ head_file = @template_dir + '_head.rhtml'
+ footer_file = @template_dir + '_footer.rhtml'
+
+ <<-TEMPLATE
+<!DOCTYPE html>
+
+<html>
+<head>
+#{head_file.read}
+
+#{body}
+
+#{footer_file.read}
+ TEMPLATE
+ end
+
+ ##
+ # Renders the ERb contained in +file_name+ relative to the template
+ # directory and returns the result based on the current context.
+
+ def render file_name
+ template_file = @template_dir + file_name
+
+ template = template_for template_file, false, RDoc::ERBPartial
+
+ template.filename = template_file.to_s
+
+ template.result @context
+ end
+
+ ##
# Load and render the erb template in the given +template_file+ and write
# it out to +out_file+.
#
@@ -332,28 +648,33 @@ class RDoc::Generator::Darkfish
#
# An io will be yielded which must be captured by binding in the caller.
- def render_template template_file, out_file # :yield: io
- template = template_for template_file
+ def render_template template_file, out_file = nil # :yield: io
+ io_output = out_file && !@dry_run && @file_output
+ erb_klass = io_output ? RDoc::ERBIO : ERB
+
+ template = template_for template_file, true, erb_klass
- unless @options.dry_run then
+ if io_output then
debug_msg "Outputting to %s" % [out_file.expand_path]
out_file.dirname.mkpath
out_file.open 'w', 0644 do |io|
io.set_encoding @options.encoding if Object.const_defined? :Encoding
- context = yield io
+ @context = yield io
- template_result template, context, template_file
+ template_result template, @context, template_file
end
else
- context = yield nil
+ @context = yield nil
- output = template_result template, context, template_file
+ output = template_result template, @context, template_file
debug_msg " would have written %d characters to %s" % [
output.length, out_file.expand_path
- ]
+ ] if @dry_run
+
+ output
end
end
@@ -374,14 +695,25 @@ class RDoc::Generator::Darkfish
##
# Retrieves a cache template for +file+, if present, or fills the cache.
- def template_for file
+ def template_for file, page = true, klass = ERB
template = @template_cache[file]
return template if template
- klass = @options.dry_run ? ERB : RDoc::ERBIO
+ template = if page then
+ assemble_template file
+ else
+ file.read
+ end
+
+ erbout = if page then
+ 'io'
+ else
+ file_var = File.basename(file).sub(/\..*/, '')
+ "_erbout_#{file_var}"
+ end
- template = klass.new file.read, nil, '<>'
+ template = klass.new template, nil, '<>', erbout
@template_cache[file] = template
template
end
diff --git a/lib/rdoc/generator/json_index.rb b/lib/rdoc/generator/json_index.rb
new file mode 100644
index 0000000000..c303b2effb
--- /dev/null
+++ b/lib/rdoc/generator/json_index.rb
@@ -0,0 +1,248 @@
+require 'json'
+
+##
+# The JsonIndex generator is designed to complement an HTML generator and
+# produces a JSON search index. This generator is derived from sdoc by
+# Vladimir Kolesnikov and contains verbatim code written by him.
+#
+# This generator is designed to be used with a regular HTML generator:
+#
+# class RDoc::Generator::Darkfish
+# def initialize options
+# # ...
+# @base_dir = Pathname.pwd.expand_path
+#
+# @json_index = RDoc::Generator::JsonIndex.new self, options
+# end
+#
+# def generate
+# # ...
+# @json_index.generate
+# end
+# end
+#
+# == Index Format
+#
+# The index is output as a JSON file assigned to the global variable
+# +search_data+. The structure is:
+#
+# var search_data = {
+# "index": {
+# "searchIndex":
+# ["a", "b", ...],
+# "longSearchIndex":
+# ["a", "a::b", ...],
+# "info": [
+# ["A", "A", "A.html", "", ""],
+# ["B", "A::B", "A::B.html", "", ""],
+# ...
+# ]
+# }
+# }
+#
+# The same item is described across the +searchIndex+, +longSearchIndex+ and
+# +info+ fields. The +searchIndex+ field contains the item's short name, the
+# +longSearchIndex+ field contains the full_name (when appropriate) and the
+# +info+ field contains the item's name, full_name, path, parameters and a
+# snippet of the item's comment.
+#
+# == LICENSE
+#
+# Copyright (c) 2009 Vladimir Kolesnikov
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+class RDoc::Generator::JsonIndex
+
+ include RDoc::Text
+
+ ##
+ # Where the search index lives in the generated output
+
+ SEARCH_INDEX_FILE = File.join 'js', 'search_index.js'
+
+ attr_reader :index # :nodoc:
+
+ ##
+ # Creates a new generator. +parent_generator+ is used to determine the
+ # class_dir and file_dir of links in the output index.
+ #
+ # +options+ are the same options passed to the parent generator.
+
+ def initialize parent_generator, options
+ @parent_generator = parent_generator
+ @store = parent_generator.store
+ @options = options
+
+ @template_dir = File.expand_path '../template/json_index', __FILE__
+ @base_dir = @parent_generator.base_dir
+
+ @classes = nil
+ @files = nil
+ @index = nil
+ end
+
+ ##
+ # Builds the JSON index as a Hash.
+
+ def build_index
+ reset @store.all_files.sort, @store.all_classes_and_modules.sort
+
+ index_classes
+ index_methods
+ index_pages
+
+ { :index => @index }
+ end
+
+ ##
+ # Output progress information if debugging is enabled
+
+ def debug_msg *msg
+ return unless $DEBUG_RDOC
+ $stderr.puts(*msg)
+ end
+
+ ##
+ # Writes the JSON index to disk
+
+ def generate
+ debug_msg "Generating JSON index"
+
+ debug_msg " writing search index to %s" % SEARCH_INDEX_FILE
+ data = build_index
+
+ return if @options.dry_run
+
+ out_dir = @base_dir + @options.op_dir
+ index_file = out_dir + SEARCH_INDEX_FILE
+
+ FileUtils.mkdir_p index_file.dirname, :verbose => $DEBUG_RDOC
+
+ index_file.open 'w', 0644 do |io|
+ io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding
+ io.write 'var search_data = '
+
+ JSON.dump data, io, 0
+ end
+
+ Dir.chdir @template_dir do
+ Dir['**/*.js'].each do |source|
+ dest = File.join out_dir, source
+
+ FileUtils.install source, dest, :mode => 0644, :verbose => $DEBUG_RDOC
+ end
+ end
+ end
+
+ ##
+ # Adds classes and modules to the index
+
+ def index_classes
+ debug_msg " generating class search index"
+
+ documented = @classes.uniq.select do |klass|
+ klass.document_self_or_methods
+ end
+
+ documented.each do |klass|
+ debug_msg " #{klass.full_name}"
+ record = klass.search_record
+ @index[:searchIndex] << search_string(record.shift)
+ @index[:longSearchIndex] << search_string(record.shift)
+ @index[:info] << record
+ end
+ end
+
+ ##
+ # Adds methods to the index
+
+ def index_methods
+ debug_msg " generating method search index"
+
+ list = @classes.uniq.map do |klass|
+ klass.method_list
+ end.flatten.sort_by do |method|
+ [method.name, method.parent.full_name]
+ end
+
+ list.each do |method|
+ debug_msg " #{method.full_name}"
+ record = method.search_record
+ @index[:searchIndex] << "#{search_string record.shift}()"
+ @index[:longSearchIndex] << "#{search_string record.shift}()"
+ @index[:info] << record
+ end
+ end
+
+ ##
+ # Adds pages to the index
+
+ def index_pages
+ debug_msg " generating pages search index"
+
+ pages = @files.select do |file|
+ file.text?
+ end
+
+ pages.each do |page|
+ debug_msg " #{page.page_name}"
+ record = page.search_record
+ @index[:searchIndex] << search_string(record.shift)
+ @index[:longSearchIndex] << ''
+ record.shift
+ @index[:info] << record
+ end
+ end
+
+ ##
+ # The directory classes are written to
+
+ def class_dir
+ @parent_generator.class_dir
+ end
+
+ ##
+ # The directory files are written to
+
+ def file_dir
+ @parent_generator.file_dir
+ end
+
+ def reset files, classes # :nodoc:
+ @files = files
+ @classes = classes
+
+ @index = {
+ :searchIndex => [],
+ :longSearchIndex => [],
+ :info => []
+ }
+ end
+
+ ##
+ # Removes whitespace and downcases +string+
+
+ def search_string string
+ string.downcase.gsub(/\s/, '')
+ end
+
+end
+
diff --git a/lib/rdoc/generator/markup.rb b/lib/rdoc/generator/markup.rb
index c267bb1c13..3b3546690e 100644
--- a/lib/rdoc/generator/markup.rb
+++ b/lib/rdoc/generator/markup.rb
@@ -1,14 +1,8 @@
-# This file is loaded by generators. It allows RDoc's CodeObject tree to
-# avoid loading generator code to increase startup time (for ri).
-
-require 'rdoc/text'
-require 'rdoc/code_objects'
-require 'rdoc/generator'
-require 'rdoc/markup/to_html_crossref'
-require 'rdoc/ruby_token'
-
##
# Handle common RDoc::Markup tasks for various CodeObjects
+#
+# This module is loaded by generators. It allows RDoc's CodeObject tree to
+# avoid loading generator code to improve startup time for +ri+.
module RDoc::Generator::Markup
@@ -39,18 +33,18 @@ module RDoc::Generator::Markup
def formatter
return @formatter if defined? @formatter
- show_hash = RDoc::RDoc.current.options.show_hash
- hyperlink_all = RDoc::RDoc.current.options.hyperlink_all
+ options = @store.rdoc.options
this = RDoc::Context === self ? self : @parent
- @formatter = RDoc::Markup::ToHtmlCrossref.new(this.path, this, show_hash,
- hyperlink_all)
+ @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this
+ @formatter.code_object = self
+ @formatter
end
##
# Build a webcvs URL starting for the given +url+ with +full_path+ appended
# as the destination path. If +url+ contains '%s' +full_path+ will be
- # sprintf'd into +url+ instead.
+ # will replace the %s using sprintf on the +url+.
def cvs_url(url, full_path)
if /%s/ =~ url then
@@ -62,10 +56,14 @@ module RDoc::Generator::Markup
end
-class RDoc::AnyMethod
+class RDoc::CodeObject
include RDoc::Generator::Markup
+end
+
+class RDoc::MethodAttr
+
@add_line_numbers = false
class << self
@@ -82,7 +80,8 @@ class RDoc::AnyMethod
#
# # File xxxxx, line dddd
#
- # If it has, line numbers are added an ', line dddd' is removed.
+ # If it has this comment then line numbers are added to +src+ and the <tt>,
+ # line dddd</tt> portion of the comment is removed.
def add_line_numbers(src)
return unless src.sub!(/\A(.*)(, line (\d+))/, '\1')
@@ -111,32 +110,7 @@ class RDoc::AnyMethod
def markup_code
return '' unless @token_stream
- src = ""
-
- @token_stream.each do |t|
- next unless t
-
- style = case t
- when RDoc::RubyToken::TkCONSTANT then 'ruby-constant'
- when RDoc::RubyToken::TkKW then 'ruby-keyword'
- when RDoc::RubyToken::TkIVAR then 'ruby-ivar'
- when RDoc::RubyToken::TkOp then 'ruby-operator'
- when RDoc::RubyToken::TkId then 'ruby-identifier'
- when RDoc::RubyToken::TkNode then 'ruby-node'
- when RDoc::RubyToken::TkCOMMENT then 'ruby-comment'
- when RDoc::RubyToken::TkREGEXP then 'ruby-regexp'
- when RDoc::RubyToken::TkSTRING then 'ruby-string'
- when RDoc::RubyToken::TkVal then 'ruby-value'
- end
-
- text = CGI.escapeHTML t.text
-
- if style then
- src << "<span class=\"#{style}\">#{text}</span>"
- else
- src << text
- end
- end
+ src = RDoc::TokenStream.to_html @token_stream
# dedent the source
indent = src.length
@@ -151,34 +125,21 @@ class RDoc::AnyMethod
end
src.gsub!(/^#{' ' * indent}/, '') if indent > 0
- add_line_numbers(src) if self.class.add_line_numbers
+ add_line_numbers(src) if RDoc::MethodAttr.add_line_numbers
src
end
end
-class RDoc::Attr
+class RDoc::ClassModule
- include RDoc::Generator::Markup
-
-end
-
-class RDoc::Alias
-
- include RDoc::Generator::Markup
-
-end
-
-class RDoc::Constant
-
- include RDoc::Generator::Markup
-
-end
-
-class RDoc::Context
+ ##
+ # Handy wrapper for marking up this class or module's comment
- include RDoc::Generator::Markup
+ def description
+ markup @comment_location
+ end
end
@@ -195,7 +156,7 @@ class RDoc::TopLevel
# command line option to set.
def cvs_url
- url = RDoc::RDoc.current.options.webcvs
+ url = @store.rdoc.options.webcvs
if /%s/ =~ url then
url % @absolute_name
diff --git a/lib/rdoc/generator/ri.rb b/lib/rdoc/generator/ri.rb
index 939a165cfb..b9c4141a5e 100644
--- a/lib/rdoc/generator/ri.rb
+++ b/lib/rdoc/generator/ri.rb
@@ -1,6 +1,3 @@
-require 'rdoc/generator'
-require 'rdoc/ri'
-
##
# Generates ri data files
@@ -16,70 +13,17 @@ class RDoc::Generator::RI
##
# Set up a new ri generator
- def initialize options #:not-new:
- @options = options
- @old_siginfo = nil
- @current = nil
-
- @store = RDoc::RI::Store.new '.'
- @store.dry_run = @options.dry_run
- @store.encoding = @options.encoding if @options.respond_to? :encoding
- end
-
- ##
- # Build the initial indices and output objects based on an array of TopLevel
- # objects containing the extracted information.
-
- def generate top_levels
- install_siginfo_handler
-
- @store.load_cache
-
- RDoc::TopLevel.all_classes_and_modules.each do |klass|
- @current = "#{klass.class}: #{klass.full_name}"
-
- @store.save_class klass
-
- klass.each_method do |method|
- @current = "#{method.class}: #{method.full_name}"
- @store.save_method klass, method
- end
-
- klass.each_attribute do |attribute|
- @store.save_method klass, attribute
- end
- end
-
- @current = 'saving cache'
-
- @store.save_cache
-
- ensure
- @current = nil
-
- remove_siginfo_handler
+ def initialize store, options #:not-new:
+ @options = options
+ @store = store
+ @store.path = '.'
end
##
- # Installs a siginfo handler that prints the current filename.
-
- def install_siginfo_handler
- return unless Signal.list.key? 'INFO'
-
- @old_siginfo = trap 'INFO' do
- puts @current if @current
- end
- end
-
- ##
- # Removes a siginfo handler and replaces the previous
-
- def remove_siginfo_handler
- return unless Signal.list.key? 'INFO'
-
- handler = @old_siginfo || 'DEFAULT'
+ # Writes the parsed data store to disk for use by ri.
- trap 'INFO', handler
+ def generate
+ @store.save
end
end
diff --git a/lib/rdoc/generator/template/darkfish/_footer.rhtml b/lib/rdoc/generator/template/darkfish/_footer.rhtml
new file mode 100644
index 0000000000..0736c335ba
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_footer.rhtml
@@ -0,0 +1,5 @@
+<footer id="validator-badges">
+ <p><a href="http://validator.w3.org/check/referer">[Validate]</a>
+ <p>Generated by <a href="https://github.com/rdoc/rdoc">RDoc</a> <%= RDoc::VERSION %>.
+ <p>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %>.
+</footer>
diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml
new file mode 100644
index 0000000000..f3d82a37f6
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_head.rhtml
@@ -0,0 +1,16 @@
+<meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type">
+
+<title><%= h @title %></title>
+
+<link type="text/css" media="screen" href="<%= asset_rel_prefix %>/rdoc.css" rel="stylesheet">
+
+<script type="text/javascript">
+ var rdoc_rel_prefix = "<%= rel_prefix %>/";
+</script>
+
+<script type="text/javascript" charset="utf-8" src="<%= asset_rel_prefix %>/js/jquery.js"></script>
+<script type="text/javascript" charset="utf-8" src="<%= asset_rel_prefix %>/js/navigation.js"></script>
+<script type="text/javascript" charset="utf-8" src="<%= search_index_rel_prefix %>/js/search_index.js"></script>
+<script type="text/javascript" charset="utf-8" src="<%= asset_rel_prefix %>/js/search.js"></script>
+<script type="text/javascript" charset="utf-8" src="<%= asset_rel_prefix %>/js/searcher.js"></script>
+<script type="text/javascript" charset="utf-8" src="<%= asset_rel_prefix %>/js/darkfish.js"></script>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
new file mode 100644
index 0000000000..93d57f39f6
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml
@@ -0,0 +1,18 @@
+<% if !svninfo.empty? then %>
+<nav id="file-svninfo-section" class="section">
+ <h3 class="section-header">VCS Info</h3>
+ <div class="section-body">
+ <dl class="svninfo">
+ <dt>Rev
+ <dd><%= svninfo[:rev] %>
+
+ <dt>Last Checked In
+ <dd><%= svninfo[:commitdate].strftime('%Y-%m-%d %H:%M:%S') %>
+ (<%= svninfo[:commitdelta] %> ago)
+
+ <dt>Checked in by
+ <dd><%= svninfo[:committer] %>
+ </dl>
+ </div>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
new file mode 100644
index 0000000000..efa202fa18
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml
@@ -0,0 +1,9 @@
+<nav id="classindex-section" class="section project-section">
+ <h3 class="section-header">Class and Module Index</h3>
+
+ <ul class="link-list">
+ <% @modsort.each do |index_klass| %>
+ <li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a>
+ <% end %>
+ </ul>
+</nav>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
new file mode 100644
index 0000000000..19273829a0
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml
@@ -0,0 +1,16 @@
+<% unless klass.extends.empty? then %>
+<!-- Extension Modules -->
+<nav id="extends-section" class="section">
+ <h3 class="section-header">Extended With Modules</h3>
+
+ <ul class="link-list">
+ <% klass.each_extend do |ext| %>
+ <% unless String === ext.module then %>
+ <li><a class="extend" href="<%= klass.aref_to ext.module.path %>"><%= ext.module.full_name %></a>
+ <% else %>
+ <li><span class="extend"><%= ext.name %></span>
+ <% end %>
+ <% end %>
+ </ul>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
new file mode 100644
index 0000000000..c4ae216a14
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml
@@ -0,0 +1,8 @@
+<nav id="file-list-section" class="section">
+ <h3 class="section-header">Defined In</h3>
+ <ul>
+<% klass.in_files.each do |tl| %>
+ <li><%= h tl.absolute_name %>
+<% end %>
+ </ul>
+</nav>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
new file mode 100644
index 0000000000..5494f1f5f8
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml
@@ -0,0 +1,16 @@
+<% unless klass.includes.empty? then %>
+<!-- Included Modules -->
+<nav id="includes-section" class="section">
+ <h3 class="section-header">Included Modules</h3>
+
+ <ul class="link-list">
+ <% klass.each_include do |inc| %>
+ <% unless String === inc.module then %>
+ <li><a class="include" href="<%= klass.aref_to inc.module.path %>"><%= inc.module.full_name %></a>
+ <% else %>
+ <li><span class="include"><%= inc.name %></span>
+ <% end %>
+ <% end %>
+ </ul>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
new file mode 100644
index 0000000000..45a3048e84
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml
@@ -0,0 +1,14 @@
+<nav id="home-section" class="section">
+ <h3 class="section-header">Documentation</h3>
+
+ <ul>
+ <% installed.each do |name, href, exists| %>
+ <li class="folder">
+ <% if exists then %>
+ <a href="<%= href %>"><%= h name %></a>
+ <% else %>
+ <%= h name %>
+ <% end %>
+ <% end %>
+ </ul>
+</nav>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
new file mode 100644
index 0000000000..88e2734819
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml
@@ -0,0 +1,12 @@
+<% unless klass.method_list.empty? then %>
+<!-- Method Quickref -->
+<nav id="method-list-section" class="section">
+ <h3 class="section-header">Methods</h3>
+
+ <ul class="link-list">
+ <% klass.each_method do |meth| %>
+ <li <% if meth.calls_super %>class="calls-super" <% end %>><a href="#<%= meth.aref %>"><%= meth.singleton ? '::' : '#' %><%= h meth.name %></a>
+ <% end %>
+ </ul>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml
new file mode 100644
index 0000000000..fdeb6aed9f
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml
@@ -0,0 +1,7 @@
+<nav id="home-section" class="section">
+ <h3 class="section-header">
+ <a href="<%= rel_prefix %>/index.html">Home</a>
+ <a href="<%= rel_prefix %>/table_of_contents.html#classes">Classes</a>
+ <a href="<%= rel_prefix %>/table_of_contents.html#methods">Methods</a>
+ </h3>
+</nav>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
new file mode 100644
index 0000000000..2089387c51
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml
@@ -0,0 +1,12 @@
+<% simple_files = @files.select { |f| f.text? } %>
+<% unless simple_files.empty? then %>
+<nav id="fileindex-section" class="section project-section">
+ <h3 class="section-header">Pages</h3>
+
+ <ul>
+ <% simple_files.each do |f| %>
+ <li class="file"><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.page_name %></a>
+ <% end %>
+ </ul>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
new file mode 100644
index 0000000000..463f05a8d9
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml
@@ -0,0 +1,10 @@
+<% if klass.type == 'class' then %>
+<nav id="parent-class-section" class="section">
+ <h3 class="section-header">Parent</h3>
+ <% if klass.superclass and not String === klass.superclass then %>
+ <p class="link"><a href="<%= klass.aref_to klass.superclass.path %>"><%= klass.superclass.full_name %></a>
+ <% else %>
+ <p class="link"><%= klass.superclass %>
+ <% end %>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml
new file mode 100644
index 0000000000..f3275783d0
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml
@@ -0,0 +1,10 @@
+<nav id="search-section" class="section project-section" class="initially-hidden">
+ <form action="#" method="get" accept-charset="utf-8">
+ <h3 class="section-header">
+ <input type="text" name="search" placeholder="Search" id="search-field"
+ title="Type to search, Up and Down to navigate, Enter to load">
+ </h3>
+ </form>
+
+ <ul id="search-results" class="initially-hidden"></ul>
+</nav>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
new file mode 100644
index 0000000000..726423a341
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml
@@ -0,0 +1,10 @@
+<% unless klass.sections.length == 1 then %>
+<nav id="sections-section" class="section">
+ <h3 class="section-header">Sections</h3>
+ <ul class="link-list">
+ <% klass.sort_sections.each do |section| %>
+ <li><a href="#<%= section.aref %>"><%= h section.title %></a></li>
+ <% end %>
+ </ul>
+</nav>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
new file mode 100644
index 0000000000..225f811f0e
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml
@@ -0,0 +1,13 @@
+<% table = current.parse(current.comment).table_of_contents
+ if table.length > 1 then %>
+<div id="table-of-contents">
+ <nav class="section">
+ <h3 class="section-header">Table of Contents</h3>
+ <ul>
+<% table.each do |heading| %>
+ <li><a href="#<%= heading.aref %>"><%= heading.plain_html %></a>
+<% end %>
+ </ul>
+ </nav>
+</div>
+<% end %>
diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml
new file mode 100644
index 0000000000..c7e52e6808
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/class.rhtml
@@ -0,0 +1,179 @@
+<body id="top" class="<%= klass.type %>">
+<nav id="metadata">
+ <%= render '_sidebar_navigation.rhtml' %>
+
+ <%= render '_sidebar_search.rhtml' %>
+
+ <%= render '_sidebar_table_of_contents.rhtml' %>
+
+ <div id="file-metadata">
+ <%= render '_sidebar_in_files.rhtml' %>
+ <%= render '_sidebar_VCS_info.rhtml' %>
+ </div>
+
+ <div id="class-metadata">
+ <%= render '_sidebar_sections.rhtml' %>
+ <%= render '_sidebar_parent.rhtml' %>
+ <%= render '_sidebar_includes.rhtml' %>
+ <%= render '_sidebar_extends.rhtml' %>
+ <%= render '_sidebar_methods.rhtml' %>
+ </div>
+
+ <div id="project-metadata">
+ <%= render '_sidebar_pages.rhtml' %>
+ <%= render '_sidebar_classes.rhtml' %>
+ </div>
+</nav>
+
+<div id="documentation">
+ <h1 class="<%= klass.type %>"><%= klass.type %> <%= klass.full_name %></h1>
+
+ <div id="description" class="description">
+ <%= klass.description %>
+ </div><!-- description -->
+
+ <% klass.each_section do |section, constants, attributes| %>
+ <% constants = constants.select { |const| const.display? } %>
+ <% attributes = attributes.select { |attr| attr.display? } %>
+ <section id="<%= section.aref %>" class="documentation-section">
+ <% if section.title then %>
+ <div class="documentation-section-title">
+ <h2 class="section-header">
+ <%= section.title %>
+ </h2>
+ <span class="section-click-top">
+ <a href="#top">&uarr; top</a>
+ </span>
+ </div>
+ <% end %>
+
+ <% if section.comment then %>
+ <div class="description">
+ <%= section.description %>
+ </div>
+ <% end %>
+
+ <% unless constants.empty? then %>
+ <!-- Constants -->
+ <section id="constants-list" class="section">
+ <h3 class="section-header">Constants</h3>
+ <dl>
+ <% constants.each do |const| %>
+ <dt id="<%= const.name %>"><%= const.name %>
+ <% if const.comment then %>
+ <dd class="description"><%= const.description.strip %>
+ <% else %>
+ <dd class="description missing-docs">(Not documented)
+ <% end %>
+ <% end %>
+ </dl>
+ </section>
+ <% end %>
+
+ <% unless attributes.empty? then %>
+ <!-- Attributes -->
+ <section id="attribute-method-details" class="method-section section">
+ <h3 class="section-header">Attributes</h3>
+
+ <% attributes.each do |attrib| %>
+ <div id="<%= attrib.aref %>" class="method-detail">
+ <div class="method-heading attribute-method-heading">
+ <span class="method-name"><%= h attrib.name %></span><span
+ class="attribute-access-type">[<%= attrib.rw %>]</span>
+ </div>
+
+ <div class="method-description">
+ <% if attrib.comment then %>
+ <%= attrib.description.strip %>
+ <% else %>
+ <p class="missing-docs">(Not documented)
+ <% end %>
+ </div>
+ </div>
+ <% end %>
+ </section><!-- attribute-method-details -->
+ <% end %>
+
+ <!-- Methods -->
+ <% klass.methods_by_type(section).each do |type, visibilities|
+ next if visibilities.empty?
+ visibilities.each do |visibility, methods|
+ next if methods.empty? %>
+ <section id="<%= visibility %>-<%= type %>-<%= section.aref %>-method-details" class="method-section section">
+ <h3 class="section-header"><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
+
+ <% methods.each do |method| %>
+ <div id="<%= method.aref %>" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
+ <% if method.call_seq then %>
+ <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
+ <div class="method-heading">
+ <span class="method-callseq">
+ <%= h(call_seq.strip.
+ gsub( /^\w+\./m, '')).
+ gsub(/(.*)[-=]&gt;/, '\1&rarr;') %>
+ </span>
+ <% if i == 0 and method.token_stream then %>
+ <span class="method-click-advice">click to toggle source</span>
+ <% end %>
+ </div>
+ <% end %>
+ <% else %>
+ <div class="method-heading">
+ <span class="method-name"><%= h method.name %></span><span
+ class="method-args"><%= method.param_seq %></span>
+ <% if method.token_stream then %>
+ <span class="method-click-advice">click to toggle source</span>
+ <% end %>
+ </div>
+ <% end %>
+
+ <div class="method-description">
+ <% if method.comment then %>
+ <%= method.description.strip %>
+ <% else %>
+ <p class="missing-docs">(Not documented)
+ <% end %>
+ <% if method.calls_super then %>
+ <div class="method-calls-super">
+ Calls superclass method
+ <%=
+ method.superclass_method ?
+ method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil
+ %>
+ </div>
+ <% end %>
+
+ <% if method.token_stream then %>
+ <div class="method-source-code" id="<%= method.html_name %>-source">
+ <pre><%= method.markup_code %></pre>
+ </div><!-- <%= method.html_name %>-source -->
+ <% end %>
+ </div>
+
+ <% unless method.aliases.empty? then %>
+ <div class="aliases">
+ Also aliased as: <%= method.aliases.map do |aka|
+ if aka.parent then # HACK lib/rexml/encodings
+ %{<a href="#{klass.aref_to aka.path}">#{h aka.name}</a>}
+ else
+ h aka.name
+ end
+ end.join ", " %>
+ </div>
+ <% end %>
+
+ <% if method.is_alias_for then %>
+ <div class="aliases">
+ Alias for: <a href="<%= klass.aref_to method.is_alias_for.path %>"><%= h method.is_alias_for.name %></a>
+ </div>
+ <% end %>
+ </div><!-- <%= method.html_name %>-method -->
+
+ <% end %>
+ </section><!-- <%= visibility %>-<%= type %>-method-details -->
+ <% end
+ end %>
+ </section><!-- <%= section.aref %> -->
+<% end %>
+
+</div><!-- documentation -->
diff --git a/lib/rdoc/generator/template/darkfish/classpage.rhtml b/lib/rdoc/generator/template/darkfish/classpage.rhtml
deleted file mode 100644
index 9c74cacf0f..0000000000
--- a/lib/rdoc/generator/template/darkfish/classpage.rhtml
+++ /dev/null
@@ -1,321 +0,0 @@
-<?xml version="1.0" encoding="<%= @options.charset %>"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
-
- <title><%= klass.type.capitalize %>: <%= klass.full_name %></title>
-
- <link rel="stylesheet" href="<%= rel_prefix %>/rdoc.css" type="text/css" media="screen" />
-
- <script src="<%= rel_prefix %>/js/jquery.js" type="text/javascript" charset="utf-8"></script>
- <script src="<%= rel_prefix %>/js/thickbox-compressed.js" type="text/javascript" charset="utf-8"></script>
- <script src="<%= rel_prefix %>/js/quicksearch.js" type="text/javascript" charset="utf-8"></script>
- <script src="<%= rel_prefix %>/js/darkfish.js" type="text/javascript" charset="utf-8"></script>
-
-</head>
-<body id="top" class="<%= klass.type %>">
-
- <div id="metadata">
- <div id="home-metadata">
- <div id="home-section" class="section">
- <h3 class="section-header">
- <a href="<%= rel_prefix %>/index.html">Home</a>
- <a href="<%= rel_prefix %>/index.html#classes">Classes</a>
- <a href="<%= rel_prefix %>/index.html#methods">Methods</a>
- </h3>
- </div>
- </div>
-
- <div id="file-metadata">
- <div id="file-list-section" class="section">
- <h3 class="section-header">In Files</h3>
- <div class="section-body">
- <ul>
- <% klass.in_files.each do |tl| %>
- <li><a href="<%= rel_prefix %>/<%= h tl.path %>?TB_iframe=true&amp;height=550&amp;width=785"
- class="thickbox" title="<%= h tl.absolute_name %>"><%= h tl.absolute_name %></a></li>
- <% end %>
- </ul>
- </div>
- </div>
-
- <% if !svninfo.empty? then %>
- <div id="file-svninfo-section" class="section">
- <h3 class="section-header">Subversion Info</h3>
- <div class="section-body">
- <dl class="svninfo">
- <dt>Rev</dt>
- <dd><%= svninfo[:rev] %></dd>
-
- <dt>Last Checked In</dt>
- <dd><%= svninfo[:commitdate].strftime('%Y-%m-%d %H:%M:%S') %>
- (<%= svninfo[:commitdelta] %> ago)</dd>
-
- <dt>Checked in by</dt>
- <dd><%= svninfo[:committer] %></dd>
- </dl>
- </div>
- </div>
- <% end %>
- </div>
-
- <div id="class-metadata">
- <% if klass.type == 'class' then %>
- <!-- Parent Class -->
- <div id="parent-class-section" class="section">
- <h3 class="section-header">Parent</h3>
- <% if klass.superclass and not String === klass.superclass then %>
- <p class="link"><a href="<%= klass.aref_to klass.superclass.path %>"><%= klass.superclass.full_name %></a></p>
- <% else %>
- <p class="link"><%= klass.superclass %></p>
- <% end %>
- </div>
- <% end %>
-
- <% unless klass.sections.length == 1 then %>
- <!-- Sections -->
- <div id="sections-section" class="section">
- <h3 class="section-header">Sections</h3>
- <ul class="link-list">
- <% klass.sections.sort_by { |s| s.title.to_s }.each do |section| %>
- <li><a href="#<%= section.aref %>"><%= h section.title %></a></li>
- <% end %>
- </ul>
- </div>
- <% end %>
-
- <% unless klass.classes_and_modules.empty? then %>
- <!-- Namespace Contents -->
- <div id="namespace-list-section" class="section">
- <h3 class="section-header">Namespace</h3>
- <ul class="link-list">
- <% (klass.modules.sort + klass.classes.sort).each do |mod| %>
- <li><span class="type"><%= mod.type.upcase %></span> <a href="<%= klass.aref_to mod.path %>"><%= mod.full_name %></a></li>
- <% end %>
- </ul>
- </div>
- <% end %>
-
- <% unless klass.method_list.empty? then %>
- <!-- Method Quickref -->
- <div id="method-list-section" class="section">
- <h3 class="section-header">Methods</h3>
- <ul class="link-list">
- <% klass.each_method do |meth| %>
- <li><a href="#<%= meth.aref %>"><%= meth.singleton ? '::' : '#' %><%= meth.name %></a></li>
- <% end %>
- </ul>
- </div>
- <% end %>
-
- <% unless klass.includes.empty? then %>
- <!-- Included Modules -->
- <div id="includes-section" class="section">
- <h3 class="section-header">Included Modules</h3>
- <ul class="link-list">
- <% klass.each_include do |inc| %>
- <% unless String === inc.module then %>
- <li><a class="include" href="<%= klass.aref_to inc.module.path %>"><%= inc.module.full_name %></a></li>
- <% else %>
- <li><span class="include"><%= inc.name %></span></li>
- <% end %>
- <% end %>
- </ul>
- </div>
- <% end %>
- </div>
-
- <div id="project-metadata">
- <% simple_files = @files.select {|tl| tl.parser == RDoc::Parser::Simple } %>
- <% unless simple_files.empty? then %>
- <div id="fileindex-section" class="section project-section">
- <h3 class="section-header">Files</h3>
- <ul>
- <% simple_files.each do |file| %>
- <li class="file"><a href="<%= rel_prefix %>/<%= file.path %>"><%= h file.base_name %></a></li>
- <% end %>
- </ul>
- </div>
- <% end %>
-
- <div id="classindex-section" class="section project-section">
- <h3 class="section-header">Class/Module Index
- <span class="search-toggle"><img src="<%= rel_prefix %>/images/find.png"
- height="16" width="16" alt="[+]"
- title="show/hide quicksearch" /></span></h3>
- <form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
- <fieldset>
- <legend>Quicksearch</legend>
- <input type="text" name="quicksearch" value=""
- class="quicksearch-field" />
- </fieldset>
- </form>
-
- <ul class="link-list">
- <% @modsort.each do |index_klass| %>
- <li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a></li>
- <% end %>
- </ul>
- <div id="no-class-search-results" style="display: none;">No matching classes.</div>
- </div>
-
- <% if $DEBUG_RDOC then %>
- <div id="debugging-toggle"><img src="<%= rel_prefix %>/images/bug.png"
- alt="toggle debugging" height="16" width="16" /></div>
- <% end %>
- </div>
- </div>
-
- <div id="documentation">
- <h1 class="<%= klass.type %>"><%= klass.full_name %></h1>
-
- <div id="description" class="description">
- <%= klass.description %>
- </div><!-- description -->
-
- <% klass.each_section do |section, constants, attributes| %>
- <% constants = constants.select { |const| const.display? } %>
- <% attributes = attributes.select { |attr| attr.display? } %>
- <div id="<%= section.aref %>" class="documentation-section">
- <% if section.title then %>
- <h2 class="section-header">
- <%= section.title %>
- <a href="#top">&uarr; top</a>
- </h2>
- <% end %>
-
- <% if section.comment then %>
- <div class="description">
- <%= section.description %>
- </div>
- <% end %>
-
- <% unless constants.empty? then %>
- <!-- Constants -->
- <div id="constants-list" class="section">
- <h3 class="section-header">Constants</h3>
- <dl>
- <% constants.each do |const| %>
- <dt><a name="<%= const.name %>"><%= const.name %></a></dt>
- <% if const.comment then %>
- <dd class="description"><%= const.description.strip %></dd>
- <% else %>
- <dd class="description missing-docs">(Not documented)</dd>
- <% end %>
- <% end %>
- </dl>
- </div>
- <% end %>
-
- <% unless attributes.empty? then %>
- <!-- Attributes -->
- <div id="attribute-method-details" class="method-section section">
- <h3 class="section-header">Attributes</h3>
-
- <% attributes.each do |attrib| %>
- <div id="<%= attrib.html_name %>-attribute-method" class="method-detail">
- <a name="<%= h attrib.name %>"></a>
- <% if attrib.rw =~ /w/i then %>
- <a name="<%= h attrib.name %>="></a>
- <% end %>
- <div class="method-heading attribute-method-heading">
- <span class="method-name"><%= h attrib.name %></span><span
- class="attribute-access-type">[<%= attrib.rw %>]</span>
- </div>
-
- <div class="method-description">
- <% if attrib.comment then %>
- <%= attrib.description.strip %>
- <% else %>
- <p class="missing-docs">(Not documented)</p>
- <% end %>
- </div>
- </div>
- <% end %>
- </div><!-- attribute-method-details -->
- <% end %>
-
- <!-- Methods -->
- <% klass.methods_by_type(section).each do |type, visibilities|
- next if visibilities.empty?
- visibilities.each do |visibility, methods|
- next if methods.empty? %>
- <div id="<%= visibility %>-<%= type %>-method-details" class="method-section section">
- <h3 class="section-header"><%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods</h3>
-
- <% methods.each do |method| %>
- <div id="<%= method.html_name %>-method" class="method-detail <%= method.is_alias_for ? "method-alias" : '' %>">
- <a name="<%= h method.aref %>"></a>
-
- <% if method.call_seq then %>
- <% method.call_seq.strip.split("\n").each_with_index do |call_seq, i| %>
- <div class="method-heading">
- <span class="method-callseq"><%= call_seq.strip.gsub(/->/, '&rarr;').gsub( /^\w+\./m, '') %></span>
- <% if i == 0 then %>
- <span class="method-click-advice">click to toggle source</span>
- <% end %>
- </div>
- <% end %>
- <% else %>
- <div class="method-heading">
- <span class="method-name"><%= h method.name %></span><span
- class="method-args"><%= method.params %></span>
- <span class="method-click-advice">click to toggle source</span>
- </div>
- <% end %>
-
- <div class="method-description">
- <% if method.comment then %>
- <%= method.description.strip %>
- <% else %>
- <p class="missing-docs">(Not documented)</p>
- <% end %>
-
- <% if method.token_stream then %>
- <div class="method-source-code" id="<%= method.html_name %>-source">
-<pre>
-<%= method.markup_code %>
-</pre>
- </div><!-- <%= method.html_name %>-source -->
- <% end %>
- </div>
-
- <% unless method.aliases.empty? then %>
- <div class="aliases">
- Also aliased as: <%= method.aliases.map do |aka|
- if aka.parent then # HACK lib/rexml/encodings
- %{<a href="#{klass.aref_to aka.path}">#{h aka.name}</a>}
- else
- h aka.name
- end
- end.join ", " %>
- </div>
- <% end %>
-
- <% if method.is_alias_for then %>
- <div class="aliases">
- Alias for: <a href="<%= klass.aref_to method.is_alias_for.path %>"><%= h method.is_alias_for.name %></a>
- </div>
- <% end %>
- </div><!-- <%= method.html_name %>-method -->
-
- <% end %>
- </div><!-- <%= visibility %>-<%= type %>-method-details -->
- <% end
- end %>
- </div><!-- <%= section.aref %> -->
- <% end %>
-
- </div><!-- documentation -->
-
- <div id="validator-badges">
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
- <p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
- Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %></small>.</p>
- </div>
-
-</body>
-</html>
-
diff --git a/lib/rdoc/generator/template/darkfish/filepage.rhtml b/lib/rdoc/generator/template/darkfish/filepage.rhtml
deleted file mode 100644
index b230a456a3..0000000000
--- a/lib/rdoc/generator/template/darkfish/filepage.rhtml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
- <meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
-
- <title>File: <%= file.base_name %> [<%= @options.title %>]</title>
-
- <link type="text/css" media="screen" href="<%= rel_prefix %>/rdoc.css" rel="stylesheet" />
-
- <script src="<%= rel_prefix %>/js/jquery.js" type="text/javascript"
- charset="utf-8"></script>
- <script src="<%= rel_prefix %>/js/thickbox-compressed.js" type="text/javascript"
- charset="utf-8"></script>
- <script src="<%= rel_prefix %>/js/quicksearch.js" type="text/javascript"
- charset="utf-8"></script>
- <script src="<%= rel_prefix %>/js/darkfish.js" type="text/javascript"
- charset="utf-8"></script>
-</head>
-
-<% if file.parser == RDoc::Parser::Simple %>
-<body class="file">
- <div id="metadata">
- <div id="home-metadata">
- <div id="home-section" class="section">
- <h3 class="section-header">
- <a href="<%= rel_prefix %>/index.html">Home</a>
- <a href="<%= rel_prefix %>/index.html#classes">Classes</a>
- <a href="<%= rel_prefix %>/index.html#methods">Methods</a>
- </h3>
- </div>
- </div>
-
- <div id="project-metadata">
- <% simple_files = @files.select { |f| f.parser == RDoc::Parser::Simple } %>
- <% unless simple_files.empty? then %>
- <div id="fileindex-section" class="section project-section">
- <h3 class="section-header">Files</h3>
- <ul>
- <% simple_files.each do |f| %>
- <li class="file"><a href="<%= rel_prefix %>/<%= f.path %>"><%= h f.base_name %></a></li>
- <% end %>
- </ul>
- </div>
- <% end %>
-
- <div id="classindex-section" class="section project-section">
- <h3 class="section-header">Class Index
- <span class="search-toggle"><img src="<%= rel_prefix %>/images/find.png"
- height="16" width="16" alt="[+]"
- title="show/hide quicksearch" /></span></h3>
- <form action="#" method="get" accept-charset="utf-8" class="initially-hidden">
- <fieldset>
- <legend>Quicksearch</legend>
- <input type="text" name="quicksearch" value=""
- class="quicksearch-field" />
- </fieldset>
- </form>
-
- <ul class="link-list">
- <% @modsort.each do |index_klass| %>
- <li><a href="<%= rel_prefix %>/<%= index_klass.path %>"><%= index_klass.full_name %></a></li>
- <% end %>
- </ul>
- <div id="no-class-search-results" style="display: none;">No matching classes.</div>
- </div>
-
- <% if $DEBUG_RDOC %>
- <div id="debugging-toggle"><img src="<%= rel_prefix %>/images/bug.png"
- alt="toggle debugging" height="16" width="16" /></div>
- <% end %>
- </div>
- </div>
-
- <div id="documentation">
- <%= file.description %>
- </div>
-
- <div id="validator-badges">
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
- <p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
- Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %></small>.</p>
- </div>
-</body>
-<% else %>
-<body class="file file-popup">
- <div id="metadata">
- <dl>
- <dt class="modified-date">Last Modified</dt>
- <dd class="modified-date"><%= file.last_modified %></dd>
-
- <% if file.requires %>
- <dt class="requires">Requires</dt>
- <dd class="requires">
- <ul>
- <% file.requires.each do |require| %>
- <li><%= require.name %></li>
- <% end %>
- </ul>
- </dd>
- <% end %>
-
- <% if @options.webcvs %>
- <dt class="scs-url">Trac URL</dt>
- <dd class="scs-url"><a target="_top"
- href="<%= file.cvs_url %>"><%= file.cvs_url %></a></dd>
- <% end %>
- </dl>
- </div>
-
- <div id="documentation">
- <% if file.comment %>
- <div class="description">
- <h2>Description</h2>
- <%= file.description %>
- </div>
- <% end %>
- </div>
-</body>
-<% end %>
-</html>
-
diff --git a/lib/rdoc/generator/template/darkfish/images/add.png b/lib/rdoc/generator/template/darkfish/images/add.png
new file mode 100755
index 0000000000..6332fefea4
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/images/add.png
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/arrow_up.png b/lib/rdoc/generator/template/darkfish/images/arrow_up.png
new file mode 100755
index 0000000000..1ebb193243
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/images/arrow_up.png
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/delete.png b/lib/rdoc/generator/template/darkfish/images/delete.png
new file mode 100755
index 0000000000..08f249365a
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/images/delete.png
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/tag_blue.png b/lib/rdoc/generator/template/darkfish/images/tag_blue.png
new file mode 100755
index 0000000000..3f02b5f8f8
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/images/tag_blue.png
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/images/transparent.png b/lib/rdoc/generator/template/darkfish/images/transparent.png
new file mode 100644
index 0000000000..d665e179ef
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/images/transparent.png
Binary files differ
diff --git a/lib/rdoc/generator/template/darkfish/index.rhtml b/lib/rdoc/generator/template/darkfish/index.rhtml
index 3198246f8a..d076c2a252 100644
--- a/lib/rdoc/generator/template/darkfish/index.rhtml
+++ b/lib/rdoc/generator/template/darkfish/index.rhtml
@@ -1,64 +1,19 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
- "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<body>
+<nav id="metadata">
+ <%= render '_sidebar_navigation.rhtml' %>
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
-<head>
- <meta content="text/html; charset=<%= @options.charset %>" http-equiv="Content-Type" />
+ <%= render '_sidebar_search.rhtml' %>
- <title><%= h @options.title %></title>
-
- <link type="text/css" media="screen" href="rdoc.css" rel="stylesheet" />
-
- <script src="js/jquery.js" type="text/javascript" charset="utf-8"></script>
- <script src="js/thickbox-compressed.js" type="text/javascript" charset="utf-8"></script>
- <script src="js/quicksearch.js" type="text/javascript" charset="utf-8"></script>
- <script src="js/darkfish.js" type="text/javascript" charset="utf-8"></script>
-
-</head>
-<body class="indexpage">
-
- <% $stderr.sync = true %>
- <h1><%= h @options.title %></h1>
-
- <% if @options.main_page && main_page = @files.find { |f| f.full_name == @options.main_page } then %>
- <div id="main">
- <%= main_page.description.sub(%r{^\s*<h1.*?/h1>}i, '') %>
- </div>
- <% else %>
- <p>This is the API documentation for '<%= @options.title %>'.</p>
- <% end %>
-
- <% simple_files = @files.select {|tl| tl.parser == RDoc::Parser::Simple } %>
- <% unless simple_files.empty? then %>
- <h2>Files</h2>
- <ul>
- <% simple_files.sort.each do |file| %>
- <li class="file"><a href="<%= file.path %>"><%= h file.base_name %></a></li>
- <% end %>
- </ul>
- <% end %>
-
- <h2 id="classes">Classes/Modules</h2>
- <ul>
- <% @modsort.each do |klass| %>
- <li class="<%= klass.type %>"><a href="<%= klass.path %>"><%= klass.full_name %></a></li>
- <% end %>
- </ul>
-
- <h2 id="methods">Methods</h2>
- <ul>
- <% RDoc::TopLevel.all_classes_and_modules.map do |mod|
- mod.method_list
- end.flatten.sort.each do |method| %>
- <li><a href="<%= method.path %>"><%= method.pretty_name %> &mdash; <%= method.parent.full_name %></a></li>
- <% end %>
- </ul>
-
- <div id="validator-badges">
- <p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
- <p><small>Generated with the <a href="http://deveiate.org/projects/Darkfish-Rdoc/">Darkfish
- Rdoc Generator</a> <%= RDoc::Generator::Darkfish::VERSION %></small>.</p>
+ <div id="project-metadata">
+ <%= render '_sidebar_pages.rhtml' %>
+ <%= render '_sidebar_classes.rhtml' %>
</div>
-</body>
-</html>
+</nav>
+
+<div id="documentation" class="description">
+<% if @options.main_page && main_page = @files.find { |f| f.full_name == @options.main_page } then %>
+<%= main_page.description %>
+<% else %>
+<p>This is the API documentation for <%= @title %>.
+<% end %>
+</div>
diff --git a/lib/rdoc/generator/template/darkfish/js/darkfish.js b/lib/rdoc/generator/template/darkfish/js/darkfish.js
index 84565c1e2d..4be722fac3 100644
--- a/lib/rdoc/generator/template/darkfish/js/darkfish.js
+++ b/lib/rdoc/generator/template/darkfish/js/darkfish.js
@@ -9,12 +9,12 @@
/* Provide console simulation for firebug-less environments */
if (!("console" in window) || !("firebug" in console)) {
- var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
+ var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
"group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
- window.console = {};
- for (var i = 0; i < names.length; ++i)
- window.console[names[i]] = function() {};
+ window.console = {};
+ for (var i = 0; i < names.length; ++i)
+ window.console[names[i]] = function() {};
};
@@ -23,94 +23,131 @@ if (!("console" in window) || !("firebug" in console)) {
*/
$.fn.unwrap = function( expr ) {
return this.each( function() {
- $(this).parents( expr ).eq( 0 ).after( this ).remove();
+ $(this).parents( expr ).eq( 0 ).after( this ).remove();
});
};
function showSource( e ) {
- var target = e.target;
- var codeSections = $(target).
- parents('.method-detail').
- find('.method-source-code');
-
- $(target).
- parents('.method-detail').
- find('.method-source-code').
- slideToggle();
+ var target = e.target;
+ var codeSections = $(target).
+ parents('.method-detail').
+ find('.method-source-code');
+
+ $(target).
+ parents('.method-detail').
+ find('.method-source-code').
+ slideToggle();
};
function hookSourceViews() {
- $('.method-description,.method-heading').click( showSource );
+ $('.method-heading').click( showSource );
};
function toggleDebuggingSection() {
- $('.debugging-section').slideToggle();
+ $('.debugging-section').slideToggle();
};
function hookDebuggingToggle() {
- $('#debugging-toggle img').click( toggleDebuggingSection );
+ $('#debugging-toggle img').click( toggleDebuggingSection );
};
-function hookQuickSearch() {
- $('.quicksearch-field').each( function() {
- var searchElems = $(this).parents('.section').find( 'li' );
- var toggle = $(this).parents('.section').find('h3 .search-toggle');
- // console.debug( "Toggle is: %o", toggle );
- var qsbox = $(this).parents('form').get( 0 );
-
- $(this).quicksearch( this, searchElems, {
- noSearchResultsIndicator: 'no-class-search-results',
- focusOnLoad: false
- });
- $(toggle).click( function() {
- // console.debug( "Toggling qsbox: %o", qsbox );
- $(qsbox).toggle();
- });
- });
+function hookTableOfContentsToggle() {
+ $('.indexpage li .toc-toggle').each( function() {
+ $(this).click( function() {
+ $(this).toggleClass('open');
+ });
+
+ var section = $(this).next();
+
+ $(this).click( function() {
+ section.slideToggle();
+ });
+ });
+}
+
+function hookSearch() {
+ var input = $('#search-field').eq(0);
+ var result = $('#search-results').eq(0);
+ $(result).show();
+
+ var search_section = $('#search-section').get(0);
+ $(search_section).show();
+
+ var search = new Search(search_data, input, result);
+
+ search.renderItem = function(result) {
+ var li = document.createElement('li');
+ var html = '';
+
+ // TODO add relative path to <script> per-page
+ html += '<p class="search-match"><a href="' + rdoc_rel_prefix + result.path + '">' + this.hlt(result.title);
+ if (result.params)
+ html += '<span class="params">' + result.params + '</span>';
+ html += '</a>';
+
+
+ if (result.namespace)
+ html += '<p class="search-namespace">' + this.hlt(result.namespace);
+
+ if (result.snippet)
+ html += '<div class="search-snippet">' + result.snippet + '</div>';
+
+ li.innerHTML = html;
+
+ return li;
+ }
+
+ search.select = function(result) {
+ var result_element = result.get(0);
+ window.location.href = result_element.firstChild.firstChild.href;
+ }
+
+ search.scrollIntoView = search.scrollInWindow;
};
function highlightTarget( anchor ) {
- console.debug( "Highlighting target '%s'.", anchor );
-
- $("a[name=" + anchor + "]").each( function() {
- if ( !$(this).parent().parent().hasClass('target-section') ) {
- console.debug( "Wrapping the target-section" );
- $('div.method-detail').unwrap( 'div.target-section' );
- $(this).parent().wrap( '<div class="target-section"></div>' );
- } else {
- console.debug( "Already wrapped." );
- }
- });
+ console.debug( "Highlighting target '%s'.", anchor );
+
+ $("a[name=" + anchor + "]").each( function() {
+ if ( !$(this).parent().parent().hasClass('target-section') ) {
+ console.debug( "Wrapping the target-section" );
+ $('div.method-detail').unwrap( 'div.target-section' );
+ $(this).parent().wrap( '<div class="target-section"></div>' );
+ } else {
+ console.debug( "Already wrapped." );
+ }
+ });
};
function highlightLocationTarget() {
- console.debug( "Location hash: %s", window.location.hash );
- if ( ! window.location.hash || window.location.hash.length == 0 ) return;
+ console.debug( "Location hash: %s", window.location.hash );
+ if ( ! window.location.hash || window.location.hash.length == 0 ) return;
- var anchor = window.location.hash.substring(1);
- console.debug( "Found anchor: %s; matching %s", anchor, "a[name=" + anchor + "]" );
+ var anchor = window.location.hash.substring(1);
+ console.debug( "Found anchor: %s; matching %s", anchor, "a[name=" + anchor + "]" );
- highlightTarget( anchor );
+ highlightTarget( anchor );
};
function highlightClickTarget( event ) {
- console.debug( "Highlighting click target for event %o", event.target );
- try {
- var anchor = $(event.target).attr( 'href' ).substring(1);
- console.debug( "Found target anchor: %s", anchor );
- highlightTarget( anchor );
- } catch ( err ) {
- console.error( "Exception while highlighting: %o", err );
- };
+ console.debug( "Highlighting click target for event %o", event.target );
+ try {
+ var anchor = $(event.target).attr( 'href' ).substring(1);
+ console.debug( "Found target anchor: %s", anchor );
+ highlightTarget( anchor );
+ } catch ( err ) {
+ console.error( "Exception while highlighting: %o", err );
+ };
};
$(document).ready( function() {
- hookSourceViews();
- hookDebuggingToggle();
- hookQuickSearch();
- highlightLocationTarget();
+ hookSourceViews();
+ hookDebuggingToggle();
+ hookSearch();
+ highlightLocationTarget();
+ hookTableOfContentsToggle();
- $('ul.link-list a').bind( "click", highlightClickTarget );
+ $('ul.link-list a').bind( "click", highlightClickTarget );
});
diff --git a/lib/rdoc/generator/template/darkfish/js/jquery.js b/lib/rdoc/generator/template/darkfish/js/jquery.js
index afe9e74c90..48590ecb96 100644
--- a/lib/rdoc/generator/template/darkfish/js/jquery.js
+++ b/lib/rdoc/generator/template/darkfish/js/jquery.js
@@ -1,32 +1,18 @@
-/*
- * jQuery 1.2.6 - New Wave Javascript
+/*!
+ * jQuery JavaScript Library v1.6.2
+ * http://jquery.com/
*
- * Copyright (c) 2008 John Resig (jquery.com)
- * Dual licensed under the MIT (MIT-LICENSE.txt)
- * and GPL (GPL-LICENSE.txt) licenses.
+ * Copyright 2011, John Resig
+ * Dual licensed under the MIT or GPL Version 2 licenses.
+ * http://jquery.org/license
*
- * $Date: 2008-09-25 09:50:52 -0700 (Thu, 25 Sep 2008) $
- * $Rev: 38 $
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ * Copyright 2011, The Dojo Foundation
+ * Released under the MIT, BSD, and GPL Licenses.
+ *
+ * Date: Thu Jun 30 14:16:56 2011 -0400
*/
-(function(){var _jQuery=window.jQuery,_$=window.$;var jQuery=window.jQuery=window.$=function(selector,context){return new jQuery.fn.init(selector,context);};var quickExpr=/^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/,isSimple=/^.[^:#\[\.]*$/,undefined;jQuery.fn=jQuery.prototype={init:function(selector,context){selector=selector||document;if(selector.nodeType){this[0]=selector;this.length=1;return this;}if(typeof selector=="string"){var match=quickExpr.exec(selector);if(match&&(match[1]||!context)){if(match[1])selector=jQuery.clean([match[1]],context);else{var elem=document.getElementById(match[3]);if(elem){if(elem.id!=match[3])return jQuery().find(selector);return jQuery(elem);}selector=[];}}else
-return jQuery(context).find(selector);}else if(jQuery.isFunction(selector))return jQuery(document)[jQuery.fn.ready?"ready":"load"](selector);return this.setArray(jQuery.makeArray(selector));},jquery:"1.2.6",size:function(){return this.length;},length:0,get:function(num){return num==undefined?jQuery.makeArray(this):this[num];},pushStack:function(elems){var ret=jQuery(elems);ret.prevObject=this;return ret;},setArray:function(elems){this.length=0;Array.prototype.push.apply(this,elems);return this;},each:function(callback,args){return jQuery.each(this,callback,args);},index:function(elem){var ret=-1;return jQuery.inArray(elem&&elem.jquery?elem[0]:elem,this);},attr:function(name,value,type){var options=name;if(name.constructor==String)if(value===undefined)return this[0]&&jQuery[type||"attr"](this[0],name);else{options={};options[name]=value;}return this.each(function(i){for(name in options)jQuery.attr(type?this.style:this,name,jQuery.prop(this,options[name],type,i,name));});},css:function(key,value){if((key=='width'||key=='height')&&parseFloat(value)<0)value=undefined;return this.attr(key,value,"curCSS");},text:function(text){if(typeof text!="object"&&text!=null)return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(text));var ret="";jQuery.each(text||this,function(){jQuery.each(this.childNodes,function(){if(this.nodeType!=8)ret+=this.nodeType!=1?this.nodeValue:jQuery.fn.text([this]);});});return ret;},wrapAll:function(html){if(this[0])jQuery(html,this[0].ownerDocument).clone().insertBefore(this[0]).map(function(){var elem=this;while(elem.firstChild)elem=elem.firstChild;return elem;}).append(this);return this;},wrapInner:function(html){return this.each(function(){jQuery(this).contents().wrapAll(html);});},wrap:function(html){return this.each(function(){jQuery(this).wrapAll(html);});},append:function(){return this.domManip(arguments,true,false,function(elem){if(this.nodeType==1)this.appendChild(elem);});},prepend:function(){return this.domManip(arguments,true,true,function(elem){if(this.nodeType==1)this.insertBefore(elem,this.firstChild);});},before:function(){return this.domManip(arguments,false,false,function(elem){this.parentNode.insertBefore(elem,this);});},after:function(){return this.domManip(arguments,false,true,function(elem){this.parentNode.insertBefore(elem,this.nextSibling);});},end:function(){return this.prevObject||jQuery([]);},find:function(selector){var elems=jQuery.map(this,function(elem){return jQuery.find(selector,elem);});return this.pushStack(/[^+>] [^+>]/.test(selector)||selector.indexOf("..")>-1?jQuery.unique(elems):elems);},clone:function(events){var ret=this.map(function(){if(jQuery.browser.msie&&!jQuery.isXMLDoc(this)){var clone=this.cloneNode(true),container=document.createElement("div");container.appendChild(clone);return jQuery.clean([container.innerHTML])[0];}else
-return this.cloneNode(true);});var clone=ret.find("*").andSelf().each(function(){if(this[expando]!=undefined)this[expando]=null;});if(events===true)this.find("*").andSelf().each(function(i){if(this.nodeType==3)return;var events=jQuery.data(this,"events");for(var type in events)for(var handler in events[type])jQuery.event.add(clone[i],type,events[type][handler],events[type][handler].data);});return ret;},filter:function(selector){return this.pushStack(jQuery.isFunction(selector)&&jQuery.grep(this,function(elem,i){return selector.call(elem,i);})||jQuery.multiFilter(selector,this));},not:function(selector){if(selector.constructor==String)if(isSimple.test(selector))return this.pushStack(jQuery.multiFilter(selector,this,true));else
-selector=jQuery.multiFilter(selector,this);var isArrayLike=selector.length&&selector[selector.length-1]!==undefined&&!selector.nodeType;return this.filter(function(){return isArrayLike?jQuery.inArray(this,selector)<0:this!=selector;});},add:function(selector){return this.pushStack(jQuery.unique(jQuery.merge(this.get(),typeof selector=='string'?jQuery(selector):jQuery.makeArray(selector))));},is:function(selector){return!!selector&&jQuery.multiFilter(selector,this).length>0;},hasClass:function(selector){return this.is("."+selector);},val:function(value){if(value==undefined){if(this.length){var elem=this[0];if(jQuery.nodeName(elem,"select")){var index=elem.selectedIndex,values=[],options=elem.options,one=elem.type=="select-one";if(index<0)return null;for(var i=one?index:0,max=one?index+1:options.length;i<max;i++){var option=options[i];if(option.selected){value=jQuery.browser.msie&&!option.attributes.value.specified?option.text:option.value;if(one)return value;values.push(value);}}return values;}else
-return(this[0].value||"").replace(/\r/g,"");}return undefined;}if(value.constructor==Number)value+='';return this.each(function(){if(this.nodeType!=1)return;if(value.constructor==Array&&/radio|checkbox/.test(this.type))this.checked=(jQuery.inArray(this.value,value)>=0||jQuery.inArray(this.name,value)>=0);else if(jQuery.nodeName(this,"select")){var values=jQuery.makeArray(value);jQuery("option",this).each(function(){this.selected=(jQuery.inArray(this.value,values)>=0||jQuery.inArray(this.text,values)>=0);});if(!values.length)this.selectedIndex=-1;}else
-this.value=value;});},html:function(value){return value==undefined?(this[0]?this[0].innerHTML:null):this.empty().append(value);},replaceWith:function(value){return this.after(value).remove();},eq:function(i){return this.slice(i,i+1);},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments));},map:function(callback){return this.pushStack(jQuery.map(this,function(elem,i){return callback.call(elem,i,elem);}));},andSelf:function(){return this.add(this.prevObject);},data:function(key,value){var parts=key.split(".");parts[1]=parts[1]?"."+parts[1]:"";if(value===undefined){var data=this.triggerHandler("getData"+parts[1]+"!",[parts[0]]);if(data===undefined&&this.length)data=jQuery.data(this[0],key);return data===undefined&&parts[1]?this.data(parts[0]):data;}else
-return this.trigger("setData"+parts[1]+"!",[parts[0],value]).each(function(){jQuery.data(this,key,value);});},removeData:function(key){return this.each(function(){jQuery.removeData(this,key);});},domManip:function(args,table,reverse,callback){var clone=this.length>1,elems;return this.each(function(){if(!elems){elems=jQuery.clean(args,this.ownerDocument);if(reverse)elems.reverse();}var obj=this;if(table&&jQuery.nodeName(this,"table")&&jQuery.nodeName(elems[0],"tr"))obj=this.getElementsByTagName("tbody")[0]||this.appendChild(this.ownerDocument.createElement("tbody"));var scripts=jQuery([]);jQuery.each(elems,function(){var elem=clone?jQuery(this).clone(true)[0]:this;if(jQuery.nodeName(elem,"script"))scripts=scripts.add(elem);else{if(elem.nodeType==1)scripts=scripts.add(jQuery("script",elem).remove());callback.call(obj,elem);}});scripts.each(evalScript);});}};jQuery.fn.init.prototype=jQuery.fn;function evalScript(i,elem){if(elem.src)jQuery.ajax({url:elem.src,async:false,dataType:"script"});else
-jQuery.globalEval(elem.text||elem.textContent||elem.innerHTML||"");if(elem.parentNode)elem.parentNode.removeChild(elem);}function now(){return+new Date;}jQuery.extend=jQuery.fn.extend=function(){var target=arguments[0]||{},i=1,length=arguments.length,deep=false,options;if(target.constructor==Boolean){deep=target;target=arguments[1]||{};i=2;}if(typeof target!="object"&&typeof target!="function")target={};if(length==i){target=this;--i;}for(;i<length;i++)if((options=arguments[i])!=null)for(var name in options){var src=target[name],copy=options[name];if(target===copy)continue;if(deep&&copy&&typeof copy=="object"&&!copy.nodeType)target[name]=jQuery.extend(deep,src||(copy.length!=null?[]:{}),copy);else if(copy!==undefined)target[name]=copy;}return target;};var expando="jQuery"+now(),uuid=0,windowData={},exclude=/z-?index|font-?weight|opacity|zoom|line-?height/i,defaultView=document.defaultView||{};jQuery.extend({noConflict:function(deep){window.$=_$;if(deep)window.jQuery=_jQuery;return jQuery;},isFunction:function(fn){return!!fn&&typeof fn!="string"&&!fn.nodeName&&fn.constructor!=Array&&/^[\s[]?function/.test(fn+"");},isXMLDoc:function(elem){return elem.documentElement&&!elem.body||elem.tagName&&elem.ownerDocument&&!elem.ownerDocument.body;},globalEval:function(data){data=jQuery.trim(data);if(data){var head=document.getElementsByTagName("head")[0]||document.documentElement,script=document.createElement("script");script.type="text/javascript";if(jQuery.browser.msie)script.text=data;else
-script.appendChild(document.createTextNode(data));head.insertBefore(script,head.firstChild);head.removeChild(script);}},nodeName:function(elem,name){return elem.nodeName&&elem.nodeName.toUpperCase()==name.toUpperCase();},cache:{},data:function(elem,name,data){elem=elem==window?windowData:elem;var id=elem[expando];if(!id)id=elem[expando]=++uuid;if(name&&!jQuery.cache[id])jQuery.cache[id]={};if(data!==undefined)jQuery.cache[id][name]=data;return name?jQuery.cache[id][name]:id;},removeData:function(elem,name){elem=elem==window?windowData:elem;var id=elem[expando];if(name){if(jQuery.cache[id]){delete jQuery.cache[id][name];name="";for(name in jQuery.cache[id])break;if(!name)jQuery.removeData(elem);}}else{try{delete elem[expando];}catch(e){if(elem.removeAttribute)elem.removeAttribute(expando);}delete jQuery.cache[id];}},each:function(object,callback,args){var name,i=0,length=object.length;if(args){if(length==undefined){for(name in object)if(callback.apply(object[name],args)===false)break;}else
-for(;i<length;)if(callback.apply(object[i++],args)===false)break;}else{if(length==undefined){for(name in object)if(callback.call(object[name],name,object[name])===false)break;}else
-for(var value=object[0];i<length&&callback.call(value,i,value)!==false;value=object[++i]){}}return object;},prop:function(elem,value,type,i,name){if(jQuery.isFunction(value))value=value.call(elem,i);return value&&value.constructor==Number&&type=="curCSS"&&!exclude.test(name)?value+"px":value;},className:{add:function(elem,classNames){jQuery.each((classNames||"").split(/\s+/),function(i,className){if(elem.nodeType==1&&!jQuery.className.has(elem.className,className))elem.className+=(elem.className?" ":"")+className;});},remove:function(elem,classNames){if(elem.nodeType==1)elem.className=classNames!=undefined?jQuery.grep(elem.className.split(/\s+/),function(className){return!jQuery.className.has(classNames,className);}).join(" "):"";},has:function(elem,className){return jQuery.inArray(className,(elem.className||elem).toString().split(/\s+/))>-1;}},swap:function(elem,options,callback){var old={};for(var name in options){old[name]=elem.style[name];elem.style[name]=options[name];}callback.call(elem);for(var name in options)elem.style[name]=old[name];},css:function(elem,name,force){if(name=="width"||name=="height"){var val,props={position:"absolute",visibility:"hidden",display:"block"},which=name=="width"?["Left","Right"]:["Top","Bottom"];function getWH(){val=name=="width"?elem.offsetWidth:elem.offsetHeight;var padding=0,border=0;jQuery.each(which,function(){padding+=parseFloat(jQuery.curCSS(elem,"padding"+this,true))||0;border+=parseFloat(jQuery.curCSS(elem,"border"+this+"Width",true))||0;});val-=Math.round(padding+border);}if(jQuery(elem).is(":visible"))getWH();else
-jQuery.swap(elem,props,getWH);return Math.max(0,val);}return jQuery.curCSS(elem,name,force);},curCSS:function(elem,name,force){var ret,style=elem.style;function color(elem){if(!jQuery.browser.safari)return false;var ret=defaultView.getComputedStyle(elem,null);return!ret||ret.getPropertyValue("color")=="";}if(name=="opacity"&&jQuery.browser.msie){ret=jQuery.attr(style,"opacity");return ret==""?"1":ret;}if(jQuery.browser.opera&&name=="display"){var save=style.outline;style.outline="0 solid black";style.outline=save;}if(name.match(/float/i))name=styleFloat;if(!force&&style&&style[name])ret=style[name];else if(defaultView.getComputedStyle){if(name.match(/float/i))name="float";name=name.replace(/([A-Z])/g,"-$1").toLowerCase();var computedStyle=defaultView.getComputedStyle(elem,null);if(computedStyle&&!color(elem))ret=computedStyle.getPropertyValue(name);else{var swap=[],stack=[],a=elem,i=0;for(;a&&color(a);a=a.parentNode)stack.unshift(a);for(;i<stack.length;i++)if(color(stack[i])){swap[i]=stack[i].style.display;stack[i].style.display="block";}ret=name=="display"&&swap[stack.length-1]!=null?"none":(computedStyle&&computedStyle.getPropertyValue(name))||"";for(i=0;i<swap.length;i++)if(swap[i]!=null)stack[i].style.display=swap[i];}if(name=="opacity"&&ret=="")ret="1";}else if(elem.currentStyle){var camelCase=name.replace(/\-(\w)/g,function(all,letter){return letter.toUpperCase();});ret=elem.currentStyle[name]||elem.currentStyle[camelCase];if(!/^\d+(px)?$/i.test(ret)&&/^\d/.test(ret)){var left=style.left,rsLeft=elem.runtimeStyle.left;elem.runtimeStyle.left=elem.currentStyle.left;style.left=ret||0;ret=style.pixelLeft+"px";style.left=left;elem.runtimeStyle.left=rsLeft;}}return ret;},clean:function(elems,context){var ret=[];context=context||document;if(typeof context.createElement=='undefined')context=context.ownerDocument||context[0]&&context[0].ownerDocument||document;jQuery.each(elems,function(i,elem){if(!elem)return;if(elem.constructor==Number)elem+='';if(typeof elem=="string"){elem=elem.replace(/(<(\w+)[^>]*?)\/>/g,function(all,front,tag){return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?all:front+"></"+tag+">";});var tags=jQuery.trim(elem).toLowerCase(),div=context.createElement("div");var wrap=!tags.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!tags.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||tags.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!tags.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!tags.indexOf("<td")||!tags.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!tags.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||jQuery.browser.msie&&[1,"div<div>","</div>"]||[0,"",""];div.innerHTML=wrap[1]+elem+wrap[2];while(wrap[0]--)div=div.lastChild;if(jQuery.browser.msie){var tbody=!tags.indexOf("<table")&&tags.indexOf("<tbody")<0?div.firstChild&&div.firstChild.childNodes:wrap[1]=="<table>"&&tags.indexOf("<tbody")<0?div.childNodes:[];for(var j=tbody.length-1;j>=0;--j)if(jQuery.nodeName(tbody[j],"tbody")&&!tbody[j].childNodes.length)tbody[j].parentNode.removeChild(tbody[j]);if(/^\s/.test(elem))div.insertBefore(context.createTextNode(elem.match(/^\s*/)[0]),div.firstChild);}elem=jQuery.makeArray(div.childNodes);}if(elem.length===0&&(!jQuery.nodeName(elem,"form")&&!jQuery.nodeName(elem,"select")))return;if(elem[0]==undefined||jQuery.nodeName(elem,"form")||elem.options)ret.push(elem);else
-ret=jQuery.merge(ret,elem);});return ret;},attr:function(elem,name,value){if(!elem||elem.nodeType==3||elem.nodeType==8)return undefined;var notxml=!jQuery.isXMLDoc(elem),set=value!==undefined,msie=jQuery.browser.msie;name=notxml&&jQuery.props[name]||name;if(elem.tagName){var special=/href|src|style/.test(name);if(name=="selected"&&jQuery.browser.safari)elem.parentNode.selectedIndex;if(name in elem&&notxml&&!special){if(set){if(name=="type"&&jQuery.nodeName(elem,"input")&&elem.parentNode)throw"type property can't be changed";elem[name]=value;}if(jQuery.nodeName(elem,"form")&&elem.getAttributeNode(name))return elem.getAttributeNode(name).nodeValue;return elem[name];}if(msie&&notxml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&&notxml&&special?elem.getAttribute(name,2):elem.getAttribute(name);return attr===null?undefined:attr;}if(msie&&name=="opacity"){if(set){elem.zoom=1;elem.filter=(elem.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(value)+''=="NaN"?"":"alpha(opacity="+value*100+")");}return elem.filter&&elem.filter.indexOf("opacity=")>=0?(parseFloat(elem.filter.match(/opacity=([^)]*)/)[1])/100)+'':"";}name=name.replace(/-([a-z])/ig,function(all,letter){return letter.toUpperCase();});if(set)elem[name]=value;return elem[name];},trim:function(text){return(text||"").replace(/^\s+|\s+$/g,"");},makeArray:function(array){var ret=[];if(array!=null){var i=array.length;if(i==null||array.split||array.setInterval||array.call)ret[0]=array;else
-while(i)ret[--i]=array[i];}return ret;},inArray:function(elem,array){for(var i=0,length=array.length;i<length;i++)if(array[i]===elem)return i;return-1;},merge:function(first,second){var i=0,elem,pos=first.length;if(jQuery.browser.msie){while(elem=second[i++])if(elem.nodeType!=8)first[pos++]=elem;}else
-while(elem=second[i++])first[pos++]=elem;return first;},unique:function(array){var ret=[],done={};try{for(var i=0,length=array.length;i<length;i++){var id=jQuery.data(array[i]);if(!done[id]){done[id]=true;ret.push(array[i]);}}}catch(e){ret=array;}return ret;},grep:function(elems,callback,inv){var ret=[];for(var i=0,length=elems.length;i<length;i++)if(!inv!=!callback(elems[i],i))ret.push(elems[i]);return ret;},map:function(elems,callback){var ret=[];for(var i=0,length=elems.length;i<length;i++){var value=callback(elems[i],i);if(value!=null)ret[ret.length]=value;}return ret.concat.apply([],ret);}});var userAgent=navigator.userAgent.toLowerCase();jQuery.browser={version:(userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[])[1],safari:/webkit/.test(userAgent),opera:/opera/.test(userAgent),msie:/msie/.test(userAgent)&&!/opera/.test(userAgent),mozilla:/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)};var styleFloat=jQuery.browser.msie?"styleFloat":"cssFloat";jQuery.extend({boxModel:!jQuery.browser.msie||document.compatMode=="CSS1Compat",props:{"for":"htmlFor","class":"className","float":styleFloat,cssFloat:styleFloat,styleFloat:styleFloat,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing"}});jQuery.each({parent:function(elem){return elem.parentNode;},parents:function(elem){return jQuery.dir(elem,"parentNode");},next:function(elem){return jQuery.nth(elem,2,"nextSibling");},prev:function(elem){return jQuery.nth(elem,2,"previousSibling");},nextAll:function(elem){return jQuery.dir(elem,"nextSibling");},prevAll:function(elem){return jQuery.dir(elem,"previousSibling");},siblings:function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},children:function(elem){return jQuery.sibling(elem.firstChild);},contents:function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}},function(name,fn){jQuery.fn[name]=function(selector){var ret=jQuery.map(this,fn);if(selector&&typeof selector=="string")ret=jQuery.multiFilter(selector,ret);return this.pushStack(jQuery.unique(ret));};});jQuery.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(name,original){jQuery.fn[name]=function(){var args=arguments;return this.each(function(){for(var i=0,length=args.length;i<length;i++)jQuery(args[i])[original](this);});};});jQuery.each({removeAttr:function(name){jQuery.attr(this,name,"");if(this.nodeType==1)this.removeAttribute(name);},addClass:function(classNames){jQuery.className.add(this,classNames);},removeClass:function(classNames){jQuery.className.remove(this,classNames);},toggleClass:function(classNames){jQuery.className[jQuery.className.has(this,classNames)?"remove":"add"](this,classNames);},remove:function(selector){if(!selector||jQuery.filter(selector,[this]).r.length){jQuery("*",this).add(this).each(function(){jQuery.event.remove(this);jQuery.removeData(this);});if(this.parentNode)this.parentNode.removeChild(this);}},empty:function(){jQuery(">*",this).remove();while(this.firstChild)this.removeChild(this.firstChild);}},function(name,fn){jQuery.fn[name]=function(){return this.each(fn,arguments);};});jQuery.each(["Height","Width"],function(i,name){var type=name.toLowerCase();jQuery.fn[type]=function(size){return this[0]==window?jQuery.browser.opera&&document.body["client"+name]||jQuery.browser.safari&&window["inner"+name]||document.compatMode=="CSS1Compat"&&document.documentElement["client"+name]||document.body["client"+name]:this[0]==document?Math.max(Math.max(document.body["scroll"+name],document.documentElement["scroll"+name]),Math.max(document.body["offset"+name],document.documentElement["offset"+name])):size==undefined?(this.length?jQuery.css(this[0],type):null):this.css(type,size.constructor==String?size:size+"px");};});function num(elem,prop){return elem[0]&&parseInt(jQuery.curCSS(elem[0],prop,true),10)||0;}var chars=jQuery.browser.safari&&parseInt(jQuery.browser.version)<417?"(?:[\\w*_-]|\\\\.)":"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",quickChild=new RegExp("^>\\s*("+chars+"+)"),quickID=new RegExp("^("+chars+"+)(#)("+chars+"+)"),quickClass=new RegExp("^([#.]?)("+chars+"*)");jQuery.extend({expr:{"":function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},"#":function(a,i,m){return a.getAttribute("id")==m[2];},":":{lt:function(a,i,m){return i<m[3]-0;},gt:function(a,i,m){return i>m[3]-0;},nth:function(a,i,m){return m[3]-0==i;},eq:function(a,i,m){return m[3]-0==i;},first:function(a,i){return i==0;},last:function(a,i,m,r){return i==r.length-1;},even:function(a,i){return i%2==0;},odd:function(a,i){return i%2;},"first-child":function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},"last-child":function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},"only-child":function(a){return!jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},parent:function(a){return a.firstChild;},empty:function(a){return!a.firstChild;},contains:function(a,i,m){return(a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},visible:function(a){return"hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},hidden:function(a){return"hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},enabled:function(a){return!a.disabled;},disabled:function(a){return a.disabled;},checked:function(a){return a.checked;},selected:function(a){return a.selected||jQuery.attr(a,"selected");},text:function(a){return"text"==a.type;},radio:function(a){return"radio"==a.type;},checkbox:function(a){return"checkbox"==a.type;},file:function(a){return"file"==a.type;},password:function(a){return"password"==a.type;},submit:function(a){return"submit"==a.type;},image:function(a){return"image"==a.type;},reset:function(a){return"reset"==a.type;},button:function(a){return"button"==a.type||jQuery.nodeName(a,"button");},input:function(a){return/input|select|textarea|button/i.test(a.nodeName);},has:function(a,i,m){return jQuery.find(m[3],a).length;},header:function(a){return/h\d/i.test(a.nodeName);},animated:function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}}},parse:[/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,new RegExp("^([:.#]*)("+chars+"+)")],multiFilter:function(expr,elems,not){var old,cur=[];while(expr&&expr!=old){old=expr;var f=jQuery.filter(expr,elems,not);expr=f.t.replace(/^\s*,\s*/,"");cur=not?elems=f.r:jQuery.merge(cur,f.r);}return cur;},find:function(t,context){if(typeof t!="string")return[t];if(context&&context.nodeType!=1&&context.nodeType!=9)return[];context=context||document;var ret=[context],done=[],last,nodeName;while(t&&last!=t){var r=[];last=t;t=jQuery.trim(t);var foundToken=false,re=quickChild,m=re.exec(t);if(m){nodeName=m[1].toUpperCase();for(var i=0;ret[i];i++)for(var c=ret[i].firstChild;c;c=c.nextSibling)if(c.nodeType==1&&(nodeName=="*"||c.nodeName.toUpperCase()==nodeName))r.push(c);ret=r;t=t.replace(re,"");if(t.indexOf(" ")==0)continue;foundToken=true;}else{re=/^([>+~])\s*(\w*)/i;if((m=re.exec(t))!=null){r=[];var merge={};nodeName=m[2].toUpperCase();m=m[1];for(var j=0,rl=ret.length;j<rl;j++){var n=m=="~"||m=="+"?ret[j].nextSibling:ret[j].firstChild;for(;n;n=n.nextSibling)if(n.nodeType==1){var id=jQuery.data(n);if(m=="~"&&merge[id])break;if(!nodeName||n.nodeName.toUpperCase()==nodeName){if(m=="~")merge[id]=true;r.push(n);}if(m=="+")break;}}ret=r;t=jQuery.trim(t.replace(re,""));foundToken=true;}}if(t&&!foundToken){if(!t.indexOf(",")){if(context==ret[0])ret.shift();done=jQuery.merge(done,ret);r=ret=[context];t=" "+t.substr(1,t.length);}else{var re2=quickID;var m=re2.exec(t);if(m){m=[0,m[2],m[3],m[1]];}else{re2=quickClass;m=re2.exec(t);}m[2]=m[2].replace(/\\/g,"");var elem=ret[ret.length-1];if(m[1]=="#"&&elem&&elem.getElementById&&!jQuery.isXMLDoc(elem)){var oid=elem.getElementById(m[2]);if((jQuery.browser.msie||jQuery.browser.opera)&&oid&&typeof oid.id=="string"&&oid.id!=m[2])oid=jQuery('[@id="'+m[2]+'"]',elem)[0];ret=r=oid&&(!m[3]||jQuery.nodeName(oid,m[3]))?[oid]:[];}else{for(var i=0;ret[i];i++){var tag=m[1]=="#"&&m[3]?m[3]:m[1]!=""||m[0]==""?"*":m[2];if(tag=="*"&&ret[i].nodeName.toLowerCase()=="object")tag="param";r=jQuery.merge(r,ret[i].getElementsByTagName(tag));}if(m[1]==".")r=jQuery.classFilter(r,m[2]);if(m[1]=="#"){var tmp=[];for(var i=0;r[i];i++)if(r[i].getAttribute("id")==m[2]){tmp=[r[i]];break;}r=tmp;}ret=r;}t=t.replace(re2,"");}}if(t){var val=jQuery.filter(t,r);ret=r=val.r;t=jQuery.trim(val.t);}}if(t)ret=[];if(ret&&context==ret[0])ret.shift();done=jQuery.merge(done,ret);return done;},classFilter:function(r,m,not){m=" "+m+" ";var tmp=[];for(var i=0;r[i];i++){var pass=(" "+r[i].className+" ").indexOf(m)>=0;if(!not&&pass||not&&!pass)tmp.push(r[i]);}return tmp;},filter:function(t,r,not){var last;while(t&&t!=last){last=t;var p=jQuery.parse,m;for(var i=0;p[i];i++){m=p[i].exec(t);if(m){t=t.substring(m[0].length);m[2]=m[2].replace(/\\/g,"");break;}}if(!m)break;if(m[1]==":"&&m[2]=="not")r=isSimple.test(m[3])?jQuery.filter(m[3],r,true).r:jQuery(r).not(m[3]);else if(m[1]==".")r=jQuery.classFilter(r,m[2],not);else if(m[1]=="["){var tmp=[],type=m[3];for(var i=0,rl=r.length;i<rl;i++){var a=r[i],z=a[jQuery.props[m[2]]||m[2]];if(z==null||/href|src|selected/.test(m[2]))z=jQuery.attr(a,m[2])||'';if((type==""&&!!z||type=="="&&z==m[5]||type=="!="&&z!=m[5]||type=="^="&&z&&!z.indexOf(m[5])||type=="$="&&z.substr(z.length-m[5].length)==m[5]||(type=="*="||type=="~=")&&z.indexOf(m[5])>=0)^not)tmp.push(a);}r=tmp;}else if(m[1]==":"&&m[2]=="nth-child"){var merge={},tmp=[],test=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(m[3]=="even"&&"2n"||m[3]=="odd"&&"2n+1"||!/\D/.test(m[3])&&"0n+"+m[3]||m[3]),first=(test[1]+(test[2]||1))-0,last=test[3]-0;for(var i=0,rl=r.length;i<rl;i++){var node=r[i],parentNode=node.parentNode,id=jQuery.data(parentNode);if(!merge[id]){var c=1;for(var n=parentNode.firstChild;n;n=n.nextSibling)if(n.nodeType==1)n.nodeIndex=c++;merge[id]=true;}var add=false;if(first==0){if(node.nodeIndex==last)add=true;}else if((node.nodeIndex-last)%first==0&&(node.nodeIndex-last)/first>=0)add=true;if(add^not)tmp.push(node);}r=tmp;}else{var fn=jQuery.expr[m[1]];if(typeof fn=="object")fn=fn[m[2]];if(typeof fn=="string")fn=eval("false||function(a,i){return "+fn+";}");r=jQuery.grep(r,function(elem,i){return fn(elem,i,m,r);},not);}}return{r:r,t:t};},dir:function(elem,dir){var matched=[],cur=elem[dir];while(cur&&cur!=document){if(cur.nodeType==1)matched.push(cur);cur=cur[dir];}return matched;},nth:function(cur,result,dir,elem){result=result||1;var num=0;for(;cur;cur=cur[dir])if(cur.nodeType==1&&++num==result)break;return cur;},sibling:function(n,elem){var r=[];for(;n;n=n.nextSibling){if(n.nodeType==1&&n!=elem)r.push(n);}return r;}});jQuery.event={add:function(elem,types,handler,data){if(elem.nodeType==3||elem.nodeType==8)return;if(jQuery.browser.msie&&elem.setInterval)elem=window;if(!handler.guid)handler.guid=this.guid++;if(data!=undefined){var fn=handler;handler=this.proxy(fn,function(){return fn.apply(this,arguments);});handler.data=data;}var events=jQuery.data(elem,"events")||jQuery.data(elem,"events",{}),handle=jQuery.data(elem,"handle")||jQuery.data(elem,"handle",function(){if(typeof jQuery!="undefined"&&!jQuery.event.triggered)return jQuery.event.handle.apply(arguments.callee.elem,arguments);});handle.elem=elem;jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];handler.type=parts[1];var handlers=events[type];if(!handlers){handlers=events[type]={};if(!jQuery.event.special[type]||jQuery.event.special[type].setup.call(elem)===false){if(elem.addEventListener)elem.addEventListener(type,handle,false);else if(elem.attachEvent)elem.attachEvent("on"+type,handle);}}handlers[handler.guid]=handler;jQuery.event.global[type]=true;});elem=null;},guid:1,global:{},remove:function(elem,types,handler){if(elem.nodeType==3||elem.nodeType==8)return;var events=jQuery.data(elem,"events"),ret,index;if(events){if(types==undefined||(typeof types=="string"&&types.charAt(0)=="."))for(var type in events)this.remove(elem,type+(types||""));else{if(types.type){handler=types.handler;types=types.type;}jQuery.each(types.split(/\s+/),function(index,type){var parts=type.split(".");type=parts[0];if(events[type]){if(handler)delete events[type][handler.guid];else
-for(handler in events[type])if(!parts[1]||events[type][handler].type==parts[1])delete events[type][handler];for(ret in events[type])break;if(!ret){if(!jQuery.event.special[type]||jQuery.event.special[type].teardown.call(elem)===false){if(elem.removeEventListener)elem.removeEventListener(type,jQuery.data(elem,"handle"),false);else if(elem.detachEvent)elem.detachEvent("on"+type,jQuery.data(elem,"handle"));}ret=null;delete events[type];}}});}for(ret in events)break;if(!ret){var handle=jQuery.data(elem,"handle");if(handle)handle.elem=null;jQuery.removeData(elem,"events");jQuery.removeData(elem,"handle");}}},trigger:function(type,data,elem,donative,extra){data=jQuery.makeArray(data);if(type.indexOf("!")>=0){type=type.slice(0,-1);var exclusive=true;}if(!elem){if(this.global[type])jQuery("*").add([window,document]).trigger(type,data);}else{if(elem.nodeType==3||elem.nodeType==8)return undefined;var val,ret,fn=jQuery.isFunction(elem[type]||null),event=!data[0]||!data[0].preventDefault;if(event){data.unshift({type:type,target:elem,preventDefault:function(){},stopPropagation:function(){},timeStamp:now()});data[0][expando]=true;}data[0].type=type;if(exclusive)data[0].exclusive=true;var handle=jQuery.data(elem,"handle");if(handle)val=handle.apply(elem,data);if((!fn||(jQuery.nodeName(elem,'a')&&type=="click"))&&elem["on"+type]&&elem["on"+type].apply(elem,data)===false)val=false;if(event)data.shift();if(extra&&jQuery.isFunction(extra)){ret=extra.apply(elem,val==null?data:data.concat(val));if(ret!==undefined)val=ret;}if(fn&&donative!==false&&val!==false&&!(jQuery.nodeName(elem,'a')&&type=="click")){this.triggered=true;try{elem[type]();}catch(e){}}this.triggered=false;}return val;},handle:function(event){var val,ret,namespace,all,handlers;event=arguments[0]=jQuery.event.fix(event||window.event);namespace=event.type.split(".");event.type=namespace[0];namespace=namespace[1];all=!namespace&&!event.exclusive;handlers=(jQuery.data(this,"events")||{})[event.type];for(var j in handlers){var handler=handlers[j];if(all||handler.type==namespace){event.handler=handler;event.data=handler.data;ret=handler.apply(this,arguments);if(val!==false)val=ret;if(ret===false){event.preventDefault();event.stopPropagation();}}}return val;},fix:function(event){if(event[expando]==true)return event;var originalEvent=event;event={originalEvent:originalEvent};var props="altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target timeStamp toElement type view wheelDelta which".split(" ");for(var i=props.length;i;i--)event[props[i]]=originalEvent[props[i]];event[expando]=true;event.preventDefault=function(){if(originalEvent.preventDefault)originalEvent.preventDefault();originalEvent.returnValue=false;};event.stopPropagation=function(){if(originalEvent.stopPropagation)originalEvent.stopPropagation();originalEvent.cancelBubble=true;};event.timeStamp=event.timeStamp||now();if(!event.target)event.target=event.srcElement||document;if(event.target.nodeType==3)event.target=event.target.parentNode;if(!event.relatedTarget&&event.fromElement)event.relatedTarget=event.fromElement==event.target?event.toElement:event.fromElement;if(event.pageX==null&&event.clientX!=null){var doc=document.documentElement,body=document.body;event.pageX=event.clientX+(doc&&doc.scrollLeft||body&&body.scrollLeft||0)-(doc.clientLeft||0);event.pageY=event.clientY+(doc&&doc.scrollTop||body&&body.scrollTop||0)-(doc.clientTop||0);}if(!event.which&&((event.charCode||event.charCode===0)?event.charCode:event.keyCode))event.which=event.charCode||event.keyCode;if(!event.metaKey&&event.ctrlKey)event.metaKey=event.ctrlKey;if(!event.which&&event.button)event.which=(event.button&1?1:(event.button&2?3:(event.button&4?2:0)));return event;},proxy:function(fn,proxy){proxy.guid=fn.guid=fn.guid||proxy.guid||this.guid++;return proxy;},special:{ready:{setup:function(){bindReady();return;},teardown:function(){return;}},mouseenter:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseover",jQuery.event.special.mouseenter.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseover",jQuery.event.special.mouseenter.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseenter";return jQuery.event.handle.apply(this,arguments);}},mouseleave:{setup:function(){if(jQuery.browser.msie)return false;jQuery(this).bind("mouseout",jQuery.event.special.mouseleave.handler);return true;},teardown:function(){if(jQuery.browser.msie)return false;jQuery(this).unbind("mouseout",jQuery.event.special.mouseleave.handler);return true;},handler:function(event){if(withinElement(event,this))return true;event.type="mouseleave";return jQuery.event.handle.apply(this,arguments);}}}};jQuery.fn.extend({bind:function(type,data,fn){return type=="unload"?this.one(type,data,fn):this.each(function(){jQuery.event.add(this,type,fn||data,fn&&data);});},one:function(type,data,fn){var one=jQuery.event.proxy(fn||data,function(event){jQuery(this).unbind(event,one);return(fn||data).apply(this,arguments);});return this.each(function(){jQuery.event.add(this,type,one,fn&&data);});},unbind:function(type,fn){return this.each(function(){jQuery.event.remove(this,type,fn);});},trigger:function(type,data,fn){return this.each(function(){jQuery.event.trigger(type,data,this,true,fn);});},triggerHandler:function(type,data,fn){return this[0]&&jQuery.event.trigger(type,data,this[0],false,fn);},toggle:function(fn){var args=arguments,i=1;while(i<args.length)jQuery.event.proxy(fn,args[i++]);return this.click(jQuery.event.proxy(fn,function(event){this.lastToggle=(this.lastToggle||0)%i;event.preventDefault();return args[this.lastToggle++].apply(this,arguments)||false;}));},hover:function(fnOver,fnOut){return this.bind('mouseenter',fnOver).bind('mouseleave',fnOut);},ready:function(fn){bindReady();if(jQuery.isReady)fn.call(document,jQuery);else
-jQuery.readyList.push(function(){return fn.call(this,jQuery);});return this;}});jQuery.extend({isReady:false,readyList:[],ready:function(){if(!jQuery.isReady){jQuery.isReady=true;if(jQuery.readyList){jQuery.each(jQuery.readyList,function(){this.call(document);});jQuery.readyList=null;}jQuery(document).triggerHandler("ready");}}});var readyBound=false;function bindReady(){if(readyBound)return;readyBound=true;if(document.addEventListener&&!jQuery.browser.opera)document.addEventListener("DOMContentLoaded",jQuery.ready,false);if(jQuery.browser.msie&&window==top)(function(){if(jQuery.isReady)return;try{document.documentElement.doScroll("left");}catch(error){setTimeout(arguments.callee,0);return;}jQuery.ready();})();if(jQuery.browser.opera)document.addEventListener("DOMContentLoaded",function(){if(jQuery.isReady)return;for(var i=0;i<document.styleSheets.length;i++)if(document.styleSheets[i].disabled){setTimeout(arguments.callee,0);return;}jQuery.ready();},false);if(jQuery.browser.safari){var numStyles;(function(){if(jQuery.isReady)return;if(document.readyState!="loaded"&&document.readyState!="complete"){setTimeout(arguments.callee,0);return;}if(numStyles===undefined)numStyles=jQuery("style, link[rel=stylesheet]").length;if(document.styleSheets.length!=numStyles){setTimeout(arguments.callee,0);return;}jQuery.ready();})();}jQuery.event.add(window,"load",jQuery.ready);}jQuery.each(("blur,focus,load,resize,scroll,unload,click,dblclick,"+"mousedown,mouseup,mousemove,mouseover,mouseout,change,select,"+"submit,keydown,keypress,keyup,error").split(","),function(i,name){jQuery.fn[name]=function(fn){return fn?this.bind(name,fn):this.trigger(name);};});var withinElement=function(event,elem){var parent=event.relatedTarget;while(parent&&parent!=elem)try{parent=parent.parentNode;}catch(error){parent=elem;}return parent==elem;};jQuery(window).bind("unload",function(){jQuery("*").add(document).unbind();});jQuery.fn.extend({_load:jQuery.fn.load,load:function(url,params,callback){if(typeof url!='string')return this._load(url);var off=url.indexOf(" ");if(off>=0){var selector=url.slice(off,url.length);url=url.slice(0,off);}callback=callback||function(){};var type="GET";if(params)if(jQuery.isFunction(params)){callback=params;params=null;}else{params=jQuery.param(params);type="POST";}var self=this;jQuery.ajax({url:url,type:type,dataType:"html",data:params,complete:function(res,status){if(status=="success"||status=="notmodified")self.html(selector?jQuery("<div/>").append(res.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(selector):res.responseText);self.each(callback,[res.responseText,status,res]);}});return this;},serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){return jQuery.nodeName(this,"form")?jQuery.makeArray(this.elements):this;}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password/i.test(this.type));}).map(function(i,elem){var val=jQuery(this).val();return val==null?null:val.constructor==Array?jQuery.map(val,function(val,i){return{name:elem.name,value:val};}):{name:elem.name,value:val};}).get();}});jQuery.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(i,o){jQuery.fn[o]=function(f){return this.bind(o,f);};});var jsc=now();jQuery.extend({get:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data=null;}return jQuery.ajax({type:"GET",url:url,data:data,success:callback,dataType:type});},getScript:function(url,callback){return jQuery.get(url,null,callback,"script");},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},post:function(url,data,callback,type){if(jQuery.isFunction(data)){callback=data;data={};}return jQuery.ajax({type:"POST",url:url,data:data,success:callback,dataType:type});},ajaxSetup:function(settings){jQuery.extend(jQuery.ajaxSettings,settings);},ajaxSettings:{url:location.href,global:true,type:"GET",timeout:0,contentType:"application/x-www-form-urlencoded",processData:true,async:true,data:null,username:null,password:null,accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(s){s=jQuery.extend(true,s,jQuery.extend(true,{},jQuery.ajaxSettings,s));var jsonp,jsre=/=\?(&|$)/g,status,data,type=s.type.toUpperCase();if(s.data&&s.processData&&typeof s.data!="string")s.data=jQuery.param(s.data);if(s.dataType=="jsonp"){if(type=="GET"){if(!s.url.match(jsre))s.url+=(s.url.match(/\?/)?"&":"?")+(s.jsonp||"callback")+"=?";}else if(!s.data||!s.data.match(jsre))s.data=(s.data?s.data+"&":"")+(s.jsonp||"callback")+"=?";s.dataType="json";}if(s.dataType=="json"&&(s.data&&s.data.match(jsre)||s.url.match(jsre))){jsonp="jsonp"+jsc++;if(s.data)s.data=(s.data+"").replace(jsre,"="+jsonp+"$1");s.url=s.url.replace(jsre,"="+jsonp+"$1");s.dataType="script";window[jsonp]=function(tmp){data=tmp;success();complete();window[jsonp]=undefined;try{delete window[jsonp];}catch(e){}if(head)head.removeChild(script);};}if(s.dataType=="script"&&s.cache==null)s.cache=false;if(s.cache===false&&type=="GET"){var ts=now();var ret=s.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+ts+"$2");s.url=ret+((ret==s.url)?(s.url.match(/\?/)?"&":"?")+"_="+ts:"");}if(s.data&&type=="GET"){s.url+=(s.url.match(/\?/)?"&":"?")+s.data;s.data=null;}if(s.global&&!jQuery.active++)jQuery.event.trigger("ajaxStart");var remote=/^(?:\w+:)?\/\/([^\/?#]+)/;if(s.dataType=="script"&&type=="GET"&&remote.test(s.url)&&remote.exec(s.url)[1]!=location.host){var head=document.getElementsByTagName("head")[0];var script=document.createElement("script");script.src=s.url;if(s.scriptCharset)script.charset=s.scriptCharset;if(!jsonp){var done=false;script.onload=script.onreadystatechange=function(){if(!done&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){done=true;success();complete();head.removeChild(script);}};}head.appendChild(script);return undefined;}var requestDone=false;var xhr=window.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest();if(s.username)xhr.open(type,s.url,s.async,s.username,s.password);else
-xhr.open(type,s.url,s.async);try{if(s.data)xhr.setRequestHeader("Content-Type",s.contentType);if(s.ifModified)xhr.setRequestHeader("If-Modified-Since",jQuery.lastModified[s.url]||"Thu, 01 Jan 1970 00:00:00 GMT");xhr.setRequestHeader("X-Requested-With","XMLHttpRequest");xhr.setRequestHeader("Accept",s.dataType&&s.accepts[s.dataType]?s.accepts[s.dataType]+", */*":s.accepts._default);}catch(e){}if(s.beforeSend&&s.beforeSend(xhr,s)===false){s.global&&jQuery.active--;xhr.abort();return false;}if(s.global)jQuery.event.trigger("ajaxSend",[xhr,s]);var onreadystatechange=function(isTimeout){if(!requestDone&&xhr&&(xhr.readyState==4||isTimeout=="timeout")){requestDone=true;if(ival){clearInterval(ival);ival=null;}status=isTimeout=="timeout"&&"timeout"||!jQuery.httpSuccess(xhr)&&"error"||s.ifModified&&jQuery.httpNotModified(xhr,s.url)&&"notmodified"||"success";if(status=="success"){try{data=jQuery.httpData(xhr,s.dataType,s.dataFilter);}catch(e){status="parsererror";}}if(status=="success"){var modRes;try{modRes=xhr.getResponseHeader("Last-Modified");}catch(e){}if(s.ifModified&&modRes)jQuery.lastModified[s.url]=modRes;if(!jsonp)success();}else
-jQuery.handleError(s,xhr,status);complete();if(s.async)xhr=null;}};if(s.async){var ival=setInterval(onreadystatechange,13);if(s.timeout>0)setTimeout(function(){if(xhr){xhr.abort();if(!requestDone)onreadystatechange("timeout");}},s.timeout);}try{xhr.send(s.data);}catch(e){jQuery.handleError(s,xhr,null,e);}if(!s.async)onreadystatechange();function success(){if(s.success)s.success(data,status);if(s.global)jQuery.event.trigger("ajaxSuccess",[xhr,s]);}function complete(){if(s.complete)s.complete(xhr,status);if(s.global)jQuery.event.trigger("ajaxComplete",[xhr,s]);if(s.global&&!--jQuery.active)jQuery.event.trigger("ajaxStop");}return xhr;},handleError:function(s,xhr,status,e){if(s.error)s.error(xhr,status,e);if(s.global)jQuery.event.trigger("ajaxError",[xhr,s,e]);},active:0,httpSuccess:function(xhr){try{return!xhr.status&&location.protocol=="file:"||(xhr.status>=200&&xhr.status<300)||xhr.status==304||xhr.status==1223||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpNotModified:function(xhr,url){try{var xhrRes=xhr.getResponseHeader("Last-Modified");return xhr.status==304||xhrRes==jQuery.lastModified[url]||jQuery.browser.safari&&xhr.status==undefined;}catch(e){}return false;},httpData:function(xhr,type,filter){var ct=xhr.getResponseHeader("content-type"),xml=type=="xml"||!type&&ct&&ct.indexOf("xml")>=0,data=xml?xhr.responseXML:xhr.responseText;if(xml&&data.documentElement.tagName=="parsererror")throw"parsererror";if(filter)data=filter(data,type);if(type=="script")jQuery.globalEval(data);if(type=="json")data=eval("("+data+")");return data;},param:function(a){var s=[];if(a.constructor==Array||a.jquery)jQuery.each(a,function(){s.push(encodeURIComponent(this.name)+"="+encodeURIComponent(this.value));});else
-for(var j in a)if(a[j]&&a[j].constructor==Array)jQuery.each(a[j],function(){s.push(encodeURIComponent(j)+"="+encodeURIComponent(this));});else
-s.push(encodeURIComponent(j)+"="+encodeURIComponent(jQuery.isFunction(a[j])?a[j]():a[j]));return s.join("&").replace(/%20/g,"+");}});jQuery.fn.extend({show:function(speed,callback){return speed?this.animate({height:"show",width:"show",opacity:"show"},speed,callback):this.filter(":hidden").each(function(){this.style.display=this.oldblock||"";if(jQuery.css(this,"display")=="none"){var elem=jQuery("<"+this.tagName+" />").appendTo("body");this.style.display=elem.css("display");if(this.style.display=="none")this.style.display="block";elem.remove();}}).end();},hide:function(speed,callback){return speed?this.animate({height:"hide",width:"hide",opacity:"hide"},speed,callback):this.filter(":visible").each(function(){this.oldblock=this.oldblock||jQuery.css(this,"display");this.style.display="none";}).end();},_toggle:jQuery.fn.toggle,toggle:function(fn,fn2){return jQuery.isFunction(fn)&&jQuery.isFunction(fn2)?this._toggle.apply(this,arguments):fn?this.animate({height:"toggle",width:"toggle",opacity:"toggle"},fn,fn2):this.each(function(){jQuery(this)[jQuery(this).is(":hidden")?"show":"hide"]();});},slideDown:function(speed,callback){return this.animate({height:"show"},speed,callback);},slideUp:function(speed,callback){return this.animate({height:"hide"},speed,callback);},slideToggle:function(speed,callback){return this.animate({height:"toggle"},speed,callback);},fadeIn:function(speed,callback){return this.animate({opacity:"show"},speed,callback);},fadeOut:function(speed,callback){return this.animate({opacity:"hide"},speed,callback);},fadeTo:function(speed,to,callback){return this.animate({opacity:to},speed,callback);},animate:function(prop,speed,easing,callback){var optall=jQuery.speed(speed,easing,callback);return this[optall.queue===false?"each":"queue"](function(){if(this.nodeType!=1)return false;var opt=jQuery.extend({},optall),p,hidden=jQuery(this).is(":hidden"),self=this;for(p in prop){if(prop[p]=="hide"&&hidden||prop[p]=="show"&&!hidden)return opt.complete.call(this);if(p=="height"||p=="width"){opt.display=jQuery.css(this,"display");opt.overflow=this.style.overflow;}}if(opt.overflow!=null)this.style.overflow="hidden";opt.curAnim=jQuery.extend({},prop);jQuery.each(prop,function(name,val){var e=new jQuery.fx(self,opt,name);if(/toggle|show|hide/.test(val))e[val=="toggle"?hidden?"show":"hide":val](prop);else{var parts=val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),start=e.cur(true)||0;if(parts){var end=parseFloat(parts[2]),unit=parts[3]||"px";if(unit!="px"){self.style[name]=(end||1)+unit;start=((end||1)/e.cur(true))*start;self.style[name]=start+unit;}if(parts[1])end=((parts[1]=="-="?-1:1)*end)+start;e.custom(start,end,unit);}else
-e.custom(start,val,"");}});return true;});},queue:function(type,fn){if(jQuery.isFunction(type)||(type&&type.constructor==Array)){fn=type;type="fx";}if(!type||(typeof type=="string"&&!fn))return queue(this[0],type);return this.each(function(){if(fn.constructor==Array)queue(this,type,fn);else{queue(this,type).push(fn);if(queue(this,type).length==1)fn.call(this);}});},stop:function(clearQueue,gotoEnd){var timers=jQuery.timers;if(clearQueue)this.queue([]);this.each(function(){for(var i=timers.length-1;i>=0;i--)if(timers[i].elem==this){if(gotoEnd)timers[i](true);timers.splice(i,1);}});if(!gotoEnd)this.dequeue();return this;}});var queue=function(elem,type,array){if(elem){type=type||"fx";var q=jQuery.data(elem,type+"queue");if(!q||array)q=jQuery.data(elem,type+"queue",jQuery.makeArray(array));}return q;};jQuery.fn.dequeue=function(type){type=type||"fx";return this.each(function(){var q=queue(this,type);q.shift();if(q.length)q[0].call(this);});};jQuery.extend({speed:function(speed,easing,fn){var opt=speed&&speed.constructor==Object?speed:{complete:fn||!fn&&easing||jQuery.isFunction(speed)&&speed,duration:speed,easing:fn&&easing||easing&&easing.constructor!=Function&&easing};opt.duration=(opt.duration&&opt.duration.constructor==Number?opt.duration:jQuery.fx.speeds[opt.duration])||jQuery.fx.speeds.def;opt.old=opt.complete;opt.complete=function(){if(opt.queue!==false)jQuery(this).dequeue();if(jQuery.isFunction(opt.old))opt.old.call(this);};return opt;},easing:{linear:function(p,n,firstNum,diff){return firstNum+diff*p;},swing:function(p,n,firstNum,diff){return((-Math.cos(p*Math.PI)/2)+0.5)*diff+firstNum;}},timers:[],timerId:null,fx:function(elem,options,prop){this.options=options;this.elem=elem;this.prop=prop;if(!options.orig)options.orig={};}});jQuery.fx.prototype={update:function(){if(this.options.step)this.options.step.call(this.elem,this.now,this);(jQuery.fx.step[this.prop]||jQuery.fx.step._default)(this);if(this.prop=="height"||this.prop=="width")this.elem.style.display="block";},cur:function(force){if(this.elem[this.prop]!=null&&this.elem.style[this.prop]==null)return this.elem[this.prop];var r=parseFloat(jQuery.css(this.elem,this.prop,force));return r&&r>-10000?r:parseFloat(jQuery.curCSS(this.elem,this.prop))||0;},custom:function(from,to,unit){this.startTime=now();this.start=from;this.end=to;this.unit=unit||this.unit||"px";this.now=this.start;this.pos=this.state=0;this.update();var self=this;function t(gotoEnd){return self.step(gotoEnd);}t.elem=this.elem;jQuery.timers.push(t);if(jQuery.timerId==null){jQuery.timerId=setInterval(function(){var timers=jQuery.timers;for(var i=0;i<timers.length;i++)if(!timers[i]())timers.splice(i--,1);if(!timers.length){clearInterval(jQuery.timerId);jQuery.timerId=null;}},13);}},show:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.show=true;this.custom(0,this.cur());if(this.prop=="width"||this.prop=="height")this.elem.style[this.prop]="1px";jQuery(this.elem).show();},hide:function(){this.options.orig[this.prop]=jQuery.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0);},step:function(gotoEnd){var t=now();if(gotoEnd||t>this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var done=true;for(var i in this.options.curAnim)if(this.options.curAnim[i]!==true)done=false;if(done){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(jQuery.css(this.elem,"display")=="none")this.elem.style.display="block";}if(this.options.hide)this.elem.style.display="none";if(this.options.hide||this.options.show)for(var p in this.options.curAnim)jQuery.attr(this.elem.style,p,this.options.orig[p]);}if(done)this.options.complete.call(this.elem);return false;}else{var n=t-this.startTime;this.state=n/this.options.duration;this.pos=jQuery.easing[this.options.easing||(jQuery.easing.swing?"swing":"linear")](this.state,n,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update();}return true;}};jQuery.extend(jQuery.fx,{speeds:{slow:600,fast:200,def:400},step:{scrollLeft:function(fx){fx.elem.scrollLeft=fx.now;},scrollTop:function(fx){fx.elem.scrollTop=fx.now;},opacity:function(fx){jQuery.attr(fx.elem.style,"opacity",fx.now);},_default:function(fx){fx.elem.style[fx.prop]=fx.now+fx.unit;}}});jQuery.fn.offset=function(){var left=0,top=0,elem=this[0],results;if(elem)with(jQuery.browser){var parent=elem.parentNode,offsetChild=elem,offsetParent=elem.offsetParent,doc=elem.ownerDocument,safari2=safari&&parseInt(version)<522&&!/adobeair/i.test(userAgent),css=jQuery.curCSS,fixed=css(elem,"position")=="fixed";if(elem.getBoundingClientRect){var box=elem.getBoundingClientRect();add(box.left+Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),box.top+Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));add(-doc.documentElement.clientLeft,-doc.documentElement.clientTop);}else{add(elem.offsetLeft,elem.offsetTop);while(offsetParent){add(offsetParent.offsetLeft,offsetParent.offsetTop);if(mozilla&&!/^t(able|d|h)$/i.test(offsetParent.tagName)||safari&&!safari2)border(offsetParent);if(!fixed&&css(offsetParent,"position")=="fixed")fixed=true;offsetChild=/^body$/i.test(offsetParent.tagName)?offsetChild:offsetParent;offsetParent=offsetParent.offsetParent;}while(parent&&parent.tagName&&!/^body|html$/i.test(parent.tagName)){if(!/^inline|table.*$/i.test(css(parent,"display")))add(-parent.scrollLeft,-parent.scrollTop);if(mozilla&&css(parent,"overflow")!="visible")border(parent);parent=parent.parentNode;}if((safari2&&(fixed||css(offsetChild,"position")=="absolute"))||(mozilla&&css(offsetChild,"position")!="absolute"))add(-doc.body.offsetLeft,-doc.body.offsetTop);if(fixed)add(Math.max(doc.documentElement.scrollLeft,doc.body.scrollLeft),Math.max(doc.documentElement.scrollTop,doc.body.scrollTop));}results={top:top,left:left};}function border(elem){add(jQuery.curCSS(elem,"borderLeftWidth",true),jQuery.curCSS(elem,"borderTopWidth",true));}function add(l,t){left+=parseInt(l,10)||0;top+=parseInt(t,10)||0;}return results;};jQuery.fn.extend({position:function(){var left=0,top=0,results;if(this[0]){var offsetParent=this.offsetParent(),offset=this.offset(),parentOffset=/^body|html$/i.test(offsetParent[0].tagName)?{top:0,left:0}:offsetParent.offset();offset.top-=num(this,'marginTop');offset.left-=num(this,'marginLeft');parentOffset.top+=num(offsetParent,'borderTopWidth');parentOffset.left+=num(offsetParent,'borderLeftWidth');results={top:offset.top-parentOffset.top,left:offset.left-parentOffset.left};}return results;},offsetParent:function(){var offsetParent=this[0].offsetParent;while(offsetParent&&(!/^body|html$/i.test(offsetParent.tagName)&&jQuery.css(offsetParent,'position')=='static'))offsetParent=offsetParent.offsetParent;return jQuery(offsetParent);}});jQuery.each(['Left','Top'],function(i,name){var method='scroll'+name;jQuery.fn[method]=function(val){if(!this[0])return;return val!=undefined?this.each(function(){this==window||this==document?window.scrollTo(!i?val:jQuery(window).scrollLeft(),i?val:jQuery(window).scrollTop()):this[method]=val;}):this[0]==window||this[0]==document?self[i?'pageYOffset':'pageXOffset']||jQuery.boxModel&&document.documentElement[method]||document.body[method]:this[0][method];};});jQuery.each(["Height","Width"],function(i,name){var tl=i?"Left":"Top",br=i?"Right":"Bottom";jQuery.fn["inner"+name]=function(){return this[name.toLowerCase()]()+num(this,"padding"+tl)+num(this,"padding"+br);};jQuery.fn["outer"+name]=function(margin){return this["inner"+name]()+num(this,"border"+tl+"Width")+num(this,"border"+br+"Width")+(margin?num(this,"margin"+tl)+num(this,"margin"+br):0);};});})(); \ No newline at end of file
+(function(a,b){function cv(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cs(a){if(!cg[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ch||(ch=c.createElement("iframe"),ch.frameBorder=ch.width=ch.height=0),b.appendChild(ch);if(!ci||!ch.createElement)ci=(ch.contentWindow||ch.contentDocument).document,ci.write((c.compatMode==="CSS1Compat"?"<!doctype html>":"")+"<html><body>"),ci.close();d=ci.createElement(a),ci.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ch)}cg[a]=e}return cg[a]}function cr(a,b){var c={};f.each(cm.concat.apply([],cm.slice(0,b)),function(){c[this]=a});return c}function cq(){cn=b}function cp(){setTimeout(cq,0);return cn=f.now()}function cf(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ce(){try{return new a.XMLHttpRequest}catch(b){}}function b$(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function bZ(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function bY(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bC.test(a)?d(a,e):bY(a+"["+(typeof e=="object"||f.isArray(e)?b:"")+"]",e,c,d)});else if(!c&&b!=null&&typeof b=="object")for(var e in b)bY(a+"["+e+"]",b[e],c,d);else d(a,b)}function bX(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bR,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bX(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bX(a,c,d,e,"*",g));return l}function bW(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bN),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bA(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?bv:bw;if(d>0){c!=="border"&&f.each(e,function(){c||(d-=parseFloat(f.css(a,"padding"+this))||0),c==="margin"?d+=parseFloat(f.css(a,c+this))||0:d-=parseFloat(f.css(a,"border"+this+"Width"))||0});return d+"px"}d=bx(a,b,b);if(d<0||d==null)d=a.style[b]||0;d=parseFloat(d)||0,c&&f.each(e,function(){d+=parseFloat(f.css(a,"padding"+this))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+this+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+this))||0)});return d+"px"}function bm(a,b){b.src?f.ajax({url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(be,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)}function bl(a){f.nodeName(a,"input")?bk(a):"getElementsByTagName"in a&&f.grep(a.getElementsByTagName("input"),bk)}function bk(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bj(a){return"getElementsByTagName"in a?a.getElementsByTagName("*"):"querySelectorAll"in a?a.querySelectorAll("*"):[]}function bi(a,b){var c;if(b.nodeType===1){b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase();if(c==="object")b.outerHTML=a.outerHTML;else if(c!=="input"||a.type!=="checkbox"&&a.type!=="radio"){if(c==="option")b.selected=a.defaultSelected;else if(c==="input"||c==="textarea")b.defaultValue=a.defaultValue}else a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value);b.removeAttribute(f.expando)}}function bh(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c=f.expando,d=f.data(a),e=f.data(b,d);if(d=d[c]){var g=d.events;e=e[c]=f.extend({},d);if(g){delete e.handle,e.events={};for(var h in g)for(var i=0,j=g[h].length;i<j;i++)f.event.add(b,h+(g[h][i].namespace?".":"")+g[h][i].namespace,g[h][i],g[h][i].data)}}}}function bg(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function W(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(R.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function V(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function N(a,b){return(a&&a!=="*"?a+".":"")+b.replace(z,"`").replace(A,"&")}function M(a){var b,c,d,e,g,h,i,j,k,l,m,n,o,p=[],q=[],r=f._data(this,"events");if(!(a.liveFired===this||!r||!r.live||a.target.disabled||a.button&&a.type==="click")){a.namespace&&(n=new RegExp("(^|\\.)"+a.namespace.split(".").join("\\.(?:.*\\.)?")+"(\\.|$)")),a.liveFired=this;var s=r.live.slice(0);for(i=0;i<s.length;i++)g=s[i],g.origType.replace(x,"")===a.type?q.push(g.selector):s.splice(i--,1);e=f(a.target).closest(q,a.currentTarget);for(j=0,k=e.length;j<k;j++){m=e[j];for(i=0;i<s.length;i++){g=s[i];if(m.selector===g.selector&&(!n||n.test(g.namespace))&&!m.elem.disabled){h=m.elem,d=null;if(g.preType==="mouseenter"||g.preType==="mouseleave")a.type=g.preType,d=f(a.relatedTarget).closest(g.selector)[0],d&&f.contains(h,d)&&(d=h);(!d||d!==h)&&p.push({elem:h,handleObj:g,level:m.level})}}}for(j=0,k=p.length;j<k;j++){e=p[j];if(c&&e.level>c)break;a.currentTarget=e.elem,a.data=e.handleObj.data,a.handleObj=e.handleObj,o=e.handleObj.origHandler.apply(e.elem,arguments);if(o===!1||a.isPropagationStopped()){c=e.level,o===!1&&(b=!1);if(a.isImmediatePropagationStopped())break}}return b}}function K(a,c,d){var e=f.extend({},d[0]);e.type=a,e.originalEvent={},e.liveFired=b,f.event.handle.call(c,e),e.isDefaultPrevented()&&d[0].preventDefault()}function E(){return!0}function D(){return!1}function m(a,c,d){var e=c+"defer",g=c+"queue",h=c+"mark",i=f.data(a,e,b,!0);i&&(d==="queue"||!f.data(a,g,b,!0))&&(d==="mark"||!f.data(a,h,b,!0))&&setTimeout(function(){!f.data(a,g,b,!0)&&!f.data(a,h,b,!0)&&(f.removeData(a,e,!0),i.resolve())},0)}function l(a){for(var b in a)if(b!=="toJSON")return!1;return!0}function k(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(j,"$1-$2").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNaN(d)?i.test(d)?f.parseJSON(d):d:parseFloat(d)}catch(g){}f.data(a,c,d)}else d=b}return d}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/\d/,n=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,o=/^[\],:{}\s]*$/,p=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,q=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,r=/(?:^|:|,)(?:\s*\[)+/g,s=/(webkit)[ \/]([\w.]+)/,t=/(opera)(?:.*version)?[ \/]([\w.]+)/,u=/(msie) ([\w.]+)/,v=/(mozilla)(?:.*? rv:([\w.]+))?/,w=/-([a-z])/ig,x=function(a,b){return b.toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=n.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.6.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.done(a);return this},eq:function(a){return a===-1?this.slice(a):this.slice(a,+a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.resolveWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").unbind("ready")}},bindReady:function(){if(!A){A=e._Deferred();if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNaN:function(a){return a==null||!m.test(a)||isNaN(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1;var c;for(c in a);return c===b||D.call(a,c)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw a},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(o.test(b.replace(p,"@").replace(q,"]").replace(r,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(b,c,d){a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b)),d=c.documentElement,(!d||!d.nodeName||d.nodeName==="parsererror")&&e.error("Invalid XML: "+b);return c},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b){if(H)return H.call(b,a);for(var c=0,d=b.length;c<d;c++)if(b[c]===a)return c;return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h){var i=a.length;if(typeof c=="object"){for(var j in c)e.access(a,j,c[j],f,g,d);return a}if(d!==b){f=!h&&f&&e.isFunction(d);for(var k=0;k<i;k++)g(a[k],c,f?d.call(a[k],k,g(a[k],c)):d,h);return a}return i?g(a[0],c):b},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=s.exec(a)||t.exec(a)||u.exec(a)||a.indexOf("compatible")<0&&v.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g="done fail isResolved isRejected promise then always pipe".split(" "),h=[].slice;f.extend({_Deferred:function(){var a=[],b,c,d,e={done:function(){if(!d){var c=arguments,g,h,i,j,k;b&&(k=b,b=0);for(g=0,h=c.length;g<h;g++)i=c[g],j=f.type(i),j==="array"?e.done.apply(e,i):j==="function"&&a.push(i);k&&e.resolveWith(k[0],k[1])}return this},resolveWith:function(e,f){if(!d&&!b&&!c){f=f||[],c=1;try{while(a[0])a.shift().apply(e,f)}finally{b=[e,f],c=0}}return this},resolve:function(){e.resolveWith(this,arguments);return this},isResolved:function(){return!!c||!!b},cancel:function(){d=1,a=[];return this}};return e},Deferred:function(a){var b=f._Deferred(),c=f._Deferred(),d;f.extend(b,{then:function(a,c){b.done(a).fail(c);return this},always:function(){return b.done.apply(b,arguments).fail.apply(this,arguments)},fail:c.done,rejectWith:c.resolveWith,reject:c.resolve,isRejected:c.isResolved,pipe:function(a,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[c,"reject"]},function(a,c){var e=c[0],g=c[1],h;f.isFunction(e)?b[a](function(){h=e.apply(this,arguments),h&&f.isFunction(h.promise)?h.promise().then(d.resolve,d.reject):d[g](h)}):b[a](d[g])})}).promise()},promise:function(a){if(a==null){if(d)return d;d=a={}}var c=g.length;while(c--)a[g[c]]=b[g[c]];return a}}),b.done(c.cancel).fail(b.cancel),delete b.cancel,a&&a.call(b,b);return b},when:function(a){function i(a){return function(c){b[a]=arguments.length>1?h.call(arguments,0):c,--e||g.resolveWith(g,h.call(b,0))}}var b=arguments,c=0,d=b.length,e=d,g=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred();if(d>1){for(;c<d;c++)b[c]&&f.isFunction(b[c].promise)?b[c].promise().then(i(c),g.reject):--e;e||g.resolveWith(g,b)}else g!==a&&g.resolveWith(g,d?[a]:[]);return g.promise()}}),f.support=function(){var a=c.createElement("div"),b=c.documentElement,d,e,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u;a.setAttribute("className","t"),a.innerHTML=" <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=a.getElementsByTagName("*"),e=a.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=a.getElementsByTagName("input")[0],k={leadingWhitespace:a.firstChild.nodeType===3,tbody:!a.getElementsByTagName("tbody").length,htmlSerialize:!!a.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55$/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:a.className!=="t",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,k.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,k.optDisabled=!h.disabled;try{delete a.test}catch(v){k.deleteExpando=!1}!a.addEventListener&&a.attachEvent&&a.fireEvent&&(a.attachEvent("onclick",function(){k.noCloneEvent=!1}),a.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),k.radioValue=i.value==="t",i.setAttribute("checked","checked"),a.appendChild(i),l=c.createDocumentFragment(),l.appendChild(a.firstChild),k.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,a.innerHTML="",a.style.width=a.style.paddingLeft="1px",m=c.getElementsByTagName("body")[0],o=c.createElement(m?"div":"body"),p={visibility:"hidden",width:0,height:0,border:0,margin:0},m&&f.extend(p,{position:"absolute",left:-1e3,top:-1e3});for(t in p)o.style[t]=p[t];o.appendChild(a),n=m||b,n.insertBefore(o,n.firstChild),k.appendChecked=i.checked,k.boxModel=a.offsetWidth===2,"zoom"in a.style&&(a.style.display="inline",a.style.zoom=1,k.inlineBlockNeedsLayout=a.offsetWidth===2,a.style.display="",a.innerHTML="<div style='width:4px;'></div>",k.shrinkWrapBlocks=a.offsetWidth!==2),a.innerHTML="<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>",q=a.getElementsByTagName("td"),u=q[0].offsetHeight===0,q[0].style.display="",q[1].style.display="none",k.reliableHiddenOffsets=u&&q[0].offsetHeight===0,a.innerHTML="",c.defaultView&&c.defaultView.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",a.appendChild(j),k.reliableMarginRight=(parseInt((c.defaultView.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0),o.innerHTML="",n.removeChild(o);if(a.attachEvent)for(t in{submit:1,change:1,focusin:1})s="on"+t,u=s in a,u||(a.setAttribute(s,"return;"),u=typeof a[s]=="function"),k[t+"Bubbles"]=u;o=l=g=h=m=j=a=i=null;return k}(),f.boxModel=f.support.boxModel;var i=/^(?:\{.*\}|\[.*\])$/,j=/([a-z])([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!l(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g=f.expando,h=typeof c=="string",i,j=a.nodeType,k=j?f.cache:a,l=j?a[f.expando]:a[f.expando]&&f.expando;if((!l||e&&l&&!k[l][g])&&h&&d===b)return;l||(j?a[f.expando]=l=++f.uuid:l=f.expando),k[l]||(k[l]={},j||(k[l].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?k[l][g]=f.extend(k[l][g],c):k[l]=f.extend(k[l],c);i=k[l],e&&(i[g]||(i[g]={}),i=i[g]),d!==b&&(i[f.camelCase(c)]=d);if(c==="events"&&!i[c])return i[g]&&i[g].events;return h?i[f.camelCase(c)]||i[c]:i}},removeData:function(b,c,d){if(!!f.acceptData(b)){var e=f.expando,g=b.nodeType,h=g?f.cache:b,i=g?b[f.expando]:f.expando;if(!h[i])return;if(c){var j=d?h[i][e]:h[i];if(j){delete j[c];if(!l(j))return}}if(d){delete h[i][e];if(!l(h[i]))return}var k=h[i][e];f.support.deleteExpando||h!=a?delete h[i]:h[i]=null,k?(h[i]={},g||(h[i].toJSON=f.noop),h[i][e]=k):g&&(f.support.deleteExpando?delete b[f.expando]:b.removeAttribute?b.removeAttribute(f.expando):b[f.expando]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d=null;if(typeof a=="undefined"){if(this.length){d=f.data(this[0]);if(this[0].nodeType===1){var e=this[0].attributes,g;for(var h=0,i=e.length;h<i;h++)g=e[h].name,g.indexOf("data-")===0&&(g=f.camelCase(g.substring(5)),k(this[0],g,d[g]))}}return d}if(typeof a=="object")return this.each(function(){f.data(this,a)});var j=a.split(".");j[1]=j[1]?"."+j[1]:"";if(c===b){d=this.triggerHandler("getData"+j[1]+"!",[j[0]]),d===b&&this.length&&(d=f.data(this[0],a),d=k(this[0],a,d));return d===b&&j[1]?this.data(j[0]):d}return this.each(function(){var b=f(this),d=[j[0],c];b.triggerHandler("setData"+j[1]+"!",d),f.data(this,a,c),b.triggerHandler("changeData"+j[1]+"!",d)})},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,c){a&&(c=(c||"fx")+"mark",f.data(a,c,(f.data(a,c,b,!0)||0)+1,!0))},_unmark:function(a,c,d){a!==!0&&(d=c,c=a,a=!1);if(c){d=d||"fx";var e=d+"mark",g=a?0:(f.data(c,e,b,!0)||1)-1;g?f.data(c,e,g,!0):(f.removeData(c,e,!0),m(c,d,"mark"))}},queue:function(a,c,d){if(a){c=(c||"fx")+"queue";var e=f.data(a,c,b,!0);d&&(!e||f.isArray(d)?e=f.data(a,c,f.makeArray(d),!0):e.push(d));return e||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e;d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),d.call(a,function(){f.dequeue(a,b)})),c.length||(f.removeData(a,b+"queue",!0),m(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){typeof a!="string"&&(c=a,a="fx");if(c===b)return f.queue(this[0],a);return this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(){var c=this;setTimeout(function(){f.dequeue(c,b)},a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f._Deferred(),!0))h++,l.done(m);m();return d.promise()}});var n=/[\n\t\r]/g,o=/\s+/,p=/\r/g,q=/^(?:button|input)$/i,r=/^(?:button|input|object|select|textarea)$/i,s=/^a(?:rea)?$/i,t=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,u=/\:|^on/,v,w;f.fn.extend({attr:function(a,b){return f.access(this,a,b,!0,f.attr)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,a,b,!0,f.prop)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(o);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(o);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(n," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(o);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ";for(var c=0,d=this.length;c<d;c++)if((" "+this[c].className+" ").replace(n," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e=this[0];if(!arguments.length){if(e){c=f.valHooks[e.nodeName.toLowerCase()]||f.valHooks[e.type];if(c&&"get"in c&&(d=c.get(e,"value"))!==b)return d;d=e.value;return typeof d=="string"?d.replace(p,""):d==null?"":d}return b}var g=f.isFunction(a);return this.each(function(d){var e=f(this),h;if(this.nodeType===1){g?h=a.call(this,d,e.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c=a.selectedIndex,d=[],e=a.options,g=a.type==="select-one";if(c<0)return null;for(var h=g?c:0,i=g?c+1:e.length;h<i;h++){var j=e[h];if(j.selected&&(f.support.optDisabled?!j.disabled:j.getAttribute("disabled")===null)&&(!j.parentNode.disabled||!f.nodeName(j.parentNode,"optgroup"))){b=f(j).val();if(g)return b;d.push(b)}}if(g&&!d.length&&e.length)return f(e[c]).val();return d},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attrFix:{tabindex:"tabIndex"},attr:function(a,c,d,e){var g=a.nodeType;if(!a||g===3||g===8||g===2)return b;if(e&&c in f.attrFn)return f(a)[c](d);if(!("getAttribute"in a))return f.prop(a,c,d);var h,i,j=g!==1||!f.isXMLDoc(a);j&&(c=f.attrFix[c]||c,i=f.attrHooks[c],i||(t.test(c)?i=w:v&&c!=="className"&&(f.nodeName(a,"form")||u.test(c))&&(i=v)));if(d!==b){if(d===null){f.removeAttr(a,c);return b}if(i&&"set"in i&&j&&(h=i.set(a,d,c))!==b)return h;a.setAttribute(c,""+d);return d}if(i&&"get"in i&&j&&(h=i.get(a,c))!==null)return h;h=a.getAttribute(c);return h===null?b:h},removeAttr:function(a,b){var c;a.nodeType===1&&(b=f.attrFix[b]||b,f.support.getSetAttribute?a.removeAttribute(b):(f.attr(a,b,""),a.removeAttributeNode(a.getAttributeNode(b))),t.test(b)&&(c=f.propFix[b]||b)in a&&(a[c]=!1))},attrHooks:{type:{set:function(a,b){if(q.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},tabIndex:{get:function(a){var c=a.getAttributeNode("tabIndex");return c&&c.specified?parseInt(c.value,10):r.test(a.nodeName)||s.test(a.nodeName)&&a.href?0:b}},value:{get:function(a,b){if(v&&f.nodeName(a,"button"))return v.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(v&&f.nodeName(a,"button"))return v.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e=a.nodeType;if(!a||e===3||e===8||e===2)return b;var g,h,i=e!==1||!f.isXMLDoc(a);i&&(c=f.propFix[c]||c,h=f.propHooks[c]);return d!==b?h&&"set"in h&&(g=h.set(a,d,c))!==b?g:a[c]=d:h&&"get"in h&&(g=h.get(a,c))!==b?g:a[c]},propHooks:{}}),w={get:function(a,c){return f.prop(a,c)?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},f.support.getSetAttribute||(f.attrFix=f.propFix,v=f.attrHooks.name=f.attrHooks.title=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&d.nodeValue!==""?d.nodeValue:b},set:function(a,b,c){var d=a.getAttributeNode(c);if(d){d.nodeValue=b;return b}}},f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})})),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex)}})),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var x=/\.(.*)$/,y=/^(?:textarea|input|select)$/i,z=/\./g,A=/ /g,B=/[^\w\s.|`]/g,C=function(a){return a.replace(B,"\\$&")};f.event={add:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){if(d===!1)d=D;else if(!d)return;var g,h;d.handler&&(g=d,d=g.handler),d.guid||(d.guid=f.guid++);var i=f._data(a);if(!i)return;var j=i.events,k=i.handle;j||(i.events=j={}),k||(i.handle=k=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.handle.apply(k.elem,arguments):b}),k.elem=a,c=c.split(" ");var l,m=0,n;while(l=c[m++]){h=g?f.extend({},g):{handler:d,data:e},l.indexOf(".")>-1?(n=l.split("."),l=n.shift(),h.namespace=n.slice(0).sort().join(".")):(n=[],h.namespace=""),h.type=l,h.guid||(h.guid=d.guid);var o=j[l],p=f.event.special[l]||{};if(!o){o=j[l]=[];if(!p.setup||p.setup.call(a,e,n,k)===!1)a.addEventListener?a.addEventListener(l,k,!1):a.attachEvent&&a.attachEvent("on"+l,k)}p.add&&(p.add.call(a,h),h.handler.guid||(h.handler.guid=d.guid)),o.push(h),f.event.global[l]=!0}a=null}},global:{},remove:function(a,c,d,e){if(a.nodeType!==3&&a.nodeType!==8){d===!1&&(d=D);var g,h,i,j,k=0,l,m,n,o,p,q,r,s=f.hasData(a)&&f._data(a),t=s&&s.events;if(!s||!t)return;c&&c.type&&(d=c.handler,c=c.type);if(!c||typeof c=="string"&&c.charAt(0)==="."){c=c||"";for(h in t)f.event.remove(a,h+c);return}c=c.split(" ");while(h=c[k++]){r=h,q=null,l=h.indexOf(".")<0,m=[],l||(m=h.split("."),h=m.shift(),n=new RegExp("(^|\\.)"+f.map(m.slice(0).sort(),C).join("\\.(?:.*\\.)?")+"(\\.|$)")),p=t[h];if(!p)continue;if(!d){for(j=0;j<p.length;j++){q=p[j];if(l||n.test(q.namespace))f.event.remove(a,r,q.handler,j),p.splice(j--,1)}continue}o=f.event.special[h]||{};for(j=e||0;j<p.length;j++){q=p[j];if(d.guid===q.guid){if(l||n.test(q.namespace))e==null&&p.splice(j--,1),o.remove&&o.remove.call(a,q);if(e!=null)break}}if(p.length===0||e!=null&&p.length===1)(!o.teardown||o.teardown.call(a,m)===!1)&&f.removeEvent(a,h,s.handle),g=null,delete t[h]}if(f.isEmptyObject(t)){var u=s.handle;u&&(u.elem=null),delete s.events,delete s.handle,f.isEmptyObject(s)&&f.removeData(a,b,!0)}}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){var h=c.type||c,i=[],j;h.indexOf("!")>=0&&(h=h.slice(0,-1),j=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.
+shift(),i.sort());if(!!e&&!f.event.customEvent[h]||!!f.event.global[h]){c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.exclusive=j,c.namespace=i.join("."),c.namespace_re=new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)");if(g||!e)c.preventDefault(),c.stopPropagation();if(!e){f.each(f.cache,function(){var a=f.expando,b=this[a];b&&b.events&&b.events[h]&&f.event.trigger(c,d,b.handle.elem)});return}if(e.nodeType===3||e.nodeType===8)return;c.result=b,c.target=e,d=d!=null?f.makeArray(d):[],d.unshift(c);var k=e,l=h.indexOf(":")<0?"on"+h:"";do{var m=f._data(k,"handle");c.currentTarget=k,m&&m.apply(k,d),l&&f.acceptData(k)&&k[l]&&k[l].apply(k,d)===!1&&(c.result=!1,c.preventDefault()),k=k.parentNode||k.ownerDocument||k===c.target.ownerDocument&&a}while(k&&!c.isPropagationStopped());if(!c.isDefaultPrevented()){var n,o=f.event.special[h]||{};if((!o._default||o._default.call(e.ownerDocument,c)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)){try{l&&e[h]&&(n=e[l],n&&(e[l]=null),f.event.triggered=h,e[h]())}catch(p){}n&&(e[l]=n),f.event.triggered=b}}return c.result}},handle:function(c){c=f.event.fix(c||a.event);var d=((f._data(this,"events")||{})[c.type]||[]).slice(0),e=!c.exclusive&&!c.namespace,g=Array.prototype.slice.call(arguments,0);g[0]=c,c.currentTarget=this;for(var h=0,i=d.length;h<i;h++){var j=d[h];if(e||c.namespace_re.test(j.namespace)){c.handler=j.handler,c.data=j.data,c.handleObj=j;var k=j.handler.apply(this,g);k!==b&&(c.result=k,k===!1&&(c.preventDefault(),c.stopPropagation()));if(c.isImmediatePropagationStopped())break}}return c.result},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(a){if(a[f.expando])return a;var d=a;a=f.Event(d);for(var e=this.props.length,g;e;)g=this.props[--e],a[g]=d[g];a.target||(a.target=a.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),!a.relatedTarget&&a.fromElement&&(a.relatedTarget=a.fromElement===a.target?a.toElement:a.fromElement);if(a.pageX==null&&a.clientX!=null){var h=a.target.ownerDocument||c,i=h.documentElement,j=h.body;a.pageX=a.clientX+(i&&i.scrollLeft||j&&j.scrollLeft||0)-(i&&i.clientLeft||j&&j.clientLeft||0),a.pageY=a.clientY+(i&&i.scrollTop||j&&j.scrollTop||0)-(i&&i.clientTop||j&&j.clientTop||0)}a.which==null&&(a.charCode!=null||a.keyCode!=null)&&(a.which=a.charCode!=null?a.charCode:a.keyCode),!a.metaKey&&a.ctrlKey&&(a.metaKey=a.ctrlKey),!a.which&&a.button!==b&&(a.which=a.button&1?1:a.button&2?3:a.button&4?2:0);return a},guid:1e8,proxy:f.proxy,special:{ready:{setup:f.bindReady,teardown:f.noop},live:{add:function(a){f.event.add(this,N(a.origType,a.selector),f.extend({},a,{handler:M,guid:a.handler.guid}))},remove:function(a){f.event.remove(this,N(a.origType,a.selector),a)}},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}}},f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!this.preventDefault)return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?E:D):this.type=a,b&&f.extend(this,b),this.timeStamp=f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=E;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=E;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=E,this.stopPropagation()},isDefaultPrevented:D,isPropagationStopped:D,isImmediatePropagationStopped:D};var F=function(a){var b=a.relatedTarget,c=!1,d=a.type;a.type=a.data,b!==this&&(b&&(c=f.contains(this,b)),c||(f.event.handle.apply(this,arguments),a.type=d))},G=function(a){a.type=a.data,f.event.handle.apply(this,arguments)};f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={setup:function(c){f.event.add(this,b,c&&c.selector?G:F,a)},teardown:function(a){f.event.remove(this,b,a&&a.selector?G:F)}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(a,b){if(!f.nodeName(this,"form"))f.event.add(this,"click.specialSubmit",function(a){var b=a.target,c=b.type;(c==="submit"||c==="image")&&f(b).closest("form").length&&K("submit",this,arguments)}),f.event.add(this,"keypress.specialSubmit",function(a){var b=a.target,c=b.type;(c==="text"||c==="password")&&f(b).closest("form").length&&a.keyCode===13&&K("submit",this,arguments)});else return!1},teardown:function(a){f.event.remove(this,".specialSubmit")}});if(!f.support.changeBubbles){var H,I=function(a){var b=a.type,c=a.value;b==="radio"||b==="checkbox"?c=a.checked:b==="select-multiple"?c=a.selectedIndex>-1?f.map(a.options,function(a){return a.selected}).join("-"):"":f.nodeName(a,"select")&&(c=a.selectedIndex);return c},J=function(c){var d=c.target,e,g;if(!!y.test(d.nodeName)&&!d.readOnly){e=f._data(d,"_change_data"),g=I(d),(c.type!=="focusout"||d.type!=="radio")&&f._data(d,"_change_data",g);if(e===b||g===e)return;if(e!=null||g)c.type="change",c.liveFired=b,f.event.trigger(c,arguments[1],d)}};f.event.special.change={filters:{focusout:J,beforedeactivate:J,click:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(c==="radio"||c==="checkbox"||f.nodeName(b,"select"))&&J.call(this,a)},keydown:function(a){var b=a.target,c=f.nodeName(b,"input")?b.type:"";(a.keyCode===13&&!f.nodeName(b,"textarea")||a.keyCode===32&&(c==="checkbox"||c==="radio")||c==="select-multiple")&&J.call(this,a)},beforeactivate:function(a){var b=a.target;f._data(b,"_change_data",I(b))}},setup:function(a,b){if(this.type==="file")return!1;for(var c in H)f.event.add(this,c+".specialChange",H[c]);return y.test(this.nodeName)},teardown:function(a){f.event.remove(this,".specialChange");return y.test(this.nodeName)}},H=f.event.special.change.filters,H.focus=H.beforeactivate}f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){function e(a){var c=f.event.fix(a);c.type=b,c.originalEvent={},f.event.trigger(c,null,c.target),c.isDefaultPrevented()&&a.preventDefault()}var d=0;f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.each(["bind","one"],function(a,c){f.fn[c]=function(a,d,e){var g;if(typeof a=="object"){for(var h in a)this[c](h,d,a[h],e);return this}if(arguments.length===2||d===!1)e=d,d=b;c==="one"?(g=function(a){f(this).unbind(a,g);return e.apply(this,arguments)},g.guid=e.guid||f.guid++):g=e;if(a==="unload"&&c!=="one")this.one(a,d,e);else for(var i=0,j=this.length;i<j;i++)f.event.add(this[i],a,g,d);return this}}),f.fn.extend({unbind:function(a,b){if(typeof a=="object"&&!a.preventDefault)for(var c in a)this.unbind(c,a[c]);else for(var d=0,e=this.length;d<e;d++)f.event.remove(this[d],a,b);return this},delegate:function(a,b,c,d){return this.live(b,c,d,a)},undelegate:function(a,b,c){return arguments.length===0?this.unbind("live"):this.die(b,null,c,a)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f.data(this,"lastToggle"+a.guid)||0)%d;f.data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}});var L={focus:"focusin",blur:"focusout",mouseenter:"mouseover",mouseleave:"mouseout"};f.each(["live","die"],function(a,c){f.fn[c]=function(a,d,e,g){var h,i=0,j,k,l,m=g||this.selector,n=g?this:f(this.context);if(typeof a=="object"&&!a.preventDefault){for(var o in a)n[c](o,d,a[o],m);return this}if(c==="die"&&!a&&g&&g.charAt(0)==="."){n.unbind(g);return this}if(d===!1||f.isFunction(d))e=d||D,d=b;a=(a||"").split(" ");while((h=a[i++])!=null){j=x.exec(h),k="",j&&(k=j[0],h=h.replace(x,""));if(h==="hover"){a.push("mouseenter"+k,"mouseleave"+k);continue}l=h,L[h]?(a.push(L[h]+k),h=h+k):h=(L[h]||h)+k;if(c==="live")for(var p=0,q=n.length;p<q;p++)f.event.add(n[p],"live."+N(h,m),{data:d,selector:m,handler:e,origType:h,origHandler:e,preType:l});else n.unbind("live."+N(h,m),e)}return this}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.bind(b,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0)}),function(){function u(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}if(i.nodeType===1){f||(i.sizcache=c,i.sizset=g);if(typeof b!="string"){if(i===b){j=!0;break}}else if(k.filter(b,[i]).length>0){j=i;break}}i=i[a]}d[g]=j}}}function t(a,b,c,d,e,f){for(var g=0,h=d.length;g<h;g++){var i=d[g];if(i){var j=!1;i=i[a];while(i){if(i.sizcache===c){j=d[i.sizset];break}i.nodeType===1&&!f&&(i.sizcache=c,i.sizset=g);if(i.nodeName.toLowerCase()===b){j=i;break}i=i[a]}d[g]=j}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d=0,e=Object.prototype.toString,g=!1,h=!0,i=/\\/g,j=/\W/;[0,0].sort(function(){h=!1;return 0});var k=function(b,d,f,g){f=f||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return f;var i,j,n,o,q,r,s,t,u=!0,w=k.isXML(d),x=[],y=b;do{a.exec(""),i=a.exec(y);if(i){y=i[3],x.push(i[1]);if(i[2]){o=i[3];break}}}while(i);if(x.length>1&&m.exec(b))if(x.length===2&&l.relative[x[0]])j=v(x[0]+x[1],d);else{j=l.relative[x[0]]?[d]:k(x.shift(),d);while(x.length)b=x.shift(),l.relative[b]&&(b+=x.shift()),j=v(b,j)}else{!g&&x.length>1&&d.nodeType===9&&!w&&l.match.ID.test(x[0])&&!l.match.ID.test(x[x.length-1])&&(q=k.find(x.shift(),d,w),d=q.expr?k.filter(q.expr,q.set)[0]:q.set[0]);if(d){q=g?{expr:x.pop(),set:p(g)}:k.find(x.pop(),x.length===1&&(x[0]==="~"||x[0]==="+")&&d.parentNode?d.parentNode:d,w),j=q.expr?k.filter(q.expr,q.set):q.set,x.length>0?n=p(j):u=!1;while(x.length)r=x.pop(),s=r,l.relative[r]?s=x.pop():r="",s==null&&(s=d),l.relative[r](n,s,w)}else n=x=[]}n||(n=j),n||k.error(r||b);if(e.call(n)==="[object Array]")if(!u)f.push.apply(f,n);else if(d&&d.nodeType===1)for(t=0;n[t]!=null;t++)n[t]&&(n[t]===!0||n[t].nodeType===1&&k.contains(d,n[t]))&&f.push(j[t]);else for(t=0;n[t]!=null;t++)n[t]&&n[t].nodeType===1&&f.push(j[t]);else p(n,f);o&&(k(o,h,f,g),k.uniqueSort(f));return f};k.uniqueSort=function(a){if(r){g=h,a.sort(r);if(g)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},k.matches=function(a,b){return k(a,null,null,b)},k.matchesSelector=function(a,b){return k(b,null,null,[a]).length>0},k.find=function(a,b,c){var d;if(!a)return[];for(var e=0,f=l.order.length;e<f;e++){var g,h=l.order[e];if(g=l.leftMatch[h].exec(a)){var j=g[1];g.splice(1,1);if(j.substr(j.length-1)!=="\\"){g[1]=(g[1]||"").replace(i,""),d=l.find[h](g,b,c);if(d!=null){a=a.replace(l.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},k.filter=function(a,c,d,e){var f,g,h=a,i=[],j=c,m=c&&c[0]&&k.isXML(c[0]);while(a&&c.length){for(var n in l.filter)if((f=l.leftMatch[n].exec(a))!=null&&f[2]){var o,p,q=l.filter[n],r=f[1];g=!1,f.splice(1,1);if(r.substr(r.length-1)==="\\")continue;j===i&&(i=[]);if(l.preFilter[n]){f=l.preFilter[n](f,j,d,i,e,m);if(!f)g=o=!0;else if(f===!0)continue}if(f)for(var s=0;(p=j[s])!=null;s++)if(p){o=q(p,f,s,j);var t=e^!!o;d&&o!=null?t?g=!0:j[s]=!1:t&&(i.push(p),g=!0)}if(o!==b){d||(j=i),a=a.replace(l.match[n],"");if(!g)return[];break}}if(a===h)if(g==null)k.error(a);else break;h=a}return j},k.error=function(a){throw"Syntax error, unrecognized expression: "+a};var l=k.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!j.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&k.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!j.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&k.filter(b,a,!0)}},"":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("parentNode",b,f,a,e,c)},"~":function(a,b,c){var e,f=d++,g=u;typeof b=="string"&&!j.test(b)&&(b=b.toLowerCase(),e=b,g=t),g("previousSibling",b,f,a,e,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(i,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(i,"")},TAG:function(a,b){return a[1].replace(i,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||k.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&k.error(a[0]);a[0]=d++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(i,"");!f&&l.attrMap[g]&&(a[1]=l.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(i,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=k(b[3],null,null,c);else{var g=k.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(l.match.POS.test(b[0])||l.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!k(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=l.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||k.getText([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}k.error(e)},CHILD:function(a,b){var c=b[1],d=a;switch(c){case"only":case"first":while(d=d.previousSibling)if(d.nodeType===1)return!1;if(c==="first")return!0;d=a;case"last":while(d=d.nextSibling)if(d.nodeType===1)return!1;return!0;case"nth":var e=b[2],f=b[3];if(e===1&&f===0)return!0;var g=b[0],h=a.parentNode;if(h&&(h.sizcache!==g||!a.nodeIndex)){var i=0;for(d=h.firstChild;d;d=d.nextSibling)d.nodeType===1&&(d.nodeIndex=++i);h.sizcache=g}var j=a.nodeIndex-f;return e===0?j===0:j%e===0&&j/e>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=l.attrHandle[c]?l.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=l.setFilters[e];if(f)return f(a,c,b,d)}}},m=l.match.POS,n=function(a,b){return"\\"+(b-0+1)};for(var o in l.match)l.match[o]=new RegExp(l.match[o].source+/(?![^\[]*\])(?![^\(]*\))/.source),l.leftMatch[o]=new RegExp(/(^(?:.|\r|\n)*?)/.source+l.match[o].source.replace(/\\(\d+)/g,n));var p=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(q){p=function(a,b){var c=0,d=b||[];if(e.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var f=a.length;c<f;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var r,s;c.documentElement.compareDocumentPosition?r=function(a,b){if(a===b){g=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(r=function(a,b){if(a===b){g=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],h=a.parentNode,i=b.parentNode,j=h;if(h===i)return s(a,b);if(!h)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return s(e[k],f[k]);return k===c?s(a,f[k],-1):s(e[k],b,1)},s=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),k.getText=function(a){var b="",c;for(var d=0;a[d];d++)c=a[d],c.nodeType===3||c.nodeType===4?b+=c.nodeValue:c.nodeType!==8&&(b+=k.getText(c.childNodes));return b},function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(l.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},l.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(l.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(l.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=k,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){k=function(b,e,f,g){e=e||c;if(!g&&!k.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return p(e.getElementsByTagName(b),f);if(h[2]&&l.find.CLASS&&e.getElementsByClassName)return p(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return p([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return p([],f);if(i.id===h[3])return p([i],f)}try{return p(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var m=e,n=e.getAttribute("id"),o=n||d,q=e.parentNode,r=/^\s*[+~]/.test(b);n?o=o.replace(/'/g,"\\$&"):e.setAttribute("id",o),r&&q&&(e=e.parentNode);try{if(!r||q)return p(e.querySelectorAll("[id='"+o+"'] "+b),f)}catch(s){}finally{n||m.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)k[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}k.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!k.isXML(a))try{if(e||!l.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return k(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;l.order.splice(1,0,"CLASS"),l.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?k.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?k.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:k.contains=function(){return!1},k.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var v=function(a,b){var c,d=[],e="",f=b.nodeType?[b]:b;while(c=l.match.PSEUDO.exec(a))e+=c[0],a=a.replace(l.match.PSEUDO,"");a=l.relative[a]?a+"*":a;for(var g=0,h=f.length;g<h;g++)k(a,f[g],d);return k.filter(e,d)};f.find=k,f.expr=k.selectors,f.expr[":"]=f.expr.filters,f.unique=k.uniqueSort,f.text=k.getText,f.isXMLDoc=k.isXML,f.contains=k.contains}();var O=/Until$/,P=/^(?:parents|prevUntil|prevAll)/,Q=/,/,R=/^.[^:#\[\.,]*$/,S=Array.prototype.slice,T=f.expr.match.POS,U={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(W(this,a,!1),"not",a)},filter:function(a){return this.pushStack(W(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h,i,j={},k=1;if(g&&a.length){for(d=0,e=a.length;d<e;d++)i=a[d],j[i]||(j[i]=T.test(i)?f(i,b||this.context):i);while(g&&g.ownerDocument&&g!==b){for(i in j)h=j[i],(h.jquery?h.index(g)>-1:f(g).is(h))&&c.push({selector:i,elem:g,level:k});g=g.parentNode,k++}}return c}var l=T.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(l?l.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a||typeof a=="string")return f.inArray(this[0],a?f(a):this.parent().children());return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(V(c[0])||V(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c),g=S.call(arguments);O.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!U[a]?f.unique(e):e,(this.length>1||Q.test(d))&&P.test(a)&&(e=e.reverse());return this.pushStack(e,a,g.join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var X=/ jQuery\d+="(?:\d+|null)"/g,Y=/^\s+/,Z=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,$=/<([\w:]+)/,_=/<tbody/i,ba=/<|&#?\w+;/,bb=/<(?:script|object|embed|option|style)/i,bc=/checked\s*(?:[^=]|=\s*.checked.)/i,bd=/\/(java|ecma)script/i,be=/^\s*<!(?:\[CDATA\[|\-\-)/,bf={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]};bf.optgroup=bf.option,bf.tbody=bf.tfoot=bf.colgroup=bf.caption=bf.thead,bf.th=bf.td,f.support.htmlSerialize||(bf._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){return this.each(function(){f(this).wrapAll(a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f(arguments[0]);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f(arguments[0]).toArray());return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(X,""):null;if(typeof a=="string"&&!bb.test(a)&&(f.support.leadingWhitespace||!Y.test(a))&&!bf[($.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Z,"<$1></$2>");try{for(var c=0,d=this.length;c<d;c++)this[c].nodeType===1&&(f.cleanData(this[c].getElementsByTagName("*")),this[c].innerHTML=a)}catch(e){this.empty().append(a)}}else f.isFunction(a)?this.each(function(b){var c=f(this);c.html(a.call(this,b,c.html()))}):this.empty().append(a);return this},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bc.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bg(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,bm)}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i;b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof a[0]=="string"&&a[0].length<512&&i===c&&a[0].charAt(0)==="<"&&!bb.test(a[0])&&(f.support.checkClone||!bc.test(a[0]))&&(g=!0,h=f.fragments[a[0]],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[a[0]]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j
+)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d=a.cloneNode(!0),e,g,h;if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bi(a,d),e=bj(a),g=bj(d);for(h=0;e[h];++h)bi(e[h],g[h])}if(b){bh(a,d);if(c){e=bj(a),g=bj(d);for(h=0;e[h];++h)bh(e[h],g[h])}}e=g=null;return d},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!ba.test(k))k=b.createTextNode(k);else{k=k.replace(Z,"<$1></$2>");var l=($.exec(k)||["",""])[1].toLowerCase(),m=bf[l]||bf._default,n=m[0],o=b.createElement("div");o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=_.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]==="<table>"&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&Y.test(k)&&o.insertBefore(b.createTextNode(Y.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i<r;i++)bl(k[i]);else bl(k);k.nodeType?h.push(k):h=f.merge(h,k)}if(d){g=function(a){return!a.type||bd.test(a.type)};for(j=0;h[j];j++)if(e&&f.nodeName(h[j],"script")&&(!h[j].type||h[j].type.toLowerCase()==="text/javascript"))e.push(h[j].parentNode?h[j].parentNode.removeChild(h[j]):h[j]);else{if(h[j].nodeType===1){var s=f.grep(h[j].getElementsByTagName("script"),g);h.splice.apply(h,[j+1,0].concat(s))}d.appendChild(h[j])}}return h},cleanData:function(a){var b,c,d=f.cache,e=f.expando,g=f.event.special,h=f.support.deleteExpando;for(var i=0,j;(j=a[i])!=null;i++){if(j.nodeName&&f.noData[j.nodeName.toLowerCase()])continue;c=j[f.expando];if(c){b=d[c]&&d[c][e];if(b&&b.events){for(var k in b.events)g[k]?f.event.remove(j,k):f.removeEvent(j,k,b.handle);b.handle&&(b.handle.elem=null)}h?delete j[f.expando]:j.removeAttribute&&j.removeAttribute(f.expando),delete d[c]}}}});var bn=/alpha\([^)]*\)/i,bo=/opacity=([^)]*)/,bp=/([A-Z]|^ms)/g,bq=/^-?\d+(?:px)?$/i,br=/^-?\d/,bs=/^[+\-]=/,bt=/[^+\-\.\de]+/g,bu={position:"absolute",visibility:"hidden",display:"block"},bv=["Left","Right"],bw=["Top","Bottom"],bx,by,bz;f.fn.css=function(a,c){if(arguments.length===2&&c===b)return this;return f.access(this,a,c,!0,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)})},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=bx(a,"opacity","opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d;if(h==="number"&&isNaN(d)||d==null)return;h==="string"&&bs.test(d)&&(d=+d.replace(bt,"")+parseFloat(f.css(a,c)),h="number"),h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(bx)return bx(a,c)},swap:function(a,b,c){var d={};for(var e in b)d[e]=a.style[e],a.style[e]=b[e];c.call(a);for(e in b)a.style[e]=d[e]}}),f.curCSS=f.css,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){var e;if(c){if(a.offsetWidth!==0)return bA(a,b,d);f.swap(a,bu,function(){e=bA(a,b,d)});return e}},set:function(a,b){if(!bq.test(b))return b;b=parseFloat(b);if(b>=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bo.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle;c.zoom=1;var e=f.isNaN(b)?"":"alpha(opacity="+b*100+")",g=d&&d.filter||c.filter||"";c.filter=bn.test(g)?g.replace(bn,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bx(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(by=function(a,c){var d,e,g;c=c.replace(bp,"-$1").toLowerCase();if(!(e=a.ownerDocument.defaultView))return b;if(g=e.getComputedStyle(a,null))d=g.getPropertyValue(c),d===""&&!f.contains(a.ownerDocument.documentElement,a)&&(d=f.style(a,c));return d}),c.documentElement.currentStyle&&(bz=function(a,b){var c,d=a.currentStyle&&a.currentStyle[b],e=a.runtimeStyle&&a.runtimeStyle[b],f=a.style;!bq.test(d)&&br.test(d)&&(c=f.left,e&&(a.runtimeStyle.left=a.currentStyle.left),f.left=b==="fontSize"?"1em":d||0,d=f.pixelLeft+"px",f.left=c,e&&(a.runtimeStyle.left=e));return d===""?"auto":d}),bx=by||bz,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bB=/%20/g,bC=/\[\]$/,bD=/\r?\n/g,bE=/#.*$/,bF=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bG=/^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bH=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/,bI=/^(?:GET|HEAD)$/,bJ=/^\/\//,bK=/\?/,bL=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bM=/^(?:select|textarea)/i,bN=/\s+/,bO=/([?&])_=[^&]*/,bP=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bQ=f.fn.load,bR={},bS={},bT,bU;try{bT=e.href}catch(bV){bT=c.createElement("a"),bT.href="",bT=bT.href}bU=bP.exec(bT.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bQ)return bQ.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bL,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bM.test(this.nodeName)||bG.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bD,"\r\n")}}):{name:b.name,value:c.replace(bD,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.bind(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?f.extend(!0,a,f.ajaxSettings,b):(b=a,a=f.extend(!0,f.ajaxSettings,b));for(var c in{context:1,url:1})c in b?a[c]=b[c]:c in f.ajaxSettings&&(a[c]=f.ajaxSettings[c]);return a},ajaxSettings:{url:bT,isLocal:bH.test(bU[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":"*/*"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML}},ajaxPrefilter:bW(bR),ajaxTransport:bW(bS),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a?4:0;var o,r,u,w=l?bZ(d,v,l):b,x,y;if(a>=200&&a<300||a===304){if(d.ifModified){if(x=v.getResponseHeader("Last-Modified"))f.lastModified[k]=x;if(y=v.getResponseHeader("Etag"))f.etag[k]=y}if(a===304)c="notmodified",o=!0;else try{r=b$(d,w),c="success",o=!0}catch(z){c="parsererror",u=z}}else{u=c;if(!c||a)c="error",a<0&&(a=0)}v.status=a,v.statusText=c,o?h.resolveWith(e,[r,c,v]):h.rejectWith(e,[v,c,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.resolveWith(e,[v,c]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f._Deferred(),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bF.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.done,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bE,"").replace(bJ,bU[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bN),d.crossDomain==null&&(r=bP.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bU[1]&&r[2]==bU[2]&&(r[3]||(r[1]==="http:"?80:443))==(bU[3]||(bU[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bX(bR,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bI.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bK.test(d.url)?"&":"?")+d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bO,"$1_="+x);d.url=y+(y===d.url?(bK.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", */*; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bX(bS,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){status<2?w(-1,z):f.error(z)}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)bY(g,a[g],c,e);return d.join("&").replace(bB,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var b_=f.now(),ca=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+b_++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ca.test(b.url)||e&&ca.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ca,l),b.url===j&&(e&&(k=k.replace(ca,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cb=a.ActiveXObject?function(){for(var a in cd)cd[a](0,1)}:!1,cc=0,cd;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ce()||cf()}:ce,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cb&&delete cd[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cc,cb&&(cd||(cd={},f(a).unload(cb)),cd[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cg={},ch,ci,cj=/^(?:toggle|show|hide)$/,ck=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cl,cm=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cn,co=a.webkitRequestAnimationFrame||a.mozRequestAnimationFrame||a.oRequestAnimationFrame;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cr("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),e===""&&f.css(d,"display")==="none"&&f._data(d,"olddisplay",cs(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(cr("hide",3),a,b,c);for(var d=0,e=this.length;d<e;d++)if(this[d].style){var g=f.css(this[d],"display");g!=="none"&&!f._data(this[d],"olddisplay")&&f._data(this[d],"olddisplay",g)}for(d=0;d<e;d++)this[d].style&&(this[d].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(cr("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return this[e.queue===!1?"each":"queue"](function(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]),h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(f.support.inlineBlockNeedsLayout?(j=cs(this.nodeName),j==="inline"?this.style.display="inline-block":(this.style.display="inline",this.style.zoom=1)):this.style.display="inline-block"))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)k=new f.fx(this,b,i),h=a[i],cj.test(h)?k[h==="toggle"?d?"show":"hide":h]():(l=ck.exec(h),m=k.cur(),l?(n=parseFloat(l[2]),o=l[3]||(f.cssNumber[i]?"":"px"),o!=="px"&&(f.style(this,i,(n||1)+o),m=(n||1)/k.cur()*m,f.style(this,i,m+o)),l[1]&&(n=(l[1]==="-="?-1:1)*n+m),k.custom(m,n,o)):k.custom(m,h,""));return!0})},stop:function(a,b){a&&this.queue([]),this.each(function(){var a=f.timers,c=a.length;b||f._unmark(!0,this);while(c--)a[c].elem===this&&(b&&a[c](!0),a.splice(c,1))}),b||this.dequeue();return this}}),f.each({slideDown:cr("show",1),slideUp:cr("hide",1),slideToggle:cr("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default,d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue!==!1?f.dequeue(this):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a,b,c,d){return c+d*a},swing:function(a,b,c,d){return(-Math.cos(a*Math.PI)/2+.5)*d+c}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,b,c){function h(a){return d.step(a)}var d=this,e=f.fx,g;this.startTime=cn||cp(),this.start=a,this.end=b,this.unit=c||this.unit||(f.cssNumber[this.prop]?"":"px"),this.now=this.start,this.pos=this.state=0,h.elem=this.elem,h()&&f.timers.push(h)&&!cl&&(co?(cl=!0,g=function(){cl&&(co(g),e.tick())},co(g)):cl=setInterval(e.tick,e.interval))},show:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.show=!0,this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b=cn||cp(),c=!0,d=this.elem,e=this.options,g,h;if(a||b>=e.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),e.animatedProperties[this.prop]=!0;for(g in e.animatedProperties)e.animatedProperties[g]!==!0&&(c=!1);if(c){e.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){d.style["overflow"+b]=e.overflow[a]}),e.hide&&f(d).hide();if(e.hide||e.show)for(var i in e.animatedProperties)f.style(d,i,e.orig[i]);e.complete.call(d)}return!1}e.duration==Infinity?this.now=b:(h=b-this.startTime,this.state=h/e.duration,this.pos=f.easing[e.animatedProperties[this.prop]](this.state,h,0,1,e.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){for(var a=f.timers,b=0;b<a.length;++b)a[b]()||a.splice(b--,1);a.length||f.fx.stop()},interval:13,stop:function(){clearInterval(cl),cl=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=(a.prop==="width"||a.prop==="height"?Math.max(0,a.now):a.now)+a.unit:a.elem[a.prop]=a.now}}}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var ct=/^t(?:able|d|h)$/i,cu=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?f.fn.offset=function(a){var b=this[0],c;if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);try{c=b.getBoundingClientRect()}catch(d){}var e=b.ownerDocument,g=e.documentElement;if(!c||!f.contains(g,b))return c?{top:c.top,left:c.left}:{top:0,left:0};var h=e.body,i=cv(e),j=g.clientTop||h.clientTop||0,k=g.clientLeft||h.clientLeft||0,l=i.pageYOffset||f.support.boxModel&&g.scrollTop||h.scrollTop,m=i.pageXOffset||f.support.boxModel&&g.scrollLeft||h.scrollLeft,n=c.top+l-j,o=c.left+m-k;return{top:n,left:o}}:f.fn.offset=function(a){var b=this[0];if(a)return this.each(function(b){f.offset.setOffset(this,a,b)});if(!b||!b.ownerDocument)return null;if(b===b.ownerDocument.body)return f.offset.bodyOffset(b);f.offset.initialize();var c,d=b.offsetParent,e=b,g=b.ownerDocument,h=g.documentElement,i=g.body,j=g.defaultView,k=j?j.getComputedStyle(b,null):b.currentStyle,l=b.offsetTop,m=b.offsetLeft;while((b=b.parentNode)&&b!==i&&b!==h){if(f.offset.supportsFixedPosition&&k.position==="fixed")break;c=j?j.getComputedStyle(b,null):b.currentStyle,l-=b.scrollTop,m-=b.scrollLeft,b===d&&(l+=b.offsetTop,m+=b.offsetLeft,f.offset.doesNotAddBorder&&(!f.offset.doesAddBorderForTableAndCells||!ct.test(b.nodeName))&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),e=d,d=b.offsetParent),f.offset.subtractsBorderForOverflowNotVisible&&c.overflow!=="visible"&&(l+=parseFloat(c.borderTopWidth)||0,m+=parseFloat(c.borderLeftWidth)||0),k=c}if(k.position==="relative"||k.position==="static")l+=i.offsetTop,m+=i.offsetLeft;f.offset.supportsFixedPosition&&k.position==="fixed"&&(l+=Math.max(h.scrollTop,i.scrollTop),m+=Math.max(h.scrollLeft,i.scrollLeft));return{top:l,left:m}},f.offset={initialize:function(){var a=c.body,b=c.createElement("div"),d,e,g,h,i=parseFloat(f.css(a,"marginTop"))||0,j="<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";f.extend(b.style,{position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"}),b.innerHTML=j,a.insertBefore(b,a.firstChild),d=b.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,this.doesNotAddBorder=e.offsetTop!==5,this.doesAddBorderForTableAndCells=h.offsetTop===5,e.style.position="fixed",e.style.top="20px",this.supportsFixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",this.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,this.doesNotIncludeMarginInBodyOffset=a.offsetTop!==i,a.removeChild(b),f.offset.initialize=f.noop},bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.offset.initialize(),f.offset.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cu.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cu.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cv(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cv(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a&&a.style?parseFloat(f.css(a,d,"padding")):null},f.fn["outer"+c]=function(a){var b=this[0];return b&&b.style?parseFloat(f.css(b,d,a?"margin":"border")):null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c];return e.document.compatMode==="CSS1Compat"&&g||e.document.body["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var h=f.css(e,d),i=parseFloat(h);return f.isNaN(i)?h:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f})(window); \ No newline at end of file
diff --git a/lib/rdoc/generator/template/darkfish/js/quicksearch.js b/lib/rdoc/generator/template/darkfish/js/quicksearch.js
deleted file mode 100644
index 70dbd33cd9..0000000000
--- a/lib/rdoc/generator/template/darkfish/js/quicksearch.js
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- *
- * JQuery QuickSearch - Hook up a form field to hide non-matching elements.
- * $Id: quicksearch.js 53 2009-01-07 02:52:03Z deveiant $
- *
- * Author: Michael Granger <mgranger@laika.com>
- *
- */
-jQuery.fn.quicksearch = function( target, searchElems, options ) {
- // console.debug( "Quicksearch fn" );
-
- var settings = {
- delay: 250,
- clearButton: false,
- highlightMatches: false,
- focusOnLoad: false,
- noSearchResultsIndicator: null
- };
- if ( options ) $.extend( settings, options );
-
- return jQuery(this).each( function() {
- // console.debug( "Creating a new quicksearch on %o for %o", this, searchElems );
- new jQuery.quicksearch( this, searchElems, settings );
- });
-};
-
-
-jQuery.quicksearch = function( searchBox, searchElems, settings ) {
- var timeout;
- var boxdiv = $(searchBox).parents('div').eq(0);
-
- function init() {
- setupKeyEventHandlers();
- focusOnLoad();
- };
-
- function setupKeyEventHandlers() {
- // console.debug( "Hooking up the 'keypress' event to %o", searchBox );
- $(searchBox).
- unbind( 'keyup' ).
- keyup( function(e) { return onSearchKey( e.keyCode ); });
- $(searchBox).
- unbind( 'keypress' ).
- keypress( function(e) {
- switch( e.which ) {
- // Execute the search on Enter, Tab, or Newline
- case 9:
- case 13:
- case 10:
- clearTimeout( timeout );
- e.preventDefault();
- doQuickSearch();
- break;
-
- // Allow backspace
- case 8:
- return true;
- break;
-
- // Only allow valid search characters
- default:
- return validQSChar( e.charCode );
- }
- });
- };
-
- function focusOnLoad() {
- if ( !settings.focusOnLoad ) return false;
- $(searchBox).focus();
- };
-
- function onSearchKey ( code ) {
- clearTimeout( timeout );
- // console.debug( "...scheduling search." );
- timeout = setTimeout( doQuickSearch, settings.delay );
- };
-
- function validQSChar( code ) {
- var c = String.fromCharCode( code );
- return (
- (c == ':') ||
- (c >= 'a' && c <= 'z') ||
- (c >= 'A' && c <= 'Z')
- );
- };
-
- function doQuickSearch() {
- var searchText = searchBox.value;
- var pat = new RegExp( searchText, "im" );
- var shownCount = 0;
-
- if ( settings.noSearchResultsIndicator ) {
- $('#' + settings.noSearchResultsIndicator).hide();
- }
-
- // All elements start out hidden
- $(searchElems).each( function(index) {
- var str = $(this).text();
-
- if ( pat.test(str) ) {
- shownCount += 1;
- $(this).fadeIn();
- } else {
- $(this).hide();
- }
- });
-
- if ( shownCount == 0 && settings.noSearchResultsIndicator ) {
- $('#' + settings.noSearchResultsIndicator).slideDown();
- }
- };
-
- init();
-};
diff --git a/lib/rdoc/generator/template/darkfish/js/search.js b/lib/rdoc/generator/template/darkfish/js/search.js
new file mode 100644
index 0000000000..dbdfdcbc4c
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/js/search.js
@@ -0,0 +1,94 @@
+Search = function(data, input, result) {
+ this.data = data;
+ this.$input = $(input);
+ this.$result = $(result);
+
+ this.$current = null;
+ this.$view = this.$result.parent();
+ this.searcher = new Searcher(data.index);
+ this.init();
+}
+
+Search.prototype = $.extend({}, Navigation, new function() {
+ var suid = 1;
+
+ this.init = function() {
+ var _this = this;
+ var observer = function() {
+ _this.search(_this.$input[0].value);
+ };
+ this.$input.keyup(observer);
+ this.$input.click(observer); // mac's clear field
+
+ this.searcher.ready(function(results, isLast) {
+ _this.addResults(results, isLast);
+ })
+
+ this.initNavigation();
+ this.setNavigationActive(false);
+ }
+
+ this.search = function(value, selectFirstMatch) {
+ value = jQuery.trim(value).toLowerCase();
+ if (value) {
+ this.setNavigationActive(true);
+ } else {
+ this.setNavigationActive(false);
+ }
+
+ if (value == '') {
+ this.lastQuery = value;
+ this.$result.empty();
+ this.setNavigationActive(false);
+ } else if (value != this.lastQuery) {
+ this.lastQuery = value;
+ this.firstRun = true;
+ this.searcher.find(value);
+ }
+ }
+
+ this.addResults = function(results, isLast) {
+ var target = this.$result.get(0);
+ if (this.firstRun && (results.length > 0 || isLast)) {
+ this.$current = null;
+ this.$result.empty();
+ }
+
+ for (var i=0, l = results.length; i < l; i++) {
+ target.appendChild(this.renderItem.call(this, results[i]));
+ };
+
+ if (this.firstRun && results.length > 0) {
+ this.firstRun = false;
+ this.$current = $(target.firstChild);
+ this.$current.addClass('current');
+ }
+ if (jQuery.browser.msie) this.$element[0].className += '';
+ }
+
+ this.move = function(isDown) {
+ if (!this.$current) return;
+ var $next = this.$current[isDown ? 'next' : 'prev']();
+ if ($next.length) {
+ this.$current.removeClass('current');
+ $next.addClass('current');
+ this.scrollIntoView($next[0], this.$view[0]);
+ this.$current = $next;
+ }
+ return true;
+ }
+
+ this.hlt = function(html) {
+ return this.escapeHTML(html).
+ replace(/\u0001/g, '<em>').
+ replace(/\u0002/g, '</em>');
+ }
+
+ this.escapeHTML = function(html) {
+ return html.replace(/[&<>]/g, function(c) {
+ return '&#' + c.charCodeAt(0) + ';';
+ });
+ }
+
+});
+
diff --git a/lib/rdoc/generator/template/darkfish/js/thickbox-compressed.js b/lib/rdoc/generator/template/darkfish/js/thickbox-compressed.js
deleted file mode 100644
index 3a3fdae1fb..0000000000
--- a/lib/rdoc/generator/template/darkfish/js/thickbox-compressed.js
+++ /dev/null
@@ -1,10 +0,0 @@
-/*
- * Thickbox 3 - One Box To Rule Them All.
- * By Cody Lindley (http://www.codylindley.com)
- * Copyright (c) 2007 cody lindley
- * Licensed under the MIT License: http://www.opensource.org/licenses/mit-license.php
-*/
-
-var tb_pathToImage = "../images/loadingAnimation.gif";
-
-eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('$(o).2S(9(){1u(\'a.18, 3n.18, 3i.18\');1w=1p 1t();1w.L=2H});9 1u(b){$(b).s(9(){6 t=X.Q||X.1v||M;6 a=X.u||X.23;6 g=X.1N||P;19(t,a,g);X.2E();H P})}9 19(d,f,g){3m{3(2t o.v.J.2i==="2g"){$("v","11").r({A:"28%",z:"28%"});$("11").r("22","2Z");3(o.1Y("1F")===M){$("v").q("<U 5=\'1F\'></U><4 5=\'B\'></4><4 5=\'8\'></4>");$("#B").s(G)}}n{3(o.1Y("B")===M){$("v").q("<4 5=\'B\'></4><4 5=\'8\'></4>");$("#B").s(G)}}3(1K()){$("#B").1J("2B")}n{$("#B").1J("2z")}3(d===M){d=""}$("v").q("<4 5=\'K\'><1I L=\'"+1w.L+"\' /></4>");$(\'#K\').2y();6 h;3(f.O("?")!==-1){h=f.3l(0,f.O("?"))}n{h=f}6 i=/\\.2s$|\\.2q$|\\.2m$|\\.2l$|\\.2k$/;6 j=h.1C().2h(i);3(j==\'.2s\'||j==\'.2q\'||j==\'.2m\'||j==\'.2l\'||j==\'.2k\'){1D="";1G="";14="";1z="";1x="";R="";1n="";1r=P;3(g){E=$("a[@1N="+g+"]").36();25(D=0;((D<E.1c)&&(R===""));D++){6 k=E[D].u.1C().2h(i);3(!(E[D].u==f)){3(1r){1z=E[D].Q;1x=E[D].u;R="<1e 5=\'1X\'>&1d;&1d;<a u=\'#\'>2T &2R;</a></1e>"}n{1D=E[D].Q;1G=E[D].u;14="<1e 5=\'1U\'>&1d;&1d;<a u=\'#\'>&2O; 2N</a></1e>"}}n{1r=1b;1n="1t "+(D+1)+" 2L "+(E.1c)}}}S=1p 1t();S.1g=9(){S.1g=M;6 a=2x();6 x=a[0]-1M;6 y=a[1]-1M;6 b=S.z;6 c=S.A;3(b>x){c=c*(x/b);b=x;3(c>y){b=b*(y/c);c=y}}n 3(c>y){b=b*(y/c);c=y;3(b>x){c=c*(x/b);b=x}}13=b+30;1a=c+2G;$("#8").q("<a u=\'\' 5=\'1L\' Q=\'1o\'><1I 5=\'2F\' L=\'"+f+"\' z=\'"+b+"\' A=\'"+c+"\' 23=\'"+d+"\'/></a>"+"<4 5=\'2D\'>"+d+"<4 5=\'2C\'>"+1n+14+R+"</4></4><4 5=\'2A\'><a u=\'#\' 5=\'Z\' Q=\'1o\'>1l</a> 1k 1j 1s</4>");$("#Z").s(G);3(!(14==="")){9 12(){3($(o).N("s",12)){$(o).N("s",12)}$("#8").C();$("v").q("<4 5=\'8\'></4>");19(1D,1G,g);H P}$("#1U").s(12)}3(!(R==="")){9 1i(){$("#8").C();$("v").q("<4 5=\'8\'></4>");19(1z,1x,g);H P}$("#1X").s(1i)}o.1h=9(e){3(e==M){I=2w.2v}n{I=e.2u}3(I==27){G()}n 3(I==3k){3(!(R=="")){o.1h="";1i()}}n 3(I==3j){3(!(14=="")){o.1h="";12()}}};16();$("#K").C();$("#1L").s(G);$("#8").r({Y:"T"})};S.L=f}n{6 l=f.2r(/^[^\\?]+\\??/,\'\');6 m=2p(l);13=(m[\'z\']*1)+30||3h;1a=(m[\'A\']*1)+3g||3f;W=13-30;V=1a-3e;3(f.O(\'2j\')!=-1){1E=f.1B(\'3d\');$("#15").C();3(m[\'1A\']!="1b"){$("#8").q("<4 5=\'2f\'><4 5=\'1H\'>"+d+"</4><4 5=\'2e\'><a u=\'#\' 5=\'Z\' Q=\'1o\'>1l</a> 1k 1j 1s</4></4><U 1W=\'0\' 2d=\'0\' L=\'"+1E[0]+"\' 5=\'15\' 1v=\'15"+1f.2c(1f.1y()*2b)+"\' 1g=\'1m()\' J=\'z:"+(W+29)+"p;A:"+(V+17)+"p;\' > </U>")}n{$("#B").N();$("#8").q("<U 1W=\'0\' 2d=\'0\' L=\'"+1E[0]+"\' 5=\'15\' 1v=\'15"+1f.2c(1f.1y()*2b)+"\' 1g=\'1m()\' J=\'z:"+(W+29)+"p;A:"+(V+17)+"p;\'> </U>")}}n{3($("#8").r("Y")!="T"){3(m[\'1A\']!="1b"){$("#8").q("<4 5=\'2f\'><4 5=\'1H\'>"+d+"</4><4 5=\'2e\'><a u=\'#\' 5=\'Z\'>1l</a> 1k 1j 1s</4></4><4 5=\'F\' J=\'z:"+W+"p;A:"+V+"p\'></4>")}n{$("#B").N();$("#8").q("<4 5=\'F\' 3c=\'3b\' J=\'z:"+W+"p;A:"+V+"p;\'></4>")}}n{$("#F")[0].J.z=W+"p";$("#F")[0].J.A=V+"p";$("#F")[0].3a=0;$("#1H").11(d)}}$("#Z").s(G);3(f.O(\'37\')!=-1){$("#F").q($(\'#\'+m[\'26\']).1T());$("#8").24(9(){$(\'#\'+m[\'26\']).q($("#F").1T())});16();$("#K").C();$("#8").r({Y:"T"})}n 3(f.O(\'2j\')!=-1){16();3($.1q.35){$("#K").C();$("#8").r({Y:"T"})}}n{$("#F").34(f+="&1y="+(1p 33().32()),9(){16();$("#K").C();1u("#F a.18");$("#8").r({Y:"T"})})}}3(!m[\'1A\']){o.21=9(e){3(e==M){I=2w.2v}n{I=e.2u}3(I==27){G()}}}}31(e){}}9 1m(){$("#K").C();$("#8").r({Y:"T"})}9 G(){$("#2Y").N("s");$("#Z").N("s");$("#8").2X("2W",9(){$(\'#8,#B,#1F\').2V("24").N().C()});$("#K").C();3(2t o.v.J.2i=="2g"){$("v","11").r({A:"1Z",z:"1Z"});$("11").r("22","")}o.1h="";o.21="";H P}9 16(){$("#8").r({2U:\'-\'+20((13/2),10)+\'p\',z:13+\'p\'});3(!(1V.1q.2Q&&1V.1q.2P<7)){$("#8").r({38:\'-\'+20((1a/2),10)+\'p\'})}}9 2p(a){6 b={};3(!a){H b}6 c=a.1B(/[;&]/);25(6 i=0;i<c.1c;i++){6 d=c[i].1B(\'=\');3(!d||d.1c!=2){39}6 e=2a(d[0]);6 f=2a(d[1]);f=f.2r(/\\+/g,\' \');b[e]=f}H b}9 2x(){6 a=o.2M;6 w=1S.2o||1R.2o||(a&&a.1Q)||o.v.1Q;6 h=1S.1P||1R.1P||(a&&a.2n)||o.v.2n;1O=[w,h];H 1O}9 1K(){6 a=2K.2J.1C();3(a.O(\'2I\')!=-1&&a.O(\'3o\')!=-1){H 1b}}',62,211,'|||if|div|id|var||TB_window|function||||||||||||||else|document|px|append|css|click||href|body||||width|height|TB_overlay|remove|TB_Counter|TB_TempArray|TB_ajaxContent|tb_remove|return|keycode|style|TB_load|src|null|unbind|indexOf|false|title|TB_NextHTML|imgPreloader|block|iframe|ajaxContentH|ajaxContentW|this|display|TB_closeWindowButton||html|goPrev|TB_WIDTH|TB_PrevHTML|TB_iframeContent|tb_position||thickbox|tb_show|TB_HEIGHT|true|length|nbsp|span|Math|onload|onkeydown|goNext|Esc|or|close|tb_showIframe|TB_imageCount|Close|new|browser|TB_FoundURL|Key|Image|tb_init|name|imgLoader|TB_NextURL|random|TB_NextCaption|modal|split|toLowerCase|TB_PrevCaption|urlNoQuery|TB_HideSelect|TB_PrevURL|TB_ajaxWindowTitle|img|addClass|tb_detectMacXFF|TB_ImageOff|150|rel|arrayPageSize|innerHeight|clientWidth|self|window|children|TB_prev|jQuery|frameborder|TB_next|getElementById|auto|parseInt|onkeyup|overflow|alt|unload|for|inlineId||100||unescape|1000|round|hspace|TB_closeAjaxWindow|TB_title|undefined|match|maxHeight|TB_iframe|bmp|gif|png|clientHeight|innerWidth|tb_parseQuery|jpeg|replace|jpg|typeof|which|keyCode|event|tb_getPageSize|show|TB_overlayBG|TB_closeWindow|TB_overlayMacFFBGHack|TB_secondLine|TB_caption|blur|TB_Image|60|tb_pathToImage|mac|userAgent|navigator|of|documentElement|Prev|lt|version|msie|gt|ready|Next|marginLeft|trigger|fast|fadeOut|TB_imageOff|hidden||catch|getTime|Date|load|safari|get|TB_inline|marginTop|continue|scrollTop|TB_modal|class|TB_|45|440|40|630|input|188|190|substr|try|area|firefox'.split('|'),0,{})) \ No newline at end of file
diff --git a/lib/rdoc/generator/template/darkfish/page.rhtml b/lib/rdoc/generator/template/darkfish/page.rhtml
new file mode 100644
index 0000000000..942172919b
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/page.rhtml
@@ -0,0 +1,18 @@
+<body class="file">
+<nav id="metadata">
+ <%= render '_sidebar_navigation.rhtml' %>
+
+ <%= render '_sidebar_search.rhtml' %>
+
+ <%= render '_sidebar_table_of_contents.rhtml' %>
+
+ <div id="project-metadata">
+ <%= render '_sidebar_pages.rhtml' %>
+ <%= render '_sidebar_classes.rhtml' %>
+ </div>
+</nav>
+
+<div id="documentation" class="description">
+ <%= file.description %>
+</div>
+
diff --git a/lib/rdoc/generator/template/darkfish/rdoc.css b/lib/rdoc/generator/template/darkfish/rdoc.css
index ea91421837..b965e604e6 100644
--- a/lib/rdoc/generator/template/darkfish/rdoc.css
+++ b/lib/rdoc/generator/template/darkfish/rdoc.css
@@ -6,15 +6,14 @@
*
*/
+/* vim: ft=css et sw=2 ts=2 sts=2 */
/* Base Green is: #6C8C22 */
-*{ padding: 0; margin: 0; }
+* { padding: 0; margin: 0; }
body {
background: #efefef;
font: 14px "Helvetica Neue", Helvetica, Tahoma, sans-serif;
-}
-body.class, body.module, body.file {
margin-left: 40px;
}
body.file-popup {
@@ -44,6 +43,15 @@ pre {
padding: 0.5em 0;
}
+blockquote {
+ background: #ddd;
+ margin: 1em;
+ padding: 0.25em;
+}
+
+blockquote > :first-child {
+ margin-top: 0 !important;
+}
/* @group Generic Classes */
@@ -51,16 +59,21 @@ pre {
display: none;
}
-.quicksearch-field {
+#search-field {
width: 98%;
- background: #ddd;
- border: 1px solid #aaa;
+ background: #eee;
+ border: none;
height: 1.5em;
-webkit-border-radius: 4px;
}
-.quicksearch-field:focus {
+#search-field:focus {
background: #f1edba;
}
+#search-field:-moz-placeholder,
+#search-field::-webkit-input-placeholder {
+ font-weight: bold;
+ color: #666;
+}
.missing-docs {
font-size: 120%;
@@ -86,28 +99,8 @@ pre {
/* @end */
-
/* @group Index Page, Standalone file pages */
-body.indexpage {
- margin: 1em 3em;
-}
-body.indexpage p,
-body.indexpage div,
-body.file p {
- margin: 1em 0;
-}
-
-.indexpage .rdoc-list p, .file .rdoc-list p {
- margin: 0em 0;
-}
-
-.indexpage ol,
-.file #documentation ol {
- line-height: 160%;
-}
-
-.indexpage ul,
-.file #documentation ul {
+.indexpage ul {
line-height: 160%;
list-style: none;
}
@@ -116,25 +109,16 @@ body.file p {
font-size: 16px;
}
-.indexpage li,
-.file #documentation li {
+.indexpage li {
padding-left: 20px;
}
-.indexpage ol,
-.file #documentation ol {
- margin-left: 20px;
-}
-
-.indexpage ol > li,
-.file #documentation ol > li {
- padding-left: 0;
-}
-
-.indexpage ul > li,
-.file #documentation ul > li {
+.indexpage ul > li {
background: url(images/bullet_black.png) no-repeat left 4px;
}
+.indexpage li.method {
+ background: url(images/plugin.png) no-repeat left 4px;
+}
.indexpage li.module {
background: url(images/package.png) no-repeat left 4px;
}
@@ -144,36 +128,37 @@ body.file p {
.indexpage li.file {
background: url(images/page_white_text.png) no-repeat left 4px;
}
-.file li p,
-.indexpage li p {
- margin: 0 0;
+.indexpage li li {
+ background: url(images/tag_blue.png) no-repeat left 4px;
+}
+.indexpage li .toc-toggle {
+ width: 16px;
+ height: 16px;
+ background: url(images/add.png) no-repeat;
+}
+
+.indexpage li .toc-toggle.open {
+ background: url(images/delete.png) no-repeat;
}
/* @end */
/* @group Top-Level Structure */
-.class #metadata,
-.file #metadata,
-.module #metadata {
+#metadata {
float: left;
width: 260px;
}
-.class #documentation,
-.file #documentation,
-.module #documentation {
+#documentation {
margin: 2em 1em 5em 300px;
min-width: 340px;
}
-.file #metadata {
- margin: 0.8em;
-}
-
#validator-badges {
clear: both;
margin: 1em 1em 2em;
+ font-size: smaller;
}
/* @end */
@@ -184,7 +169,7 @@ body.file p {
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border: 1px solid #aaa;
- margin: 0 8px 16px;
+ margin: 0 8px 8px;
font-size: 90%;
overflow: hidden;
}
@@ -210,11 +195,24 @@ body.file p {
list-style: none;
}
+#file-metadata {
+ margin-top: 2em;
+}
+
#file-metadata ul {
padding-left: 28px;
list-style-image: url(images/page_green.png);
}
+#table-of-contents {
+ margin-top: 2em;
+}
+
+#table-of-contents ul {
+ padding-left: 28px;
+ list-style-image: url(images/tag_blue.png);
+}
+
dl.svninfo {
color: #666;
margin: 0;
@@ -225,7 +223,9 @@ dl.svninfo dt {
ul.link-list li {
white-space: nowrap;
+ line-height: 20px;
}
+
ul.link-list .type {
font-size: 8px;
text-transform: uppercase;
@@ -235,16 +235,21 @@ ul.link-list .type {
-webkit-border-radius: 5px;
}
+.calls-super {
+ background: url(images/arrow_up.png) no-repeat right center;
+}
+
/* @end */
+/* @group Class Metadata Section */
+#class-metadata {
+ margin-top: 2em;
+}
+/* @end */
/* @group Project Metadata Section */
#project-metadata {
- margin-top: 3em;
-}
-
-.file #project-metadata {
- margin-top: 0em;
+ margin-top: 2em;
}
#project-metadata .section {
@@ -254,33 +259,14 @@ ul.link-list .type {
border-bottom: 1px solid #aaa;
position: relative;
}
-#project-metadata h3.section-header .search-toggle {
- position: absolute;
- right: 5px;
-}
-
#project-metadata form {
color: #777;
background: #ccc;
- padding: 8px 8px 16px;
- border-bottom: 1px solid #bbb;
-}
-#project-metadata fieldset {
- border: 0;
-}
-
-#no-class-search-results {
- margin: 0 auto 1em;
- text-align: center;
- font-size: 14px;
- font-weight: bold;
- color: #aaa;
}
/* @end */
-
/* @group Documentation Section */
.description {
font-size: 100%;
@@ -295,34 +281,44 @@ ul.link-list .type {
margin: 0;
}
+.description ol,
.description ul {
margin-left: 1.5em;
}
+.description ol li,
.description ul li {
line-height: 1.4em;
}
-.description dl,
-#documentation dl {
+.note-list {
+ margin: 8px 0;
+}
+
+.label-list {
margin: 8px 1.5em;
border: 1px solid #ccc;
}
-.description dl {
+.description .label-list {
font-size: 14px;
}
-.description dt,
-#documentation dt {
+.note-list dt {
+ font-weight: bold;
+}
+.note-list dd {
+ padding: 0 12px;
+}
+
+.label-list dt {
padding: 2px 4px;
font-weight: bold;
background: #ddd;
}
-.description dd,
-#documentation dd {
+.label-list dd {
padding: 2px 12px;
}
-.description dd + dt,
-#documentation dd + dt {
+.label-list dd + dt,
+.note-list dd + dt {
margin-top: 0.7em;
}
@@ -331,8 +327,8 @@ ul.link-list .type {
}
#documentation h2.section-header {
- margin-top: 2em;
- padding: 0.75em 0.5em;
+ margin-top: 1em;
+ padding: 0.25em 0.5em;
background: #ccc;
color: #333;
font-size: 175%;
@@ -341,8 +337,25 @@ ul.link-list .type {
-webkit-border-radius: 3px;
}
+.documentation-section-title {
+ position: relative;
+}
+.documentation-section-title .section-click-top {
+ position: absolute;
+ top: 6px;
+ right: 12px;
+ font-size: 10px;
+ color: #9b9877;
+ visibility: hidden;
+ padding-right: 0.5px;
+}
+
+.documentation-section-title:hover .section-click-top {
+ visibility: visible;
+}
+
#documentation h3.section-header {
- margin-top: 2em;
+ margin-top: 1em;
padding: 0.25em 0.5em;
background-color: #dedede;
color: #333;
@@ -398,6 +411,11 @@ ul.link-list .type {
display: none;
}
+#documentation .method-description .method-calls-super {
+ color: #333;
+ font-weight: bolder;
+}
+
#documentation .method-detail {
margin: 0.5em 0;
padding: 0.5em 0;
@@ -429,7 +447,7 @@ ul.link-list .type {
line-height: 20px;
background: url(images/zoom.png) no-repeat right top;
}
-#documentation .method-detail:hover .method-click-advice {
+#documentation .method-heading:hover .method-click-advice {
visibility: visible;
}
@@ -455,14 +473,14 @@ ul.link-list .type {
cursor: default;
}
#documentation .method-description p {
- padding: 0;
-}
-#documentation .method-description p + p {
margin-bottom: 0.5em;
}
#documentation .method-description ul {
margin-left: 1.5em;
}
+pre {
+ margin: 0.5em 0;
+}
#documentation .attribute-method-heading {
background: url(images/tag_green.png) no-repeat left bottom;
@@ -481,283 +499,76 @@ ul.link-list .type {
/* @end */
-
-
/* @group Source Code */
-div.method-source-code {
+pre {
+ overflow: auto;
background: #262626;
- color: #efefef;
- margin: 1em;
- padding: 0.5em;
+ color: white;
border: 1px dashed #999;
- overflow: hidden;
+ padding: 0.5em;
}
-div.method-source-code pre {
- background: inherit;
- padding: 0;
- color: white;
- overflow: auto;
+.description pre {
+ margin: 0 0.4em;
}
-/* @group Ruby keyword styles */
-
.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-comment { color: #dc0000; font-weight: bold; background: transparent; }
.ruby-regexp { color: #ffa07a; background: transparent; }
.ruby-value { color: #7fffd4; background: transparent; }
/* @end */
-/* @end */
-
-
-/* @group File Popup Contents */
-
-.file #metadata,
-.file-popup #metadata {
-}
-
-.file-popup dl {
- font-size: 80%;
- padding: 0.75em;
- background-color: #dedede;
- color: #333;
- border: 1px solid #bbb;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
-}
-.file dt {
- font-weight: bold;
- padding-left: 22px;
- line-height: 20px;
- background: url(images/page_white_width.png) no-repeat left top;
-}
-.file dt.modified-date {
- background: url(images/date.png) no-repeat left top;
-}
-.file dt.requires {
- background: url(images/plugin.png) no-repeat left top;
-}
-.file dt.scs-url {
- background: url(images/wrench.png) no-repeat left top;
-}
-
-.file dl dd {
- margin: 0 0 1em 0;
-}
-.file #metadata dl dd ul {
- list-style: circle;
- margin-left: 20px;
- padding-top: 0;
-}
-.file #metadata dl dd ul li {
-}
-
-
-.file h2 {
- margin-top: 2em;
- padding: 0.75em 0.5em;
- background-color: #dedede;
- color: #333;
- font-size: 120%;
- border: 1px solid #bbb;
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
-}
-
-/* @end */
-
-
-/* @group ThickBox Styles */
-#TB_window {
- font: 12px Arial, Helvetica, sans-serif;
- color: #333333;
-}
-
-#TB_secondLine {
- font: 10px Arial, Helvetica, sans-serif;
- color:#666666;
+/* @group search results */
+#search-results h1 {
+ font-size: 1em;
+ font-weight: normal;
+ text-shadow: none;
}
-#TB_window :link,
-#TB_window :visited { color: #666666; }
-#TB_window :link:hover,
-#TB_window :visited:hover { color: #000; }
-#TB_window :link:active,
-#TB_window :visited:active { color: #666666; }
-#TB_window :link:focus,
-#TB_window :visited:focus { color: #666666; }
-
-#TB_overlay {
- position: fixed;
- z-index:100;
- top: 0px;
- left: 0px;
- height:100%;
- width:100%;
-}
-
-.TB_overlayMacFFBGHack {background: url(images/macFFBgHack.png) repeat;}
-.TB_overlayBG {
- background-color:#000;
- filter:alpha(opacity=75);
- -moz-opacity: 0.75;
- opacity: 0.75;
-}
-
-* html #TB_overlay { /* ie6 hack */
- position: absolute;
- height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
-}
-
-#TB_window {
- position: fixed;
- background: #ffffff;
- z-index: 102;
- color:#000000;
- display:none;
- border: 4px solid #525252;
- text-align:left;
- top:50%;
- left:50%;
-}
-
-* html #TB_window { /* ie6 hack */
- position: absolute;
- margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
-}
-
-#TB_window img#TB_Image {
- display:block;
- margin: 15px 0 0 15px;
- border-right: 1px solid #ccc;
- border-bottom: 1px solid #ccc;
- border-top: 1px solid #666;
- border-left: 1px solid #666;
-}
-
-#TB_caption{
- height:25px;
- padding:7px 30px 10px 25px;
- float:left;
-}
-
-#TB_closeWindow{
- height:25px;
- padding:11px 25px 10px 0;
- float:right;
-}
-
-#TB_closeAjaxWindow{
- padding:7px 10px 5px 0;
- margin-bottom:1px;
- text-align:right;
- float:right;
-}
-
-#TB_ajaxWindowTitle{
- float:left;
- padding:7px 0 5px 10px;
- margin-bottom:1px;
- font-size: 22px;
-}
-
-#TB_title{
- background-color: #6C8C22;
- color: #dedede;
- height:40px;
-}
-#TB_title :link,
-#TB_title :visited {
- color: white !important;
- border-bottom: 1px dotted #dedede;
-}
-
-#TB_ajaxContent{
- clear:both;
- padding:2px 15px 15px 15px;
- overflow:auto;
- text-align:left;
- line-height:1.4em;
-}
-
-#TB_ajaxContent.TB_modal{
- padding:15px;
+#search-results .current {
+ background: #ccc;
+ border-bottom: 1px solid transparent;
}
-#TB_ajaxContent p{
- padding:5px 0px 5px 0px;
+#search-results li {
+ list-style: none;
+ border-bottom: 1px solid #aaa;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ margin-bottom: 0.5em;
}
-#TB_load{
- position: fixed;
- display:none;
- height:13px;
- width:208px;
- z-index:103;
- top: 50%;
- left: 50%;
- margin: -6px 0 0 -104px; /* -height/2 0 0 -width/2 */
+#search-results li:last-child {
+ border-bottom: none;
+ margin-bottom: 0;
}
-* html #TB_load { /* ie6 hack */
- position: absolute;
- margin-top: expression(0 - parseInt(this.offsetHeight / 2) + (TBWindowMargin = document.documentElement && document.documentElement.scrollTop || document.body.scrollTop) + 'px');
+#search-results li p {
+ padding: 0;
+ margin: 0.5em;
}
-#TB_HideSelect{
- z-index:99;
- position:fixed;
- top: 0;
- left: 0;
- background-color:#fff;
- border:none;
- filter:alpha(opacity=0);
- -moz-opacity: 0;
- opacity: 0;
- height:100%;
- width:100%;
+#search-results .search-namespace {
+ font-weight: bold;
}
-* html #TB_HideSelect { /* ie6 hack */
- position: absolute;
- height: expression(document.body.scrollHeight > document.body.offsetHeight ? document.body.scrollHeight : document.body.offsetHeight + 'px');
+#search-results li em {
+ background: yellow;
+ font-style: normal;
}
-#TB_iframeContent{
- clear:both;
- border:none;
- margin-bottom:-1px;
- margin-top:1px;
- _margin-bottom:1px;
+#search-results pre {
+ margin: 0.5em;
}
/* @end */
-/* @group Debugging Section */
-
-#debugging-toggle {
- text-align: center;
-}
-#debugging-toggle img {
- cursor: pointer;
-}
-
-#rdoc-debugging-section-dump {
- display: none;
- margin: 0 2em 2em;
- background: #ccc;
- border: 1px solid #999;
-}
-
-
-
-/* @end */
diff --git a/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml b/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml
new file mode 100644
index 0000000000..24c9ba8eaa
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/servlet_not_found.rhtml
@@ -0,0 +1,18 @@
+<body>
+<nav id="metadata">
+ <%= render '_sidebar_navigation.rhtml' %>
+
+ <%= render '_sidebar_search.rhtml' %>
+
+ <div id="project-metadata">
+ <%= render '_sidebar_pages.rhtml' %>
+ <%= render '_sidebar_classes.rhtml' %>
+ </div>
+</nav>
+
+<div id="documentation" class="description">
+ <h1>Not Found</h1>
+
+ <p>The page <kbd><%=h path %></kbd> was not found
+</div>
+
diff --git a/lib/rdoc/generator/template/darkfish/servlet_root.rhtml b/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
new file mode 100644
index 0000000000..63b4ee8ff7
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/servlet_root.rhtml
@@ -0,0 +1,37 @@
+<body>
+<nav id="metadata">
+<%= render '_sidebar_search.rhtml' %>
+
+<%= render '_sidebar_installed.rhtml' %>
+</nav>
+
+<div id="documentation" class="description">
+ <h1>Local RDoc Documentation</h1>
+
+ <p>Here you can browse local documentation from the ruby standard library and
+ your installed gems.
+
+<% gems = installed.select { |_, _, _, type,| type == :gem } %>
+<% missing = gems.reject { |_, _, exists,| exists } %>
+<% unless missing.empty? then %>
+ <h2>Missing Gem Documentation</h2>
+
+ <p>You are missing documentation for some of your installed gems.
+ You can install missing documentation for gems by running
+ <kbd>gem rdoc --all</kbd>. After installing the missing documentation you
+ only need to reload this page. The newly created documentation will
+ automatically appear.
+
+ <p>You can also install documentation for a specific gem by running one of
+ the following commands.
+
+ <ul>
+ <% names = missing.map { |name,| name.sub(/-([^-]*)$/, '') }.uniq %>
+ <% names.each do |name| %>
+ <li><kbd>gem rdoc <%=h name %></kbd>
+ <% end %>
+ </ul>
+<% end %>
+
+</div>
+
diff --git a/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
new file mode 100644
index 0000000000..8f19085bb4
--- /dev/null
+++ b/lib/rdoc/generator/template/darkfish/table_of_contents.rhtml
@@ -0,0 +1,55 @@
+<body class="indexpage">
+<h1><%= h @title %></h1>
+
+<% simple_files = @files.select { |f| f.text? } %>
+<% unless simple_files.empty? then %>
+<h2>Pages</h2>
+<ul>
+<% simple_files.sort.each do |file| %>
+ <li class="file">
+ <a href="<%= file.path %>"><%= h file.page_name %></a>
+<%
+ # HACK table_of_contents should not exist on Document
+ table = file.parse(file.comment).table_of_contents
+ unless table.empty? then %>
+ <img class="toc-toggle" src="images/transparent.png" alt="" title="toggle headings">
+ <ul class="initially-hidden">
+<% table.each do |heading| %>
+ <li><a href="<%= file.path %>#<%= heading.aref %>"><%= heading.plain_html %></a>
+<% end %>
+ </ul>
+<% end %>
+ </li>
+ <% end %>
+</ul>
+<% end %>
+
+<h2 id="classes">Classes/Modules</h2>
+<ul>
+<% @modsort.each do |klass| %>
+ <li class="<%= klass.type %>">
+ <a href="<%= klass.path %>"><%= klass.full_name %></a>
+<% table = []
+ table.concat klass.parse(klass.comment).table_of_contents
+ table.concat klass.section_contents
+
+ unless table.empty? then %>
+ <img class="toc-toggle" src="images/transparent.png" alt="" title="toggle headings">
+ <ul class="initially-hidden">
+<% table.each do |item| %>
+ <li><a href="<%= klass.path %>#<%= item.aref %>"><%= item.plain_html %></a>
+<% end %>
+ </ul>
+<% end %>
+ </li>
+ <% end %>
+</ul>
+
+<h2 id="methods">Methods</h2>
+<ul>
+ <% @store.all_classes_and_modules.map do |mod|
+ mod.method_list
+ end.flatten.sort.each do |method| %>
+ <li class="method"><a href="<%= method.path %>"><%= method.pretty_name %> &mdash; <%= method.parent.full_name %></a>
+ <% end %>
+</ul>
diff --git a/lib/rdoc/generator/template/json_index/js/navigation.js b/lib/rdoc/generator/template/json_index/js/navigation.js
new file mode 100644
index 0000000000..e41268123e
--- /dev/null
+++ b/lib/rdoc/generator/template/json_index/js/navigation.js
@@ -0,0 +1,142 @@
+/*
+ * Navigation allows movement using the arrow keys through the search results.
+ *
+ * When using this library you will need to set scrollIntoView to the
+ * appropriate function for your layout. Use scrollInWindow if the container
+ * is not scrollable and scrollInElement if the container is a separate
+ * scrolling region.
+ */
+Navigation = new function() {
+ this.initNavigation = function() {
+ var _this = this;
+
+ $(document).keydown(function(e) {
+ _this.onkeydown(e);
+ }).keyup(function(e) {
+ _this.onkeyup(e);
+ });
+
+ this.navigationActive = true;
+ }
+
+ this.setNavigationActive = function(state) {
+ this.navigationActive = state;
+ this.clearMoveTimeout();
+ }
+
+ this.onkeyup = function(e) {
+ if (!this.navigationActive) return;
+
+ switch(e.keyCode) {
+ case 37: //Event.KEY_LEFT:
+ case 38: //Event.KEY_UP:
+ case 39: //Event.KEY_RIGHT:
+ case 40: //Event.KEY_DOWN:
+ this.clearMoveTimeout();
+ break;
+ }
+ }
+
+ this.onkeydown = function(e) {
+ if (!this.navigationActive) return;
+ switch(e.keyCode) {
+ case 37: //Event.KEY_LEFT:
+ if (this.moveLeft()) e.preventDefault();
+ break;
+ case 38: //Event.KEY_UP:
+ if (e.keyCode == 38 || e.ctrlKey) {
+ if (this.moveUp()) e.preventDefault();
+ this.startMoveTimeout(false);
+ }
+ break;
+ case 39: //Event.KEY_RIGHT:
+ if (this.moveRight()) e.preventDefault();
+ break;
+ case 40: //Event.KEY_DOWN:
+ if (e.keyCode == 40 || e.ctrlKey) {
+ if (this.moveDown()) e.preventDefault();
+ this.startMoveTimeout(true);
+ }
+ break;
+ case 13: //Event.KEY_RETURN:
+ if (this.$current)
+ e.preventDefault();
+ this.select(this.$current);
+ break;
+ }
+ if (e.ctrlKey && e.shiftKey) this.select(this.$current);
+ }
+
+ this.clearMoveTimeout = function() {
+ clearTimeout(this.moveTimeout);
+ this.moveTimeout = null;
+ }
+
+ this.startMoveTimeout = function(isDown) {
+ if (!$.browser.mozilla && !$.browser.opera) return;
+ if (this.moveTimeout) this.clearMoveTimeout();
+ var _this = this;
+
+ var go = function() {
+ if (!_this.moveTimeout) return;
+ _this[isDown ? 'moveDown' : 'moveUp']();
+ _this.moveTimout = setTimeout(go, 100);
+ }
+ this.moveTimeout = setTimeout(go, 200);
+ }
+
+ this.moveRight = function() {
+ }
+
+ this.moveLeft = function() {
+ }
+
+ this.move = function(isDown) {
+ }
+
+ this.moveUp = function() {
+ return this.move(false);
+ }
+
+ this.moveDown = function() {
+ return this.move(true);
+ }
+
+ /*
+ * Scrolls to the given element in the scrollable element view.
+ */
+ this.scrollInElement = function(element, view) {
+ var offset, viewHeight, viewScroll, height;
+ offset = element.offsetTop;
+ height = element.offsetHeight;
+ viewHeight = view.offsetHeight;
+ viewScroll = view.scrollTop;
+
+ if (offset - viewScroll + height > viewHeight) {
+ view.scrollTop = offset - viewHeight + height;
+ }
+ if (offset < viewScroll) {
+ view.scrollTop = offset;
+ }
+ }
+
+ /*
+ * Scrolls to the given element in the window. The second argument is
+ * ignored
+ */
+ this.scrollInWindow = function(element, ignored) {
+ var offset, viewHeight, viewScroll, height;
+ offset = element.offsetTop;
+ height = element.offsetHeight;
+ viewHeight = window.innerHeight;
+ viewScroll = window.scrollY;
+
+ if (offset - viewScroll + height > viewHeight) {
+ window.scrollTo(window.scrollX, offset - viewHeight + height);
+ }
+ if (offset < viewScroll) {
+ window.scrollTo(window.scrollX, offset);
+ }
+ }
+}
+
diff --git a/lib/rdoc/generator/template/json_index/js/searcher.js b/lib/rdoc/generator/template/json_index/js/searcher.js
new file mode 100644
index 0000000000..f854b541d0
--- /dev/null
+++ b/lib/rdoc/generator/template/json_index/js/searcher.js
@@ -0,0 +1,228 @@
+Searcher = function(data) {
+ this.data = data;
+ this.handlers = [];
+}
+
+Searcher.prototype = new function() {
+ // search is performed in chunks of 1000 for non-blocking user input
+ var CHUNK_SIZE = 1000;
+ // do not try to find more than 100 results
+ var MAX_RESULTS = 100;
+ var huid = 1;
+ var suid = 1;
+ var runs = 0;
+
+ this.find = function(query) {
+ var queries = splitQuery(query);
+ var regexps = buildRegexps(queries);
+ var highlighters = buildHilighters(queries);
+ var state = { from: 0, pass: 0, limit: MAX_RESULTS, n: suid++};
+ var _this = this;
+
+ this.currentSuid = state.n;
+
+ if (!query) return;
+
+ var run = function() {
+ // stop current search thread if new search started
+ if (state.n != _this.currentSuid) return;
+
+ var results =
+ performSearch(_this.data, regexps, queries, highlighters, state);
+ var hasMore = (state.limit > 0 && state.pass < 4);
+
+ triggerResults.call(_this, results, !hasMore);
+ if (hasMore) {
+ setTimeout(run, 2);
+ }
+ runs++;
+ };
+ runs = 0;
+
+ // start search thread
+ run();
+ }
+
+ /* ----- Events ------ */
+ this.ready = function(fn) {
+ fn.huid = huid;
+ this.handlers.push(fn);
+ }
+
+ /* ----- Utilities ------ */
+ function splitQuery(query) {
+ return jQuery.grep(query.split(/(\s+|::?|\(\)?)/), function(string) {
+ return string.match(/\S/)
+ });
+ }
+
+ function buildRegexps(queries) {
+ return jQuery.map(queries, function(query) {
+ return new RegExp(query.replace(/(.)/g, '([$1])([^$1]*?)'), 'i')
+ });
+ }
+
+ function buildHilighters(queries) {
+ return jQuery.map(queries, function(query) {
+ return jQuery.map(query.split(''), function(l, i) {
+ return '\u0001$' + (i*2+1) + '\u0002$' + (i*2+2);
+ }).join('');
+ });
+ }
+
+ // function longMatchRegexp(index, longIndex, regexps) {
+ // for (var i = regexps.length - 1; i >= 0; i--){
+ // if (!index.match(regexps[i]) && !longIndex.match(regexps[i])) return false;
+ // };
+ // return true;
+ // }
+
+
+ /* ----- Mathchers ------ */
+
+ /*
+ * This record matches if the index starts with queries[0] and the record
+ * matches all of the regexps
+ */
+ function matchPassBeginning(index, longIndex, queries, regexps) {
+ if (index.indexOf(queries[0]) != 0) return false;
+ for (var i=1, l = regexps.length; i < l; i++) {
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
+ return false;
+ };
+ return true;
+ }
+
+ /*
+ * This record matches if the longIndex starts with queries[0] and the
+ * longIndex matches all of the regexps
+ */
+ function matchPassLongIndex(index, longIndex, queries, regexps) {
+ if (longIndex.indexOf(queries[0]) != 0) return false;
+ for (var i=1, l = regexps.length; i < l; i++) {
+ if (!longIndex.match(regexps[i]))
+ return false;
+ };
+ return true;
+ }
+
+ /*
+ * This record matches if the index contains queries[0] and the record
+ * matches all of the regexps
+ */
+ function matchPassContains(index, longIndex, queries, regexps) {
+ if (index.indexOf(queries[0]) == -1) return false;
+ for (var i=1, l = regexps.length; i < l; i++) {
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
+ return false;
+ };
+ return true;
+ }
+
+ /*
+ * This record matches if regexps[0] matches the index and the record
+ * matches all of the regexps
+ */
+ function matchPassRegexp(index, longIndex, queries, regexps) {
+ if (!index.match(regexps[0])) return false;
+ for (var i=1, l = regexps.length; i < l; i++) {
+ if (!index.match(regexps[i]) && !longIndex.match(regexps[i]))
+ return false;
+ };
+ return true;
+ }
+
+
+ /* ----- Highlighters ------ */
+ function highlightRegexp(info, queries, regexps, highlighters) {
+ var result = createResult(info);
+ for (var i=0, l = regexps.length; i < l; i++) {
+ result.title = result.title.replace(regexps[i], highlighters[i]);
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
+ };
+ return result;
+ }
+
+ function hltSubstring(string, pos, length) {
+ return string.substring(0, pos) + '\u0001' + string.substring(pos, pos + length) + '\u0002' + string.substring(pos + length);
+ }
+
+ function highlightQuery(info, queries, regexps, highlighters) {
+ var result = createResult(info);
+ var pos = 0;
+ var lcTitle = result.title.toLowerCase();
+
+ pos = lcTitle.indexOf(queries[0]);
+ if (pos != -1) {
+ result.title = hltSubstring(result.title, pos, queries[0].length);
+ }
+
+ result.namespace = result.namespace.replace(regexps[0], highlighters[0]);
+ for (var i=1, l = regexps.length; i < l; i++) {
+ result.title = result.title.replace(regexps[i], highlighters[i]);
+ result.namespace = result.namespace.replace(regexps[i], highlighters[i]);
+ };
+ return result;
+ }
+
+ function createResult(info) {
+ var result = {};
+ result.title = info[0];
+ result.namespace = info[1];
+ result.path = info[2];
+ result.params = info[3];
+ result.snippet = info[4];
+ return result;
+ }
+
+ /* ----- Searching ------ */
+ function performSearch(data, regexps, queries, highlighters, state) {
+ var searchIndex = data.searchIndex;
+ var longSearchIndex = data.longSearchIndex;
+ var info = data.info;
+ var result = [];
+ var i = state.from;
+ var l = searchIndex.length;
+ var togo = CHUNK_SIZE;
+ var matchFunc, hltFunc;
+
+ while (state.pass < 4 && state.limit > 0 && togo > 0) {
+ if (state.pass == 0) {
+ matchFunc = matchPassBeginning;
+ hltFunc = highlightQuery;
+ } else if (state.pass == 1) {
+ matchFunc = matchPassLongIndex;
+ hltFunc = highlightQuery;
+ } else if (state.pass == 2) {
+ matchFunc = matchPassContains;
+ hltFunc = highlightQuery;
+ } else if (state.pass == 3) {
+ matchFunc = matchPassRegexp;
+ hltFunc = highlightRegexp;
+ }
+
+ for (; togo > 0 && i < l && state.limit > 0; i++, togo--) {
+ if (info[i].n == state.n) continue;
+ if (matchFunc(searchIndex[i], longSearchIndex[i], queries, regexps)) {
+ info[i].n = state.n;
+ result.push(hltFunc(info[i], queries, regexps, highlighters));
+ state.limit--;
+ }
+ };
+ if (searchIndex.length <= i) {
+ state.pass++;
+ i = state.from = 0;
+ } else {
+ state.from = i;
+ }
+ }
+ return result;
+ }
+
+ function triggerResults(results, isLast) {
+ jQuery.each(this.handlers, function(i, fn) {
+ fn.call(this, results, isLast)
+ })
+ }
+}
+
diff --git a/lib/rdoc/ghost_method.rb b/lib/rdoc/ghost_method.rb
index 192b46f51f..7eb2d93167 100644
--- a/lib/rdoc/ghost_method.rb
+++ b/lib/rdoc/ghost_method.rb
@@ -1,5 +1,3 @@
-require 'rdoc/any_method'
-
##
# GhostMethod represents a method referenced only by a comment
diff --git a/lib/rdoc/include.rb b/lib/rdoc/include.rb
index 9cebd3d8ef..1e9ff5a464 100644
--- a/lib/rdoc/include.rb
+++ b/lib/rdoc/include.rb
@@ -1,5 +1,3 @@
-require 'rdoc/code_object'
-
##
# A Module include in a class with \#include
@@ -17,7 +15,7 @@ class RDoc::Include < RDoc::CodeObject
super()
@name = name
self.comment = comment
- @module = nil # cache for module if found
+ @module = nil # cache for module if found
end
##
@@ -30,10 +28,11 @@ class RDoc::Include < RDoc::CodeObject
end
def == other # :nodoc:
- self.class == other.class and
- self.name == other.name
+ self.class === other and @name == other.name
end
+ alias eql? ==
+
##
# Full name based on #module
@@ -42,6 +41,10 @@ class RDoc::Include < RDoc::CodeObject
RDoc::ClassModule === m ? m.full_name : @name
end
+ def hash # :nodoc:
+ [@name, self.module].hash
+ end
+
def inspect # :nodoc:
"#<%s:0x%x %s.include %s>" % [
self.class,
@@ -59,6 +62,13 @@ class RDoc::Include < RDoc::CodeObject
# - if not found, look into the children of included modules,
# in reverse inclusion order;
# - if still not found, go up the hierarchy of names.
+ #
+ # This method has <code>O(n!)</code> behavior when the module calling
+ # include is referencing nonexistent modules. Avoid calling #module until
+ # after all the files are parsed. This behavior is due to ruby's constant
+ # lookup behavior.
+ #
+ # As of the beginning of October, 2011, no gem includes nonexistent modules.
def module
return @module if @module
@@ -66,7 +76,7 @@ class RDoc::Include < RDoc::CodeObject
# search the current context
return @name unless parent
full_name = parent.child_name(@name)
- @module = RDoc::TopLevel.modules_hash[full_name]
+ @module = @store.modules_hash[full_name]
return @module if @module
return @name if @name =~ /^::/
@@ -76,22 +86,31 @@ class RDoc::Include < RDoc::CodeObject
inc = i.module
next if String === inc
full_name = inc.child_name(@name)
- @module = RDoc::TopLevel.modules_hash[full_name]
+ @module = @store.modules_hash[full_name]
return @module if @module
end
# go up the hierarchy of names
- p = parent.parent
- while p
- full_name = p.child_name(@name)
- @module = RDoc::TopLevel.modules_hash[full_name]
+ up = parent.parent
+ while up
+ full_name = up.child_name(@name)
+ @module = @store.modules_hash[full_name]
return @module if @module
- p = p.parent
+ up = up.parent
end
@name
end
+ ##
+ # Sets the store for this class or module and its contained code objects.
+
+ def store= store
+ super
+
+ @file = @store.add_file @file.full_name if @file
+ end
+
def to_s # :nodoc:
"include #@name in: #{parent}"
end
diff --git a/lib/rdoc/markdown.rb b/lib/rdoc/markdown.rb
new file mode 100644
index 0000000000..f1fa2cf17b
--- /dev/null
+++ b/lib/rdoc/markdown.rb
@@ -0,0 +1,16372 @@
+# coding: UTF-8
+# :markup: markdown
+
+##
+# RDoc::Markdown as described by the [markdown syntax][syntax].
+#
+# To choose Markdown as your only default format see
+# RDoc::Options@Saved+Options for instructions on setting up a `.doc_options`
+# file to store your project default.
+#
+# ## Extensions
+#
+# The following markdown extensions are supported by the parser, but not all
+# are used in RDoc output by default.
+#
+# ### RDoc
+#
+# The RDoc Markdown parser has the following built-in behaviors that cannot be
+# disabled.
+#
+# Underscores embedded in words are never interpreted as emphasis. (While the
+# [markdown dingus][dingus] emphasizes in-word underscores, neither the
+# Markdown syntax nor MarkdownTest mention this behavior.)
+#
+# For HTML output, RDoc always auto-links bare URLs.
+#
+# ### Break on Newline
+#
+# The break_on_newline extension converts all newlines into hard line breaks
+# as in [Github Flavored Markdown][GFM]. This extension is disabled by
+# default.
+#
+# ### CSS
+#
+# The #css extension enables CSS blocks to be included in the output, but they
+# are not used for any built-in RDoc output format. This extension is disabled
+# by default.
+#
+# Example:
+#
+# <style type="text/css">
+# h1 { font-size: 3em }
+# </style>
+#
+# ### Definition Lists
+#
+# The definition_lists extension allows definition lists using the [PHP
+# Markdown Extra syntax][PHPE], but only one label and definition are supported
+# at this time. This extension is enabled by default.
+#
+# Example:
+#
+# ```
+# cat
+# : A small furry mammal
+# that seems to sleep a lot
+#
+# ant
+# : A little insect that is known
+# to enjoy picnics
+#
+# ```
+#
+# Produces:
+#
+# cat
+# : A small furry mammal
+# that seems to sleep a lot
+#
+# ant
+# : A little insect that is known
+# to enjoy picnics
+#
+# ### Github
+#
+# The #github extension enables a partial set of [Github Flavored Markdown]
+# [GFM]. This extension is enabled by default.
+#
+# Supported github extensions include:
+#
+# #### Fenced code blocks
+#
+# Use ` ``` ` around a block of code instead of indenting it four spaces.
+#
+# #### Syntax highlighting
+#
+# Use ` ``` ruby ` as the start of a code fence to add syntax highlighting.
+# (Currently only `ruby` syntax is supported).
+#
+# ### HTML
+#
+# Enables raw HTML to be included in the output. This extension is enabled by
+# default.
+#
+# Example:
+#
+# <table>
+# ...
+# </table>
+#
+# ### Notes
+#
+# The #notes extension enables footnote support. This extension is enabled by
+# default.
+#
+# Example:
+#
+# Here is some text[^1] including an inline footnote ^[for short footnotes]
+#
+# ...
+#
+# [^1]: With the footnote text down at the bottom
+#
+# Produces:
+#
+# Here is some text[^1] including an inline footnote ^[for short footnotes]
+#
+# [^1]: With the footnote text down at the bottom
+#
+# ## Limitations
+#
+# * Link titles are not used
+# * Image links are not generated correctly
+# * Footnotes are collapsed into a single paragraph
+#
+# ## Author
+#
+# This markdown parser is a port to kpeg from [peg-markdown][pegmarkdown] by
+# John MacFarlane.
+#
+# It is used under the MIT license:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+#
+# The port to kpeg was performed by Eric Hodel and Evan Phoenix
+#
+# [dingus]: http://daringfireball.net/projects/markdown/dingus
+# [GFM]: http://github.github.com/github-flavored-markdown/
+# [pegmarkdown]: https://github.com/jgm/peg-markdown
+# [PHPE]: http://michelf.com/projects/php-markdown/extra/#def-list
+# [syntax]: http://daringfireball.net/projects/markdown/syntax
+#--
+# Last updated to jgm/peg-markdown commit 8f8fc22ef0
+class RDoc::Markdown
+ # :stopdoc:
+
+ # This is distinct from setup_parser so that a standalone parser
+ # can redefine #initialize and still have access to the proper
+ # parser setup code.
+ def initialize(str, debug=false)
+ setup_parser(str, debug)
+ end
+
+
+
+ # Prepares for parsing +str+. If you define a custom initialize you must
+ # call this method before #parse
+ def setup_parser(str, debug=false)
+ @string = str
+ @pos = 0
+ @memoizations = Hash.new { |h,k| h[k] = {} }
+ @result = nil
+ @failed_rule = nil
+ @failing_rule_offset = -1
+
+ setup_foreign_grammar
+ end
+
+ attr_reader :string
+ attr_reader :failing_rule_offset
+ attr_accessor :result, :pos
+
+
+ def current_column(target=pos)
+ if c = string.rindex("\n", target-1)
+ return target - c - 1
+ end
+
+ target + 1
+ end
+
+ def current_line(target=pos)
+ cur_offset = 0
+ cur_line = 0
+
+ string.each_line do |line|
+ cur_line += 1
+ cur_offset += line.size
+ return cur_line if cur_offset >= target
+ end
+
+ -1
+ end
+
+ def lines
+ lines = []
+ string.each_line { |l| lines << l }
+ lines
+ end
+
+
+
+ def get_text(start)
+ @string[start..@pos-1]
+ end
+
+ def show_pos
+ width = 10
+ if @pos < width
+ "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
+ else
+ "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
+ end
+ end
+
+ def failure_info
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+
+ if @failed_rule.kind_of? Symbol
+ info = self.class::Rules[@failed_rule]
+ "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
+ else
+ "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
+ end
+ end
+
+ def failure_caret
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+
+ line = lines[l-1]
+ "#{line}\n#{' ' * (c - 1)}^"
+ end
+
+ def failure_character
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+ lines[l-1][c-1, 1]
+ end
+
+ def failure_oneline
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+
+ char = lines[l-1][c-1, 1]
+
+ if @failed_rule.kind_of? Symbol
+ info = self.class::Rules[@failed_rule]
+ "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
+ else
+ "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
+ end
+ end
+
+ class ParseError < RuntimeError
+ end
+
+ def raise_error
+ raise ParseError, failure_oneline
+ end
+
+ def show_error(io=STDOUT)
+ error_pos = @failing_rule_offset
+ line_no = current_line(error_pos)
+ col_no = current_column(error_pos)
+
+ io.puts "On line #{line_no}, column #{col_no}:"
+
+ if @failed_rule.kind_of? Symbol
+ info = self.class::Rules[@failed_rule]
+ io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
+ else
+ io.puts "Failed to match rule '#{@failed_rule}'"
+ end
+
+ io.puts "Got: #{string[error_pos,1].inspect}"
+ line = lines[line_no-1]
+ io.puts "=> #{line}"
+ io.print(" " * (col_no + 3))
+ io.puts "^"
+ end
+
+ def set_failed_rule(name)
+ if @pos > @failing_rule_offset
+ @failed_rule = name
+ @failing_rule_offset = @pos
+ end
+ end
+
+ attr_reader :failed_rule
+
+ def match_string(str)
+ len = str.size
+ if @string[pos,len] == str
+ @pos += len
+ return str
+ end
+
+ return nil
+ end
+
+ def scan(reg)
+ if m = reg.match(@string[@pos..-1])
+ width = m.end(0)
+ @pos += width
+ return true
+ end
+
+ return nil
+ end
+
+ if "".respond_to? :getbyte
+ def get_byte
+ if @pos >= @string.size
+ return nil
+ end
+
+ s = @string.getbyte @pos
+ @pos += 1
+ s
+ end
+ else
+ def get_byte
+ if @pos >= @string.size
+ return nil
+ end
+
+ s = @string[@pos]
+ @pos += 1
+ s
+ end
+ end
+
+ def parse(rule=nil)
+ # We invoke the rules indirectly via apply
+ # instead of by just calling them as methods because
+ # if the rules use left recursion, apply needs to
+ # manage that.
+
+ if !rule
+ apply(:_root)
+ else
+ method = rule.gsub("-","_hyphen_")
+ apply :"_#{method}"
+ end
+ end
+
+ class MemoEntry
+ def initialize(ans, pos)
+ @ans = ans
+ @pos = pos
+ @result = nil
+ @set = false
+ @left_rec = false
+ end
+
+ attr_reader :ans, :pos, :result, :set
+ attr_accessor :left_rec
+
+ def move!(ans, pos, result)
+ @ans = ans
+ @pos = pos
+ @result = result
+ @set = true
+ @left_rec = false
+ end
+ end
+
+ def external_invoke(other, rule, *args)
+ old_pos = @pos
+ old_string = @string
+
+ @pos = other.pos
+ @string = other.string
+
+ begin
+ if val = __send__(rule, *args)
+ other.pos = @pos
+ other.result = @result
+ else
+ other.set_failed_rule "#{self.class}##{rule}"
+ end
+ val
+ ensure
+ @pos = old_pos
+ @string = old_string
+ end
+ end
+
+ def apply_with_args(rule, *args)
+ memo_key = [rule, args]
+ if m = @memoizations[memo_key][@pos]
+ @pos = m.pos
+ if !m.set
+ m.left_rec = true
+ return nil
+ end
+
+ @result = m.result
+
+ return m.ans
+ else
+ m = MemoEntry.new(nil, @pos)
+ @memoizations[memo_key][@pos] = m
+ start_pos = @pos
+
+ ans = __send__ rule, *args
+
+ lr = m.left_rec
+
+ m.move! ans, @pos, @result
+
+ # Don't bother trying to grow the left recursion
+ # if it's failing straight away (thus there is no seed)
+ if ans and lr
+ return grow_lr(rule, args, start_pos, m)
+ else
+ return ans
+ end
+
+ return ans
+ end
+ end
+
+ def apply(rule)
+ if m = @memoizations[rule][@pos]
+ @pos = m.pos
+ if !m.set
+ m.left_rec = true
+ return nil
+ end
+
+ @result = m.result
+
+ return m.ans
+ else
+ m = MemoEntry.new(nil, @pos)
+ @memoizations[rule][@pos] = m
+ start_pos = @pos
+
+ ans = __send__ rule
+
+ lr = m.left_rec
+
+ m.move! ans, @pos, @result
+
+ # Don't bother trying to grow the left recursion
+ # if it's failing straight away (thus there is no seed)
+ if ans and lr
+ return grow_lr(rule, nil, start_pos, m)
+ else
+ return ans
+ end
+
+ return ans
+ end
+ end
+
+ def grow_lr(rule, args, start_pos, m)
+ while true
+ @pos = start_pos
+ @result = m.result
+
+ if args
+ ans = __send__ rule, *args
+ else
+ ans = __send__ rule
+ end
+ return nil unless ans
+
+ break if @pos <= m.pos
+
+ m.move! ans, @pos, @result
+ end
+
+ @result = m.result
+ @pos = m.pos
+ return m.ans
+ end
+
+ class RuleInfo
+ def initialize(name, rendered)
+ @name = name
+ @rendered = rendered
+ end
+
+ attr_reader :name, :rendered
+ end
+
+ def self.rule_info(name, rendered)
+ RuleInfo.new(name, rendered)
+ end
+
+
+ # :startdoc:
+
+
+
+ require 'rubygems'
+ require 'rdoc'
+ require 'rdoc/markup/to_joined_paragraph'
+ require 'rdoc/markdown/entities'
+
+ if RUBY_VERSION > '1.9' then
+ require 'rdoc/markdown/literals_1_9'
+ else
+ require 'rdoc/markdown/literals_1_8'
+ end
+
+ ##
+ # Supported extensions
+
+ EXTENSIONS = []
+
+ ##
+ # Extensions enabled by default
+
+ DEFAULT_EXTENSIONS = [
+ :definition_lists,
+ :github,
+ :html,
+ :notes,
+ ]
+
+ # :section: Extensions
+
+ ##
+ # Creates extension methods for the `name` extension to enable and disable
+ # the extension and to query if they are active.
+
+ def self.extension name
+ EXTENSIONS << name
+
+ eval <<-RUBY
+ def #{name}?
+ extension? __method__
+ end
+
+ def #{name}= enable
+ extension __method__, enable
+ end
+ RUBY
+ end
+
+ ##
+ # Converts all newlines into hard breaks
+
+ extension :break_on_newline
+
+ ##
+ # Allow style blocks
+
+ extension :css
+
+ ##
+ # Allow PHP Markdown Extras style definition lists
+
+ extension :definition_lists
+
+ ##
+ # Allow Github Flavored Markdown
+
+ extension :github
+
+ ##
+ # Allow HTML
+
+ extension :html
+
+ ##
+ # Enables the notes extension
+
+ extension :notes
+
+ # :section:
+
+ ##
+ # Parses the `markdown` document into an RDoc::Document using the default
+ # extensions.
+
+ def self.parse markdown
+ parser = new
+
+ parser.parse markdown
+ end
+
+ # TODO remove when kpeg 0.10 is released
+ alias orig_initialize initialize # :nodoc:
+
+ ##
+ # Creates a new markdown parser that enables the given +extensions+.
+
+ def initialize extensions = DEFAULT_EXTENSIONS, debug = false
+ @debug = debug
+ @formatter = RDoc::Markup::ToJoinedParagraph.new
+ @extensions = extensions
+
+ @references = nil
+ @unlinked_references = nil
+
+ @footnotes = nil
+ @note_order = nil
+ end
+
+ ##
+ # Wraps `text` in emphasis for rdoc inline formatting
+
+ def emphasis text
+ if text =~ /\A[a-z\d.\/]+\z/i then
+ "_#{text}_"
+ else
+ "<em>#{text}</em>"
+ end
+ end
+
+ ##
+ # :category: Extensions
+ #
+ # Is the extension `name` enabled?
+
+ def extension? name
+ name = name.to_s.delete('?').intern
+
+ @extensions.include? name
+ end
+
+ ##
+ # :category: Extensions
+ #
+ # Enables or disables the extension with `name`
+
+ def extension name, enable
+ name = name.to_s.delete('=').intern
+
+ if enable then
+ @extensions |= [name]
+ else
+ @extensions -= [name]
+ end
+ end
+
+ ##
+ # Parses `text` in a clone of this parser. This is used for handling nested
+ # lists the same way as markdown_parser.
+
+ def inner_parse text # :nodoc:
+ parser = clone
+
+ parser.setup_parser text, @debug
+
+ parser.peg_parse
+
+ doc = parser.result
+
+ doc.accept @formatter
+
+ doc.parts
+ end
+
+ ##
+ # Finds a link reference for `label` and creates a new link to it with
+ # `content` as the link text. If `label` was not encountered in the
+ # reference-gathering parser pass the label and content are reconstructed
+ # with the linking `text` (usually whitespace).
+
+ def link_to content, label = content, text = nil
+ raise 'enable notes extension' if
+ content.start_with? '^' and label.equal? content
+
+ if ref = @references[label] then
+ "{#{content}}[#{ref}]"
+ elsif label.equal? content then
+ "[#{content}]#{text}"
+ else
+ "[#{content}]#{text}[#{label}]"
+ end
+ end
+
+ ##
+ # Creates an RDoc::Markup::ListItem by parsing the `unparsed` content from
+ # the first parsing pass.
+
+ def list_item_from unparsed
+ parsed = inner_parse unparsed.join
+ RDoc::Markup::ListItem.new nil, *parsed
+ end
+
+ ##
+ # Stores `label` as a note and fills in previously unknown note references.
+
+ def note label
+ #foottext = "rdoc-label:foottext-#{label}:footmark-#{label}"
+
+ #ref.replace foottext if ref = @unlinked_notes.delete(label)
+
+ @notes[label] = foottext
+
+ #"{^1}[rdoc-label:footmark-#{label}:foottext-#{label}] "
+ end
+
+ ##
+ # Creates a new link for the footnote `reference` and adds the reference to
+ # the note order list for proper display at the end of the document.
+
+ def note_for ref
+ @note_order << ref
+
+ label = @note_order.length
+
+ "{*#{label}}[rdoc-label:foottext-#{label}:footmark-#{label}]"
+ end
+
+ ##
+ # The internal kpeg parse method
+
+ alias peg_parse parse # :nodoc:
+
+ ##
+ # Creates an RDoc::Markup::Paragraph from `parts` and including
+ # extension-specific behavior
+
+ def paragraph parts
+ parts = parts.map do |part|
+ if "\n" == part then
+ RDoc::Markup::HardBreak.new
+ else
+ part
+ end
+ end if break_on_newline?
+
+ RDoc::Markup::Paragraph.new(*parts)
+ end
+
+ ##
+ # Parses `markdown` into an RDoc::Document
+
+ def parse markdown
+ @references = {}
+ @unlinked_references = {}
+
+ markdown += "\n\n"
+
+ setup_parser markdown, @debug
+ peg_parse 'References'
+
+ if notes? then
+ @footnotes = {}
+
+ setup_parser markdown, @debug
+ peg_parse 'Notes'
+
+ # using note_order on the first pass would be a bug
+ @note_order = []
+ end
+
+ setup_parser markdown, @debug
+ peg_parse
+
+ doc = result
+
+ if notes? and not @footnotes.empty? then
+ doc << RDoc::Markup::Rule.new(1)
+
+ @note_order.each_with_index do |ref, index|
+ label = index + 1
+ note = @footnotes[ref]
+
+ link = "{^#{label}}[rdoc-label:footmark-#{label}:foottext-#{label}] "
+ note.parts.unshift link
+
+ doc << note
+ end
+ end
+
+ doc.accept @formatter
+
+ doc
+ end
+
+ ##
+ # Stores `label` as a reference to `link` and fills in previously unknown
+ # link references.
+
+ def reference label, link
+ if ref = @unlinked_references.delete(label) then
+ ref.replace link
+ end
+
+ @references[label] = link
+ end
+
+ ##
+ # Wraps `text` in strong markup for rdoc inline formatting
+
+ def strong text
+ if text =~ /\A[a-z\d.\/-]+\z/i then
+ "*#{text}*"
+ else
+ "<b>#{text}</b>"
+ end
+ end
+
+
+ # :stopdoc:
+ def setup_foreign_grammar
+ @_grammar_literals = RDoc::Markdown::Literals.new(nil)
+ end
+
+ # root = Doc
+ def _root
+ _tmp = apply(:_Doc)
+ set_failed_rule :_root unless _tmp
+ return _tmp
+ end
+
+ # Doc = BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }
+ def _Doc
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_BOM)
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _ary = []
+ while true
+ _tmp = apply(:_Block)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::Document.new(*a.compact) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Doc unless _tmp
+ return _tmp
+ end
+
+ # Block = BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)
+ def _Block
+
+ _save = self.pos
+ while true # sequence
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_BlockQuote)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Verbatim)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_CodeFence)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Note)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Reference)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_HorizontalRule)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Heading)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_OrderedList)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_BulletList)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_DefinitionList)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_HtmlBlock)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_StyleBlock)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Para)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Plain)
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Block unless _tmp
+ return _tmp
+ end
+
+ # Para = NonindentSpace Inlines:a BlankLine+ { paragraph a }
+ def _Para
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inlines)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = apply(:_BlankLine)
+ if _tmp
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; paragraph a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Para unless _tmp
+ return _tmp
+ end
+
+ # Plain = Inlines:a { paragraph a }
+ def _Plain
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Inlines)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; paragraph a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Plain unless _tmp
+ return _tmp
+ end
+
+ # AtxInline = !Newline !(Sp? "#"* Sp Newline) Inline
+ def _AtxInline
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_Sp)
+ unless _tmp
+ _tmp = true
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ while true
+ _tmp = match_string("#")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inline)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_AtxInline unless _tmp
+ return _tmp
+ end
+
+ # AtxStart = < ("######" | "#####" | "####" | "###" | "##" | "#") > { text.length }
+ def _AtxStart
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("######")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("#####")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("####")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("###")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("##")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("#")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text.length ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_AtxStart unless _tmp
+ return _tmp
+ end
+
+ # AtxHeading = AtxStart:s Sp? AtxInline+:a (Sp? "#"* Sp)? Newline { RDoc::Markup::Heading.new(s, a.join) }
+ def _AtxHeading
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_AtxStart)
+ s = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = apply(:_Sp)
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _ary = []
+ _tmp = apply(:_AtxInline)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_AtxInline)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save2
+ end
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = apply(:_Sp)
+ unless _tmp
+ _tmp = true
+ self.pos = _save5
+ end
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ while true
+ _tmp = match_string("#")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ unless _tmp
+ _tmp = true
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::Heading.new(s, a.join) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_AtxHeading unless _tmp
+ return _tmp
+ end
+
+ # SetextHeading = (SetextHeading1 | SetextHeading2)
+ def _SetextHeading
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_SetextHeading1)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_SetextHeading2)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_SetextHeading unless _tmp
+ return _tmp
+ end
+
+ # SetextBottom1 = "===" "="* Newline
+ def _SetextBottom1
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("===")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = match_string("=")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_SetextBottom1 unless _tmp
+ return _tmp
+ end
+
+ # SetextBottom2 = "---" "-"* Newline
+ def _SetextBottom2
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("---")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = match_string("-")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_SetextBottom2 unless _tmp
+ return _tmp
+ end
+
+ # SetextHeading1 = &(RawLine SetextBottom1) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom1 { a; RDoc::Markup::Heading.new(1, a.join) }
+ def _SetextHeading1
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_RawLine)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_SetextBottom1)
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = apply(:_Endline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_Inline)
+ b = @result
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save6 = self.pos
+ while true # sequence
+ _save7 = self.pos
+ _tmp = apply(:_Endline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ _tmp = apply(:_Inline)
+ b = @result
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save6
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save8 = self.pos
+ _tmp = apply(:_Sp)
+ unless _tmp
+ _tmp = true
+ self.pos = _save8
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_SetextBottom1)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a; RDoc::Markup::Heading.new(1, a.join) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_SetextHeading1 unless _tmp
+ return _tmp
+ end
+
+ # SetextHeading2 = &(RawLine SetextBottom2) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) }
+ def _SetextHeading2
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_RawLine)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_SetextBottom2)
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = apply(:_Endline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_Inline)
+ b = @result
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save6 = self.pos
+ while true # sequence
+ _save7 = self.pos
+ _tmp = apply(:_Endline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ _tmp = apply(:_Inline)
+ b = @result
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save6
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save8 = self.pos
+ _tmp = apply(:_Sp)
+ unless _tmp
+ _tmp = true
+ self.pos = _save8
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_SetextBottom2)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::Heading.new(2, a.join) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_SetextHeading2 unless _tmp
+ return _tmp
+ end
+
+ # Heading = (SetextHeading | AtxHeading)
+ def _Heading
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_SetextHeading)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_AtxHeading)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Heading unless _tmp
+ return _tmp
+ end
+
+ # BlockQuote = BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) }
+ def _BlockQuote
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_BlockQuoteRaw)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::BlockQuote.new(*a) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_BlockQuote unless _tmp
+ return _tmp
+ end
+
+ # BlockQuoteRaw = StartList:a (">" " "? Line:l { a << l } (!">" !BlankLine Line:c { a << c })* (BlankLine:n { a << n })*)+ { inner_parse a.join }
+ def _BlockQuoteRaw
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _save3 = self.pos
+ _tmp = match_string(" ")
+ unless _tmp
+ _tmp = true
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Line)
+ l = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ while true
+
+ _save5 = self.pos
+ while true # sequence
+ _save6 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Line)
+ c = @result
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ @result = begin; a << c ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ while true
+
+ _save9 = self.pos
+ while true # sequence
+ _tmp = apply(:_BlankLine)
+ n = @result
+ unless _tmp
+ self.pos = _save9
+ break
+ end
+ @result = begin; a << n ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save9
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save10 = self.pos
+ while true # sequence
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ _save11 = self.pos
+ _tmp = match_string(" ")
+ unless _tmp
+ _tmp = true
+ self.pos = _save11
+ end
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ _tmp = apply(:_Line)
+ l = @result
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ while true
+
+ _save13 = self.pos
+ while true # sequence
+ _save14 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save14
+ unless _tmp
+ self.pos = _save13
+ break
+ end
+ _save15 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save15
+ unless _tmp
+ self.pos = _save13
+ break
+ end
+ _tmp = apply(:_Line)
+ c = @result
+ unless _tmp
+ self.pos = _save13
+ break
+ end
+ @result = begin; a << c ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save13
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ while true
+
+ _save17 = self.pos
+ while true # sequence
+ _tmp = apply(:_BlankLine)
+ n = @result
+ unless _tmp
+ self.pos = _save17
+ break
+ end
+ @result = begin; a << n ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save17
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save10
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; inner_parse a.join ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_BlockQuoteRaw unless _tmp
+ return _tmp
+ end
+
+ # NonblankIndentedLine = !BlankLine IndentedLine
+ def _NonblankIndentedLine
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_IndentedLine)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_NonblankIndentedLine unless _tmp
+ return _tmp
+ end
+
+ # VerbatimChunk = BlankLine*:a NonblankIndentedLine+:b { a.concat b }
+ def _VerbatimChunk
+
+ _save = self.pos
+ while true # sequence
+ _ary = []
+ while true
+ _tmp = apply(:_BlankLine)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _ary = []
+ _tmp = apply(:_NonblankIndentedLine)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_NonblankIndentedLine)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save2
+ end
+ b = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a.concat b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_VerbatimChunk unless _tmp
+ return _tmp
+ end
+
+ # Verbatim = VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) }
+ def _Verbatim
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _ary = []
+ _tmp = apply(:_VerbatimChunk)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_VerbatimChunk)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save1
+ end
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::Verbatim.new(*a.flatten) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Verbatim unless _tmp
+ return _tmp
+ end
+
+ # HorizontalRule = NonindentSpace ("*" Sp "*" Sp "*" (Sp "*")* | "-" Sp "-" Sp "-" (Sp "-")* | "_" Sp "_" Sp "_" (Sp "_")*) Sp Newline BlankLine+ { RDoc::Markup::Rule.new 1 }
+ def _HorizontalRule
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = match_string("*")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = match_string("*")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = match_string("*")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ while true
+
+ _save4 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = match_string("*")
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string("-")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = match_string("-")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = match_string("-")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ while true
+
+ _save7 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = match_string("-")
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save8 = self.pos
+ while true # sequence
+ _tmp = match_string("_")
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = match_string("_")
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = match_string("_")
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ while true
+
+ _save10 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ _tmp = match_string("_")
+ unless _tmp
+ self.pos = _save10
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save8
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save11 = self.pos
+ _tmp = apply(:_BlankLine)
+ if _tmp
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save11
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::Rule.new 1 ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HorizontalRule unless _tmp
+ return _tmp
+ end
+
+ # Bullet = !HorizontalRule NonindentSpace ("+" | "*" | "-") Spacechar+
+ def _Bullet
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_HorizontalRule)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = match_string("+")
+ break if _tmp
+ self.pos = _save2
+ _tmp = match_string("*")
+ break if _tmp
+ self.pos = _save2
+ _tmp = match_string("-")
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+ _tmp = apply(:_Spacechar)
+ if _tmp
+ while true
+ _tmp = apply(:_Spacechar)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Bullet unless _tmp
+ return _tmp
+ end
+
+ # BulletList = &Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) }
+ def _BulletList
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Bullet)
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_ListTight)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_ListLoose)
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::List.new(:BULLET, *a) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_BulletList unless _tmp
+ return _tmp
+ end
+
+ # ListTight = ListItemTight+:a BlankLine* !(Bullet | Enumerator) { a }
+ def _ListTight
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _ary = []
+ _tmp = apply(:_ListItemTight)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_ListItemTight)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save1
+ end
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # choice
+ _tmp = apply(:_Bullet)
+ break if _tmp
+ self.pos = _save4
+ _tmp = apply(:_Enumerator)
+ break if _tmp
+ self.pos = _save4
+ break
+ end # end choice
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListTight unless _tmp
+ return _tmp
+ end
+
+ # ListLoose = StartList:a (ListItem:b BlankLine* { a << b })+ { a }
+ def _ListLoose
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_ListItem)
+ b = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save4 = self.pos
+ while true # sequence
+ _tmp = apply(:_ListItem)
+ b = @result
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListLoose unless _tmp
+ return _tmp
+ end
+
+ # ListItem = (Bullet | Enumerator) StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a }
+ def _ListItem
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_Bullet)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_Enumerator)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_ListBlock)
+ b = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save3 = self.pos
+ while true # sequence
+ _tmp = apply(:_ListContinuationBlock)
+ c = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; a.push(*c) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; list_item_from a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListItem unless _tmp
+ return _tmp
+ end
+
+ # ListItemTight = (Bullet | Enumerator) ListBlock:a (!BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a }
+ def _ListItemTight
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_Bullet)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_Enumerator)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_ListBlock)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_ListContinuationBlock)
+ b = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; a.push(*b) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save5 = self.pos
+ _tmp = apply(:_ListContinuationBlock)
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; list_item_from a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListItemTight unless _tmp
+ return _tmp
+ end
+
+ # ListBlock = !BlankLine Line:a ListBlockLine*:c { [a, *c] }
+ def _ListBlock
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Line)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _ary = []
+ while true
+ _tmp = apply(:_ListBlockLine)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ c = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; [a, *c] ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListBlock unless _tmp
+ return _tmp
+ end
+
+ # ListContinuationBlock = StartList:a < BlankLine* > { a << "\n" } (Indent ListBlock:b { a.concat b })+ { a }
+ def _ListContinuationBlock
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << "\n" ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _tmp = apply(:_Indent)
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_ListBlock)
+ b = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; a.concat b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save4 = self.pos
+ while true # sequence
+ _tmp = apply(:_Indent)
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_ListBlock)
+ b = @result
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; a.concat b ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListContinuationBlock unless _tmp
+ return _tmp
+ end
+
+ # Enumerator = NonindentSpace [0-9]+ "." Spacechar+
+ def _Enumerator
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _save2 = self.pos
+ _tmp = get_byte
+ if _tmp
+ unless _tmp >= 48 and _tmp <= 57
+ self.pos = _save2
+ _tmp = nil
+ end
+ end
+ if _tmp
+ while true
+ _save3 = self.pos
+ _tmp = get_byte
+ if _tmp
+ unless _tmp >= 48 and _tmp <= 57
+ self.pos = _save3
+ _tmp = nil
+ end
+ end
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(".")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save4 = self.pos
+ _tmp = apply(:_Spacechar)
+ if _tmp
+ while true
+ _tmp = apply(:_Spacechar)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Enumerator unless _tmp
+ return _tmp
+ end
+
+ # OrderedList = &Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) }
+ def _OrderedList
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Enumerator)
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_ListTight)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_ListLoose)
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::List.new(:NUMBER, *a) ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_OrderedList unless _tmp
+ return _tmp
+ end
+
+ # ListBlockLine = !BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine
+ def _ListBlockLine
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_Indent)
+ unless _tmp
+ _tmp = true
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+
+ _save5 = self.pos
+ while true # choice
+ _tmp = apply(:_Bullet)
+ break if _tmp
+ self.pos = _save5
+ _tmp = apply(:_Enumerator)
+ break if _tmp
+ self.pos = _save5
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save6 = self.pos
+ _tmp = apply(:_HorizontalRule)
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_OptionallyIndentedLine)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ListBlockLine unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenAddress = "<" Spnl ("address" | "ADDRESS") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenAddress
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("address")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("ADDRESS")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenAddress unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseAddress = "<" Spnl "/" ("address" | "ADDRESS") Spnl ">"
+ def _HtmlBlockCloseAddress
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("address")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("ADDRESS")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseAddress unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockAddress = HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress
+ def _HtmlBlockAddress
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenAddress)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockAddress)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseAddress)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseAddress)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockAddress unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenBlockquote = "<" Spnl ("blockquote" | "BLOCKQUOTE") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenBlockquote
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("blockquote")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("BLOCKQUOTE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenBlockquote unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseBlockquote = "<" Spnl "/" ("blockquote" | "BLOCKQUOTE") Spnl ">"
+ def _HtmlBlockCloseBlockquote
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("blockquote")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("BLOCKQUOTE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseBlockquote unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockBlockquote = HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote
+ def _HtmlBlockBlockquote
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenBlockquote)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockBlockquote)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseBlockquote)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseBlockquote)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockBlockquote unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenCenter = "<" Spnl ("center" | "CENTER") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenCenter
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("center")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("CENTER")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenCenter unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseCenter = "<" Spnl "/" ("center" | "CENTER") Spnl ">"
+ def _HtmlBlockCloseCenter
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("center")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("CENTER")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseCenter unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCenter = HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter
+ def _HtmlBlockCenter
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenCenter)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockCenter)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseCenter)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseCenter)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCenter unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenDir = "<" Spnl ("dir" | "DIR") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenDir
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dir")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DIR")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenDir unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseDir = "<" Spnl "/" ("dir" | "DIR") Spnl ">"
+ def _HtmlBlockCloseDir
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dir")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DIR")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseDir unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockDir = HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir
+ def _HtmlBlockDir
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenDir)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockDir)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseDir)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseDir)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockDir unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenDiv = "<" Spnl ("div" | "DIV") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenDiv
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("div")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DIV")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenDiv unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseDiv = "<" Spnl "/" ("div" | "DIV") Spnl ">"
+ def _HtmlBlockCloseDiv
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("div")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DIV")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseDiv unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockDiv = HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv
+ def _HtmlBlockDiv
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenDiv)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockDiv)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseDiv)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseDiv)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockDiv unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenDl = "<" Spnl ("dl" | "DL") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenDl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dl")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DL")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenDl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseDl = "<" Spnl "/" ("dl" | "DL") Spnl ">"
+ def _HtmlBlockCloseDl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dl")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DL")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseDl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockDl = HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl
+ def _HtmlBlockDl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenDl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockDl)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseDl)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseDl)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockDl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenFieldset = "<" Spnl ("fieldset" | "FIELDSET") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenFieldset
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("fieldset")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("FIELDSET")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenFieldset unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseFieldset = "<" Spnl "/" ("fieldset" | "FIELDSET") Spnl ">"
+ def _HtmlBlockCloseFieldset
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("fieldset")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("FIELDSET")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseFieldset unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockFieldset = HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset
+ def _HtmlBlockFieldset
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenFieldset)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockFieldset)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseFieldset)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseFieldset)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockFieldset unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenForm = "<" Spnl ("form" | "FORM") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenForm
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("form")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("FORM")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenForm unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseForm = "<" Spnl "/" ("form" | "FORM") Spnl ">"
+ def _HtmlBlockCloseForm
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("form")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("FORM")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseForm unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockForm = HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm
+ def _HtmlBlockForm
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenForm)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockForm)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseForm)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseForm)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockForm unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenH1 = "<" Spnl ("h1" | "H1") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenH1
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h1")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H1")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenH1 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseH1 = "<" Spnl "/" ("h1" | "H1") Spnl ">"
+ def _HtmlBlockCloseH1
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h1")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H1")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseH1 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockH1 = HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1
+ def _HtmlBlockH1
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenH1)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockH1)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseH1)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseH1)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockH1 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenH2 = "<" Spnl ("h2" | "H2") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenH2
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h2")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H2")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenH2 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseH2 = "<" Spnl "/" ("h2" | "H2") Spnl ">"
+ def _HtmlBlockCloseH2
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h2")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H2")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseH2 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockH2 = HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2
+ def _HtmlBlockH2
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenH2)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockH2)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseH2)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseH2)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockH2 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenH3 = "<" Spnl ("h3" | "H3") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenH3
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h3")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H3")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenH3 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseH3 = "<" Spnl "/" ("h3" | "H3") Spnl ">"
+ def _HtmlBlockCloseH3
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h3")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H3")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseH3 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockH3 = HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3
+ def _HtmlBlockH3
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenH3)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockH3)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseH3)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseH3)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockH3 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenH4 = "<" Spnl ("h4" | "H4") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenH4
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h4")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H4")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenH4 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseH4 = "<" Spnl "/" ("h4" | "H4") Spnl ">"
+ def _HtmlBlockCloseH4
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h4")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H4")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseH4 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockH4 = HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4
+ def _HtmlBlockH4
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenH4)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockH4)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseH4)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseH4)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockH4 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenH5 = "<" Spnl ("h5" | "H5") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenH5
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h5")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H5")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenH5 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseH5 = "<" Spnl "/" ("h5" | "H5") Spnl ">"
+ def _HtmlBlockCloseH5
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h5")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H5")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseH5 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockH5 = HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5
+ def _HtmlBlockH5
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenH5)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockH5)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseH5)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseH5)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockH5 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenH6 = "<" Spnl ("h6" | "H6") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenH6
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h6")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H6")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenH6 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseH6 = "<" Spnl "/" ("h6" | "H6") Spnl ">"
+ def _HtmlBlockCloseH6
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("h6")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("H6")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseH6 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockH6 = HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6
+ def _HtmlBlockH6
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenH6)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockH6)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseH6)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseH6)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockH6 unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenMenu = "<" Spnl ("menu" | "MENU") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenMenu
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("menu")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("MENU")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenMenu unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseMenu = "<" Spnl "/" ("menu" | "MENU") Spnl ">"
+ def _HtmlBlockCloseMenu
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("menu")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("MENU")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseMenu unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockMenu = HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu
+ def _HtmlBlockMenu
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenMenu)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockMenu)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseMenu)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseMenu)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockMenu unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenNoframes = "<" Spnl ("noframes" | "NOFRAMES") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenNoframes
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("noframes")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("NOFRAMES")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenNoframes unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseNoframes = "<" Spnl "/" ("noframes" | "NOFRAMES") Spnl ">"
+ def _HtmlBlockCloseNoframes
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("noframes")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("NOFRAMES")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseNoframes unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockNoframes = HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes
+ def _HtmlBlockNoframes
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenNoframes)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockNoframes)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseNoframes)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseNoframes)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockNoframes unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenNoscript = "<" Spnl ("noscript" | "NOSCRIPT") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenNoscript
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("noscript")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("NOSCRIPT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenNoscript unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseNoscript = "<" Spnl "/" ("noscript" | "NOSCRIPT") Spnl ">"
+ def _HtmlBlockCloseNoscript
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("noscript")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("NOSCRIPT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseNoscript unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockNoscript = HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript
+ def _HtmlBlockNoscript
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenNoscript)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockNoscript)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseNoscript)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseNoscript)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockNoscript unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenOl = "<" Spnl ("ol" | "OL") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenOl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("ol")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("OL")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenOl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseOl = "<" Spnl "/" ("ol" | "OL") Spnl ">"
+ def _HtmlBlockCloseOl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("ol")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("OL")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseOl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOl = HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl
+ def _HtmlBlockOl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenOl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockOl)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseOl)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseOl)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenP = "<" Spnl ("p" | "P") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenP
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("p")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("P")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenP unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseP = "<" Spnl "/" ("p" | "P") Spnl ">"
+ def _HtmlBlockCloseP
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("p")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("P")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseP unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockP = HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP
+ def _HtmlBlockP
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenP)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockP)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseP)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseP)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockP unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenPre = "<" Spnl ("pre" | "PRE") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenPre
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("pre")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("PRE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenPre unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockClosePre = "<" Spnl "/" ("pre" | "PRE") Spnl ">"
+ def _HtmlBlockClosePre
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("pre")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("PRE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockClosePre unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockPre = HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre
+ def _HtmlBlockPre
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenPre)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockPre)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockClosePre)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockClosePre)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockPre unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenTable = "<" Spnl ("table" | "TABLE") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenTable
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("table")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TABLE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenTable unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseTable = "<" Spnl "/" ("table" | "TABLE") Spnl ">"
+ def _HtmlBlockCloseTable
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("table")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TABLE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseTable unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockTable = HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable
+ def _HtmlBlockTable
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenTable)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockTable)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseTable)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseTable)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockTable unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenUl = "<" Spnl ("ul" | "UL") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenUl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("ul")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("UL")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenUl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseUl = "<" Spnl "/" ("ul" | "UL") Spnl ">"
+ def _HtmlBlockCloseUl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("ul")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("UL")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseUl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockUl = HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl
+ def _HtmlBlockUl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenUl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockUl)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseUl)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseUl)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockUl unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenDd = "<" Spnl ("dd" | "DD") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenDd
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dd")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DD")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenDd unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseDd = "<" Spnl "/" ("dd" | "DD") Spnl ">"
+ def _HtmlBlockCloseDd
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dd")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DD")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseDd unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockDd = HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd
+ def _HtmlBlockDd
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenDd)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockDd)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseDd)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseDd)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockDd unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenDt = "<" Spnl ("dt" | "DT") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenDt
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dt")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenDt unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseDt = "<" Spnl "/" ("dt" | "DT") Spnl ">"
+ def _HtmlBlockCloseDt
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("dt")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("DT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseDt unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockDt = HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt
+ def _HtmlBlockDt
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenDt)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockDt)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseDt)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseDt)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockDt unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenFrameset = "<" Spnl ("frameset" | "FRAMESET") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenFrameset
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("frameset")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("FRAMESET")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenFrameset unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseFrameset = "<" Spnl "/" ("frameset" | "FRAMESET") Spnl ">"
+ def _HtmlBlockCloseFrameset
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("frameset")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("FRAMESET")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseFrameset unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockFrameset = HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset
+ def _HtmlBlockFrameset
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenFrameset)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockFrameset)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseFrameset)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseFrameset)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockFrameset unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenLi = "<" Spnl ("li" | "LI") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenLi
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("li")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("LI")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenLi unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseLi = "<" Spnl "/" ("li" | "LI") Spnl ">"
+ def _HtmlBlockCloseLi
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("li")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("LI")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseLi unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockLi = HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi
+ def _HtmlBlockLi
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenLi)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockLi)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseLi)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseLi)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockLi unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenTbody = "<" Spnl ("tbody" | "TBODY") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenTbody
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("tbody")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TBODY")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenTbody unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseTbody = "<" Spnl "/" ("tbody" | "TBODY") Spnl ">"
+ def _HtmlBlockCloseTbody
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("tbody")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TBODY")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseTbody unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockTbody = HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody
+ def _HtmlBlockTbody
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenTbody)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockTbody)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseTbody)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseTbody)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockTbody unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenTd = "<" Spnl ("td" | "TD") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenTd
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("td")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TD")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenTd unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseTd = "<" Spnl "/" ("td" | "TD") Spnl ">"
+ def _HtmlBlockCloseTd
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("td")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TD")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseTd unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockTd = HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd
+ def _HtmlBlockTd
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenTd)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockTd)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseTd)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseTd)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockTd unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenTfoot = "<" Spnl ("tfoot" | "TFOOT") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenTfoot
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("tfoot")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TFOOT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenTfoot unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseTfoot = "<" Spnl "/" ("tfoot" | "TFOOT") Spnl ">"
+ def _HtmlBlockCloseTfoot
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("tfoot")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TFOOT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseTfoot unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockTfoot = HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot
+ def _HtmlBlockTfoot
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenTfoot)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockTfoot)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseTfoot)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseTfoot)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockTfoot unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenTh = "<" Spnl ("th" | "TH") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenTh
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("th")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TH")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenTh unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseTh = "<" Spnl "/" ("th" | "TH") Spnl ">"
+ def _HtmlBlockCloseTh
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("th")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TH")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseTh unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockTh = HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh
+ def _HtmlBlockTh
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenTh)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockTh)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseTh)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseTh)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockTh unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenThead = "<" Spnl ("thead" | "THEAD") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenThead
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("thead")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("THEAD")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenThead unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseThead = "<" Spnl "/" ("thead" | "THEAD") Spnl ">"
+ def _HtmlBlockCloseThead
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("thead")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("THEAD")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseThead unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockThead = HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead
+ def _HtmlBlockThead
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenThead)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockThead)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseThead)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseThead)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockThead unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenTr = "<" Spnl ("tr" | "TR") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenTr
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("tr")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TR")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenTr unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseTr = "<" Spnl "/" ("tr" | "TR") Spnl ">"
+ def _HtmlBlockCloseTr
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("tr")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("TR")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseTr unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockTr = HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr
+ def _HtmlBlockTr
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenTr)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockTr)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_HtmlBlockCloseTr)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseTr)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockTr unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockOpenScript = "<" Spnl ("script" | "SCRIPT") Spnl HtmlAttribute* ">"
+ def _HtmlBlockOpenScript
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("script")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("SCRIPT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockOpenScript unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockCloseScript = "<" Spnl "/" ("script" | "SCRIPT") Spnl ">"
+ def _HtmlBlockCloseScript
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("script")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("SCRIPT")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockCloseScript unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockScript = HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript
+ def _HtmlBlockScript
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_HtmlBlockOpenScript)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_HtmlBlockCloseScript)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockCloseScript)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockScript unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockInTags = (HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript)
+ def _HtmlBlockInTags
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockAddress)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockBlockquote)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockCenter)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockDir)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockDiv)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockDl)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockFieldset)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockForm)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockH1)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockH2)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockH3)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockH4)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockH5)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockH6)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockMenu)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockNoframes)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockNoscript)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockOl)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockP)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockPre)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockTable)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockUl)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockDd)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockDt)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockFrameset)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockLi)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockTbody)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockTd)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockTfoot)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockTh)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockThead)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockTr)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_HtmlBlockScript)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_HtmlBlockInTags unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlock = < (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > BlankLine+ { if html? then RDoc::Markup::Raw.new text end }
+ def _HtmlBlock
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlockInTags)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_HtmlComment)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_HtmlBlockSelfClosing)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_HtmlUnclosed)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_BlankLine)
+ if _tmp
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; if html? then
+ RDoc::Markup::Raw.new text
+ end ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlock unless _tmp
+ return _tmp
+ end
+
+ # HtmlUnclosed = "<" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl ">"
+ def _HtmlUnclosed
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlUnclosedType)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlUnclosed unless _tmp
+ return _tmp
+ end
+
+ # HtmlUnclosedType = ("HR" | "hr")
+ def _HtmlUnclosedType
+
+ _save = self.pos
+ while true # choice
+ _tmp = match_string("HR")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("hr")
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_HtmlUnclosedType unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockSelfClosing = "<" Spnl HtmlBlockType Spnl HtmlAttribute* "/" Spnl ">"
+ def _HtmlBlockSelfClosing
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_HtmlBlockType)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlBlockSelfClosing unless _tmp
+ return _tmp
+ end
+
+ # HtmlBlockType = ("ADDRESS" | "BLOCKQUOTE" | "CENTER" | "DD" | "DIR" | "DIV" | "DL" | "DT" | "FIELDSET" | "FORM" | "FRAMESET" | "H1" | "H2" | "H3" | "H4" | "H5" | "H6" | "HR" | "ISINDEX" | "LI" | "MENU" | "NOFRAMES" | "NOSCRIPT" | "OL" | "P" | "PRE" | "SCRIPT" | "TABLE" | "TBODY" | "TD" | "TFOOT" | "TH" | "THEAD" | "TR" | "UL" | "address" | "blockquote" | "center" | "dd" | "dir" | "div" | "dl" | "dt" | "fieldset" | "form" | "frameset" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "hr" | "isindex" | "li" | "menu" | "noframes" | "noscript" | "ol" | "p" | "pre" | "script" | "table" | "tbody" | "td" | "tfoot" | "th" | "thead" | "tr" | "ul")
+ def _HtmlBlockType
+
+ _save = self.pos
+ while true # choice
+ _tmp = match_string("ADDRESS")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("BLOCKQUOTE")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("CENTER")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("DD")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("DIR")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("DIV")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("DL")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("DT")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("FIELDSET")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("FORM")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("FRAMESET")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("H1")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("H2")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("H3")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("H4")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("H5")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("H6")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("HR")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("ISINDEX")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("LI")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("MENU")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("NOFRAMES")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("NOSCRIPT")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("OL")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("P")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("PRE")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("SCRIPT")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("TABLE")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("TBODY")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("TD")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("TFOOT")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("TH")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("THEAD")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("TR")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("UL")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("address")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("blockquote")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("center")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("dd")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("dir")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("div")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("dl")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("dt")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("fieldset")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("form")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("frameset")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("h1")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("h2")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("h3")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("h4")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("h5")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("h6")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("hr")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("isindex")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("li")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("menu")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("noframes")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("noscript")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("ol")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("p")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("pre")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("script")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("table")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("tbody")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("td")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("tfoot")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("th")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("thead")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("tr")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("ul")
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_HtmlBlockType unless _tmp
+ return _tmp
+ end
+
+ # StyleOpen = "<" Spnl ("style" | "STYLE") Spnl HtmlAttribute* ">"
+ def _StyleOpen
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("style")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("STYLE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StyleOpen unless _tmp
+ return _tmp
+ end
+
+ # StyleClose = "<" Spnl "/" ("style" | "STYLE") Spnl ">"
+ def _StyleClose
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("/")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = match_string("style")
+ break if _tmp
+ self.pos = _save1
+ _tmp = match_string("STYLE")
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StyleClose unless _tmp
+ return _tmp
+ end
+
+ # InStyleTags = StyleOpen (!StyleClose .)* StyleClose
+ def _InStyleTags
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StyleOpen)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_StyleClose)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StyleClose)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_InStyleTags unless _tmp
+ return _tmp
+ end
+
+ # StyleBlock = < InStyleTags > BlankLine* { if css? then RDoc::Markup::Raw.new text end }
+ def _StyleBlock
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _tmp = apply(:_InStyleTags)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; if css? then
+ RDoc::Markup::Raw.new text
+ end ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StyleBlock unless _tmp
+ return _tmp
+ end
+
+ # Inlines = (!Endline Inline:i { i } | Endline:c &Inline { c })+:chunks Endline? { chunks }
+ def _Inlines
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _ary = []
+
+ _save2 = self.pos
+ while true # choice
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_Endline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_Inline)
+ i = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; i ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = apply(:_Endline)
+ c = @result
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save6 = self.pos
+ _tmp = apply(:_Inline)
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ @result = begin; c ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ if _tmp
+ _ary << @result
+ while true
+
+ _save7 = self.pos
+ while true # choice
+
+ _save8 = self.pos
+ while true # sequence
+ _save9 = self.pos
+ _tmp = apply(:_Endline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_Inline)
+ i = @result
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ @result = begin; i ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save8
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save7
+
+ _save10 = self.pos
+ while true # sequence
+ _tmp = apply(:_Endline)
+ c = @result
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ _save11 = self.pos
+ _tmp = apply(:_Inline)
+ self.pos = _save11
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ @result = begin; c ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save10
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save7
+ break
+ end # end choice
+
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save1
+ end
+ chunks = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save12 = self.pos
+ _tmp = apply(:_Endline)
+ unless _tmp
+ _tmp = true
+ self.pos = _save12
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; chunks ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Inlines unless _tmp
+ return _tmp
+ end
+
+ # Inline = (Str | Endline | UlOrStarLine | Space | Strong | Emph | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)
+ def _Inline
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_Str)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Endline)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_UlOrStarLine)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Space)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Strong)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Emph)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Image)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Link)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_NoteReference)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_InlineNote)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Code)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_RawHtml)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Entity)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_EscapedChar)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_Symbol)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Inline unless _tmp
+ return _tmp
+ end
+
+ # Space = Spacechar+ { " " }
+ def _Space
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Spacechar)
+ if _tmp
+ while true
+ _tmp = apply(:_Spacechar)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; " " ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Space unless _tmp
+ return _tmp
+ end
+
+ # Str = StartList:a < NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }
+ def _Str
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _save1 = self.pos
+ _tmp = apply(:_NormalChar)
+ if _tmp
+ while true
+ _tmp = apply(:_NormalChar)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a = text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save3 = self.pos
+ while true # sequence
+ _tmp = apply(:_StrChunk)
+ c = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; a << c ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Str unless _tmp
+ return _tmp
+ end
+
+ # StrChunk = < (NormalChar | "_"+ &Alphanumeric)+ > { text }
+ def _StrChunk
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_NormalChar)
+ break if _tmp
+ self.pos = _save2
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = match_string("_")
+ if _tmp
+ while true
+ _tmp = match_string("_")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _save5 = self.pos
+ _tmp = apply(:_Alphanumeric)
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save6 = self.pos
+ while true # choice
+ _tmp = apply(:_NormalChar)
+ break if _tmp
+ self.pos = _save6
+
+ _save7 = self.pos
+ while true # sequence
+ _save8 = self.pos
+ _tmp = match_string("_")
+ if _tmp
+ while true
+ _tmp = match_string("_")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save8
+ end
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _save9 = self.pos
+ _tmp = apply(:_Alphanumeric)
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save6
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StrChunk unless _tmp
+ return _tmp
+ end
+
+ # EscapedChar = "\\" !Newline < /[:\\`|*_{}\[\]()#+.!><-]/ > { text }
+ def _EscapedChar
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("\\")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _tmp = scan(/\A(?-mix:[:\\`|*_{}\[\]()#+.!><-])/)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_EscapedChar unless _tmp
+ return _tmp
+ end
+
+ # Entity = (HexEntity | DecEntity | CharEntity):a { a }
+ def _Entity
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_HexEntity)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_DecEntity)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_CharEntity)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Entity unless _tmp
+ return _tmp
+ end
+
+ # Endline = (LineBreak | TerminalEndline | NormalEndline)
+ def _Endline
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_LineBreak)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_TerminalEndline)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_NormalEndline)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Endline unless _tmp
+ return _tmp
+ end
+
+ # NormalEndline = Sp Newline !BlankLine !">" !AtxStart !(Line ("===" "="* | "---" "-"*) Newline) { "\n" }
+ def _NormalEndline
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+ _tmp = apply(:_AtxStart)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save4 = self.pos
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = apply(:_Line)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+
+ _save6 = self.pos
+ while true # choice
+
+ _save7 = self.pos
+ while true # sequence
+ _tmp = match_string("===")
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ while true
+ _tmp = match_string("=")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save6
+
+ _save9 = self.pos
+ while true # sequence
+ _tmp = match_string("---")
+ unless _tmp
+ self.pos = _save9
+ break
+ end
+ while true
+ _tmp = match_string("-")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save9
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save6
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; "\n" ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_NormalEndline unless _tmp
+ return _tmp
+ end
+
+ # TerminalEndline = Sp Newline Eof
+ def _TerminalEndline
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Eof)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TerminalEndline unless _tmp
+ return _tmp
+ end
+
+ # LineBreak = < " " NormalEndline > { RDoc::Markup::HardBreak.new }
+ def _LineBreak
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save1 = self.pos
+ while true # sequence
+ _tmp = match_string(" ")
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ _tmp = apply(:_NormalEndline)
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::HardBreak.new ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_LineBreak unless _tmp
+ return _tmp
+ end
+
+ # Symbol = < SpecialChar > { text }
+ def _Symbol
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _tmp = apply(:_SpecialChar)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Symbol unless _tmp
+ return _tmp
+ end
+
+ # UlOrStarLine = (UlLine | StarLine):a { a }
+ def _UlOrStarLine
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_UlLine)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_StarLine)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_UlOrStarLine unless _tmp
+ return _tmp
+ end
+
+ # StarLine = (< "****" "*"* > { text } | < Spacechar "*"+ &Spacechar > { text })
+ def _StarLine
+
+ _save = self.pos
+ while true # choice
+
+ _save1 = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = match_string("****")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ while true
+ _tmp = match_string("*")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+
+ _save4 = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = apply(:_Spacechar)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save6 = self.pos
+ _tmp = match_string("*")
+ if _tmp
+ while true
+ _tmp = match_string("*")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save6
+ end
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = apply(:_Spacechar)
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_StarLine unless _tmp
+ return _tmp
+ end
+
+ # UlLine = (< "____" "_"* > { text } | < Spacechar "_"+ &Spacechar > { text })
+ def _UlLine
+
+ _save = self.pos
+ while true # choice
+
+ _save1 = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = match_string("____")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ while true
+ _tmp = match_string("_")
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+
+ _save4 = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = apply(:_Spacechar)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save6 = self.pos
+ _tmp = match_string("_")
+ if _tmp
+ while true
+ _tmp = match_string("_")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save6
+ end
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = apply(:_Spacechar)
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_UlLine unless _tmp
+ return _tmp
+ end
+
+ # Emph = (EmphStar | EmphUl)
+ def _Emph
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_EmphStar)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_EmphUl)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Emph unless _tmp
+ return _tmp
+ end
+
+ # OneStarOpen = !StarLine "*" !Spacechar !Newline
+ def _OneStarOpen
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_StarLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("*")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_OneStarOpen unless _tmp
+ return _tmp
+ end
+
+ # OneStarClose = !Spacechar !Newline Inline:a "*" { a }
+ def _OneStarClose
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inline)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("*")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_OneStarClose unless _tmp
+ return _tmp
+ end
+
+ # EmphStar = OneStarOpen StartList:a (!OneStarClose Inline:l { a << l })* OneStarClose:l { a << l } { emphasis a.join }
+ def _EmphStar
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_OneStarOpen)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_OneStarClose)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Inline)
+ l = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_OneStarClose)
+ l = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; emphasis a.join ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_EmphStar unless _tmp
+ return _tmp
+ end
+
+ # OneUlOpen = !UlLine "_" !Spacechar !Newline
+ def _OneUlOpen
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_UlLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("_")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_OneUlOpen unless _tmp
+ return _tmp
+ end
+
+ # OneUlClose = !Spacechar !Newline Inline:a "_" { a }
+ def _OneUlClose
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inline)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("_")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_OneUlClose unless _tmp
+ return _tmp
+ end
+
+ # EmphUl = OneUlOpen StartList:a (!OneUlClose Inline:l { a << l })* OneUlClose:l { a << l } { emphasis a.join }
+ def _EmphUl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_OneUlOpen)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_OneUlClose)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Inline)
+ l = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_OneUlClose)
+ l = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; emphasis a.join ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_EmphUl unless _tmp
+ return _tmp
+ end
+
+ # Strong = (StrongStar | StrongUl)
+ def _Strong
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_StrongStar)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_StrongUl)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Strong unless _tmp
+ return _tmp
+ end
+
+ # TwoStarOpen = !StarLine "**" !Spacechar !Newline
+ def _TwoStarOpen
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_StarLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("**")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TwoStarOpen unless _tmp
+ return _tmp
+ end
+
+ # TwoStarClose = !Spacechar !Newline Inline:a "**" { a }
+ def _TwoStarClose
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inline)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("**")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TwoStarClose unless _tmp
+ return _tmp
+ end
+
+ # StrongStar = TwoStarOpen StartList:a (!TwoStarClose Inline:l { a << l })* TwoStarClose:l { a << l } { strong a.join }
+ def _StrongStar
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_TwoStarOpen)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_TwoStarClose)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Inline)
+ l = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_TwoStarClose)
+ l = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; strong a.join ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StrongStar unless _tmp
+ return _tmp
+ end
+
+ # TwoUlOpen = !UlLine "__" !Spacechar !Newline
+ def _TwoUlOpen
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_UlLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("__")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save3 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TwoUlOpen unless _tmp
+ return _tmp
+ end
+
+ # TwoUlClose = !Spacechar !Newline Inline:a "__" { a }
+ def _TwoUlClose
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inline)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("__")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TwoUlClose unless _tmp
+ return _tmp
+ end
+
+ # StrongUl = TwoUlOpen StartList:a (!TwoUlClose Inline:i { a << i })* TwoUlClose:l { a << l } { strong a.join }
+ def _StrongUl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_TwoUlOpen)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_TwoUlClose)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Inline)
+ i = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << i ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_TwoUlClose)
+ l = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; strong a.join ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StrongUl unless _tmp
+ return _tmp
+ end
+
+ # Image = "!" (ExplicitLink | ReferenceLink):a { a }
+ def _Image
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("!")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_ExplicitLink)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_ReferenceLink)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Image unless _tmp
+ return _tmp
+ end
+
+ # Link = (ExplicitLink | ReferenceLink | AutoLink)
+ def _Link
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_ExplicitLink)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_ReferenceLink)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_AutoLink)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Link unless _tmp
+ return _tmp
+ end
+
+ # ReferenceLink = (ReferenceLinkDouble | ReferenceLinkSingle)
+ def _ReferenceLink
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_ReferenceLinkDouble)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_ReferenceLinkSingle)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_ReferenceLink unless _tmp
+ return _tmp
+ end
+
+ # ReferenceLinkDouble = Label:content < Spnl > !"[]" Label:label { link_to content, label, text }
+ def _ReferenceLinkDouble
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Label)
+ content = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _tmp = apply(:_Spnl)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("[]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Label)
+ label = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; link_to content, label, text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ReferenceLinkDouble unless _tmp
+ return _tmp
+ end
+
+ # ReferenceLinkSingle = Label:content < (Spnl "[]")? > { link_to content, content, text }
+ def _ReferenceLinkSingle
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Label)
+ content = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = match_string("[]")
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; link_to content, content, text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ReferenceLinkSingle unless _tmp
+ return _tmp
+ end
+
+ # ExplicitLink = Label:l Spnl "(" Sp Source:s Spnl Title:t Sp ")" { "{#{l}}[#{s}]" }
+ def _ExplicitLink
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Label)
+ l = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("(")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Source)
+ s = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Title)
+ t = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(")")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; "{#{l}}[#{s}]" ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ExplicitLink unless _tmp
+ return _tmp
+ end
+
+ # Source = ("<" < SourceContents > ">" | < SourceContents >) { text }
+ def _Source
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _text_start = self.pos
+ _tmp = apply(:_SourceContents)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+ _text_start = self.pos
+ _tmp = apply(:_SourceContents)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Source unless _tmp
+ return _tmp
+ end
+
+ # SourceContents = (((!"(" !")" !">" Nonspacechar)+ | "(" SourceContents ")")* | "")
+ def _SourceContents
+
+ _save = self.pos
+ while true # choice
+ while true
+
+ _save2 = self.pos
+ while true # choice
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = match_string("(")
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _save6 = self.pos
+ _tmp = match_string(")")
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _save7 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save8 = self.pos
+ while true # sequence
+ _save9 = self.pos
+ _tmp = match_string("(")
+ _tmp = _tmp ? nil : true
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _save10 = self.pos
+ _tmp = match_string(")")
+ _tmp = _tmp ? nil : true
+ self.pos = _save10
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _save11 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save11
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save8
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ break if _tmp
+ self.pos = _save2
+
+ _save12 = self.pos
+ while true # sequence
+ _tmp = match_string("(")
+ unless _tmp
+ self.pos = _save12
+ break
+ end
+ _tmp = apply(:_SourceContents)
+ unless _tmp
+ self.pos = _save12
+ break
+ end
+ _tmp = match_string(")")
+ unless _tmp
+ self.pos = _save12
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("")
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_SourceContents unless _tmp
+ return _tmp
+ end
+
+ # Title = (TitleSingle | TitleDouble | < "" >):a { a }
+ def _Title
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_TitleSingle)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_TitleDouble)
+ break if _tmp
+ self.pos = _save1
+ _text_start = self.pos
+ _tmp = match_string("")
+ if _tmp
+ text = get_text(_text_start)
+ end
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Title unless _tmp
+ return _tmp
+ end
+
+ # TitleSingle = "'" < (!("'" Sp (")" | Newline)) .)* > "'"
+ def _TitleSingle
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+
+ _save5 = self.pos
+ while true # choice
+ _tmp = match_string(")")
+ break if _tmp
+ self.pos = _save5
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save5
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TitleSingle unless _tmp
+ return _tmp
+ end
+
+ # TitleDouble = "\"" < (!("\"" Sp (")" | Newline)) .)* > "\""
+ def _TitleDouble
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+
+ _save5 = self.pos
+ while true # choice
+ _tmp = match_string(")")
+ break if _tmp
+ self.pos = _save5
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save5
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_TitleDouble unless _tmp
+ return _tmp
+ end
+
+ # AutoLink = (AutoLinkUrl | AutoLinkEmail)
+ def _AutoLink
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_AutoLinkUrl)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_AutoLinkEmail)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_AutoLink unless _tmp
+ return _tmp
+ end
+
+ # AutoLinkUrl = "<" < /[A-Za-z]+/ "://" (!Newline !">" .)+ > ">" { text }
+ def _AutoLinkUrl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+
+ _save1 = self.pos
+ while true # sequence
+ _tmp = scan(/\A(?-mix:[A-Za-z]+)/)
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ _tmp = match_string("://")
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _save5 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save6 = self.pos
+ while true # sequence
+ _save7 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ _save8 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save8
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save6
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_AutoLinkUrl unless _tmp
+ return _tmp
+ end
+
+ # AutoLinkEmail = "<" "mailto:"? < /[\w+_.\/!%~$-]+/i "@" (!Newline !">" .)+ > ">" { "mailto:#{text}" }
+ def _AutoLinkEmail
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("mailto:")
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = scan(/\A(?i-mx:[\w+_.\/!%~$-]+)/)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = match_string("@")
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _save6 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save7 = self.pos
+ while true # sequence
+ _save8 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save8
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _save9 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; "mailto:#{text}" ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_AutoLinkEmail unless _tmp
+ return _tmp
+ end
+
+ # Reference = NonindentSpace !"[]" Label:label ":" Spnl RefSrc:link RefTitle:title BlankLine+ { # TODO use title reference label, link nil }
+ def _Reference
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("[]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Label)
+ label = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(":")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_RefSrc)
+ link = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_RefTitle)
+ title = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_BlankLine)
+ if _tmp
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; # TODO use title
+ reference label, link
+ nil
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Reference unless _tmp
+ return _tmp
+ end
+
+ # Label = "[" (!"^" &{ notes? } | &. &{ !notes? }) StartList:a (!"]" Inline:l { a << l })* "]" { a.join.gsub(/\s+/, ' ') }
+ def _Label
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("[")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+
+ _save1 = self.pos
+ while true # choice
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = match_string("^")
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _save4 = self.pos
+ _tmp = begin; notes? ; end
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save5 = self.pos
+ while true # sequence
+ _save6 = self.pos
+ _tmp = get_byte
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = begin; !notes? ; end
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save9 = self.pos
+ while true # sequence
+ _save10 = self.pos
+ _tmp = match_string("]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save10
+ unless _tmp
+ self.pos = _save9
+ break
+ end
+ _tmp = apply(:_Inline)
+ l = @result
+ unless _tmp
+ self.pos = _save9
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save9
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("]")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a.join.gsub(/\s+/, ' ') ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Label unless _tmp
+ return _tmp
+ end
+
+ # RefSrc = < Nonspacechar+ > { text }
+ def _RefSrc
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _save1 = self.pos
+ _tmp = apply(:_Nonspacechar)
+ if _tmp
+ while true
+ _tmp = apply(:_Nonspacechar)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RefSrc unless _tmp
+ return _tmp
+ end
+
+ # RefTitle = (RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle)
+ def _RefTitle
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_RefTitleSingle)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_RefTitleDouble)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_RefTitleParens)
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_EmptyTitle)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_RefTitle unless _tmp
+ return _tmp
+ end
+
+ # EmptyTitle = < "" >
+ def _EmptyTitle
+ _text_start = self.pos
+ _tmp = match_string("")
+ if _tmp
+ text = get_text(_text_start)
+ end
+ set_failed_rule :_EmptyTitle unless _tmp
+ return _tmp
+ end
+
+ # RefTitleSingle = Spnl "'" < (!("'" Sp Newline | Newline) .)* > "'" { text }
+ def _RefTitleSingle
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # choice
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save4
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save4
+ break
+ end # end choice
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RefTitleSingle unless _tmp
+ return _tmp
+ end
+
+ # RefTitleDouble = Spnl "\"" < (!("\"" Sp Newline | Newline) .)* > "\"" { text }
+ def _RefTitleDouble
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # choice
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save4
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save4
+ break
+ end # end choice
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RefTitleDouble unless _tmp
+ return _tmp
+ end
+
+ # RefTitleParens = Spnl "(" < (!(")" Sp Newline | Newline) .)* > ")" { text }
+ def _RefTitleParens
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("(")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # choice
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string(")")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save4
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save4
+ break
+ end # end choice
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(")")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RefTitleParens unless _tmp
+ return _tmp
+ end
+
+ # References = (Reference | SkipBlock)*
+ def _References
+ while true
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_Reference)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_SkipBlock)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ set_failed_rule :_References unless _tmp
+ return _tmp
+ end
+
+ # Ticks1 = "`" !"`"
+ def _Ticks1
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("`")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Ticks1 unless _tmp
+ return _tmp
+ end
+
+ # Ticks2 = "``" !"`"
+ def _Ticks2
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("``")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Ticks2 unless _tmp
+ return _tmp
+ end
+
+ # Ticks3 = "```" !"`"
+ def _Ticks3
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("```")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Ticks3 unless _tmp
+ return _tmp
+ end
+
+ # Ticks4 = "````" !"`"
+ def _Ticks4
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("````")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Ticks4 unless _tmp
+ return _tmp
+ end
+
+ # Ticks5 = "`````" !"`"
+ def _Ticks5
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("`````")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Ticks5 unless _tmp
+ return _tmp
+ end
+
+ # Code = (Ticks1 Sp < ((!"`" Nonspacechar)+ | !Ticks1 "`"+ | !(Sp Ticks1) (Spacechar | Newline !BlankLine))+ > Sp Ticks1 | Ticks2 Sp < ((!"`" Nonspacechar)+ | !Ticks2 "`"+ | !(Sp Ticks2) (Spacechar | Newline !BlankLine))+ > Sp Ticks2 | Ticks3 Sp < ((!"`" Nonspacechar)+ | !Ticks3 "`"+ | !(Sp Ticks3) (Spacechar | Newline !BlankLine))+ > Sp Ticks3 | Ticks4 Sp < ((!"`" Nonspacechar)+ | !Ticks4 "`"+ | !(Sp Ticks4) (Spacechar | Newline !BlankLine))+ > Sp Ticks4 | Ticks5 Sp < ((!"`" Nonspacechar)+ | !Ticks5 "`"+ | !(Sp Ticks5) (Spacechar | Newline !BlankLine))+ > Sp Ticks5) { "<code>#{text}</code>" }
+ def _Code
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_Ticks1)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _text_start = self.pos
+ _save3 = self.pos
+
+ _save4 = self.pos
+ while true # choice
+ _save5 = self.pos
+
+ _save6 = self.pos
+ while true # sequence
+ _save7 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save6
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save6
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save8 = self.pos
+ while true # sequence
+ _save9 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save8
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save5
+ end
+ break if _tmp
+ self.pos = _save4
+
+ _save10 = self.pos
+ while true # sequence
+ _save11 = self.pos
+ _tmp = apply(:_Ticks1)
+ _tmp = _tmp ? nil : true
+ self.pos = _save11
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ _save12 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save12
+ end
+ unless _tmp
+ self.pos = _save10
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save4
+
+ _save13 = self.pos
+ while true # sequence
+ _save14 = self.pos
+
+ _save15 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save15
+ break
+ end
+ _tmp = apply(:_Ticks1)
+ unless _tmp
+ self.pos = _save15
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save14
+ unless _tmp
+ self.pos = _save13
+ break
+ end
+
+ _save16 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save16
+
+ _save17 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save17
+ break
+ end
+ _save18 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save18
+ unless _tmp
+ self.pos = _save17
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save16
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save13
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save4
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save19 = self.pos
+ while true # choice
+ _save20 = self.pos
+
+ _save21 = self.pos
+ while true # sequence
+ _save22 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save22
+ unless _tmp
+ self.pos = _save21
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save21
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save23 = self.pos
+ while true # sequence
+ _save24 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save24
+ unless _tmp
+ self.pos = _save23
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save23
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save20
+ end
+ break if _tmp
+ self.pos = _save19
+
+ _save25 = self.pos
+ while true # sequence
+ _save26 = self.pos
+ _tmp = apply(:_Ticks1)
+ _tmp = _tmp ? nil : true
+ self.pos = _save26
+ unless _tmp
+ self.pos = _save25
+ break
+ end
+ _save27 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save27
+ end
+ unless _tmp
+ self.pos = _save25
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save19
+
+ _save28 = self.pos
+ while true # sequence
+ _save29 = self.pos
+
+ _save30 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save30
+ break
+ end
+ _tmp = apply(:_Ticks1)
+ unless _tmp
+ self.pos = _save30
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save29
+ unless _tmp
+ self.pos = _save28
+ break
+ end
+
+ _save31 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save31
+
+ _save32 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save32
+ break
+ end
+ _save33 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save33
+ unless _tmp
+ self.pos = _save32
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save31
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save28
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save19
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save3
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Ticks1)
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save34 = self.pos
+ while true # sequence
+ _tmp = apply(:_Ticks2)
+ unless _tmp
+ self.pos = _save34
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save34
+ break
+ end
+ _text_start = self.pos
+ _save35 = self.pos
+
+ _save36 = self.pos
+ while true # choice
+ _save37 = self.pos
+
+ _save38 = self.pos
+ while true # sequence
+ _save39 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save39
+ unless _tmp
+ self.pos = _save38
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save38
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save40 = self.pos
+ while true # sequence
+ _save41 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save41
+ unless _tmp
+ self.pos = _save40
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save40
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save37
+ end
+ break if _tmp
+ self.pos = _save36
+
+ _save42 = self.pos
+ while true # sequence
+ _save43 = self.pos
+ _tmp = apply(:_Ticks2)
+ _tmp = _tmp ? nil : true
+ self.pos = _save43
+ unless _tmp
+ self.pos = _save42
+ break
+ end
+ _save44 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save44
+ end
+ unless _tmp
+ self.pos = _save42
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save36
+
+ _save45 = self.pos
+ while true # sequence
+ _save46 = self.pos
+
+ _save47 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save47
+ break
+ end
+ _tmp = apply(:_Ticks2)
+ unless _tmp
+ self.pos = _save47
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save46
+ unless _tmp
+ self.pos = _save45
+ break
+ end
+
+ _save48 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save48
+
+ _save49 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save49
+ break
+ end
+ _save50 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save50
+ unless _tmp
+ self.pos = _save49
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save48
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save45
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save36
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save51 = self.pos
+ while true # choice
+ _save52 = self.pos
+
+ _save53 = self.pos
+ while true # sequence
+ _save54 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save54
+ unless _tmp
+ self.pos = _save53
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save53
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save55 = self.pos
+ while true # sequence
+ _save56 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save56
+ unless _tmp
+ self.pos = _save55
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save55
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save52
+ end
+ break if _tmp
+ self.pos = _save51
+
+ _save57 = self.pos
+ while true # sequence
+ _save58 = self.pos
+ _tmp = apply(:_Ticks2)
+ _tmp = _tmp ? nil : true
+ self.pos = _save58
+ unless _tmp
+ self.pos = _save57
+ break
+ end
+ _save59 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save59
+ end
+ unless _tmp
+ self.pos = _save57
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save51
+
+ _save60 = self.pos
+ while true # sequence
+ _save61 = self.pos
+
+ _save62 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save62
+ break
+ end
+ _tmp = apply(:_Ticks2)
+ unless _tmp
+ self.pos = _save62
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save61
+ unless _tmp
+ self.pos = _save60
+ break
+ end
+
+ _save63 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save63
+
+ _save64 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save64
+ break
+ end
+ _save65 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save65
+ unless _tmp
+ self.pos = _save64
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save63
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save60
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save51
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save35
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save34
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save34
+ break
+ end
+ _tmp = apply(:_Ticks2)
+ unless _tmp
+ self.pos = _save34
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save66 = self.pos
+ while true # sequence
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save66
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save66
+ break
+ end
+ _text_start = self.pos
+ _save67 = self.pos
+
+ _save68 = self.pos
+ while true # choice
+ _save69 = self.pos
+
+ _save70 = self.pos
+ while true # sequence
+ _save71 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save71
+ unless _tmp
+ self.pos = _save70
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save70
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save72 = self.pos
+ while true # sequence
+ _save73 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save73
+ unless _tmp
+ self.pos = _save72
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save72
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save69
+ end
+ break if _tmp
+ self.pos = _save68
+
+ _save74 = self.pos
+ while true # sequence
+ _save75 = self.pos
+ _tmp = apply(:_Ticks3)
+ _tmp = _tmp ? nil : true
+ self.pos = _save75
+ unless _tmp
+ self.pos = _save74
+ break
+ end
+ _save76 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save76
+ end
+ unless _tmp
+ self.pos = _save74
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save68
+
+ _save77 = self.pos
+ while true # sequence
+ _save78 = self.pos
+
+ _save79 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save79
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save79
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save78
+ unless _tmp
+ self.pos = _save77
+ break
+ end
+
+ _save80 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save80
+
+ _save81 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save81
+ break
+ end
+ _save82 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save82
+ unless _tmp
+ self.pos = _save81
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save80
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save77
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save68
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save83 = self.pos
+ while true # choice
+ _save84 = self.pos
+
+ _save85 = self.pos
+ while true # sequence
+ _save86 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save86
+ unless _tmp
+ self.pos = _save85
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save85
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save87 = self.pos
+ while true # sequence
+ _save88 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save88
+ unless _tmp
+ self.pos = _save87
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save87
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save84
+ end
+ break if _tmp
+ self.pos = _save83
+
+ _save89 = self.pos
+ while true # sequence
+ _save90 = self.pos
+ _tmp = apply(:_Ticks3)
+ _tmp = _tmp ? nil : true
+ self.pos = _save90
+ unless _tmp
+ self.pos = _save89
+ break
+ end
+ _save91 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save91
+ end
+ unless _tmp
+ self.pos = _save89
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save83
+
+ _save92 = self.pos
+ while true # sequence
+ _save93 = self.pos
+
+ _save94 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save94
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save94
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save93
+ unless _tmp
+ self.pos = _save92
+ break
+ end
+
+ _save95 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save95
+
+ _save96 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save96
+ break
+ end
+ _save97 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save97
+ unless _tmp
+ self.pos = _save96
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save95
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save92
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save83
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save67
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save66
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save66
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save66
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save98 = self.pos
+ while true # sequence
+ _tmp = apply(:_Ticks4)
+ unless _tmp
+ self.pos = _save98
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save98
+ break
+ end
+ _text_start = self.pos
+ _save99 = self.pos
+
+ _save100 = self.pos
+ while true # choice
+ _save101 = self.pos
+
+ _save102 = self.pos
+ while true # sequence
+ _save103 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save103
+ unless _tmp
+ self.pos = _save102
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save102
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save104 = self.pos
+ while true # sequence
+ _save105 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save105
+ unless _tmp
+ self.pos = _save104
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save104
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save101
+ end
+ break if _tmp
+ self.pos = _save100
+
+ _save106 = self.pos
+ while true # sequence
+ _save107 = self.pos
+ _tmp = apply(:_Ticks4)
+ _tmp = _tmp ? nil : true
+ self.pos = _save107
+ unless _tmp
+ self.pos = _save106
+ break
+ end
+ _save108 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save108
+ end
+ unless _tmp
+ self.pos = _save106
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save100
+
+ _save109 = self.pos
+ while true # sequence
+ _save110 = self.pos
+
+ _save111 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save111
+ break
+ end
+ _tmp = apply(:_Ticks4)
+ unless _tmp
+ self.pos = _save111
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save110
+ unless _tmp
+ self.pos = _save109
+ break
+ end
+
+ _save112 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save112
+
+ _save113 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save113
+ break
+ end
+ _save114 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save114
+ unless _tmp
+ self.pos = _save113
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save112
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save109
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save100
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save115 = self.pos
+ while true # choice
+ _save116 = self.pos
+
+ _save117 = self.pos
+ while true # sequence
+ _save118 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save118
+ unless _tmp
+ self.pos = _save117
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save117
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save119 = self.pos
+ while true # sequence
+ _save120 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save120
+ unless _tmp
+ self.pos = _save119
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save119
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save116
+ end
+ break if _tmp
+ self.pos = _save115
+
+ _save121 = self.pos
+ while true # sequence
+ _save122 = self.pos
+ _tmp = apply(:_Ticks4)
+ _tmp = _tmp ? nil : true
+ self.pos = _save122
+ unless _tmp
+ self.pos = _save121
+ break
+ end
+ _save123 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save123
+ end
+ unless _tmp
+ self.pos = _save121
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save115
+
+ _save124 = self.pos
+ while true # sequence
+ _save125 = self.pos
+
+ _save126 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save126
+ break
+ end
+ _tmp = apply(:_Ticks4)
+ unless _tmp
+ self.pos = _save126
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save125
+ unless _tmp
+ self.pos = _save124
+ break
+ end
+
+ _save127 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save127
+
+ _save128 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save128
+ break
+ end
+ _save129 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save129
+ unless _tmp
+ self.pos = _save128
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save127
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save124
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save115
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save99
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save98
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save98
+ break
+ end
+ _tmp = apply(:_Ticks4)
+ unless _tmp
+ self.pos = _save98
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+
+ _save130 = self.pos
+ while true # sequence
+ _tmp = apply(:_Ticks5)
+ unless _tmp
+ self.pos = _save130
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save130
+ break
+ end
+ _text_start = self.pos
+ _save131 = self.pos
+
+ _save132 = self.pos
+ while true # choice
+ _save133 = self.pos
+
+ _save134 = self.pos
+ while true # sequence
+ _save135 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save135
+ unless _tmp
+ self.pos = _save134
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save134
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save136 = self.pos
+ while true # sequence
+ _save137 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save137
+ unless _tmp
+ self.pos = _save136
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save136
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save133
+ end
+ break if _tmp
+ self.pos = _save132
+
+ _save138 = self.pos
+ while true # sequence
+ _save139 = self.pos
+ _tmp = apply(:_Ticks5)
+ _tmp = _tmp ? nil : true
+ self.pos = _save139
+ unless _tmp
+ self.pos = _save138
+ break
+ end
+ _save140 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save140
+ end
+ unless _tmp
+ self.pos = _save138
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save132
+
+ _save141 = self.pos
+ while true # sequence
+ _save142 = self.pos
+
+ _save143 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save143
+ break
+ end
+ _tmp = apply(:_Ticks5)
+ unless _tmp
+ self.pos = _save143
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save142
+ unless _tmp
+ self.pos = _save141
+ break
+ end
+
+ _save144 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save144
+
+ _save145 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save145
+ break
+ end
+ _save146 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save146
+ unless _tmp
+ self.pos = _save145
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save144
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save141
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save132
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save147 = self.pos
+ while true # choice
+ _save148 = self.pos
+
+ _save149 = self.pos
+ while true # sequence
+ _save150 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save150
+ unless _tmp
+ self.pos = _save149
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save149
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save151 = self.pos
+ while true # sequence
+ _save152 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save152
+ unless _tmp
+ self.pos = _save151
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save151
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save148
+ end
+ break if _tmp
+ self.pos = _save147
+
+ _save153 = self.pos
+ while true # sequence
+ _save154 = self.pos
+ _tmp = apply(:_Ticks5)
+ _tmp = _tmp ? nil : true
+ self.pos = _save154
+ unless _tmp
+ self.pos = _save153
+ break
+ end
+ _save155 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save155
+ end
+ unless _tmp
+ self.pos = _save153
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save147
+
+ _save156 = self.pos
+ while true # sequence
+ _save157 = self.pos
+
+ _save158 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save158
+ break
+ end
+ _tmp = apply(:_Ticks5)
+ unless _tmp
+ self.pos = _save158
+ end
+ break
+ end # end sequence
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save157
+ unless _tmp
+ self.pos = _save156
+ break
+ end
+
+ _save159 = self.pos
+ while true # choice
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save159
+
+ _save160 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save160
+ break
+ end
+ _save161 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save161
+ unless _tmp
+ self.pos = _save160
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save159
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save156
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save147
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save131
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save130
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save130
+ break
+ end
+ _tmp = apply(:_Ticks5)
+ unless _tmp
+ self.pos = _save130
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; "<code>#{text}</code>" ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Code unless _tmp
+ return _tmp
+ end
+
+ # RawHtml = < (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end }
+ def _RawHtml
+
+ _save = self.pos
+ while true # sequence
+ _text_start = self.pos
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlComment)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_HtmlBlockScript)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_HtmlTag)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; if html? then text else '' end ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RawHtml unless _tmp
+ return _tmp
+ end
+
+ # BlankLine = Sp Newline { "\n" }
+ def _BlankLine
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; "\n" ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_BlankLine unless _tmp
+ return _tmp
+ end
+
+ # Quoted = ("\"" (!"\"" .)* "\"" | "'" (!"'" .)* "'")
+ def _Quoted
+
+ _save = self.pos
+ while true # choice
+
+ _save1 = self.pos
+ while true # sequence
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ while true
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = match_string("\"")
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ _tmp = match_string("\"")
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ while true
+
+ _save7 = self.pos
+ while true # sequence
+ _save8 = self.pos
+ _tmp = match_string("'")
+ _tmp = _tmp ? nil : true
+ self.pos = _save8
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = match_string("'")
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Quoted unless _tmp
+ return _tmp
+ end
+
+ # HtmlAttribute = (AlphanumericAscii | "-")+ Spnl ("=" Spnl (Quoted | (!">" Nonspacechar)+))? Spnl
+ def _HtmlAttribute
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_AlphanumericAscii)
+ break if _tmp
+ self.pos = _save2
+ _tmp = match_string("-")
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save3 = self.pos
+ while true # choice
+ _tmp = apply(:_AlphanumericAscii)
+ break if _tmp
+ self.pos = _save3
+ _tmp = match_string("-")
+ break if _tmp
+ self.pos = _save3
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save4 = self.pos
+
+ _save5 = self.pos
+ while true # sequence
+ _tmp = match_string("=")
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+
+ _save6 = self.pos
+ while true # choice
+ _tmp = apply(:_Quoted)
+ break if _tmp
+ self.pos = _save6
+ _save7 = self.pos
+
+ _save8 = self.pos
+ while true # sequence
+ _save9 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save8
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save10 = self.pos
+ while true # sequence
+ _save11 = self.pos
+ _tmp = match_string(">")
+ _tmp = _tmp ? nil : true
+ self.pos = _save11
+ unless _tmp
+ self.pos = _save10
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save10
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save7
+ end
+ break if _tmp
+ self.pos = _save6
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ unless _tmp
+ _tmp = true
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlAttribute unless _tmp
+ return _tmp
+ end
+
+ # HtmlComment = "<!--" (!"-->" .)* "-->"
+ def _HtmlComment
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<!--")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = match_string("-->")
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("-->")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlComment unless _tmp
+ return _tmp
+ end
+
+ # HtmlTag = "<" Spnl "/"? AlphanumericAscii+ Spnl HtmlAttribute* "/"? Spnl ">"
+ def _HtmlTag
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("<")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = match_string("/")
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_AlphanumericAscii)
+ if _tmp
+ while true
+ _tmp = apply(:_AlphanumericAscii)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_HtmlAttribute)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save4 = self.pos
+ _tmp = match_string("/")
+ unless _tmp
+ _tmp = true
+ self.pos = _save4
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(">")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HtmlTag unless _tmp
+ return _tmp
+ end
+
+ # Eof = !.
+ def _Eof
+ _save = self.pos
+ _tmp = get_byte
+ _tmp = _tmp ? nil : true
+ self.pos = _save
+ set_failed_rule :_Eof unless _tmp
+ return _tmp
+ end
+
+ # Nonspacechar = !Spacechar !Newline .
+ def _Nonspacechar
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Spacechar)
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save2
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Nonspacechar unless _tmp
+ return _tmp
+ end
+
+ # Sp = Spacechar*
+ def _Sp
+ while true
+ _tmp = apply(:_Spacechar)
+ break unless _tmp
+ end
+ _tmp = true
+ set_failed_rule :_Sp unless _tmp
+ return _tmp
+ end
+
+ # Spnl = Sp (Newline Sp)?
+ def _Spnl
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Spnl unless _tmp
+ return _tmp
+ end
+
+ # SpecialChar = ("*" | "_" | "`" | "&" | "[" | "]" | "(" | ")" | "<" | "!" | "#" | "\\" | "'" | "\"" | ExtendedSpecialChar)
+ def _SpecialChar
+
+ _save = self.pos
+ while true # choice
+ _tmp = match_string("*")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("_")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("`")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("&")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("[")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("]")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("(")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string(")")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("<")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("!")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("#")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("\\")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("'")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("\"")
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_ExtendedSpecialChar)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_SpecialChar unless _tmp
+ return _tmp
+ end
+
+ # NormalChar = !(SpecialChar | Spacechar | Newline) .
+ def _NormalChar
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # choice
+ _tmp = apply(:_SpecialChar)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save2
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save2
+ break
+ end # end choice
+
+ _tmp = _tmp ? nil : true
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_NormalChar unless _tmp
+ return _tmp
+ end
+
+ # Digit = [0-9]
+ def _Digit
+ _save = self.pos
+ _tmp = get_byte
+ if _tmp
+ unless _tmp >= 48 and _tmp <= 57
+ self.pos = _save
+ _tmp = nil
+ end
+ end
+ set_failed_rule :_Digit unless _tmp
+ return _tmp
+ end
+
+ # Alphanumeric = %literals.Alphanumeric
+ def _Alphanumeric
+ _tmp = @_grammar_literals.external_invoke(self, :_Alphanumeric)
+ set_failed_rule :_Alphanumeric unless _tmp
+ return _tmp
+ end
+
+ # AlphanumericAscii = %literals.AlphanumericAscii
+ def _AlphanumericAscii
+ _tmp = @_grammar_literals.external_invoke(self, :_AlphanumericAscii)
+ set_failed_rule :_AlphanumericAscii unless _tmp
+ return _tmp
+ end
+
+ # BOM = %literals.BOM
+ def _BOM
+ _tmp = @_grammar_literals.external_invoke(self, :_BOM)
+ set_failed_rule :_BOM unless _tmp
+ return _tmp
+ end
+
+ # Newline = %literals.Newline
+ def _Newline
+ _tmp = @_grammar_literals.external_invoke(self, :_Newline)
+ set_failed_rule :_Newline unless _tmp
+ return _tmp
+ end
+
+ # NonAlphanumeric = %literals.NonAlphanumeric
+ def _NonAlphanumeric
+ _tmp = @_grammar_literals.external_invoke(self, :_NonAlphanumeric)
+ set_failed_rule :_NonAlphanumeric unless _tmp
+ return _tmp
+ end
+
+ # Spacechar = %literals.Spacechar
+ def _Spacechar
+ _tmp = @_grammar_literals.external_invoke(self, :_Spacechar)
+ set_failed_rule :_Spacechar unless _tmp
+ return _tmp
+ end
+
+ # HexEntity = "&" "#" /[Xx]/ < /[0-9a-fA-F]+/ > ";" { [text.to_i(16)].pack 'U' }
+ def _HexEntity
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("&")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("#")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = scan(/\A(?-mix:[Xx])/)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _tmp = scan(/\A(?-mix:[0-9a-fA-F]+)/)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(";")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; [text.to_i(16)].pack 'U' ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_HexEntity unless _tmp
+ return _tmp
+ end
+
+ # DecEntity = "&" "#" < /[0-9]+/ > ";" { [text.to_i].pack 'U' }
+ def _DecEntity
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("&")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("#")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _tmp = scan(/\A(?-mix:[0-9]+)/)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(";")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; [text.to_i].pack 'U' ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_DecEntity unless _tmp
+ return _tmp
+ end
+
+ # CharEntity = "&" < /[A-Za-z0-9]+/ > ";" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else "&#{text};" end }
+ def _CharEntity
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("&")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _tmp = scan(/\A(?-mix:[A-Za-z0-9]+)/)
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(";")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; if entity = HTML_ENTITIES[text] then
+ entity.pack 'U*'
+ else
+ "&#{text};"
+ end
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_CharEntity unless _tmp
+ return _tmp
+ end
+
+ # NonindentSpace = (" " | " " | " " | "")
+ def _NonindentSpace
+
+ _save = self.pos
+ while true # choice
+ _tmp = match_string(" ")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string(" ")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string(" ")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string("")
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_NonindentSpace unless _tmp
+ return _tmp
+ end
+
+ # Indent = ("\t" | " ")
+ def _Indent
+
+ _save = self.pos
+ while true # choice
+ _tmp = match_string("\t")
+ break if _tmp
+ self.pos = _save
+ _tmp = match_string(" ")
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_Indent unless _tmp
+ return _tmp
+ end
+
+ # IndentedLine = Indent Line
+ def _IndentedLine
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_Indent)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Line)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_IndentedLine unless _tmp
+ return _tmp
+ end
+
+ # OptionallyIndentedLine = Indent? Line
+ def _OptionallyIndentedLine
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = apply(:_Indent)
+ unless _tmp
+ _tmp = true
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Line)
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_OptionallyIndentedLine unless _tmp
+ return _tmp
+ end
+
+ # StartList = &. { [] }
+ def _StartList
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = get_byte
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; [] ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_StartList unless _tmp
+ return _tmp
+ end
+
+ # Line = RawLine:a { a }
+ def _Line
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_RawLine)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Line unless _tmp
+ return _tmp
+ end
+
+ # RawLine = (< (!" " !"\n" .)* Newline > | < .+ > Eof) { text }
+ def _RawLine
+
+ _save = self.pos
+ while true # sequence
+
+ _save1 = self.pos
+ while true # choice
+ _text_start = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ while true
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = match_string("\r")
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _save6 = self.pos
+ _tmp = match_string("\n")
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ text = get_text(_text_start)
+ end
+ break if _tmp
+ self.pos = _save1
+
+ _save7 = self.pos
+ while true # sequence
+ _text_start = self.pos
+ _save8 = self.pos
+ _tmp = get_byte
+ if _tmp
+ while true
+ _tmp = get_byte
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save8
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = apply(:_Eof)
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RawLine unless _tmp
+ return _tmp
+ end
+
+ # SkipBlock = (HtmlBlock | (!"#" !SetextBottom1 !SetextBottom2 !BlankLine RawLine)+ BlankLine* | BlankLine+ | RawLine)
+ def _SkipBlock
+
+ _save = self.pos
+ while true # choice
+ _tmp = apply(:_HtmlBlock)
+ break if _tmp
+ self.pos = _save
+
+ _save1 = self.pos
+ while true # sequence
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = match_string("#")
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _save5 = self.pos
+ _tmp = apply(:_SetextBottom1)
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _save6 = self.pos
+ _tmp = apply(:_SetextBottom2)
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _save7 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_RawLine)
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save8 = self.pos
+ while true # sequence
+ _save9 = self.pos
+ _tmp = match_string("#")
+ _tmp = _tmp ? nil : true
+ self.pos = _save9
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _save10 = self.pos
+ _tmp = apply(:_SetextBottom1)
+ _tmp = _tmp ? nil : true
+ self.pos = _save10
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _save11 = self.pos
+ _tmp = apply(:_SetextBottom2)
+ _tmp = _tmp ? nil : true
+ self.pos = _save11
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _save12 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save12
+ unless _tmp
+ self.pos = _save8
+ break
+ end
+ _tmp = apply(:_RawLine)
+ unless _tmp
+ self.pos = _save8
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save1
+ break
+ end
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save1
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save
+ _save14 = self.pos
+ _tmp = apply(:_BlankLine)
+ if _tmp
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save14
+ end
+ break if _tmp
+ self.pos = _save
+ _tmp = apply(:_RawLine)
+ break if _tmp
+ self.pos = _save
+ break
+ end # end choice
+
+ set_failed_rule :_SkipBlock unless _tmp
+ return _tmp
+ end
+
+ # ExtendedSpecialChar = &{ notes? } "^"
+ def _ExtendedSpecialChar
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = begin; notes? ; end
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("^")
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_ExtendedSpecialChar unless _tmp
+ return _tmp
+ end
+
+ # NoteReference = &{ notes? } RawNoteReference:ref { note_for ref }
+ def _NoteReference
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = begin; notes? ; end
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_RawNoteReference)
+ ref = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; note_for ref ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_NoteReference unless _tmp
+ return _tmp
+ end
+
+ # RawNoteReference = "[^" < (!Newline !"]" .)+ > "]" { text }
+ def _RawNoteReference
+
+ _save = self.pos
+ while true # sequence
+ _tmp = match_string("[^")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _save4 = self.pos
+ _tmp = match_string("]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save5 = self.pos
+ while true # sequence
+ _save6 = self.pos
+ _tmp = apply(:_Newline)
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _save7 = self.pos
+ _tmp = match_string("]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save7
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = get_byte
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("]")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RawNoteReference unless _tmp
+ return _tmp
+ end
+
+ # Note = &{ notes? } NonindentSpace RawNoteReference:ref ":" Sp StartList:a RawNoteBlock:l (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }
+ def _Note
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = begin; notes? ; end
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_RawNoteReference)
+ ref = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(":")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_RawNoteBlock)
+ l = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = apply(:_Indent)
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_RawNoteBlock)
+ i = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; a.concat i ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; @footnotes[ref] = paragraph a
+
+ nil
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_Note unless _tmp
+ return _tmp
+ end
+
+ # InlineNote = &{ notes? } "^[" StartList:a (!"]" Inline:l { a << l })+ "]" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }
+ def _InlineNote
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = begin; notes? ; end
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("^[")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _save4 = self.pos
+ _tmp = match_string("]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save4
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_Inline)
+ l = @result
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save5 = self.pos
+ while true # sequence
+ _save6 = self.pos
+ _tmp = match_string("]")
+ _tmp = _tmp ? nil : true
+ self.pos = _save6
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ _tmp = apply(:_Inline)
+ l = @result
+ unless _tmp
+ self.pos = _save5
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save5
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string("]")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin;
+ ref = [:inline, @note_order.length]
+ @footnotes[ref] = paragraph a
+
+ note_for ref
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_InlineNote unless _tmp
+ return _tmp
+ end
+
+ # Notes = (Note | SkipBlock)*
+ def _Notes
+ while true
+
+ _save1 = self.pos
+ while true # choice
+ _tmp = apply(:_Note)
+ break if _tmp
+ self.pos = _save1
+ _tmp = apply(:_SkipBlock)
+ break if _tmp
+ self.pos = _save1
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ set_failed_rule :_Notes unless _tmp
+ return _tmp
+ end
+
+ # RawNoteBlock = StartList:a (!BlankLine OptionallyIndentedLine:l { a << l })+ < BlankLine* > { a << text } { a }
+ def _RawNoteBlock
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StartList)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+
+ _save2 = self.pos
+ while true # sequence
+ _save3 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save3
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ _tmp = apply(:_OptionallyIndentedLine)
+ l = @result
+ unless _tmp
+ self.pos = _save2
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save2
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save4 = self.pos
+ while true # sequence
+ _save5 = self.pos
+ _tmp = apply(:_BlankLine)
+ _tmp = _tmp ? nil : true
+ self.pos = _save5
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ _tmp = apply(:_OptionallyIndentedLine)
+ l = @result
+ unless _tmp
+ self.pos = _save4
+ break
+ end
+ @result = begin; a << l ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save4
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a << text ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_RawNoteBlock unless _tmp
+ return _tmp
+ end
+
+ # CodeFence = &{ github? } Ticks3 (Sp StrChunk:format)? Spnl < ((!"`" Nonspacechar)+ | !Ticks3 "`"+ | Spacechar | Newline)+ > Ticks3 Sp Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim }
+ def _CodeFence
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = begin; github? ; end
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+
+ _save3 = self.pos
+ while true # sequence
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save3
+ break
+ end
+ _tmp = apply(:_StrChunk)
+ format = @result
+ unless _tmp
+ self.pos = _save3
+ end
+ break
+ end # end sequence
+
+ unless _tmp
+ _tmp = true
+ self.pos = _save2
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Spnl)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _text_start = self.pos
+ _save4 = self.pos
+
+ _save5 = self.pos
+ while true # choice
+ _save6 = self.pos
+
+ _save7 = self.pos
+ while true # sequence
+ _save8 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save8
+ unless _tmp
+ self.pos = _save7
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save7
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save9 = self.pos
+ while true # sequence
+ _save10 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save10
+ unless _tmp
+ self.pos = _save9
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save9
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save6
+ end
+ break if _tmp
+ self.pos = _save5
+
+ _save11 = self.pos
+ while true # sequence
+ _save12 = self.pos
+ _tmp = apply(:_Ticks3)
+ _tmp = _tmp ? nil : true
+ self.pos = _save12
+ unless _tmp
+ self.pos = _save11
+ break
+ end
+ _save13 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save13
+ end
+ unless _tmp
+ self.pos = _save11
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save5
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save5
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save5
+ break
+ end # end choice
+
+ if _tmp
+ while true
+
+ _save14 = self.pos
+ while true # choice
+ _save15 = self.pos
+
+ _save16 = self.pos
+ while true # sequence
+ _save17 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save17
+ unless _tmp
+ self.pos = _save16
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save16
+ end
+ break
+ end # end sequence
+
+ if _tmp
+ while true
+
+ _save18 = self.pos
+ while true # sequence
+ _save19 = self.pos
+ _tmp = match_string("`")
+ _tmp = _tmp ? nil : true
+ self.pos = _save19
+ unless _tmp
+ self.pos = _save18
+ break
+ end
+ _tmp = apply(:_Nonspacechar)
+ unless _tmp
+ self.pos = _save18
+ end
+ break
+ end # end sequence
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save15
+ end
+ break if _tmp
+ self.pos = _save14
+
+ _save20 = self.pos
+ while true # sequence
+ _save21 = self.pos
+ _tmp = apply(:_Ticks3)
+ _tmp = _tmp ? nil : true
+ self.pos = _save21
+ unless _tmp
+ self.pos = _save20
+ break
+ end
+ _save22 = self.pos
+ _tmp = match_string("`")
+ if _tmp
+ while true
+ _tmp = match_string("`")
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save22
+ end
+ unless _tmp
+ self.pos = _save20
+ end
+ break
+ end # end sequence
+
+ break if _tmp
+ self.pos = _save14
+ _tmp = apply(:_Spacechar)
+ break if _tmp
+ self.pos = _save14
+ _tmp = apply(:_Newline)
+ break if _tmp
+ self.pos = _save14
+ break
+ end # end choice
+
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save4
+ end
+ if _tmp
+ text = get_text(_text_start)
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Ticks3)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ while true
+ _tmp = apply(:_Newline)
+ break unless _tmp
+ end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; verbatim = RDoc::Markup::Verbatim.new text
+ verbatim.format = format.intern if format
+ verbatim
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_CodeFence unless _tmp
+ return _tmp
+ end
+
+ # DefinitionList = &{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }
+ def _DefinitionList
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _tmp = begin; definition_lists? ; end
+ self.pos = _save1
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _ary = []
+ _tmp = apply(:_DefinitionListItem)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_DefinitionListItem)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save2
+ end
+ list = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; RDoc::Markup::List.new :NOTE, *list.flatten ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_DefinitionList unless _tmp
+ return _tmp
+ end
+
+ # DefinitionListItem = DefinitionListLabel+:label DefinitionListDefinition+:defn { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defn.shift) list_items.concat defn.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }
+ def _DefinitionListItem
+
+ _save = self.pos
+ while true # sequence
+ _save1 = self.pos
+ _ary = []
+ _tmp = apply(:_DefinitionListLabel)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_DefinitionListLabel)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save1
+ end
+ label = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save2 = self.pos
+ _ary = []
+ _tmp = apply(:_DefinitionListDefinition)
+ if _tmp
+ _ary << @result
+ while true
+ _tmp = apply(:_DefinitionListDefinition)
+ _ary << @result if _tmp
+ break unless _tmp
+ end
+ _tmp = true
+ @result = _ary
+ else
+ self.pos = _save2
+ end
+ defn = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; list_items = []
+ list_items <<
+ RDoc::Markup::ListItem.new(label, defn.shift)
+
+ list_items.concat defn.map { |defn|
+ RDoc::Markup::ListItem.new nil, defn
+ } unless list_items.empty?
+
+ list_items
+ ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_DefinitionListItem unless _tmp
+ return _tmp
+ end
+
+ # DefinitionListLabel = StrChunk:label Sp Newline { label }
+ def _DefinitionListLabel
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_StrChunk)
+ label = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Sp)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Newline)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; label ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_DefinitionListLabel unless _tmp
+ return _tmp
+ end
+
+ # DefinitionListDefinition = NonindentSpace ":" Space Inlines:a BlankLine+ { paragraph a }
+ def _DefinitionListDefinition
+
+ _save = self.pos
+ while true # sequence
+ _tmp = apply(:_NonindentSpace)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = match_string(":")
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Space)
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _tmp = apply(:_Inlines)
+ a = @result
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ _save1 = self.pos
+ _tmp = apply(:_BlankLine)
+ if _tmp
+ while true
+ _tmp = apply(:_BlankLine)
+ break unless _tmp
+ end
+ _tmp = true
+ else
+ self.pos = _save1
+ end
+ unless _tmp
+ self.pos = _save
+ break
+ end
+ @result = begin; paragraph a ; end
+ _tmp = true
+ unless _tmp
+ self.pos = _save
+ end
+ break
+ end # end sequence
+
+ set_failed_rule :_DefinitionListDefinition unless _tmp
+ return _tmp
+ end
+
+ Rules = {}
+ Rules[:_root] = rule_info("root", "Doc")
+ Rules[:_Doc] = rule_info("Doc", "BOM? Block*:a { RDoc::Markup::Document.new(*a.compact) }")
+ Rules[:_Block] = rule_info("Block", "BlankLine* (BlockQuote | Verbatim | CodeFence | Note | Reference | HorizontalRule | Heading | OrderedList | BulletList | DefinitionList | HtmlBlock | StyleBlock | Para | Plain)")
+ Rules[:_Para] = rule_info("Para", "NonindentSpace Inlines:a BlankLine+ { paragraph a }")
+ Rules[:_Plain] = rule_info("Plain", "Inlines:a { paragraph a }")
+ Rules[:_AtxInline] = rule_info("AtxInline", "!Newline !(Sp? \"\#\"* Sp Newline) Inline")
+ Rules[:_AtxStart] = rule_info("AtxStart", "< (\"\#\#\#\#\#\#\" | \"\#\#\#\#\#\" | \"\#\#\#\#\" | \"\#\#\#\" | \"\#\#\" | \"\#\") > { text.length }")
+ Rules[:_AtxHeading] = rule_info("AtxHeading", "AtxStart:s Sp? AtxInline+:a (Sp? \"\#\"* Sp)? Newline { RDoc::Markup::Heading.new(s, a.join) }")
+ Rules[:_SetextHeading] = rule_info("SetextHeading", "(SetextHeading1 | SetextHeading2)")
+ Rules[:_SetextBottom1] = rule_info("SetextBottom1", "\"===\" \"=\"* Newline")
+ Rules[:_SetextBottom2] = rule_info("SetextBottom2", "\"---\" \"-\"* Newline")
+ Rules[:_SetextHeading1] = rule_info("SetextHeading1", "&(RawLine SetextBottom1) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom1 { a; RDoc::Markup::Heading.new(1, a.join) }")
+ Rules[:_SetextHeading2] = rule_info("SetextHeading2", "&(RawLine SetextBottom2) StartList:a (!Endline Inline:b { a << b })+ Sp? Newline SetextBottom2 { RDoc::Markup::Heading.new(2, a.join) }")
+ Rules[:_Heading] = rule_info("Heading", "(SetextHeading | AtxHeading)")
+ Rules[:_BlockQuote] = rule_info("BlockQuote", "BlockQuoteRaw:a { RDoc::Markup::BlockQuote.new(*a) }")
+ Rules[:_BlockQuoteRaw] = rule_info("BlockQuoteRaw", "StartList:a (\">\" \" \"? Line:l { a << l } (!\">\" !BlankLine Line:c { a << c })* (BlankLine:n { a << n })*)+ { inner_parse a.join }")
+ Rules[:_NonblankIndentedLine] = rule_info("NonblankIndentedLine", "!BlankLine IndentedLine")
+ Rules[:_VerbatimChunk] = rule_info("VerbatimChunk", "BlankLine*:a NonblankIndentedLine+:b { a.concat b }")
+ Rules[:_Verbatim] = rule_info("Verbatim", "VerbatimChunk+:a { RDoc::Markup::Verbatim.new(*a.flatten) }")
+ Rules[:_HorizontalRule] = rule_info("HorizontalRule", "NonindentSpace (\"*\" Sp \"*\" Sp \"*\" (Sp \"*\")* | \"-\" Sp \"-\" Sp \"-\" (Sp \"-\")* | \"_\" Sp \"_\" Sp \"_\" (Sp \"_\")*) Sp Newline BlankLine+ { RDoc::Markup::Rule.new 1 }")
+ Rules[:_Bullet] = rule_info("Bullet", "!HorizontalRule NonindentSpace (\"+\" | \"*\" | \"-\") Spacechar+")
+ Rules[:_BulletList] = rule_info("BulletList", "&Bullet (ListTight | ListLoose):a { RDoc::Markup::List.new(:BULLET, *a) }")
+ Rules[:_ListTight] = rule_info("ListTight", "ListItemTight+:a BlankLine* !(Bullet | Enumerator) { a }")
+ Rules[:_ListLoose] = rule_info("ListLoose", "StartList:a (ListItem:b BlankLine* { a << b })+ { a }")
+ Rules[:_ListItem] = rule_info("ListItem", "(Bullet | Enumerator) StartList:a ListBlock:b { a << b } (ListContinuationBlock:c { a.push(*c) })* { list_item_from a }")
+ Rules[:_ListItemTight] = rule_info("ListItemTight", "(Bullet | Enumerator) ListBlock:a (!BlankLine ListContinuationBlock:b { a.push(*b) })* !ListContinuationBlock { list_item_from a }")
+ Rules[:_ListBlock] = rule_info("ListBlock", "!BlankLine Line:a ListBlockLine*:c { [a, *c] }")
+ Rules[:_ListContinuationBlock] = rule_info("ListContinuationBlock", "StartList:a < BlankLine* > { a << \"\\n\" } (Indent ListBlock:b { a.concat b })+ { a }")
+ Rules[:_Enumerator] = rule_info("Enumerator", "NonindentSpace [0-9]+ \".\" Spacechar+")
+ Rules[:_OrderedList] = rule_info("OrderedList", "&Enumerator (ListTight | ListLoose):a { RDoc::Markup::List.new(:NUMBER, *a) }")
+ Rules[:_ListBlockLine] = rule_info("ListBlockLine", "!BlankLine !(Indent? (Bullet | Enumerator)) !HorizontalRule OptionallyIndentedLine")
+ Rules[:_HtmlBlockOpenAddress] = rule_info("HtmlBlockOpenAddress", "\"<\" Spnl (\"address\" | \"ADDRESS\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseAddress] = rule_info("HtmlBlockCloseAddress", "\"<\" Spnl \"/\" (\"address\" | \"ADDRESS\") Spnl \">\"")
+ Rules[:_HtmlBlockAddress] = rule_info("HtmlBlockAddress", "HtmlBlockOpenAddress (HtmlBlockAddress | !HtmlBlockCloseAddress .)* HtmlBlockCloseAddress")
+ Rules[:_HtmlBlockOpenBlockquote] = rule_info("HtmlBlockOpenBlockquote", "\"<\" Spnl (\"blockquote\" | \"BLOCKQUOTE\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseBlockquote] = rule_info("HtmlBlockCloseBlockquote", "\"<\" Spnl \"/\" (\"blockquote\" | \"BLOCKQUOTE\") Spnl \">\"")
+ Rules[:_HtmlBlockBlockquote] = rule_info("HtmlBlockBlockquote", "HtmlBlockOpenBlockquote (HtmlBlockBlockquote | !HtmlBlockCloseBlockquote .)* HtmlBlockCloseBlockquote")
+ Rules[:_HtmlBlockOpenCenter] = rule_info("HtmlBlockOpenCenter", "\"<\" Spnl (\"center\" | \"CENTER\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseCenter] = rule_info("HtmlBlockCloseCenter", "\"<\" Spnl \"/\" (\"center\" | \"CENTER\") Spnl \">\"")
+ Rules[:_HtmlBlockCenter] = rule_info("HtmlBlockCenter", "HtmlBlockOpenCenter (HtmlBlockCenter | !HtmlBlockCloseCenter .)* HtmlBlockCloseCenter")
+ Rules[:_HtmlBlockOpenDir] = rule_info("HtmlBlockOpenDir", "\"<\" Spnl (\"dir\" | \"DIR\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseDir] = rule_info("HtmlBlockCloseDir", "\"<\" Spnl \"/\" (\"dir\" | \"DIR\") Spnl \">\"")
+ Rules[:_HtmlBlockDir] = rule_info("HtmlBlockDir", "HtmlBlockOpenDir (HtmlBlockDir | !HtmlBlockCloseDir .)* HtmlBlockCloseDir")
+ Rules[:_HtmlBlockOpenDiv] = rule_info("HtmlBlockOpenDiv", "\"<\" Spnl (\"div\" | \"DIV\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseDiv] = rule_info("HtmlBlockCloseDiv", "\"<\" Spnl \"/\" (\"div\" | \"DIV\") Spnl \">\"")
+ Rules[:_HtmlBlockDiv] = rule_info("HtmlBlockDiv", "HtmlBlockOpenDiv (HtmlBlockDiv | !HtmlBlockCloseDiv .)* HtmlBlockCloseDiv")
+ Rules[:_HtmlBlockOpenDl] = rule_info("HtmlBlockOpenDl", "\"<\" Spnl (\"dl\" | \"DL\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseDl] = rule_info("HtmlBlockCloseDl", "\"<\" Spnl \"/\" (\"dl\" | \"DL\") Spnl \">\"")
+ Rules[:_HtmlBlockDl] = rule_info("HtmlBlockDl", "HtmlBlockOpenDl (HtmlBlockDl | !HtmlBlockCloseDl .)* HtmlBlockCloseDl")
+ Rules[:_HtmlBlockOpenFieldset] = rule_info("HtmlBlockOpenFieldset", "\"<\" Spnl (\"fieldset\" | \"FIELDSET\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseFieldset] = rule_info("HtmlBlockCloseFieldset", "\"<\" Spnl \"/\" (\"fieldset\" | \"FIELDSET\") Spnl \">\"")
+ Rules[:_HtmlBlockFieldset] = rule_info("HtmlBlockFieldset", "HtmlBlockOpenFieldset (HtmlBlockFieldset | !HtmlBlockCloseFieldset .)* HtmlBlockCloseFieldset")
+ Rules[:_HtmlBlockOpenForm] = rule_info("HtmlBlockOpenForm", "\"<\" Spnl (\"form\" | \"FORM\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseForm] = rule_info("HtmlBlockCloseForm", "\"<\" Spnl \"/\" (\"form\" | \"FORM\") Spnl \">\"")
+ Rules[:_HtmlBlockForm] = rule_info("HtmlBlockForm", "HtmlBlockOpenForm (HtmlBlockForm | !HtmlBlockCloseForm .)* HtmlBlockCloseForm")
+ Rules[:_HtmlBlockOpenH1] = rule_info("HtmlBlockOpenH1", "\"<\" Spnl (\"h1\" | \"H1\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseH1] = rule_info("HtmlBlockCloseH1", "\"<\" Spnl \"/\" (\"h1\" | \"H1\") Spnl \">\"")
+ Rules[:_HtmlBlockH1] = rule_info("HtmlBlockH1", "HtmlBlockOpenH1 (HtmlBlockH1 | !HtmlBlockCloseH1 .)* HtmlBlockCloseH1")
+ Rules[:_HtmlBlockOpenH2] = rule_info("HtmlBlockOpenH2", "\"<\" Spnl (\"h2\" | \"H2\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseH2] = rule_info("HtmlBlockCloseH2", "\"<\" Spnl \"/\" (\"h2\" | \"H2\") Spnl \">\"")
+ Rules[:_HtmlBlockH2] = rule_info("HtmlBlockH2", "HtmlBlockOpenH2 (HtmlBlockH2 | !HtmlBlockCloseH2 .)* HtmlBlockCloseH2")
+ Rules[:_HtmlBlockOpenH3] = rule_info("HtmlBlockOpenH3", "\"<\" Spnl (\"h3\" | \"H3\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseH3] = rule_info("HtmlBlockCloseH3", "\"<\" Spnl \"/\" (\"h3\" | \"H3\") Spnl \">\"")
+ Rules[:_HtmlBlockH3] = rule_info("HtmlBlockH3", "HtmlBlockOpenH3 (HtmlBlockH3 | !HtmlBlockCloseH3 .)* HtmlBlockCloseH3")
+ Rules[:_HtmlBlockOpenH4] = rule_info("HtmlBlockOpenH4", "\"<\" Spnl (\"h4\" | \"H4\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseH4] = rule_info("HtmlBlockCloseH4", "\"<\" Spnl \"/\" (\"h4\" | \"H4\") Spnl \">\"")
+ Rules[:_HtmlBlockH4] = rule_info("HtmlBlockH4", "HtmlBlockOpenH4 (HtmlBlockH4 | !HtmlBlockCloseH4 .)* HtmlBlockCloseH4")
+ Rules[:_HtmlBlockOpenH5] = rule_info("HtmlBlockOpenH5", "\"<\" Spnl (\"h5\" | \"H5\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseH5] = rule_info("HtmlBlockCloseH5", "\"<\" Spnl \"/\" (\"h5\" | \"H5\") Spnl \">\"")
+ Rules[:_HtmlBlockH5] = rule_info("HtmlBlockH5", "HtmlBlockOpenH5 (HtmlBlockH5 | !HtmlBlockCloseH5 .)* HtmlBlockCloseH5")
+ Rules[:_HtmlBlockOpenH6] = rule_info("HtmlBlockOpenH6", "\"<\" Spnl (\"h6\" | \"H6\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseH6] = rule_info("HtmlBlockCloseH6", "\"<\" Spnl \"/\" (\"h6\" | \"H6\") Spnl \">\"")
+ Rules[:_HtmlBlockH6] = rule_info("HtmlBlockH6", "HtmlBlockOpenH6 (HtmlBlockH6 | !HtmlBlockCloseH6 .)* HtmlBlockCloseH6")
+ Rules[:_HtmlBlockOpenMenu] = rule_info("HtmlBlockOpenMenu", "\"<\" Spnl (\"menu\" | \"MENU\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseMenu] = rule_info("HtmlBlockCloseMenu", "\"<\" Spnl \"/\" (\"menu\" | \"MENU\") Spnl \">\"")
+ Rules[:_HtmlBlockMenu] = rule_info("HtmlBlockMenu", "HtmlBlockOpenMenu (HtmlBlockMenu | !HtmlBlockCloseMenu .)* HtmlBlockCloseMenu")
+ Rules[:_HtmlBlockOpenNoframes] = rule_info("HtmlBlockOpenNoframes", "\"<\" Spnl (\"noframes\" | \"NOFRAMES\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseNoframes] = rule_info("HtmlBlockCloseNoframes", "\"<\" Spnl \"/\" (\"noframes\" | \"NOFRAMES\") Spnl \">\"")
+ Rules[:_HtmlBlockNoframes] = rule_info("HtmlBlockNoframes", "HtmlBlockOpenNoframes (HtmlBlockNoframes | !HtmlBlockCloseNoframes .)* HtmlBlockCloseNoframes")
+ Rules[:_HtmlBlockOpenNoscript] = rule_info("HtmlBlockOpenNoscript", "\"<\" Spnl (\"noscript\" | \"NOSCRIPT\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseNoscript] = rule_info("HtmlBlockCloseNoscript", "\"<\" Spnl \"/\" (\"noscript\" | \"NOSCRIPT\") Spnl \">\"")
+ Rules[:_HtmlBlockNoscript] = rule_info("HtmlBlockNoscript", "HtmlBlockOpenNoscript (HtmlBlockNoscript | !HtmlBlockCloseNoscript .)* HtmlBlockCloseNoscript")
+ Rules[:_HtmlBlockOpenOl] = rule_info("HtmlBlockOpenOl", "\"<\" Spnl (\"ol\" | \"OL\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseOl] = rule_info("HtmlBlockCloseOl", "\"<\" Spnl \"/\" (\"ol\" | \"OL\") Spnl \">\"")
+ Rules[:_HtmlBlockOl] = rule_info("HtmlBlockOl", "HtmlBlockOpenOl (HtmlBlockOl | !HtmlBlockCloseOl .)* HtmlBlockCloseOl")
+ Rules[:_HtmlBlockOpenP] = rule_info("HtmlBlockOpenP", "\"<\" Spnl (\"p\" | \"P\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseP] = rule_info("HtmlBlockCloseP", "\"<\" Spnl \"/\" (\"p\" | \"P\") Spnl \">\"")
+ Rules[:_HtmlBlockP] = rule_info("HtmlBlockP", "HtmlBlockOpenP (HtmlBlockP | !HtmlBlockCloseP .)* HtmlBlockCloseP")
+ Rules[:_HtmlBlockOpenPre] = rule_info("HtmlBlockOpenPre", "\"<\" Spnl (\"pre\" | \"PRE\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockClosePre] = rule_info("HtmlBlockClosePre", "\"<\" Spnl \"/\" (\"pre\" | \"PRE\") Spnl \">\"")
+ Rules[:_HtmlBlockPre] = rule_info("HtmlBlockPre", "HtmlBlockOpenPre (HtmlBlockPre | !HtmlBlockClosePre .)* HtmlBlockClosePre")
+ Rules[:_HtmlBlockOpenTable] = rule_info("HtmlBlockOpenTable", "\"<\" Spnl (\"table\" | \"TABLE\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseTable] = rule_info("HtmlBlockCloseTable", "\"<\" Spnl \"/\" (\"table\" | \"TABLE\") Spnl \">\"")
+ Rules[:_HtmlBlockTable] = rule_info("HtmlBlockTable", "HtmlBlockOpenTable (HtmlBlockTable | !HtmlBlockCloseTable .)* HtmlBlockCloseTable")
+ Rules[:_HtmlBlockOpenUl] = rule_info("HtmlBlockOpenUl", "\"<\" Spnl (\"ul\" | \"UL\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseUl] = rule_info("HtmlBlockCloseUl", "\"<\" Spnl \"/\" (\"ul\" | \"UL\") Spnl \">\"")
+ Rules[:_HtmlBlockUl] = rule_info("HtmlBlockUl", "HtmlBlockOpenUl (HtmlBlockUl | !HtmlBlockCloseUl .)* HtmlBlockCloseUl")
+ Rules[:_HtmlBlockOpenDd] = rule_info("HtmlBlockOpenDd", "\"<\" Spnl (\"dd\" | \"DD\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseDd] = rule_info("HtmlBlockCloseDd", "\"<\" Spnl \"/\" (\"dd\" | \"DD\") Spnl \">\"")
+ Rules[:_HtmlBlockDd] = rule_info("HtmlBlockDd", "HtmlBlockOpenDd (HtmlBlockDd | !HtmlBlockCloseDd .)* HtmlBlockCloseDd")
+ Rules[:_HtmlBlockOpenDt] = rule_info("HtmlBlockOpenDt", "\"<\" Spnl (\"dt\" | \"DT\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseDt] = rule_info("HtmlBlockCloseDt", "\"<\" Spnl \"/\" (\"dt\" | \"DT\") Spnl \">\"")
+ Rules[:_HtmlBlockDt] = rule_info("HtmlBlockDt", "HtmlBlockOpenDt (HtmlBlockDt | !HtmlBlockCloseDt .)* HtmlBlockCloseDt")
+ Rules[:_HtmlBlockOpenFrameset] = rule_info("HtmlBlockOpenFrameset", "\"<\" Spnl (\"frameset\" | \"FRAMESET\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseFrameset] = rule_info("HtmlBlockCloseFrameset", "\"<\" Spnl \"/\" (\"frameset\" | \"FRAMESET\") Spnl \">\"")
+ Rules[:_HtmlBlockFrameset] = rule_info("HtmlBlockFrameset", "HtmlBlockOpenFrameset (HtmlBlockFrameset | !HtmlBlockCloseFrameset .)* HtmlBlockCloseFrameset")
+ Rules[:_HtmlBlockOpenLi] = rule_info("HtmlBlockOpenLi", "\"<\" Spnl (\"li\" | \"LI\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseLi] = rule_info("HtmlBlockCloseLi", "\"<\" Spnl \"/\" (\"li\" | \"LI\") Spnl \">\"")
+ Rules[:_HtmlBlockLi] = rule_info("HtmlBlockLi", "HtmlBlockOpenLi (HtmlBlockLi | !HtmlBlockCloseLi .)* HtmlBlockCloseLi")
+ Rules[:_HtmlBlockOpenTbody] = rule_info("HtmlBlockOpenTbody", "\"<\" Spnl (\"tbody\" | \"TBODY\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseTbody] = rule_info("HtmlBlockCloseTbody", "\"<\" Spnl \"/\" (\"tbody\" | \"TBODY\") Spnl \">\"")
+ Rules[:_HtmlBlockTbody] = rule_info("HtmlBlockTbody", "HtmlBlockOpenTbody (HtmlBlockTbody | !HtmlBlockCloseTbody .)* HtmlBlockCloseTbody")
+ Rules[:_HtmlBlockOpenTd] = rule_info("HtmlBlockOpenTd", "\"<\" Spnl (\"td\" | \"TD\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseTd] = rule_info("HtmlBlockCloseTd", "\"<\" Spnl \"/\" (\"td\" | \"TD\") Spnl \">\"")
+ Rules[:_HtmlBlockTd] = rule_info("HtmlBlockTd", "HtmlBlockOpenTd (HtmlBlockTd | !HtmlBlockCloseTd .)* HtmlBlockCloseTd")
+ Rules[:_HtmlBlockOpenTfoot] = rule_info("HtmlBlockOpenTfoot", "\"<\" Spnl (\"tfoot\" | \"TFOOT\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseTfoot] = rule_info("HtmlBlockCloseTfoot", "\"<\" Spnl \"/\" (\"tfoot\" | \"TFOOT\") Spnl \">\"")
+ Rules[:_HtmlBlockTfoot] = rule_info("HtmlBlockTfoot", "HtmlBlockOpenTfoot (HtmlBlockTfoot | !HtmlBlockCloseTfoot .)* HtmlBlockCloseTfoot")
+ Rules[:_HtmlBlockOpenTh] = rule_info("HtmlBlockOpenTh", "\"<\" Spnl (\"th\" | \"TH\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseTh] = rule_info("HtmlBlockCloseTh", "\"<\" Spnl \"/\" (\"th\" | \"TH\") Spnl \">\"")
+ Rules[:_HtmlBlockTh] = rule_info("HtmlBlockTh", "HtmlBlockOpenTh (HtmlBlockTh | !HtmlBlockCloseTh .)* HtmlBlockCloseTh")
+ Rules[:_HtmlBlockOpenThead] = rule_info("HtmlBlockOpenThead", "\"<\" Spnl (\"thead\" | \"THEAD\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseThead] = rule_info("HtmlBlockCloseThead", "\"<\" Spnl \"/\" (\"thead\" | \"THEAD\") Spnl \">\"")
+ Rules[:_HtmlBlockThead] = rule_info("HtmlBlockThead", "HtmlBlockOpenThead (HtmlBlockThead | !HtmlBlockCloseThead .)* HtmlBlockCloseThead")
+ Rules[:_HtmlBlockOpenTr] = rule_info("HtmlBlockOpenTr", "\"<\" Spnl (\"tr\" | \"TR\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseTr] = rule_info("HtmlBlockCloseTr", "\"<\" Spnl \"/\" (\"tr\" | \"TR\") Spnl \">\"")
+ Rules[:_HtmlBlockTr] = rule_info("HtmlBlockTr", "HtmlBlockOpenTr (HtmlBlockTr | !HtmlBlockCloseTr .)* HtmlBlockCloseTr")
+ Rules[:_HtmlBlockOpenScript] = rule_info("HtmlBlockOpenScript", "\"<\" Spnl (\"script\" | \"SCRIPT\") Spnl HtmlAttribute* \">\"")
+ Rules[:_HtmlBlockCloseScript] = rule_info("HtmlBlockCloseScript", "\"<\" Spnl \"/\" (\"script\" | \"SCRIPT\") Spnl \">\"")
+ Rules[:_HtmlBlockScript] = rule_info("HtmlBlockScript", "HtmlBlockOpenScript (!HtmlBlockCloseScript .)* HtmlBlockCloseScript")
+ Rules[:_HtmlBlockInTags] = rule_info("HtmlBlockInTags", "(HtmlBlockAddress | HtmlBlockBlockquote | HtmlBlockCenter | HtmlBlockDir | HtmlBlockDiv | HtmlBlockDl | HtmlBlockFieldset | HtmlBlockForm | HtmlBlockH1 | HtmlBlockH2 | HtmlBlockH3 | HtmlBlockH4 | HtmlBlockH5 | HtmlBlockH6 | HtmlBlockMenu | HtmlBlockNoframes | HtmlBlockNoscript | HtmlBlockOl | HtmlBlockP | HtmlBlockPre | HtmlBlockTable | HtmlBlockUl | HtmlBlockDd | HtmlBlockDt | HtmlBlockFrameset | HtmlBlockLi | HtmlBlockTbody | HtmlBlockTd | HtmlBlockTfoot | HtmlBlockTh | HtmlBlockThead | HtmlBlockTr | HtmlBlockScript)")
+ Rules[:_HtmlBlock] = rule_info("HtmlBlock", "< (HtmlBlockInTags | HtmlComment | HtmlBlockSelfClosing | HtmlUnclosed) > BlankLine+ { if html? then RDoc::Markup::Raw.new text end }")
+ Rules[:_HtmlUnclosed] = rule_info("HtmlUnclosed", "\"<\" Spnl HtmlUnclosedType Spnl HtmlAttribute* Spnl \">\"")
+ Rules[:_HtmlUnclosedType] = rule_info("HtmlUnclosedType", "(\"HR\" | \"hr\")")
+ Rules[:_HtmlBlockSelfClosing] = rule_info("HtmlBlockSelfClosing", "\"<\" Spnl HtmlBlockType Spnl HtmlAttribute* \"/\" Spnl \">\"")
+ Rules[:_HtmlBlockType] = rule_info("HtmlBlockType", "(\"ADDRESS\" | \"BLOCKQUOTE\" | \"CENTER\" | \"DD\" | \"DIR\" | \"DIV\" | \"DL\" | \"DT\" | \"FIELDSET\" | \"FORM\" | \"FRAMESET\" | \"H1\" | \"H2\" | \"H3\" | \"H4\" | \"H5\" | \"H6\" | \"HR\" | \"ISINDEX\" | \"LI\" | \"MENU\" | \"NOFRAMES\" | \"NOSCRIPT\" | \"OL\" | \"P\" | \"PRE\" | \"SCRIPT\" | \"TABLE\" | \"TBODY\" | \"TD\" | \"TFOOT\" | \"TH\" | \"THEAD\" | \"TR\" | \"UL\" | \"address\" | \"blockquote\" | \"center\" | \"dd\" | \"dir\" | \"div\" | \"dl\" | \"dt\" | \"fieldset\" | \"form\" | \"frameset\" | \"h1\" | \"h2\" | \"h3\" | \"h4\" | \"h5\" | \"h6\" | \"hr\" | \"isindex\" | \"li\" | \"menu\" | \"noframes\" | \"noscript\" | \"ol\" | \"p\" | \"pre\" | \"script\" | \"table\" | \"tbody\" | \"td\" | \"tfoot\" | \"th\" | \"thead\" | \"tr\" | \"ul\")")
+ Rules[:_StyleOpen] = rule_info("StyleOpen", "\"<\" Spnl (\"style\" | \"STYLE\") Spnl HtmlAttribute* \">\"")
+ Rules[:_StyleClose] = rule_info("StyleClose", "\"<\" Spnl \"/\" (\"style\" | \"STYLE\") Spnl \">\"")
+ Rules[:_InStyleTags] = rule_info("InStyleTags", "StyleOpen (!StyleClose .)* StyleClose")
+ Rules[:_StyleBlock] = rule_info("StyleBlock", "< InStyleTags > BlankLine* { if css? then RDoc::Markup::Raw.new text end }")
+ Rules[:_Inlines] = rule_info("Inlines", "(!Endline Inline:i { i } | Endline:c &Inline { c })+:chunks Endline? { chunks }")
+ Rules[:_Inline] = rule_info("Inline", "(Str | Endline | UlOrStarLine | Space | Strong | Emph | Image | Link | NoteReference | InlineNote | Code | RawHtml | Entity | EscapedChar | Symbol)")
+ Rules[:_Space] = rule_info("Space", "Spacechar+ { \" \" }")
+ Rules[:_Str] = rule_info("Str", "StartList:a < NormalChar+ > { a = text } (StrChunk:c { a << c })* { a }")
+ Rules[:_StrChunk] = rule_info("StrChunk", "< (NormalChar | \"_\"+ &Alphanumeric)+ > { text }")
+ Rules[:_EscapedChar] = rule_info("EscapedChar", "\"\\\\\" !Newline < /[:\\\\`|*_{}\\[\\]()\#+.!><-]/ > { text }")
+ Rules[:_Entity] = rule_info("Entity", "(HexEntity | DecEntity | CharEntity):a { a }")
+ Rules[:_Endline] = rule_info("Endline", "(LineBreak | TerminalEndline | NormalEndline)")
+ Rules[:_NormalEndline] = rule_info("NormalEndline", "Sp Newline !BlankLine !\">\" !AtxStart !(Line (\"===\" \"=\"* | \"---\" \"-\"*) Newline) { \"\\n\" }")
+ Rules[:_TerminalEndline] = rule_info("TerminalEndline", "Sp Newline Eof")
+ Rules[:_LineBreak] = rule_info("LineBreak", "< \" \" NormalEndline > { RDoc::Markup::HardBreak.new }")
+ Rules[:_Symbol] = rule_info("Symbol", "< SpecialChar > { text }")
+ Rules[:_UlOrStarLine] = rule_info("UlOrStarLine", "(UlLine | StarLine):a { a }")
+ Rules[:_StarLine] = rule_info("StarLine", "(< \"****\" \"*\"* > { text } | < Spacechar \"*\"+ &Spacechar > { text })")
+ Rules[:_UlLine] = rule_info("UlLine", "(< \"____\" \"_\"* > { text } | < Spacechar \"_\"+ &Spacechar > { text })")
+ Rules[:_Emph] = rule_info("Emph", "(EmphStar | EmphUl)")
+ Rules[:_OneStarOpen] = rule_info("OneStarOpen", "!StarLine \"*\" !Spacechar !Newline")
+ Rules[:_OneStarClose] = rule_info("OneStarClose", "!Spacechar !Newline Inline:a \"*\" { a }")
+ Rules[:_EmphStar] = rule_info("EmphStar", "OneStarOpen StartList:a (!OneStarClose Inline:l { a << l })* OneStarClose:l { a << l } { emphasis a.join }")
+ Rules[:_OneUlOpen] = rule_info("OneUlOpen", "!UlLine \"_\" !Spacechar !Newline")
+ Rules[:_OneUlClose] = rule_info("OneUlClose", "!Spacechar !Newline Inline:a \"_\" { a }")
+ Rules[:_EmphUl] = rule_info("EmphUl", "OneUlOpen StartList:a (!OneUlClose Inline:l { a << l })* OneUlClose:l { a << l } { emphasis a.join }")
+ Rules[:_Strong] = rule_info("Strong", "(StrongStar | StrongUl)")
+ Rules[:_TwoStarOpen] = rule_info("TwoStarOpen", "!StarLine \"**\" !Spacechar !Newline")
+ Rules[:_TwoStarClose] = rule_info("TwoStarClose", "!Spacechar !Newline Inline:a \"**\" { a }")
+ Rules[:_StrongStar] = rule_info("StrongStar", "TwoStarOpen StartList:a (!TwoStarClose Inline:l { a << l })* TwoStarClose:l { a << l } { strong a.join }")
+ Rules[:_TwoUlOpen] = rule_info("TwoUlOpen", "!UlLine \"__\" !Spacechar !Newline")
+ Rules[:_TwoUlClose] = rule_info("TwoUlClose", "!Spacechar !Newline Inline:a \"__\" { a }")
+ Rules[:_StrongUl] = rule_info("StrongUl", "TwoUlOpen StartList:a (!TwoUlClose Inline:i { a << i })* TwoUlClose:l { a << l } { strong a.join }")
+ Rules[:_Image] = rule_info("Image", "\"!\" (ExplicitLink | ReferenceLink):a { a }")
+ Rules[:_Link] = rule_info("Link", "(ExplicitLink | ReferenceLink | AutoLink)")
+ Rules[:_ReferenceLink] = rule_info("ReferenceLink", "(ReferenceLinkDouble | ReferenceLinkSingle)")
+ Rules[:_ReferenceLinkDouble] = rule_info("ReferenceLinkDouble", "Label:content < Spnl > !\"[]\" Label:label { link_to content, label, text }")
+ Rules[:_ReferenceLinkSingle] = rule_info("ReferenceLinkSingle", "Label:content < (Spnl \"[]\")? > { link_to content, content, text }")
+ Rules[:_ExplicitLink] = rule_info("ExplicitLink", "Label:l Spnl \"(\" Sp Source:s Spnl Title:t Sp \")\" { \"{\#{l}}[\#{s}]\" }")
+ Rules[:_Source] = rule_info("Source", "(\"<\" < SourceContents > \">\" | < SourceContents >) { text }")
+ Rules[:_SourceContents] = rule_info("SourceContents", "(((!\"(\" !\")\" !\">\" Nonspacechar)+ | \"(\" SourceContents \")\")* | \"\")")
+ Rules[:_Title] = rule_info("Title", "(TitleSingle | TitleDouble | < \"\" >):a { a }")
+ Rules[:_TitleSingle] = rule_info("TitleSingle", "\"'\" < (!(\"'\" Sp (\")\" | Newline)) .)* > \"'\"")
+ Rules[:_TitleDouble] = rule_info("TitleDouble", "\"\\\"\" < (!(\"\\\"\" Sp (\")\" | Newline)) .)* > \"\\\"\"")
+ Rules[:_AutoLink] = rule_info("AutoLink", "(AutoLinkUrl | AutoLinkEmail)")
+ Rules[:_AutoLinkUrl] = rule_info("AutoLinkUrl", "\"<\" < /[A-Za-z]+/ \"://\" (!Newline !\">\" .)+ > \">\" { text }")
+ Rules[:_AutoLinkEmail] = rule_info("AutoLinkEmail", "\"<\" \"mailto:\"? < /[\\w+_.\\/!%~$-]+/i \"@\" (!Newline !\">\" .)+ > \">\" { \"mailto:\#{text}\" }")
+ Rules[:_Reference] = rule_info("Reference", "NonindentSpace !\"[]\" Label:label \":\" Spnl RefSrc:link RefTitle:title BlankLine+ { \# TODO use title reference label, link nil }")
+ Rules[:_Label] = rule_info("Label", "\"[\" (!\"^\" &{ notes? } | &. &{ !notes? }) StartList:a (!\"]\" Inline:l { a << l })* \"]\" { a.join.gsub(/\\s+/, ' ') }")
+ Rules[:_RefSrc] = rule_info("RefSrc", "< Nonspacechar+ > { text }")
+ Rules[:_RefTitle] = rule_info("RefTitle", "(RefTitleSingle | RefTitleDouble | RefTitleParens | EmptyTitle)")
+ Rules[:_EmptyTitle] = rule_info("EmptyTitle", "< \"\" >")
+ Rules[:_RefTitleSingle] = rule_info("RefTitleSingle", "Spnl \"'\" < (!(\"'\" Sp Newline | Newline) .)* > \"'\" { text }")
+ Rules[:_RefTitleDouble] = rule_info("RefTitleDouble", "Spnl \"\\\"\" < (!(\"\\\"\" Sp Newline | Newline) .)* > \"\\\"\" { text }")
+ Rules[:_RefTitleParens] = rule_info("RefTitleParens", "Spnl \"(\" < (!(\")\" Sp Newline | Newline) .)* > \")\" { text }")
+ Rules[:_References] = rule_info("References", "(Reference | SkipBlock)*")
+ Rules[:_Ticks1] = rule_info("Ticks1", "\"`\" !\"`\"")
+ Rules[:_Ticks2] = rule_info("Ticks2", "\"``\" !\"`\"")
+ Rules[:_Ticks3] = rule_info("Ticks3", "\"```\" !\"`\"")
+ Rules[:_Ticks4] = rule_info("Ticks4", "\"````\" !\"`\"")
+ Rules[:_Ticks5] = rule_info("Ticks5", "\"`````\" !\"`\"")
+ Rules[:_Code] = rule_info("Code", "(Ticks1 Sp < ((!\"`\" Nonspacechar)+ | !Ticks1 \"`\"+ | !(Sp Ticks1) (Spacechar | Newline !BlankLine))+ > Sp Ticks1 | Ticks2 Sp < ((!\"`\" Nonspacechar)+ | !Ticks2 \"`\"+ | !(Sp Ticks2) (Spacechar | Newline !BlankLine))+ > Sp Ticks2 | Ticks3 Sp < ((!\"`\" Nonspacechar)+ | !Ticks3 \"`\"+ | !(Sp Ticks3) (Spacechar | Newline !BlankLine))+ > Sp Ticks3 | Ticks4 Sp < ((!\"`\" Nonspacechar)+ | !Ticks4 \"`\"+ | !(Sp Ticks4) (Spacechar | Newline !BlankLine))+ > Sp Ticks4 | Ticks5 Sp < ((!\"`\" Nonspacechar)+ | !Ticks5 \"`\"+ | !(Sp Ticks5) (Spacechar | Newline !BlankLine))+ > Sp Ticks5) { \"<code>\#{text}</code>\" }")
+ Rules[:_RawHtml] = rule_info("RawHtml", "< (HtmlComment | HtmlBlockScript | HtmlTag) > { if html? then text else '' end }")
+ Rules[:_BlankLine] = rule_info("BlankLine", "Sp Newline { \"\\n\" }")
+ Rules[:_Quoted] = rule_info("Quoted", "(\"\\\"\" (!\"\\\"\" .)* \"\\\"\" | \"'\" (!\"'\" .)* \"'\")")
+ Rules[:_HtmlAttribute] = rule_info("HtmlAttribute", "(AlphanumericAscii | \"-\")+ Spnl (\"=\" Spnl (Quoted | (!\">\" Nonspacechar)+))? Spnl")
+ Rules[:_HtmlComment] = rule_info("HtmlComment", "\"<!--\" (!\"-->\" .)* \"-->\"")
+ Rules[:_HtmlTag] = rule_info("HtmlTag", "\"<\" Spnl \"/\"? AlphanumericAscii+ Spnl HtmlAttribute* \"/\"? Spnl \">\"")
+ Rules[:_Eof] = rule_info("Eof", "!.")
+ Rules[:_Nonspacechar] = rule_info("Nonspacechar", "!Spacechar !Newline .")
+ Rules[:_Sp] = rule_info("Sp", "Spacechar*")
+ Rules[:_Spnl] = rule_info("Spnl", "Sp (Newline Sp)?")
+ Rules[:_SpecialChar] = rule_info("SpecialChar", "(\"*\" | \"_\" | \"`\" | \"&\" | \"[\" | \"]\" | \"(\" | \")\" | \"<\" | \"!\" | \"\#\" | \"\\\\\" | \"'\" | \"\\\"\" | ExtendedSpecialChar)")
+ Rules[:_NormalChar] = rule_info("NormalChar", "!(SpecialChar | Spacechar | Newline) .")
+ Rules[:_Digit] = rule_info("Digit", "[0-9]")
+ Rules[:_Alphanumeric] = rule_info("Alphanumeric", "%literals.Alphanumeric")
+ Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "%literals.AlphanumericAscii")
+ Rules[:_BOM] = rule_info("BOM", "%literals.BOM")
+ Rules[:_Newline] = rule_info("Newline", "%literals.Newline")
+ Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "%literals.NonAlphanumeric")
+ Rules[:_Spacechar] = rule_info("Spacechar", "%literals.Spacechar")
+ Rules[:_HexEntity] = rule_info("HexEntity", "\"&\" \"\#\" /[Xx]/ < /[0-9a-fA-F]+/ > \";\" { [text.to_i(16)].pack 'U' }")
+ Rules[:_DecEntity] = rule_info("DecEntity", "\"&\" \"\#\" < /[0-9]+/ > \";\" { [text.to_i].pack 'U' }")
+ Rules[:_CharEntity] = rule_info("CharEntity", "\"&\" < /[A-Za-z0-9]+/ > \";\" { if entity = HTML_ENTITIES[text] then entity.pack 'U*' else \"&\#{text};\" end }")
+ Rules[:_NonindentSpace] = rule_info("NonindentSpace", "(\" \" | \" \" | \" \" | \"\")")
+ Rules[:_Indent] = rule_info("Indent", "(\"\\t\" | \" \")")
+ Rules[:_IndentedLine] = rule_info("IndentedLine", "Indent Line")
+ Rules[:_OptionallyIndentedLine] = rule_info("OptionallyIndentedLine", "Indent? Line")
+ Rules[:_StartList] = rule_info("StartList", "&. { [] }")
+ Rules[:_Line] = rule_info("Line", "RawLine:a { a }")
+ Rules[:_RawLine] = rule_info("RawLine", "(< (!\" \" !\"\\n\" .)* Newline > | < .+ > Eof) { text }")
+ Rules[:_SkipBlock] = rule_info("SkipBlock", "(HtmlBlock | (!\"\#\" !SetextBottom1 !SetextBottom2 !BlankLine RawLine)+ BlankLine* | BlankLine+ | RawLine)")
+ Rules[:_ExtendedSpecialChar] = rule_info("ExtendedSpecialChar", "&{ notes? } \"^\"")
+ Rules[:_NoteReference] = rule_info("NoteReference", "&{ notes? } RawNoteReference:ref { note_for ref }")
+ Rules[:_RawNoteReference] = rule_info("RawNoteReference", "\"[^\" < (!Newline !\"]\" .)+ > \"]\" { text }")
+ Rules[:_Note] = rule_info("Note", "&{ notes? } NonindentSpace RawNoteReference:ref \":\" Sp StartList:a RawNoteBlock:l (&Indent RawNoteBlock:i { a.concat i })* { @footnotes[ref] = paragraph a nil }")
+ Rules[:_InlineNote] = rule_info("InlineNote", "&{ notes? } \"^[\" StartList:a (!\"]\" Inline:l { a << l })+ \"]\" { ref = [:inline, @note_order.length] @footnotes[ref] = paragraph a note_for ref }")
+ Rules[:_Notes] = rule_info("Notes", "(Note | SkipBlock)*")
+ Rules[:_RawNoteBlock] = rule_info("RawNoteBlock", "StartList:a (!BlankLine OptionallyIndentedLine:l { a << l })+ < BlankLine* > { a << text } { a }")
+ Rules[:_CodeFence] = rule_info("CodeFence", "&{ github? } Ticks3 (Sp StrChunk:format)? Spnl < ((!\"`\" Nonspacechar)+ | !Ticks3 \"`\"+ | Spacechar | Newline)+ > Ticks3 Sp Newline* { verbatim = RDoc::Markup::Verbatim.new text verbatim.format = format.intern if format verbatim }")
+ Rules[:_DefinitionList] = rule_info("DefinitionList", "&{ definition_lists? } DefinitionListItem+:list { RDoc::Markup::List.new :NOTE, *list.flatten }")
+ Rules[:_DefinitionListItem] = rule_info("DefinitionListItem", "DefinitionListLabel+:label DefinitionListDefinition+:defn { list_items = [] list_items << RDoc::Markup::ListItem.new(label, defn.shift) list_items.concat defn.map { |defn| RDoc::Markup::ListItem.new nil, defn } unless list_items.empty? list_items }")
+ Rules[:_DefinitionListLabel] = rule_info("DefinitionListLabel", "StrChunk:label Sp Newline { label }")
+ Rules[:_DefinitionListDefinition] = rule_info("DefinitionListDefinition", "NonindentSpace \":\" Space Inlines:a BlankLine+ { paragraph a }")
+ # :startdoc:
+end
diff --git a/lib/rdoc/markdown/entities.rb b/lib/rdoc/markdown/entities.rb
new file mode 100644
index 0000000000..2b45f20d37
--- /dev/null
+++ b/lib/rdoc/markdown/entities.rb
@@ -0,0 +1,2128 @@
+RDoc::Markdown::HTML_ENTITIES = {
+ "AElig" => [0x000C6],
+ "AMP" => [0x00026],
+ "Aacute" => [0x000C1],
+ "Abreve" => [0x00102],
+ "Acirc" => [0x000C2],
+ "Acy" => [0x00410],
+ "Afr" => [0x1D504],
+ "Agrave" => [0x000C0],
+ "Alpha" => [0x00391],
+ "Amacr" => [0x00100],
+ "And" => [0x02A53],
+ "Aogon" => [0x00104],
+ "Aopf" => [0x1D538],
+ "ApplyFunction" => [0x02061],
+ "Aring" => [0x000C5],
+ "Ascr" => [0x1D49C],
+ "Assign" => [0x02254],
+ "Atilde" => [0x000C3],
+ "Auml" => [0x000C4],
+ "Backslash" => [0x02216],
+ "Barv" => [0x02AE7],
+ "Barwed" => [0x02306],
+ "Bcy" => [0x00411],
+ "Because" => [0x02235],
+ "Bernoullis" => [0x0212C],
+ "Beta" => [0x00392],
+ "Bfr" => [0x1D505],
+ "Bopf" => [0x1D539],
+ "Breve" => [0x002D8],
+ "Bscr" => [0x0212C],
+ "Bumpeq" => [0x0224E],
+ "CHcy" => [0x00427],
+ "COPY" => [0x000A9],
+ "Cacute" => [0x00106],
+ "Cap" => [0x022D2],
+ "CapitalDifferentialD" => [0x02145],
+ "Cayleys" => [0x0212D],
+ "Ccaron" => [0x0010C],
+ "Ccedil" => [0x000C7],
+ "Ccirc" => [0x00108],
+ "Cconint" => [0x02230],
+ "Cdot" => [0x0010A],
+ "Cedilla" => [0x000B8],
+ "CenterDot" => [0x000B7],
+ "Cfr" => [0x0212D],
+ "Chi" => [0x003A7],
+ "CircleDot" => [0x02299],
+ "CircleMinus" => [0x02296],
+ "CirclePlus" => [0x02295],
+ "CircleTimes" => [0x02297],
+ "ClockwiseContourIntegral" => [0x02232],
+ "CloseCurlyDoubleQuote" => [0x0201D],
+ "CloseCurlyQuote" => [0x02019],
+ "Colon" => [0x02237],
+ "Colone" => [0x02A74],
+ "Congruent" => [0x02261],
+ "Conint" => [0x0222F],
+ "ContourIntegral" => [0x0222E],
+ "Copf" => [0x02102],
+ "Coproduct" => [0x02210],
+ "CounterClockwiseContourIntegral" => [0x02233],
+ "Cross" => [0x02A2F],
+ "Cscr" => [0x1D49E],
+ "Cup" => [0x022D3],
+ "CupCap" => [0x0224D],
+ "DD" => [0x02145],
+ "DDotrahd" => [0x02911],
+ "DJcy" => [0x00402],
+ "DScy" => [0x00405],
+ "DZcy" => [0x0040F],
+ "Dagger" => [0x02021],
+ "Darr" => [0x021A1],
+ "Dashv" => [0x02AE4],
+ "Dcaron" => [0x0010E],
+ "Dcy" => [0x00414],
+ "Del" => [0x02207],
+ "Delta" => [0x00394],
+ "Dfr" => [0x1D507],
+ "DiacriticalAcute" => [0x000B4],
+ "DiacriticalDot" => [0x002D9],
+ "DiacriticalDoubleAcute" => [0x002DD],
+ "DiacriticalGrave" => [0x00060],
+ "DiacriticalTilde" => [0x002DC],
+ "Diamond" => [0x022C4],
+ "DifferentialD" => [0x02146],
+ "Dopf" => [0x1D53B],
+ "Dot" => [0x000A8],
+ "DotDot" => [0x020DC],
+ "DotEqual" => [0x02250],
+ "DoubleContourIntegral" => [0x0222F],
+ "DoubleDot" => [0x000A8],
+ "DoubleDownArrow" => [0x021D3],
+ "DoubleLeftArrow" => [0x021D0],
+ "DoubleLeftRightArrow" => [0x021D4],
+ "DoubleLeftTee" => [0x02AE4],
+ "DoubleLongLeftArrow" => [0x027F8],
+ "DoubleLongLeftRightArrow" => [0x027FA],
+ "DoubleLongRightArrow" => [0x027F9],
+ "DoubleRightArrow" => [0x021D2],
+ "DoubleRightTee" => [0x022A8],
+ "DoubleUpArrow" => [0x021D1],
+ "DoubleUpDownArrow" => [0x021D5],
+ "DoubleVerticalBar" => [0x02225],
+ "DownArrow" => [0x02193],
+ "DownArrowBar" => [0x02913],
+ "DownArrowUpArrow" => [0x021F5],
+ "DownBreve" => [0x00311],
+ "DownLeftRightVector" => [0x02950],
+ "DownLeftTeeVector" => [0x0295E],
+ "DownLeftVector" => [0x021BD],
+ "DownLeftVectorBar" => [0x02956],
+ "DownRightTeeVector" => [0x0295F],
+ "DownRightVector" => [0x021C1],
+ "DownRightVectorBar" => [0x02957],
+ "DownTee" => [0x022A4],
+ "DownTeeArrow" => [0x021A7],
+ "Downarrow" => [0x021D3],
+ "Dscr" => [0x1D49F],
+ "Dstrok" => [0x00110],
+ "ENG" => [0x0014A],
+ "ETH" => [0x000D0],
+ "Eacute" => [0x000C9],
+ "Ecaron" => [0x0011A],
+ "Ecirc" => [0x000CA],
+ "Ecy" => [0x0042D],
+ "Edot" => [0x00116],
+ "Efr" => [0x1D508],
+ "Egrave" => [0x000C8],
+ "Element" => [0x02208],
+ "Emacr" => [0x00112],
+ "EmptySmallSquare" => [0x025FB],
+ "EmptyVerySmallSquare" => [0x025AB],
+ "Eogon" => [0x00118],
+ "Eopf" => [0x1D53C],
+ "Epsilon" => [0x00395],
+ "Equal" => [0x02A75],
+ "EqualTilde" => [0x02242],
+ "Equilibrium" => [0x021CC],
+ "Escr" => [0x02130],
+ "Esim" => [0x02A73],
+ "Eta" => [0x00397],
+ "Euml" => [0x000CB],
+ "Exists" => [0x02203],
+ "ExponentialE" => [0x02147],
+ "Fcy" => [0x00424],
+ "Ffr" => [0x1D509],
+ "FilledSmallSquare" => [0x025FC],
+ "FilledVerySmallSquare" => [0x025AA],
+ "Fopf" => [0x1D53D],
+ "ForAll" => [0x02200],
+ "Fouriertrf" => [0x02131],
+ "Fscr" => [0x02131],
+ "GJcy" => [0x00403],
+ "GT" => [0x0003E],
+ "Gamma" => [0x00393],
+ "Gammad" => [0x003DC],
+ "Gbreve" => [0x0011E],
+ "Gcedil" => [0x00122],
+ "Gcirc" => [0x0011C],
+ "Gcy" => [0x00413],
+ "Gdot" => [0x00120],
+ "Gfr" => [0x1D50A],
+ "Gg" => [0x022D9],
+ "Gopf" => [0x1D53E],
+ "GreaterEqual" => [0x02265],
+ "GreaterEqualLess" => [0x022DB],
+ "GreaterFullEqual" => [0x02267],
+ "GreaterGreater" => [0x02AA2],
+ "GreaterLess" => [0x02277],
+ "GreaterSlantEqual" => [0x02A7E],
+ "GreaterTilde" => [0x02273],
+ "Gscr" => [0x1D4A2],
+ "Gt" => [0x0226B],
+ "HARDcy" => [0x0042A],
+ "Hacek" => [0x002C7],
+ "Hat" => [0x0005E],
+ "Hcirc" => [0x00124],
+ "Hfr" => [0x0210C],
+ "HilbertSpace" => [0x0210B],
+ "Hopf" => [0x0210D],
+ "HorizontalLine" => [0x02500],
+ "Hscr" => [0x0210B],
+ "Hstrok" => [0x00126],
+ "HumpDownHump" => [0x0224E],
+ "HumpEqual" => [0x0224F],
+ "IEcy" => [0x00415],
+ "IJlig" => [0x00132],
+ "IOcy" => [0x00401],
+ "Iacute" => [0x000CD],
+ "Icirc" => [0x000CE],
+ "Icy" => [0x00418],
+ "Idot" => [0x00130],
+ "Ifr" => [0x02111],
+ "Igrave" => [0x000CC],
+ "Im" => [0x02111],
+ "Imacr" => [0x0012A],
+ "ImaginaryI" => [0x02148],
+ "Implies" => [0x021D2],
+ "Int" => [0x0222C],
+ "Integral" => [0x0222B],
+ "Intersection" => [0x022C2],
+ "InvisibleComma" => [0x02063],
+ "InvisibleTimes" => [0x02062],
+ "Iogon" => [0x0012E],
+ "Iopf" => [0x1D540],
+ "Iota" => [0x00399],
+ "Iscr" => [0x02110],
+ "Itilde" => [0x00128],
+ "Iukcy" => [0x00406],
+ "Iuml" => [0x000CF],
+ "Jcirc" => [0x00134],
+ "Jcy" => [0x00419],
+ "Jfr" => [0x1D50D],
+ "Jopf" => [0x1D541],
+ "Jscr" => [0x1D4A5],
+ "Jsercy" => [0x00408],
+ "Jukcy" => [0x00404],
+ "KHcy" => [0x00425],
+ "KJcy" => [0x0040C],
+ "Kappa" => [0x0039A],
+ "Kcedil" => [0x00136],
+ "Kcy" => [0x0041A],
+ "Kfr" => [0x1D50E],
+ "Kopf" => [0x1D542],
+ "Kscr" => [0x1D4A6],
+ "LJcy" => [0x00409],
+ "LT" => [0x0003C],
+ "Lacute" => [0x00139],
+ "Lambda" => [0x0039B],
+ "Lang" => [0x027EA],
+ "Laplacetrf" => [0x02112],
+ "Larr" => [0x0219E],
+ "Lcaron" => [0x0013D],
+ "Lcedil" => [0x0013B],
+ "Lcy" => [0x0041B],
+ "LeftAngleBracket" => [0x027E8],
+ "LeftArrow" => [0x02190],
+ "LeftArrowBar" => [0x021E4],
+ "LeftArrowRightArrow" => [0x021C6],
+ "LeftCeiling" => [0x02308],
+ "LeftDoubleBracket" => [0x027E6],
+ "LeftDownTeeVector" => [0x02961],
+ "LeftDownVector" => [0x021C3],
+ "LeftDownVectorBar" => [0x02959],
+ "LeftFloor" => [0x0230A],
+ "LeftRightArrow" => [0x02194],
+ "LeftRightVector" => [0x0294E],
+ "LeftTee" => [0x022A3],
+ "LeftTeeArrow" => [0x021A4],
+ "LeftTeeVector" => [0x0295A],
+ "LeftTriangle" => [0x022B2],
+ "LeftTriangleBar" => [0x029CF],
+ "LeftTriangleEqual" => [0x022B4],
+ "LeftUpDownVector" => [0x02951],
+ "LeftUpTeeVector" => [0x02960],
+ "LeftUpVector" => [0x021BF],
+ "LeftUpVectorBar" => [0x02958],
+ "LeftVector" => [0x021BC],
+ "LeftVectorBar" => [0x02952],
+ "Leftarrow" => [0x021D0],
+ "Leftrightarrow" => [0x021D4],
+ "LessEqualGreater" => [0x022DA],
+ "LessFullEqual" => [0x02266],
+ "LessGreater" => [0x02276],
+ "LessLess" => [0x02AA1],
+ "LessSlantEqual" => [0x02A7D],
+ "LessTilde" => [0x02272],
+ "Lfr" => [0x1D50F],
+ "Ll" => [0x022D8],
+ "Lleftarrow" => [0x021DA],
+ "Lmidot" => [0x0013F],
+ "LongLeftArrow" => [0x027F5],
+ "LongLeftRightArrow" => [0x027F7],
+ "LongRightArrow" => [0x027F6],
+ "Longleftarrow" => [0x027F8],
+ "Longleftrightarrow" => [0x027FA],
+ "Longrightarrow" => [0x027F9],
+ "Lopf" => [0x1D543],
+ "LowerLeftArrow" => [0x02199],
+ "LowerRightArrow" => [0x02198],
+ "Lscr" => [0x02112],
+ "Lsh" => [0x021B0],
+ "Lstrok" => [0x00141],
+ "Lt" => [0x0226A],
+ "Map" => [0x02905],
+ "Mcy" => [0x0041C],
+ "MediumSpace" => [0x0205F],
+ "Mellintrf" => [0x02133],
+ "Mfr" => [0x1D510],
+ "MinusPlus" => [0x02213],
+ "Mopf" => [0x1D544],
+ "Mscr" => [0x02133],
+ "Mu" => [0x0039C],
+ "NJcy" => [0x0040A],
+ "Nacute" => [0x00143],
+ "Ncaron" => [0x00147],
+ "Ncedil" => [0x00145],
+ "Ncy" => [0x0041D],
+ "NegativeMediumSpace" => [0x0200B],
+ "NegativeThickSpace" => [0x0200B],
+ "NegativeThinSpace" => [0x0200B],
+ "NegativeVeryThinSpace" => [0x0200B],
+ "NestedGreaterGreater" => [0x0226B],
+ "NestedLessLess" => [0x0226A],
+ "NewLine" => [0x0000A],
+ "Nfr" => [0x1D511],
+ "NoBreak" => [0x02060],
+ "NonBreakingSpace" => [0x000A0],
+ "Nopf" => [0x02115],
+ "Not" => [0x02AEC],
+ "NotCongruent" => [0x02262],
+ "NotCupCap" => [0x0226D],
+ "NotDoubleVerticalBar" => [0x02226],
+ "NotElement" => [0x02209],
+ "NotEqual" => [0x02260],
+ "NotEqualTilde" => [0x02242, 0x00338],
+ "NotExists" => [0x02204],
+ "NotGreater" => [0x0226F],
+ "NotGreaterEqual" => [0x02271],
+ "NotGreaterFullEqual" => [0x02267, 0x00338],
+ "NotGreaterGreater" => [0x0226B, 0x00338],
+ "NotGreaterLess" => [0x02279],
+ "NotGreaterSlantEqual" => [0x02A7E, 0x00338],
+ "NotGreaterTilde" => [0x02275],
+ "NotHumpDownHump" => [0x0224E, 0x00338],
+ "NotHumpEqual" => [0x0224F, 0x00338],
+ "NotLeftTriangle" => [0x022EA],
+ "NotLeftTriangleBar" => [0x029CF, 0x00338],
+ "NotLeftTriangleEqual" => [0x022EC],
+ "NotLess" => [0x0226E],
+ "NotLessEqual" => [0x02270],
+ "NotLessGreater" => [0x02278],
+ "NotLessLess" => [0x0226A, 0x00338],
+ "NotLessSlantEqual" => [0x02A7D, 0x00338],
+ "NotLessTilde" => [0x02274],
+ "NotNestedGreaterGreater" => [0x02AA2, 0x00338],
+ "NotNestedLessLess" => [0x02AA1, 0x00338],
+ "NotPrecedes" => [0x02280],
+ "NotPrecedesEqual" => [0x02AAF, 0x00338],
+ "NotPrecedesSlantEqual" => [0x022E0],
+ "NotReverseElement" => [0x0220C],
+ "NotRightTriangle" => [0x022EB],
+ "NotRightTriangleBar" => [0x029D0, 0x00338],
+ "NotRightTriangleEqual" => [0x022ED],
+ "NotSquareSubset" => [0x0228F, 0x00338],
+ "NotSquareSubsetEqual" => [0x022E2],
+ "NotSquareSuperset" => [0x02290, 0x00338],
+ "NotSquareSupersetEqual" => [0x022E3],
+ "NotSubset" => [0x02282, 0x020D2],
+ "NotSubsetEqual" => [0x02288],
+ "NotSucceeds" => [0x02281],
+ "NotSucceedsEqual" => [0x02AB0, 0x00338],
+ "NotSucceedsSlantEqual" => [0x022E1],
+ "NotSucceedsTilde" => [0x0227F, 0x00338],
+ "NotSuperset" => [0x02283, 0x020D2],
+ "NotSupersetEqual" => [0x02289],
+ "NotTilde" => [0x02241],
+ "NotTildeEqual" => [0x02244],
+ "NotTildeFullEqual" => [0x02247],
+ "NotTildeTilde" => [0x02249],
+ "NotVerticalBar" => [0x02224],
+ "Nscr" => [0x1D4A9],
+ "Ntilde" => [0x000D1],
+ "Nu" => [0x0039D],
+ "OElig" => [0x00152],
+ "Oacute" => [0x000D3],
+ "Ocirc" => [0x000D4],
+ "Ocy" => [0x0041E],
+ "Odblac" => [0x00150],
+ "Ofr" => [0x1D512],
+ "Ograve" => [0x000D2],
+ "Omacr" => [0x0014C],
+ "Omega" => [0x003A9],
+ "Omicron" => [0x0039F],
+ "Oopf" => [0x1D546],
+ "OpenCurlyDoubleQuote" => [0x0201C],
+ "OpenCurlyQuote" => [0x02018],
+ "Or" => [0x02A54],
+ "Oscr" => [0x1D4AA],
+ "Oslash" => [0x000D8],
+ "Otilde" => [0x000D5],
+ "Otimes" => [0x02A37],
+ "Ouml" => [0x000D6],
+ "OverBar" => [0x0203E],
+ "OverBrace" => [0x023DE],
+ "OverBracket" => [0x023B4],
+ "OverParenthesis" => [0x023DC],
+ "PartialD" => [0x02202],
+ "Pcy" => [0x0041F],
+ "Pfr" => [0x1D513],
+ "Phi" => [0x003A6],
+ "Pi" => [0x003A0],
+ "PlusMinus" => [0x000B1],
+ "Poincareplane" => [0x0210C],
+ "Popf" => [0x02119],
+ "Pr" => [0x02ABB],
+ "Precedes" => [0x0227A],
+ "PrecedesEqual" => [0x02AAF],
+ "PrecedesSlantEqual" => [0x0227C],
+ "PrecedesTilde" => [0x0227E],
+ "Prime" => [0x02033],
+ "Product" => [0x0220F],
+ "Proportion" => [0x02237],
+ "Proportional" => [0x0221D],
+ "Pscr" => [0x1D4AB],
+ "Psi" => [0x003A8],
+ "QUOT" => [0x00022],
+ "Qfr" => [0x1D514],
+ "Qopf" => [0x0211A],
+ "Qscr" => [0x1D4AC],
+ "RBarr" => [0x02910],
+ "REG" => [0x000AE],
+ "Racute" => [0x00154],
+ "Rang" => [0x027EB],
+ "Rarr" => [0x021A0],
+ "Rarrtl" => [0x02916],
+ "Rcaron" => [0x00158],
+ "Rcedil" => [0x00156],
+ "Rcy" => [0x00420],
+ "Re" => [0x0211C],
+ "ReverseElement" => [0x0220B],
+ "ReverseEquilibrium" => [0x021CB],
+ "ReverseUpEquilibrium" => [0x0296F],
+ "Rfr" => [0x0211C],
+ "Rho" => [0x003A1],
+ "RightAngleBracket" => [0x027E9],
+ "RightArrow" => [0x02192],
+ "RightArrowBar" => [0x021E5],
+ "RightArrowLeftArrow" => [0x021C4],
+ "RightCeiling" => [0x02309],
+ "RightDoubleBracket" => [0x027E7],
+ "RightDownTeeVector" => [0x0295D],
+ "RightDownVector" => [0x021C2],
+ "RightDownVectorBar" => [0x02955],
+ "RightFloor" => [0x0230B],
+ "RightTee" => [0x022A2],
+ "RightTeeArrow" => [0x021A6],
+ "RightTeeVector" => [0x0295B],
+ "RightTriangle" => [0x022B3],
+ "RightTriangleBar" => [0x029D0],
+ "RightTriangleEqual" => [0x022B5],
+ "RightUpDownVector" => [0x0294F],
+ "RightUpTeeVector" => [0x0295C],
+ "RightUpVector" => [0x021BE],
+ "RightUpVectorBar" => [0x02954],
+ "RightVector" => [0x021C0],
+ "RightVectorBar" => [0x02953],
+ "Rightarrow" => [0x021D2],
+ "Ropf" => [0x0211D],
+ "RoundImplies" => [0x02970],
+ "Rrightarrow" => [0x021DB],
+ "Rscr" => [0x0211B],
+ "Rsh" => [0x021B1],
+ "RuleDelayed" => [0x029F4],
+ "SHCHcy" => [0x00429],
+ "SHcy" => [0x00428],
+ "SOFTcy" => [0x0042C],
+ "Sacute" => [0x0015A],
+ "Sc" => [0x02ABC],
+ "Scaron" => [0x00160],
+ "Scedil" => [0x0015E],
+ "Scirc" => [0x0015C],
+ "Scy" => [0x00421],
+ "Sfr" => [0x1D516],
+ "ShortDownArrow" => [0x02193],
+ "ShortLeftArrow" => [0x02190],
+ "ShortRightArrow" => [0x02192],
+ "ShortUpArrow" => [0x02191],
+ "Sigma" => [0x003A3],
+ "SmallCircle" => [0x02218],
+ "Sopf" => [0x1D54A],
+ "Sqrt" => [0x0221A],
+ "Square" => [0x025A1],
+ "SquareIntersection" => [0x02293],
+ "SquareSubset" => [0x0228F],
+ "SquareSubsetEqual" => [0x02291],
+ "SquareSuperset" => [0x02290],
+ "SquareSupersetEqual" => [0x02292],
+ "SquareUnion" => [0x02294],
+ "Sscr" => [0x1D4AE],
+ "Star" => [0x022C6],
+ "Sub" => [0x022D0],
+ "Subset" => [0x022D0],
+ "SubsetEqual" => [0x02286],
+ "Succeeds" => [0x0227B],
+ "SucceedsEqual" => [0x02AB0],
+ "SucceedsSlantEqual" => [0x0227D],
+ "SucceedsTilde" => [0x0227F],
+ "SuchThat" => [0x0220B],
+ "Sum" => [0x02211],
+ "Sup" => [0x022D1],
+ "Superset" => [0x02283],
+ "SupersetEqual" => [0x02287],
+ "Supset" => [0x022D1],
+ "THORN" => [0x000DE],
+ "TRADE" => [0x02122],
+ "TSHcy" => [0x0040B],
+ "TScy" => [0x00426],
+ "Tab" => [0x00009],
+ "Tau" => [0x003A4],
+ "Tcaron" => [0x00164],
+ "Tcedil" => [0x00162],
+ "Tcy" => [0x00422],
+ "Tfr" => [0x1D517],
+ "Therefore" => [0x02234],
+ "Theta" => [0x00398],
+ "ThickSpace" => [0x0205F, 0x0200A],
+ "ThinSpace" => [0x02009],
+ "Tilde" => [0x0223C],
+ "TildeEqual" => [0x02243],
+ "TildeFullEqual" => [0x02245],
+ "TildeTilde" => [0x02248],
+ "Topf" => [0x1D54B],
+ "TripleDot" => [0x020DB],
+ "Tscr" => [0x1D4AF],
+ "Tstrok" => [0x00166],
+ "Uacute" => [0x000DA],
+ "Uarr" => [0x0219F],
+ "Uarrocir" => [0x02949],
+ "Ubrcy" => [0x0040E],
+ "Ubreve" => [0x0016C],
+ "Ucirc" => [0x000DB],
+ "Ucy" => [0x00423],
+ "Udblac" => [0x00170],
+ "Ufr" => [0x1D518],
+ "Ugrave" => [0x000D9],
+ "Umacr" => [0x0016A],
+ "UnderBar" => [0x0005F],
+ "UnderBrace" => [0x023DF],
+ "UnderBracket" => [0x023B5],
+ "UnderParenthesis" => [0x023DD],
+ "Union" => [0x022C3],
+ "UnionPlus" => [0x0228E],
+ "Uogon" => [0x00172],
+ "Uopf" => [0x1D54C],
+ "UpArrow" => [0x02191],
+ "UpArrowBar" => [0x02912],
+ "UpArrowDownArrow" => [0x021C5],
+ "UpDownArrow" => [0x02195],
+ "UpEquilibrium" => [0x0296E],
+ "UpTee" => [0x022A5],
+ "UpTeeArrow" => [0x021A5],
+ "Uparrow" => [0x021D1],
+ "Updownarrow" => [0x021D5],
+ "UpperLeftArrow" => [0x02196],
+ "UpperRightArrow" => [0x02197],
+ "Upsi" => [0x003D2],
+ "Upsilon" => [0x003A5],
+ "Uring" => [0x0016E],
+ "Uscr" => [0x1D4B0],
+ "Utilde" => [0x00168],
+ "Uuml" => [0x000DC],
+ "VDash" => [0x022AB],
+ "Vbar" => [0x02AEB],
+ "Vcy" => [0x00412],
+ "Vdash" => [0x022A9],
+ "Vdashl" => [0x02AE6],
+ "Vee" => [0x022C1],
+ "Verbar" => [0x02016],
+ "Vert" => [0x02016],
+ "VerticalBar" => [0x02223],
+ "VerticalLine" => [0x0007C],
+ "VerticalSeparator" => [0x02758],
+ "VerticalTilde" => [0x02240],
+ "VeryThinSpace" => [0x0200A],
+ "Vfr" => [0x1D519],
+ "Vopf" => [0x1D54D],
+ "Vscr" => [0x1D4B1],
+ "Vvdash" => [0x022AA],
+ "Wcirc" => [0x00174],
+ "Wedge" => [0x022C0],
+ "Wfr" => [0x1D51A],
+ "Wopf" => [0x1D54E],
+ "Wscr" => [0x1D4B2],
+ "Xfr" => [0x1D51B],
+ "Xi" => [0x0039E],
+ "Xopf" => [0x1D54F],
+ "Xscr" => [0x1D4B3],
+ "YAcy" => [0x0042F],
+ "YIcy" => [0x00407],
+ "YUcy" => [0x0042E],
+ "Yacute" => [0x000DD],
+ "Ycirc" => [0x00176],
+ "Ycy" => [0x0042B],
+ "Yfr" => [0x1D51C],
+ "Yopf" => [0x1D550],
+ "Yscr" => [0x1D4B4],
+ "Yuml" => [0x00178],
+ "ZHcy" => [0x00416],
+ "Zacute" => [0x00179],
+ "Zcaron" => [0x0017D],
+ "Zcy" => [0x00417],
+ "Zdot" => [0x0017B],
+ "ZeroWidthSpace" => [0x0200B],
+ "Zeta" => [0x00396],
+ "Zfr" => [0x02128],
+ "Zopf" => [0x02124],
+ "Zscr" => [0x1D4B5],
+ "aacute" => [0x000E1],
+ "abreve" => [0x00103],
+ "ac" => [0x0223E],
+ "acE" => [0x0223E, 0x00333],
+ "acd" => [0x0223F],
+ "acirc" => [0x000E2],
+ "acute" => [0x000B4],
+ "acy" => [0x00430],
+ "aelig" => [0x000E6],
+ "af" => [0x02061],
+ "afr" => [0x1D51E],
+ "agrave" => [0x000E0],
+ "alefsym" => [0x02135],
+ "aleph" => [0x02135],
+ "alpha" => [0x003B1],
+ "amacr" => [0x00101],
+ "amalg" => [0x02A3F],
+ "amp" => [0x00026],
+ "and" => [0x02227],
+ "andand" => [0x02A55],
+ "andd" => [0x02A5C],
+ "andslope" => [0x02A58],
+ "andv" => [0x02A5A],
+ "ang" => [0x02220],
+ "ange" => [0x029A4],
+ "angle" => [0x02220],
+ "angmsd" => [0x02221],
+ "angmsdaa" => [0x029A8],
+ "angmsdab" => [0x029A9],
+ "angmsdac" => [0x029AA],
+ "angmsdad" => [0x029AB],
+ "angmsdae" => [0x029AC],
+ "angmsdaf" => [0x029AD],
+ "angmsdag" => [0x029AE],
+ "angmsdah" => [0x029AF],
+ "angrt" => [0x0221F],
+ "angrtvb" => [0x022BE],
+ "angrtvbd" => [0x0299D],
+ "angsph" => [0x02222],
+ "angst" => [0x000C5],
+ "angzarr" => [0x0237C],
+ "aogon" => [0x00105],
+ "aopf" => [0x1D552],
+ "ap" => [0x02248],
+ "apE" => [0x02A70],
+ "apacir" => [0x02A6F],
+ "ape" => [0x0224A],
+ "apid" => [0x0224B],
+ "apos" => [0x00027],
+ "approx" => [0x02248],
+ "approxeq" => [0x0224A],
+ "aring" => [0x000E5],
+ "ascr" => [0x1D4B6],
+ "ast" => [0x0002A],
+ "asymp" => [0x02248],
+ "asympeq" => [0x0224D],
+ "atilde" => [0x000E3],
+ "auml" => [0x000E4],
+ "awconint" => [0x02233],
+ "awint" => [0x02A11],
+ "bNot" => [0x02AED],
+ "backcong" => [0x0224C],
+ "backepsilon" => [0x003F6],
+ "backprime" => [0x02035],
+ "backsim" => [0x0223D],
+ "backsimeq" => [0x022CD],
+ "barvee" => [0x022BD],
+ "barwed" => [0x02305],
+ "barwedge" => [0x02305],
+ "bbrk" => [0x023B5],
+ "bbrktbrk" => [0x023B6],
+ "bcong" => [0x0224C],
+ "bcy" => [0x00431],
+ "bdquo" => [0x0201E],
+ "becaus" => [0x02235],
+ "because" => [0x02235],
+ "bemptyv" => [0x029B0],
+ "bepsi" => [0x003F6],
+ "bernou" => [0x0212C],
+ "beta" => [0x003B2],
+ "beth" => [0x02136],
+ "between" => [0x0226C],
+ "bfr" => [0x1D51F],
+ "bigcap" => [0x022C2],
+ "bigcirc" => [0x025EF],
+ "bigcup" => [0x022C3],
+ "bigodot" => [0x02A00],
+ "bigoplus" => [0x02A01],
+ "bigotimes" => [0x02A02],
+ "bigsqcup" => [0x02A06],
+ "bigstar" => [0x02605],
+ "bigtriangledown" => [0x025BD],
+ "bigtriangleup" => [0x025B3],
+ "biguplus" => [0x02A04],
+ "bigvee" => [0x022C1],
+ "bigwedge" => [0x022C0],
+ "bkarow" => [0x0290D],
+ "blacklozenge" => [0x029EB],
+ "blacksquare" => [0x025AA],
+ "blacktriangle" => [0x025B4],
+ "blacktriangledown" => [0x025BE],
+ "blacktriangleleft" => [0x025C2],
+ "blacktriangleright" => [0x025B8],
+ "blank" => [0x02423],
+ "blk12" => [0x02592],
+ "blk14" => [0x02591],
+ "blk34" => [0x02593],
+ "block" => [0x02588],
+ "bne" => [0x0003D, 0x020E5],
+ "bnequiv" => [0x02261, 0x020E5],
+ "bnot" => [0x02310],
+ "bopf" => [0x1D553],
+ "bot" => [0x022A5],
+ "bottom" => [0x022A5],
+ "bowtie" => [0x022C8],
+ "boxDL" => [0x02557],
+ "boxDR" => [0x02554],
+ "boxDl" => [0x02556],
+ "boxDr" => [0x02553],
+ "boxH" => [0x02550],
+ "boxHD" => [0x02566],
+ "boxHU" => [0x02569],
+ "boxHd" => [0x02564],
+ "boxHu" => [0x02567],
+ "boxUL" => [0x0255D],
+ "boxUR" => [0x0255A],
+ "boxUl" => [0x0255C],
+ "boxUr" => [0x02559],
+ "boxV" => [0x02551],
+ "boxVH" => [0x0256C],
+ "boxVL" => [0x02563],
+ "boxVR" => [0x02560],
+ "boxVh" => [0x0256B],
+ "boxVl" => [0x02562],
+ "boxVr" => [0x0255F],
+ "boxbox" => [0x029C9],
+ "boxdL" => [0x02555],
+ "boxdR" => [0x02552],
+ "boxdl" => [0x02510],
+ "boxdr" => [0x0250C],
+ "boxh" => [0x02500],
+ "boxhD" => [0x02565],
+ "boxhU" => [0x02568],
+ "boxhd" => [0x0252C],
+ "boxhu" => [0x02534],
+ "boxminus" => [0x0229F],
+ "boxplus" => [0x0229E],
+ "boxtimes" => [0x022A0],
+ "boxuL" => [0x0255B],
+ "boxuR" => [0x02558],
+ "boxul" => [0x02518],
+ "boxur" => [0x02514],
+ "boxv" => [0x02502],
+ "boxvH" => [0x0256A],
+ "boxvL" => [0x02561],
+ "boxvR" => [0x0255E],
+ "boxvh" => [0x0253C],
+ "boxvl" => [0x02524],
+ "boxvr" => [0x0251C],
+ "bprime" => [0x02035],
+ "breve" => [0x002D8],
+ "brvbar" => [0x000A6],
+ "bscr" => [0x1D4B7],
+ "bsemi" => [0x0204F],
+ "bsim" => [0x0223D],
+ "bsime" => [0x022CD],
+ "bsol" => [0x0005C],
+ "bsolb" => [0x029C5],
+ "bsolhsub" => [0x027C8],
+ "bull" => [0x02022],
+ "bullet" => [0x02022],
+ "bump" => [0x0224E],
+ "bumpE" => [0x02AAE],
+ "bumpe" => [0x0224F],
+ "bumpeq" => [0x0224F],
+ "cacute" => [0x00107],
+ "cap" => [0x02229],
+ "capand" => [0x02A44],
+ "capbrcup" => [0x02A49],
+ "capcap" => [0x02A4B],
+ "capcup" => [0x02A47],
+ "capdot" => [0x02A40],
+ "caps" => [0x02229, 0x0FE00],
+ "caret" => [0x02041],
+ "caron" => [0x002C7],
+ "ccaps" => [0x02A4D],
+ "ccaron" => [0x0010D],
+ "ccedil" => [0x000E7],
+ "ccirc" => [0x00109],
+ "ccups" => [0x02A4C],
+ "ccupssm" => [0x02A50],
+ "cdot" => [0x0010B],
+ "cedil" => [0x000B8],
+ "cemptyv" => [0x029B2],
+ "cent" => [0x000A2],
+ "centerdot" => [0x000B7],
+ "cfr" => [0x1D520],
+ "chcy" => [0x00447],
+ "check" => [0x02713],
+ "checkmark" => [0x02713],
+ "chi" => [0x003C7],
+ "cir" => [0x025CB],
+ "cirE" => [0x029C3],
+ "circ" => [0x002C6],
+ "circeq" => [0x02257],
+ "circlearrowleft" => [0x021BA],
+ "circlearrowright" => [0x021BB],
+ "circledR" => [0x000AE],
+ "circledS" => [0x024C8],
+ "circledast" => [0x0229B],
+ "circledcirc" => [0x0229A],
+ "circleddash" => [0x0229D],
+ "cire" => [0x02257],
+ "cirfnint" => [0x02A10],
+ "cirmid" => [0x02AEF],
+ "cirscir" => [0x029C2],
+ "clubs" => [0x02663],
+ "clubsuit" => [0x02663],
+ "colon" => [0x0003A],
+ "colone" => [0x02254],
+ "coloneq" => [0x02254],
+ "comma" => [0x0002C],
+ "commat" => [0x00040],
+ "comp" => [0x02201],
+ "compfn" => [0x02218],
+ "complement" => [0x02201],
+ "complexes" => [0x02102],
+ "cong" => [0x02245],
+ "congdot" => [0x02A6D],
+ "conint" => [0x0222E],
+ "copf" => [0x1D554],
+ "coprod" => [0x02210],
+ "copy" => [0x000A9],
+ "copysr" => [0x02117],
+ "crarr" => [0x021B5],
+ "cross" => [0x02717],
+ "cscr" => [0x1D4B8],
+ "csub" => [0x02ACF],
+ "csube" => [0x02AD1],
+ "csup" => [0x02AD0],
+ "csupe" => [0x02AD2],
+ "ctdot" => [0x022EF],
+ "cudarrl" => [0x02938],
+ "cudarrr" => [0x02935],
+ "cuepr" => [0x022DE],
+ "cuesc" => [0x022DF],
+ "cularr" => [0x021B6],
+ "cularrp" => [0x0293D],
+ "cup" => [0x0222A],
+ "cupbrcap" => [0x02A48],
+ "cupcap" => [0x02A46],
+ "cupcup" => [0x02A4A],
+ "cupdot" => [0x0228D],
+ "cupor" => [0x02A45],
+ "cups" => [0x0222A, 0x0FE00],
+ "curarr" => [0x021B7],
+ "curarrm" => [0x0293C],
+ "curlyeqprec" => [0x022DE],
+ "curlyeqsucc" => [0x022DF],
+ "curlyvee" => [0x022CE],
+ "curlywedge" => [0x022CF],
+ "curren" => [0x000A4],
+ "curvearrowleft" => [0x021B6],
+ "curvearrowright" => [0x021B7],
+ "cuvee" => [0x022CE],
+ "cuwed" => [0x022CF],
+ "cwconint" => [0x02232],
+ "cwint" => [0x02231],
+ "cylcty" => [0x0232D],
+ "dArr" => [0x021D3],
+ "dHar" => [0x02965],
+ "dagger" => [0x02020],
+ "daleth" => [0x02138],
+ "darr" => [0x02193],
+ "dash" => [0x02010],
+ "dashv" => [0x022A3],
+ "dbkarow" => [0x0290F],
+ "dblac" => [0x002DD],
+ "dcaron" => [0x0010F],
+ "dcy" => [0x00434],
+ "dd" => [0x02146],
+ "ddagger" => [0x02021],
+ "ddarr" => [0x021CA],
+ "ddotseq" => [0x02A77],
+ "deg" => [0x000B0],
+ "delta" => [0x003B4],
+ "demptyv" => [0x029B1],
+ "dfisht" => [0x0297F],
+ "dfr" => [0x1D521],
+ "dharl" => [0x021C3],
+ "dharr" => [0x021C2],
+ "diam" => [0x022C4],
+ "diamond" => [0x022C4],
+ "diamondsuit" => [0x02666],
+ "diams" => [0x02666],
+ "die" => [0x000A8],
+ "digamma" => [0x003DD],
+ "disin" => [0x022F2],
+ "div" => [0x000F7],
+ "divide" => [0x000F7],
+ "divideontimes" => [0x022C7],
+ "divonx" => [0x022C7],
+ "djcy" => [0x00452],
+ "dlcorn" => [0x0231E],
+ "dlcrop" => [0x0230D],
+ "dollar" => [0x00024],
+ "dopf" => [0x1D555],
+ "dot" => [0x002D9],
+ "doteq" => [0x02250],
+ "doteqdot" => [0x02251],
+ "dotminus" => [0x02238],
+ "dotplus" => [0x02214],
+ "dotsquare" => [0x022A1],
+ "doublebarwedge" => [0x02306],
+ "downarrow" => [0x02193],
+ "downdownarrows" => [0x021CA],
+ "downharpoonleft" => [0x021C3],
+ "downharpoonright" => [0x021C2],
+ "drbkarow" => [0x02910],
+ "drcorn" => [0x0231F],
+ "drcrop" => [0x0230C],
+ "dscr" => [0x1D4B9],
+ "dscy" => [0x00455],
+ "dsol" => [0x029F6],
+ "dstrok" => [0x00111],
+ "dtdot" => [0x022F1],
+ "dtri" => [0x025BF],
+ "dtrif" => [0x025BE],
+ "duarr" => [0x021F5],
+ "duhar" => [0x0296F],
+ "dwangle" => [0x029A6],
+ "dzcy" => [0x0045F],
+ "dzigrarr" => [0x027FF],
+ "eDDot" => [0x02A77],
+ "eDot" => [0x02251],
+ "eacute" => [0x000E9],
+ "easter" => [0x02A6E],
+ "ecaron" => [0x0011B],
+ "ecir" => [0x02256],
+ "ecirc" => [0x000EA],
+ "ecolon" => [0x02255],
+ "ecy" => [0x0044D],
+ "edot" => [0x00117],
+ "ee" => [0x02147],
+ "efDot" => [0x02252],
+ "efr" => [0x1D522],
+ "eg" => [0x02A9A],
+ "egrave" => [0x000E8],
+ "egs" => [0x02A96],
+ "egsdot" => [0x02A98],
+ "el" => [0x02A99],
+ "elinters" => [0x023E7],
+ "ell" => [0x02113],
+ "els" => [0x02A95],
+ "elsdot" => [0x02A97],
+ "emacr" => [0x00113],
+ "empty" => [0x02205],
+ "emptyset" => [0x02205],
+ "emptyv" => [0x02205],
+ "emsp" => [0x02003],
+ "emsp13" => [0x02004],
+ "emsp14" => [0x02005],
+ "eng" => [0x0014B],
+ "ensp" => [0x02002],
+ "eogon" => [0x00119],
+ "eopf" => [0x1D556],
+ "epar" => [0x022D5],
+ "eparsl" => [0x029E3],
+ "eplus" => [0x02A71],
+ "epsi" => [0x003B5],
+ "epsilon" => [0x003B5],
+ "epsiv" => [0x003F5],
+ "eqcirc" => [0x02256],
+ "eqcolon" => [0x02255],
+ "eqsim" => [0x02242],
+ "eqslantgtr" => [0x02A96],
+ "eqslantless" => [0x02A95],
+ "equals" => [0x0003D],
+ "equest" => [0x0225F],
+ "equiv" => [0x02261],
+ "equivDD" => [0x02A78],
+ "eqvparsl" => [0x029E5],
+ "erDot" => [0x02253],
+ "erarr" => [0x02971],
+ "escr" => [0x0212F],
+ "esdot" => [0x02250],
+ "esim" => [0x02242],
+ "eta" => [0x003B7],
+ "eth" => [0x000F0],
+ "euml" => [0x000EB],
+ "euro" => [0x020AC],
+ "excl" => [0x00021],
+ "exist" => [0x02203],
+ "expectation" => [0x02130],
+ "exponentiale" => [0x02147],
+ "fallingdotseq" => [0x02252],
+ "fcy" => [0x00444],
+ "female" => [0x02640],
+ "ffilig" => [0x0FB03],
+ "fflig" => [0x0FB00],
+ "ffllig" => [0x0FB04],
+ "ffr" => [0x1D523],
+ "filig" => [0x0FB01],
+ "fjlig" => [0x00066, 0x0006A],
+ "flat" => [0x0266D],
+ "fllig" => [0x0FB02],
+ "fltns" => [0x025B1],
+ "fnof" => [0x00192],
+ "fopf" => [0x1D557],
+ "forall" => [0x02200],
+ "fork" => [0x022D4],
+ "forkv" => [0x02AD9],
+ "fpartint" => [0x02A0D],
+ "frac12" => [0x000BD],
+ "frac13" => [0x02153],
+ "frac14" => [0x000BC],
+ "frac15" => [0x02155],
+ "frac16" => [0x02159],
+ "frac18" => [0x0215B],
+ "frac23" => [0x02154],
+ "frac25" => [0x02156],
+ "frac34" => [0x000BE],
+ "frac35" => [0x02157],
+ "frac38" => [0x0215C],
+ "frac45" => [0x02158],
+ "frac56" => [0x0215A],
+ "frac58" => [0x0215D],
+ "frac78" => [0x0215E],
+ "frasl" => [0x02044],
+ "frown" => [0x02322],
+ "fscr" => [0x1D4BB],
+ "gE" => [0x02267],
+ "gEl" => [0x02A8C],
+ "gacute" => [0x001F5],
+ "gamma" => [0x003B3],
+ "gammad" => [0x003DD],
+ "gap" => [0x02A86],
+ "gbreve" => [0x0011F],
+ "gcirc" => [0x0011D],
+ "gcy" => [0x00433],
+ "gdot" => [0x00121],
+ "ge" => [0x02265],
+ "gel" => [0x022DB],
+ "geq" => [0x02265],
+ "geqq" => [0x02267],
+ "geqslant" => [0x02A7E],
+ "ges" => [0x02A7E],
+ "gescc" => [0x02AA9],
+ "gesdot" => [0x02A80],
+ "gesdoto" => [0x02A82],
+ "gesdotol" => [0x02A84],
+ "gesl" => [0x022DB, 0x0FE00],
+ "gesles" => [0x02A94],
+ "gfr" => [0x1D524],
+ "gg" => [0x0226B],
+ "ggg" => [0x022D9],
+ "gimel" => [0x02137],
+ "gjcy" => [0x00453],
+ "gl" => [0x02277],
+ "glE" => [0x02A92],
+ "gla" => [0x02AA5],
+ "glj" => [0x02AA4],
+ "gnE" => [0x02269],
+ "gnap" => [0x02A8A],
+ "gnapprox" => [0x02A8A],
+ "gne" => [0x02A88],
+ "gneq" => [0x02A88],
+ "gneqq" => [0x02269],
+ "gnsim" => [0x022E7],
+ "gopf" => [0x1D558],
+ "grave" => [0x00060],
+ "gscr" => [0x0210A],
+ "gsim" => [0x02273],
+ "gsime" => [0x02A8E],
+ "gsiml" => [0x02A90],
+ "gt" => [0x0003E],
+ "gtcc" => [0x02AA7],
+ "gtcir" => [0x02A7A],
+ "gtdot" => [0x022D7],
+ "gtlPar" => [0x02995],
+ "gtquest" => [0x02A7C],
+ "gtrapprox" => [0x02A86],
+ "gtrarr" => [0x02978],
+ "gtrdot" => [0x022D7],
+ "gtreqless" => [0x022DB],
+ "gtreqqless" => [0x02A8C],
+ "gtrless" => [0x02277],
+ "gtrsim" => [0x02273],
+ "gvertneqq" => [0x02269, 0x0FE00],
+ "gvnE" => [0x02269, 0x0FE00],
+ "hArr" => [0x021D4],
+ "hairsp" => [0x0200A],
+ "half" => [0x000BD],
+ "hamilt" => [0x0210B],
+ "hardcy" => [0x0044A],
+ "harr" => [0x02194],
+ "harrcir" => [0x02948],
+ "harrw" => [0x021AD],
+ "hbar" => [0x0210F],
+ "hcirc" => [0x00125],
+ "hearts" => [0x02665],
+ "heartsuit" => [0x02665],
+ "hellip" => [0x02026],
+ "hercon" => [0x022B9],
+ "hfr" => [0x1D525],
+ "hksearow" => [0x02925],
+ "hkswarow" => [0x02926],
+ "hoarr" => [0x021FF],
+ "homtht" => [0x0223B],
+ "hookleftarrow" => [0x021A9],
+ "hookrightarrow" => [0x021AA],
+ "hopf" => [0x1D559],
+ "horbar" => [0x02015],
+ "hscr" => [0x1D4BD],
+ "hslash" => [0x0210F],
+ "hstrok" => [0x00127],
+ "hybull" => [0x02043],
+ "hyphen" => [0x02010],
+ "iacute" => [0x000ED],
+ "ic" => [0x02063],
+ "icirc" => [0x000EE],
+ "icy" => [0x00438],
+ "iecy" => [0x00435],
+ "iexcl" => [0x000A1],
+ "iff" => [0x021D4],
+ "ifr" => [0x1D526],
+ "igrave" => [0x000EC],
+ "ii" => [0x02148],
+ "iiiint" => [0x02A0C],
+ "iiint" => [0x0222D],
+ "iinfin" => [0x029DC],
+ "iiota" => [0x02129],
+ "ijlig" => [0x00133],
+ "imacr" => [0x0012B],
+ "image" => [0x02111],
+ "imagline" => [0x02110],
+ "imagpart" => [0x02111],
+ "imath" => [0x00131],
+ "imof" => [0x022B7],
+ "imped" => [0x001B5],
+ "in" => [0x02208],
+ "incare" => [0x02105],
+ "infin" => [0x0221E],
+ "infintie" => [0x029DD],
+ "inodot" => [0x00131],
+ "int" => [0x0222B],
+ "intcal" => [0x022BA],
+ "integers" => [0x02124],
+ "intercal" => [0x022BA],
+ "intlarhk" => [0x02A17],
+ "intprod" => [0x02A3C],
+ "iocy" => [0x00451],
+ "iogon" => [0x0012F],
+ "iopf" => [0x1D55A],
+ "iota" => [0x003B9],
+ "iprod" => [0x02A3C],
+ "iquest" => [0x000BF],
+ "iscr" => [0x1D4BE],
+ "isin" => [0x02208],
+ "isinE" => [0x022F9],
+ "isindot" => [0x022F5],
+ "isins" => [0x022F4],
+ "isinsv" => [0x022F3],
+ "isinv" => [0x02208],
+ "it" => [0x02062],
+ "itilde" => [0x00129],
+ "iukcy" => [0x00456],
+ "iuml" => [0x000EF],
+ "jcirc" => [0x00135],
+ "jcy" => [0x00439],
+ "jfr" => [0x1D527],
+ "jmath" => [0x00237],
+ "jopf" => [0x1D55B],
+ "jscr" => [0x1D4BF],
+ "jsercy" => [0x00458],
+ "jukcy" => [0x00454],
+ "kappa" => [0x003BA],
+ "kappav" => [0x003F0],
+ "kcedil" => [0x00137],
+ "kcy" => [0x0043A],
+ "kfr" => [0x1D528],
+ "kgreen" => [0x00138],
+ "khcy" => [0x00445],
+ "kjcy" => [0x0045C],
+ "kopf" => [0x1D55C],
+ "kscr" => [0x1D4C0],
+ "lAarr" => [0x021DA],
+ "lArr" => [0x021D0],
+ "lAtail" => [0x0291B],
+ "lBarr" => [0x0290E],
+ "lE" => [0x02266],
+ "lEg" => [0x02A8B],
+ "lHar" => [0x02962],
+ "lacute" => [0x0013A],
+ "laemptyv" => [0x029B4],
+ "lagran" => [0x02112],
+ "lambda" => [0x003BB],
+ "lang" => [0x027E8],
+ "langd" => [0x02991],
+ "langle" => [0x027E8],
+ "lap" => [0x02A85],
+ "laquo" => [0x000AB],
+ "larr" => [0x02190],
+ "larrb" => [0x021E4],
+ "larrbfs" => [0x0291F],
+ "larrfs" => [0x0291D],
+ "larrhk" => [0x021A9],
+ "larrlp" => [0x021AB],
+ "larrpl" => [0x02939],
+ "larrsim" => [0x02973],
+ "larrtl" => [0x021A2],
+ "lat" => [0x02AAB],
+ "latail" => [0x02919],
+ "late" => [0x02AAD],
+ "lates" => [0x02AAD, 0x0FE00],
+ "lbarr" => [0x0290C],
+ "lbbrk" => [0x02772],
+ "lbrace" => [0x0007B],
+ "lbrack" => [0x0005B],
+ "lbrke" => [0x0298B],
+ "lbrksld" => [0x0298F],
+ "lbrkslu" => [0x0298D],
+ "lcaron" => [0x0013E],
+ "lcedil" => [0x0013C],
+ "lceil" => [0x02308],
+ "lcub" => [0x0007B],
+ "lcy" => [0x0043B],
+ "ldca" => [0x02936],
+ "ldquo" => [0x0201C],
+ "ldquor" => [0x0201E],
+ "ldrdhar" => [0x02967],
+ "ldrushar" => [0x0294B],
+ "ldsh" => [0x021B2],
+ "le" => [0x02264],
+ "leftarrow" => [0x02190],
+ "leftarrowtail" => [0x021A2],
+ "leftharpoondown" => [0x021BD],
+ "leftharpoonup" => [0x021BC],
+ "leftleftarrows" => [0x021C7],
+ "leftrightarrow" => [0x02194],
+ "leftrightarrows" => [0x021C6],
+ "leftrightharpoons" => [0x021CB],
+ "leftrightsquigarrow" => [0x021AD],
+ "leftthreetimes" => [0x022CB],
+ "leg" => [0x022DA],
+ "leq" => [0x02264],
+ "leqq" => [0x02266],
+ "leqslant" => [0x02A7D],
+ "les" => [0x02A7D],
+ "lescc" => [0x02AA8],
+ "lesdot" => [0x02A7F],
+ "lesdoto" => [0x02A81],
+ "lesdotor" => [0x02A83],
+ "lesg" => [0x022DA, 0x0FE00],
+ "lesges" => [0x02A93],
+ "lessapprox" => [0x02A85],
+ "lessdot" => [0x022D6],
+ "lesseqgtr" => [0x022DA],
+ "lesseqqgtr" => [0x02A8B],
+ "lessgtr" => [0x02276],
+ "lesssim" => [0x02272],
+ "lfisht" => [0x0297C],
+ "lfloor" => [0x0230A],
+ "lfr" => [0x1D529],
+ "lg" => [0x02276],
+ "lgE" => [0x02A91],
+ "lhard" => [0x021BD],
+ "lharu" => [0x021BC],
+ "lharul" => [0x0296A],
+ "lhblk" => [0x02584],
+ "ljcy" => [0x00459],
+ "ll" => [0x0226A],
+ "llarr" => [0x021C7],
+ "llcorner" => [0x0231E],
+ "llhard" => [0x0296B],
+ "lltri" => [0x025FA],
+ "lmidot" => [0x00140],
+ "lmoust" => [0x023B0],
+ "lmoustache" => [0x023B0],
+ "lnE" => [0x02268],
+ "lnap" => [0x02A89],
+ "lnapprox" => [0x02A89],
+ "lne" => [0x02A87],
+ "lneq" => [0x02A87],
+ "lneqq" => [0x02268],
+ "lnsim" => [0x022E6],
+ "loang" => [0x027EC],
+ "loarr" => [0x021FD],
+ "lobrk" => [0x027E6],
+ "longleftarrow" => [0x027F5],
+ "longleftrightarrow" => [0x027F7],
+ "longmapsto" => [0x027FC],
+ "longrightarrow" => [0x027F6],
+ "looparrowleft" => [0x021AB],
+ "looparrowright" => [0x021AC],
+ "lopar" => [0x02985],
+ "lopf" => [0x1D55D],
+ "loplus" => [0x02A2D],
+ "lotimes" => [0x02A34],
+ "lowast" => [0x02217],
+ "lowbar" => [0x0005F],
+ "loz" => [0x025CA],
+ "lozenge" => [0x025CA],
+ "lozf" => [0x029EB],
+ "lpar" => [0x00028],
+ "lparlt" => [0x02993],
+ "lrarr" => [0x021C6],
+ "lrcorner" => [0x0231F],
+ "lrhar" => [0x021CB],
+ "lrhard" => [0x0296D],
+ "lrm" => [0x0200E],
+ "lrtri" => [0x022BF],
+ "lsaquo" => [0x02039],
+ "lscr" => [0x1D4C1],
+ "lsh" => [0x021B0],
+ "lsim" => [0x02272],
+ "lsime" => [0x02A8D],
+ "lsimg" => [0x02A8F],
+ "lsqb" => [0x0005B],
+ "lsquo" => [0x02018],
+ "lsquor" => [0x0201A],
+ "lstrok" => [0x00142],
+ "lt" => [0x0003C],
+ "ltcc" => [0x02AA6],
+ "ltcir" => [0x02A79],
+ "ltdot" => [0x022D6],
+ "lthree" => [0x022CB],
+ "ltimes" => [0x022C9],
+ "ltlarr" => [0x02976],
+ "ltquest" => [0x02A7B],
+ "ltrPar" => [0x02996],
+ "ltri" => [0x025C3],
+ "ltrie" => [0x022B4],
+ "ltrif" => [0x025C2],
+ "lurdshar" => [0x0294A],
+ "luruhar" => [0x02966],
+ "lvertneqq" => [0x02268, 0x0FE00],
+ "lvnE" => [0x02268, 0x0FE00],
+ "mDDot" => [0x0223A],
+ "macr" => [0x000AF],
+ "male" => [0x02642],
+ "malt" => [0x02720],
+ "maltese" => [0x02720],
+ "map" => [0x021A6],
+ "mapsto" => [0x021A6],
+ "mapstodown" => [0x021A7],
+ "mapstoleft" => [0x021A4],
+ "mapstoup" => [0x021A5],
+ "marker" => [0x025AE],
+ "mcomma" => [0x02A29],
+ "mcy" => [0x0043C],
+ "mdash" => [0x02014],
+ "measuredangle" => [0x02221],
+ "mfr" => [0x1D52A],
+ "mho" => [0x02127],
+ "micro" => [0x000B5],
+ "mid" => [0x02223],
+ "midast" => [0x0002A],
+ "midcir" => [0x02AF0],
+ "middot" => [0x000B7],
+ "minus" => [0x02212],
+ "minusb" => [0x0229F],
+ "minusd" => [0x02238],
+ "minusdu" => [0x02A2A],
+ "mlcp" => [0x02ADB],
+ "mldr" => [0x02026],
+ "mnplus" => [0x02213],
+ "models" => [0x022A7],
+ "mopf" => [0x1D55E],
+ "mp" => [0x02213],
+ "mscr" => [0x1D4C2],
+ "mstpos" => [0x0223E],
+ "mu" => [0x003BC],
+ "multimap" => [0x022B8],
+ "mumap" => [0x022B8],
+ "nGg" => [0x022D9, 0x00338],
+ "nGt" => [0x0226B, 0x020D2],
+ "nGtv" => [0x0226B, 0x00338],
+ "nLeftarrow" => [0x021CD],
+ "nLeftrightarrow" => [0x021CE],
+ "nLl" => [0x022D8, 0x00338],
+ "nLt" => [0x0226A, 0x020D2],
+ "nLtv" => [0x0226A, 0x00338],
+ "nRightarrow" => [0x021CF],
+ "nVDash" => [0x022AF],
+ "nVdash" => [0x022AE],
+ "nabla" => [0x02207],
+ "nacute" => [0x00144],
+ "nang" => [0x02220, 0x020D2],
+ "nap" => [0x02249],
+ "napE" => [0x02A70, 0x00338],
+ "napid" => [0x0224B, 0x00338],
+ "napos" => [0x00149],
+ "napprox" => [0x02249],
+ "natur" => [0x0266E],
+ "natural" => [0x0266E],
+ "naturals" => [0x02115],
+ "nbsp" => [0x000A0],
+ "nbump" => [0x0224E, 0x00338],
+ "nbumpe" => [0x0224F, 0x00338],
+ "ncap" => [0x02A43],
+ "ncaron" => [0x00148],
+ "ncedil" => [0x00146],
+ "ncong" => [0x02247],
+ "ncongdot" => [0x02A6D, 0x00338],
+ "ncup" => [0x02A42],
+ "ncy" => [0x0043D],
+ "ndash" => [0x02013],
+ "ne" => [0x02260],
+ "neArr" => [0x021D7],
+ "nearhk" => [0x02924],
+ "nearr" => [0x02197],
+ "nearrow" => [0x02197],
+ "nedot" => [0x02250, 0x00338],
+ "nequiv" => [0x02262],
+ "nesear" => [0x02928],
+ "nesim" => [0x02242, 0x00338],
+ "nexist" => [0x02204],
+ "nexists" => [0x02204],
+ "nfr" => [0x1D52B],
+ "ngE" => [0x02267, 0x00338],
+ "nge" => [0x02271],
+ "ngeq" => [0x02271],
+ "ngeqq" => [0x02267, 0x00338],
+ "ngeqslant" => [0x02A7E, 0x00338],
+ "nges" => [0x02A7E, 0x00338],
+ "ngsim" => [0x02275],
+ "ngt" => [0x0226F],
+ "ngtr" => [0x0226F],
+ "nhArr" => [0x021CE],
+ "nharr" => [0x021AE],
+ "nhpar" => [0x02AF2],
+ "ni" => [0x0220B],
+ "nis" => [0x022FC],
+ "nisd" => [0x022FA],
+ "niv" => [0x0220B],
+ "njcy" => [0x0045A],
+ "nlArr" => [0x021CD],
+ "nlE" => [0x02266, 0x00338],
+ "nlarr" => [0x0219A],
+ "nldr" => [0x02025],
+ "nle" => [0x02270],
+ "nleftarrow" => [0x0219A],
+ "nleftrightarrow" => [0x021AE],
+ "nleq" => [0x02270],
+ "nleqq" => [0x02266, 0x00338],
+ "nleqslant" => [0x02A7D, 0x00338],
+ "nles" => [0x02A7D, 0x00338],
+ "nless" => [0x0226E],
+ "nlsim" => [0x02274],
+ "nlt" => [0x0226E],
+ "nltri" => [0x022EA],
+ "nltrie" => [0x022EC],
+ "nmid" => [0x02224],
+ "nopf" => [0x1D55F],
+ "not" => [0x000AC],
+ "notin" => [0x02209],
+ "notinE" => [0x022F9, 0x00338],
+ "notindot" => [0x022F5, 0x00338],
+ "notinva" => [0x02209],
+ "notinvb" => [0x022F7],
+ "notinvc" => [0x022F6],
+ "notni" => [0x0220C],
+ "notniva" => [0x0220C],
+ "notnivb" => [0x022FE],
+ "notnivc" => [0x022FD],
+ "npar" => [0x02226],
+ "nparallel" => [0x02226],
+ "nparsl" => [0x02AFD, 0x020E5],
+ "npart" => [0x02202, 0x00338],
+ "npolint" => [0x02A14],
+ "npr" => [0x02280],
+ "nprcue" => [0x022E0],
+ "npre" => [0x02AAF, 0x00338],
+ "nprec" => [0x02280],
+ "npreceq" => [0x02AAF, 0x00338],
+ "nrArr" => [0x021CF],
+ "nrarr" => [0x0219B],
+ "nrarrc" => [0x02933, 0x00338],
+ "nrarrw" => [0x0219D, 0x00338],
+ "nrightarrow" => [0x0219B],
+ "nrtri" => [0x022EB],
+ "nrtrie" => [0x022ED],
+ "nsc" => [0x02281],
+ "nsccue" => [0x022E1],
+ "nsce" => [0x02AB0, 0x00338],
+ "nscr" => [0x1D4C3],
+ "nshortmid" => [0x02224],
+ "nshortparallel" => [0x02226],
+ "nsim" => [0x02241],
+ "nsime" => [0x02244],
+ "nsimeq" => [0x02244],
+ "nsmid" => [0x02224],
+ "nspar" => [0x02226],
+ "nsqsube" => [0x022E2],
+ "nsqsupe" => [0x022E3],
+ "nsub" => [0x02284],
+ "nsubE" => [0x02AC5, 0x00338],
+ "nsube" => [0x02288],
+ "nsubset" => [0x02282, 0x020D2],
+ "nsubseteq" => [0x02288],
+ "nsubseteqq" => [0x02AC5, 0x00338],
+ "nsucc" => [0x02281],
+ "nsucceq" => [0x02AB0, 0x00338],
+ "nsup" => [0x02285],
+ "nsupE" => [0x02AC6, 0x00338],
+ "nsupe" => [0x02289],
+ "nsupset" => [0x02283, 0x020D2],
+ "nsupseteq" => [0x02289],
+ "nsupseteqq" => [0x02AC6, 0x00338],
+ "ntgl" => [0x02279],
+ "ntilde" => [0x000F1],
+ "ntlg" => [0x02278],
+ "ntriangleleft" => [0x022EA],
+ "ntrianglelefteq" => [0x022EC],
+ "ntriangleright" => [0x022EB],
+ "ntrianglerighteq" => [0x022ED],
+ "nu" => [0x003BD],
+ "num" => [0x00023],
+ "numero" => [0x02116],
+ "numsp" => [0x02007],
+ "nvDash" => [0x022AD],
+ "nvHarr" => [0x02904],
+ "nvap" => [0x0224D, 0x020D2],
+ "nvdash" => [0x022AC],
+ "nvge" => [0x02265, 0x020D2],
+ "nvgt" => [0x0003E, 0x020D2],
+ "nvinfin" => [0x029DE],
+ "nvlArr" => [0x02902],
+ "nvle" => [0x02264, 0x020D2],
+ "nvlt" => [0x0003C, 0x020D2],
+ "nvltrie" => [0x022B4, 0x020D2],
+ "nvrArr" => [0x02903],
+ "nvrtrie" => [0x022B5, 0x020D2],
+ "nvsim" => [0x0223C, 0x020D2],
+ "nwArr" => [0x021D6],
+ "nwarhk" => [0x02923],
+ "nwarr" => [0x02196],
+ "nwarrow" => [0x02196],
+ "nwnear" => [0x02927],
+ "oS" => [0x024C8],
+ "oacute" => [0x000F3],
+ "oast" => [0x0229B],
+ "ocir" => [0x0229A],
+ "ocirc" => [0x000F4],
+ "ocy" => [0x0043E],
+ "odash" => [0x0229D],
+ "odblac" => [0x00151],
+ "odiv" => [0x02A38],
+ "odot" => [0x02299],
+ "odsold" => [0x029BC],
+ "oelig" => [0x00153],
+ "ofcir" => [0x029BF],
+ "ofr" => [0x1D52C],
+ "ogon" => [0x002DB],
+ "ograve" => [0x000F2],
+ "ogt" => [0x029C1],
+ "ohbar" => [0x029B5],
+ "ohm" => [0x003A9],
+ "oint" => [0x0222E],
+ "olarr" => [0x021BA],
+ "olcir" => [0x029BE],
+ "olcross" => [0x029BB],
+ "oline" => [0x0203E],
+ "olt" => [0x029C0],
+ "omacr" => [0x0014D],
+ "omega" => [0x003C9],
+ "omicron" => [0x003BF],
+ "omid" => [0x029B6],
+ "ominus" => [0x02296],
+ "oopf" => [0x1D560],
+ "opar" => [0x029B7],
+ "operp" => [0x029B9],
+ "oplus" => [0x02295],
+ "or" => [0x02228],
+ "orarr" => [0x021BB],
+ "ord" => [0x02A5D],
+ "order" => [0x02134],
+ "orderof" => [0x02134],
+ "ordf" => [0x000AA],
+ "ordm" => [0x000BA],
+ "origof" => [0x022B6],
+ "oror" => [0x02A56],
+ "orslope" => [0x02A57],
+ "orv" => [0x02A5B],
+ "oscr" => [0x02134],
+ "oslash" => [0x000F8],
+ "osol" => [0x02298],
+ "otilde" => [0x000F5],
+ "otimes" => [0x02297],
+ "otimesas" => [0x02A36],
+ "ouml" => [0x000F6],
+ "ovbar" => [0x0233D],
+ "par" => [0x02225],
+ "para" => [0x000B6],
+ "parallel" => [0x02225],
+ "parsim" => [0x02AF3],
+ "parsl" => [0x02AFD],
+ "part" => [0x02202],
+ "pcy" => [0x0043F],
+ "percnt" => [0x00025],
+ "period" => [0x0002E],
+ "permil" => [0x02030],
+ "perp" => [0x022A5],
+ "pertenk" => [0x02031],
+ "pfr" => [0x1D52D],
+ "phi" => [0x003C6],
+ "phiv" => [0x003D5],
+ "phmmat" => [0x02133],
+ "phone" => [0x0260E],
+ "pi" => [0x003C0],
+ "pitchfork" => [0x022D4],
+ "piv" => [0x003D6],
+ "planck" => [0x0210F],
+ "planckh" => [0x0210E],
+ "plankv" => [0x0210F],
+ "plus" => [0x0002B],
+ "plusacir" => [0x02A23],
+ "plusb" => [0x0229E],
+ "pluscir" => [0x02A22],
+ "plusdo" => [0x02214],
+ "plusdu" => [0x02A25],
+ "pluse" => [0x02A72],
+ "plusmn" => [0x000B1],
+ "plussim" => [0x02A26],
+ "plustwo" => [0x02A27],
+ "pm" => [0x000B1],
+ "pointint" => [0x02A15],
+ "popf" => [0x1D561],
+ "pound" => [0x000A3],
+ "pr" => [0x0227A],
+ "prE" => [0x02AB3],
+ "prap" => [0x02AB7],
+ "prcue" => [0x0227C],
+ "pre" => [0x02AAF],
+ "prec" => [0x0227A],
+ "precapprox" => [0x02AB7],
+ "preccurlyeq" => [0x0227C],
+ "preceq" => [0x02AAF],
+ "precnapprox" => [0x02AB9],
+ "precneqq" => [0x02AB5],
+ "precnsim" => [0x022E8],
+ "precsim" => [0x0227E],
+ "prime" => [0x02032],
+ "primes" => [0x02119],
+ "prnE" => [0x02AB5],
+ "prnap" => [0x02AB9],
+ "prnsim" => [0x022E8],
+ "prod" => [0x0220F],
+ "profalar" => [0x0232E],
+ "profline" => [0x02312],
+ "profsurf" => [0x02313],
+ "prop" => [0x0221D],
+ "propto" => [0x0221D],
+ "prsim" => [0x0227E],
+ "prurel" => [0x022B0],
+ "pscr" => [0x1D4C5],
+ "psi" => [0x003C8],
+ "puncsp" => [0x02008],
+ "qfr" => [0x1D52E],
+ "qint" => [0x02A0C],
+ "qopf" => [0x1D562],
+ "qprime" => [0x02057],
+ "qscr" => [0x1D4C6],
+ "quaternions" => [0x0210D],
+ "quatint" => [0x02A16],
+ "quest" => [0x0003F],
+ "questeq" => [0x0225F],
+ "quot" => [0x00022],
+ "rAarr" => [0x021DB],
+ "rArr" => [0x021D2],
+ "rAtail" => [0x0291C],
+ "rBarr" => [0x0290F],
+ "rHar" => [0x02964],
+ "race" => [0x0223D, 0x00331],
+ "racute" => [0x00155],
+ "radic" => [0x0221A],
+ "raemptyv" => [0x029B3],
+ "rang" => [0x027E9],
+ "rangd" => [0x02992],
+ "range" => [0x029A5],
+ "rangle" => [0x027E9],
+ "raquo" => [0x000BB],
+ "rarr" => [0x02192],
+ "rarrap" => [0x02975],
+ "rarrb" => [0x021E5],
+ "rarrbfs" => [0x02920],
+ "rarrc" => [0x02933],
+ "rarrfs" => [0x0291E],
+ "rarrhk" => [0x021AA],
+ "rarrlp" => [0x021AC],
+ "rarrpl" => [0x02945],
+ "rarrsim" => [0x02974],
+ "rarrtl" => [0x021A3],
+ "rarrw" => [0x0219D],
+ "ratail" => [0x0291A],
+ "ratio" => [0x02236],
+ "rationals" => [0x0211A],
+ "rbarr" => [0x0290D],
+ "rbbrk" => [0x02773],
+ "rbrace" => [0x0007D],
+ "rbrack" => [0x0005D],
+ "rbrke" => [0x0298C],
+ "rbrksld" => [0x0298E],
+ "rbrkslu" => [0x02990],
+ "rcaron" => [0x00159],
+ "rcedil" => [0x00157],
+ "rceil" => [0x02309],
+ "rcub" => [0x0007D],
+ "rcy" => [0x00440],
+ "rdca" => [0x02937],
+ "rdldhar" => [0x02969],
+ "rdquo" => [0x0201D],
+ "rdquor" => [0x0201D],
+ "rdsh" => [0x021B3],
+ "real" => [0x0211C],
+ "realine" => [0x0211B],
+ "realpart" => [0x0211C],
+ "reals" => [0x0211D],
+ "rect" => [0x025AD],
+ "reg" => [0x000AE],
+ "rfisht" => [0x0297D],
+ "rfloor" => [0x0230B],
+ "rfr" => [0x1D52F],
+ "rhard" => [0x021C1],
+ "rharu" => [0x021C0],
+ "rharul" => [0x0296C],
+ "rho" => [0x003C1],
+ "rhov" => [0x003F1],
+ "rightarrow" => [0x02192],
+ "rightarrowtail" => [0x021A3],
+ "rightharpoondown" => [0x021C1],
+ "rightharpoonup" => [0x021C0],
+ "rightleftarrows" => [0x021C4],
+ "rightleftharpoons" => [0x021CC],
+ "rightrightarrows" => [0x021C9],
+ "rightsquigarrow" => [0x0219D],
+ "rightthreetimes" => [0x022CC],
+ "ring" => [0x002DA],
+ "risingdotseq" => [0x02253],
+ "rlarr" => [0x021C4],
+ "rlhar" => [0x021CC],
+ "rlm" => [0x0200F],
+ "rmoust" => [0x023B1],
+ "rmoustache" => [0x023B1],
+ "rnmid" => [0x02AEE],
+ "roang" => [0x027ED],
+ "roarr" => [0x021FE],
+ "robrk" => [0x027E7],
+ "ropar" => [0x02986],
+ "ropf" => [0x1D563],
+ "roplus" => [0x02A2E],
+ "rotimes" => [0x02A35],
+ "rpar" => [0x00029],
+ "rpargt" => [0x02994],
+ "rppolint" => [0x02A12],
+ "rrarr" => [0x021C9],
+ "rsaquo" => [0x0203A],
+ "rscr" => [0x1D4C7],
+ "rsh" => [0x021B1],
+ "rsqb" => [0x0005D],
+ "rsquo" => [0x02019],
+ "rsquor" => [0x02019],
+ "rthree" => [0x022CC],
+ "rtimes" => [0x022CA],
+ "rtri" => [0x025B9],
+ "rtrie" => [0x022B5],
+ "rtrif" => [0x025B8],
+ "rtriltri" => [0x029CE],
+ "ruluhar" => [0x02968],
+ "rx" => [0x0211E],
+ "sacute" => [0x0015B],
+ "sbquo" => [0x0201A],
+ "sc" => [0x0227B],
+ "scE" => [0x02AB4],
+ "scap" => [0x02AB8],
+ "scaron" => [0x00161],
+ "sccue" => [0x0227D],
+ "sce" => [0x02AB0],
+ "scedil" => [0x0015F],
+ "scirc" => [0x0015D],
+ "scnE" => [0x02AB6],
+ "scnap" => [0x02ABA],
+ "scnsim" => [0x022E9],
+ "scpolint" => [0x02A13],
+ "scsim" => [0x0227F],
+ "scy" => [0x00441],
+ "sdot" => [0x022C5],
+ "sdotb" => [0x022A1],
+ "sdote" => [0x02A66],
+ "seArr" => [0x021D8],
+ "searhk" => [0x02925],
+ "searr" => [0x02198],
+ "searrow" => [0x02198],
+ "sect" => [0x000A7],
+ "semi" => [0x0003B],
+ "seswar" => [0x02929],
+ "setminus" => [0x02216],
+ "setmn" => [0x02216],
+ "sext" => [0x02736],
+ "sfr" => [0x1D530],
+ "sfrown" => [0x02322],
+ "sharp" => [0x0266F],
+ "shchcy" => [0x00449],
+ "shcy" => [0x00448],
+ "shortmid" => [0x02223],
+ "shortparallel" => [0x02225],
+ "shy" => [0x000AD],
+ "sigma" => [0x003C3],
+ "sigmaf" => [0x003C2],
+ "sigmav" => [0x003C2],
+ "sim" => [0x0223C],
+ "simdot" => [0x02A6A],
+ "sime" => [0x02243],
+ "simeq" => [0x02243],
+ "simg" => [0x02A9E],
+ "simgE" => [0x02AA0],
+ "siml" => [0x02A9D],
+ "simlE" => [0x02A9F],
+ "simne" => [0x02246],
+ "simplus" => [0x02A24],
+ "simrarr" => [0x02972],
+ "slarr" => [0x02190],
+ "smallsetminus" => [0x02216],
+ "smashp" => [0x02A33],
+ "smeparsl" => [0x029E4],
+ "smid" => [0x02223],
+ "smile" => [0x02323],
+ "smt" => [0x02AAA],
+ "smte" => [0x02AAC],
+ "smtes" => [0x02AAC, 0x0FE00],
+ "softcy" => [0x0044C],
+ "sol" => [0x0002F],
+ "solb" => [0x029C4],
+ "solbar" => [0x0233F],
+ "sopf" => [0x1D564],
+ "spades" => [0x02660],
+ "spadesuit" => [0x02660],
+ "spar" => [0x02225],
+ "sqcap" => [0x02293],
+ "sqcaps" => [0x02293, 0x0FE00],
+ "sqcup" => [0x02294],
+ "sqcups" => [0x02294, 0x0FE00],
+ "sqsub" => [0x0228F],
+ "sqsube" => [0x02291],
+ "sqsubset" => [0x0228F],
+ "sqsubseteq" => [0x02291],
+ "sqsup" => [0x02290],
+ "sqsupe" => [0x02292],
+ "sqsupset" => [0x02290],
+ "sqsupseteq" => [0x02292],
+ "squ" => [0x025A1],
+ "square" => [0x025A1],
+ "squarf" => [0x025AA],
+ "squf" => [0x025AA],
+ "srarr" => [0x02192],
+ "sscr" => [0x1D4C8],
+ "ssetmn" => [0x02216],
+ "ssmile" => [0x02323],
+ "sstarf" => [0x022C6],
+ "star" => [0x02606],
+ "starf" => [0x02605],
+ "straightepsilon" => [0x003F5],
+ "straightphi" => [0x003D5],
+ "strns" => [0x000AF],
+ "sub" => [0x02282],
+ "subE" => [0x02AC5],
+ "subdot" => [0x02ABD],
+ "sube" => [0x02286],
+ "subedot" => [0x02AC3],
+ "submult" => [0x02AC1],
+ "subnE" => [0x02ACB],
+ "subne" => [0x0228A],
+ "subplus" => [0x02ABF],
+ "subrarr" => [0x02979],
+ "subset" => [0x02282],
+ "subseteq" => [0x02286],
+ "subseteqq" => [0x02AC5],
+ "subsetneq" => [0x0228A],
+ "subsetneqq" => [0x02ACB],
+ "subsim" => [0x02AC7],
+ "subsub" => [0x02AD5],
+ "subsup" => [0x02AD3],
+ "succ" => [0x0227B],
+ "succapprox" => [0x02AB8],
+ "succcurlyeq" => [0x0227D],
+ "succeq" => [0x02AB0],
+ "succnapprox" => [0x02ABA],
+ "succneqq" => [0x02AB6],
+ "succnsim" => [0x022E9],
+ "succsim" => [0x0227F],
+ "sum" => [0x02211],
+ "sung" => [0x0266A],
+ "sup" => [0x02283],
+ "sup1" => [0x000B9],
+ "sup2" => [0x000B2],
+ "sup3" => [0x000B3],
+ "supE" => [0x02AC6],
+ "supdot" => [0x02ABE],
+ "supdsub" => [0x02AD8],
+ "supe" => [0x02287],
+ "supedot" => [0x02AC4],
+ "suphsol" => [0x027C9],
+ "suphsub" => [0x02AD7],
+ "suplarr" => [0x0297B],
+ "supmult" => [0x02AC2],
+ "supnE" => [0x02ACC],
+ "supne" => [0x0228B],
+ "supplus" => [0x02AC0],
+ "supset" => [0x02283],
+ "supseteq" => [0x02287],
+ "supseteqq" => [0x02AC6],
+ "supsetneq" => [0x0228B],
+ "supsetneqq" => [0x02ACC],
+ "supsim" => [0x02AC8],
+ "supsub" => [0x02AD4],
+ "supsup" => [0x02AD6],
+ "swArr" => [0x021D9],
+ "swarhk" => [0x02926],
+ "swarr" => [0x02199],
+ "swarrow" => [0x02199],
+ "swnwar" => [0x0292A],
+ "szlig" => [0x000DF],
+ "target" => [0x02316],
+ "tau" => [0x003C4],
+ "tbrk" => [0x023B4],
+ "tcaron" => [0x00165],
+ "tcedil" => [0x00163],
+ "tcy" => [0x00442],
+ "tdot" => [0x020DB],
+ "telrec" => [0x02315],
+ "tfr" => [0x1D531],
+ "there4" => [0x02234],
+ "therefore" => [0x02234],
+ "theta" => [0x003B8],
+ "thetasym" => [0x003D1],
+ "thetav" => [0x003D1],
+ "thickapprox" => [0x02248],
+ "thicksim" => [0x0223C],
+ "thinsp" => [0x02009],
+ "thkap" => [0x02248],
+ "thksim" => [0x0223C],
+ "thorn" => [0x000FE],
+ "tilde" => [0x002DC],
+ "times" => [0x000D7],
+ "timesb" => [0x022A0],
+ "timesbar" => [0x02A31],
+ "timesd" => [0x02A30],
+ "tint" => [0x0222D],
+ "toea" => [0x02928],
+ "top" => [0x022A4],
+ "topbot" => [0x02336],
+ "topcir" => [0x02AF1],
+ "topf" => [0x1D565],
+ "topfork" => [0x02ADA],
+ "tosa" => [0x02929],
+ "tprime" => [0x02034],
+ "trade" => [0x02122],
+ "triangle" => [0x025B5],
+ "triangledown" => [0x025BF],
+ "triangleleft" => [0x025C3],
+ "trianglelefteq" => [0x022B4],
+ "triangleq" => [0x0225C],
+ "triangleright" => [0x025B9],
+ "trianglerighteq" => [0x022B5],
+ "tridot" => [0x025EC],
+ "trie" => [0x0225C],
+ "triminus" => [0x02A3A],
+ "triplus" => [0x02A39],
+ "trisb" => [0x029CD],
+ "tritime" => [0x02A3B],
+ "trpezium" => [0x023E2],
+ "tscr" => [0x1D4C9],
+ "tscy" => [0x00446],
+ "tshcy" => [0x0045B],
+ "tstrok" => [0x00167],
+ "twixt" => [0x0226C],
+ "twoheadleftarrow" => [0x0219E],
+ "twoheadrightarrow" => [0x021A0],
+ "uArr" => [0x021D1],
+ "uHar" => [0x02963],
+ "uacute" => [0x000FA],
+ "uarr" => [0x02191],
+ "ubrcy" => [0x0045E],
+ "ubreve" => [0x0016D],
+ "ucirc" => [0x000FB],
+ "ucy" => [0x00443],
+ "udarr" => [0x021C5],
+ "udblac" => [0x00171],
+ "udhar" => [0x0296E],
+ "ufisht" => [0x0297E],
+ "ufr" => [0x1D532],
+ "ugrave" => [0x000F9],
+ "uharl" => [0x021BF],
+ "uharr" => [0x021BE],
+ "uhblk" => [0x02580],
+ "ulcorn" => [0x0231C],
+ "ulcorner" => [0x0231C],
+ "ulcrop" => [0x0230F],
+ "ultri" => [0x025F8],
+ "umacr" => [0x0016B],
+ "uml" => [0x000A8],
+ "uogon" => [0x00173],
+ "uopf" => [0x1D566],
+ "uparrow" => [0x02191],
+ "updownarrow" => [0x02195],
+ "upharpoonleft" => [0x021BF],
+ "upharpoonright" => [0x021BE],
+ "uplus" => [0x0228E],
+ "upsi" => [0x003C5],
+ "upsih" => [0x003D2],
+ "upsilon" => [0x003C5],
+ "upuparrows" => [0x021C8],
+ "urcorn" => [0x0231D],
+ "urcorner" => [0x0231D],
+ "urcrop" => [0x0230E],
+ "uring" => [0x0016F],
+ "urtri" => [0x025F9],
+ "uscr" => [0x1D4CA],
+ "utdot" => [0x022F0],
+ "utilde" => [0x00169],
+ "utri" => [0x025B5],
+ "utrif" => [0x025B4],
+ "uuarr" => [0x021C8],
+ "uuml" => [0x000FC],
+ "uwangle" => [0x029A7],
+ "vArr" => [0x021D5],
+ "vBar" => [0x02AE8],
+ "vBarv" => [0x02AE9],
+ "vDash" => [0x022A8],
+ "vangrt" => [0x0299C],
+ "varepsilon" => [0x003F5],
+ "varkappa" => [0x003F0],
+ "varnothing" => [0x02205],
+ "varphi" => [0x003D5],
+ "varpi" => [0x003D6],
+ "varpropto" => [0x0221D],
+ "varr" => [0x02195],
+ "varrho" => [0x003F1],
+ "varsigma" => [0x003C2],
+ "varsubsetneq" => [0x0228A, 0x0FE00],
+ "varsubsetneqq" => [0x02ACB, 0x0FE00],
+ "varsupsetneq" => [0x0228B, 0x0FE00],
+ "varsupsetneqq" => [0x02ACC, 0x0FE00],
+ "vartheta" => [0x003D1],
+ "vartriangleleft" => [0x022B2],
+ "vartriangleright" => [0x022B3],
+ "vcy" => [0x00432],
+ "vdash" => [0x022A2],
+ "vee" => [0x02228],
+ "veebar" => [0x022BB],
+ "veeeq" => [0x0225A],
+ "vellip" => [0x022EE],
+ "verbar" => [0x0007C],
+ "vert" => [0x0007C],
+ "vfr" => [0x1D533],
+ "vltri" => [0x022B2],
+ "vnsub" => [0x02282, 0x020D2],
+ "vnsup" => [0x02283, 0x020D2],
+ "vopf" => [0x1D567],
+ "vprop" => [0x0221D],
+ "vrtri" => [0x022B3],
+ "vscr" => [0x1D4CB],
+ "vsubnE" => [0x02ACB, 0x0FE00],
+ "vsubne" => [0x0228A, 0x0FE00],
+ "vsupnE" => [0x02ACC, 0x0FE00],
+ "vsupne" => [0x0228B, 0x0FE00],
+ "vzigzag" => [0x0299A],
+ "wcirc" => [0x00175],
+ "wedbar" => [0x02A5F],
+ "wedge" => [0x02227],
+ "wedgeq" => [0x02259],
+ "weierp" => [0x02118],
+ "wfr" => [0x1D534],
+ "wopf" => [0x1D568],
+ "wp" => [0x02118],
+ "wr" => [0x02240],
+ "wreath" => [0x02240],
+ "wscr" => [0x1D4CC],
+ "xcap" => [0x022C2],
+ "xcirc" => [0x025EF],
+ "xcup" => [0x022C3],
+ "xdtri" => [0x025BD],
+ "xfr" => [0x1D535],
+ "xhArr" => [0x027FA],
+ "xharr" => [0x027F7],
+ "xi" => [0x003BE],
+ "xlArr" => [0x027F8],
+ "xlarr" => [0x027F5],
+ "xmap" => [0x027FC],
+ "xnis" => [0x022FB],
+ "xodot" => [0x02A00],
+ "xopf" => [0x1D569],
+ "xoplus" => [0x02A01],
+ "xotime" => [0x02A02],
+ "xrArr" => [0x027F9],
+ "xrarr" => [0x027F6],
+ "xscr" => [0x1D4CD],
+ "xsqcup" => [0x02A06],
+ "xuplus" => [0x02A04],
+ "xutri" => [0x025B3],
+ "xvee" => [0x022C1],
+ "xwedge" => [0x022C0],
+ "yacute" => [0x000FD],
+ "yacy" => [0x0044F],
+ "ycirc" => [0x00177],
+ "ycy" => [0x0044B],
+ "yen" => [0x000A5],
+ "yfr" => [0x1D536],
+ "yicy" => [0x00457],
+ "yopf" => [0x1D56A],
+ "yscr" => [0x1D4CE],
+ "yucy" => [0x0044E],
+ "yuml" => [0x000FF],
+ "zacute" => [0x0017A],
+ "zcaron" => [0x0017E],
+ "zcy" => [0x00437],
+ "zdot" => [0x0017C],
+ "zeetrf" => [0x02128],
+ "zeta" => [0x003B6],
+ "zfr" => [0x1D537],
+ "zhcy" => [0x00436],
+ "zigrarr" => [0x021DD],
+ "zopf" => [0x1D56B],
+ "zscr" => [0x1D4CF],
+ "zwj" => [0x0200D],
+ "zwnj" => [0x0200C],
+}
+
diff --git a/lib/rdoc/markdown/literals_1_9.rb b/lib/rdoc/markdown/literals_1_9.rb
new file mode 100644
index 0000000000..01d00e41f6
--- /dev/null
+++ b/lib/rdoc/markdown/literals_1_9.rb
@@ -0,0 +1,417 @@
+# coding: UTF-8
+# :markup: markdown
+
+##
+#--
+# This set of literals is for ruby 1.9 regular expressions and gives full
+# unicode support.
+#
+# Unlike peg-markdown, this set of literals recognizes Unicode alphanumeric
+# characters, newlines and spaces.
+class RDoc::Markdown::Literals
+ # :stopdoc:
+
+ # This is distinct from setup_parser so that a standalone parser
+ # can redefine #initialize and still have access to the proper
+ # parser setup code.
+ def initialize(str, debug=false)
+ setup_parser(str, debug)
+ end
+
+
+
+ # Prepares for parsing +str+. If you define a custom initialize you must
+ # call this method before #parse
+ def setup_parser(str, debug=false)
+ @string = str
+ @pos = 0
+ @memoizations = Hash.new { |h,k| h[k] = {} }
+ @result = nil
+ @failed_rule = nil
+ @failing_rule_offset = -1
+
+ setup_foreign_grammar
+ end
+
+ attr_reader :string
+ attr_reader :failing_rule_offset
+ attr_accessor :result, :pos
+
+
+ def current_column(target=pos)
+ if c = string.rindex("\n", target-1)
+ return target - c - 1
+ end
+
+ target + 1
+ end
+
+ def current_line(target=pos)
+ cur_offset = 0
+ cur_line = 0
+
+ string.each_line do |line|
+ cur_line += 1
+ cur_offset += line.size
+ return cur_line if cur_offset >= target
+ end
+
+ -1
+ end
+
+ def lines
+ lines = []
+ string.each_line { |l| lines << l }
+ lines
+ end
+
+
+
+ def get_text(start)
+ @string[start..@pos-1]
+ end
+
+ def show_pos
+ width = 10
+ if @pos < width
+ "#{@pos} (\"#{@string[0,@pos]}\" @ \"#{@string[@pos,width]}\")"
+ else
+ "#{@pos} (\"... #{@string[@pos - width, width]}\" @ \"#{@string[@pos,width]}\")"
+ end
+ end
+
+ def failure_info
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+
+ if @failed_rule.kind_of? Symbol
+ info = self.class::Rules[@failed_rule]
+ "line #{l}, column #{c}: failed rule '#{info.name}' = '#{info.rendered}'"
+ else
+ "line #{l}, column #{c}: failed rule '#{@failed_rule}'"
+ end
+ end
+
+ def failure_caret
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+
+ line = lines[l-1]
+ "#{line}\n#{' ' * (c - 1)}^"
+ end
+
+ def failure_character
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+ lines[l-1][c-1, 1]
+ end
+
+ def failure_oneline
+ l = current_line @failing_rule_offset
+ c = current_column @failing_rule_offset
+
+ char = lines[l-1][c-1, 1]
+
+ if @failed_rule.kind_of? Symbol
+ info = self.class::Rules[@failed_rule]
+ "@#{l}:#{c} failed rule '#{info.name}', got '#{char}'"
+ else
+ "@#{l}:#{c} failed rule '#{@failed_rule}', got '#{char}'"
+ end
+ end
+
+ class ParseError < RuntimeError
+ end
+
+ def raise_error
+ raise ParseError, failure_oneline
+ end
+
+ def show_error(io=STDOUT)
+ error_pos = @failing_rule_offset
+ line_no = current_line(error_pos)
+ col_no = current_column(error_pos)
+
+ io.puts "On line #{line_no}, column #{col_no}:"
+
+ if @failed_rule.kind_of? Symbol
+ info = self.class::Rules[@failed_rule]
+ io.puts "Failed to match '#{info.rendered}' (rule '#{info.name}')"
+ else
+ io.puts "Failed to match rule '#{@failed_rule}'"
+ end
+
+ io.puts "Got: #{string[error_pos,1].inspect}"
+ line = lines[line_no-1]
+ io.puts "=> #{line}"
+ io.print(" " * (col_no + 3))
+ io.puts "^"
+ end
+
+ def set_failed_rule(name)
+ if @pos > @failing_rule_offset
+ @failed_rule = name
+ @failing_rule_offset = @pos
+ end
+ end
+
+ attr_reader :failed_rule
+
+ def match_string(str)
+ len = str.size
+ if @string[pos,len] == str
+ @pos += len
+ return str
+ end
+
+ return nil
+ end
+
+ def scan(reg)
+ if m = reg.match(@string[@pos..-1])
+ width = m.end(0)
+ @pos += width
+ return true
+ end
+
+ return nil
+ end
+
+ if "".respond_to? :getbyte
+ def get_byte
+ if @pos >= @string.size
+ return nil
+ end
+
+ s = @string.getbyte @pos
+ @pos += 1
+ s
+ end
+ else
+ def get_byte
+ if @pos >= @string.size
+ return nil
+ end
+
+ s = @string[@pos]
+ @pos += 1
+ s
+ end
+ end
+
+ def parse(rule=nil)
+ # We invoke the rules indirectly via apply
+ # instead of by just calling them as methods because
+ # if the rules use left recursion, apply needs to
+ # manage that.
+
+ if !rule
+ apply(:_root)
+ else
+ method = rule.gsub("-","_hyphen_")
+ apply :"_#{method}"
+ end
+ end
+
+ class MemoEntry
+ def initialize(ans, pos)
+ @ans = ans
+ @pos = pos
+ @result = nil
+ @set = false
+ @left_rec = false
+ end
+
+ attr_reader :ans, :pos, :result, :set
+ attr_accessor :left_rec
+
+ def move!(ans, pos, result)
+ @ans = ans
+ @pos = pos
+ @result = result
+ @set = true
+ @left_rec = false
+ end
+ end
+
+ def external_invoke(other, rule, *args)
+ old_pos = @pos
+ old_string = @string
+
+ @pos = other.pos
+ @string = other.string
+
+ begin
+ if val = __send__(rule, *args)
+ other.pos = @pos
+ other.result = @result
+ else
+ other.set_failed_rule "#{self.class}##{rule}"
+ end
+ val
+ ensure
+ @pos = old_pos
+ @string = old_string
+ end
+ end
+
+ def apply_with_args(rule, *args)
+ memo_key = [rule, args]
+ if m = @memoizations[memo_key][@pos]
+ @pos = m.pos
+ if !m.set
+ m.left_rec = true
+ return nil
+ end
+
+ @result = m.result
+
+ return m.ans
+ else
+ m = MemoEntry.new(nil, @pos)
+ @memoizations[memo_key][@pos] = m
+ start_pos = @pos
+
+ ans = __send__ rule, *args
+
+ lr = m.left_rec
+
+ m.move! ans, @pos, @result
+
+ # Don't bother trying to grow the left recursion
+ # if it's failing straight away (thus there is no seed)
+ if ans and lr
+ return grow_lr(rule, args, start_pos, m)
+ else
+ return ans
+ end
+
+ return ans
+ end
+ end
+
+ def apply(rule)
+ if m = @memoizations[rule][@pos]
+ @pos = m.pos
+ if !m.set
+ m.left_rec = true
+ return nil
+ end
+
+ @result = m.result
+
+ return m.ans
+ else
+ m = MemoEntry.new(nil, @pos)
+ @memoizations[rule][@pos] = m
+ start_pos = @pos
+
+ ans = __send__ rule
+
+ lr = m.left_rec
+
+ m.move! ans, @pos, @result
+
+ # Don't bother trying to grow the left recursion
+ # if it's failing straight away (thus there is no seed)
+ if ans and lr
+ return grow_lr(rule, nil, start_pos, m)
+ else
+ return ans
+ end
+
+ return ans
+ end
+ end
+
+ def grow_lr(rule, args, start_pos, m)
+ while true
+ @pos = start_pos
+ @result = m.result
+
+ if args
+ ans = __send__ rule, *args
+ else
+ ans = __send__ rule
+ end
+ return nil unless ans
+
+ break if @pos <= m.pos
+
+ m.move! ans, @pos, @result
+ end
+
+ @result = m.result
+ @pos = m.pos
+ return m.ans
+ end
+
+ class RuleInfo
+ def initialize(name, rendered)
+ @name = name
+ @rendered = rendered
+ end
+
+ attr_reader :name, :rendered
+ end
+
+ def self.rule_info(name, rendered)
+ RuleInfo.new(name, rendered)
+ end
+
+
+ # :startdoc:
+ # :stopdoc:
+ def setup_foreign_grammar; end
+
+ # Alphanumeric = /\p{Word}/
+ def _Alphanumeric
+ _tmp = scan(/\A(?-mix:\p{Word})/)
+ set_failed_rule :_Alphanumeric unless _tmp
+ return _tmp
+ end
+
+ # AlphanumericAscii = /[A-Za-z0-9]/
+ def _AlphanumericAscii
+ _tmp = scan(/\A(?-mix:[A-Za-z0-9])/)
+ set_failed_rule :_AlphanumericAscii unless _tmp
+ return _tmp
+ end
+
+ # BOM = "uFEFF"
+ def _BOM
+ _tmp = match_string("uFEFF")
+ set_failed_rule :_BOM unless _tmp
+ return _tmp
+ end
+
+ # Newline = /\n|\r\n?|\p{Zl}|\p{Zp}/
+ def _Newline
+ _tmp = scan(/\A(?-mix:\n|\r\n?|\p{Zl}|\p{Zp})/)
+ set_failed_rule :_Newline unless _tmp
+ return _tmp
+ end
+
+ # NonAlphanumeric = /\p{^Word}/
+ def _NonAlphanumeric
+ _tmp = scan(/\A(?-mix:\p{^Word})/)
+ set_failed_rule :_NonAlphanumeric unless _tmp
+ return _tmp
+ end
+
+ # Spacechar = /\t|\p{Zs}/
+ def _Spacechar
+ _tmp = scan(/\A(?-mix:\t|\p{Zs})/)
+ set_failed_rule :_Spacechar unless _tmp
+ return _tmp
+ end
+
+ Rules = {}
+ Rules[:_Alphanumeric] = rule_info("Alphanumeric", "/\\p{Word}/")
+ Rules[:_AlphanumericAscii] = rule_info("AlphanumericAscii", "/[A-Za-z0-9]/")
+ Rules[:_BOM] = rule_info("BOM", "\"uFEFF\"")
+ Rules[:_Newline] = rule_info("Newline", "/\\n|\\r\\n?|\\p{Zl}|\\p{Zp}/")
+ Rules[:_NonAlphanumeric] = rule_info("NonAlphanumeric", "/\\p{^Word}/")
+ Rules[:_Spacechar] = rule_info("Spacechar", "/\\t|\\p{Zs}/")
+ # :startdoc:
+end
diff --git a/lib/rdoc/markup.rb b/lib/rdoc/markup.rb
index 07fd5493c8..bdd2064d6f 100644
--- a/lib/rdoc/markup.rb
+++ b/lib/rdoc/markup.rb
@@ -1,5 +1,3 @@
-require 'rdoc'
-
##
# RDoc::Markup parses plain text documents and attempts to decompose them into
# their constituent parts. Some of these parts are high-level: paragraphs,
@@ -8,11 +6,44 @@ require 'rdoc'
# is similar in spirit to that used on WikiWiki webs, where folks create web
# pages using a simple set of formatting rules.
#
-# RDoc::Markup itself does no output formatting: this is left to a different
-# set of classes.
+# RDoc::Markup and other markup formats do no output formatting, this is
+# handled by the RDoc::Markup::Formatter subclasses.
+#
+# = Supported Formats
+#
+# Besides the RDoc::Markup format, the following formats are built in to RDoc:
+#
+# markdown::
+# The markdown format as described by
+# http://daringfireball.net/projects/markdown/. See RDoc::Markdown for
+# details on the parser and supported extensions.
+# rd::
+# The rdtool format. See RDoc::RD for details on the parser and format.
+# tomdoc::
+# The TomDoc format as described by http://tomdoc.org/. See RDoc::TomDoc
+# for details on the parser and supported extensions.
+#
+# You can choose a markup format using the following methods:
+#
+# per project::
+# If you build your documentation with rake use RDoc::Task#markup.
+#
+# If you build your documentation by hand run:
#
-# RDoc::Markup is extendable at runtime: you can add \new markup elements to
-# be recognised in the documents that RDoc::Markup parses.
+# rdoc --markup your_favorite_format --write-options
+#
+# and commit <tt>.rdoc_options</tt> and ship it with your packaged gem.
+# per file::
+# At the top of the file use the <tt>:markup:</tt> directive to set the
+# default format for the rest of the file.
+# per comment::
+# Use the <tt>:markup:</tt> directive at the top of a comment you want
+# to write in a different format.
+#
+# = RDoc::Markup
+#
+# RDoc::Markup is extensible at runtime: you can add \new markup elements to
+# be recognized in the documents that RDoc::Markup parses.
#
# RDoc::Markup is intended to be the basis for a family of tools which share
# the common requirement that simple, plain-text should be rendered in a
@@ -26,21 +57,20 @@ require 'rdoc'
# the +convert+ method, so you can use the same RDoc::Markup converter to
# convert multiple input strings.
#
-# require 'rdoc/markup/to_html'
+# require 'rdoc'
#
# h = RDoc::Markup::ToHtml.new
#
# puts h.convert(input_string)
#
-# You can extend the RDoc::Markup parser to recognise new markup
+# You can extend the RDoc::Markup parser to recognize new markup
# sequences, and to add special processing for text that matches a
# regular expression. Here we make WikiWords significant to the parser,
# and also make the sequences {word} and \<no>text...</no> signify
# strike-through text. We then subclass the HTML output class to deal
# with these:
#
-# require 'rdoc/markup'
-# require 'rdoc/markup/to_html'
+# require 'rdoc'
#
# class WikiHtml < RDoc::Markup::ToHtml
# def handle_special_WIKIWORD(special)
@@ -96,7 +126,12 @@ require 'rdoc'
# have been removed. In addition, the verbatim text has been shifted
# left, so the amount of indentation of verbatim text is unimportant.
#
-# === Headers and Rules
+# For HTML output RDoc makes a small effort to determine if a verbatim section
+# contains ruby source code. If so, the verbatim block will be marked up as
+# HTML. Triggers include "def", "class", "module", "require", the "hash
+# rocket"# (=>) or a block call with a parameter.
+#
+# === Headers
#
# A line starting with an equal sign (=) is treated as a
# heading. Level one headings have one equals sign, level two headings
@@ -104,7 +139,36 @@ require 'rdoc'
# (seven hyphens or more result in a level six heading).
#
# For example, the above header was obtained with:
-# == Headers and Rules
+#
+# === Headers
+#
+# In HTML output headers have an id matching their name. The above example's
+# HTML is:
+#
+# <h3 id="label-Headers">Headers</h3>
+#
+# If a heading is inside a method body the id will be prefixed with the
+# method's id. If the above header where in the documentation for a method
+# such as:
+#
+# ##
+# # This method does fun things
+# #
+# # = Example
+# #
+# # Example of fun things goes here ...
+#
+# def do_fun_things
+# end
+#
+# The header's id would be:
+#
+# <h1 id="method-i-do_fun_things-label-Example">Example</h3>
+#
+# The label can be linked-to using <tt>SomeClass@Headers</tt>. See
+# {Links}[RDoc::Markup@Links] for further details.
+#
+# === Rules
#
# A line starting with three or more hyphens (at the current indent)
# generates a horizontal rule. The more hyphens, the thicker the rule
@@ -240,7 +304,6 @@ require 'rdoc'
# verbatim text outside of the list (the list is therefore closed)
# regular paragraph after the list
#
-#
# == Text Markup
#
# === Bold, Italic, Typewriter Text
@@ -272,15 +335,26 @@ require 'rdoc'
# === Links
#
# Links to starting with +http:+, +https:+, +mailto:+, +ftp:+ or +www.+
-# are recognized. An HTTP url that references an external image file is
-# converted into an inline image element.
-#
-# Links starting with <tt>rdoc-ref:</tt> will link to the referenced class,
-# module, method, file, etc. If the referenced item is not documented the
-# text will be and no link will be generated.
-#
-# Links starting with +link:+ refer to local files whose path is relative to
-# the <tt>--op</tt> directory.
+# are recognized. An HTTP url that references an external image is converted
+# into an inline image element.
+#
+# Classes and methods will be automatically linked to their definition. For
+# example, <tt>RDoc::Markup</tt> will link to this documentation. By default
+# methods will only be automatically linked if they contain an <tt>_</tt> (all
+# methods can be automatically linked through the <tt>--hyperlink-all</tt>
+# command line option).
+#
+# Single-word methods can be linked by using the <tt>#</tt> character for
+# instance methods or <tt>::</tt> for class methods. For example,
+# <tt>#convert</tt> links to #convert. A class or method may be combined like
+# <tt>RDoc::Markup#convert</tt>.
+#
+# A heading inside the documentation can be linked by following the class
+# or method by an <tt>@</tt> then the heading name.
+# <tt>RDoc::Markup@Links</tt> will link to this section like this:
+# RDoc::Markup@Links. Spaces in headings with multiple words must be escaped
+# with <tt>+</tt> like <tt>RDoc::Markup@Escaping+Text+Markup</tt>.
+# Punctuation and other special characters must be escaped like CGI.escape.
#
# Links can also be of the form <tt>label[url]</tt>, in which case +label+ is
# used in the displayed text, and +url+ is used as the target. If +label+
@@ -293,6 +367,11 @@ require 'rdoc'
# no link will be generated and <tt>rdoc-ref:</tt> will be removed from the
# resulting text.
#
+# Links starting with <tt>rdoc-label:label_name</tt> will link to the
+# +label_name+. You can create a label for the current link (for
+# bidirectional links) by supplying a name for the current link like
+# <tt>rdoc-label:label-other:label-mine</tt>.
+#
# Links starting with +link:+ refer to local files whose path is relative to
# the <tt>--op</tt> directory. Use <tt>rdoc-ref:</tt> instead of
# <tt>link:</tt> to link to files generated by RDoc as the link target may
@@ -492,27 +571,54 @@ require 'rdoc'
# so you won't see the documentation unless you use the +-a+ command line
# option.
#
-# === Other directives
+# === Method arguments
#
-# [+:include:+ _filename_]
-# Include the contents of the named file at this point. This directive
-# must appear alone on one line, possibly preceded by spaces. In this
-# position, it can be escaped with a \ in front of the first colon.
+# [+:arg:+ or +:args:+ _parameters_]
+# Overrides the default argument handling with exactly these parameters.
#
-# The file will be searched for in the directories listed by the +--include+
-# option, or in the current directory by default. The contents of the file
-# will be shifted to have the same indentation as the ':' at the start of
-# the +:include:+ directive.
+# ##
+# # :args: a, b
#
-# [+:title:+ _text_]
-# Sets the title for the document. Equivalent to the <tt>--title</tt>
-# command line parameter. (The command line parameter overrides any :title:
-# directive in the source).
+# def some_method(*a)
+# end
#
-# [+:main:+ _name_]
-# Equivalent to the <tt>--main</tt> command line parameter.
+# [+:yield:+ or +:yields:+ _parameters_]
+# Overrides the default yield discovery with these parameters.
+#
+# ##
+# # :yields: key, value
+#
+# def each_thing &block
+# @things.each(&block)
+# end
+#
+# [+:call-seq:+]
+# Lines up to the next blank line or lines with a common prefix in the
+# comment are treated as the method's calling sequence, overriding the
+# default parsing of method parameters and yield arguments.
+#
+# Multiple lines may be used.
+#
+# # :call-seq:
+# # ARGF.readlines(sep=$/) -> array
+# # ARGF.readlines(limit) -> array
+# # ARGF.readlines(sep, limit) -> array
+# #
+# # ARGF.to_a(sep=$/) -> array
+# # ARGF.to_a(limit) -> array
+# # ARGF.to_a(sep, limit) -> array
+# #
+# # The remaining lines are documentation ...
+#
+# === Sections
#
-# [<tt>:category: section</tt>]
+# Sections allow you to group methods in a class into sensible containers. If
+# you use the sections 'Public', 'Internal' and 'Deprecated' (the three
+# allowed method statuses from TomDoc) the sections will be displayed in that
+# order placing the most useful methods at the top. Otherwise, sections will
+# be displayed in alphabetical order.
+#
+# [+:category:+ _section_]
# Adds this item to the named +section+ overriding the current section. Use
# this to group methods by section in RDoc output while maintaining a
# sensible ordering (like alphabetical).
@@ -541,7 +647,7 @@ require 'rdoc'
# Use the :section: directive to provide introductory text for a section of
# documentation.
#
-# [<tt>:section: title</tt>]
+# [+:section:+ _title_]
# Provides section introductory text in RDoc output. The title following
# +:section:+ is used as the section name and the remainder of the comment
# containing the section is used as introductory text. A section's comment
@@ -573,12 +679,60 @@ require 'rdoc'
# # ...
# end
#
-# [+:call-seq:+]
-# Lines up to the next blank line in the comment are treated as the method's
-# calling sequence, overriding the default parsing of method parameters and
-# yield arguments.
+# === Other directives
+#
+# [+:markup:+ _type_]
+# Overrides the default markup type for this comment with the specified
+# markup type. For ruby files, if the first comment contains this directive
+# it is applied automatically to all comments in the file.
+#
+# Unless you are converting between markup formats you should use a
+# <code>.rdoc_options</code> file to specify the default documentation
+# format for your entire project. See RDoc::Options@Saved+Options for
+# instructions.
+#
+# At the top of a file the +:markup:+ directive applies to the entire file:
+#
+# # coding: UTF-8
+# # :markup: TomDoc
+#
+# # TomDoc comment here ...
+#
+# class MyClass
+# # ...
+#
+# For just one comment:
+#
+# # ...
+# end
+#
+# # :markup: RDoc
+# #
+# # This is a comment in RDoc markup format ...
+#
+# def some_method
+# # ...
+#
+# See Markup@DEVELOPERS for instructions on adding a new markup format.
+#
+# [+:include:+ _filename_]
+# Include the contents of the named file at this point. This directive
+# must appear alone on one line, possibly preceded by spaces. In this
+# position, it can be escaped with a \ in front of the first colon.
+#
+# The file will be searched for in the directories listed by the +--include+
+# option, or in the current directory by default. The contents of the file
+# will be shifted to have the same indentation as the ':' at the start of
+# the +:include:+ directive.
+#
+# [+:title:+ _text_]
+# Sets the title for the document. Equivalent to the <tt>--title</tt>
+# command line parameter. (The command line parameter overrides any :title:
+# directive in the source).
+#
+# [+:main:+ _name_]
+# Equivalent to the <tt>--main</tt> command line parameter.
#
-# Further directives can be found in RDoc::Parser::Ruby and RDoc::Parser::C.
#--
# Original Author:: Dave Thomas, dave@pragmaticprogrammer.com
# License:: Ruby license
@@ -591,6 +745,34 @@ class RDoc::Markup
attr_reader :attribute_manager
##
+ # Parses +str+ into an RDoc::Markup::Document.
+
+ def self.parse str
+ RDoc::Markup::Parser.parse str
+ rescue RDoc::Markup::Parser::Error => e
+ $stderr.puts <<-EOF
+While parsing markup, RDoc encountered a #{e.class}:
+
+#{e}
+\tfrom #{e.backtrace.join "\n\tfrom "}
+
+---8<---
+#{text}
+---8<---
+
+RDoc #{RDoc::VERSION}
+
+Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} #{RUBY_RELEASE_DATE}
+
+Please file a bug report with the above information at:
+
+https://github.com/rdoc/rdoc/issues
+
+ EOF
+ raise
+ end
+
+ ##
# Take a block of text and use various heuristics to determine its
# structure (paragraphs, lists, and so on). Invoke an event handler as we
# identify significant chunks.
@@ -644,9 +826,47 @@ class RDoc::Markup
document.accept formatter
end
-end
+ autoload :Parser, 'rdoc/markup/parser'
+ autoload :PreProcess, 'rdoc/markup/pre_process'
+
+ # Inline markup classes
+ autoload :AttrChanger, 'rdoc/markup/attr_changer'
+ autoload :AttrSpan, 'rdoc/markup/attr_span'
+ autoload :Attributes, 'rdoc/markup/attributes'
+ autoload :AttributeManager, 'rdoc/markup/attribute_manager'
+ autoload :Special, 'rdoc/markup/special'
+
+ # RDoc::Markup AST
+ autoload :BlankLine, 'rdoc/markup/blank_line'
+ autoload :BlockQuote, 'rdoc/markup/block_quote'
+ autoload :Document, 'rdoc/markup/document'
+ autoload :HardBreak, 'rdoc/markup/hard_break'
+ autoload :Heading, 'rdoc/markup/heading'
+ autoload :Include, 'rdoc/markup/include'
+ autoload :IndentedParagraph, 'rdoc/markup/indented_paragraph'
+ autoload :List, 'rdoc/markup/list'
+ autoload :ListItem, 'rdoc/markup/list_item'
+ autoload :Paragraph, 'rdoc/markup/paragraph'
+ autoload :Raw, 'rdoc/markup/raw'
+ autoload :Rule, 'rdoc/markup/rule'
+ autoload :Verbatim, 'rdoc/markup/verbatim'
-require 'rdoc/markup/parser'
-require 'rdoc/markup/attribute_manager'
-require 'rdoc/markup/inline'
+ # Formatters
+ autoload :Formatter, 'rdoc/markup/formatter'
+ autoload :FormatterTestCase, 'rdoc/markup/formatter_test_case'
+ autoload :TextFormatterTestCase, 'rdoc/markup/text_formatter_test_case'
+
+ autoload :ToAnsi, 'rdoc/markup/to_ansi'
+ autoload :ToBs, 'rdoc/markup/to_bs'
+ autoload :ToHtml, 'rdoc/markup/to_html'
+ autoload :ToHtmlCrossref, 'rdoc/markup/to_html_crossref'
+ autoload :ToHtmlSnippet, 'rdoc/markup/to_html_snippet'
+ autoload :ToLabel, 'rdoc/markup/to_label'
+ autoload :ToMarkdown, 'rdoc/markup/to_markdown'
+ autoload :ToRdoc, 'rdoc/markup/to_rdoc'
+ autoload :ToTableOfContents, 'rdoc/markup/to_table_of_contents'
+ autoload :ToTest, 'rdoc/markup/to_test'
+ autoload :ToTtOnly, 'rdoc/markup/to_tt_only'
+
+end
diff --git a/lib/rdoc/markup/attr_changer.rb b/lib/rdoc/markup/attr_changer.rb
new file mode 100644
index 0000000000..1772f18b2b
--- /dev/null
+++ b/lib/rdoc/markup/attr_changer.rb
@@ -0,0 +1,22 @@
+class RDoc::Markup
+
+ AttrChanger = Struct.new :turn_on, :turn_off # :nodoc:
+
+end
+
+##
+# An AttrChanger records a change in attributes. It contains a bitmap of the
+# attributes to turn on, and a bitmap of those to turn off.
+
+class RDoc::Markup::AttrChanger
+
+ def to_s # :nodoc:
+ "Attr: +#{turn_on}/-#{turn_off}"
+ end
+
+ def inspect # :nodoc:
+ '+%d/-%d' % [turn_on, turn_off]
+ end
+
+end
+
diff --git a/lib/rdoc/markup/attr_span.rb b/lib/rdoc/markup/attr_span.rb
new file mode 100644
index 0000000000..b5c1b3b7b7
--- /dev/null
+++ b/lib/rdoc/markup/attr_span.rb
@@ -0,0 +1,29 @@
+##
+# An array of attributes which parallels the characters in a string.
+
+class RDoc::Markup::AttrSpan
+
+ ##
+ # Creates a new AttrSpan for +length+ characters
+
+ def initialize(length)
+ @attrs = Array.new(length, 0)
+ end
+
+ ##
+ # Toggles +bits+ from +start+ to +length+
+ def set_attrs(start, length, bits)
+ for i in start ... (start+length)
+ @attrs[i] |= bits
+ end
+ end
+
+ ##
+ # Accesses flags for character +n+
+
+ def [](n)
+ @attrs[n]
+ end
+
+end
+
diff --git a/lib/rdoc/markup/attribute_manager.rb b/lib/rdoc/markup/attribute_manager.rb
index d2402f1b1d..71d5e2b2cc 100644
--- a/lib/rdoc/markup/attribute_manager.rb
+++ b/lib/rdoc/markup/attribute_manager.rb
@@ -23,6 +23,11 @@ class RDoc::Markup::AttributeManager
PROTECT_ATTR = A_PROTECT.chr # :nodoc:
##
+ # The attributes enabled for this markup object.
+
+ attr_reader :attributes
+
+ ##
# This maps delimiters that occur around words (such as *bold* or +tt+)
# where the start and end delimiters and the same. This lets us optimize
# the regexp
@@ -60,8 +65,9 @@ class RDoc::Markup::AttributeManager
@html_tags = {}
@matching_word_pairs = {}
@protectable = %w[<]
- @special = {}
+ @special = []
@word_pair_map = {}
+ @attributes = RDoc::Markup::Attributes.new
add_word_pair "*", "*", :BOLD
add_word_pair "_", "_", :EM
@@ -96,11 +102,11 @@ class RDoc::Markup::AttributeManager
def changed_attribute_by_name current_set, new_set
current = new = 0
current_set.each do |name|
- current |= RDoc::Markup::Attribute.bitmap_for(name)
+ current |= @attributes.bitmap_for(name)
end
new_set.each do |name|
- new |= RDoc::Markup::Attribute.bitmap_for(name)
+ new |= @attributes.bitmap_for(name)
end
change_attribute(current, new)
@@ -161,12 +167,15 @@ class RDoc::Markup::AttributeManager
##
# Converts special sequences to RDoc attributes
- def convert_specials(str, attrs)
+ def convert_specials str, attrs
unless @special.empty?
- @special.each do |regexp, attr|
+ @special.each do |regexp, attribute|
str.scan(regexp) do
- attrs.set_attrs($`.length, $&.length,
- attr | RDoc::Markup::Attribute::SPECIAL)
+ capture = $~.size == 1 ? 0 : 1
+
+ s, e = $~.offset capture
+
+ attrs.set_attrs s, e - s, attribute | @attributes.special
end
end
end
@@ -200,7 +209,7 @@ class RDoc::Markup::AttributeManager
raise ArgumentError, "Word flags may not start with '<'" if
start[0,1] == '<'
- bitmap = RDoc::Markup::Attribute.bitmap_for name
+ bitmap = @attributes.bitmap_for name
if start == stop then
@matching_word_pairs[start] = bitmap
@@ -220,7 +229,7 @@ class RDoc::Markup::AttributeManager
# am.add_html 'em', :EM
def add_html(tag, name)
- @html_tags[tag.downcase] = RDoc::Markup::Attribute.bitmap_for name
+ @html_tags[tag.downcase] = @attributes.bitmap_for name
end
##
@@ -229,14 +238,14 @@ class RDoc::Markup::AttributeManager
#
# @am.add_special(/((https?:)\S+\w)/, :HYPERLINK)
- def add_special(pattern, name)
- @special[pattern] = RDoc::Markup::Attribute.bitmap_for name
+ def add_special pattern, name
+ @special << [pattern, @attributes.bitmap_for(name)]
end
##
# Processes +str+ converting attributes, HTML and specials
- def flow(str)
+ def flow str
@str = str
mask_protected_sequences
@@ -303,9 +312,9 @@ class RDoc::Markup::AttributeManager
res << change_attribute(current_attr, new_attr)
current_attr = new_attr
- if (current_attr & RDoc::Markup::Attribute::SPECIAL) != 0 then
+ if (current_attr & @attributes.special) != 0 then
i += 1 while
- i < str_len and (@attrs[i] & RDoc::Markup::Attribute::SPECIAL) != 0
+ i < str_len and (@attrs[i] & @attributes.special) != 0
res << RDoc::Markup::Special.new(current_attr,
copy_string(start_pos, i))
diff --git a/lib/rdoc/markup/attributes.rb b/lib/rdoc/markup/attributes.rb
new file mode 100644
index 0000000000..3423f10ca7
--- /dev/null
+++ b/lib/rdoc/markup/attributes.rb
@@ -0,0 +1,70 @@
+##
+# We manage a set of attributes. Each attribute has a symbol name and a bit
+# value.
+
+class RDoc::Markup::Attributes
+
+ ##
+ # The special attribute type. See RDoc::Markup#add_special
+
+ attr_reader :special
+
+ ##
+ # Creates a new attributes set.
+
+ def initialize
+ @special = 1
+
+ @name_to_bitmap = [
+ [:_SPECIAL_, @special],
+ ]
+
+ @next_bitmap = @special << 1
+ end
+
+ ##
+ # Returns a unique bit for +name+
+
+ def bitmap_for name
+ bitmap = @name_to_bitmap.assoc name
+
+ unless bitmap then
+ bitmap = @next_bitmap
+ @next_bitmap <<= 1
+ @name_to_bitmap << [name, bitmap]
+ else
+ bitmap = bitmap.last
+ end
+
+ bitmap
+ end
+
+ ##
+ # Returns a string representation of +bitmap+
+
+ def as_string bitmap
+ return 'none' if bitmap.zero?
+ res = []
+
+ @name_to_bitmap.each do |name, bit|
+ res << name if (bitmap & bit) != 0
+ end
+
+ res.join ','
+ end
+
+ ##
+ # yields each attribute name in +bitmap+
+
+ def each_name_of bitmap
+ return enum_for __method__, bitmap unless block_given?
+
+ @name_to_bitmap.each do |name, bit|
+ next if bit == @special
+
+ yield name.to_s if (bitmap & bit) != 0
+ end
+ end
+
+end
+
diff --git a/lib/rdoc/markup/block_quote.rb b/lib/rdoc/markup/block_quote.rb
new file mode 100644
index 0000000000..552f0c4baa
--- /dev/null
+++ b/lib/rdoc/markup/block_quote.rb
@@ -0,0 +1,14 @@
+##
+# A quoted section which contains markup items.
+
+class RDoc::Markup::BlockQuote < RDoc::Markup::Raw
+
+ ##
+ # Calls #accept_block_quote on +visitor+
+
+ def accept visitor
+ visitor.accept_block_quote self
+ end
+
+end
+
diff --git a/lib/rdoc/markup/document.rb b/lib/rdoc/markup/document.rb
index 7077f357d3..198cef9ed9 100644
--- a/lib/rdoc/markup/document.rb
+++ b/lib/rdoc/markup/document.rb
@@ -3,11 +3,13 @@
class RDoc::Markup::Document
+ include Enumerable
+
##
# The file this document was created from. See also
# RDoc::ClassModule#add_comment
- attr_accessor :file
+ attr_reader :file
##
# The parts of the Document
@@ -19,7 +21,7 @@ class RDoc::Markup::Document
def initialize *parts
@parts = []
- @parts.push(*parts)
+ @parts.concat parts
@file = nil
end
@@ -31,7 +33,7 @@ class RDoc::Markup::Document
case part
when RDoc::Markup::Document then
unless part.empty? then
- parts.push(*part.parts)
+ parts.concat part.parts
parts << RDoc::Markup::BlankLine.new
end
when String then
@@ -68,6 +70,20 @@ class RDoc::Markup::Document
end
##
+ # Concatenates the given +parts+ onto the document
+
+ def concat parts
+ self.parts.concat parts
+ end
+
+ ##
+ # Enumerator for the parts of this document
+
+ def each &block
+ @parts.each(&block)
+ end
+
+ ##
# Does this document have no parts?
def empty?
@@ -75,6 +91,18 @@ class RDoc::Markup::Document
end
##
+ # The file this Document was created from.
+
+ def file= location
+ @file = case location
+ when RDoc::TopLevel then
+ location.absolute_name
+ else
+ location
+ end
+ end
+
+ ##
# When this is a collection of documents (#file is not set and this document
# contains only other documents as its direct children) #merge replaces
# documents in this class with documents from +other+ when the file matches
@@ -120,7 +148,16 @@ class RDoc::Markup::Document
# Appends +parts+ to the document
def push *parts
- self.parts.push(*parts)
+ self.parts.concat parts
+ end
+
+ ##
+ # Returns an Array of headings in the document.
+ #
+ # Require 'rdoc/markup/formatter' before calling this method.
+
+ def table_of_contents
+ accept RDoc::Markup::ToTableOfContents.to_toc
end
end
diff --git a/lib/rdoc/markup/formatter.rb b/lib/rdoc/markup/formatter.rb
index f42b3fc6ea..ac76db3536 100644
--- a/lib/rdoc/markup/formatter.rb
+++ b/lib/rdoc/markup/formatter.rb
@@ -1,9 +1,9 @@
-require 'rdoc/markup'
-
##
# Base class for RDoc markup formatters
#
-# Formatters use a visitor pattern to convert content into output.
+# Formatters are a visitor that converts an RDoc::Markup tree (from a comment)
+# into some kind of output. RDoc ships with formatters for converting back to
+# rdoc, ANSI text, HTML, a Table of Contents and other formats.
#
# If you'd like to write your own Formatter use
# RDoc::Markup::FormatterTestCase. If you're writing a text-output formatter
@@ -20,14 +20,21 @@ class RDoc::Markup::Formatter
##
# Creates a new Formatter
- def initialize markup = nil
+ def initialize options, markup = nil
+ @options = options
+
@markup = markup || RDoc::Markup.new
@am = @markup.attribute_manager
+ @am.add_special(/<br>/, :HARD_BREAK)
+
+ @attributes = @am.attributes
@attr_tags = []
@in_tt = 0
- @tt_bit = RDoc::Markup::Attribute.bitmap_for :TT
+ @tt_bit = @attributes.bitmap_for :TT
+
+ @hard_break = ''
end
##
@@ -44,7 +51,7 @@ class RDoc::Markup::Formatter
# tags for flexibility
def add_tag(name, start, stop)
- attr = RDoc::Markup::Attribute.bitmap_for name
+ attr = @attributes.bitmap_for name
@attr_tags << InlineTag.new(attr, start, stop)
end
@@ -58,7 +65,7 @@ class RDoc::Markup::Formatter
##
# Marks up +content+
- def convert(content)
+ def convert content
@markup.convert content, self
end
@@ -93,7 +100,7 @@ class RDoc::Markup::Formatter
handled = false
- RDoc::Markup::Attribute.each_name_of special.type do |name|
+ @attributes.each_name_of special.type do |name|
method_name = "handle_special_#{name}"
if respond_to? method_name then
@@ -102,7 +109,11 @@ class RDoc::Markup::Formatter
end
end
- raise "Unhandled special: #{special}" unless handled
+ unless handled then
+ special_name = @attributes.as_string special.type
+
+ raise RDoc::Error, "Unhandled special #{special_name}: #{special}"
+ end
special.text
end
@@ -115,6 +126,17 @@ class RDoc::Markup::Formatter
end
##
+ # Use ignore in your subclass to ignore the content of a node.
+ #
+ # ##
+ # # We don't support raw nodes in ToNoRaw
+ #
+ # alias accept_raw ignore
+
+ def ignore *node
+ end
+
+ ##
# Are we currently inside tt tags?
def in_tt?
@@ -160,10 +182,3 @@ class RDoc::Markup::Formatter
end
-class RDoc::Markup
- autoload :ToAnsi, 'rdoc/markup/to_ansi'
- autoload :ToBs, 'rdoc/markup/to_bs'
- autoload :ToHtml, 'rdoc/markup/to_html'
- autoload :ToHtmlCrossref, 'rdoc/markup/to_html_crossref'
- autoload :ToRdoc, 'rdoc/markup/to_rdoc'
-end
diff --git a/lib/rdoc/markup/formatter_test_case.rb b/lib/rdoc/markup/formatter_test_case.rb
index c739f990b3..6616a75898 100644
--- a/lib/rdoc/markup/formatter_test_case.rb
+++ b/lib/rdoc/markup/formatter_test_case.rb
@@ -1,5 +1,4 @@
require 'minitest/unit'
-require 'rdoc/markup/formatter'
##
# Test case for creating new RDoc::Markup formatters. See
@@ -35,7 +34,7 @@ require 'rdoc/markup/formatter'
#
# end
-class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
+class RDoc::Markup::FormatterTestCase < RDoc::TestCase
##
# Call #setup when inheriting from this test case.
@@ -54,8 +53,9 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
def setup
super
- @m = RDoc::Markup.new
- @RM = RDoc::Markup
+ @options = RDoc::Options.new
+
+ @m = @RM.new
@bullet_list = @RM::List.new(:BULLET,
@RM::ListItem.new(nil, @RM::Paragraph.new('l1')),
@@ -86,7 +86,7 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
# Call to add the visitor tests to your test case
def self.add_visitor_tests
- self.class_eval do
+ class_eval do
##
# Calls start_accepting which needs to verify startup state
@@ -120,6 +120,16 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
end
##
+ # Calls accept_block_quote
+
+ def test_accept_block_quote
+ @to.start_accepting
+
+ @to.accept_block_quote block para 'quote'
+
+ accept_block_quote
+ end
+ ##
# Test case that calls <tt>@to.accept_document</tt>
def test_accept_document
@@ -234,6 +244,29 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
end
##
+ # Calls accept_paragraph_br with a RDoc::Markup::Paragraph containing
+ # a \<br>
+
+ def test_accept_paragraph_br
+ @to.start_accepting
+
+ @to.accept_paragraph para 'one<br>two'
+
+ accept_paragraph_br
+ end
+
+ ##
+ # Calls accept_paragraph with a Paragraph containing a hard break
+
+ def test_accept_paragraph_break
+ @to.start_accepting
+
+ @to.accept_paragraph para('hello', hard_break, 'world')
+
+ accept_paragraph_break
+ end
+
+ ##
# Calls accept_paragraph_i with a RDoc::Markup::Paragraph containing
# emphasized words
@@ -374,9 +407,9 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
# Calls accept_list_item_start_note_2
def test_accept_list_item_start_note_2
- list = @RM::List.new(:NOTE,
- @RM::ListItem.new('<tt>teletype</tt>',
- @RM::Paragraph.new('teletype description')))
+ list = list(:NOTE,
+ item('<tt>teletype</tt>',
+ para('teletype description')))
@to.start_accepting
@@ -388,6 +421,41 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
end
##
+ # Calls accept_list_item_start_note_multi_description
+
+ def test_accept_list_item_start_note_multi_description
+ list = list(:NOTE,
+ item(%w[label],
+ para('description one')),
+ item(nil, para('description two')))
+
+ @to.start_accepting
+
+ list.accept @to
+
+ @to.end_accepting
+
+ accept_list_item_start_note_multi_description
+ end
+
+ ##
+ # Calls accept_list_item_start_note_multi_label
+
+ def test_accept_list_item_start_note_multi_label
+ list = list(:NOTE,
+ item(%w[one two],
+ para('two headers')))
+
+ @to.start_accepting
+
+ list.accept @to
+
+ @to.end_accepting
+
+ accept_list_item_start_note_multi_label
+ end
+
+ ##
# Calls accept_list_item_start_number
def test_accept_list_item_start_number
@@ -635,7 +703,7 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
end
##
- # Calls accept_list_end_ulpha
+ # Calls accept_list_end_ualpha
def test_accept_list_end_ualpha
@to.start_accepting
@@ -670,28 +738,28 @@ class RDoc::Markup::FormatterTestCase < MiniTest::Unit::TestCase
# Calls list_verbatim with a list containing a verbatim block
def test_list_verbatim # HACK overblown
- doc = @RM::Document.new(
- @RM::List.new(:BULLET,
- @RM::ListItem.new(nil,
- @RM::Paragraph.new('list', 'stuff'),
- @RM::BlankLine.new,
- @RM::Verbatim.new("* list\n",
- " with\n",
- "\n",
- " second\n",
- "\n",
- " 1. indented\n",
- " 2. numbered\n",
- "\n",
- " third\n",
- "\n",
- "* second\n"))))
+ doc =
+ doc(
+ list(:BULLET,
+ item(nil,
+ para('list stuff'),
+ blank_line,
+ verb("* list\n",
+ " with\n",
+ "\n",
+ " second\n",
+ "\n",
+ " 1. indented\n",
+ " 2. numbered\n",
+ "\n",
+ " third\n",
+ "\n",
+ "* second\n"))))
doc.accept @to
list_verbatim
end
-
end
end
diff --git a/lib/rdoc/markup/hard_break.rb b/lib/rdoc/markup/hard_break.rb
new file mode 100644
index 0000000000..8445ad26e7
--- /dev/null
+++ b/lib/rdoc/markup/hard_break.rb
@@ -0,0 +1,31 @@
+##
+# A hard-break in the middle of a paragraph.
+
+class RDoc::Markup::HardBreak
+
+ @instance = new
+
+ ##
+ # RDoc::Markup::HardBreak is a singleton
+
+ def self.new
+ @instance
+ end
+
+ ##
+ # Calls #accept_hard_break on +visitor+
+
+ def accept visitor
+ visitor.accept_hard_break self
+ end
+
+ def == other # :nodoc:
+ self.class === other
+ end
+
+ def pretty_print q # :nodoc:
+ q.text "[break]"
+ end
+
+end
+
diff --git a/lib/rdoc/markup/heading.rb b/lib/rdoc/markup/heading.rb
index 3bda77a1e1..b72c3e2b14 100644
--- a/lib/rdoc/markup/heading.rb
+++ b/lib/rdoc/markup/heading.rb
@@ -3,6 +3,35 @@
class RDoc::Markup::Heading < Struct.new :level, :text
+ @to_html = nil
+ @to_label = nil
+
+ ##
+ # A singleton RDoc::Markup::ToLabel formatter for headings.
+
+ def self.to_label
+ @to_label ||= RDoc::Markup::ToLabel.new
+ end
+
+ ##
+ # A singleton plain HTML formatter for headings. Used for creating labels
+ # for the Table of Contents
+
+ def self.to_html
+ return @to_html if @to_html
+
+ markup = RDoc::Markup.new
+ markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
+
+ @to_html = RDoc::Markup::ToHtml.new nil
+
+ def @to_html.handle_special_CROSSREF special
+ special.text.sub(/^\\/, '')
+ end
+
+ @to_html
+ end
+
##
# Calls #accept_heading on +visitor+
@@ -10,6 +39,21 @@ class RDoc::Markup::Heading < Struct.new :level, :text
visitor.accept_heading self
end
+ ##
+ # An HTML-safe anchor reference for this header.
+
+ def aref
+ "label-#{self.class.to_label.convert text.dup}"
+ end
+
+ ##
+ # HTML markup of the text of this label without the surrounding header
+ # element.
+
+ def plain_html
+ self.class.to_html.to_html(text.dup)
+ end
+
def pretty_print q # :nodoc:
q.group 2, "[head: #{level} ", ']' do
q.pp text
diff --git a/lib/rdoc/markup/include.rb b/lib/rdoc/markup/include.rb
new file mode 100644
index 0000000000..a2e8903279
--- /dev/null
+++ b/lib/rdoc/markup/include.rb
@@ -0,0 +1,42 @@
+##
+# A file included at generation time. Objects of this class are created by
+# RDoc::RD for an extension-less include.
+#
+# This implementation in incomplete.
+
+class RDoc::Markup::Include
+
+ ##
+ # The filename to be included, without extension
+
+ attr_reader :file
+
+ ##
+ # Directories to search for #file
+
+ attr_reader :include_path
+
+ ##
+ # Creates a new include that will import +file+ from +include_path+
+
+ def initialize file, include_path
+ @file = file
+ @include_path = include_path
+ end
+
+ def == other # :nodoc:
+ self.class === other and
+ @file == other.file and @include_path == other.include_path
+ end
+
+ def pretty_print q # :nodoc:
+ q.group 2, '[incl ', ']' do
+ q.text file
+ q.breakable
+ q.text 'from '
+ q.pp include_path
+ end
+ end
+
+end
+
diff --git a/lib/rdoc/markup/indented_paragraph.rb b/lib/rdoc/markup/indented_paragraph.rb
index d995c7d8ed..1b8a8c725d 100644
--- a/lib/rdoc/markup/indented_paragraph.rb
+++ b/lib/rdoc/markup/indented_paragraph.rb
@@ -29,5 +29,19 @@ class RDoc::Markup::IndentedParagraph < RDoc::Markup::Raw
visitor.accept_indented_paragraph self
end
+ ##
+ # Joins the raw paragraph text and converts inline HardBreaks to the
+ # +hard_break+ text followed by the indent.
+
+ def text hard_break = nil
+ @parts.map do |part|
+ if RDoc::Markup::HardBreak === part then
+ '%1$s%3$*2$s' % [hard_break, @indent, ' '] if hard_break
+ else
+ part
+ end
+ end.join
+ end
+
end
diff --git a/lib/rdoc/markup/inline.rb b/lib/rdoc/markup/inline.rb
index cf598d1583..fb3ab5c74d 100644
--- a/lib/rdoc/markup/inline.rb
+++ b/lib/rdoc/markup/inline.rb
@@ -1,144 +1 @@
-require 'rdoc'
-class RDoc::Markup
-
- ##
- # We manage a set of attributes. Each attribute has a symbol name and a bit
- # value.
-
- class Attribute
-
- ##
- # Special attribute type. See RDoc::Markup#add_special
-
- SPECIAL = 1
-
- @@name_to_bitmap = { :_SPECIAL_ => SPECIAL }
- @@next_bitmap = 2
-
- ##
- # Returns a unique bit for +name+
-
- def self.bitmap_for(name)
- bitmap = @@name_to_bitmap[name]
- unless bitmap then
- bitmap = @@next_bitmap
- @@next_bitmap <<= 1
- @@name_to_bitmap[name] = bitmap
- end
- bitmap
- end
-
- ##
- # Returns a string representation of +bitmap+
-
- def self.as_string(bitmap)
- return "none" if bitmap.zero?
- res = []
- @@name_to_bitmap.each do |name, bit|
- res << name if (bitmap & bit) != 0
- end
- res.join(",")
- end
-
- ##
- # yields each attribute name in +bitmap+
-
- def self.each_name_of(bitmap)
- @@name_to_bitmap.each do |name, bit|
- next if bit == SPECIAL
- yield name.to_s if (bitmap & bit) != 0
- end
- end
-
- end
-
- AttrChanger = Struct.new :turn_on, :turn_off # :nodoc:
-
- ##
- # An AttrChanger records a change in attributes. It contains a bitmap of the
- # attributes to turn on, and a bitmap of those to turn off.
-
- class AttrChanger
- def to_s # :nodoc:
- "Attr: +#{Attribute.as_string turn_on}/-#{Attribute.as_string turn_off}"
- end
-
- def inspect # :nodoc:
- "+%s/-%s" % [
- Attribute.as_string(turn_on),
- Attribute.as_string(turn_off),
- ]
- end
- end
-
- ##
- # An array of attributes which parallels the characters in a string.
-
- class AttrSpan
-
- ##
- # Creates a new AttrSpan for +length+ characters
-
- def initialize(length)
- @attrs = Array.new(length, 0)
- end
-
- ##
- # Toggles +bits+ from +start+ to +length+
- def set_attrs(start, length, bits)
- for i in start ... (start+length)
- @attrs[i] |= bits
- end
- end
-
- ##
- # Accesses flags for character +n+
-
- def [](n)
- @attrs[n]
- end
-
- end
-
- ##
- # Hold details of a special sequence
-
- class Special
-
- ##
- # Special type
-
- attr_reader :type
-
- ##
- # Special text
-
- attr_accessor :text
-
- ##
- # Creates a new special sequence of +type+ with +text+
-
- def initialize(type, text)
- @type, @text = type, text
- end
-
- ##
- # Specials are equal when the have the same text and type
-
- def ==(o)
- self.text == o.text && self.type == o.type
- end
-
- def inspect # :nodoc:
- "#<RDoc::Markup::Special:0x%x @type=%p, name=%p @text=%p>" % [
- object_id, @type, RDoc::Markup::Attribute.as_string(type), text.dump]
- end
-
- def to_s # :nodoc:
- "Special: type=#{type}, name=#{RDoc::Markup::Attribute.as_string type}, text=#{text.dump}"
- end
-
- end
-
-end
-
+warn "requiring rdoc/markup/inline is deprecated and will be removed in RDoc 4." if $-w
diff --git a/lib/rdoc/markup/list.rb b/lib/rdoc/markup/list.rb
index 820b4c9645..86ed845634 100644
--- a/lib/rdoc/markup/list.rb
+++ b/lib/rdoc/markup/list.rb
@@ -1,5 +1,24 @@
##
-# A List of ListItems
+# A List is a homogeneous set of ListItems.
+#
+# The supported list types include:
+#
+# :BULLET::
+# An unordered list
+# :LABEL::
+# An unordered definition list, but using an alternate RDoc::Markup syntax
+# :LALPHA::
+# An ordered list using increasing lowercase English letters
+# :NOTE::
+# An unordered definition list
+# :NUMBER::
+# An ordered list using increasing Arabic numerals
+# :UALPHA::
+# An ordered list using increasing uppercase English letters
+#
+# Definition lists behave like HTML definition lists. Each list item can
+# describe multiple terms. See RDoc::Markup::ListItem for how labels and
+# definition are stored as list items.
class RDoc::Markup::List
@@ -14,12 +33,13 @@ class RDoc::Markup::List
attr_reader :items
##
- # Creates a new list of +type+ with +items+
+ # Creates a new list of +type+ with +items+. Valid list types are:
+ # +:BULLET+, +:LABEL+, +:LALPHA+, +:NOTE+, +:NUMBER+, +:UALPHA+
def initialize type = nil, *items
@type = type
@items = []
- @items.push(*items)
+ @items.concat items
end
##
@@ -74,7 +94,7 @@ class RDoc::Markup::List
# Appends +items+ to the list
def push *items
- @items.push(*items)
+ @items.concat items
end
end
diff --git a/lib/rdoc/markup/list_item.rb b/lib/rdoc/markup/list_item.rb
index d719c352ec..c5e59fe167 100644
--- a/lib/rdoc/markup/list_item.rb
+++ b/lib/rdoc/markup/list_item.rb
@@ -1,5 +1,12 @@
##
# An item within a List that contains paragraphs, headings, etc.
+#
+# For BULLET, NUMBER, LALPHA and UALPHA lists, the label will always be nil.
+# For NOTE and LABEL lists, the list label may contain:
+#
+# * a single String for a single label
+# * an Array of Strings for a list item with multiple terms
+# * nil for an extra description attached to a previously labeled list item
class RDoc::Markup::ListItem
@@ -19,7 +26,7 @@ class RDoc::Markup::ListItem
def initialize label = nil, *parts
@label = label
@parts = []
- @parts.push(*parts)
+ @parts.concat parts
end
##
@@ -64,8 +71,14 @@ class RDoc::Markup::ListItem
def pretty_print q # :nodoc:
q.group 2, '[item: ', ']' do
- if @label then
- q.text @label
+ case @label
+ when Array then
+ q.pp @label
+ q.text ';'
+ q.breakable
+ when String then
+ q.pp @label
+ q.text ';'
q.breakable
end
@@ -79,7 +92,7 @@ class RDoc::Markup::ListItem
# Adds +parts+ to the ListItem
def push *parts
- @parts.push(*parts)
+ @parts.concat parts
end
end
diff --git a/lib/rdoc/markup/paragraph.rb b/lib/rdoc/markup/paragraph.rb
index 808430d576..7180729f75 100644
--- a/lib/rdoc/markup/paragraph.rb
+++ b/lib/rdoc/markup/paragraph.rb
@@ -10,5 +10,19 @@ class RDoc::Markup::Paragraph < RDoc::Markup::Raw
visitor.accept_paragraph self
end
+ ##
+ # Joins the raw paragraph text and converts inline HardBreaks to the
+ # +hard_break+ text.
+
+ def text hard_break = ''
+ @parts.map do |part|
+ if RDoc::Markup::HardBreak === part then
+ hard_break
+ else
+ part
+ end
+ end.join
+ end
+
end
diff --git a/lib/rdoc/markup/parser.rb b/lib/rdoc/markup/parser.rb
index c18ce821fb..ca384d0639 100644
--- a/lib/rdoc/markup/parser.rb
+++ b/lib/rdoc/markup/parser.rb
@@ -1,5 +1,4 @@
require 'strscan'
-require 'rdoc/text'
##
# A recursive-descent parser for RDoc markup.
@@ -52,7 +51,9 @@ class RDoc::Markup::Parser
attr_reader :tokens
##
- # Parses +str+ into a Document
+ # Parses +str+ into a Document.
+ #
+ # Use RDoc::Markup#parse instead of this method.
def self.parse str
parser = new
@@ -74,12 +75,15 @@ class RDoc::Markup::Parser
# Creates a new Parser. See also ::parse
def initialize
- @tokens = []
- @current_token = nil
- @debug = false
-
- @line = 0
- @line_pos = 0
+ @binary_input = nil
+ @current_token = nil
+ @debug = false
+ @have_encoding = Object.const_defined? :Encoding
+ @input_encoding = nil
+ @line = 0
+ @line_pos = 0
+ @s = nil
+ @tokens = []
end
##
@@ -107,13 +111,13 @@ class RDoc::Markup::Parser
p :list_start => margin if @debug
list = RDoc::Markup::List.new
+ label = nil
until @tokens.empty? do
type, data, column, = get
case type
- when :BULLET, :LABEL, :LALPHA, :NOTE, :NUMBER, :UALPHA then
-
+ when *LIST_TOKENS then
if column < margin || (list.type && list.type != type) then
unget
break
@@ -124,6 +128,8 @@ class RDoc::Markup::Parser
case type
when :NOTE, :LABEL then
+ label = [] unless label
+
if peek_type == :NEWLINE then
# description not on the same line as LABEL/NOTE
# skip the trailing newline & any blank lines below
@@ -146,32 +152,35 @@ class RDoc::Markup::Parser
# In all cases, we have an empty description.
# In the last case only, we continue.
if peek_type.nil? || column < margin then
- empty = 1
+ empty = true
elsif column == margin then
case peek_type
when type
- empty = 2 # continue
+ empty = :continue
when *LIST_TOKENS
- empty = 1
+ empty = true
else
- empty = 0
+ empty = false
end
else
- empty = 0
+ empty = false
end
- if empty > 0 then
- item = RDoc::Markup::ListItem.new(data)
- item << RDoc::Markup::BlankLine.new
- list << item
- break if empty == 1
- next
+ if empty then
+ label << data
+ next if empty == :continue
+ break
end
end
else
data = nil
end
+ if label then
+ data = label << data
+ label = nil
+ end
+
list_item = RDoc::Markup::ListItem.new data
parse list_item, column
list << list_item
@@ -184,7 +193,13 @@ class RDoc::Markup::Parser
p :list_end => margin if @debug
- return nil if list.empty?
+ if list.empty? then
+ return nil unless label
+ return nil unless [:LABEL, :NOTE].include? list.type
+
+ list_item = RDoc::Markup::ListItem.new label, RDoc::Markup::BlankLine.new
+ list << list_item
+ end
list
end
@@ -200,15 +215,20 @@ class RDoc::Markup::Parser
until @tokens.empty? do
type, data, column, = get
- if type == :TEXT && column == margin then
+ if type == :TEXT and column == margin then
paragraph << data
- skip :NEWLINE
+
+ break if peek_token.first == :BREAK
+
+ data << ' ' if skip :NEWLINE
else
unget
break
end
end
+ paragraph.parts.last.sub!(/ \z/, '') # cleanup
+
p :paragraph_end => margin if @debug
paragraph
@@ -267,7 +287,7 @@ class RDoc::Markup::Parser
peek_column ||= column + width
indent = peek_column - column - width
line << ' ' * indent
- when :TEXT then
+ when :BREAK, :TEXT then
line << data
else # *LIST_TOKENS
list_marker = case type
@@ -298,6 +318,19 @@ class RDoc::Markup::Parser
end
##
+ # The character offset for the input string at the given +byte_offset+
+
+ def char_pos byte_offset
+ if @have_encoding then
+ matched = @binary_input[0, byte_offset]
+ matched.force_encoding @input_encoding
+ matched.length
+ else
+ byte_offset
+ end
+ end
+
+ ##
# Pulls the next token from the stream.
def get
@@ -321,7 +354,12 @@ class RDoc::Markup::Parser
until @tokens.empty? do
type, data, column, = get
- if type == :NEWLINE then
+ case type
+ when :BREAK then
+ parent << RDoc::Markup::BlankLine.new
+ skip :NEWLINE, false
+ next
+ when :NEWLINE then
# trailing newlines are skipped below, so this is a blank line
parent << RDoc::Markup::BlankLine.new
skip :NEWLINE, false
@@ -373,6 +411,21 @@ class RDoc::Markup::Parser
end
##
+ # Creates the StringScanner
+
+ def setup_scanner input
+ @line = 0
+ @line_pos = 0
+
+ if @have_encoding then
+ @input_encoding = input.encoding
+ @binary_input = input.dup.force_encoding Encoding::BINARY
+ end
+
+ @s = StringScanner.new input
+ end
+
+ ##
# Skips the next token if its type is +token_type+.
#
# Optionally raises an error if the next token is not of the expected type.
@@ -389,58 +442,55 @@ class RDoc::Markup::Parser
# Turns text +input+ into a stream of tokens
def tokenize input
- s = StringScanner.new input
+ setup_scanner input
- @line = 0
- @line_pos = 0
-
- until s.eos? do
- pos = s.pos
+ until @s.eos? do
+ pos = @s.pos
# leading spaces will be reflected by the column of the next token
# the only thing we loose are trailing spaces at the end of the file
- next if s.scan(/ +/)
+ next if @s.scan(/ +/)
# note: after BULLET, LABEL, etc.,
# indent will be the column of the next non-newline token
@tokens << case
# [CR]LF => :NEWLINE
- when s.scan(/\r?\n/) then
- token = [:NEWLINE, s.matched, *token_pos(pos)]
- @line_pos = s.pos
+ when @s.scan(/\r?\n/) then
+ token = [:NEWLINE, @s.matched, *token_pos(pos)]
+ @line_pos = char_pos @s.pos
@line += 1
token
# === text => :HEADER then :TEXT
- when s.scan(/(=+)(\s*)/) then
- level = s[1].length
+ when @s.scan(/(=+)(\s*)/) then
+ level = @s[1].length
header = [:HEADER, level, *token_pos(pos)]
- if s[2] =~ /^\r?\n/ then
- s.pos -= s[2].length
+ if @s[2] =~ /^\r?\n/ then
+ @s.pos -= @s[2].length
header
else
- pos = s.pos
- s.scan(/.*/)
+ pos = @s.pos
+ @s.scan(/.*/)
@tokens << header
- [:TEXT, s.matched.sub(/\r$/, ''), *token_pos(pos)]
+ [:TEXT, @s.matched.sub(/\r$/, ''), *token_pos(pos)]
end
# --- (at least 3) and nothing else on the line => :RULE
- when s.scan(/(-{3,}) *$/) then
- [:RULE, s[1].length - 2, *token_pos(pos)]
+ when @s.scan(/(-{3,}) *\r?$/) then
+ [:RULE, @s[1].length - 2, *token_pos(pos)]
# * or - followed by white space and text => :BULLET
- when s.scan(/([*-]) +(\S)/) then
- s.pos -= s[2].bytesize # unget \S
- [:BULLET, s[1], *token_pos(pos)]
+ when @s.scan(/([*-]) +(\S)/) then
+ @s.pos -= @s[2].bytesize # unget \S
+ [:BULLET, @s[1], *token_pos(pos)]
# A. text, a. text, 12. text => :UALPHA, :LALPHA, :NUMBER
- when s.scan(/([a-z]|\d+)\. +(\S)/i) then
+ when @s.scan(/([a-z]|\d+)\. +(\S)/i) then
# FIXME if tab(s), the column will be wrong
# either support tabs everywhere by first expanding them to
# spaces, or assume that they will have been replaced
# before (and provide a check for that at least in debug
# mode)
- list_label = s[1]
- s.pos -= s[2].bytesize # unget \S
+ list_label = @s[1]
+ @s.pos -= @s[2].bytesize # unget \S
list_type =
case list_label
when /[a-z]/ then :LALPHA
@@ -451,14 +501,21 @@ class RDoc::Markup::Parser
end
[list_type, list_label, *token_pos(pos)]
# [text] followed by spaces or end of line => :LABEL
- when s.scan(/\[(.*?)\]( +|$)/) then
- [:LABEL, s[1], *token_pos(pos)]
+ when @s.scan(/\[(.*?)\]( +|\r?$)/) then
+ [:LABEL, @s[1], *token_pos(pos)]
# text:: followed by spaces or end of line => :NOTE
- when s.scan(/(.*?)::( +|$)/) then
- [:NOTE, s[1], *token_pos(pos)]
+ when @s.scan(/(.*?)::( +|\r?$)/) then
+ [:NOTE, @s[1], *token_pos(pos)]
# anything else: :TEXT
- else s.scan(/.*/)
- [:TEXT, s.matched.sub(/\r$/, ''), *token_pos(pos)]
+ else @s.scan(/(.*?)( )?\r?$/)
+ token = [:TEXT, @s[1], *token_pos(pos)]
+
+ if @s[2] then
+ @tokens << token
+ [:BREAK, @s[2], *token_pos(pos + @s[1].length)]
+ else
+ token
+ end
end
end
@@ -466,9 +523,12 @@ class RDoc::Markup::Parser
end
##
- # Calculates the column and line of the current token based on +offset+.
+ # Calculates the column (by character) and line of the current token from
+ # +scanner+ based on +byte_offset+.
+
+ def token_pos byte_offset
+ offset = char_pos byte_offset
- def token_pos offset
[offset - @line_pos, @line]
end
@@ -484,14 +544,3 @@ class RDoc::Markup::Parser
end
-require 'rdoc/markup/blank_line'
-require 'rdoc/markup/document'
-require 'rdoc/markup/heading'
-require 'rdoc/markup/list'
-require 'rdoc/markup/list_item'
-require 'rdoc/markup/raw'
-require 'rdoc/markup/paragraph'
-require 'rdoc/markup/indented_paragraph'
-require 'rdoc/markup/rule'
-require 'rdoc/markup/verbatim'
-
diff --git a/lib/rdoc/markup/pre_process.rb b/lib/rdoc/markup/pre_process.rb
index 53e8e38ec1..6024edcd27 100644
--- a/lib/rdoc/markup/pre_process.rb
+++ b/lib/rdoc/markup/pre_process.rb
@@ -1,6 +1,3 @@
-require 'rdoc/markup'
-require 'rdoc/encoding'
-
##
# Handle common directives that can occur in a block of text:
#
@@ -9,18 +6,48 @@ require 'rdoc/encoding'
# Directives can be escaped by preceding them with a backslash.
#
# RDoc plugin authors can register additional directives to be handled by
-# using RDoc::Markup::PreProcess::register
+# using RDoc::Markup::PreProcess::register.
+#
+# Any directive that is not built-in to RDoc (including those registered via
+# plugins) will be stored in the metadata hash on the CodeObject the comment
+# is attached to. See RDoc::Markup@Directives for the list of built-in
+# directives.
class RDoc::Markup::PreProcess
+ ##
+ # An RDoc::Options instance that will be filled in with overrides from
+ # directives
+
attr_accessor :options
- @registered = {}
+ ##
+ # Adds a post-process handler for directives. The handler will be called
+ # with the result RDoc::Comment (or text String) and the code object for the
+ # comment (if any).
+
+ def self.post_process &block
+ @post_processors << block
+ end
+
+ ##
+ # Registered post-processors
+
+ def self.post_processors
+ @post_processors
+ end
##
# Registers +directive+ as one handled by RDoc. If a block is given the
# directive will be replaced by the result of the block, otherwise the
# directive will be removed from the processed text.
+ #
+ # The block will be called with the directive name and the directive
+ # parameter:
+ #
+ # RDoc::Markup::PreProcess.register 'my-directive' do |directive, param|
+ # # replace text, etc.
+ # end
def self.register directive, &block
@registered[directive] = block
@@ -34,6 +61,16 @@ class RDoc::Markup::PreProcess
end
##
+ # Clears all registered directives and post-processors
+
+ def self.reset
+ @post_processors = []
+ @registered = {}
+ end
+
+ reset
+
+ ##
# Creates a new pre-processor for +input_file_name+ that will look for
# included files in +include_path+
@@ -44,7 +81,7 @@ class RDoc::Markup::PreProcess
end
##
- # Look for directives in a chunk of +text+.
+ # Look for directives in the given +text+.
#
# Options that we don't handle are yielded. If the block returns false the
# directive is restored to the text. If the block returns nil or no block
@@ -54,27 +91,56 @@ class RDoc::Markup::PreProcess
# If no matching directive was registered the directive is restored to the
# text.
#
- # If +code_object+ is given and the param is set as metadata on the
- # +code_object+. See RDoc::CodeObject#metadata
+ # If +code_object+ is given and the directive is unknown then the
+ # directive's parameter is set as metadata on the +code_object+. See
+ # RDoc::CodeObject#metadata for details.
def handle text, code_object = nil, &block
- encoding = if defined?(Encoding) then text.encoding else nil end
+ if RDoc::Comment === text then
+ comment = text
+ text = text.text
+ end
+
+ encoding = text.encoding if defined?(Encoding)
+
# regexp helper (square brackets for optional)
# $1 $2 $3 $4 $5
# [prefix][\]:directive:[spaces][param]newline
- text.gsub!(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?\n/) do
+ text.gsub!(/^([ \t]*(?:#|\/?\*)?[ \t]*)(\\?):(\w+):([ \t]*)(.+)?(\r?\n|$)/) do
# skip something like ':toto::'
next $& if $4.empty? and $5 and $5[0, 1] == ':'
# skip if escaped
next "#$1:#$3:#$4#$5\n" unless $2.empty?
+ # This is not in handle_directive because I didn't want to pass another
+ # argument into it
+ if comment and $3 == 'markup' then
+ next "#{$1.strip}\n" unless $5
+ comment.format = $5.downcase
+ next "#{$1.strip}\n"
+ end
+
handle_directive $1, $3, $5, code_object, encoding, &block
end
+ comment = text unless comment
+
+ self.class.post_processors.each do |handler|
+ handler.call comment, code_object
+ end
+
text
end
+ ##
+ # Performs the actions described by +directive+ and its parameter +param+.
+ #
+ # +code_object+ is used for directives that operate on a class or module.
+ # +prefix+ is used to ensure the replacement for handled directives is
+ # correct. +encoding+ is used for the <tt>include</tt> directive.
+ #
+ # For a list of directives in RDoc see RDoc::Markup.
#--
# When 1.8.7 support is ditched prefix can be defaulted to ''
@@ -92,7 +158,7 @@ class RDoc::Markup::PreProcess
blankline
when 'category' then
if RDoc::Context === code_object then
- section = code_object.add_section param, ''
+ section = code_object.add_section param
code_object.temporary_section = section
end
diff --git a/lib/rdoc/markup/raw.rb b/lib/rdoc/markup/raw.rb
index ca877c79af..e11e8efff4 100644
--- a/lib/rdoc/markup/raw.rb
+++ b/lib/rdoc/markup/raw.rb
@@ -13,7 +13,7 @@ class RDoc::Markup::Raw
def initialize *parts
@parts = []
- @parts.push(*parts)
+ @parts.concat parts
end
##
@@ -24,7 +24,7 @@ class RDoc::Markup::Raw
end
def == other # :nodoc:
- self.class == other.class and text == other.text
+ self.class == other.class and @parts == other.parts
end
##
@@ -38,11 +38,11 @@ class RDoc::Markup::Raw
# Appends +other+'s parts
def merge other
- @parts.push(*other.parts)
+ @parts.concat other.parts
end
def pretty_print q # :nodoc:
- self.class.name =~ /.*::(\w{4})/i
+ self.class.name =~ /.*::(\w{1,4})/i
q.group 2, "[#{$1.downcase}: ", ']' do
q.seplist @parts do |part|
@@ -55,7 +55,7 @@ class RDoc::Markup::Raw
# Appends +texts+ onto this Paragraph
def push *texts
- self.parts.push(*texts)
+ self.parts.concat texts
end
##
diff --git a/lib/rdoc/markup/special.rb b/lib/rdoc/markup/special.rb
new file mode 100644
index 0000000000..1c0fc03eea
--- /dev/null
+++ b/lib/rdoc/markup/special.rb
@@ -0,0 +1,40 @@
+##
+# Hold details of a special sequence
+
+class RDoc::Markup::Special
+
+ ##
+ # Special type
+
+ attr_reader :type
+
+ ##
+ # Special text
+
+ attr_accessor :text
+
+ ##
+ # Creates a new special sequence of +type+ with +text+
+
+ def initialize(type, text)
+ @type, @text = type, text
+ end
+
+ ##
+ # Specials are equal when the have the same text and type
+
+ def ==(o)
+ self.text == o.text && self.type == o.type
+ end
+
+ def inspect # :nodoc:
+ "#<RDoc::Markup::Special:0x%x @type=%p, @text=%p>" % [
+ object_id, @type, text.dump]
+ end
+
+ def to_s # :nodoc:
+ "Special: type=#{type} text=#{text.dump}"
+ end
+
+end
+
diff --git a/lib/rdoc/markup/text_formatter_test_case.rb b/lib/rdoc/markup/text_formatter_test_case.rb
index ba9e7c6187..4abf42563b 100644
--- a/lib/rdoc/markup/text_formatter_test_case.rb
+++ b/lib/rdoc/markup/text_formatter_test_case.rb
@@ -1,5 +1,3 @@
-require 'rdoc/markup/formatter_test_case'
-
##
# Test case for creating new plain-text RDoc::Markup formatters. See also
# RDoc::Markup::FormatterTestCase
diff --git a/lib/rdoc/markup/to_ansi.rb b/lib/rdoc/markup/to_ansi.rb
index 1e8a0289d9..4d439ce88d 100644
--- a/lib/rdoc/markup/to_ansi.rb
+++ b/lib/rdoc/markup/to_ansi.rb
@@ -1,5 +1,3 @@
-require 'rdoc/markup/to_rdoc'
-
##
# Outputs RDoc markup with vibrant ANSI color!
@@ -34,6 +32,11 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
when :BULLET then
2
when :NOTE, :LABEL then
+ if @prefix then
+ @res << @prefix.strip
+ @prefix = nil
+ end
+
@res << "\n" unless res.length == 1
2
else
@@ -53,7 +56,13 @@ class RDoc::Markup::ToAnsi < RDoc::Markup::ToRdoc
when :BULLET then
'*'
when :NOTE, :LABEL then
- attributes(list_item.label) + ":\n"
+ labels = Array(list_item.label).map do |label|
+ attributes(label).strip
+ end.join "\n"
+
+ labels << ":\n" unless labels.empty?
+
+ labels
else
@list_index.last.to_s + '.'
end
diff --git a/lib/rdoc/markup/to_bs.rb b/lib/rdoc/markup/to_bs.rb
index 32b1bbb9eb..10c31854d2 100644
--- a/lib/rdoc/markup/to_bs.rb
+++ b/lib/rdoc/markup/to_bs.rb
@@ -1,5 +1,3 @@
-require 'rdoc/markup/to_rdoc'
-
##
# Outputs RDoc markup with hot backspace action! You will probably need a
# pager to use this output format.
diff --git a/lib/rdoc/markup/to_html.rb b/lib/rdoc/markup/to_html.rb
index bd5fdb493e..9cd94a5945 100644
--- a/lib/rdoc/markup/to_html.rb
+++ b/lib/rdoc/markup/to_html.rb
@@ -1,10 +1,7 @@
-require 'rdoc/markup/formatter'
-require 'rdoc/markup/inline'
-
require 'cgi'
##
-# Outputs RDoc markup as HTML
+# Outputs RDoc markup as HTML.
class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
@@ -16,12 +13,12 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# Maps RDoc::Markup::Parser::LIST_TOKENS types to HTML tags
LIST_TYPE_TO_HTML = {
- :BULLET => ['<ul>', '</ul>'],
- :LABEL => ['<dl class="rdoc-list">', '</dl>'],
- :LALPHA => ['<ol style="display: lower-alpha">', '</ol>'],
- :NOTE => ['<table class="rdoc-list">', '</table>'],
- :NUMBER => ['<ol>', '</ol>'],
- :UALPHA => ['<ol style="display: upper-alpha">', '</ol>'],
+ :BULLET => ['<ul>', '</ul>'],
+ :LABEL => ['<dl class="rdoc-list label-list">', '</dl>'],
+ :LALPHA => ['<ol style="list-style-type: lower-alpha">', '</ol>'],
+ :NOTE => ['<dl class="rdoc-list note-list">', '</dl>'],
+ :NUMBER => ['<ol>', '</ol>'],
+ :UALPHA => ['<ol style="list-style-type: upper-alpha">', '</ol>'],
}
attr_reader :res # :nodoc:
@@ -29,6 +26,12 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
attr_reader :list # :nodoc:
##
+ # The RDoc::CodeObject HTML is being generated for. This is used to
+ # generate namespaced URI fragments
+
+ attr_accessor :code_object
+
+ ##
# Path to this document for relative links
attr_accessor :from_path
@@ -62,19 +65,31 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
##
# Creates a new formatter that will output HTML
- def initialize markup = nil
+ def initialize options, markup = nil
super
- @th = nil
+ @code_object = nil
+ @from_path = ''
@in_list_entry = nil
@list = nil
- @from_path = ''
+ @th = nil
+ @hard_break = "<br>\n"
# external links
- @markup.add_special(/((link:|https?:|mailto:|ftp:|www\.)\S+\w)/, :HYPERLINK)
+ @markup.add_special(/(?:link:|https?:|mailto:|ftp:|irc:|www\.)\S+\w/,
+ :HYPERLINK)
+
+ # internal links
+ @markup.add_special(/rdoc-[a-z]+:\S+/, :RDOCLINK)
# and links of the form <text>[<url>]
- @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\])/, :TIDYLINK)
+ @markup.add_special(/(?:
+ \{.*?\} | # multi-word label
+ \b[^\s{}]+? # single-word label
+ )
+
+ \[\S+?\] # link target
+ /x, :TIDYLINK)
init_tags
end
@@ -84,6 +99,13 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# These methods handle special markup added by RDoc::Markup#add_special.
##
+ # +special+ is a <code><br></code>
+
+ def handle_special_HARD_BREAK special
+ '<br>'
+ end
+
+ ##
# +special+ is a potential link. The following schemes are handled:
#
# <tt>mailto:</tt>::
@@ -102,6 +124,39 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
end
##
+ # +special+ is an rdoc-schemed link that will be converted into a hyperlink.
+ #
+ # For the +rdoc-ref+ scheme the named reference will be returned without
+ # creating a link.
+ #
+ # For the +rdoc-label+ scheme the footnote and label prefixes are stripped
+ # when creating a link. All other contents will be linked verbatim.
+
+ def handle_special_RDOCLINK special
+ url = special.text
+
+ case url
+ when /\Ardoc-ref:/
+ $'
+ when /\Ardoc-label:/
+ text = $'
+
+ text = case text
+ when /\Alabel-/ then $'
+ when /\Afootmark-/ then "^#{$'}"
+ when /\Afoottext-/ then "*#{$'}"
+ else text
+ end
+
+ gen_url url, text
+ else
+ url =~ /\Ardoc-[a-z]+:/
+
+ $'
+ end
+ end
+
+ ##
# This +special+ is a link where the label is different from the URL
# <tt>label[url]</tt> or <tt>{long label}[url]</tt>
@@ -136,21 +191,47 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
end
##
+ # Adds +block_quote+ to the output
+
+ def accept_block_quote block_quote
+ @res << "\n<blockquote>"
+
+ block_quote.parts.each do |part|
+ part.accept self
+ end
+
+ @res << "</blockquote>\n"
+ end
+
+ ##
# Adds +paragraph+ to the output
- def accept_paragraph(paragraph)
+ def accept_paragraph paragraph
@res << "\n<p>"
- @res << wrap(to_html(paragraph.text))
+ text = paragraph.text @hard_break
+ @res << wrap(to_html(text))
@res << "</p>\n"
end
##
# Adds +verbatim+ to the output
- def accept_verbatim(verbatim)
- @res << "\n<pre>"
- @res << CGI.escapeHTML(verbatim.text.rstrip)
- @res << "</pre>\n"
+ def accept_verbatim verbatim
+ text = verbatim.text.rstrip
+
+ @res << if verbatim.ruby? or parseable? text then
+ begin
+ tokens = RDoc::RubyLex.tokenize text, @options
+
+ html = RDoc::TokenStream.to_html tokens
+
+ "\n<pre class=\"ruby\">#{html}</pre>\n"
+ rescue RDoc::RubyLex::Error
+ "\n<pre>#{CGI.escapeHTML text}</pre>\n"
+ end
+ else
+ "\n<pre>#{CGI.escapeHTML text}</pre>\n"
+ end
end
##
@@ -208,12 +289,19 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
end
##
- # Adds +heading+ to the output
+ # Adds +heading+ to the output. The headings greater than 6 are trimmed to
+ # level 6.
+
+ def accept_heading heading
+ level = [6, heading.level].min
- def accept_heading(heading)
- @res << "\n<h#{heading.level}>"
+ label = heading.aref
+ label = [@code_object.aref, label].compact.join '-' if
+ @code_object and @code_object.respond_to? :aref
+
+ @res << "\n<h#{level} id=\"#{label}\">"
@res << to_html(heading.text)
- @res << "</h#{heading.level}>\n"
+ @res << "</h#{level}>\n"
end
##
@@ -226,18 +314,22 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# :section: Utilities
##
- # CGI escapes +text+
+ # CGI-escapes +text+
def convert_string(text)
CGI.escapeHTML text
end
##
- # Generate a link for +url+, labeled with +text+. Handles the special cases
+ # Generate a link to +url+ with content +text+. Handles the special cases
# for img: and link: described under handle_special_HYPERLINK
- def gen_url(url, text)
- if url =~ /([A-Za-z]+):(.*)/ then
+ def gen_url url, text
+ if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then
+ type = "link"
+ path = "##{$1}"
+ id = " id=\"#{$2}\"" if $2
+ elsif url =~ /([A-Za-z]+):(.*)/ then
type = $1
path = $2
else
@@ -258,7 +350,7 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
"<img src=\"#{url}\" />"
else
- "<a href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
+ "<a#{id} href=\"#{url}\">#{text.sub(%r{^#{type}:/*}, '')}</a>"
end
end
@@ -275,9 +367,9 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
# Maps attributes to HTML tags
def init_tags
- add_tag :BOLD, "<b>", "</b>"
- add_tag :TT, "<tt>", "</tt>"
- add_tag :EM, "<em>", "</em>"
+ add_tag :BOLD, "<strong>", "</strong>"
+ add_tag :TT, "<code>", "</code>"
+ add_tag :EM, "<em>", "</em>"
end
##
@@ -288,10 +380,10 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
case list_type
when :BULLET, :LALPHA, :NUMBER, :UALPHA then
"<li>"
- when :LABEL then
- "<dt>#{to_html list_item.label}</dt>\n<dd>"
- when :NOTE then
- "<tr><td class=\"rdoc-term\"><p>#{to_html list_item.label}</p></td>\n<td>"
+ when :LABEL, :NOTE then
+ Array(list_item.label).map do |label|
+ "<dt>#{to_html label}\n"
+ end.join << "<dd>"
else
raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
end
@@ -304,16 +396,22 @@ class RDoc::Markup::ToHtml < RDoc::Markup::Formatter
case list_type
when :BULLET, :LALPHA, :NUMBER, :UALPHA then
"</li>"
- when :LABEL then
+ when :LABEL, :NOTE then
"</dd>"
- when :NOTE then
- "</td></tr>"
else
raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
end
end
##
+ # Returns true if Ripper is available it can create a sexp from +text+
+
+ def parseable? text
+ text =~ /\b(def|class|module|require) |=>|\{\s?\||do \|/ and
+ text !~ /<%|%>/
+ end
+
+ ##
# Converts +item+ to HTML using RDoc::Text#to_html
def to_html item
diff --git a/lib/rdoc/markup/to_html_crossref.rb b/lib/rdoc/markup/to_html_crossref.rb
index 450ea960b5..405f68c14f 100644
--- a/lib/rdoc/markup/to_html_crossref.rb
+++ b/lib/rdoc/markup/to_html_crossref.rb
@@ -1,6 +1,3 @@
-require 'rdoc/markup/to_html'
-require 'rdoc/cross_reference'
-
##
# Subclass of the RDoc::Markup::ToHtml class that supports looking up method
# names, classes, etc to create links. RDoc::CrossReference is used to
@@ -31,21 +28,20 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
# references are removed unless +show_hash+ is true. Only method names
# preceded by '#' or '::' are linked, unless +hyperlink_all+ is true.
- def initialize(from_path, context, show_hash, hyperlink_all = false,
- markup = nil)
+ def initialize(options, from_path, context, markup = nil)
raise ArgumentError, 'from_path cannot be nil' if from_path.nil?
- super markup
- crossref_re = hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
+ super options, markup
- @cross_reference = RDoc::CrossReference.new context
+ @context = context
+ @from_path = from_path
+ @hyperlink_all = @options.hyperlink_all
+ @show_hash = @options.show_hash
+ crossref_re = @hyperlink_all ? ALL_CROSSREF_REGEXP : CROSSREF_REGEXP
@markup.add_special crossref_re, :CROSSREF
- @markup.add_special(/rdoc-ref:\S+\w/, :HYPERLINK)
- @from_path = from_path
- @hyperlink_all = hyperlink_all
- @show_hash = show_hash
+ @cross_reference = RDoc::CrossReference.new @context
end
##
@@ -57,6 +53,8 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
name = name[1..-1] unless @show_hash if name[0, 1] == '#'
+ name = "#{CGI.unescape $'} at #{$1}" if name =~ /(.*[^#:])@/
+
text = name unless text
link lookup, text
@@ -72,6 +70,8 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
def handle_special_CROSSREF(special)
name = special.text
+ return name if name =~ /@[\w-]+\.[\w-]/ # labels that look like emails
+
unless @hyperlink_all then
# This ensures that words entirely consisting of lowercase letters will
# not have cross-references generated (to suppress lots of erroneous
@@ -93,6 +93,25 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
end
##
+ # +special+ is an rdoc-schemed link that will be converted into a hyperlink.
+ # For the rdoc-ref scheme the cross-reference will be looked up and the
+ # given name will be used.
+ #
+ # All other contents are handled by
+ # {the superclass}[rdoc-ref:RDoc::Markup::ToHtml#handle_special_RDOCLINK]
+
+ def handle_special_RDOCLINK special
+ url = special.text
+
+ case url
+ when /\Ardoc-ref:/ then
+ cross_reference $'
+ else
+ super
+ end
+ end
+
+ ##
# Generates links for <tt>rdoc-ref:</tt> scheme URLs and allows
# RDoc::Markup::ToHtml to handle other schemes.
@@ -106,13 +125,31 @@ class RDoc::Markup::ToHtmlCrossref < RDoc::Markup::ToHtml
# Creates an HTML link to +name+ with the given +text+.
def link name, text
+ original_name = name
+
+ if name =~ /(.*[^#:])@/ then
+ name = $1
+ label = $'
+ end
+
ref = @cross_reference.resolve name, text
+ text = ref.output_name @context if
+ RDoc::MethodAttr === ref and text == original_name
+
case ref
when String then
ref
else
- "<a href=\"#{ref.as_href @from_path}\">#{text}</a>"
+ path = ref.as_href @from_path
+
+ if path =~ /#/ then
+ path << "-label-#{label}"
+ else
+ path << "#label-#{label}"
+ end if label
+
+ "<a href=\"#{path}\">#{text}</a>"
end
end
diff --git a/lib/rdoc/markup/to_html_snippet.rb b/lib/rdoc/markup/to_html_snippet.rb
new file mode 100644
index 0000000000..4ad0a9a4b9
--- /dev/null
+++ b/lib/rdoc/markup/to_html_snippet.rb
@@ -0,0 +1,284 @@
+##
+# Outputs RDoc markup as paragraphs with inline markup only.
+
+class RDoc::Markup::ToHtmlSnippet < RDoc::Markup::ToHtml
+
+ ##
+ # After this many characters the input will be cut off.
+
+ attr_reader :character_limit
+
+ ##
+ # The number of characters seen so far.
+
+ attr_reader :characters # :nodoc:
+
+ ##
+ # The attribute bitmask
+
+ attr_reader :mask
+
+ ##
+ # After this many paragraphs the input will be cut off.
+
+ attr_reader :paragraph_limit
+
+ ##
+ # Count of paragraphs found
+
+ attr_reader :paragraphs
+
+ ##
+ # Creates a new ToHtmlSnippet formatter that will cut off the input on the
+ # next word boundary after the given number of +characters+ or +paragraphs+
+ # of text have been encountered.
+
+ def initialize options, characters = 100, paragraphs = 3, markup = nil
+ super options, markup
+
+ @character_limit = characters
+ @paragraph_limit = paragraphs
+
+ @characters = 0
+ @mask = 0
+ @paragraphs = 0
+
+ @markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
+ end
+
+ ##
+ # Adds +heading+ to the output as a paragraph
+
+ def accept_heading heading
+ @res << "<p>#{to_html heading.text}\n"
+
+ add_paragraph
+ end
+
+ ##
+ # Raw sections are untrusted and ignored
+
+ alias accept_raw ignore
+
+ ##
+ # Rules are ignored
+
+ alias accept_rule ignore
+
+ def accept_paragraph paragraph
+ para = @in_list_entry.last || "<p>"
+
+ text = paragraph.text @hard_break
+
+ @res << "#{para}#{wrap to_html text}\n"
+
+ add_paragraph
+ end
+
+ ##
+ # Finishes consumption of +list_item+
+
+ def accept_list_item_end list_item
+ end
+
+ ##
+ # Prepares the visitor for consuming +list_item+
+
+ def accept_list_item_start list_item
+ @res << list_item_start(list_item, @list.last)
+ end
+
+ ##
+ # Prepares the visitor for consuming +list+
+
+ def accept_list_start list
+ @list << list.type
+ @res << html_list_name(list.type, true)
+ @in_list_entry.push ''
+ end
+
+ ##
+ # Adds +verbatim+ to the output
+
+ def accept_verbatim verbatim
+ throw :done if @characters >= @character_limit
+ input = verbatim.text.rstrip
+
+ text = truncate input
+ text << ' ...' unless text == input
+
+ super RDoc::Markup::Verbatim.new text
+
+ add_paragraph
+ end
+
+ ##
+ # Prepares the visitor for HTML snippet generation
+
+ def start_accepting
+ super
+
+ @characters = 0
+ end
+
+ ##
+ # Removes escaping from the cross-references in +special+
+
+ def handle_special_CROSSREF special
+ special.text.sub(/\A\\/, '')
+ end
+
+ ##
+ # +special+ is a <code><br></code>
+
+ def handle_special_HARD_BREAK special
+ @characters -= 4
+ '<br>'
+ end
+
+ ##
+ # Lists are paragraphs, but notes and labels have a separator
+
+ def list_item_start list_item, list_type
+ throw :done if @characters >= @character_limit
+
+ case list_type
+ when :BULLET, :LALPHA, :NUMBER, :UALPHA then
+ "<p>"
+ when :LABEL, :NOTE then
+ labels = Array(list_item.label).map do |label|
+ to_html label
+ end.join ', '
+
+ labels << " &mdash; " unless labels.empty?
+
+ start = "<p>#{labels}"
+ @characters += 1 # try to include the label
+ start
+ else
+ raise RDoc::Error, "Invalid list type: #{list_type.inspect}"
+ end
+ end
+
+ ##
+ # Returns just the text of +link+, +url+ is only used to determine the link
+ # type.
+
+ def gen_url url, text
+ if url =~ /^rdoc-label:([^:]*)(?::(.*))?/ then
+ type = "link"
+ elsif url =~ /([A-Za-z]+):(.*)/ then
+ type = $1
+ else
+ type = "http"
+ end
+
+ if (type == "http" or type == "https" or type == "link") and
+ url =~ /\.(gif|png|jpg|jpeg|bmp)$/ then
+ ''
+ else
+ text.sub(%r%^#{type}:/*%, '')
+ end
+ end
+
+ ##
+ # In snippets, there are no lists
+
+ def html_list_name list_type, open_tag
+ ''
+ end
+
+ ##
+ # Throws +:done+ when paragraph_limit paragraphs have been encountered
+
+ def add_paragraph
+ @paragraphs += 1
+
+ throw :done if @paragraphs >= @paragraph_limit
+ end
+
+ ##
+ # Marks up +content+
+
+ def convert content
+ catch :done do
+ return super
+ end
+
+ end_accepting
+ end
+
+ ##
+ # Converts flow items +flow+
+
+ def convert_flow flow
+ throw :done if @characters >= @character_limit
+
+ res = []
+ @mask = 0
+
+ flow.each do |item|
+ case item
+ when RDoc::Markup::AttrChanger then
+ off_tags res, item
+ on_tags res, item
+ when String then
+ text = convert_string item
+ res << truncate(text)
+ when RDoc::Markup::Special then
+ text = convert_special item
+ res << truncate(text)
+ else
+ raise "Unknown flow element: #{item.inspect}"
+ end
+
+ if @characters >= @character_limit then
+ off_tags res, RDoc::Markup::AttrChanger.new(0, @mask)
+ break
+ end
+ end
+
+ res << ' ...' if @characters >= @character_limit
+
+ res.join
+ end
+
+ ##
+ # Maintains a bitmask to allow HTML elements to be closed properly. See
+ # RDoc::Markup::Formatter.
+
+ def on_tags res, item
+ @mask ^= item.turn_on
+
+ super
+ end
+
+ ##
+ # Maintains a bitmask to allow HTML elements to be closed properly. See
+ # RDoc::Markup::Formatter.
+
+ def off_tags res, item
+ @mask ^= item.turn_off
+
+ super
+ end
+
+ ##
+ # Truncates +text+ at the end of the first word after the character_limit.
+
+ def truncate text
+ length = text.length
+ characters = @characters
+ @characters += length
+
+ return text if @characters < @character_limit
+
+ remaining = @character_limit - characters
+
+ text =~ /\A(.{#{remaining},}?)(\s|$)/m # TODO word-break instead of \s?
+
+ $1
+ end
+
+end
+
diff --git a/lib/rdoc/markup/to_joined_paragraph.rb b/lib/rdoc/markup/to_joined_paragraph.rb
new file mode 100644
index 0000000000..d91eb439f0
--- /dev/null
+++ b/lib/rdoc/markup/to_joined_paragraph.rb
@@ -0,0 +1,68 @@
+##
+# Joins the parts of an RDoc::Markup::Paragraph into a single String.
+#
+# This allows for easier maintenance and testing of Markdown support.
+#
+# This formatter only works on Paragraph instances. Attempting to process
+# other markup syntax items will not work.
+
+class RDoc::Markup::ToJoinedParagraph < RDoc::Markup::Formatter
+
+ def initialize # :nodoc:
+ super nil
+ end
+
+ def start_accepting
+ end
+
+ def end_accepting
+ end
+
+ def accept_paragraph paragraph
+ parts = []
+ string = false
+
+ paragraph.parts.each do |part|
+ if String === part then
+ if string then
+ string << part
+ else
+ parts << part
+ string = part
+ end
+ else
+ parts << part
+ string = false
+ end
+ end
+
+ parts = parts.map do |part|
+ if String === part then
+ part.rstrip
+ else
+ part
+ end
+ end
+
+ # TODO use Enumerable#chunk when ruby 1.8 support is dropped
+ #parts = paragraph.parts.chunk do |part|
+ # String === part
+ #end.map do |string, chunk|
+ # string ? chunk.join.rstrip : chunk
+ #end.flatten
+
+ paragraph.parts.replace parts
+ end
+
+ alias accept_block_quote ignore
+ alias accept_heading ignore
+ alias accept_list_end ignore
+ alias accept_list_item_end ignore
+ alias accept_list_item_start ignore
+ alias accept_list_start ignore
+ alias accept_raw ignore
+ alias accept_rule ignore
+ alias accept_verbatim ignore
+
+end
+
diff --git a/lib/rdoc/markup/to_label.rb b/lib/rdoc/markup/to_label.rb
new file mode 100644
index 0000000000..ace89c324a
--- /dev/null
+++ b/lib/rdoc/markup/to_label.rb
@@ -0,0 +1,74 @@
+require 'cgi'
+
+##
+# Creates HTML-safe labels suitable for use in id attributes. Tidylinks are
+# converted to their link part and cross-reference links have the suppression
+# marks removed (\\SomeClass is converted to SomeClass).
+
+class RDoc::Markup::ToLabel < RDoc::Markup::Formatter
+
+ attr_reader :res # :nodoc:
+
+ ##
+ # Creates a new formatter that will output HTML-safe labels
+
+ def initialize markup = nil
+ super nil, markup
+
+ @markup.add_special RDoc::CrossReference::CROSSREF_REGEXP, :CROSSREF
+ @markup.add_special(/(((\{.*?\})|\b\S+?)\[\S+?\])/, :TIDYLINK)
+
+ add_tag :BOLD, '', ''
+ add_tag :TT, '', ''
+ add_tag :EM, '', ''
+
+ @res = []
+ end
+
+ ##
+ # Converts +text+ to an HTML-safe label
+
+ def convert text
+ label = convert_flow @am.flow text
+
+ CGI.escape label
+ end
+
+ ##
+ # Converts the CROSSREF +special+ to plain text, removing the suppression
+ # marker, if any
+
+ def handle_special_CROSSREF special
+ text = special.text
+
+ text.sub(/^\\/, '')
+ end
+
+ ##
+ # Converts the TIDYLINK +special+ to just the text part
+
+ def handle_special_TIDYLINK special
+ text = special.text
+
+ return text unless text =~ /\{(.*?)\}\[(.*?)\]/ or text =~ /(\S+)\[(.*?)\]/
+
+ $1
+ end
+
+ alias accept_blank_line ignore
+ alias accept_block_quote ignore
+ alias accept_heading ignore
+ alias accept_list_end ignore
+ alias accept_list_item_end ignore
+ alias accept_list_item_start ignore
+ alias accept_list_start ignore
+ alias accept_paragraph ignore
+ alias accept_raw ignore
+ alias accept_rule ignore
+ alias accept_verbatim ignore
+ alias end_accepting ignore
+ alias handle_special_HARD_BREAK ignore
+ alias start_accepting ignore
+
+end
+
diff --git a/lib/rdoc/markup/to_markdown.rb b/lib/rdoc/markup/to_markdown.rb
new file mode 100644
index 0000000000..e984776399
--- /dev/null
+++ b/lib/rdoc/markup/to_markdown.rb
@@ -0,0 +1,134 @@
+# :markup: markdown
+
+##
+# Outputs parsed markup as Markdown
+
+class RDoc::Markup::ToMarkdown < RDoc::Markup::ToRdoc
+
+ ##
+ # Creates a new formatter that will output Markdown format text
+
+ def initialize markup = nil
+ super
+
+ @headings[1] = ['# ', '']
+ @headings[2] = ['## ', '']
+ @headings[3] = ['### ', '']
+ @headings[4] = ['#### ', '']
+ @headings[5] = ['##### ', '']
+ @headings[6] = ['###### ', '']
+
+ @hard_break = " \n"
+ end
+
+ ##
+ # Maps attributes to HTML sequences
+
+ def init_tags
+ add_tag :BOLD, '**', '**'
+ add_tag :EM, '*', '*'
+ add_tag :TT, '`', '`'
+ end
+
+ ##
+ # Adds a newline to the output
+
+ def handle_special_HARD_BREAK special
+ " \n"
+ end
+
+ ##
+ # Finishes consumption of `list`
+
+ def accept_list_end list
+ @res << "\n"
+
+ super
+ end
+
+ ##
+ # Finishes consumption of `list_item`
+
+ def accept_list_item_end list_item
+ width = case @list_type.last
+ when :BULLET then
+ 4
+ when :NOTE, :LABEL then
+ use_prefix
+
+ 4
+ else
+ @list_index[-1] = @list_index.last.succ
+ 4
+ end
+
+ @indent -= width
+ end
+
+ ##
+ # Prepares the visitor for consuming `list_item`
+
+ def accept_list_item_start list_item
+ type = @list_type.last
+
+ case type
+ when :NOTE, :LABEL then
+ bullets = Array(list_item.label).map do |label|
+ attributes(label).strip
+ end.join "\n"
+
+ bullets << "\n:"
+
+ @prefix = ' ' * @indent
+ @indent += 4
+ @prefix << bullets + (' ' * (@indent - 1))
+ else
+ bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.'
+ @prefix = (' ' * @indent) + bullet.ljust(4)
+
+ @indent += 4
+ end
+ end
+
+ ##
+ # Prepares the visitor for consuming `list`
+
+ def accept_list_start list
+ case list.type
+ when :BULLET, :LABEL, :NOTE then
+ @list_index << nil
+ when :LALPHA, :NUMBER, :UALPHA then
+ @list_index << 1
+ else
+ raise RDoc::Error, "invalid list type #{list.type}"
+ end
+
+ @list_width << 4
+ @list_type << list.type
+ end
+
+ ##
+ # Adds `rule` to the output
+
+ def accept_rule rule
+ use_prefix or @res << ' ' * @indent
+ @res << '-' * 3
+ @res << "\n"
+ end
+
+ ##
+ # Outputs `verbatim` indented 4 columns
+
+ def accept_verbatim verbatim
+ indent = ' ' * (@indent + 4)
+
+ verbatim.parts.each do |part|
+ @res << indent unless part == "\n"
+ @res << part
+ end
+
+ @res << "\n" unless @res =~ /\n\z/
+ end
+
+end
+
diff --git a/lib/rdoc/markup/to_rdoc.rb b/lib/rdoc/markup/to_rdoc.rb
index 6f2faac2f6..f16b4ed5a3 100644
--- a/lib/rdoc/markup/to_rdoc.rb
+++ b/lib/rdoc/markup/to_rdoc.rb
@@ -1,6 +1,3 @@
-require 'rdoc/markup/formatter'
-require 'rdoc/markup/inline'
-
##
# Outputs RDoc markup as RDoc markup! (mostly)
@@ -45,7 +42,7 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
# Creates a new formatter that will output (mostly) \RDoc markup
def initialize markup = nil
- super
+ super nil, markup
@markup.add_special(/\\\S/, :SUPPRESSED_CROSSREF)
@width = 78
@@ -60,6 +57,8 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
@headings[4] = ['==== ', '']
@headings[5] = ['===== ', '']
@headings[6] = ['====== ', '']
+
+ @hard_break = "\n"
end
##
@@ -79,6 +78,21 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
end
##
+ # Adds +paragraph+ to the output
+
+ def accept_block_quote block_quote
+ @indent += 2
+
+ block_quote.parts.each do |part|
+ @prefix = '> '
+
+ part.accept self
+ end
+
+ @indent -= 2
+ end
+
+ ##
# Adds +heading+ to the output
def accept_heading heading
@@ -106,6 +120,11 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
when :BULLET then
2
when :NOTE, :LABEL then
+ if @prefix then
+ @res << @prefix.strip
+ @prefix = nil
+ end
+
@res << "\n"
2
else
@@ -125,10 +144,15 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
case type
when :NOTE, :LABEL then
- bullet = attributes(list_item.label) + ":\n"
+ bullets = Array(list_item.label).map do |label|
+ attributes(label).strip
+ end.join "\n"
+
+ bullets << ":\n" unless bullets.empty?
+
@prefix = ' ' * @indent
@indent += 2
- @prefix << bullet + (' ' * @indent)
+ @prefix << bullets + (' ' * @indent)
else
bullet = type == :BULLET ? '*' : @list_index.last.to_s + '.'
@prefix = (' ' * @indent) + bullet.ljust(bullet.length + 1)
@@ -168,7 +192,8 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
# Adds +paragraph+ to the output
def accept_paragraph paragraph
- wrap attributes(paragraph.text)
+ text = paragraph.text @hard_break
+ wrap attributes text
end
##
@@ -176,7 +201,8 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
def accept_indented_paragraph paragraph
@indent += paragraph.indent
- wrap attributes(paragraph.text)
+ text = paragraph.text @hard_break
+ wrap attributes text
@indent -= paragraph.indent
end
@@ -235,6 +261,13 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
end
##
+ # Adds a newline to the output
+
+ def handle_special_HARD_BREAK special
+ "\n"
+ end
+
+ ##
# Prepares the visitor for text generation
def start_accepting
@@ -252,8 +285,7 @@ class RDoc::Markup::ToRdoc < RDoc::Markup::Formatter
# prefix for later consumption.
def use_prefix
- prefix = @prefix
- @prefix = nil
+ prefix, @prefix = @prefix, nil
@res << prefix if prefix
prefix
diff --git a/lib/rdoc/markup/to_table_of_contents.rb b/lib/rdoc/markup/to_table_of_contents.rb
new file mode 100644
index 0000000000..54f2d5f64f
--- /dev/null
+++ b/lib/rdoc/markup/to_table_of_contents.rb
@@ -0,0 +1,61 @@
+##
+# Extracts just the RDoc::Markup::Heading elements from a
+# RDoc::Markup::Document to help build a table of contents
+
+class RDoc::Markup::ToTableOfContents < RDoc::Markup::Formatter
+
+ @to_toc = nil
+
+ ##
+ # Singleton for table-of-contents generation
+
+ def self.to_toc
+ @to_toc ||= new
+ end
+
+ ##
+ # Output accumulator
+
+ attr_reader :res
+
+ def initialize # :nodoc:
+ super nil
+ end
+
+ ##
+ # Adds +heading+ to the table of contents
+
+ def accept_heading heading
+ @res << heading
+ end
+
+ ##
+ # Returns the table of contents
+
+ def end_accepting
+ @res
+ end
+
+ ##
+ # Prepares the visitor for text generation
+
+ def start_accepting
+ @res = []
+ end
+
+ # :stopdoc:
+ alias accept_block_quote ignore
+ alias accept_raw ignore
+ alias accept_rule ignore
+ alias accept_blank_line ignore
+ alias accept_paragraph ignore
+ alias accept_verbatim ignore
+ alias accept_list_end ignore
+ alias accept_list_item_start ignore
+ alias accept_list_item_end ignore
+ alias accept_list_end_bullet ignore
+ alias accept_list_start ignore
+ # :startdoc:
+
+end
+
diff --git a/lib/rdoc/markup/to_test.rb b/lib/rdoc/markup/to_test.rb
index 4847fd29f7..c51f64b917 100644
--- a/lib/rdoc/markup/to_test.rb
+++ b/lib/rdoc/markup/to_test.rb
@@ -1,6 +1,3 @@
-require 'rdoc/markup'
-require 'rdoc/markup/formatter'
-
##
# This Markup outputter is used for testing purposes.
diff --git a/lib/rdoc/markup/to_tt_only.rb b/lib/rdoc/markup/to_tt_only.rb
index 078e87db98..e2da20c6f3 100644
--- a/lib/rdoc/markup/to_tt_only.rb
+++ b/lib/rdoc/markup/to_tt_only.rb
@@ -1,6 +1,3 @@
-require 'rdoc/markup/formatter'
-require 'rdoc/markup/inline'
-
##
# Extracts sections of text enclosed in plus, tt or code. Used to discover
# undocumented parameters.
@@ -21,12 +18,19 @@ class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter
# Creates a new tt-only formatter.
def initialize markup = nil
- super
+ super nil, markup
add_tag :TT, nil, nil
end
##
+ # Adds tts from +block_quote+ to the output
+
+ def accept_block_quote block_quote
+ tt_sections block_quote.text
+ end
+
+ ##
# Pops the list type for +list+ from #list_type
def accept_list_end list
@@ -46,7 +50,9 @@ class RDoc::Markup::ToTtOnly < RDoc::Markup::Formatter
def accept_list_item_start list_item
case @list_type.last
when :NOTE, :LABEL then
- tt_sections(list_item.label)
+ Array(list_item.label).map do |label|
+ tt_sections label
+ end.flatten
end
end
diff --git a/lib/rdoc/markup/verbatim.rb b/lib/rdoc/markup/verbatim.rb
index 8fe2184699..3886bbe8a5 100644
--- a/lib/rdoc/markup/verbatim.rb
+++ b/lib/rdoc/markup/verbatim.rb
@@ -4,6 +4,21 @@
class RDoc::Markup::Verbatim < RDoc::Markup::Raw
##
+ # Format of this verbatim section
+
+ attr_accessor :format
+
+ def initialize *parts # :nodoc:
+ super
+
+ @format = nil
+ end
+
+ def == other # :nodoc:
+ super and @format == other.format
+ end
+
+ ##
# Calls #accept_verbatim on +visitor+
def accept visitor
@@ -34,6 +49,29 @@ class RDoc::Markup::Verbatim < RDoc::Markup::Raw
@parts = parts
end
+ def pretty_print q # :nodoc:
+ self.class.name =~ /.*::(\w{1,4})/i
+
+ q.group 2, "[#{$1.downcase}: ", ']' do
+ if @format then
+ q.text "format: #{@format}"
+ q.breakable
+ end
+
+ q.seplist @parts do |part|
+ q.pp part
+ end
+ end
+ end
+
+ ##
+ # Is this verbatim section ruby code?
+
+ def ruby?
+ @format ||= nil # TODO for older ri data, switch the tree to marshal_dump
+ @format == :ruby
+ end
+
##
# The text of the section
diff --git a/lib/rdoc/meta_method.rb b/lib/rdoc/meta_method.rb
index e0c065c2ba..68ba8109e0 100644
--- a/lib/rdoc/meta_method.rb
+++ b/lib/rdoc/meta_method.rb
@@ -1,5 +1,3 @@
-require 'rdoc/any_method'
-
##
# MetaMethod represents a meta-programmed method
diff --git a/lib/rdoc/method_attr.rb b/lib/rdoc/method_attr.rb
index a4cd3c5fff..5021929ea0 100644
--- a/lib/rdoc/method_attr.rb
+++ b/lib/rdoc/method_attr.rb
@@ -1,5 +1,3 @@
-require 'rdoc/code_object'
-
##
# Abstract class representing either a method or an attribute.
@@ -100,7 +98,12 @@ class RDoc::MethodAttr < RDoc::CodeObject
# Order by #singleton then #name
def <=>(other)
- [@singleton ? 0 : 1, name] <=> [other.singleton ? 0 : 1, other.name]
+ [ @singleton ? 0 : 1, name] <=>
+ [other.singleton ? 0 : 1, other.name]
+ end
+
+ def == other # :nodoc:
+ super or self.class == other.class and full_name == other.full_name
end
##
@@ -135,6 +138,15 @@ class RDoc::MethodAttr < RDoc::CodeObject
@see
end
+ ##
+ # Sets the store for this class or module and its contained code objects.
+
+ def store= store
+ super
+
+ @file = @store.add_file @file.full_name if @file
+ end
+
def find_see # :nodoc:
return nil if singleton || is_alias_for
@@ -151,7 +163,7 @@ class RDoc::MethodAttr < RDoc::CodeObject
return nil unless parent.respond_to? :ancestors
searched = parent.ancestors
- kernel = RDoc::TopLevel.all_modules_hash['Kernel']
+ kernel = @store.modules_hash['Kernel']
searched << kernel if kernel &&
parent != kernel && !searched.include?(kernel)
@@ -173,10 +185,10 @@ class RDoc::MethodAttr < RDoc::CodeObject
# Abstract method. Contexts in their building phase call this
# to register a new alias for this known method/attribute.
#
- # - creates a new AnyMethod/Attribute +newa+ named an_alias.new_name;
- # - adds +self+ as +newa.is_alias_for+;
- # - adds +newa+ to #aliases
- # - adds +newa+ to the methods/attributes of +context+.
+ # - creates a new AnyMethod/Attribute named <tt>an_alias.new_name</tt>;
+ # - adds +self+ as an alias for the new method or attribute
+ # - adds the method or attribute to #aliases
+ # - adds the method or attribute to +context+.
def add_alias(an_alias, context)
raise NotImplementedError
@@ -261,6 +273,8 @@ class RDoc::MethodAttr < RDoc::CodeObject
# HTML id-friendly method/attribute name
def html_name
+ require 'cgi'
+
CGI.escape(@name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '')
end
@@ -268,14 +282,39 @@ class RDoc::MethodAttr < RDoc::CodeObject
# Full method/attribute name including namespace
def full_name
- @full_name || "#{parent_name}#{pretty_name}"
+ @full_name ||= "#{parent_name}#{pretty_name}"
+ end
+
+ def inspect # :nodoc:
+ alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
+ visibility = self.visibility
+ visibility = "forced #{visibility}" if force_documentation
+ "#<%s:0x%x %s (%s)%s>" % [
+ self.class, object_id,
+ full_name,
+ visibility,
+ alias_for,
+ ]
end
##
# '::' for a class method/attribute, '#' for an instance method.
def name_prefix
- singleton ? '::' : '#'
+ @singleton ? '::' : '#'
+ end
+
+ ##
+ # Name for output to HTML. For class methods the full name with a "." is
+ # used like +SomeClass.method_name+. For instance methods the class name is
+ # used if +context+ does not match the parent.
+ #
+ # This is to help prevent people from using :: to call class methods.
+
+ def output_name context
+ return "#{name_prefix}#{@name}" if context == parent
+
+ "#{parent_name}#{@singleton ? '.' : '#'}#{@name}"
end
##
@@ -293,7 +332,7 @@ class RDoc::MethodAttr < RDoc::CodeObject
end
##
- # Path to this method
+ # Path to this method for use with HTML generator output.
def path
"#{@parent.path}##{aref}"
@@ -331,15 +370,19 @@ class RDoc::MethodAttr < RDoc::CodeObject
end
end
- def inspect # :nodoc:
- alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil
- visibility = self.visibility
- visibility = "forced #{visibility}" if force_documentation
- "#<%s:0x%x %s (%s)%s>" % [
- self.class, object_id,
+ ##
+ # Used by RDoc::Generator::JsonIndex to create a record for the search
+ # engine.
+
+ def search_record
+ [
+ @name,
full_name,
- visibility,
- alias_for,
+ @name,
+ @parent.full_name,
+ path,
+ params,
+ snippet(@comment),
]
end
diff --git a/lib/rdoc/normal_class.rb b/lib/rdoc/normal_class.rb
index f67380e783..dd7482c37c 100644
--- a/lib/rdoc/normal_class.rb
+++ b/lib/rdoc/normal_class.rb
@@ -1,15 +1,23 @@
-require 'rdoc/class_module'
-
##
# A normal class, neither singleton nor anonymous
class RDoc::NormalClass < RDoc::ClassModule
##
- # Appends the superclass, if any, to the included modules.
+ # The ancestors of this class including modules. Unlike Module#ancestors,
+ # this class is not included in the result. The result will contain both
+ # RDoc::ClassModules and Strings.
def ancestors
- superclass ? super + [superclass] : super
+ if String === superclass then
+ super << superclass
+ elsif superclass then
+ ancestors = super
+ ancestors << superclass
+ ancestors.concat superclass.ancestors
+ else
+ super
+ end
end
##
@@ -19,11 +27,15 @@ class RDoc::NormalClass < RDoc::ClassModule
"class #{full_name}"
end
+ def direct_ancestors
+ superclass ? super + [superclass] : super
+ end
+
def inspect # :nodoc:
superclass = @superclass ? " < #{@superclass}" : nil
- "<%s:0x%x class %s%s includes: %p attributes: %p methods: %p aliases: %p>" % [
+ "<%s:0x%x class %s%s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [
self.class, object_id,
- full_name, superclass, @includes, @attributes, @method_list, @aliases
+ full_name, superclass, @includes, @extends, @attributes, @method_list, @aliases
]
end
@@ -46,19 +58,24 @@ class RDoc::NormalClass < RDoc::ClassModule
q.seplist @includes do |inc| q.pp inc end
q.breakable
+ q.text "constants:"
+ q.breakable
+ q.seplist @constants do |const| q.pp const end
+
+ q.breakable
q.text "attributes:"
q.breakable
- q.seplist @attributes do |inc| q.pp inc end
+ q.seplist @attributes do |attr| q.pp attr end
q.breakable
q.text "methods:"
q.breakable
- q.seplist @method_list do |inc| q.pp inc end
+ q.seplist @method_list do |meth| q.pp meth end
q.breakable
q.text "aliases:"
q.breakable
- q.seplist @aliases do |inc| q.pp inc end
+ q.seplist @aliases do |aliaz| q.pp aliaz end
q.breakable
q.text "comment:"
diff --git a/lib/rdoc/normal_module.rb b/lib/rdoc/normal_module.rb
index 0fa7223547..cd77b1e39e 100644
--- a/lib/rdoc/normal_module.rb
+++ b/lib/rdoc/normal_module.rb
@@ -1,14 +1,12 @@
-require 'rdoc/class_module'
-
##
# A normal module, like NormalClass
class RDoc::NormalModule < RDoc::ClassModule
def inspect # :nodoc:
- "#<%s:0x%x module %s includes: %p attributes: %p methods: %p aliases: %p>" % [
+ "#<%s:0x%x module %s includes: %p extends: %p attributes: %p methods: %p aliases: %p>" % [
self.class, object_id,
- full_name, @includes, @attributes, @method_list, @aliases
+ full_name, @includes, @extends, @attributes, @method_list, @aliases
]
end
@@ -34,19 +32,24 @@ class RDoc::NormalModule < RDoc::ClassModule
q.seplist @includes do |inc| q.pp inc end
q.breakable
+ q.breakable
+ q.text "constants:"
+ q.breakable
+ q.seplist @constants do |const| q.pp const end
+
q.text "attributes:"
q.breakable
- q.seplist @attributes do |inc| q.pp inc end
+ q.seplist @attributes do |attr| q.pp attr end
q.breakable
q.text "methods:"
q.breakable
- q.seplist @method_list do |inc| q.pp inc end
+ q.seplist @method_list do |meth| q.pp meth end
q.breakable
q.text "aliases:"
q.breakable
- q.seplist @aliases do |inc| q.pp inc end
+ q.seplist @aliases do |aliaz| q.pp aliaz end
q.breakable
q.text "comment:"
diff --git a/lib/rdoc/options.rb b/lib/rdoc/options.rb
index bab5463897..d862b0adf3 100644
--- a/lib/rdoc/options.rb
+++ b/lib/rdoc/options.rb
@@ -1,9 +1,62 @@
require 'optparse'
-require 'rdoc/ri/paths'
-
##
# RDoc::Options handles the parsing and storage of options
+#
+# == Saved Options
+#
+# You can save some options like the markup format in the
+# <tt>.rdoc_options</tt> file in your gem. The easiest way to do this is:
+#
+# rdoc --markup tomdoc --write-options
+#
+# Which will automatically create the file and fill it with the options you
+# specified.
+#
+# The following options will not be saved since they interfere with the user's
+# preferences or with the normal operation of RDoc:
+#
+# * +--coverage-report+
+# * +--dry-run+
+# * +--encoding+
+# * +--force-update+
+# * +--format+
+# * +--pipe+
+# * +--quiet+
+# * +--template+
+# * +--verbose+
+#
+# == Custom Options
+#
+# Generators can hook into RDoc::Options to add generator-specific command
+# line options.
+#
+# When <tt>--format</tt> is encountered in ARGV, RDoc calls ::setup_options on
+# the generator class to add extra options to the option parser. Options for
+# custom generators must occur after <tt>--format</tt>. <tt>rdoc --help</tt>
+# will list options for all installed generators.
+#
+# Example:
+#
+# class RDoc::Generator::Spellcheck
+# RDoc::RDoc.add_generator self
+#
+# def self.setup_options rdoc_options
+# op = rdoc_options.option_parser
+#
+# op.on('--spell-dictionary DICTIONARY',
+# RDoc::Options::Path) do |dictionary|
+# rdoc_options.spell_dictionary = dictionary
+# end
+# end
+# end
+#
+# == Option Validators
+#
+# OptionParser validators will validate and cast user input values. In
+# addition to the validators that ship with OptionParser (String, Integer,
+# Float, TrueClass, FalseClass, Array, Regexp, Date, Time, URI, etc.),
+# RDoc::Options adds Path, PathArray and Template.
class RDoc::Options
@@ -25,9 +78,50 @@ class RDoc::Options
}
##
- # Template option validator for OptionParser
+ # RDoc options ignored (or handled specially) by --write-options
+
+ SPECIAL = %w[
+ coverage_report
+ dry_run
+ encoding
+ files
+ force_output
+ force_update
+ generator
+ generator_name
+ generator_options
+ generators
+ op_dir
+ option_parser
+ pipe
+ rdoc_include
+ static_path
+ stylesheet_url
+ template
+ template_dir
+ update_output_dir
+ verbosity
+ write_options
+ ]
+
+ ##
+ # Option validator for OptionParser that matches a file or directory that
+ # exists on the filesystem.
+
+ Path = Object.new
+
+ ##
+ # Option validator for OptionParser that matches a comma-separated list of
+ # files or directories that exist on the filesystem.
- Template = nil
+ PathArray = Object.new
+
+ ##
+ # Option validator for OptionParser that matches a template directory for an
+ # installed generator that lives in
+ # <tt>"rdoc/generator/template/#{template_name}"</tt>
+
+ Template = Object.new
##
# Character-set for HTML output. #encoding is preferred over #charset
@@ -40,9 +134,11 @@ class RDoc::Options
attr_accessor :dry_run
##
- # Encoding of output where. This is set via --encoding.
+ # The output encoding. All input files will be transcoded to this encoding.
+ #
+ # The default encoding is UTF-8. This is set via --encoding.
- attr_accessor :encoding if Object.const_defined? :Encoding
+ attr_accessor :encoding
##
# Files matching this pattern will be excluded
@@ -71,11 +167,16 @@ class RDoc::Options
attr_accessor :formatter
##
- # Description of the output generator (set with the <tt>--fmt</tt> option)
+ # Description of the output generator (set with the <tt>--format</tt> option)
attr_accessor :generator
##
+ # For #==
+
+ attr_reader :generator_name # :nodoc:
+
+ ##
# Loaded generator options. Used to prevent --help from loading the same
# options multiple times.
@@ -99,6 +200,12 @@ class RDoc::Options
attr_accessor :main_page
##
+ # The default markup format. The default is 'rdoc'. 'markdown', 'tomdoc'
+ # and 'rd' are also built-in.
+
+ attr_accessor :markup
+
+ ##
# If true, only report on undocumented files
attr_accessor :coverage_report
@@ -129,6 +236,11 @@ class RDoc::Options
attr_accessor :show_hash
##
+ # Directory to copy static files from
+
+ attr_accessor :static_path
+
+ ##
# The number of columns in a tab
attr_accessor :tab_width
@@ -171,9 +283,13 @@ class RDoc::Options
attr_accessor :visibility
def initialize # :nodoc:
- require 'rdoc/rdoc'
+ init_ivars
+ end
+
+ def init_ivars # :nodoc:
@dry_run = false
@exclude = []
+ @files = nil
@force_output = false
@force_update = true
@generator = nil
@@ -183,12 +299,14 @@ class RDoc::Options
@hyperlink_all = false
@line_numbers = false
@main_page = nil
+ @markup = 'rdoc'
@coverage_report = false
@op_dir = nil
@pipe = false
@rdoc_include = []
@show_hash = false
- @stylesheet_url = nil
+ @static_path = []
+ @stylesheet_url = nil # TODO remove in RDoc 4
@tab_width = 8
@template = nil
@template_dir = nil
@@ -197,15 +315,67 @@ class RDoc::Options
@verbosity = 1
@visibility = :protected
@webcvs = nil
+ @write_options = false
if Object.const_defined? :Encoding then
- @encoding = Encoding.default_external
- @charset = @encoding.to_s
+ @encoding = Encoding::UTF_8
+ @charset = @encoding.name
else
+ @encoding = nil
@charset = 'UTF-8'
end
end
+ def init_with map # :nodoc:
+ init_ivars
+
+ encoding = map['encoding']
+ @encoding = if Object.const_defined? :Encoding then
+ encoding ? Encoding.find(encoding) : encoding
+ end
+
+ @charset = map['charset']
+ @exclude = map['exclude']
+ @generator_name = map['generator_name']
+ @hyperlink_all = map['hyperlink_all']
+ @line_numbers = map['line_numbers']
+ @main_page = map['main_page']
+ @markup = map['markup']
+ @op_dir = map['op_dir']
+ @show_hash = map['show_hash']
+ @tab_width = map['tab_width']
+ @template_dir = map['template_dir']
+ @title = map['title']
+ @visibility = map['visibility']
+ @webcvs = map['webcvs']
+
+ @rdoc_include = sanitize_path map['rdoc_include']
+ @static_path = sanitize_path map['static_path']
+ end
+
+ def yaml_initialize tag, map # :nodoc:
+ init_with map
+ end
+
+ def == other # :nodoc:
+ self.class === other and
+ @encoding == other.encoding and
+ @generator_name == other.generator_name and
+ @hyperlink_all == other.hyperlink_all and
+ @line_numbers == other.line_numbers and
+ @main_page == other.main_page and
+ @markup == other.markup and
+ @op_dir == other.op_dir and
+ @rdoc_include == other.rdoc_include and
+ @show_hash == other.show_hash and
+ @static_path == other.static_path and
+ @tab_width == other.tab_width and
+ @template == other.template and
+ @title == other.title and
+ @visibility == other.visibility and
+ @webcvs == other.webcvs
+ end
+
##
# Check that the files on the command line exist
@@ -247,6 +417,24 @@ class RDoc::Options
end
##
+ # For dumping YAML
+
+ def encode_with coder # :nodoc:
+ encoding = @encoding ? @encoding.name : nil
+
+ coder.add 'encoding', encoding
+ coder.add 'static_path', sanitize_path(@static_path)
+ coder.add 'rdoc_include', sanitize_path(@rdoc_include)
+
+ ivars = instance_variables.map { |ivar| ivar.to_s[1..-1] }
+ ivars -= SPECIAL
+
+ ivars.sort.each do |ivar|
+ coder.add ivar, instance_variable_get("@#{ivar}")
+ end
+ end
+
+ ##
# Completes any unfinished option setup business such as filtering for
# existent files, creating a regexp for #exclude and setting a default
# #template.
@@ -306,7 +494,7 @@ class RDoc::Options
##
# Parses command line options.
- def parse(argv)
+ def parse argv
ignore_invalid = true
argv.insert(0, *ENV['RDOCOPT'].split) if ENV['RDOCOPT']
@@ -367,13 +555,35 @@ Usage: #{opt.program_name} [options] [names...]
template_dir = template_dir_for template
unless template_dir then
- warn "could not find template #{template}"
+ $stderr.puts "could not find template #{template}"
nil
else
[template, template_dir]
end
end
+ opt.accept Path do |path|
+ path = File.expand_path path
+
+ raise OptionParser::InvalidArgument unless File.exist? path
+
+ path
+ end
+
+ opt.accept PathArray do |paths,|
+ paths = if paths then
+ paths.split(',').map { |d| d unless d.empty? }
+ end
+
+ paths.map do |path|
+ path = File.expand_path path
+
+ raise OptionParser::InvalidArgument unless File.exist? path
+
+ path
+ end
+ end
+
opt.separator nil
opt.separator "Parsing options:"
opt.separator nil
@@ -382,9 +592,10 @@ Usage: #{opt.program_name} [options] [names...]
opt.on("--encoding=ENCODING", "-e", Encoding.list.map { |e| e.name },
"Specifies the output encoding. All files",
"read will be converted to this encoding.",
- "Preferred over --charset") do |value|
+ "The default encoding is UTF-8.",
+ "--encoding is preferred over --charset") do |value|
@encoding = Encoding.find value
- @charset = @encoding.to_s # may not be valid value
+ @charset = @encoding.name # may not be valid value
end
opt.separator nil
@@ -452,6 +663,17 @@ Usage: #{opt.program_name} [options] [names...]
end
opt.separator nil
+
+ markup_formats = RDoc::Text::MARKUP_FORMAT.keys.sort
+
+ opt.on("--markup=MARKUP", markup_formats,
+ "The markup format for the named files.",
+ "The default is rdoc. Valid values are:",
+ markup_formats.join(', ')) do |value|
+ @markup = value
+ end
+
+ opt.separator nil
opt.separator "Common generator options:"
opt.separator nil
@@ -477,7 +699,7 @@ Usage: #{opt.program_name} [options] [names...]
opt.separator nil
- opt.on("--include=DIRECTORIES", "-i", Array,
+ opt.on("--include=DIRECTORIES", "-i", PathArray,
"Set (or add to) the list of directories to",
"be searched when satisfying :include:",
"requests. Can be used more than once.") do |value|
@@ -576,6 +798,18 @@ Usage: #{opt.program_name} [options] [names...]
opt.separator nil
+ opt.on("--copy-files=PATH", Path,
+ "Specify a file or directory to copy static",
+ "files from.",
+ "If a file is given it will be copied into",
+ "the output dir. If a directory is given the",
+ "entire directory will be copied.",
+ "You can use this multiple times") do |value|
+ @static_path << value
+ end
+
+ opt.separator nil
+
opt.on("--webcvs=URL", "-W",
"Specify a URL for linking to a web frontend",
"to CVS. If the URL contains a '\%s', the",
@@ -620,32 +854,52 @@ Usage: #{opt.program_name} [options] [names...]
opt.separator "Generic options:"
opt.separator nil
+ opt.on("--write-options",
+ "Write .rdoc_options to the current",
+ "directory with the given options. Not all",
+ "options will be used. See RDoc::Options",
+ "for details.") do |value|
+ @write_options = true
+ end
+
+ opt.separator nil
+
opt.on("--[no-]dry-run",
"Don't write any files") do |value|
@dry_run = value
end
+ opt.separator nil
+
opt.on("-D", "--[no-]debug",
"Displays lots on internal stuff.") do |value|
$DEBUG_RDOC = value
end
+ opt.separator nil
+
opt.on("--[no-]ignore-invalid",
"Ignore invalid options and continue",
"(default true).") do |value|
ignore_invalid = value
end
+ opt.separator nil
+
opt.on("--quiet", "-q",
"Don't show progress as we parse.") do |value|
@verbosity = 0
end
+ opt.separator nil
+
opt.on("--verbose", "-v",
"Display extra progress as RDoc parses") do |value|
@verbosity = 2
end
+ opt.separator nil
+
opt.on("--help",
"Display this help") do
RDoc::RDoc::GENERATORS.each_key do |generator|
@@ -711,6 +965,13 @@ Usage: #{opt.program_name} [options] [names...]
@files = argv.dup
finish
+
+ if @write_options then
+ write_options
+ exit
+ end
+
+ self
end
##
@@ -728,6 +989,20 @@ Usage: #{opt.program_name} [options] [names...]
end
##
+ # Removes directories from +path+ that are outside the current directory
+
+ def sanitize_path path
+ require 'pathname'
+ dot = Pathname.new('.').expand_path
+
+ path.reject do |item|
+ path = Pathname.new(item).expand_path
+ relative = path.relative_path_from(dot).to_s
+ relative.start_with? '..'
+ end
+ end
+
+ ##
# Set up an output generator for the named +generator_name+.
#
# If the found generator responds to :setup_options it will be called with
@@ -766,5 +1041,39 @@ Usage: #{opt.program_name} [options] [names...]
end
end
+ ##
+ # This is compatibility code for syck
+
+ def to_yaml opts = {} # :nodoc:
+ return super if YAML.const_defined?(:ENGINE) and not YAML::ENGINE.syck?
+
+ YAML.quick_emit self, opts do |out|
+ out.map taguri, to_yaml_style do |map|
+ encode_with map
+ end
+ end
+ end
+
+ ##
+ # Displays a warning using Kernel#warn if we're being verbose
+
+ def warn message
+ super message if @verbosity > 1
+ end
+
+ ##
+ # Writes the YAML file .rdoc_options to the current directory containing the
+ # parsed options.
+
+ def write_options
+ RDoc.load_yaml
+
+ open '.rdoc_options', 'w' do |io|
+ io.set_encoding Encoding::UTF_8 if Object.const_defined? :Encoding
+
+ YAML.dump self, io
+ end
+ end
+
end
diff --git a/lib/rdoc/parser.rb b/lib/rdoc/parser.rb
index 1dee485492..b51f7868ea 100644
--- a/lib/rdoc/parser.rb
+++ b/lib/rdoc/parser.rb
@@ -1,41 +1,31 @@
-require 'rdoc'
-require 'rdoc/code_objects'
-require 'rdoc/markup/pre_process'
-require 'rdoc/stats'
-
##
-# A parser is a class that subclasses RDoc::Parser and implements
-#
-# #initialize top_level, file_name, body, options, stats
-#
-# and
-#
-# #scan
+# A parser is simple a class that subclasses RDoc::Parser and implements #scan
+# to fill in an RDoc::TopLevel with parsed data.
#
-# The initialize method takes a file name to be used, the body of the file,
-# and an RDoc::Options object. The scan method is then called to return an
-# appropriately parsed TopLevel code object.
+# The initialize method takes an RDoc::TopLevel to fill with parsed content,
+# the name of the file to be parsed, the content of the file, an RDoc::Options
+# object and an RDoc::Stats object to inform the user of parsed items. The
+# scan method is then called to parse the file and must return the
+# RDoc::TopLevel object. By calling super these items will be set for you.
#
-# RDoc::Parser::for is a factory that creates the correct parser for a
-# given filename extension. Parsers have to register themselves RDoc::Parser
-# using parse_files_matching as when they are loaded:
+# In order to be used by RDoc the parser needs to register the file extensions
+# it can parse. Use ::parse_files_matching to register extensions.
#
-# require "rdoc/parser"
+# require 'rdoc'
#
# class RDoc::Parser::Xyz < RDoc::Parser
-# parse_files_matching /\.xyz$/ # <<<<
+# parse_files_matching /\.xyz$/
#
-# def initialize top_level, file_name, body, options, stats
-# ...
+# def initialize top_level, file_name, content, options, stats
+# super
+#
+# # extra initialization if needed
# end
#
# def scan
-# ...
+# # parse file and fill in @top_level
# end
# end
-#
-# If a plain text file is detected, RDoc also looks for a shebang line in case
-# the file is a shell script.
class RDoc::Parser
@@ -61,7 +51,7 @@ class RDoc::Parser
old_ext = old_ext.sub(/^\.(.*)/, '\1')
new_ext = new_ext.sub(/^\.(.*)/, '\1')
- parser = can_parse_by_name "xxx.#{old_ext}"
+ parser = can_parse "xxx.#{old_ext}"
return false unless parser
RDoc::Parser.parsers.unshift [/\.#{new_ext}$/, parser]
@@ -80,14 +70,14 @@ class RDoc::Parser
have_encoding = s.respond_to? :encoding
+ if have_encoding then
+ return false if s.encoding != Encoding::ASCII_8BIT and s.valid_encoding?
+ end
+
return true if s[0, 2] == Marshal.dump('')[0, 2] or s.index("\x00")
if have_encoding then
- mode = "r"
- s.sub!(/\A#!.*\n/, '') # assume shebang line isn't longer than 1024.
- encoding = s[/^\s*\#\s*(?:-\*-\s*)?(?:en)?coding:\s*([^\s;]+?)(?:-\*-|[\s;])/, 1]
- mode = "r:#{encoding}" if encoding
- s = File.open(file, mode) {|f| f.gets(nil, 1024)}
+ s.force_encoding Encoding.default_external
not s.valid_encoding?
else
@@ -134,54 +124,51 @@ class RDoc::Parser
zip_signature == "PK\x03\x04" or
zip_signature == "PK\x05\x06" or
zip_signature == "PK\x07\x08"
- rescue
- false
end
##
# Return a parser that can handle a particular extension
def self.can_parse(file_name)
- parser = can_parse_by_name(file_name)
+ parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }.last
# HACK Selenium hides a jar file using a .txt extension
return if parser == RDoc::Parser::Simple and zip? file_name
- parser
- end
-
- def self.can_parse_by_name(file_name)
- pattern, parser = RDoc::Parser.parsers.find { |regexp,| regexp =~ file_name }
-
# The default parser must not parse binary files
ext_name = File.extname file_name
return parser if ext_name.empty?
- return if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/ and file_name[pattern].empty?
+ return if parser == RDoc::Parser::Simple and ext_name !~ /txt|rdoc/
parser
+ rescue Errno::EACCES
end
##
- # Find the correct parser for a particular file name. Return a SimpleParser
- # for ones that we don't know
+ # Finds and instantiates the correct parser for the given +file_name+ and
+ # +content+.
- def self.for(top_level, file_name, body, options, stats)
+ def self.for top_level, file_name, content, options, stats
return if binary? file_name
- # If no extension, look for shebang
- if file_name !~ /\.\w+$/ && body =~ %r{\A#!(.+)} then
- shebang = $1
- case shebang
- when %r{env\s+ruby}, %r{/ruby}
- file_name = "dummy.rb"
+ parser = use_markup content
+
+ unless parser then
+ # If no extension, look for shebang
+ if file_name !~ /\.\w+$/ && content =~ %r{\A#!(.+)} then
+ shebang = $1
+ case shebang
+ when %r{env\s+ruby}, %r{/ruby}
+ file_name = "dummy.rb"
+ end
end
- end
- parser = can_parse file_name
+ parser = can_parse file_name
+ end
return unless parser
- parser.new top_level, file_name, body, options, stats
+ parser.new top_level, file_name, content, options, stats
end
##
@@ -194,13 +181,48 @@ class RDoc::Parser
end
##
- # Creates a new Parser storing +top_level+, +file_name+, +content+,
- # +options+ and +stats+ in instance variables.
+ # If there is a <tt>markup: parser_name</tt> comment at the front of the
+ # file, use it to determine the parser. For example:
+ #
+ # # markup: rdoc
+ # # Class comment can go here
+ #
+ # class C
+ # end
+ #
+ # The comment should appear as the first line of the +content+.
#
- # Usually invoked by +super+
+ # If the content contains a shebang or editor modeline the comment may
+ # appear on the second or third line.
+ #
+ # Any comment style may be used to hide the markup comment.
+
+ def self.use_markup content
+ markup = content.lines.first(3).grep(/markup:\s+(\w+)/) { $1 }.first
+
+ return unless markup
+
+ # TODO Ruby should be returned only when the filename is correct
+ return RDoc::Parser::Ruby if %w[tomdoc markdown].include? markup
- def initialize(top_level, file_name, content, options, stats)
+ markup = Regexp.escape markup
+
+ RDoc::Parser.parsers.find do |_, parser|
+ /^#{markup}$/i =~ parser.name.sub(/.*:/, '')
+ end.last
+ end
+
+ ##
+ # Creates a new Parser storing +top_level+, +file_name+, +content+,
+ # +options+ and +stats+ in instance variables. In +@preprocess+ an
+ # RDoc::Markup::PreProcess object is created which allows processing of
+ # directives.
+
+ def initialize top_level, file_name, content, options, stats
@top_level = top_level
+ @top_level.parser = self.class
+ @store = @top_level.store
+
@file_name = file_name
@content = content
@options = options
@@ -210,7 +232,15 @@ class RDoc::Parser
@preprocess.options = @options
end
+ autoload :RubyTools, 'rdoc/parser/ruby_tools'
+ autoload :Text, 'rdoc/parser/text'
+
end
+# simple must come first in order to show up last in the parsers list
require 'rdoc/parser/simple'
+require 'rdoc/parser/c'
+require 'rdoc/parser/markdown'
+require 'rdoc/parser/rd'
+require 'rdoc/parser/ruby'
diff --git a/lib/rdoc/parser/c.rb b/lib/rdoc/parser/c.rb
index 3da1820c50..31be27169c 100644
--- a/lib/rdoc/parser/c.rb
+++ b/lib/rdoc/parser/c.rb
@@ -1,6 +1,4 @@
-
-require 'rdoc/parser/ruby'
-require 'rdoc/known_classes'
+require 'tsort'
##
# RDoc::Parser::C attempts to parse C extension files. It looks for
@@ -58,6 +56,13 @@ require 'rdoc/known_classes'
# [Document-const: +name+]
# Documentation for the named +rb_define_const+.
#
+# Constant values can be supplied on the first line of the comment like so:
+#
+# /* 300: The highest possible score in bowling */
+# rb_define_const(cFoo, "PERFECT", INT2FIX(300));
+#
+# The value can contain internal colons so long as they are escaped with a \
+#
# [Document-global: +name+]
# Documentation for the named +rb_define_global_const+
#
@@ -122,27 +127,27 @@ class RDoc::Parser::C < RDoc::Parser
attr_accessor :content
+ ##
+ # Dependencies from a missing enclosing class to the classes in
+ # missing_dependencies that depend upon it.
+
+ attr_reader :enclosure_dependencies
##
- # Maps C variable names to names of ruby classes (andsingleton classes)
+ # Maps C variable names to names of ruby classes (and singleton classes)
attr_reader :known_classes
##
- # Maps C variable names to names of ruby singleton classes
+ # Classes found while parsing the C file that were not yet registered due to
+ # a missing enclosing class. These are processed by do_missing
- attr_reader :singleton_classes
+ attr_reader :missing_dependencies
##
- # Resets cross-file state. Call when parsing different projects that need
- # separate documentation.
-
- def self.reset
- @@enclosure_classes = {}
- @@known_bodies = {}
- end
+ # Maps C variable names to names of ruby singleton classes
- reset
+ attr_reader :singleton_classes
##
# Prepare to parse a C file
@@ -155,6 +160,38 @@ class RDoc::Parser::C < RDoc::Parser
@classes = {}
@singleton_classes = {}
@file_dir = File.dirname(@file_name)
+
+ # missing variable => [handle_class_module arguments]
+ @missing_dependencies = {}
+
+ # missing enclosure variable => [dependent handle_class_module arguments]
+ @enclosure_dependencies = Hash.new { |h, k| h[k] = [] }
+ @enclosure_dependencies.instance_variable_set :@missing_dependencies,
+ @missing_dependencies
+
+ @enclosure_dependencies.extend TSort
+
+ def @enclosure_dependencies.tsort_each_node &block
+ each_key(&block)
+ rescue TSort::Cyclic => e
+ cycle_vars = e.message.scan(/"(.*?)"/).flatten
+
+ cycle = cycle_vars.sort.map do |var_name|
+ delete var_name
+
+ var_name, type, mod_name, = @missing_dependencies[var_name]
+
+ "#{type} #{mod_name} (#{var_name})"
+ end.join ', '
+
+ warn "Unable to create #{cycle} due to a cyclic class or module creation"
+
+ retry
+ end
+
+ def @enclosure_dependencies.tsort_each_child node, &block
+ fetch(node, []).each(&block)
+ end
end
##
@@ -169,7 +206,7 @@ class RDoc::Parser::C < RDoc::Parser
class_name = @known_classes[var_name]
unless class_name then
- warn "Enclosing class/module %p for alias %s %s not known" % [
+ @options.warn "Enclosing class or module %p for alias %s %s is not known" % [
var_name, new_name, old_name]
next
end
@@ -180,7 +217,9 @@ class RDoc::Parser::C < RDoc::Parser
al.singleton = @singleton_classes.key? var_name
comment = find_alias_comment var_name, new_name, old_name
- comment = strip_stars comment
+
+ comment.normalize
+
al.comment = comment
al.record_location @top_level
@@ -214,62 +253,26 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # Scans #content for rb_define_module, rb_define_class, boot_defclass,
- # rb_define_module_under, rb_define_class_under and rb_singleton_class
-
- def do_classes
- @content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
- |var_name, class_name|
- handle_class_module(var_name, "module", class_name, nil, nil)
- end
-
- # The '.' lets us handle SWIG-generated files
- @content.scan(/([\w\.]+)\s* = \s*rb_define_class\s*
- \(
- \s*"(\w+)",
- \s*(\w+)\s*
- \)/mx) do |var_name, class_name, parent|
- handle_class_module(var_name, "class", class_name, parent, nil)
- end
+ # Scans #content for boot_defclass
+ def do_boot_defclass
@content.scan(/(\w+)\s*=\s*boot_defclass\s*\(\s*"(\w+?)",\s*(\w+?)\s*\)/) do
|var_name, class_name, parent|
parent = nil if parent == "0"
- handle_class_module(var_name, "class", class_name, parent, nil)
- end
-
- @content.scan(/(\w+)\s* = \s*rb_define_module_under\s*
- \(
- \s*(\w+),
- \s*"(\w+)"
- \s*\)/mx) do |var_name, in_module, class_name|
- handle_class_module(var_name, "module", class_name, nil, in_module)
+ handle_class_module(var_name, :class, class_name, parent, nil)
end
+ end
- @content.scan(/([\w\.]+)\s* = # var_name
- \s*rb_define_class_under\s*
- \(
- \s* (\w+), # under
- \s* "(\w+)", # class_name
- \s*
- (?:
- ([\w\*\s\(\)\.\->]+) | # parent_name
- rb_path2class\("([\w:]+)"\) # path
- )
- \s*
- \)
- /mx) do |var_name, under, class_name, parent_name, path|
- parent = path || parent_name
-
- handle_class_module var_name, 'class', class_name, parent, under
- end
+ ##
+ # Scans #content for rb_define_class, boot_defclass, rb_define_class_under
+ # and rb_singleton_class
- @content.scan(/([\w\.]+)\s* = \s*rb_singleton_class\s*
- \(
- \s*(\w+)
- \s*\)/mx) do |sclass_var, class_var|
- handle_singleton sclass_var, class_var
- end
+ def do_classes
+ do_boot_defclass
+ do_define_class
+ do_define_class_under
+ do_singleton_class
+ do_struct_define_without_accessor
end
##
@@ -300,8 +303,82 @@ class RDoc::Parser::C < RDoc::Parser
\)
\s*;%xm) do |consts|
const = consts.first
+
handle_constants 'const', 'mCurses', const, "UINT2NUM(#{const})"
end
+
+ @content.scan(%r%
+ \Wrb_file_const
+ \s*\(
+ \s*
+ "([^"]+)",
+ \s*
+ (.*?)
+ \s*
+ \)
+ \s*;%xm) do |name, value|
+ handle_constants 'const', 'rb_mFConst', name, value
+ end
+ end
+
+ ##
+ # Scans #content for rb_define_class
+
+ def do_define_class
+ # The '.' lets us handle SWIG-generated files
+ @content.scan(/([\w\.]+)\s* = \s*rb_define_class\s*
+ \(
+ \s*"(\w+)",
+ \s*(\w+)\s*
+ \)/mx) do |var_name, class_name, parent|
+ handle_class_module(var_name, :class, class_name, parent, nil)
+ end
+ end
+
+ ##
+ # Scans #content for rb_define_class_under
+
+ def do_define_class_under
+ @content.scan(/([\w\.]+)\s* = # var_name
+ \s*rb_define_class_under\s*
+ \(
+ \s* (\w+), # under
+ \s* "(\w+)", # class_name
+ \s*
+ (?:
+ ([\w\*\s\(\)\.\->]+) | # parent_name
+ rb_path2class\("([\w:]+)"\) # path
+ )
+ \s*
+ \)
+ /mx) do |var_name, under, class_name, parent_name, path|
+ parent = path || parent_name
+
+ handle_class_module var_name, :class, class_name, parent, under
+ end
+ end
+
+ ##
+ # Scans #content for rb_define_module
+
+ def do_define_module
+ @content.scan(/(\w+)\s* = \s*rb_define_module\s*\(\s*"(\w+)"\s*\)/mx) do
+ |var_name, class_name|
+ handle_class_module(var_name, :module, class_name, nil, nil)
+ end
+ end
+
+ ##
+ # Scans #content for rb_define_module_under
+
+ def do_define_module_under
+ @content.scan(/(\w+)\s* = \s*rb_define_module_under\s*
+ \(
+ \s*(\w+),
+ \s*"(\w+)"
+ \s*\)/mx) do |var_name, in_module, class_name|
+ handle_class_module(var_name, :module, class_name, nil, in_module)
+ end
end
##
@@ -311,7 +388,9 @@ class RDoc::Parser::C < RDoc::Parser
@content.scan(/rb_include_module\s*\(\s*(\w+?),\s*(\w+?)\s*\)/) do |c,m|
if cls = @classes[c]
m = @known_classes[m] || m
- incl = cls.add_include RDoc::Include.new(m, "")
+
+ comment = RDoc::Comment.new '', @top_level
+ incl = cls.add_include RDoc::Include.new(m, comment)
incl.record_location @top_level
end
end
@@ -367,6 +446,54 @@ class RDoc::Parser::C < RDoc::Parser
end
end
+ def do_missing
+ return if @missing_dependencies.empty?
+
+ @enclosure_dependencies.tsort.each do |in_module|
+ arguments = @missing_dependencies.delete in_module
+
+ next unless arguments # dependency on existing class
+
+ handle_class_module(*arguments)
+ end
+ end
+
+ ##
+ # Scans #content for rb_define_module and rb_define_module_under
+
+ def do_modules
+ do_define_module
+ do_define_module_under
+ end
+
+ ##
+ # Scans #content for rb_singleton_class
+
+ def do_singleton_class
+ @content.scan(/([\w\.]+)\s* = \s*rb_singleton_class\s*
+ \(
+ \s*(\w+)
+ \s*\)/mx) do |sclass_var, class_var|
+ handle_singleton sclass_var, class_var
+ end
+ end
+
+ ##
+ # Scans #content for struct_define_without_accessor
+
+ def do_struct_define_without_accessor
+ @content.scan(/([\w\.]+)\s* = \s*rb_struct_define_without_accessor\s*
+ \(
+ \s*"(\w+)", # Class name
+ \s*(\w+), # Parent class
+ \s*\w+, # Allocation function
+ (\s*"\w+",)* # Attributes
+ \s*NULL
+ \)/mx) do |var_name, class_name, parent|
+ handle_class_module(var_name, :class, class_name, parent, nil)
+ end
+ end
+
##
# Finds the comment for an alias on +class_name+ from +new_name+ to
# +old_name+
@@ -377,7 +504,7 @@ class RDoc::Parser::C < RDoc::Parser
\s*"#{Regexp.escape new_name}"\s*,
\s*"#{Regexp.escape old_name}"\s*\);%xm
- $1 || ''
+ RDoc::Comment.new($1 || '', @top_level)
end
##
@@ -398,22 +525,24 @@ class RDoc::Parser::C < RDoc::Parser
/.*?/m
end
- if @content =~ %r%((?>/\*.*?\*/\s+))
- rb_define_attr\((?:\s*#{var_name},)?\s*
- "#{attr_name}"\s*,
- #{rw}\)\s*;%xm then
- $1
- elsif @content =~ %r%((?>/\*.*?\*/\s+))
- rb_attr\(\s*#{var_name}\s*,
- \s*#{attr_name}\s*,
- #{rw},.*?\)\s*;%xm then
- $1
- elsif @content =~ %r%Document-attr:\s#{attr_name}\s*?\n
- ((?>.*?\*/))%xm then
- $1
- else
- ''
- end
+ comment = if @content =~ %r%((?>/\*.*?\*/\s+))
+ rb_define_attr\((?:\s*#{var_name},)?\s*
+ "#{attr_name}"\s*,
+ #{rw}\)\s*;%xm then
+ $1
+ elsif @content =~ %r%((?>/\*.*?\*/\s+))
+ rb_attr\(\s*#{var_name}\s*,
+ \s*#{attr_name}\s*,
+ #{rw},.*?\)\s*;%xm then
+ $1
+ elsif @content =~ %r%Document-attr:\s#{attr_name}\s*?\n
+ ((?>.*?\*/))%xm then
+ $1
+ else
+ ''
+ end
+
+ RDoc::Comment.new comment, @top_level
end
##
@@ -425,11 +554,11 @@ class RDoc::Parser::C < RDoc::Parser
((?:(?:static|SWIGINTERN)\s+)?
(?:intern\s+)?VALUE\s+#{meth_name}
\s*(\([^)]*\))([^;]|$))%xm then
- comment = $1
+ comment = RDoc::Comment.new $1, @top_level
body = $2
- offset = $~.offset(2).first
+ offset, = $~.offset(2)
- remove_private_comments comment if comment
+ comment.remove_private if comment
# try to find the whole body
body = $& if /#{Regexp.escape body}[^(]*?\{.*?^\}/m =~ file_content
@@ -443,6 +572,7 @@ class RDoc::Parser::C < RDoc::Parser
override_comment = find_override_comment class_name, meth_obj
comment = override_comment if override_comment
+ comment.normalize
find_modifiers comment, meth_obj if comment
#meth_obj.params = params
@@ -450,24 +580,26 @@ class RDoc::Parser::C < RDoc::Parser
tk = RDoc::RubyToken::Token.new nil, 1, 1
tk.set_text body
meth_obj.add_token tk
- meth_obj.comment = strip_stars comment
+ meth_obj.comment = comment
meth_obj.offset = offset
meth_obj.line = file_content[0, offset].count("\n") + 1
body
when %r%((?>/\*.*?\*/\s*))^\s*(\#\s*define\s+#{meth_name}\s+(\w+))%m then
- comment = $1
+ comment = RDoc::Comment.new $1, @top_level
body = $2
offset = $~.offset(2).first
find_body class_name, $3, meth_obj, file_content, true
+
+ comment.normalize
find_modifiers comment, meth_obj
meth_obj.start_collecting_tokens
tk = RDoc::RubyToken::Token.new nil, 1, 1
tk.set_text body
meth_obj.add_token tk
- meth_obj.comment = strip_stars(comment) + meth_obj.comment.to_s
+ meth_obj.comment = comment
meth_obj.offset = offset
meth_obj.line = file_content[0, offset].count("\n") + 1
@@ -480,18 +612,19 @@ class RDoc::Parser::C < RDoc::Parser
return body if body
- warn "No definition for #{meth_name}" if @options.verbosity > 1
+ @options.warn "No definition for #{meth_name}"
false
else # No body, but might still have an override comment
comment = find_override_comment class_name, meth_obj
if comment then
+ comment.normalize
find_modifiers comment, meth_obj
- meth_obj.comment = strip_stars comment
+ meth_obj.comment = comment
''
else
- warn "No definition for #{meth_name}" if @options.verbosity > 1
+ @options.warn "No definition for #{meth_name}"
false
end
end
@@ -540,7 +673,7 @@ class RDoc::Parser::C < RDoc::Parser
# */
# VALUE cFoo = rb_define_class("Foo", rb_cObject);
- def find_class_comment(class_name, class_mod)
+ def find_class_comment class_name, class_mod
comment = nil
if @content =~ %r%
@@ -551,17 +684,21 @@ class RDoc::Parser::C < RDoc::Parser
comment = $1.sub(%r%Document-(?:class|module):\s+#{class_name}%, '')
elsif @content =~ %r%Document-(?:class|module):\s+#{class_name}\s*?
(?:<\s+[:,\w]+)?\n((?>.*?\*/))%xm then
- comment = $1
- elsif @content =~ %r%((?>/\*.*?\*/\s+))
+ comment = "/*\n#{$1}"
+ elsif @content =~ %r%.*((?>/\*.*?\*/\s+))
([\w\.\s]+\s* = \s+)?rb_define_(class|module).*?"(#{class_name})"%xm then
comment = $1
+ elsif @content =~ %r%.*((?>/\*.*?\*/\s+))
+ ([\w\.\s]+\s* = \s+)?rb_define_(class|module)_under.*?"(#{class_name.split('::').last})"%xm then
+ comment = $1
+ else
+ comment = ''
end
- return unless comment
-
- comment = strip_stars comment
+ comment = RDoc::Comment.new comment, @top_level
+ comment.normalize
- comment = look_for_directives_in class_mod, comment
+ look_for_directives_in class_mod, comment
class_mod.add_comment comment, @top_level
end
@@ -571,79 +708,33 @@ class RDoc::Parser::C < RDoc::Parser
# comment or in the matching Document- section.
def find_const_comment(type, const_name, class_name = nil)
- if @content =~ %r%((?>^\s*/\*.*?\*/\s+))
- rb_define_#{type}\((?:\s*(\w+),)?\s*
- "#{const_name}"\s*,
- .*?\)\s*;%xmi then
- $1
- elsif class_name and
- @content =~ %r%Document-(?:const|global|variable):\s
- #{class_name}::#{const_name}
- \s*?\n((?>.*?\*/))%xm then
- $1
- elsif @content =~ %r%Document-(?:const|global|variable):\s#{const_name}
- \s*?\n((?>.*?\*/))%xm then
- $1
- else
- ''
- end
+ comment = if @content =~ %r%((?>^\s*/\*.*?\*/\s+))
+ rb_define_#{type}\((?:\s*(\w+),)?\s*
+ "#{const_name}"\s*,
+ .*?\)\s*;%xmi then
+ $1
+ elsif class_name and
+ @content =~ %r%Document-(?:const|global|variable):\s
+ #{class_name}::#{const_name}
+ \s*?\n((?>.*?\*/))%xm then
+ "/*\n#{$1}"
+ elsif @content =~ %r%Document-(?:const|global|variable):
+ \s#{const_name}
+ \s*?\n((?>.*?\*/))%xm then
+ "/*\n#{$1}"
+ else
+ ''
+ end
+
+ RDoc::Comment.new comment, @top_level
end
##
# Handles modifiers in +comment+ and updates +meth_obj+ as appropriate.
- #
- # If <tt>:nodoc:</tt> is found, documentation on +meth_obj+ is suppressed.
- #
- # If <tt>:yields:</tt> is followed by an argument list it is used for the
- # #block_params of +meth_obj+.
- #
- # If the comment block contains a <tt>call-seq:</tt> section like:
- #
- # call-seq:
- # ARGF.readlines(sep=$/) -> array
- # ARGF.readlines(limit) -> array
- # ARGF.readlines(sep, limit) -> array
- #
- # ARGF.to_a(sep=$/) -> array
- # ARGF.to_a(limit) -> array
- # ARGF.to_a(sep, limit) -> array
- #
- # it is used for the parameters of +meth_obj+.
def find_modifiers comment, meth_obj
- # we must handle situations like the above followed by an unindented first
- # comment. The difficulty is to make sure not to match lines starting
- # with ARGF at the same indent, but that are after the first description
- # paragraph.
-
- if comment =~ /call-seq:(.*?(?:\S|\*\/?).*?)^\s*(?:\*\/?)?\s*$/m then
- all_start, all_stop = $~.offset(0)
- seq_start, seq_stop = $~.offset(1)
-
- # we get the following lines that start with the leading word at the
- # same indent, even if they have blank lines before
- if $1 =~ /(^\s*\*?\s*\n)+^(\s*\*?\s*\w+)/m then
- leading = $2 # ' * ARGF' in the example above
- re = %r%
- \A(
- (^\s*\*?\s*\n)+
- (^#{Regexp.escape leading}.*?\n)+
- )+
- ^\s*\*?\s*$
- %xm
- if comment[seq_stop..-1] =~ re then
- all_stop = seq_stop + $~.offset(0).last
- seq_stop = seq_stop + $~.offset(1).last
- end
- end
-
- seq = comment[seq_start..seq_stop]
- seq.gsub!(/^(\s*\*?\s*?)(\S|\n)/m, '\2')
- comment.slice! all_start...all_stop
- meth_obj.call_seq = seq
- elsif comment.sub!(/\A\/\*\s*call-seq:(.*?)\*\/\Z/, '') then
- meth_obj.call_seq = $1.strip
- end
+ comment.normalize
+ comment.extract_call_seq meth_obj
look_for_directives_in meth_obj, comment
end
@@ -655,11 +746,18 @@ class RDoc::Parser::C < RDoc::Parser
name = Regexp.escape meth_obj.name
prefix = Regexp.escape meth_obj.name_prefix
- if @content =~ %r%Document-method:\s+#{class_name}#{prefix}#{name}\s*?\n((?>.*?\*/))%m then
- $1
- elsif @content =~ %r%Document-method:\s#{name}\s*?\n((?>.*?\*/))%m then
- $1
- end
+ comment = if @content =~ %r%Document-method:
+ \s+#{class_name}#{prefix}#{name}
+ \s*?\n((?>.*?\*/))%xm then
+ "/*#{$1}"
+ elsif @content =~ %r%Document-method:
+ \s#{name}\s*?\n((?>.*?\*/))%xm then
+ "/*#{$1}"
+ end
+
+ return unless comment
+
+ RDoc::Comment.new comment, @top_level
end
##
@@ -680,7 +778,7 @@ class RDoc::Parser::C < RDoc::Parser
return unless class_obj
comment = find_attr_comment var_name, attr_name
- comment = strip_stars comment
+ comment.normalize
name = attr_name.gsub(/rb_intern\("([^"]+)"\)/, '\1')
@@ -699,23 +797,26 @@ class RDoc::Parser::C < RDoc::Parser
parent_name = @known_classes[parent] || parent
if in_module then
- enclosure = @classes[in_module] || @@enclosure_classes[in_module]
+ enclosure = @classes[in_module] || @store.c_enclosure_classes[in_module]
if enclosure.nil? and enclosure = @known_classes[in_module] then
- enc_type = /^rb_m/ =~ in_module ? "module" : "class"
+ enc_type = /^rb_m/ =~ in_module ? :module : :class
handle_class_module in_module, enc_type, enclosure, nil, nil
enclosure = @classes[in_module]
end
unless enclosure then
- warn "Enclosing class/module '#{in_module}' for #{type} #{class_name} not known"
+ @enclosure_dependencies[in_module] << var_name
+ @missing_dependencies[var_name] =
+ [var_name, type, class_name, parent, in_module]
+
return
end
else
enclosure = @top_level
end
- if type == "class" then
+ if type == :class then
full_name = if RDoc::ClassModule === enclosure then
enclosure.full_name + "::#{class_name}"
else
@@ -743,7 +844,7 @@ class RDoc::Parser::C < RDoc::Parser
end
@classes[var_name] = cm
- @@enclosure_classes[var_name] = cm
+ @store.c_enclosure_classes[var_name] = cm
@known_classes[var_name] = cm.full_name
end
@@ -765,25 +866,20 @@ class RDoc::Parser::C < RDoc::Parser
class_obj = find_class var_name, class_name
unless class_obj then
- warn "Enclosing class/module #{const_name.inspect} not known"
+ @options.warn 'Enclosing class or module %p is not known' % [const_name]
return
end
comment = find_const_comment type, const_name, class_name
- comment = strip_stars comment
- comment = normalize_comment comment
+ comment.normalize
# In the case of rb_define_const, the definition and comment are in
# "/* definition: comment */" form. The literal ':' and '\' characters
# can be escaped with a backslash.
if type.downcase == 'const' then
- elements = comment.split ':'
-
- if elements.nil? or elements.empty? then
- con = RDoc::Constant.new const_name, definition, comment
- else
- new_definition = elements[0..-2].join(':')
+ no_match, new_definition, new_comment = comment.text.split(/(\A.*):/)
+ if no_match and no_match.empty? then
if new_definition.empty? then # Default to literal C definition
new_definition = definition
else
@@ -793,13 +889,13 @@ class RDoc::Parser::C < RDoc::Parser
new_definition.sub!(/\A(\s+)/, '')
- new_comment = if $1.nil? then
- elements.last.lstrip
- else
- "#{$1}#{elements.last.lstrip}"
- end
+ new_comment = "#{$1}#{new_comment.lstrip}"
+
+ new_comment = RDoc::Comment.new new_comment, @top_level
con = RDoc::Constant.new const_name, new_definition, new_comment
+ else
+ con = RDoc::Constant.new const_name, definition, comment
end
else
con = RDoc::Constant.new const_name, definition, comment
@@ -849,9 +945,9 @@ class RDoc::Parser::C < RDoc::Parser
file_name = File.join @file_dir, source_file
if File.exist? file_name then
- file_content = (@@known_bodies[file_name] ||= File.read(file_name))
+ file_content = File.read file_name
else
- warn "unknown source #{source_file} for #{meth_name} in #{@file_name}"
+ @options.warn "unknown source #{source_file} for #{meth_name} in #{@file_name}"
end
else
file_content = @content
@@ -1021,20 +1117,16 @@ class RDoc::Parser::C < RDoc::Parser
end
##
- # Removes private comments from +comment+
-
- def remove_private_comments(comment)
- comment.gsub!(/\/?\*--\n(.*?)\/?\*\+\+/m, '')
- comment.sub!(/\/?\*--\n.*/m, '')
- end
-
- ##
# Extracts the classes, modules, methods, attributes, constants and aliases
# from a C file and returns an RDoc::TopLevel for this file
def scan
remove_commented_out_lines
+
+ do_modules
do_classes
+ do_missing
+
do_constants
do_methods
do_includes
diff --git a/lib/rdoc/parser/markdown.rb b/lib/rdoc/parser/markdown.rb
new file mode 100644
index 0000000000..6fd88cf614
--- /dev/null
+++ b/lib/rdoc/parser/markdown.rb
@@ -0,0 +1,23 @@
+##
+# Parse a Markdown format file. The parsed RDoc::Markup::Document is attached
+# as a file comment.
+
+class RDoc::Parser::Markdown < RDoc::Parser
+
+ include RDoc::Parser::Text
+
+ parse_files_matching(/\.(md|markdown)(?:\.[^.]+)?$/)
+
+ ##
+ # Creates an Markdown-format TopLevel for the given file.
+
+ def scan
+ comment = RDoc::Comment.new @content, @top_level
+ comment.format = 'markdown'
+
+ @top_level.comment = comment
+ end
+
+end
+
+
diff --git a/lib/rdoc/parser/rd.rb b/lib/rdoc/parser/rd.rb
new file mode 100644
index 0000000000..09069ae297
--- /dev/null
+++ b/lib/rdoc/parser/rd.rb
@@ -0,0 +1,22 @@
+##
+# Parse a RD format file. The parsed RDoc::Markup::Document is attached as a
+# file comment.
+
+class RDoc::Parser::RD < RDoc::Parser
+
+ include RDoc::Parser::Text
+
+ parse_files_matching(/\.rd(?:\.[^.]+)?$/)
+
+ ##
+ # Creates an rd-format TopLevel for the given file.
+
+ def scan
+ comment = RDoc::Comment.new @content, @top_level
+ comment.format = 'rd'
+
+ @top_level.comment = comment
+ end
+
+end
+
diff --git a/lib/rdoc/parser/ruby.rb b/lib/rdoc/parser/ruby.rb
index c9a12a8fe8..0b207fae3b 100644
--- a/lib/rdoc/parser/ruby.rb
+++ b/lib/rdoc/parser/ruby.rb
@@ -7,15 +7,6 @@
# by Keiju ISHITSUKA (Nippon Rational Inc.)
#
-require 'rdoc/ruby_token'
-require 'rdoc/ruby_lex'
-
-require 'rdoc/code_objects'
-require 'rdoc/token_stream'
-require 'rdoc/markup/pre_process'
-require 'rdoc/parser'
-require 'rdoc/parser/ruby_tools'
-
$TOKEN_DEBUG ||= nil
##
@@ -103,7 +94,7 @@ $TOKEN_DEBUG ||= nil
# You can force the name of a method using the :method: directive:
#
# ##
-# # :method: woo_hoo!
+# # :method: some_method!
#
# By default, meta-methods are instance methods. To indicate that a method is
# a singleton method instead use the :singleton-method: directive:
@@ -114,7 +105,7 @@ $TOKEN_DEBUG ||= nil
# You can also use the :singleton-method: directive with a name:
#
# ##
-# # :singleton-method: woo_hoo!
+# # :singleton-method: some_method!
#
# Additionally you can mark a method as an attribute by
# using :attr:, :attr_reader:, :attr_writer: or :attr_accessor:. Just like
@@ -173,6 +164,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
@scanner = RDoc::RubyLex.new content, @options
@scanner.exception_on_syntax_error = false
@prev_seek = nil
+ @markup = @options.markup
@encoding = nil
@encoding = @options.encoding if Object.const_defined? :Encoding
@@ -213,7 +205,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
unget_tk tk
- comment
+ new_comment comment
end
##
@@ -226,22 +218,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
##
- # Look for a 'call-seq' in the comment, and override the normal parameter
- # stuff
- #--
- # TODO handle undent
-
- def extract_call_seq(comment, meth)
- if comment.sub!(/:?call-seq:(.*?)(^\s*#?\s*$|\z)/m, '') then
- seq = $1
- seq.gsub!(/^\s*\#\s*/, '')
- meth.call_seq = seq
- end
-
- meth
- end
-
- ##
# Looks for a true or false token. Returns false if TkFALSE or TkNIL are
# found.
@@ -264,7 +240,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
# with :: separated named) and return the ultimate name, the associated
# container, and the given name (with the ::).
- def get_class_or_module(container)
+ def get_class_or_module container
skip_tkspace
name_t = get_tk
given_name = ''
@@ -283,14 +259,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
while TkCOLON2 === peek_tk do
prev_container = container
container = container.find_module_named name_t.name
- unless container then
- container = prev_container.add_module RDoc::NormalModule, name_t.name
- end
+ container ||= prev_container.add_module RDoc::NormalModule, name_t.name
+
+ container.ignore unless prev_container.document_children
+
get_tk
+ skip_tkspace false
name_t = get_tk
given_name << '::' << name_t.name
end
+
skip_tkspace false
+
return [container, name_t, given_name]
end
@@ -299,9 +279,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
def get_class_specification
tk = get_tk
- return "self" if TkSELF === tk
+ return 'self' if TkSELF === tk
+ return '' if TkGVAR === tk
- res = ""
+ res = ''
while TkCOLON2 === tk or TkCOLON3 === tk or TkCONSTANT === tk do
res += tk.name
tk = get_tk
@@ -412,8 +393,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
'attr', 'attr_accessor', 'attr_reader', 'attr_writer' then
false # handled elsewhere
when 'section' then
- context.set_current_section param, comment
- comment.replace ''
+ context.set_current_section param, comment.dup
+ comment.text = ''
break
end
end
@@ -433,6 +414,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
##
+ # Creates a comment with the correct format
+
+ def new_comment comment
+ c = RDoc::Comment.new comment, @top_level
+ c.format = @markup
+ c
+ end
+
+ ##
# Creates an RDoc::Attr for the name following +tk+, setting the comment to
# +comment+.
@@ -590,7 +580,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
##
# Parses a class in +context+ with +comment+
- def parse_class(container, single, tk, comment)
+ def parse_class container, single, tk, comment
offset = tk.seek
line_no = tk.line_no
@@ -602,6 +592,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
name = name_t.name
superclass = '::Object'
+ if given_name =~ /^::/ then
+ declaration_context = @top_level
+ given_name = $'
+ end
+
if TkLT === peek_tk then
get_tk
skip_tkspace
@@ -626,17 +621,25 @@ class RDoc::Parser::Ruby < RDoc::Parser
parse_statements cls
when TkLSHFT
case name = get_class_specification
- when "self", container.name
+ when 'self', container.name
parse_statements container, SINGLE
else
- other = RDoc::TopLevel.find_class_named name
+ other = @store.find_class_named name
unless other then
+ if name =~ /^::/ then
+ name = $'
+ container = @top_level
+ end
+
other = container.add_module RDoc::NormalModule, name
other.record_location @top_level
other.offset = offset
other.line = line_no
+ # class << $gvar
+ other.ignore if name.empty?
+
other.add_comment comment, @top_level
end
@@ -678,6 +681,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
return false
end
+ value = ''
+ con = RDoc::Constant.new name, value, comment
nest = 0
get_tkread
@@ -705,13 +710,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
(@scanner.lex_state == EXPR_END || !@scanner.continue) then
unget_tk tk
break
+ else
+ unget_tk tk
+ read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
end
when TkCONSTANT then
rhs_name << tk.name
if nest <= 0 and TkNL === peek_tk then
mod = if rhs_name =~ /^::/ then
- RDoc::TopLevel.find_class_or_module rhs_name
+ @store.find_class_or_module rhs_name
else
container.find_module_named rhs_name
end
@@ -736,14 +744,15 @@ class RDoc::Parser::Ruby < RDoc::Parser
res = get_tkread.gsub(/^[ \t]+/, '').strip
res = "" if res == ";"
- con = RDoc::Constant.new name, res, comment
+ value.replace res
con.record_location @top_level
con.offset = offset
con.line = line_no
read_documentation_modifiers con, RDoc::CONSTANT_MODIFIERS
@stats.add_constant con
- container.add_constant con
+ con = container.add_constant con
+
true
end
@@ -751,15 +760,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
# Generates an RDoc::Method or RDoc::Attr from +comment+ by looking for
# :method: or :attr: directives in +comment+.
- def parse_comment(container, tk, comment)
+ def parse_comment container, tk, comment
+ return parse_comment_tomdoc container, tk, comment if @markup == 'tomdoc'
column = tk.char_no
offset = tk.seek
line_no = tk.line_no
- singleton = !!comment.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
+ text = comment.text
+
+ singleton = !!text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
# REFACTOR
- if comment.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
+ if text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
name = $1 unless $1.empty?
meth = RDoc::GhostMethod.new get_tkread, name
@@ -769,16 +781,17 @@ class RDoc::Parser::Ruby < RDoc::Parser
meth.line = line_no
meth.start_collecting_tokens
- indent = TkSPACE.new nil, 1, 1
+ indent = TkSPACE.new 0, 1, 1
indent.set_text " " * column
- position_comment = TkCOMMENT.new nil, line_no, 1
+ position_comment = TkCOMMENT.new 0, line_no, 1
position_comment.set_text "# File #{@top_level.absolute_name}, line #{line_no}"
meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
meth.params = ''
- extract_call_seq comment, meth
+ comment.normalize
+ comment.extract_call_seq meth
return unless meth.name
@@ -787,7 +800,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
meth.comment = comment
@stats.add_method meth
- elsif comment.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
+ elsif text.sub!(/# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
rw = case $1
when 'attr_reader' then 'R'
when 'attr_writer' then 'W'
@@ -810,6 +823,43 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
##
+ # Creates an RDoc::Method on +container+ from +comment+ if there is a
+ # Signature section in the comment
+
+ def parse_comment_tomdoc container, tk, comment
+ return unless signature = RDoc::TomDoc.signature(comment)
+ offset = tk.seek
+ line_no = tk.line_no
+
+ name, = signature.split %r%[ \(]%, 2
+
+ meth = RDoc::GhostMethod.new get_tkread, name
+ meth.record_location @top_level
+ meth.offset = offset
+ meth.line = line_no
+
+ meth.start_collecting_tokens
+ indent = TkSPACE.new 0, 1, 1
+ indent.set_text " " * offset
+
+ position_comment = TkCOMMENT.new 0, line_no, 1
+ position_comment.set_text "# File #{@top_level.absolute_name}, line #{line_no}"
+ meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
+
+ meth.call_seq = signature
+
+ comment.normalize
+
+ return unless meth.name
+
+ container.add_method meth
+
+ meth.comment = comment
+
+ @stats.add_method meth
+ end
+
+ ##
# Parses an +include+ in +context+ with +comment+
def parse_include context, comment
@@ -830,6 +880,26 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
##
+ # Parses an +extend+ in +context+ with +comment+
+
+ def parse_extend context, comment
+ loop do
+ skip_tkspace_comment
+
+ name = get_constant_with_optional_parens
+
+ unless name.empty? then
+ incl = context.add_extend RDoc::Extend.new(name, comment)
+ incl.record_location @top_level
+ end
+
+ return unless TkCOMMA === peek_tk
+
+ get_tk
+ end
+ end
+
+ ##
# Parses a meta-programmed attribute and creates an RDoc::Attr.
#
# To create foo and bar attributes on class C with comment "My attributes":
@@ -867,7 +937,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
tmp = RDoc::CodeObject.new
read_documentation_modifiers tmp, RDoc::ATTR_MODIFIERS
- if comment.sub!(/^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
+ if comment.text.sub!(/^# +:?(attr(_reader|_writer|_accessor)?): *(\S*).*?\n/i, '') then
rw = case $1
when 'attr_reader' then 'R'
when 'attr_writer' then 'W'
@@ -892,6 +962,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
@stats.add_attribute att
end
end
+
+ att
end
##
@@ -908,9 +980,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
skip_tkspace false
- singleton = !!comment.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
+ singleton = !!comment.text.sub!(/(^# +:?)(singleton-)(method:)/, '\1\3')
- if comment.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
+ if comment.text.sub!(/^# +:?method: *(\S*).*?\n/i, '') then
name = $1 unless $1.empty?
end
@@ -939,10 +1011,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
remove_token_listener self
meth.start_collecting_tokens
- indent = TkSPACE.new nil, 1, 1
+ indent = TkSPACE.new 0, 1, 1
indent.set_text " " * column
- position_comment = TkCOMMENT.new nil, line_no, 1
+ position_comment = TkCOMMENT.new 0, line_no, 1
position_comment.value = "# File #{@top_level.absolute_name}, line #{line_no}"
meth.add_tokens [position_comment, NEWLINE_TOKEN, indent]
meth.add_tokens @token_stream
@@ -950,7 +1022,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
token_listener meth do
meth.params = ''
- extract_call_seq comment, meth
+ comment.normalize
+ comment.extract_call_seq meth
container.add_method meth
@@ -965,7 +1038,6 @@ class RDoc::Parser::Ruby < RDoc::Parser
when TkSPACE then
# expression continues
when TkDO then
- unget_tk tk
parse_statements container, single, meth
break
else
@@ -977,6 +1049,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
meth.comment = comment
@stats.add_method meth
+
+ meth
end
##
@@ -1002,15 +1076,23 @@ class RDoc::Parser::Ruby < RDoc::Parser
meth = nil
added_container = false
- dot = get_tk
- if TkDOT === dot or TkCOLON2 === dot then
+ case dot = get_tk
+ when TkDOT, TkCOLON2 then
@scanner.instance_eval do @lex_state = EXPR_FNAME end
skip_tkspace
name_t2 = get_tk
case name_t
when TkSELF, TkMOD then
- name = name_t2.name
+ name = case name_t2
+ # NOTE: work around '[' being consumed early and not being
+ # re-tokenized as a TkAREF
+ when TkfLBRACK then
+ get_tk
+ '[]'
+ else
+ name_t2.name
+ end
when TkCONSTANT then
name = name_t2.name
prev_container = container
@@ -1039,11 +1121,12 @@ class RDoc::Parser::Ruby < RDoc::Parser
when TkIDENTIFIER, TkIVAR, TkGVAR then
dummy = RDoc::Context.new
dummy.parent = container
+ dummy.store = container.store
skip_method dummy
return
when TkTRUE, TkFALSE, TkNIL then
klass_name = "#{name_t.name.capitalize}Class"
- container = RDoc::TopLevel.find_class_named klass_name
+ container = @store.find_class_named klass_name
container ||= @top_level.add_class RDoc::NormalClass, klass_name
name = name_t2.name
@@ -1084,10 +1167,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
meth.line = line_no
meth.start_collecting_tokens
- indent = TkSPACE.new nil, 1, 1
+ indent = TkSPACE.new 0, 1, 1
indent.set_text " " * column
- token = TkCOMMENT.new nil, line_no, 1
+ token = TkCOMMENT.new 0, line_no, 1
token.set_text "# File #{@top_level.absolute_name}, line #{line_no}"
meth.add_tokens [token, NEWLINE_TOKEN, indent]
meth.add_tokens @token_stream
@@ -1118,7 +1201,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
parse_statements container, single, meth
end
- extract_call_seq comment, meth
+ comment.normalize
+ comment.extract_call_seq meth
meth.comment = comment
@@ -1212,17 +1296,18 @@ class RDoc::Parser::Ruby < RDoc::Parser
##
# Parses an RDoc::NormalModule in +container+ with +comment+
- def parse_module(container, single, tk, comment)
+ def parse_module container, single, tk, comment
container, name_t, = get_class_or_module container
name = name_t.name
mod = container.add_module RDoc::NormalModule, name
+ mod.ignore unless container.document_children
mod.record_location @top_level
read_documentation_modifiers mod, RDoc::CLASS_MODIFIERS
mod.add_comment comment, @top_level
- parse_statements(mod)
+ parse_statements mod
@top_level.add_to_classes_or_modules mod
@stats.add_module mod
@@ -1253,7 +1338,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
# The core of the ruby parser.
def parse_statements(container, single = NORMAL, current_method = nil,
- comment = '')
+ comment = new_comment(''))
+ raise 'no' unless RDoc::Comment === comment
comment.force_encoding @encoding if @encoding
nest = 1
@@ -1293,6 +1379,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
end
+ comment = new_comment comment
+
unless comment.empty? then
look_for_directives_in container, comment
@@ -1306,18 +1394,14 @@ class RDoc::Parser::Ruby < RDoc::Parser
non_comment_seen = true
end
- unget_tk tk # TODO peek instead of get then unget
+ unget_tk tk
keep_comment = true
when TkCLASS then
parse_class container, single, tk, comment
when TkMODULE then
- if container.document_children then
- parse_module container, single, tk, comment
- else
- nest += 1
- end
+ parse_module container, single, tk, comment
when TkDEF then
parse_method container, single, tk, comment
@@ -1354,6 +1438,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
when TkCASE, TkDO, TkIF, TkUNLESS, TkBEGIN then
nest += 1
+ when TkSUPER then
+ current_method.calls_super = true if current_method
+
when TkIDENTIFIER then
if nest == 1 and current_method.nil? then
case tk.name
@@ -1370,12 +1457,16 @@ class RDoc::Parser::Ruby < RDoc::Parser
when 'require', 'include' then
# ignore
else
- if comment =~ /\A#\#$/ then
- case comment
+ if comment.text =~ /\A#\#$/ then
+ case comment.text
when /^# +:?attr(_reader|_writer|_accessor)?:/ then
parse_meta_attr container, single, tk, comment
else
- parse_meta_method container, single, tk, comment
+ method = parse_meta_method container, single, tk, comment
+ method.params = container.params if
+ container.params
+ method.block_params = container.block_params if
+ container.block_params
end
end
end
@@ -1386,6 +1477,8 @@ class RDoc::Parser::Ruby < RDoc::Parser
parse_require container, comment
when "include" then
parse_include container, comment
+ when "extend" then
+ parse_extend container, comment
end
when TkEND then
@@ -1410,8 +1503,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
unless keep_comment then
- comment = ''
+ comment = new_comment ''
comment.force_encoding @encoding if @encoding
+ container.params = nil
+ container.block_params = nil
end
begin
@@ -1419,6 +1514,9 @@ class RDoc::Parser::Ruby < RDoc::Parser
skip_tkspace false
end while peek_tk == TkNL
end
+
+ container.params = nil
+ container.block_params = nil
end
##
@@ -1497,8 +1595,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
def parse_top_level_statements container
comment = collect_first_comment
+
look_for_directives_in container, comment
+ @markup = comment.format
+
# HACK move if to RDoc::Context#comment=
container.comment = comment if container.document_self unless comment.empty?
@@ -1604,28 +1705,44 @@ class RDoc::Parser::Ruby < RDoc::Parser
#
# class MyClass # :nodoc:
#
- # We return the directive name and any parameters as a two element array
+ # We return the directive name and any parameters as a two element array if
+ # the name is in +allowed+. A directive can be found anywhere up to the end
+ # of the current line.
def read_directive allowed
- tk = get_tk
+ tokens = []
- if TkCOMMENT === tk then
- return unless tk.text =~ /\s*:?(\w+):\s*(.*)/
+ while tk = get_tk do
+ tokens << tk
- directive = $1.downcase
+ case tk
+ when TkNL then return
+ when TkCOMMENT then
+ return unless tk.text =~ /\s*:?([\w-]+):\s*(.*)/
- return [directive, $2] if allowed.include? directive
- else
- unget_tk tk
+ directive = $1.downcase
+
+ return [directive, $2] if allowed.include? directive
+
+ return
+ end
+ end
+ ensure
+ unless tokens.length == 1 and TkCOMMENT === tokens.first then
+ tokens.reverse_each do |token|
+ unget_tk token
+ end
end
end
##
- # Handles the directive for +context+ if the directive is listed in +allow+.
- # This method is called for directives following a definition.
+ # Handles directives following the definition for +context+ (any
+ # RDoc::CodeObject) if the directives are +allowed+ at this point.
+ #
+ # See also RDoc::Markup::PreProcess#handle_directive
- def read_documentation_modifiers context, allow
- directive, value = read_directive allow
+ def read_documentation_modifiers context, allowed
+ directive, value = read_directive allowed
return unless directive
@@ -1640,13 +1757,11 @@ class RDoc::Parser::Ruby < RDoc::Parser
##
# Removes private comments from +comment+
+ #--
+ # TODO remove
- def remove_private_comments(comment)
- empty = ''
- empty.force_encoding comment.encoding if Object.const_defined? :Encoding
-
- comment.gsub!(/^#--.*?^#\+\+\n?/m, empty)
- comment.sub!(/^#--.*/m, '')
+ def remove_private_comments comment
+ comment.remove_private
end
##
@@ -1658,6 +1773,7 @@ class RDoc::Parser::Ruby < RDoc::Parser
catch :eof do
begin
parse_top_level_statements @top_level
+
rescue StandardError => e
bytes = ''
@@ -1770,12 +1886,10 @@ class RDoc::Parser::Ruby < RDoc::Parser
end
##
- # Prints +msg+ to +$stderr+ unless we're being quiet
+ # Prints +message+ to +$stderr+ unless we're being quiet
- def warn(msg)
- return if @options.quiet
- msg = make_message msg
- $stderr.puts msg
+ def warn message
+ @options.warn make_message message
end
end
diff --git a/lib/rdoc/parser/ruby_tools.rb b/lib/rdoc/parser/ruby_tools.rb
index 678f721624..654431ea30 100644
--- a/lib/rdoc/parser/ruby_tools.rb
+++ b/lib/rdoc/parser/ruby_tools.rb
@@ -43,8 +43,7 @@ module RDoc::Parser::RubyTools
tk = Token(TkSYMBOL).set_text(":" + tk1.text)
end
- # remove the identifier we just read (we're about to replace it with a
- # symbol)
+ # remove the identifier we just read to replace it with a symbol
@token_listeners.each do |obj|
obj.pop_token
end if @token_listeners
@@ -70,7 +69,13 @@ module RDoc::Parser::RubyTools
loop do
tk = get_tk
- case tk when *tokens then unget_tk tk; break end
+
+ case tk
+ when *tokens then
+ unget_tk tk
+ break
+ end
+
read << tk
end
diff --git a/lib/rdoc/parser/simple.rb b/lib/rdoc/parser/simple.rb
index 1e82eb5097..65cfc1b2e7 100644
--- a/lib/rdoc/parser/simple.rb
+++ b/lib/rdoc/parser/simple.rb
@@ -4,6 +4,8 @@
class RDoc::Parser::Simple < RDoc::Parser
+ include RDoc::Parser::Text
+
parse_files_matching(//)
attr_reader :content # :nodoc:
@@ -24,26 +26,36 @@ class RDoc::Parser::Simple < RDoc::Parser
def scan
comment = remove_coding_comment @content
- comment = remove_private_comments comment
+ comment = remove_private_comment comment
+
+ comment = RDoc::Comment.new comment, @top_level
@top_level.comment = comment
- @top_level.parser = self.class
@top_level
end
##
- # Removes comments wrapped in <tt>--/++</tt>
-
- def remove_private_comments text
- text.gsub(/^--\n.*?^\+\+/m, '').sub(/^--\n.*/m, '')
- end
-
- ##
# Removes the encoding magic comment from +text+
def remove_coding_comment text
text.sub(/\A# .*coding[=:].*$/, '')
end
+ ##
+ # Removes private comments.
+ #
+ # Unlike RDoc::Comment#remove_private this implementation only looks for two
+ # dashes at the beginning of the line. Three or more dashes are considered
+ # to be a rule and ignored.
+
+ def remove_private_comment comment
+ # Workaround for gsub encoding for Ruby 1.9.2 and earlier
+ empty = ''
+ empty.force_encoding comment.encoding if Object.const_defined? :Encoding
+
+ comment = comment.gsub(%r%^--\n.*?^\+\+\n?%m, empty)
+ comment.sub(%r%^--\n.*%m, empty)
+ end
+
end
diff --git a/lib/rdoc/parser/text.rb b/lib/rdoc/parser/text.rb
new file mode 100644
index 0000000000..f973313551
--- /dev/null
+++ b/lib/rdoc/parser/text.rb
@@ -0,0 +1,11 @@
+##
+# Indicates this parser is text and doesn't contain code constructs.
+#
+# Include this module in a RDoc::Parser subclass to make it show up as a file,
+# not as part of a class or module.
+#--
+# This is not named File to avoid overriding ::File
+
+module RDoc::Parser::Text
+end
+
diff --git a/lib/rdoc/rd.rb b/lib/rdoc/rd.rb
new file mode 100644
index 0000000000..28c5d286e0
--- /dev/null
+++ b/lib/rdoc/rd.rb
@@ -0,0 +1,99 @@
+##
+# RDoc::RD implements the RD format from the rdtool gem.
+#
+# To choose RD as your only default format see
+# RDoc::Options@Saved+Options for instructions on setting up a
+# <code>.doc_options</code> file to store your project default.
+#
+# == LICENSE
+#
+# The grammar that produces RDoc::RD::BlockParser and RDoc::RD::InlineParser
+# is included in RDoc under the Ruby License.
+#
+# You can find the original source for rdtool at
+# https://github.com/uwabami/rdtool/
+#
+# You can use, re-distribute or change these files under Ruby's License or GPL.
+#
+# 1. You may make and give away verbatim copies of the source form of the
+# software without restriction, provided that you duplicate all of the
+# original copyright notices and associated disclaimers.
+#
+# 2. You may modify your copy of the software in any way, provided that
+# you do at least ONE of the following:
+#
+# a. place your modifications in the Public Domain or otherwise
+# make them Freely Available, such as by posting said
+# modifications to Usenet or an equivalent medium, or by allowing
+# the author to include your modifications in the software.
+#
+# b. use the modified software only within your corporation or
+# organization.
+#
+# c. give non-standard binaries non-standard names, with
+# instructions on where to get the original software distribution.
+#
+# d. make other distribution arrangements with the author.
+#
+# 3. You may distribute the software in object code or binary form,
+# provided that you do at least ONE of the following:
+#
+# a. distribute the binaries and library files of the software,
+# together with instructions (in the manual page or equivalent)
+# on where to get the original distribution.
+#
+# b. accompany the distribution with the machine-readable source of
+# the software.
+#
+# c. give non-standard binaries non-standard names, with
+# instructions on where to get the original software distribution.
+#
+# d. make other distribution arrangements with the author.
+#
+# 4. You may modify and include the part of the software into any other
+# software (possibly commercial). But some files in the distribution
+# are not written by the author, so that they are not under these terms.
+#
+# For the list of those files and their copying conditions, see the
+# file LEGAL.
+#
+# 5. The scripts and library files supplied as input to or produced as
+# output from the software do not automatically fall under the
+# copyright of the software, but belong to whomever generated them,
+# and may be sold commercially, and may be aggregated with this
+# software.
+#
+# 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+# PURPOSE.
+
+class RDoc::RD
+
+ ##
+ # Parses +rd+ source and returns an RDoc::Markup::Document. If the
+ # <tt>=begin</tt> or <tt>=end</tt> lines are missing they will be added.
+
+ def self.parse rd
+ rd = rd.lines.to_a
+
+ if rd.find { |i| /\S/ === i } and !rd.find{|i| /^=begin\b/ === i } then
+ rd.unshift("=begin\n").push("=end\n")
+ end
+
+ parser = RDoc::RD::BlockParser.new
+ document = parser.parse rd
+
+ # isn't this always true?
+ document.parts.shift if RDoc::Markup::BlankLine === document.parts.first
+ document.parts.pop if RDoc::Markup::BlankLine === document.parts.last
+
+ document
+ end
+
+ autoload :BlockParser, 'rdoc/rd/block_parser'
+ autoload :InlineParser, 'rdoc/rd/inline_parser'
+ autoload :Inline, 'rdoc/rd/inline'
+
+end
+
diff --git a/lib/rdoc/rd/block_parser.rb b/lib/rdoc/rd/block_parser.rb
new file mode 100644
index 0000000000..e74f3f2901
--- /dev/null
+++ b/lib/rdoc/rd/block_parser.rb
@@ -0,0 +1,1054 @@
+#
+# DO NOT MODIFY!!!!
+# This file is automatically generated by Racc 1.4.9
+# from Racc grammer file "".
+#
+
+require 'racc/parser.rb'
+
+class RDoc::RD
+
+##
+# RD format parser for headings, paragraphs, lists, verbatim sections that
+# exist as blocks.
+
+class BlockParser < Racc::Parser
+
+
+# :stopdoc:
+
+TMPFILE = ["rdtmp", $$, 0]
+
+MARK_TO_LEVEL = {
+ '=' => 1,
+ '==' => 2,
+ '===' => 3,
+ '====' => 4,
+ '+' => 5,
+ '++' => 6,
+}
+
+# :startdoc:
+
+##
+# Footnotes for this document
+
+attr_reader :footnotes
+
+##
+# Labels for items in this document
+
+attr_reader :labels
+
+##
+# Path to find included files in
+
+attr_accessor :include_path
+
+##
+# Creates a new RDoc::RD::BlockParser. Use #parse to parse an rd-format
+# document.
+
+def initialize
+ @inline_parser = RDoc::RD::InlineParser.new self
+ @include_path = []
+
+ # for testing
+ @footnotes = []
+ @labels = {}
+end
+
+##
+# Parses +src+ and returns an RDoc::Markup::Document.
+
+def parse src
+ @src = src
+ @src.push false
+
+ @footnotes = []
+ @labels = {}
+
+ # @i: index(line no.) of src
+ @i = 0
+
+ # stack for current indentation
+ @indent_stack = []
+
+ # how indented.
+ @current_indent = @indent_stack.join("")
+
+ # RDoc::RD::BlockParser for tmp src
+ @subparser = nil
+
+ # which part is in now
+ @in_part = nil
+ @part_content = []
+
+ @in_verbatim = false
+
+ @yydebug = true
+
+ document = do_parse
+
+ unless @footnotes.empty? then
+ blankline = document.parts.pop
+
+ document.parts << RDoc::Markup::Rule.new(1)
+ document.parts.concat @footnotes
+
+ document.parts.push blankline
+ end
+
+ document
+end
+
+##
+# Returns the next token from the document
+
+def next_token # :nodoc:
+ # preprocessing
+ # if it is not in RD part
+ # => method
+ while @in_part != "rd"
+ line = @src[@i]
+ @i += 1 # next line
+
+ case line
+ # src end
+ when false
+ return [false, false]
+ # RD part begin
+ when /^=begin\s*(?:\bRD\b.*)?\s*$/
+ if @in_part # if in non-RD part
+ @part_content.push(line)
+ else
+ @in_part = "rd"
+ return [:WHITELINE, "=begin\n"] # <= for textblockand
+ end
+ # non-RD part begin
+ when /^=begin\s+(\w+)/
+ part = $1
+ if @in_part # if in non-RD part
+ @part_content.push(line)
+ else
+ @in_part = part if @tree.filter[part] # if filter exists
+# p "BEGIN_PART: #{@in_part}" # DEBUG
+ end
+ # non-RD part end
+ when /^=end/
+ if @in_part # if in non-RD part
+# p "END_PART: #{@in_part}" # DEBUG
+ # make Part-in object
+ part = RDoc::RD::Part.new(@part_content.join(""), @tree, "r")
+ @part_content.clear
+ # call filter, part_out is output(Part object)
+ part_out = @tree.filter[@in_part].call(part)
+
+ if @tree.filter[@in_part].mode == :rd # if output is RD formated
+ subtree = parse_subtree(part_out.to_a)
+ else # if output is target formated
+ basename = TMPFILE.join('.')
+ TMPFILE[-1] += 1
+ tmpfile = open(@tree.tmp_dir + "/" + basename + ".#{@in_part}", "w")
+ tmpfile.print(part_out)
+ tmpfile.close
+ subtree = parse_subtree(["=begin\n", "<<< #{basename}\n", "=end\n"])
+ end
+ @in_part = nil
+ return [:SUBTREE, subtree]
+ end
+ else
+ if @in_part # if in non-RD part
+ @part_content.push(line)
+ end
+ end
+ end
+
+ @current_indent = @indent_stack.join("")
+ line = @src[@i]
+ case line
+ when false
+ if_current_indent_equal("") do
+ [false, false]
+ end
+ when /^=end/
+ if_current_indent_equal("") do
+ @in_part = nil
+ [:WHITELINE, "=end"] # MUST CHANGE??
+ end
+ when /^\s*$/
+ @i += 1 # next line
+ return [:WHITELINE, ':WHITELINE']
+ when /^\#/ # comment line
+ @i += 1 # next line
+ self.next_token()
+ when /^(={1,4})(?!=)\s*(?=\S)/, /^(\+{1,2})(?!\+)\s*(?=\S)/
+ rest = $' # '
+ rest.strip!
+ mark = $1
+ if_current_indent_equal("") do
+ return [:HEADLINE, [MARK_TO_LEVEL[mark], rest]]
+ end
+ when /^<<<\s*(\S+)/
+ file = $1
+ if_current_indent_equal("") do
+ suffix = file[-3 .. -1]
+ if suffix == ".rd" or suffix == ".rb"
+ subtree = parse_subtree(get_included(file))
+ [:SUBTREE, subtree]
+ else
+ [:INCLUDE, file]
+ end
+ end
+ when /^(\s*)\*(\s*)/
+ rest = $' # '
+ newIndent = $2
+ if_current_indent_equal($1) do
+ if @in_verbatim
+ [:STRINGLINE, line]
+ else
+ @indent_stack.push("\s" << newIndent)
+ [:ITEMLISTLINE, rest]
+ end
+ end
+ when /^(\s*)(\(\d+\))(\s*)/
+ rest = $' # '
+ mark = $2
+ newIndent = $3
+ if_current_indent_equal($1) do
+ if @in_verbatim
+ [:STRINGLINE, line]
+ else
+ @indent_stack.push("\s" * mark.size << newIndent)
+ [:ENUMLISTLINE, rest]
+ end
+ end
+ when /^(\s*):(\s*)/
+ rest = $' # '
+ newIndent = $2
+ if_current_indent_equal($1) do
+ if @in_verbatim
+ [:STRINGLINE, line]
+ else
+ @indent_stack.push("\s#{$2}")
+ [:DESCLISTLINE, rest]
+ end
+ end
+ when /^(\s*)---(?!-|\s*$)/
+ indent = $1
+ rest = $'
+ /\s*/ === rest
+ term = $'
+ new_indent = $&
+ if_current_indent_equal(indent) do
+ if @in_verbatim
+ [:STRINGLINE, line]
+ else
+ @indent_stack.push("\s\s\s" + new_indent)
+ [:METHODLISTLINE, term]
+ end
+ end
+ when /^(\s*)/
+ if_current_indent_equal($1) do
+ [:STRINGLINE, line]
+ end
+ else
+ raise "[BUG] parsing error may occured."
+ end
+end
+
+##
+# Yields to the given block if +indent+ matches the current indent, otherwise
+# an indentation token is processed.
+
+def if_current_indent_equal(indent)
+ indent = indent.sub(/\t/, "\s" * 8)
+ if @current_indent == indent
+ @i += 1 # next line
+ yield
+ elsif indent.index(@current_indent) == 0
+ @indent_stack.push(indent[@current_indent.size .. -1])
+ [:INDENT, ":INDENT"]
+ else
+ @indent_stack.pop
+ [:DEDENT, ":DEDENT"]
+ end
+end
+private :if_current_indent_equal
+
+##
+# Cuts off excess whitespace in +src+
+
+def cut_off(src)
+ ret = []
+ whiteline_buf = []
+
+ line = src.shift
+ /^\s*/ =~ line
+
+ indent = Regexp.quote($&)
+ ret.push($')
+
+ while line = src.shift
+ if /^(\s*)$/ =~ line
+ whiteline_buf.push(line)
+ elsif /^#{indent}/ =~ line
+ unless whiteline_buf.empty?
+ ret.concat(whiteline_buf)
+ whiteline_buf.clear
+ end
+ ret.push($')
+ else
+ raise "[BUG]: probably Parser Error while cutting off.\n"
+ end
+ end
+ ret
+end
+private :cut_off
+
+def set_term_to_element(parent, term)
+# parent.set_term_under_document_struct(term, @tree.document_struct)
+ parent.set_term_without_document_struct(term)
+end
+private :set_term_to_element
+
+##
+# Raises a ParseError when invalid formatting is found
+
+def on_error(et, ev, _values)
+ prv, cur, nxt = format_line_num(@i, @i+1, @i+2)
+
+ raise ParseError, <<Msg
+
+RD syntax error: line #{@i+1}:
+ #{prv} |#{@src[@i-1].chomp}
+ #{cur}=>|#{@src[@i].chomp}
+ #{nxt} |#{@src[@i+1].chomp}
+
+Msg
+end
+
+##
+# Current line number
+
+def line_index
+ @i
+end
+
+##
+# Parses subtree +src+
+
+def parse_subtree src
+ @subparser ||= RDoc::RD::BlockParser.new
+
+ @subparser.parse src
+end
+private :parse_subtree
+
+##
+# Retrieves the content for +file+ from the include_path
+
+def get_included(file)
+ included = []
+
+ @include_path.each do |dir|
+ file_name = File.join dir, file
+
+ if File.exist? file_name then
+ included = IO.readlines file_name
+ break
+ end
+ end
+
+ included
+end
+private :get_included
+
+##
+# Formats line numbers +line_numbers+ prettily
+
+def format_line_num(*line_numbers)
+ width = line_numbers.collect{|i| i.to_s.length }.max
+ line_numbers.collect{|i| sprintf("%#{width}d", i) }
+end
+private :format_line_num
+
+##
+# Retrieves the content of +values+ as a single String
+
+def content values
+ values.map { |value| value.content }.join
+end
+
+##
+# Creates a paragraph for +value+
+
+def paragraph value
+ content = cut_off(value).join(' ').rstrip
+ contents = @inline_parser.parse content
+
+ RDoc::Markup::Paragraph.new(*contents)
+end
+
+##
+# Adds footnote +content+ to the document
+
+def add_footnote content
+ index = @footnotes.length + 1
+
+ footmark_link = "{^#{index}}[rdoc-label:footmark-#{index}:foottext-#{index}]"
+
+ @footnotes << RDoc::Markup::Paragraph.new(footmark_link, *content)
+
+ index
+end
+
+##
+# Adds label +label+ to the document
+
+def add_label label
+ @labels[label] = true
+
+ label
+end
+
+# :stopdoc:
+
+##### State transition tables begin ###
+
+racc_action_table = [
+ 34, 35, 30, 33, 14, 73, 38, 33, 76, 15,
+ 88, 34, 35, 30, 33, 40, 34, 35, 30, 33,
+ 40, 65, 34, 35, 30, 33, 14, 73, 77, 14,
+ 54, 15, 34, 35, 30, 33, 14, 9, 10, 11,
+ 12, 15, 34, 35, 30, 33, 14, 73, 81, 54,
+ 38, 15, 34, 35, 30, 33, 14, 73, 40, 67,
+ 83, 15, 34, 35, 30, 33, 14, 73, 54, 30,
+ 35, 15, 34, 35, 30, 33, 34, 47, 36, 14,
+ 59, 15, 34, 35, 30, 33, 14, 73, 38, nil,
+ nil, 15, 34, 35, 30, 33, nil, 47, nil, nil,
+ nil, 15, 34, 35, 30, 33, 14, 73, nil, nil,
+ nil, 15, 34, 35, 30, 33, 14, 73, nil, nil,
+ nil, 15, 34, 35, 30, 33, 14, 9, 10, 11,
+ 12, 15, 34, 35, 30, 33, 14, 73, nil, nil,
+ nil, 15, 34, 35, 30, 33, 14, 73, 61, 63,
+ nil, 15, nil, 62, 60, 61, 63, 61, 63, 14,
+ 62, 87, 62, nil, 79, 34, 35, 30, 33 ]
+
+racc_action_check = [
+ 86, 86, 86, 86, 86, 86, 57, 31, 49, 86,
+ 86, 41, 41, 41, 41, 41, 15, 15, 15, 15,
+ 15, 41, 45, 45, 45, 45, 45, 45, 51, 34,
+ 54, 45, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 85, 85, 85, 85, 85, 85, 56, 33,
+ 58, 85, 79, 79, 79, 79, 79, 79, 62, 44,
+ 66, 79, 78, 78, 78, 78, 78, 78, 30, 28,
+ 25, 78, 24, 24, 24, 24, 22, 24, 1, 35,
+ 36, 24, 75, 75, 75, 75, 75, 75, 13, nil,
+ nil, 75, 27, 27, 27, 27, nil, 27, nil, nil,
+ nil, 27, 74, 74, 74, 74, 74, 74, nil, nil,
+ nil, 74, 68, 68, 68, 68, 68, 68, nil, nil,
+ nil, 68, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 46, 46, 46, 46, 46, 46, nil, nil,
+ nil, 46, 47, 47, 47, 47, 47, 47, 39, 39,
+ nil, 47, nil, 39, 39, 82, 82, 64, 64, 52,
+ 82, 82, 64, nil, 52, 20, 20, 20, 20 ]
+
+racc_action_pointer = [
+ 29, 78, 119, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, 81, nil, 13, nil, nil, nil, nil,
+ 162, nil, 73, nil, 69, 66, nil, 89, 64, nil,
+ 60, 1, nil, 41, 22, 72, 80, nil, nil, 141,
+ nil, 8, nil, nil, 46, 19, 129, 139, nil, -5,
+ nil, 15, 152, nil, 22, nil, 35, -1, 43, nil,
+ nil, nil, 51, nil, 150, nil, 47, nil, 109, nil,
+ nil, nil, nil, nil, 99, 79, nil, nil, 59, 49,
+ nil, nil, 148, nil, nil, 39, -3, nil, nil ]
+
+racc_action_default = [
+ -2, -73, -1, -4, -5, -6, -7, -8, -9, -10,
+ -11, -12, -13, -14, -16, -73, -23, -24, -25, -26,
+ -27, -31, -32, -34, -72, -36, -38, -72, -40, -42,
+ -59, -44, -46, -59, -63, -65, -73, -3, -15, -73,
+ -22, -73, -30, -33, -73, -69, -70, -71, -37, -73,
+ -41, -73, -51, -58, -61, -45, -73, -62, -64, 89,
+ -17, -19, -73, -21, -18, -28, -73, -35, -66, -53,
+ -54, -55, -56, -57, -67, -68, -39, -43, -49, -73,
+ -60, -47, -73, -29, -52, -48, -73, -20, -50 ]
+
+racc_goto_table = [
+ 4, 39, 4, 68, 74, 75, 5, 6, 5, 6,
+ 51, 42, 44, 56, 3, 49, 37, 57, 58, 41,
+ 43, 48, 84, 50, 66, 55, 1, 64, 84, 84,
+ 45, 46, 42, 45, 46, 2, 85, 86, 80, 84,
+ 84, nil, nil, nil, nil, nil, nil, nil, 82, nil,
+ nil, nil, 78 ]
+
+racc_goto_check = [
+ 4, 10, 4, 31, 31, 31, 5, 6, 5, 6,
+ 27, 12, 21, 27, 3, 21, 3, 9, 9, 17,
+ 19, 23, 32, 26, 11, 29, 1, 10, 32, 32,
+ 5, 6, 12, 5, 6, 2, 31, 31, 33, 32,
+ 32, nil, nil, nil, nil, nil, nil, nil, 10, nil,
+ nil, nil, 4 ]
+
+racc_goto_pointer = [
+ nil, 26, 35, 14, 0, 6, 7, nil, nil, -17,
+ -14, -17, -9, nil, nil, nil, nil, 4, nil, -2,
+ nil, -12, nil, -4, nil, nil, -5, -20, nil, -6,
+ nil, -42, -46, -16 ]
+
+racc_goto_default = [
+ nil, nil, nil, nil, 70, 71, 72, 7, 8, 13,
+ nil, nil, 21, 16, 17, 18, 19, 20, 22, 23,
+ 24, nil, 25, 26, 27, 28, 29, nil, 31, 32,
+ 52, nil, 69, 53 ]
+
+racc_reduce_table = [
+ 0, 0, :racc_error,
+ 1, 15, :_reduce_1,
+ 0, 15, :_reduce_2,
+ 2, 16, :_reduce_3,
+ 1, 16, :_reduce_4,
+ 1, 17, :_reduce_5,
+ 1, 17, :_reduce_6,
+ 1, 17, :_reduce_none,
+ 1, 17, :_reduce_8,
+ 1, 17, :_reduce_9,
+ 1, 17, :_reduce_10,
+ 1, 17, :_reduce_11,
+ 1, 21, :_reduce_12,
+ 1, 22, :_reduce_13,
+ 1, 18, :_reduce_14,
+ 2, 23, :_reduce_15,
+ 1, 23, :_reduce_16,
+ 3, 19, :_reduce_17,
+ 1, 25, :_reduce_18,
+ 2, 24, :_reduce_19,
+ 4, 24, :_reduce_20,
+ 2, 24, :_reduce_21,
+ 1, 24, :_reduce_22,
+ 1, 26, :_reduce_none,
+ 1, 26, :_reduce_none,
+ 1, 26, :_reduce_none,
+ 1, 26, :_reduce_none,
+ 1, 20, :_reduce_27,
+ 3, 20, :_reduce_28,
+ 4, 20, :_reduce_29,
+ 2, 31, :_reduce_30,
+ 1, 31, :_reduce_31,
+ 1, 27, :_reduce_32,
+ 2, 32, :_reduce_33,
+ 1, 32, :_reduce_34,
+ 3, 33, :_reduce_35,
+ 1, 28, :_reduce_36,
+ 2, 36, :_reduce_37,
+ 1, 36, :_reduce_38,
+ 3, 37, :_reduce_39,
+ 1, 29, :_reduce_40,
+ 2, 39, :_reduce_41,
+ 1, 39, :_reduce_42,
+ 3, 40, :_reduce_43,
+ 1, 30, :_reduce_44,
+ 2, 42, :_reduce_45,
+ 1, 42, :_reduce_46,
+ 3, 43, :_reduce_47,
+ 3, 41, :_reduce_48,
+ 2, 41, :_reduce_49,
+ 4, 41, :_reduce_50,
+ 1, 41, :_reduce_51,
+ 2, 45, :_reduce_52,
+ 1, 45, :_reduce_none,
+ 1, 46, :_reduce_54,
+ 1, 46, :_reduce_55,
+ 1, 46, :_reduce_none,
+ 1, 46, :_reduce_57,
+ 1, 44, :_reduce_none,
+ 0, 44, :_reduce_none,
+ 2, 47, :_reduce_none,
+ 1, 47, :_reduce_none,
+ 2, 34, :_reduce_62,
+ 1, 34, :_reduce_63,
+ 2, 38, :_reduce_64,
+ 1, 38, :_reduce_65,
+ 2, 35, :_reduce_66,
+ 2, 35, :_reduce_67,
+ 2, 35, :_reduce_68,
+ 1, 35, :_reduce_69,
+ 1, 35, :_reduce_none,
+ 1, 35, :_reduce_71,
+ 0, 35, :_reduce_72 ]
+
+racc_reduce_n = 73
+
+racc_shift_n = 89
+
+racc_token_table = {
+ false => 0,
+ :error => 1,
+ :DUMMY => 2,
+ :ITEMLISTLINE => 3,
+ :ENUMLISTLINE => 4,
+ :DESCLISTLINE => 5,
+ :METHODLISTLINE => 6,
+ :STRINGLINE => 7,
+ :WHITELINE => 8,
+ :SUBTREE => 9,
+ :HEADLINE => 10,
+ :INCLUDE => 11,
+ :INDENT => 12,
+ :DEDENT => 13 }
+
+racc_nt_base = 14
+
+racc_use_result_var = true
+
+Racc_arg = [
+ racc_action_table,
+ racc_action_check,
+ racc_action_default,
+ racc_action_pointer,
+ racc_goto_table,
+ racc_goto_check,
+ racc_goto_default,
+ racc_goto_pointer,
+ racc_nt_base,
+ racc_reduce_table,
+ racc_token_table,
+ racc_shift_n,
+ racc_reduce_n,
+ racc_use_result_var ]
+
+Racc_token_to_s_table = [
+ "$end",
+ "error",
+ "DUMMY",
+ "ITEMLISTLINE",
+ "ENUMLISTLINE",
+ "DESCLISTLINE",
+ "METHODLISTLINE",
+ "STRINGLINE",
+ "WHITELINE",
+ "SUBTREE",
+ "HEADLINE",
+ "INCLUDE",
+ "INDENT",
+ "DEDENT",
+ "$start",
+ "document",
+ "blocks",
+ "block",
+ "textblock",
+ "verbatim",
+ "lists",
+ "headline",
+ "include",
+ "textblockcontent",
+ "verbatimcontent",
+ "verbatim_after_lists",
+ "list",
+ "itemlist",
+ "enumlist",
+ "desclist",
+ "methodlist",
+ "lists2",
+ "itemlistitems",
+ "itemlistitem",
+ "first_textblock_in_itemlist",
+ "other_blocks_in_list",
+ "enumlistitems",
+ "enumlistitem",
+ "first_textblock_in_enumlist",
+ "desclistitems",
+ "desclistitem",
+ "description_part",
+ "methodlistitems",
+ "methodlistitem",
+ "whitelines",
+ "blocks_in_list",
+ "block_in_list",
+ "whitelines2" ]
+
+Racc_debug_parser = false
+
+##### State transition tables end #####
+
+# reduce 0 omitted
+
+def _reduce_1(val, _values, result)
+ result = RDoc::Markup::Document.new(*val[0])
+ result
+end
+
+def _reduce_2(val, _values, result)
+ raise ParseError, "file empty"
+ result
+end
+
+def _reduce_3(val, _values, result)
+ result = val[0].concat val[1]
+ result
+end
+
+def _reduce_4(val, _values, result)
+ result = val[0]
+ result
+end
+
+def _reduce_5(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_6(val, _values, result)
+ result = val
+ result
+end
+
+# reduce 7 omitted
+
+def _reduce_8(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_9(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_10(val, _values, result)
+ result = [RDoc::Markup::BlankLine.new]
+ result
+end
+
+def _reduce_11(val, _values, result)
+ result = val[0].parts
+ result
+end
+
+def _reduce_12(val, _values, result)
+ # val[0] is like [level, title]
+ title = @inline_parser.parse(val[0][1])
+ result = RDoc::Markup::Heading.new(val[0][0], title)
+
+ result
+end
+
+def _reduce_13(val, _values, result)
+ result = RDoc::Markup::Include.new val[0], @include_path
+
+ result
+end
+
+def _reduce_14(val, _values, result)
+ # val[0] is Array of String
+ result = paragraph val[0]
+
+ result
+end
+
+def _reduce_15(val, _values, result)
+ result << val[1].rstrip
+ result
+end
+
+def _reduce_16(val, _values, result)
+ result = [val[0].rstrip]
+ result
+end
+
+def _reduce_17(val, _values, result)
+ # val[1] is Array of String
+ content = cut_off val[1]
+ result = RDoc::Markup::Verbatim.new(*content)
+
+ # imform to lexer.
+ @in_verbatim = false
+
+ result
+end
+
+def _reduce_18(val, _values, result)
+ # val[0] is Array of String
+ content = cut_off val[0]
+ result = RDoc::Markup::Verbatim.new(*content)
+
+ # imform to lexer.
+ @in_verbatim = false
+
+ result
+end
+
+def _reduce_19(val, _values, result)
+ result << val[1]
+
+ result
+end
+
+def _reduce_20(val, _values, result)
+ result.concat val[2]
+
+ result
+end
+
+def _reduce_21(val, _values, result)
+ result << "\n"
+
+ result
+end
+
+def _reduce_22(val, _values, result)
+ result = val
+ # inform to lexer.
+ @in_verbatim = true
+
+ result
+end
+
+# reduce 23 omitted
+
+# reduce 24 omitted
+
+# reduce 25 omitted
+
+# reduce 26 omitted
+
+def _reduce_27(val, _values, result)
+ result = val[0]
+
+ result
+end
+
+def _reduce_28(val, _values, result)
+ result = val[1]
+
+ result
+end
+
+def _reduce_29(val, _values, result)
+ result = val[1].push(val[2])
+
+ result
+end
+
+def _reduce_30(val, _values, result)
+ result = val[0] << val[1]
+ result
+end
+
+def _reduce_31(val, _values, result)
+ result = [val[0]]
+ result
+end
+
+def _reduce_32(val, _values, result)
+ result = RDoc::Markup::List.new :BULLET, *val[0]
+
+ result
+end
+
+def _reduce_33(val, _values, result)
+ result.push(val[1])
+ result
+end
+
+def _reduce_34(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_35(val, _values, result)
+ result = RDoc::Markup::ListItem.new nil, val[0], *val[1]
+
+ result
+end
+
+def _reduce_36(val, _values, result)
+ result = RDoc::Markup::List.new :NUMBER, *val[0]
+
+ result
+end
+
+def _reduce_37(val, _values, result)
+ result.push(val[1])
+ result
+end
+
+def _reduce_38(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_39(val, _values, result)
+ result = RDoc::Markup::ListItem.new nil, val[0], *val[1]
+
+ result
+end
+
+def _reduce_40(val, _values, result)
+ result = RDoc::Markup::List.new :NOTE, *val[0]
+
+ result
+end
+
+def _reduce_41(val, _values, result)
+ result.push(val[1])
+ result
+end
+
+def _reduce_42(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_43(val, _values, result)
+ term = @inline_parser.parse val[0].strip
+
+ result = RDoc::Markup::ListItem.new term, *val[1]
+
+ result
+end
+
+def _reduce_44(val, _values, result)
+ result = RDoc::Markup::List.new :LABEL, *val[0]
+
+ result
+end
+
+def _reduce_45(val, _values, result)
+ result.push(val[1])
+ result
+end
+
+def _reduce_46(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_47(val, _values, result)
+ result = RDoc::Markup::ListItem.new "<tt>#{val[0].strip}</tt>", *val[1]
+
+ result
+end
+
+def _reduce_48(val, _values, result)
+ result = [val[1]].concat(val[2])
+
+ result
+end
+
+def _reduce_49(val, _values, result)
+ result = [val[1]]
+
+ result
+end
+
+def _reduce_50(val, _values, result)
+ result = val[2]
+
+ result
+end
+
+def _reduce_51(val, _values, result)
+ result = []
+
+ result
+end
+
+def _reduce_52(val, _values, result)
+ result.concat val[1]
+ result
+end
+
+# reduce 53 omitted
+
+def _reduce_54(val, _values, result)
+ result = val
+ result
+end
+
+def _reduce_55(val, _values, result)
+ result = val
+ result
+end
+
+# reduce 56 omitted
+
+def _reduce_57(val, _values, result)
+ result = []
+ result
+end
+
+# reduce 58 omitted
+
+# reduce 59 omitted
+
+# reduce 60 omitted
+
+# reduce 61 omitted
+
+def _reduce_62(val, _values, result)
+ result = paragraph [val[0]].concat(val[1])
+
+ result
+end
+
+def _reduce_63(val, _values, result)
+ result = paragraph [val[0]]
+
+ result
+end
+
+def _reduce_64(val, _values, result)
+ result = paragraph [val[0]].concat(val[1])
+
+ result
+end
+
+def _reduce_65(val, _values, result)
+ result = paragraph [val[0]]
+
+ result
+end
+
+def _reduce_66(val, _values, result)
+ result = [val[0]].concat(val[1])
+
+ result
+end
+
+def _reduce_67(val, _values, result)
+ result.concat val[1]
+ result
+end
+
+def _reduce_68(val, _values, result)
+ result = val[1]
+ result
+end
+
+def _reduce_69(val, _values, result)
+ result = val
+ result
+end
+
+# reduce 70 omitted
+
+def _reduce_71(val, _values, result)
+ result = []
+ result
+end
+
+def _reduce_72(val, _values, result)
+ result = []
+ result
+end
+
+def _reduce_none(val, _values, result)
+ val[0]
+end
+
+end # class BlockParser
+
+end
diff --git a/lib/rdoc/rd/inline.rb b/lib/rdoc/rd/inline.rb
new file mode 100644
index 0000000000..ee724fb80f
--- /dev/null
+++ b/lib/rdoc/rd/inline.rb
@@ -0,0 +1,71 @@
+##
+# Inline keeps track of markup and labels to create proper links.
+
+class RDoc::RD::Inline
+
+ ##
+ # The text of the reference
+
+ attr_reader :reference
+
+ ##
+ # The markup of this reference in RDoc format
+
+ attr_reader :rdoc
+
+ ##
+ # Creates a new Inline for +rdoc+ and +reference+.
+ #
+ # +rdoc+ may be another Inline or a String. If +reference+ is not given it
+ # will use the text from +rdoc+.
+
+ def self.new rdoc, reference = rdoc
+ if self === rdoc and reference.equal? rdoc then
+ rdoc
+ else
+ super
+ end
+ end
+
+ ##
+ # Initializes the Inline with +rdoc+ and +inline+
+
+ def initialize rdoc, reference # :not-new:
+ @reference = reference.equal?(rdoc) ? reference.dup : reference
+
+ # unpack
+ @reference = @reference.reference if self.class === @reference
+ @rdoc = rdoc
+ end
+
+ def == other # :nodoc:
+ self.class === other and
+ @reference == other.reference and @rdoc == other.rdoc
+ end
+
+ ##
+ # Appends +more+ to this inline. +more+ may be a String or another Inline.
+
+ def append more
+ case more
+ when String then
+ @reference << more
+ @rdoc << more
+ when RDoc::RD::Inline then
+ @reference << more.reference
+ @rdoc << more.rdoc
+ else
+ raise "unknown thingy #{more}"
+ end
+
+ self
+ end
+
+ def inspect # :nodoc:
+ "(inline: #{self})"
+ end
+
+ alias to_s rdoc # :nodoc:
+
+end
+
diff --git a/lib/rdoc/rd/inline_parser.rb b/lib/rdoc/rd/inline_parser.rb
new file mode 100644
index 0000000000..03a1e84dea
--- /dev/null
+++ b/lib/rdoc/rd/inline_parser.rb
@@ -0,0 +1,1207 @@
+#
+# DO NOT MODIFY!!!!
+# This file is automatically generated by Racc 1.4.9
+# from Racc grammer file "".
+#
+
+require 'racc/parser.rb'
+
+require 'strscan'
+
+class RDoc::RD
+
+##
+# RD format parser for inline markup such as emphasis, links, footnotes, etc.
+
+class InlineParser < Racc::Parser
+
+
+# :stopdoc:
+
+EM_OPEN = '((*'
+EM_OPEN_RE = /\A#{Regexp.quote(EM_OPEN)}/
+EM_CLOSE = '*))'
+EM_CLOSE_RE = /\A#{Regexp.quote(EM_CLOSE)}/
+CODE_OPEN = '(({'
+CODE_OPEN_RE = /\A#{Regexp.quote(CODE_OPEN)}/
+CODE_CLOSE = '}))'
+CODE_CLOSE_RE = /\A#{Regexp.quote(CODE_CLOSE)}/
+VAR_OPEN = '((|'
+VAR_OPEN_RE = /\A#{Regexp.quote(VAR_OPEN)}/
+VAR_CLOSE = '|))'
+VAR_CLOSE_RE = /\A#{Regexp.quote(VAR_CLOSE)}/
+KBD_OPEN = '((%'
+KBD_OPEN_RE = /\A#{Regexp.quote(KBD_OPEN)}/
+KBD_CLOSE = '%))'
+KBD_CLOSE_RE = /\A#{Regexp.quote(KBD_CLOSE)}/
+INDEX_OPEN = '((:'
+INDEX_OPEN_RE = /\A#{Regexp.quote(INDEX_OPEN)}/
+INDEX_CLOSE = ':))'
+INDEX_CLOSE_RE = /\A#{Regexp.quote(INDEX_CLOSE)}/
+REF_OPEN = '((<'
+REF_OPEN_RE = /\A#{Regexp.quote(REF_OPEN)}/
+REF_CLOSE = '>))'
+REF_CLOSE_RE = /\A#{Regexp.quote(REF_CLOSE)}/
+FOOTNOTE_OPEN = '((-'
+FOOTNOTE_OPEN_RE = /\A#{Regexp.quote(FOOTNOTE_OPEN)}/
+FOOTNOTE_CLOSE = '-))'
+FOOTNOTE_CLOSE_RE = /\A#{Regexp.quote(FOOTNOTE_CLOSE)}/
+VERB_OPEN = "(('"
+VERB_OPEN_RE = /\A#{Regexp.quote(VERB_OPEN)}/
+VERB_CLOSE = "'))"
+VERB_CLOSE_RE = /\A#{Regexp.quote(VERB_CLOSE)}/
+
+BAR = "|"
+BAR_RE = /\A#{Regexp.quote(BAR)}/
+QUOTE = '"'
+QUOTE_RE = /\A#{Regexp.quote(QUOTE)}/
+SLASH = "/"
+SLASH_RE = /\A#{Regexp.quote(SLASH)}/
+BACK_SLASH = "\\"
+BACK_SLASH_RE = /\A#{Regexp.quote(BACK_SLASH)}/
+URL = "URL:"
+URL_RE = /\A#{Regexp.quote(URL)}/
+
+other_re_mode = Regexp::EXTENDED
+other_re_mode |= Regexp::MULTILINE
+
+OTHER_RE = Regexp.new(
+ "\\A.+?(?=#{Regexp.quote(EM_OPEN)}|#{Regexp.quote(EM_CLOSE)}|
+ #{Regexp.quote(CODE_OPEN)}|#{Regexp.quote(CODE_CLOSE)}|
+ #{Regexp.quote(VAR_OPEN)}|#{Regexp.quote(VAR_CLOSE)}|
+ #{Regexp.quote(KBD_OPEN)}|#{Regexp.quote(KBD_CLOSE)}|
+ #{Regexp.quote(INDEX_OPEN)}|#{Regexp.quote(INDEX_CLOSE)}|
+ #{Regexp.quote(REF_OPEN)}|#{Regexp.quote(REF_CLOSE)}|
+ #{Regexp.quote(FOOTNOTE_OPEN)}|#{Regexp.quote(FOOTNOTE_CLOSE)}|
+ #{Regexp.quote(VERB_OPEN)}|#{Regexp.quote(VERB_CLOSE)}|
+ #{Regexp.quote(BAR)}|
+ #{Regexp.quote(QUOTE)}|
+ #{Regexp.quote(SLASH)}|
+ #{Regexp.quote(BACK_SLASH)}|
+ #{Regexp.quote(URL)})", other_re_mode)
+
+# :startdoc:
+
+##
+# Creates a new parser for inline markup in the rd format. The +block_parser+
+# is used to for footnotes and labels in the inline text.
+
+def initialize block_parser
+ @block_parser = block_parser
+end
+
+##
+# Parses the +inline+ text from RD format into RDoc format.
+
+def parse inline
+ @inline = inline
+ @src = StringScanner.new inline
+ @pre = ""
+ @yydebug = true
+ do_parse.to_s
+end
+
+##
+# Returns the next token from the inline text
+
+def next_token
+ return [false, false] if @src.eos?
+# p @src.rest if @yydebug
+ if ret = @src.scan(EM_OPEN_RE)
+ @pre << ret
+ [:EM_OPEN, ret]
+ elsif ret = @src.scan(EM_CLOSE_RE)
+ @pre << ret
+ [:EM_CLOSE, ret]
+ elsif ret = @src.scan(CODE_OPEN_RE)
+ @pre << ret
+ [:CODE_OPEN, ret]
+ elsif ret = @src.scan(CODE_CLOSE_RE)
+ @pre << ret
+ [:CODE_CLOSE, ret]
+ elsif ret = @src.scan(VAR_OPEN_RE)
+ @pre << ret
+ [:VAR_OPEN, ret]
+ elsif ret = @src.scan(VAR_CLOSE_RE)
+ @pre << ret
+ [:VAR_CLOSE, ret]
+ elsif ret = @src.scan(KBD_OPEN_RE)
+ @pre << ret
+ [:KBD_OPEN, ret]
+ elsif ret = @src.scan(KBD_CLOSE_RE)
+ @pre << ret
+ [:KBD_CLOSE, ret]
+ elsif ret = @src.scan(INDEX_OPEN_RE)
+ @pre << ret
+ [:INDEX_OPEN, ret]
+ elsif ret = @src.scan(INDEX_CLOSE_RE)
+ @pre << ret
+ [:INDEX_CLOSE, ret]
+ elsif ret = @src.scan(REF_OPEN_RE)
+ @pre << ret
+ [:REF_OPEN, ret]
+ elsif ret = @src.scan(REF_CLOSE_RE)
+ @pre << ret
+ [:REF_CLOSE, ret]
+ elsif ret = @src.scan(FOOTNOTE_OPEN_RE)
+ @pre << ret
+ [:FOOTNOTE_OPEN, ret]
+ elsif ret = @src.scan(FOOTNOTE_CLOSE_RE)
+ @pre << ret
+ [:FOOTNOTE_CLOSE, ret]
+ elsif ret = @src.scan(VERB_OPEN_RE)
+ @pre << ret
+ [:VERB_OPEN, ret]
+ elsif ret = @src.scan(VERB_CLOSE_RE)
+ @pre << ret
+ [:VERB_CLOSE, ret]
+ elsif ret = @src.scan(BAR_RE)
+ @pre << ret
+ [:BAR, ret]
+ elsif ret = @src.scan(QUOTE_RE)
+ @pre << ret
+ [:QUOTE, ret]
+ elsif ret = @src.scan(SLASH_RE)
+ @pre << ret
+ [:SLASH, ret]
+ elsif ret = @src.scan(BACK_SLASH_RE)
+ @pre << ret
+ [:BACK_SLASH, ret]
+ elsif ret = @src.scan(URL_RE)
+ @pre << ret
+ [:URL, ret]
+ elsif ret = @src.scan(OTHER_RE)
+ @pre << ret
+ [:OTHER, ret]
+ else
+ ret = @src.rest
+ @pre << ret
+ @src.terminate
+ [:OTHER, ret]
+ end
+end
+
+##
+# Raises a ParseError when invalid formatting is found
+
+def on_error(et, ev, values)
+ lines_of_rest = @src.rest.lines.to_a.length
+ prev_words = prev_words_on_error(ev)
+ at = 4 + prev_words.length
+
+ message = <<-MSG
+RD syntax error: line #{@block_parser.line_index - lines_of_rest}:
+...#{prev_words} #{(ev||'')} #{next_words_on_error()} ...
+ MSG
+
+ message << " " * at + "^" * (ev ? ev.length : 0) + "\n"
+ raise ParseError, message
+end
+
+##
+# Returns words before the error
+
+def prev_words_on_error(ev)
+ pre = @pre
+ if ev and /#{Regexp.quote(ev)}$/ =~ pre
+ pre = $`
+ end
+ last_line(pre)
+end
+
+##
+# Returns the last line of +src+
+
+def last_line(src)
+ if n = src.rindex("\n")
+ src[(n+1) .. -1]
+ else
+ src
+ end
+end
+private :last_line
+
+##
+# Returns words following an error
+
+def next_words_on_error
+ if n = @src.rest.index("\n")
+ @src.rest[0 .. (n-1)]
+ else
+ @src.rest
+ end
+end
+
+##
+# Creates a new RDoc::RD::Inline for the +rdoc+ markup and the raw +reference+
+
+def inline rdoc, reference = rdoc
+ RDoc::RD::Inline.new rdoc, reference
+end
+
+# :stopdoc:
+##### State transition tables begin ###
+
+racc_action_table = [
+ 63, 64, 65, 153, 81, 62, 76, 78, 79, 87,
+ 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+ 77, 80, 152, 63, 64, 65, 61, 81, 62, 76,
+ 78, 79, 124, 66, 67, 68, 69, 70, 71, 72,
+ 73, 74, 75, 77, 80, 149, 104, 103, 102, 100,
+ 101, 99, 115, 116, 117, 164, 105, 106, 107, 108,
+ 109, 110, 111, 112, 113, 114, 96, 118, 119, 104,
+ 103, 102, 100, 101, 99, 115, 116, 117, 89, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 88,
+ 118, 119, 104, 103, 102, 100, 101, 99, 115, 116,
+ 117, 161, 105, 106, 107, 108, 109, 110, 111, 112,
+ 113, 114, 86, 118, 119, 104, 103, 102, 100, 101,
+ 99, 115, 116, 117, 85, 105, 106, 107, 108, 109,
+ 110, 111, 112, 113, 114, 137, 118, 119, 63, 64,
+ 65, 61, 81, 62, 76, 78, 79, 84, 66, 67,
+ 68, 69, 70, 71, 72, 73, 74, 75, 77, 80,
+ 22, 23, 24, 25, 26, 21, 18, 19, 176, 177,
+ 13, 173, 14, 154, 15, 175, 16, 137, 17, 42,
+ 148, 20, 54, 38, 53, 55, 56, 57, 29, 13,
+ 177, 14, nil, 15, nil, 16, nil, 17, nil, nil,
+ 20, 22, 23, 24, 25, 26, 21, 18, 19, nil,
+ nil, 13, nil, 14, nil, 15, nil, 16, nil, 17,
+ nil, nil, 20, 22, 23, 24, 25, 26, 21, 18,
+ 19, nil, nil, 13, nil, 14, nil, 15, nil, 16,
+ nil, 17, nil, nil, 20, 22, 23, 24, 25, 26,
+ 21, 18, 19, nil, nil, 13, nil, 14, nil, 15,
+ nil, 16, nil, 17, 145, nil, 20, 54, 133, 53,
+ 55, 56, 57, nil, 13, nil, 14, nil, 15, nil,
+ 16, nil, 17, nil, nil, 20, 22, 23, 24, 25,
+ 26, 21, 18, 19, nil, nil, 13, nil, 14, nil,
+ 15, nil, 16, nil, 17, 145, nil, 20, 54, 133,
+ 53, 55, 56, 57, nil, 13, nil, 14, nil, 15,
+ nil, 16, nil, 17, nil, nil, 20, 22, 23, 24,
+ 25, 26, 21, 18, 19, nil, nil, 13, nil, 14,
+ nil, 15, nil, 16, nil, 17, 145, nil, 20, 54,
+ 133, 53, 55, 56, 57, nil, 13, nil, 14, nil,
+ 15, nil, 16, nil, 17, 145, nil, 20, 54, 133,
+ 53, 55, 56, 57, nil, 13, nil, 14, nil, 15,
+ nil, 16, nil, 17, nil, nil, 20, 22, 23, 24,
+ 25, 26, 21, 18, 19, nil, nil, 13, nil, 14,
+ nil, 15, nil, 16, 122, 17, nil, 54, 20, 53,
+ 55, 56, 57, nil, 13, nil, 14, nil, 15, nil,
+ 16, nil, 17, nil, nil, 20, 22, 23, 24, 25,
+ 26, 21, 18, 19, nil, nil, 13, nil, 14, nil,
+ 15, nil, 16, nil, 17, nil, nil, 20, 135, 136,
+ 54, 133, 53, 55, 56, 57, nil, 13, nil, 14,
+ nil, 15, nil, 16, nil, 17, nil, nil, 20, 135,
+ 136, 54, 133, 53, 55, 56, 57, nil, 13, nil,
+ 14, nil, 15, nil, 16, nil, 17, nil, nil, 20,
+ 135, 136, 54, 133, 53, 55, 56, 57, nil, 13,
+ nil, 14, nil, 15, nil, 16, nil, 17, nil, nil,
+ 20, 172, 135, 136, 54, 133, 53, 55, 56, 57,
+ 165, 135, 136, 54, 133, 53, 55, 56, 57, 95,
+ nil, nil, 54, 91, 53, 55, 56, 57, 174, 135,
+ 136, 54, 133, 53, 55, 56, 57, 158, nil, nil,
+ 54, nil, 53, 55, 56, 57, 178, 135, 136, 54,
+ 133, 53, 55, 56, 57, 145, nil, nil, 54, 133,
+ 53, 55, 56, 57, 145, nil, nil, 54, 133, 53,
+ 55, 56, 57, 135, 136, 54, 133, 53, 55, 56,
+ 57, 135, 136, 54, 133, 53, 55, 56, 57, 135,
+ 136, 54, 133, 53, 55, 56, 57, 22, 23, 24,
+ 25, 26, 21 ]
+
+racc_action_check = [
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 33,
+ 61, 61, 61, 61, 61, 61, 61, 61, 61, 61,
+ 61, 61, 61, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 41, 59, 59, 59, 59, 59, 59, 59,
+ 59, 59, 59, 59, 59, 59, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 125, 97, 97, 97, 97,
+ 97, 97, 97, 97, 97, 97, 37, 97, 97, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 35, 38,
+ 38, 38, 38, 38, 38, 38, 38, 38, 38, 34,
+ 38, 38, 155, 155, 155, 155, 155, 155, 155, 155,
+ 155, 100, 155, 155, 155, 155, 155, 155, 155, 155,
+ 155, 155, 32, 155, 155, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 31, 91, 91, 91, 91, 91,
+ 91, 91, 91, 91, 91, 43, 91, 91, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 29, 20, 20,
+ 20, 20, 20, 20, 20, 20, 20, 20, 20, 20,
+ 17, 17, 17, 17, 17, 17, 17, 17, 165, 165,
+ 17, 162, 17, 90, 17, 164, 17, 94, 17, 18,
+ 58, 17, 18, 18, 18, 18, 18, 18, 1, 18,
+ 172, 18, nil, 18, nil, 18, nil, 18, nil, nil,
+ 18, 19, 19, 19, 19, 19, 19, 19, 19, nil,
+ nil, 19, nil, 19, nil, 19, nil, 19, nil, 19,
+ nil, nil, 19, 16, 16, 16, 16, 16, 16, 16,
+ 16, nil, nil, 16, nil, 16, nil, 16, nil, 16,
+ nil, 16, nil, nil, 16, 15, 15, 15, 15, 15,
+ 15, 15, 15, nil, nil, 15, nil, 15, nil, 15,
+ nil, 15, nil, 15, 45, nil, 15, 45, 45, 45,
+ 45, 45, 45, nil, 45, nil, 45, nil, 45, nil,
+ 45, nil, 45, nil, nil, 45, 14, 14, 14, 14,
+ 14, 14, 14, 14, nil, nil, 14, nil, 14, nil,
+ 14, nil, 14, nil, 14, 146, nil, 14, 146, 146,
+ 146, 146, 146, 146, nil, 146, nil, 146, nil, 146,
+ nil, 146, nil, 146, nil, nil, 146, 13, 13, 13,
+ 13, 13, 13, 13, 13, nil, nil, 13, nil, 13,
+ nil, 13, nil, 13, nil, 13, 138, nil, 13, 138,
+ 138, 138, 138, 138, 138, nil, 138, nil, 138, nil,
+ 138, nil, 138, nil, 138, 44, nil, 138, 44, 44,
+ 44, 44, 44, 44, nil, 44, nil, 44, nil, 44,
+ nil, 44, nil, 44, nil, nil, 44, 2, 2, 2,
+ 2, 2, 2, 2, 2, nil, nil, 2, nil, 2,
+ nil, 2, nil, 2, 39, 2, nil, 39, 2, 39,
+ 39, 39, 39, nil, 39, nil, 39, nil, 39, nil,
+ 39, nil, 39, nil, nil, 39, 0, 0, 0, 0,
+ 0, 0, 0, 0, nil, nil, 0, nil, 0, nil,
+ 0, nil, 0, nil, 0, nil, nil, 0, 122, 122,
+ 122, 122, 122, 122, 122, 122, nil, 122, nil, 122,
+ nil, 122, nil, 122, nil, 122, nil, nil, 122, 127,
+ 127, 127, 127, 127, 127, 127, 127, nil, 127, nil,
+ 127, nil, 127, nil, 127, nil, 127, nil, nil, 127,
+ 42, 42, 42, 42, 42, 42, 42, 42, nil, 42,
+ nil, 42, nil, 42, nil, 42, nil, 42, nil, nil,
+ 42, 159, 159, 159, 159, 159, 159, 159, 159, 159,
+ 126, 126, 126, 126, 126, 126, 126, 126, 126, 36,
+ nil, nil, 36, 36, 36, 36, 36, 36, 163, 163,
+ 163, 163, 163, 163, 163, 163, 163, 92, nil, nil,
+ 92, nil, 92, 92, 92, 92, 171, 171, 171, 171,
+ 171, 171, 171, 171, 171, 142, nil, nil, 142, 142,
+ 142, 142, 142, 142, 52, nil, nil, 52, 52, 52,
+ 52, 52, 52, 95, 95, 95, 95, 95, 95, 95,
+ 95, 168, 168, 168, 168, 168, 168, 168, 168, 158,
+ 158, 158, 158, 158, 158, 158, 158, 27, 27, 27,
+ 27, 27, 27 ]
+
+racc_action_pointer = [
+ 423, 188, 384, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, 324, 283, 242, 220, 157, 176, 198,
+ 135, nil, nil, nil, nil, nil, nil, 604, nil, 147,
+ nil, 110, 96, -9, 69, 56, 526, 43, 66, 401,
+ nil, 28, 486, 130, 362, 261, nil, nil, nil, nil,
+ nil, nil, 571, nil, nil, nil, nil, nil, 169, 20,
+ nil, -3, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ 150, 112, 544, nil, 172, 579, nil, 43, nil, nil,
+ 95, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, 444, nil, nil, 52, 517, 465, nil, nil,
+ nil, nil, nil, nil, nil, nil, nil, nil, 343, nil,
+ nil, nil, 562, nil, nil, nil, 302, nil, nil, nil,
+ nil, nil, nil, nil, nil, 89, nil, nil, 595, 508,
+ nil, nil, 168, 535, 171, 164, nil, nil, 587, nil,
+ nil, 553, 185, nil, nil, nil, nil, nil, nil ]
+
+racc_action_default = [
+ -138, -138, -1, -3, -4, -5, -6, -7, -8, -9,
+ -10, -11, -12, -138, -138, -138, -138, -138, -138, -138,
+ -138, -103, -104, -105, -106, -107, -108, -111, -110, -138,
+ -2, -138, -138, -138, -138, -138, -138, -138, -138, -27,
+ -26, -35, -138, -58, -41, -40, -47, -48, -49, -50,
+ -51, -52, -63, -66, -67, -68, -69, -70, -138, -138,
+ -112, -138, -116, -117, -118, -119, -120, -121, -122, -123,
+ -124, -125, -126, -127, -128, -129, -130, -131, -132, -133,
+ -134, -135, -137, -109, 179, -13, -14, -15, -16, -17,
+ -138, -138, -23, -22, -33, -138, -19, -24, -79, -80,
+ -138, -82, -83, -84, -85, -86, -87, -88, -89, -90,
+ -91, -92, -93, -94, -95, -96, -97, -98, -99, -100,
+ -25, -35, -138, -58, -28, -138, -59, -42, -46, -55,
+ -56, -65, -71, -72, -75, -76, -77, -31, -38, -44,
+ -53, -54, -57, -61, -73, -74, -39, -62, -101, -102,
+ -136, -113, -114, -115, -18, -20, -21, -33, -138, -138,
+ -78, -81, -138, -59, -36, -37, -64, -45, -59, -43,
+ -60, -138, -34, -36, -37, -29, -30, -32, -34 ]
+
+racc_goto_table = [
+ 126, 44, 125, 43, 144, 144, 160, 93, 97, 52,
+ 166, 82, 144, 41, 40, 39, 138, 146, 169, 147,
+ 167, 94, 44, 1, 123, 129, 169, 52, 36, 37,
+ 52, 90, 59, 92, 121, 120, 31, 32, 33, 34,
+ 35, 170, 58, 166, 83, 30, 170, 166, 151, nil,
+ 150, nil, 166, 159, 8, 166, 8, nil, nil, nil,
+ nil, 155, nil, 156, 160, nil, nil, 8, 8, 8,
+ 8, 8, nil, 8, 4, nil, 4, 157, nil, nil,
+ 163, nil, 162, 52, nil, 168, nil, 4, 4, 4,
+ 4, 4, nil, 4, nil, nil, nil, nil, 144, nil,
+ nil, nil, 144, nil, nil, 129, 144, 144, nil, 5,
+ 129, 5, nil, nil, nil, nil, 171, 6, nil, 6,
+ nil, nil, 5, 5, 5, 5, 5, 11, 5, 11,
+ 6, 6, 6, 6, 6, 7, 6, 7, nil, nil,
+ 11, 11, 11, 11, 11, nil, 11, nil, 7, 7,
+ 7, 7, 7, nil, 7 ]
+
+racc_goto_check = [
+ 22, 24, 21, 23, 36, 36, 37, 18, 16, 34,
+ 35, 41, 36, 20, 19, 17, 25, 25, 28, 32,
+ 29, 23, 24, 1, 23, 24, 28, 34, 13, 15,
+ 34, 14, 38, 17, 20, 19, 1, 1, 1, 1,
+ 1, 33, 1, 35, 39, 3, 33, 35, 42, nil,
+ 41, nil, 35, 22, 8, 35, 8, nil, nil, nil,
+ nil, 16, nil, 18, 37, nil, nil, 8, 8, 8,
+ 8, 8, nil, 8, 4, nil, 4, 23, nil, nil,
+ 22, nil, 21, 34, nil, 22, nil, 4, 4, 4,
+ 4, 4, nil, 4, nil, nil, nil, nil, 36, nil,
+ nil, nil, 36, nil, nil, 24, 36, 36, nil, 5,
+ 24, 5, nil, nil, nil, nil, 22, 6, nil, 6,
+ nil, nil, 5, 5, 5, 5, 5, 11, 5, 11,
+ 6, 6, 6, 6, 6, 7, 6, 7, nil, nil,
+ 11, 11, 11, 11, 11, nil, 11, nil, 7, 7,
+ 7, 7, 7, nil, 7 ]
+
+racc_goto_pointer = [
+ nil, 23, nil, 43, 74, 109, 117, 135, 54, nil,
+ nil, 127, nil, 10, -5, 11, -30, -3, -29, -4,
+ -5, -40, -42, -15, -17, -28, nil, nil, -120, -107,
+ nil, nil, -33, -101, -9, -116, -40, -91, 12, 17,
+ nil, -9, -13 ]
+
+racc_goto_default = [
+ nil, nil, 2, 3, 46, 47, 48, 49, 50, 9,
+ 10, 51, 12, nil, nil, nil, nil, nil, nil, nil,
+ nil, nil, nil, nil, 140, nil, 45, 127, 139, 128,
+ 141, 130, 142, 143, 132, 131, 134, 98, nil, 28,
+ 27, nil, 60 ]
+
+racc_reduce_table = [
+ 0, 0, :racc_error,
+ 1, 27, :_reduce_none,
+ 2, 28, :_reduce_2,
+ 1, 28, :_reduce_3,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 1, 29, :_reduce_none,
+ 3, 30, :_reduce_13,
+ 3, 31, :_reduce_14,
+ 3, 32, :_reduce_15,
+ 3, 33, :_reduce_16,
+ 3, 34, :_reduce_17,
+ 4, 35, :_reduce_18,
+ 3, 35, :_reduce_19,
+ 2, 40, :_reduce_20,
+ 2, 40, :_reduce_21,
+ 1, 40, :_reduce_22,
+ 1, 40, :_reduce_23,
+ 2, 41, :_reduce_24,
+ 2, 41, :_reduce_25,
+ 1, 41, :_reduce_26,
+ 1, 41, :_reduce_27,
+ 2, 39, :_reduce_none,
+ 4, 39, :_reduce_29,
+ 4, 39, :_reduce_30,
+ 2, 43, :_reduce_31,
+ 4, 43, :_reduce_32,
+ 1, 44, :_reduce_33,
+ 3, 44, :_reduce_34,
+ 1, 45, :_reduce_none,
+ 3, 45, :_reduce_36,
+ 3, 45, :_reduce_37,
+ 2, 46, :_reduce_38,
+ 2, 46, :_reduce_39,
+ 1, 46, :_reduce_40,
+ 1, 46, :_reduce_41,
+ 1, 47, :_reduce_none,
+ 2, 51, :_reduce_43,
+ 1, 51, :_reduce_44,
+ 2, 53, :_reduce_45,
+ 1, 53, :_reduce_46,
+ 1, 50, :_reduce_none,
+ 1, 50, :_reduce_none,
+ 1, 50, :_reduce_none,
+ 1, 50, :_reduce_none,
+ 1, 50, :_reduce_none,
+ 1, 50, :_reduce_none,
+ 1, 54, :_reduce_none,
+ 1, 54, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 55, :_reduce_none,
+ 1, 56, :_reduce_57,
+ 1, 52, :_reduce_58,
+ 1, 57, :_reduce_59,
+ 2, 58, :_reduce_60,
+ 1, 58, :_reduce_none,
+ 2, 49, :_reduce_62,
+ 1, 49, :_reduce_none,
+ 2, 48, :_reduce_64,
+ 1, 48, :_reduce_none,
+ 1, 60, :_reduce_none,
+ 1, 60, :_reduce_none,
+ 1, 60, :_reduce_none,
+ 1, 60, :_reduce_none,
+ 1, 60, :_reduce_none,
+ 1, 62, :_reduce_none,
+ 1, 62, :_reduce_none,
+ 1, 59, :_reduce_none,
+ 1, 59, :_reduce_none,
+ 1, 61, :_reduce_none,
+ 1, 61, :_reduce_none,
+ 1, 61, :_reduce_none,
+ 2, 42, :_reduce_78,
+ 1, 42, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 2, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 1, 63, :_reduce_none,
+ 3, 36, :_reduce_101,
+ 3, 37, :_reduce_102,
+ 1, 65, :_reduce_none,
+ 1, 65, :_reduce_none,
+ 1, 65, :_reduce_none,
+ 1, 65, :_reduce_none,
+ 1, 65, :_reduce_none,
+ 1, 65, :_reduce_none,
+ 2, 66, :_reduce_109,
+ 1, 66, :_reduce_none,
+ 1, 38, :_reduce_111,
+ 1, 67, :_reduce_none,
+ 2, 67, :_reduce_113,
+ 2, 67, :_reduce_114,
+ 2, 67, :_reduce_115,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 1, 68, :_reduce_none,
+ 2, 64, :_reduce_136,
+ 1, 64, :_reduce_none ]
+
+racc_reduce_n = 138
+
+racc_shift_n = 179
+
+racc_token_table = {
+ false => 0,
+ :error => 1,
+ :EX_LOW => 2,
+ :QUOTE => 3,
+ :BAR => 4,
+ :SLASH => 5,
+ :BACK_SLASH => 6,
+ :URL => 7,
+ :OTHER => 8,
+ :REF_OPEN => 9,
+ :FOOTNOTE_OPEN => 10,
+ :FOOTNOTE_CLOSE => 11,
+ :EX_HIGH => 12,
+ :EM_OPEN => 13,
+ :EM_CLOSE => 14,
+ :CODE_OPEN => 15,
+ :CODE_CLOSE => 16,
+ :VAR_OPEN => 17,
+ :VAR_CLOSE => 18,
+ :KBD_OPEN => 19,
+ :KBD_CLOSE => 20,
+ :INDEX_OPEN => 21,
+ :INDEX_CLOSE => 22,
+ :REF_CLOSE => 23,
+ :VERB_OPEN => 24,
+ :VERB_CLOSE => 25 }
+
+racc_nt_base = 26
+
+racc_use_result_var = true
+
+Racc_arg = [
+ racc_action_table,
+ racc_action_check,
+ racc_action_default,
+ racc_action_pointer,
+ racc_goto_table,
+ racc_goto_check,
+ racc_goto_default,
+ racc_goto_pointer,
+ racc_nt_base,
+ racc_reduce_table,
+ racc_token_table,
+ racc_shift_n,
+ racc_reduce_n,
+ racc_use_result_var ]
+
+Racc_token_to_s_table = [
+ "$end",
+ "error",
+ "EX_LOW",
+ "QUOTE",
+ "BAR",
+ "SLASH",
+ "BACK_SLASH",
+ "URL",
+ "OTHER",
+ "REF_OPEN",
+ "FOOTNOTE_OPEN",
+ "FOOTNOTE_CLOSE",
+ "EX_HIGH",
+ "EM_OPEN",
+ "EM_CLOSE",
+ "CODE_OPEN",
+ "CODE_CLOSE",
+ "VAR_OPEN",
+ "VAR_CLOSE",
+ "KBD_OPEN",
+ "KBD_CLOSE",
+ "INDEX_OPEN",
+ "INDEX_CLOSE",
+ "REF_CLOSE",
+ "VERB_OPEN",
+ "VERB_CLOSE",
+ "$start",
+ "content",
+ "elements",
+ "element",
+ "emphasis",
+ "code",
+ "var",
+ "keyboard",
+ "index",
+ "reference",
+ "footnote",
+ "verb",
+ "normal_str_ele",
+ "substitute",
+ "ref_label",
+ "ref_label2",
+ "ref_url_strings",
+ "filename",
+ "element_label",
+ "element_label2",
+ "ref_subst_content",
+ "ref_subst_content_q",
+ "ref_subst_strings_q",
+ "ref_subst_strings_first",
+ "ref_subst_ele2",
+ "ref_subst_eles",
+ "ref_subst_str_ele_first",
+ "ref_subst_eles_q",
+ "ref_subst_ele",
+ "ref_subst_ele_q",
+ "ref_subst_str_ele",
+ "ref_subst_str_ele_q",
+ "ref_subst_strings",
+ "ref_subst_string3",
+ "ref_subst_string",
+ "ref_subst_string_q",
+ "ref_subst_string2",
+ "ref_url_string",
+ "verb_strings",
+ "normal_string",
+ "normal_strings",
+ "verb_string",
+ "verb_normal_string" ]
+
+Racc_debug_parser = false
+
+##### State transition tables end #####
+
+# reduce 0 omitted
+
+# reduce 1 omitted
+
+def _reduce_2(val, _values, result)
+ result.append val[1]
+ result
+end
+
+def _reduce_3(val, _values, result)
+ result = val[0]
+ result
+end
+
+# reduce 4 omitted
+
+# reduce 5 omitted
+
+# reduce 6 omitted
+
+# reduce 7 omitted
+
+# reduce 8 omitted
+
+# reduce 9 omitted
+
+# reduce 10 omitted
+
+# reduce 11 omitted
+
+# reduce 12 omitted
+
+def _reduce_13(val, _values, result)
+ content = val[1]
+ result = inline "<em>#{content}</em>", content
+
+ result
+end
+
+def _reduce_14(val, _values, result)
+ content = val[1]
+ result = inline "<code>#{content}</code>", content
+
+ result
+end
+
+def _reduce_15(val, _values, result)
+ content = val[1]
+ result = inline "+#{content}+", content
+
+ result
+end
+
+def _reduce_16(val, _values, result)
+ content = val[1]
+ result = inline "<tt>#{content}</tt>", content
+
+ result
+end
+
+def _reduce_17(val, _values, result)
+ label = val[1]
+ @block_parser.add_label label.reference
+ result = "<span id=\"label-#{label}\">#{label}</span>"
+
+ result
+end
+
+def _reduce_18(val, _values, result)
+ result = "{#{val[1]}}[#{val[2].join}]"
+
+ result
+end
+
+def _reduce_19(val, _values, result)
+ scheme, inline = val[1]
+
+ result = "{#{inline}}[#{scheme}#{inline.reference}]"
+
+ result
+end
+
+def _reduce_20(val, _values, result)
+ result = [nil, inline(val[1])]
+
+ result
+end
+
+def _reduce_21(val, _values, result)
+ result = [
+ 'rdoc-label:',
+ inline("#{val[0].reference}/#{val[1].reference}")
+ ]
+
+ result
+end
+
+def _reduce_22(val, _values, result)
+ result = ['rdoc-label:', val[0].reference]
+
+ result
+end
+
+def _reduce_23(val, _values, result)
+ result = ['rdoc-label:', "#{val[0].reference}/"]
+
+ result
+end
+
+def _reduce_24(val, _values, result)
+ result = [nil, inline(val[1])]
+
+ result
+end
+
+def _reduce_25(val, _values, result)
+ result = [
+ 'rdoc-label:',
+ inline("#{val[0].reference}/#{val[1].reference}")
+ ]
+
+ result
+end
+
+def _reduce_26(val, _values, result)
+ result = ['rdoc-label:', val[0]]
+
+ result
+end
+
+def _reduce_27(val, _values, result)
+ ref = val[0].reference
+ result = ['rdoc-label:', inline(ref, "#{ref}/")]
+
+ result
+end
+
+# reduce 28 omitted
+
+def _reduce_29(val, _values, result)
+ result = val[1]
+ result
+end
+
+def _reduce_30(val, _values, result)
+ result = val[1]
+ result
+end
+
+def _reduce_31(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+def _reduce_32(val, _values, result)
+ result = inline "\"#{val[1]}\""
+
+ result
+end
+
+def _reduce_33(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+def _reduce_34(val, _values, result)
+ result = inline "\"#{val[1]}\""
+
+ result
+end
+
+# reduce 35 omitted
+
+def _reduce_36(val, _values, result)
+ result = val[1]
+ result
+end
+
+def _reduce_37(val, _values, result)
+ result = inline val[1]
+ result
+end
+
+def _reduce_38(val, _values, result)
+ result = val[0].append val[1]
+
+ result
+end
+
+def _reduce_39(val, _values, result)
+ result = val[0].append val[1]
+
+ result
+end
+
+def _reduce_40(val, _values, result)
+ result = val[0]
+
+ result
+end
+
+def _reduce_41(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+# reduce 42 omitted
+
+def _reduce_43(val, _values, result)
+ result = val[0].append val[1]
+
+ result
+end
+
+def _reduce_44(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+def _reduce_45(val, _values, result)
+ result = val[0].append val[1]
+
+ result
+end
+
+def _reduce_46(val, _values, result)
+ result = val[0]
+
+ result
+end
+
+# reduce 47 omitted
+
+# reduce 48 omitted
+
+# reduce 49 omitted
+
+# reduce 50 omitted
+
+# reduce 51 omitted
+
+# reduce 52 omitted
+
+# reduce 53 omitted
+
+# reduce 54 omitted
+
+# reduce 55 omitted
+
+# reduce 56 omitted
+
+def _reduce_57(val, _values, result)
+ result = val[0]
+
+ result
+end
+
+def _reduce_58(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+def _reduce_59(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+def _reduce_60(val, _values, result)
+ result << val[1]
+ result
+end
+
+# reduce 61 omitted
+
+def _reduce_62(val, _values, result)
+ result << val[1]
+
+ result
+end
+
+# reduce 63 omitted
+
+def _reduce_64(val, _values, result)
+ result << val[1]
+
+ result
+end
+
+# reduce 65 omitted
+
+# reduce 66 omitted
+
+# reduce 67 omitted
+
+# reduce 68 omitted
+
+# reduce 69 omitted
+
+# reduce 70 omitted
+
+# reduce 71 omitted
+
+# reduce 72 omitted
+
+# reduce 73 omitted
+
+# reduce 74 omitted
+
+# reduce 75 omitted
+
+# reduce 76 omitted
+
+# reduce 77 omitted
+
+def _reduce_78(val, _values, result)
+ result << val[1]
+ result
+end
+
+# reduce 79 omitted
+
+# reduce 80 omitted
+
+# reduce 81 omitted
+
+# reduce 82 omitted
+
+# reduce 83 omitted
+
+# reduce 84 omitted
+
+# reduce 85 omitted
+
+# reduce 86 omitted
+
+# reduce 87 omitted
+
+# reduce 88 omitted
+
+# reduce 89 omitted
+
+# reduce 90 omitted
+
+# reduce 91 omitted
+
+# reduce 92 omitted
+
+# reduce 93 omitted
+
+# reduce 94 omitted
+
+# reduce 95 omitted
+
+# reduce 96 omitted
+
+# reduce 97 omitted
+
+# reduce 98 omitted
+
+# reduce 99 omitted
+
+# reduce 100 omitted
+
+def _reduce_101(val, _values, result)
+ index = @block_parser.add_footnote val[1].rdoc
+ result = "{*#{index}}[rdoc-label:foottext-#{index}:footmark-#{index}]"
+
+ result
+end
+
+def _reduce_102(val, _values, result)
+ result = "<tt>#{val[1]}</tt>"
+
+ result
+end
+
+# reduce 103 omitted
+
+# reduce 104 omitted
+
+# reduce 105 omitted
+
+# reduce 106 omitted
+
+# reduce 107 omitted
+
+# reduce 108 omitted
+
+def _reduce_109(val, _values, result)
+ result << val[1]
+ result
+end
+
+# reduce 110 omitted
+
+def _reduce_111(val, _values, result)
+ result = inline val[0]
+
+ result
+end
+
+# reduce 112 omitted
+
+def _reduce_113(val, _values, result)
+ result = val[1]
+ result
+end
+
+def _reduce_114(val, _values, result)
+ result = val[1]
+ result
+end
+
+def _reduce_115(val, _values, result)
+ result = val[1]
+ result
+end
+
+# reduce 116 omitted
+
+# reduce 117 omitted
+
+# reduce 118 omitted
+
+# reduce 119 omitted
+
+# reduce 120 omitted
+
+# reduce 121 omitted
+
+# reduce 122 omitted
+
+# reduce 123 omitted
+
+# reduce 124 omitted
+
+# reduce 125 omitted
+
+# reduce 126 omitted
+
+# reduce 127 omitted
+
+# reduce 128 omitted
+
+# reduce 129 omitted
+
+# reduce 130 omitted
+
+# reduce 131 omitted
+
+# reduce 132 omitted
+
+# reduce 133 omitted
+
+# reduce 134 omitted
+
+# reduce 135 omitted
+
+def _reduce_136(val, _values, result)
+ result << val[1]
+ result
+end
+
+# reduce 137 omitted
+
+def _reduce_none(val, _values, result)
+ val[0]
+end
+
+end # class InlineParser
+
+end
diff --git a/lib/rdoc/rdoc.rb b/lib/rdoc/rdoc.rb
index 95ba9ae8ab..d72e686249 100644
--- a/lib/rdoc/rdoc.rb
+++ b/lib/rdoc/rdoc.rb
@@ -1,53 +1,38 @@
require 'rdoc'
-require 'rdoc/encoding'
-require 'rdoc/parser'
-
-# Simple must come first
-require 'rdoc/parser/simple'
-require 'rdoc/parser/ruby'
-require 'rdoc/parser/c'
-
-require 'rdoc/stats'
-require 'rdoc/options'
-
require 'find'
require 'fileutils'
require 'time'
##
-# Encapsulate the production of rdoc documentation. Basically you can use this
-# as you would invoke rdoc from the command line:
-#
-# rdoc = RDoc::RDoc.new
-# rdoc.document(args)
-#
-# Where +args+ is an array of strings, each corresponding to an argument you'd
-# give rdoc on the command line. See <tt>rdoc --help<tt> for details.
+# This is the driver for generating RDoc output. It handles file parsing and
+# generation of output.
#
-# = Plugins
+# To use this class to generate RDoc output via the API, the recommended way
+# is:
#
-# When you <tt>require 'rdoc/rdoc'</tt> RDoc looks for 'rdoc/discover' files
-# in your installed gems. This can be used to load alternate generators or
-# add additional preprocessor directives.
-#
-# You will want to wrap your plugin loading in an RDoc version check.
-# Something like:
+# rdoc = RDoc::RDoc.new
+# options = rdoc.load_options # returns an RDoc::Options instance
+# # set extra options
+# rdoc.document options
#
-# begin
-# gem 'rdoc', '~> 3'
-# require 'path/to/my/awesome/rdoc/plugin'
-# rescue Gem::LoadError
-# end
+# You can also generate output like the +rdoc+ executable:
#
-# The most obvious plugin type is a new output generator. See RDoc::Generator
-# for details.
+# rdoc = RDoc::RDoc.new
+# rdoc.document argv
#
-# You can also hook into RDoc::Markup to add new directives (:nodoc: is a
-# directive). See RDoc::Markup::PreProcess::register for details.
+# Where +argv+ is an array of strings, each corresponding to an argument you'd
+# give rdoc on the command line. See <tt>rdoc --help<tt> for details.
class RDoc::RDoc
+ @current = nil
+
+ ##
+ # This is the list of supported output generators
+
+ GENERATORS = {}
+
##
# File pattern to exclude
@@ -74,9 +59,9 @@ class RDoc::RDoc
attr_reader :stats
##
- # This is the list of supported output generators
+ # The current documentation store
- GENERATORS = {}
+ attr_reader :store
##
# Add +klass+ that can generate output after parsing
@@ -96,19 +81,11 @@ class RDoc::RDoc
##
# Sets the active RDoc::RDoc instance
- def self.current=(rdoc)
+ def self.current= rdoc
@current = rdoc
end
##
- # Resets all internal state
-
- def self.reset
- RDoc::TopLevel.reset
- RDoc::Parser::C.reset
- end
-
- ##
# Creates a new RDoc::RDoc instance. Call #document to parse files and
# generate documentation.
@@ -120,6 +97,7 @@ class RDoc::RDoc
@old_siginfo = nil
@options = nil
@stats = nil
+ @store = nil
end
##
@@ -141,15 +119,21 @@ class RDoc::RDoc
file_list = file_list.uniq
file_list = remove_unparseable file_list
+
+ file_list.sort
end
##
# Turns RDoc from stdin into HTML
def handle_pipe
- @html = RDoc::Markup::ToHtml.new
+ @html = RDoc::Markup::ToHtml.new @options
+
+ parser = RDoc::Text::MARKUP_FORMAT[@options.markup]
- out = @html.convert $stdin.read
+ document = parser.parse $stdin.read
+
+ out = @html.convert document
$stdout.write out
end
@@ -166,6 +150,33 @@ class RDoc::RDoc
end
##
+ # Loads options from .rdoc_options if the file exists, otherwise creates a
+ # new RDoc::Options instance.
+
+ def load_options
+ options_file = File.expand_path '.rdoc_options'
+ return RDoc::Options.new unless File.exist? options_file
+
+ RDoc.load_yaml
+
+ parse_error = if Object.const_defined? :Psych then
+ Psych::SyntaxError
+ else
+ ArgumentError
+ end
+
+ begin
+ options = YAML.load_file '.rdoc_options'
+ rescue *parse_error
+ end
+
+ raise RDoc::Error, "#{options_file} is not a valid rdoc options file" unless
+ RDoc::Options === options
+
+ options
+ end
+
+ ##
# Create an output dir if it doesn't exist. If it does exist, but doesn't
# contain the flag file <tt>created.rid</tt> then we refuse to use it, as
# we may clobber some manually generated documentation
@@ -212,6 +223,15 @@ option)
end
##
+ # Sets the current documentation tree to +store+ and sets the store's rdoc
+ # driver to this instance.
+
+ def store= store
+ @store = store
+ @store.rdoc = self
+ end
+
+ ##
# Update the flag file in an output directory.
def update_output_dir(op_dir, time, last = {})
@@ -291,7 +311,7 @@ option)
file_list << list_files_in_directory(rel_file_name)
end
else
- raise RDoc::Error, "I can't deal with a #{type} #{rel_file_name}"
+ warn "rdoc can't parse the #{type} #{rel_file_name}"
end
end
@@ -325,7 +345,7 @@ option)
return unless content
- top_level = RDoc::TopLevel.new filename
+ top_level = @store.add_file filename
parser = RDoc::Parser.for top_level, filename, content, @options, @stats
@@ -340,6 +360,14 @@ option)
top_level
+ rescue Errno::EACCES => e
+ $stderr.puts <<-EOF
+Unable to read #{filename}, #{e.message}
+
+Please check the permissions for this file. Perhaps you do not have access to
+it or perhaps the original author's permissions are to restrictive. If the
+this is not your library please report a bug to the author.
+ EOF
rescue => e
$stderr.puts <<-EOF
Before reporting this, could you check that the file you're documenting
@@ -366,7 +394,7 @@ The internal error was:
def parse_files files
file_list = gather_files files
- @stats = RDoc::Stats.new file_list.size, @options.verbosity
+ @stats = RDoc::Stats.new @store, file_list.length, @options.verbosity
return [] if file_list.empty?
@@ -385,11 +413,16 @@ The internal error was:
end
##
- # Removes file extensions known to be unparseable from +files+
+ # Removes file extensions known to be unparseable from +files+ and TAGS
+ # files for emacs and vim.
def remove_unparseable files
files.reject do |file|
- file =~ /\.(?:class|eps|erb|scpt\.txt|ttf|yml)$/i
+ file =~ /\.(?:class|eps|erb|scpt\.txt|ttf|yml)$/i or
+ (file =~ /tags$/i and
+ open(file, 'rb') { |io|
+ io.read(100) =~ /\A(\f\n[^,]+,\d+$|!_TAG_)/
+ })
end
end
@@ -408,13 +441,13 @@ The internal error was:
# current directory, so make sure you're somewhere writable before invoking.
def document options
- RDoc::RDoc.reset
+ self.store = RDoc::Store.new
if RDoc::Options === options then
@options = options
@options.finish
else
- @options = RDoc::Options.new
+ @options = load_options
@options.parse options
end
@@ -429,13 +462,18 @@ The internal error was:
@last_modified = setup_output_dir @options.op_dir, @options.force_update
end
+ @store.encoding = @options.encoding if @options.respond_to? :encoding
+ @store.dry_run = @options.dry_run
+ @store.main = @options.main_page
+ @store.title = @options.title
+
@start_time = Time.now
file_info = parse_files @options.files
@options.default_title = "RDoc Documentation"
- RDoc::TopLevel.complete @options.visibility
+ @store.complete @options.visibility
@stats.coverage_level = @options.coverage_report
@@ -448,9 +486,9 @@ The internal error was:
else
gen_klass = @options.generator
- @generator = gen_klass.new @options
+ @generator = gen_klass.new @store, @options
- generate file_info
+ generate
end
if @stats and (@options.coverage_report or not @options.quiet) then
@@ -466,20 +504,14 @@ The internal error was:
# output dir using the generator selected
# by the RDoc options
- def generate file_info
+ def generate
Dir.chdir @options.op_dir do
- begin
- self.class.current = self
-
- unless @options.quiet then
- $stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..."
- end
-
- @generator.generate file_info
- update_output_dir '.', @start_time, @last_modified
- ensure
- self.class.current = nil
+ unless @options.quiet then
+ $stderr.puts "\nGenerating #{@generator.class.name.sub(/^.*::/, '')} format into #{Dir.pwd}..."
end
+
+ @generator.generate
+ update_output_dir '.', @start_time, @last_modified
end
end
diff --git a/lib/rdoc/require.rb b/lib/rdoc/require.rb
index 65d3d464da..a3d4bd18c0 100644
--- a/lib/rdoc/require.rb
+++ b/lib/rdoc/require.rb
@@ -1,5 +1,3 @@
-require 'rdoc/code_object'
-
##
# A file loaded by \#require
diff --git a/lib/rdoc/ri.rb b/lib/rdoc/ri.rb
index 17da3fbe83..8b35e0fa2f 100644
--- a/lib/rdoc/ri.rb
+++ b/lib/rdoc/ri.rb
@@ -12,7 +12,9 @@ module RDoc::RI
class Error < RDoc::Error; end
-end
+ autoload :Driver, 'rdoc/ri/driver'
+ autoload :Paths, 'rdoc/ri/paths'
+ autoload :Store, 'rdoc/ri/store'
-require 'rdoc/ri/store'
+end
diff --git a/lib/rdoc/ri/driver.rb b/lib/rdoc/ri/driver.rb
index 26304dca96..4beda55881 100644
--- a/lib/rdoc/ri/driver.rb
+++ b/lib/rdoc/ri/driver.rb
@@ -11,11 +11,7 @@ begin
rescue LoadError
end
-require 'rdoc/ri'
-require 'rdoc/ri/paths'
-require 'rdoc/markup'
-require 'rdoc/markup/formatter'
-require 'rdoc/text'
+require 'rdoc'
##
# For RubyGems backwards compatibility
@@ -61,6 +57,11 @@ class RDoc::RI::Driver
end
##
+ # Show all method documentation following a class or module
+
+ attr_accessor :show_all
+
+ ##
# An RDoc::RI::Store for each entry in the RI path
attr_accessor :stores
@@ -75,17 +76,18 @@ class RDoc::RI::Driver
def self.default_options
options = {}
- options[:use_stdout] = !$stdout.tty?
- options[:width] = 72
options[:interactive] = false
- options[:use_cache] = true
- options[:profile] = false
+ options[:profile] = false
+ options[:show_all] = false
+ options[:use_cache] = true
+ options[:use_stdout] = !$stdout.tty?
+ options[:width] = 72
# By default all standard paths are used.
- options[:use_system] = true
- options[:use_site] = true
- options[:use_home] = true
- options[:use_gems] = true
+ options[:use_system] = true
+ options[:use_site] = true
+ options[:use_home] = true
+ options[:use_gems] = true
options[:extra_doc_dirs] = []
return options
@@ -123,7 +125,11 @@ Usage: #{opt.program_name} [options] [names...]
Where name can be:
- Class | Class::method | Class#method | Class.method | method
+ Class | Module | Module::Class
+
+ Class::method | Class#method | Class.method | method
+
+ gem_name: | gem_name:README | gem_name:History
All class names may be abbreviated to their minimum unambiguous form. If a name
is ambiguous, all valid options will be listed.
@@ -131,12 +137,18 @@ is ambiguous, all valid options will be listed.
A '.' matches either class or instance methods, while #method
matches only instance and ::method matches only class methods.
+README and other files may be displayed by prefixing them with the gem name
+they're contained in. If the gem name is followed by a ':' all files in the
+gem will be shown. The file name extension may be omitted where it is
+unambiguous.
+
For example:
#{opt.program_name} Fil
#{opt.program_name} File
#{opt.program_name} File.new
#{opt.program_name} zip
+ #{opt.program_name} rdoc:README
Note that shell quoting or escaping may be required for method names containing
punctuation:
@@ -151,7 +163,10 @@ To see the default directories ri will search, run:
Specifying the --system, --site, --home, --gems or --doc-dir options will
limit ri to searching only the specified directories.
-Options may also be set in the 'RI' environment variable.
+ri options may be set in the 'RI' environment variable.
+
+The ri pager can be set with the 'RI_PAGER' environment variable or the
+'PAGER' environment variable.
EOT
opt.separator nil
@@ -159,64 +174,74 @@ Options may also be set in the 'RI' environment variable.
opt.separator nil
- formatters = RDoc::Markup.constants.grep(/^To[A-Z][a-z]+$/).sort
- formatters = formatters.sort.map do |formatter|
- formatter.to_s.sub('To', '').downcase
+ opt.on("--[no-]interactive", "-i",
+ "In interactive mode you can repeatedly",
+ "look up methods with autocomplete.") do |interactive|
+ options[:interactive] = interactive
end
- opt.on("--format=NAME", "-f",
- "Uses the selected formatter. The default",
- "formatter is bs for paged output and ansi",
- "otherwise. Valid formatters are:",
- formatters.join(' '), formatters) do |value|
- options[:formatter] = RDoc::Markup.const_get "To#{value.capitalize}"
+ opt.separator nil
+
+ opt.on("--[no-]all", "-a",
+ "Show all documentation for a class or",
+ "module.") do |show_all|
+ options[:show_all] = show_all
end
opt.separator nil
- opt.on("--no-pager", "-T",
- "Send output directly to stdout,",
- "rather than to a pager.") do
- options[:use_stdout] = true
+ opt.on("--[no-]list", "-l",
+ "List classes ri knows about.") do |list|
+ options[:list] = list
end
opt.separator nil
- opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger,
- "Set the width of the output.") do |value|
- options[:width] = value
+ opt.on("--[no-]pager", "-T",
+ "Send output directly to stdout,",
+ "rather than to a pager.") do |use_pager|
+ options[:use_stdout] = !use_pager
end
opt.separator nil
- opt.on("--interactive", "-i",
- "In interactive mode you can repeatedly",
- "look up methods with autocomplete.") do
- options[:interactive] = true
+ opt.on("--width=WIDTH", "-w", OptionParser::DecimalInteger,
+ "Set the width of the output.") do |width|
+ options[:width] = width
end
opt.separator nil
- opt.on("--list", "-l",
- "List classes ri knows about.") do
- options[:list] = true
+ opt.on("--server [PORT]", Integer,
+ "Run RDoc server on the given port.",
+ "The default port is 8214.") do |port|
+ options[:server] = port || 8214
end
opt.separator nil
- opt.on("--[no-]profile",
- "Run with the ruby profiler") do |value|
- options[:profile] = value
+ formatters = RDoc::Markup.constants.grep(/^To[A-Z][a-z]+$/).sort
+ formatters = formatters.sort.map do |formatter|
+ formatter.to_s.sub('To', '').downcase
+ end
+ formatters -= %w[html label test] # remove useless output formats
+
+ opt.on("--format=NAME", "-f",
+ "Uses the selected formatter. The default",
+ "formatter is bs for paged output and ansi",
+ "otherwise. Valid formatters are:",
+ formatters.join(' '), formatters) do |value|
+ options[:formatter] = RDoc::Markup.const_get "To#{value.capitalize}"
end
opt.separator nil
opt.separator "Data source options:"
opt.separator nil
- opt.on("--list-doc-dirs",
+ opt.on("--[no-]list-doc-dirs",
"List the directories from which ri will",
- "source documentation on stdout and exit.") do
- options[:list_doc_dirs] = true
+ "source documentation on stdout and exit.") do |list_doc_dirs|
+ options[:list_doc_dirs] = list_doc_dirs
end
opt.separator nil
@@ -284,6 +309,13 @@ Options may also be set in the 'RI' environment variable.
opt.separator "Debug options:"
opt.separator nil
+ opt.on("--[no-]profile",
+ "Run with the ruby profiler") do |value|
+ options[:profile] = value
+ end
+
+ opt.separator nil
+
opt.on("--dump=CACHE", File,
"Dumps data from an ri cache or data file") do |value|
options[:dump_path] = value
@@ -356,7 +388,12 @@ Options may also be set in the 'RI' environment variable.
@list_doc_dirs = options[:list_doc_dirs]
@interactive = options[:interactive]
+ @server = options[:server]
@use_stdout = options[:use_stdout]
+ @show_all = options[:show_all]
+
+ # pager process for jruby
+ @jruby_pager_process = nil
end
##
@@ -404,15 +441,23 @@ Options may also be set in the 'RI' environment variable.
end
##
- # Adds +includes+ to +out+
+ # Adds +extends+ to +out+
- def add_includes out, includes
- return if includes.empty?
+ def add_extends out, extends
+ add_extension_modules out, 'Extended by', extends
+ end
+
+ ##
+ # Adds a list of +extensions+ to this module of the given +type+ to +out+.
+ # add_includes and add_extends call this, so you should use those directly.
+
+ def add_extension_modules out, type, extensions
+ return if extensions.empty?
out << RDoc::Markup::Rule.new(1)
- out << RDoc::Markup::Heading.new(1, "Includes:")
+ out << RDoc::Markup::Heading.new(1, "#{type}:")
- includes.each do |modules, store|
+ extensions.each do |modules, store|
if modules.length == 1 then
include = modules.first
name = include.name
@@ -450,6 +495,37 @@ Options may also be set in the 'RI' environment variable.
end
##
+ # Adds +includes+ to +out+
+
+ def add_includes out, includes
+ add_extension_modules out, 'Includes', includes
+ end
+
+ ##
+ # Looks up the method +name+ and adds it to +out+
+
+ def add_method out, name
+ filtered = lookup_method name
+
+ method_out = method_document name, filtered
+
+ out.concat method_out.parts
+ end
+
+ ##
+ # Adds documentation for all methods in +klass+ to +out+
+
+ def add_method_documentation out, klass
+ klass.method_list.each do |method|
+ begin
+ add_method out, method.full_name
+ rescue NotFoundError
+ next
+ end
+ end
+ end
+
+ ##
# Adds a list of +methods+ to +out+ with a heading of +name+
def add_method_list out, methods, name
@@ -458,10 +534,10 @@ Options may also be set in the 'RI' environment variable.
out << RDoc::Markup::Heading.new(1, "#{name}:")
out << RDoc::Markup::BlankLine.new
- if @use_stdout and !@interactive
- out.push(*methods.map do |method|
+ if @use_stdout and !@interactive then
+ out.concat methods.map { |method|
RDoc::Markup::Verbatim.new method
- end)
+ }
else
out << RDoc::Markup::IndentedParagraph.new(2, methods.join(', '))
end
@@ -493,8 +569,8 @@ Options may also be set in the 'RI' environment variable.
klasses = klasses - seen
- ancestors.push(*klasses)
- unexamined.push(*klasses)
+ ancestors.concat klasses
+ unexamined.concat klasses
end
ancestors.reverse
@@ -509,7 +585,7 @@ Options may also be set in the 'RI' environment variable.
##
# Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+
- def class_document name, found, klasses, includes
+ def class_document name, found, klasses, includes, extends
also_in = []
out = RDoc::Markup::Document.new
@@ -517,6 +593,7 @@ Options may also be set in the 'RI' environment variable.
add_class out, name, klasses
add_includes out, includes
+ add_extends out, extends
found.each do |store, klass|
comment = klass.comment
@@ -542,7 +619,7 @@ Options may also be set in the 'RI' environment variable.
parts.flatten!
parts.pop
- out.push(*parts)
+ out.concat parts
else
out << comment
end
@@ -559,13 +636,13 @@ Options may also be set in the 'RI' environment variable.
constants = klass.constants.sort_by { |constant| constant.name }
- list.push(*constants.map do |constant|
+ list.items.concat constants.map { |constant|
parts = constant.comment.parts if constant.comment
parts << RDoc::Markup::Paragraph.new('[not documented]') if
parts.empty?
RDoc::Markup::ListItem.new(constant.name, *parts)
- end)
+ }
out << list
out << RDoc::Markup::BlankLine.new
@@ -574,6 +651,8 @@ Options may also be set in the 'RI' environment variable.
add_method_list out, class_methods, 'Class methods'
add_method_list out, instance_methods, 'Instance methods'
add_method_list out, attributes, 'Attributes'
+
+ add_method_documentation out, klass if @show_all
end
add_also_in out, also_in
@@ -601,26 +680,29 @@ Options may also be set in the 'RI' environment variable.
end
##
- # Returns the stores wherin +name+ is found along with the classes and
- # includes that match it
+ # Returns the stores wherein +name+ is found along with the classes,
+ # extends and includes that match it
- def classes_and_includes_for name
+ def classes_and_includes_and_extends_for name
klasses = []
+ extends = []
includes = []
found = @stores.map do |store|
begin
klass = store.load_class name
klasses << klass
+ extends << [klass.extends, store] if klass.extends
includes << [klass.includes, store] if klass.includes
[store, klass]
- rescue Errno::ENOENT
+ rescue RDoc::Store::MissingFileError
end
end.compact
+ extends.reject! do |modules,| modules.empty? end
includes.reject! do |modules,| modules.empty? end
- [found, klasses, includes]
+ [found, klasses, includes, extends]
end
##
@@ -659,7 +741,7 @@ Options may also be set in the 'RI' environment variable.
completions << "#{klass}#{selector}"
end
- completions.push(*methods)
+ completions.concat methods
end
completions.sort.uniq
@@ -682,11 +764,12 @@ Options may also be set in the 'RI' environment variable.
def display_class name
return if name =~ /#|\./
- found, klasses, includes = classes_and_includes_for name
+ found, klasses, includes, extends =
+ classes_and_includes_and_extends_for name
return if found.empty?
- out = class_document name, found, klasses, includes
+ out = class_document name, found, klasses, includes, extends
display out
end
@@ -695,13 +778,9 @@ Options may also be set in the 'RI' environment variable.
# Outputs formatted RI data for method +name+
def display_method name
- found = load_methods_matching name
-
- raise NotFoundError, name if found.empty?
-
- filtered = filter_methods found, name
+ out = RDoc::Markup::Document.new
- out = method_document name, filtered
+ add_method out, name
display out
end
@@ -713,6 +792,11 @@ Options may also be set in the 'RI' environment variable.
# be guessed, raises an error if +name+ couldn't be guessed.
def display_name name
+ if name =~ /\w:(\w|$)/ then
+ display_page name
+ return true
+ end
+
return true if display_class name
display_method name if name =~ /::|#|\./
@@ -727,7 +811,7 @@ Options may also be set in the 'RI' environment variable.
page do |io|
io.puts "#{name} not found, maybe you meant:"
io.puts
- io.puts matches.join("\n")
+ io.puts matches.sort.join("\n")
end
false
@@ -745,6 +829,61 @@ Options may also be set in the 'RI' environment variable.
end
##
+ # Outputs formatted RI data for page +name+.
+
+ def display_page name
+ store_name, page_name = name.split ':', 2
+
+ store = @stores.find { |s| s.source == store_name }
+
+ return display_page_list store if page_name.empty?
+
+ pages = store.cache[:pages]
+
+ unless pages.include? page_name then
+ found_names = pages.select do |n|
+ n =~ /^#{Regexp.escape page_name}\.[^.]+$/
+ end
+
+ if found_names.length > 1 then
+ return display_page_list store, found_names, page_name
+ end
+
+ page_name = found_names.first
+ end
+
+ page = store.load_page page_name
+
+ display page.comment
+ end
+
+ ##
+ # Outputs a formatted RI page list for the pages in +store+.
+
+ def display_page_list store, pages = store.cache[:pages], search = nil
+ out = RDoc::Markup::Document.new
+
+ title = if search then
+ "#{search} pages"
+ else
+ 'Pages'
+ end
+
+ out << RDoc::Markup::Heading.new(1, "#{title} in #{store.friendly_path}")
+ out << RDoc::Markup::BlankLine.new
+
+ list = RDoc::Markup::List.new(:BULLET)
+
+ pages.each do |page|
+ list << RDoc::Markup::Paragraph.new(page)
+ end
+
+ out << list
+
+ display out
+ end
+
+ ##
# Expands abbreviated klass +klass+ into a fully-qualified class. "Zl::Da"
# will be expanded to Zlib::DataError.
@@ -776,7 +915,12 @@ Options may also be set in the 'RI' environment variable.
return [selector, method].join if klass.empty?
- "#{expand_class klass}#{selector}#{method}"
+ case selector
+ when ':' then
+ [find_store(klass), selector, method]
+ else
+ [expand_class(klass), selector, method]
+ end.join
end
##
@@ -841,6 +985,55 @@ Options may also be set in the 'RI' environment variable.
end
##
+ # Finds the given +pager+ for jruby. Returns an IO if +pager+ was found.
+ #
+ # Returns false if +pager+ does not exist.
+ #
+ # Returns nil if the jruby JVM doesn't support ProcessBuilder redirection
+ # (1.6 and older).
+
+ def find_pager_jruby pager
+ require 'java'
+ require 'shellwords'
+
+ return nil unless java.lang.ProcessBuilder.constants.include? :Redirect
+
+ pager = Shellwords.split pager
+
+ pb = java.lang.ProcessBuilder.new(*pager)
+ pb = pb.redirect_output java.lang.ProcessBuilder::Redirect::INHERIT
+
+ @jruby_pager_process = pb.start
+
+ input = @jruby_pager_process.output_stream
+
+ io = input.to_io
+ io.sync = true
+ io
+ rescue java.io.IOException
+ false
+ end
+
+ ##
+ # Finds a store that matches +name+ which can be the name of a gem, "ruby",
+ # "home" or "site".
+ #
+ # See also RDoc::Store#source
+
+ def find_store name
+ @stores.each do |store|
+ source = store.source
+
+ return source if source == name
+
+ return source if
+ store.type == :gem and source =~ /^#{Regexp.escape name}-\d/
+ end
+
+ raise RDoc::RI::Driver::NotFoundError, name
+ end
+
+ ##
# Creates a new RDoc::Markup::Formatter. If a formatter is given with -f,
# use it. If we're outputting to a pager, use bs, otherwise ansi.
@@ -909,7 +1102,7 @@ Options may also be set in the 'RI' environment variable.
classes = []
stores.each do |store|
- classes << store.modules
+ classes << store.module_names
end
classes = classes.flatten.uniq.sort
@@ -951,7 +1144,7 @@ Options may also be set in the 'RI' environment variable.
"#{klass}##{match}"
end
- found.push(*matches)
+ found.concat matches
end
end
@@ -965,7 +1158,7 @@ Options may also be set in the 'RI' environment variable.
"#{klass}::#{match}"
end
- found.push(*matches)
+ found.concat matches
end
end
@@ -1012,7 +1205,18 @@ Options may also be set in the 'RI' environment variable.
end
##
- # Builds a RDoc::Markup::Document from +found+, +klasess+ and +includes+
+ # Returns a filtered list of methods matching +name+
+
+ def lookup_method name
+ found = load_methods_matching name
+
+ raise NotFoundError, name if found.empty?
+
+ filter_methods found, name
+ end
+
+ ##
+ # Builds a RDoc::Markup::Document from +found+, +klasses+ and +includes+
def method_document name, filtered
out = RDoc::Markup::Document.new
@@ -1027,6 +1231,7 @@ Options may also be set in the 'RI' environment variable.
unless name =~ /^#{Regexp.escape method.parent_name}/ then
out << RDoc::Markup::Heading.new(3, "Implementation from #{method.parent_name}")
end
+
out << RDoc::Markup::Rule.new(1)
if method.arglists then
@@ -1036,6 +1241,12 @@ Options may also be set in the 'RI' environment variable.
out << RDoc::Markup::Rule.new(1)
end
+ if method.respond_to?(:superclass_method) and method.superclass_method
+ out << RDoc::Markup::BlankLine.new
+ out << RDoc::Markup::Heading.new(4, "(Uses superclass method #{method.superclass_method})")
+ out << RDoc::Markup::Rule.new(1)
+ end
+
out << RDoc::Markup::BlankLine.new
out << method.comment
out << RDoc::Markup::BlankLine.new
@@ -1080,6 +1291,7 @@ Options may also be set in the 'RI' environment variable.
yield pager
ensure
pager.close
+ @jruby_pager_process.wait_for if @jruby_pager_process
end
else
yield $stdout
@@ -1101,10 +1313,10 @@ Options may also be set in the 'RI' environment variable.
# Foo::Bar#baz.
#
# NOTE: Given Foo::Bar, Bar is considered a class even though it may be a
- # method
+ # method
def parse_name name
- parts = name.split(/(::|#|\.)/)
+ parts = name.split(/(::?|#|\.)/)
if parts.length == 1 then
if parts.first =~ /^[a-z]|^([%&*+\/<>^`|~-]|\+@|-@|<<|<=>?|===?|=>|=~|>>|\[\]=?|~@)$/ then
@@ -1135,6 +1347,8 @@ Options may also be set in the 'RI' environment variable.
puts @doc_dirs
elsif @list then
list_known_classes @names
+ elsif @server then
+ start_server
elsif @interactive or @names.empty? then
interactive
else
@@ -1151,6 +1365,8 @@ Options may also be set in the 'RI' environment variable.
def setup_pager
return if @use_stdout
+ jruby = Object.const_defined?(:RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
+
pagers = [ENV['RI_PAGER'], ENV['PAGER'], 'pager', 'less', 'more']
pagers.compact.uniq.each do |pager|
@@ -1160,9 +1376,17 @@ Options may also be set in the 'RI' environment variable.
next unless in_path? pager_cmd
- io = IO.popen(pager, 'w') rescue next
+ if jruby then
+ case io = find_pager_jruby(pager)
+ when nil then break
+ when false then next
+ else io
+ end
+ else
+ io = IO.popen(pager, 'w') rescue next
+ end
- next if $? and $?.exited? # pager didn't work
+ next if $? and $?.pid == io.pid and $?.exited? # pager didn't work
@paging = true
@@ -1174,5 +1398,21 @@ Options may also be set in the 'RI' environment variable.
nil
end
+ ##
+ # Starts a WEBrick server for ri.
+
+ def start_server
+ require 'webrick'
+
+ server = WEBrick::HTTPServer.new :Port => @server
+
+ server.mount '/', RDoc::Servlet
+
+ trap 'INT' do server.shutdown end
+ trap 'TERM' do server.shutdown end
+
+ server.start
+ end
+
end
diff --git a/lib/rdoc/ri/paths.rb b/lib/rdoc/ri/paths.rb
index a3c65bf928..d7ea285eaa 100644
--- a/lib/rdoc/ri/paths.rb
+++ b/lib/rdoc/ri/paths.rb
@@ -1,7 +1,8 @@
require 'rdoc/ri'
##
-# The directories where ri data lives.
+# The directories where ri data lives. Paths can be enumerated via ::each, or
+# queried individually via ::system_dir, ::site_dir, ::home_dir and ::gem_dir.
module RDoc::RI::Paths
@@ -10,15 +11,12 @@ module RDoc::RI::Paths
version = RbConfig::CONFIG['ruby_version']
- base = if RbConfig::CONFIG.key? 'ridir' then
+ BASE = if RbConfig::CONFIG.key? 'ridir' then
File.join RbConfig::CONFIG['ridir'], version
else
File.join RbConfig::CONFIG['datadir'], 'ri', version
end
- SYSDIR = File.join base, "system"
- SITEDIR = File.join base, "site"
-
homedir = begin
File.expand_path('~')
rescue ArgumentError
@@ -32,8 +30,6 @@ module RDoc::RI::Paths
end
#:startdoc:
- @gemdirs = nil
-
##
# Iterates over each selected path yielding the directory and type.
#
@@ -47,16 +43,19 @@ module RDoc::RI::Paths
# :extra:: ri data directory from the command line. Yielded for each
# entry in +extra_dirs+
- def self.each system, site, home, gems, *extra_dirs # :yields: directory, type
+ def self.each system = true, site = true, home = true, gems = :latest, *extra_dirs # :yields: directory, type
+ return enum_for __method__, system, site, home, gems, *extra_dirs unless
+ block_given?
+
extra_dirs.each do |dir|
yield dir, :extra
end
- yield SYSDIR, :system if system
- yield SITEDIR, :site if site
- yield HOMEDIR, :home if home and HOMEDIR
+ yield system_dir, :system if system
+ yield site_dir, :site if site
+ yield home_dir, :home if home and HOMEDIR
- gemdirs.each do |dir|
+ gemdirs(gems).each do |dir|
yield dir, :gem
end if gems
@@ -64,36 +63,72 @@ module RDoc::RI::Paths
end
##
- # The latest installed gems' ri directories
+ # The ri directory for the gem with +gem_name+.
- def self.gemdirs
- return @gemdirs if @gemdirs
+ def self.gem_dir name, version
+ req = Gem::Requirement.new "= #{version}"
- require 'rubygems' unless defined?(Gem)
+ spec = Gem::Specification.find_by_name name, req
- # HACK dup'd from Gem.latest_partials and friends
- all_paths = []
+ File.join spec.doc_dir, 'ri'
+ end
- all_paths = Gem.path.map do |dir|
- Dir[File.join(dir, 'doc', '*', 'ri')]
- end.flatten
+ ##
+ # The latest installed gems' ri directories. +filter+ can be :all or
+ # :latest.
+ #
+ # A +filter+ :all includes all versions of gems and includes gems without
+ # ri documentation.
+
+ def self.gemdirs filter = :latest
+ require 'rubygems' unless defined?(Gem)
ri_paths = {}
- all_paths.each do |dir|
- base = File.basename File.dirname(dir)
- if base =~ /(.*)-((\d+\.)*\d+)/ then
- name, version = $1, $2
- ver = Gem::Version.new version
- if ri_paths[name].nil? or ver > ri_paths[name][0] then
- ri_paths[name] = [ver, dir]
+ all = Gem::Specification.map do |spec|
+ [File.join(spec.doc_dir, 'ri'), spec.name, spec.version]
+ end
+
+ if filter == :all then
+ gemdirs = []
+
+ all.group_by do |_, name, _|
+ name
+ end.sort_by do |group, _|
+ group
+ end.map do |group, items|
+ items.sort_by do |_, _, version|
+ version
+ end.reverse_each do |dir,|
+ gemdirs << dir
end
end
+
+ return gemdirs
+ end
+
+ all.each do |dir, name, ver|
+ next unless File.exist? dir
+
+ if ri_paths[name].nil? or ver > ri_paths[name].first then
+ ri_paths[name] = [ver, name, dir]
+ end
end
- @gemdirs = ri_paths.map { |k,v| v.last }.sort
+ ri_paths.sort_by { |_, (_, name, _)| name }.map { |k, v| v.last }
rescue LoadError
- @gemdirs = []
+ []
+ end
+
+ ##
+ # The location of the rdoc data in the user's home directory.
+ #
+ # Like ::system, ri data in the user's home directory is rare and predates
+ # libraries distributed via RubyGems. ri data is rarely generated into this
+ # directory.
+
+ def self.home_dir
+ HOMEDIR
end
##
@@ -102,7 +137,7 @@ module RDoc::RI::Paths
#
# See also ::each
- def self.path(system, site, home, gems, *extra_dirs)
+ def self.path(system = true, site = true, home = true, gems = :latest, *extra_dirs)
path = raw_path system, site, home, gems, *extra_dirs
path.select { |directory| File.directory? directory }
@@ -124,5 +159,29 @@ module RDoc::RI::Paths
path.compact
end
+ ##
+ # The location of ri data installed into the site dir.
+ #
+ # Historically this was available for documentation installed by ruby
+ # libraries predating RubyGems. It is unlikely to contain any content for
+ # modern ruby installations.
+
+ def self.site_dir
+ File.join BASE, 'site'
+ end
+
+ ##
+ # The location of the built-in ri data.
+ #
+ # This data is built automatically when `make` is run when ruby is
+ # installed. If you did not install ruby by hand you may need to install
+ # the documentation yourself. Please consult the documentation for your
+ # package manager or ruby installer for details. You can also use the
+ # rdoc-data gem to install system ri data for common versions of ruby.
+
+ def self.system_dir
+ File.join BASE, 'system'
+ end
+
end
diff --git a/lib/rdoc/ri/store.rb b/lib/rdoc/ri/store.rb
index fe4ccc244d..9fa9bbb03c 100644
--- a/lib/rdoc/ri/store.rb
+++ b/lib/rdoc/ri/store.rb
@@ -1,358 +1,6 @@
-require 'rdoc/code_objects'
-require 'fileutils'
+module RDoc::RI
-##
-# A set of ri data.
-#
-# The store manages reading and writing ri data for a project (gem, path,
-# etc.) and maintains a cache of methods, classes and ancestors in the
-# store.
-#
-# The store maintains a #cache of its contents for faster lookup. After
-# adding items to the store it must be flushed using #save_cache. The cache
-# contains the following structures:
-#
-# @cache = {
-# :class_methods => {}, # class name => class methods
-# :instance_methods => {}, # class name => instance methods
-# :attributes => {}, # class name => attributes
-# :modules => [], # classes and modules in this store
-# :ancestors => {}, # class name => ancestor names
-# }
-#--
-# TODO need to store the list of files and prune classes
-
-class RDoc::RI::Store
-
- ##
- # If true this Store will not write any files
-
- attr_accessor :dry_run
-
- ##
- # Path this store reads or writes
-
- attr_accessor :path
-
- ##
- # Type of ri datastore this was loaded from. See RDoc::RI::Driver,
- # RDoc::RI::Paths.
-
- attr_accessor :type
-
- ##
- # The contents of the Store
-
- attr_reader :cache
-
- ##
- # The encoding of the contents in the Store
-
- attr_accessor :encoding
-
- ##
- # Creates a new Store of +type+ that will load or save to +path+
-
- def initialize path, type = nil
- @dry_run = false
- @type = type
- @path = path
- @encoding = nil
-
- @cache = {
- :ancestors => {},
- :attributes => {},
- :class_methods => {},
- :encoding => @encoding,
- :instance_methods => {},
- :modules => [],
- }
- end
-
- ##
- # Ancestors cache accessor. Maps a klass name to an Array of its ancestors
- # in this store. If Foo in this store inherits from Object, Kernel won't be
- # listed (it will be included from ruby's ri store).
-
- def ancestors
- @cache[:ancestors]
- end
-
- ##
- # Attributes cache accessor. Maps a class to an Array of its attributes.
-
- def attributes
- @cache[:attributes]
- end
-
- ##
- # Path to the cache file
-
- def cache_path
- File.join @path, 'cache.ri'
- end
-
- ##
- # Path to the ri data for +klass_name+
-
- def class_file klass_name
- name = klass_name.split('::').last
- File.join class_path(klass_name), "cdesc-#{name}.ri"
- end
-
- ##
- # Class methods cache accessor. Maps a class to an Array of its class
- # methods (not full name).
-
- def class_methods
- @cache[:class_methods]
- end
-
- ##
- # Path where data for +klass_name+ will be stored (methods or class data)
-
- def class_path klass_name
- File.join @path, *klass_name.split('::')
- end
-
- ##
- # Removes empty items and ensures item in each collection are unique and
- # sorted
-
- def clean_cache_collection collection # :nodoc:
- collection.each do |name, item|
- if item.empty? then
- collection.delete name
- else
- # HACK mongrel-1.1.5 documents its files twice
- item.uniq!
- item.sort!
- end
- end
- end
-
- ##
- # Friendly rendition of #path
-
- def friendly_path
- case type
- when :gem then
- sep = Regexp.union(*['/', File::ALT_SEPARATOR].compact)
- @path =~ /#{sep}doc#{sep}(.*?)#{sep}ri$/
- "gem #{$1}"
- when :home then '~/.ri'
- when :site then 'ruby site'
- when :system then 'ruby core'
- else @path
- end
- end
-
- def inspect # :nodoc:
- "#<%s:0x%x %s %p>" % [self.class, object_id, @path, modules.sort]
- end
-
- ##
- # Instance methods cache accessor. Maps a class to an Array of its
- # instance methods (not full name).
-
- def instance_methods
- @cache[:instance_methods]
- end
-
- ##
- # Loads cache file for this store
-
- def load_cache
- #orig_enc = @encoding
-
- open cache_path, 'rb' do |io|
- @cache = Marshal.load io.read
- end
-
- load_enc = @cache[:encoding]
-
- # TODO this feature will be time-consuming to add:
- # a) Encodings may be incompatible but transcodeable
- # b) Need to warn in the appropriate spots, wherever they may be
- # c) Need to handle cross-cache differences in encodings
- # d) Need to warn when generating into a cache with diffent encodings
- #
- #if orig_enc and load_enc != orig_enc then
- # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
- # "from #{path}/cache.ri" unless
- # Encoding.compatible? orig_enc, load_enc
- #end
-
- @encoding = load_enc unless @encoding
-
- @cache
- rescue Errno::ENOENT
- end
-
- ##
- # Loads ri data for +klass_name+
-
- def load_class klass_name
- open class_file(klass_name), 'rb' do |io|
- Marshal.load io.read
- end
- end
-
- ##
- # Loads ri data for +method_name+ in +klass_name+
-
- def load_method klass_name, method_name
- open method_file(klass_name, method_name), 'rb' do |io|
- Marshal.load io.read
- end
- end
-
- ##
- # Path to the ri data for +method_name+ in +klass_name+
-
- def method_file klass_name, method_name
- method_name = method_name.split('::').last
- method_name =~ /#(.*)/
- method_type = $1 ? 'i' : 'c'
- method_name = $1 if $1
-
- method_name = if ''.respond_to? :ord then
- method_name.gsub(/\W/) { "%%%02x" % $&[0].ord }
- else
- method_name.gsub(/\W/) { "%%%02x" % $&[0] }
- end
-
- File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
- end
-
- ##
- # Modules cache accessor. An Array of all the modules (and classes) in the
- # store.
-
- def modules
- @cache[:modules]
- end
-
- ##
- # Writes the cache file for this store
-
- def save_cache
- clean_cache_collection @cache[:ancestors]
- clean_cache_collection @cache[:attributes]
- clean_cache_collection @cache[:class_methods]
- clean_cache_collection @cache[:instance_methods]
-
- @cache[:modules].uniq!
- @cache[:modules].sort!
- @cache[:encoding] = @encoding # this gets set twice due to assert_cache
-
- return if @dry_run
-
- marshal = Marshal.dump @cache
-
- open cache_path, 'wb' do |io|
- io.write marshal
- end
- end
-
- ##
- # Writes the ri data for +klass+
-
- def save_class klass
- full_name = klass.full_name
-
- FileUtils.mkdir_p class_path(full_name) unless @dry_run
-
- @cache[:modules] << full_name
-
- path = class_file full_name
-
- begin
- disk_klass = load_class full_name
-
- klass = disk_klass.merge klass
- rescue Errno::ENOENT
- end
-
- # BasicObject has no ancestors
- ancestors = klass.ancestors.compact.map do |ancestor|
- # HACK for classes we don't know about (class X < RuntimeError)
- String === ancestor ? ancestor : ancestor.full_name
- end
-
- @cache[:ancestors][full_name] ||= []
- @cache[:ancestors][full_name].push(*ancestors)
-
- attributes = klass.attributes.map do |attribute|
- "#{attribute.definition} #{attribute.name}"
- end
-
- unless attributes.empty? then
- @cache[:attributes][full_name] ||= []
- @cache[:attributes][full_name].push(*attributes)
- end
-
- to_delete = []
-
- unless klass.method_list.empty? then
- @cache[:class_methods][full_name] ||= []
- @cache[:instance_methods][full_name] ||= []
-
- class_methods, instance_methods =
- klass.method_list.partition { |meth| meth.singleton }
-
- class_methods = class_methods. map { |method| method.name }
- instance_methods = instance_methods.map { |method| method.name }
-
- old = @cache[:class_methods][full_name] - class_methods
- to_delete.concat old.map { |method|
- method_file full_name, "#{full_name}::#{method}"
- }
-
- old = @cache[:instance_methods][full_name] - instance_methods
- to_delete.concat old.map { |method|
- method_file full_name, "#{full_name}##{method}"
- }
-
- @cache[:class_methods][full_name] = class_methods
- @cache[:instance_methods][full_name] = instance_methods
- end
-
- return if @dry_run
-
- FileUtils.rm_f to_delete
-
- marshal = Marshal.dump klass
-
- open path, 'wb' do |io|
- io.write marshal
- end
- end
-
- ##
- # Writes the ri data for +method+ on +klass+
-
- def save_method klass, method
- full_name = klass.full_name
-
- FileUtils.mkdir_p class_path(full_name) unless @dry_run
-
- cache = if method.singleton then
- @cache[:class_methods]
- else
- @cache[:instance_methods]
- end
- cache[full_name] ||= []
- cache[full_name] << method.name
-
- return if @dry_run
-
- marshal = Marshal.dump method
-
- open method_file(full_name, method.full_name), 'wb' do |io|
- io.write marshal
- end
- end
+ Store = RDoc::Store # :nodoc:
end
diff --git a/lib/rdoc/ruby_lex.rb b/lib/rdoc/ruby_lex.rb
index 4392cea9cf..845569b0bc 100644
--- a/lib/rdoc/ruby_lex.rb
+++ b/lib/rdoc/ruby_lex.rb
@@ -11,7 +11,6 @@
require "e2mmap"
require "irb/slex"
-require "rdoc/ruby_token"
require "stringio"
##
@@ -21,6 +20,12 @@ require "stringio"
class RDoc::RubyLex
+ ##
+ # Raised upon invalid input
+
+ class Error < RDoc::Error
+ end
+
# :stopdoc:
extend Exception2MessageMapper
@@ -51,6 +56,29 @@ class RDoc::RubyLex
self.debug_level = 0
+ # :startdoc:
+
+ ##
+ # Returns an Array of +ruby+ tokens. See ::new for a description of
+ # +options+.
+
+ def self.tokenize ruby, options
+ tokens = []
+
+ scanner = RDoc::RubyLex.new ruby, options
+ scanner.exception_on_syntax_error = true
+
+ while token = scanner.token do
+ tokens << token
+ end
+
+ tokens
+ end
+
+ ##
+ # Creates a new lexer for +content+. +options+ is an RDoc::Options, only
+ # +tab_width is used.
+
def initialize(content, options)
lex_init
@@ -91,8 +119,11 @@ class RDoc::RubyLex
@prompt = nil
@prev_seek = nil
+ @ltype = nil
end
+ # :stopdoc:
+
def inspect # :nodoc:
"#<%s:0x%x pos %d lex_state %p space_seen %p>" % [
self.class, object_id,
@@ -122,8 +153,8 @@ class RDoc::RubyLex
end
def get_readed
- if idx = @readed.reverse.index("\n")
- @base_char_no = idx
+ if idx = @readed.rindex("\n")
+ @base_char_no = @readed.size - (idx + 1)
else
@base_char_no += @readed.size
end
@@ -188,8 +219,8 @@ class RDoc::RubyLex
@seek -= 1
if c == "\n"
@line_no -= 1
- if idx = @readed.reverse.index("\n")
- @char_no = @readed.size - idx
+ if idx = @readed.rindex("\n")
+ @char_no = idx + 1
else
@char_no = @base_char_no + @readed.size
end
@@ -323,7 +354,7 @@ class RDoc::RubyLex
tk = @OP.match(self)
@space_seen = tk.kind_of?(TkSPACE)
rescue SyntaxError => e
- raise RDoc::Error, "syntax error: #{e.message}" if
+ raise Error, "syntax error: #{e.message}" if
@exception_on_syntax_error
tk = TkError.new(@seek, @line_no, @char_no)
@@ -381,7 +412,7 @@ class RDoc::RubyLex
def lex_init()
@OP = IRB::SLex.new
@OP.def_rules("\0", "\004", "\032") do |op, io|
- Token(TkEND_OF_SCRIPT)
+ Token(TkEND_OF_SCRIPT, '')
end
@OP.def_rules(" ", "\t", "\f", "\r", "\13") do |op, io|
@@ -413,7 +444,7 @@ class RDoc::RubyLex
gets # consume =end
@ltype = nil
- Token(TkCOMMENT, res)
+ Token(TkRD_COMMENT, res)
end
@OP.def_rule("\n") do |op, io|
@@ -460,7 +491,7 @@ class RDoc::RubyLex
|op, io|
tk = nil
if @lex_state != EXPR_END && @lex_state != EXPR_CLASS &&
- (@lex_state != EXPR_ARG || @space_seen)
+ (@lex_state != EXPR_ARG || @space_seen)
c = peek(0)
if /\S/ =~ c && (/["'`]/ =~ c || /\w/ =~ c || c == "-")
tk = identify_here_document
@@ -505,13 +536,8 @@ class RDoc::RubyLex
@lex_state = EXPR_BEG;
Token(TkQUESTION)
else
- str = ch
- if ch == '\\'
- str << read_escape
- end
@lex_state = EXPR_END
- str << (ch.respond_to?(:ord) ? ch.ord : ch[0])
- Token(TkINTEGER, str)
+ Token(TkSTRING, ch)
end
end
end
@@ -782,7 +808,8 @@ class RDoc::RubyLex
@OP.def_rule("_") do
if peek_match?(/_END__/) and @lex_state == EXPR_BEG then
- Token(TkEND_OF_SCRIPT)
+ 6.times { getc }
+ Token(TkEND_OF_SCRIPT, '__END__')
else
ungetc
identify_identifier
@@ -909,6 +936,8 @@ class RDoc::RubyLex
@indent += 1
@indent_stack.push token_c
end
+ else
+ token_c = TkIDENTIFIER
end
elsif DEINDENT_CLAUSE.include?(token)
@@ -929,7 +958,8 @@ class RDoc::RubyLex
if peek(0) == '='
token.concat getc
end
- elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT
+ elsif @lex_state == EXPR_BEG || @lex_state == EXPR_DOT ||
+ @lex_state == EXPR_ARG
@lex_state = EXPR_ARG
else
@lex_state = EXPR_END
@@ -978,14 +1008,15 @@ class RDoc::RubyLex
end
@here_header = false
- doc = ''
+ doc = '"'
while l = gets
- l = l.sub(/(:?\r)?\n\z/, '')
- if (indent ? l.strip : l) == quoted
+ l = l.sub(/(:?\r)?\n\z/, "\n")
+ if (indent ? l.strip : l.chomp) == quoted
break
end
doc << l
end
+ doc << '"'
@here_header = true
@here_readed.concat reserve
@@ -999,13 +1030,14 @@ class RDoc::RubyLex
end
def identify_quotation
- ch = getc
- if lt = PERCENT_LTYPE[ch]
+ type = ch = getc
+ if lt = PERCENT_LTYPE[type]
ch = getc
- elsif ch =~ /\W/
+ elsif type =~ /\W/
+ type = nil
lt = "\""
else
- raise RDoc::Error, "unknown type of %string #{ch.inspect}"
+ return Token(TkMOD, '%')
end
# if ch !~ /\W/
# ungetc
@@ -1013,7 +1045,7 @@ class RDoc::RubyLex
# end
#@ltype = lt
@quoted = ch unless @quoted = PERCENT_PAREN[ch]
- identify_string(lt, @quoted)
+ identify_string(lt, @quoted, type)
end
def identify_number(op = "")
@@ -1040,7 +1072,7 @@ class RDoc::RubyLex
when /[0-7]/
match = /[0-7_]/
when /[89]/
- raise RDoc::Error, "Illegal octal digit"
+ raise Error, "Illegal octal digit"
else
return Token(TkINTEGER, num)
end
@@ -1054,7 +1086,7 @@ class RDoc::RubyLex
if match =~ ch
if ch == "_"
if non_digit
- raise RDoc::Error, "trailing `#{ch}' in number"
+ raise Error, "trailing `#{ch}' in number"
else
non_digit = ch
end
@@ -1066,10 +1098,10 @@ class RDoc::RubyLex
ungetc
num[-1, 1] = ''
if len0
- raise RDoc::Error, "numeric literal without digits"
+ raise Error, "numeric literal without digits"
end
if non_digit
- raise RDoc::Error, "trailing `#{non_digit}' in number"
+ raise Error, "trailing `#{non_digit}' in number"
end
break
end
@@ -1090,7 +1122,7 @@ class RDoc::RubyLex
non_digit = ch
when allow_point && "."
if non_digit
- raise RDoc::Error, "trailing `#{non_digit}' in number"
+ raise Error, "trailing `#{non_digit}' in number"
end
type = TkFLOAT
if peek(0) !~ /[0-9]/
@@ -1102,7 +1134,7 @@ class RDoc::RubyLex
allow_point = false
when allow_e && "e", allow_e && "E"
if non_digit
- raise RDoc::Error, "trailing `#{non_digit}' in number"
+ raise Error, "trailing `#{non_digit}' in number"
end
type = TkFLOAT
if peek(0) =~ /[+-]/
@@ -1113,7 +1145,7 @@ class RDoc::RubyLex
non_digit = ch
else
if non_digit
- raise RDoc::Error, "trailing `#{non_digit}' in number"
+ raise Error, "trailing `#{non_digit}' in number"
end
ungetc
num[-1, 1] = ''
@@ -1124,14 +1156,17 @@ class RDoc::RubyLex
Token(type, num)
end
- def identify_string(ltype, quoted = ltype)
+ def identify_string(ltype, quoted = ltype, type = nil)
+ close = PERCENT_PAREN.values.include?(quoted)
@ltype = ltype
@quoted = quoted
- str = if ltype == quoted then
+ str = if ltype == quoted and %w[" ' /].include? ltype then
ltype.dup
+ elsif RUBY_VERSION > '1.9' then
+ "%#{type or PERCENT_LTYPE.key ltype}#{PERCENT_PAREN_REV[quoted]}"
else
- "%#{PERCENT_PAREN_REV[quoted]}"
+ "%#{type or PERCENT_LTYPE.index ltype}#{PERCENT_PAREN_REV[quoted]}"
end
subtype = nil
@@ -1141,7 +1176,7 @@ class RDoc::RubyLex
while ch = getc
str << ch
- if @quoted == ch and nest == 0
+ if @quoted == ch and nest <= 0
break
elsif @ltype != "'" && @ltype != "]" && @ltype != ":" and ch == "#"
ch = getc
@@ -1152,17 +1187,21 @@ class RDoc::RubyLex
else
ungetc
end
- elsif ch == '\\' and @ltype == "'" #'
- case ch = getc
- when "\\", "\n", "'"
+ elsif ch == '\\'
+ if %w[' /].include? @ltype then
+ case ch = getc
+ when "\\", "\n", "'"
+ when @ltype
+ str << ch
+ else
+ ungetc
+ end
else
- ungetc
+ str << read_escape
end
- elsif ch == '\\' #'
- str << read_escape
end
- if PERCENT_PAREN.values.include?(@quoted)
+ if close then
if PERCENT_PAREN[ch] == @quoted
nest += 1
elsif ch == @quoted
diff --git a/lib/rdoc/ruby_token.rb b/lib/rdoc/ruby_token.rb
index 93b7a5cbc8..571ea70404 100644
--- a/lib/rdoc/ruby_token.rb
+++ b/lib/rdoc/ruby_token.rb
@@ -60,6 +60,11 @@ module RDoc::RubyToken
self
end
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @text]
+ end
+
end
class TkNode < Token
@@ -83,6 +88,12 @@ module RDoc::RubyToken
end
alias text node
+
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @node]
+ end
+
end
class TkId < Token
@@ -105,6 +116,12 @@ module RDoc::RubyToken
end
alias text name
+
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name]
+ end
+
end
class TkKW < TkId
@@ -130,6 +147,12 @@ module RDoc::RubyToken
end
alias text value
+
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %s, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @value]
+ end
+
end
class TkOp < Token
@@ -153,6 +176,12 @@ module RDoc::RubyToken
end
alias text name
+
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name]
+ end
+
end
class TkOPASGN < TkOp
@@ -175,6 +204,12 @@ module RDoc::RubyToken
def text
@text ||= "#{TkToken2Reading[op]}="
end
+
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @op]
+ end
+
end
class TkUnknownChar < Token
@@ -197,6 +232,12 @@ module RDoc::RubyToken
end
alias text name
+
+ def inspect # :nodoc:
+ klass = self.class.name.split('::').last
+ "{%s %d, %d:%d %p}" % [klass, @seek, @line_no, @char_no, @name]
+ end
+
end
class TkError < Token
@@ -329,13 +370,13 @@ module RDoc::RubyToken
[:TkfLPAREN, Token, "("], # func( #
[:TkfLBRACK, Token, "["], # func[ #
[:TkfLBRACE, Token, "{"], # func{ #
- [:TkSTAR, Token, "*"], # *arg
- [:TkAMPER, Token, "&"], # &arg #
[:TkSYMBEG, Token, ":"], # :SYMBOL
+ [:TkAMPER, TkOp, "&"],
[:TkGT, TkOp, ">"],
[:TkLT, TkOp, "<"],
[:TkPLUS, TkOp, "+"],
+ [:TkSTAR, TkOp, "*"],
[:TkMINUS, TkOp, "-"],
[:TkMULT, TkOp, "*"],
[:TkDIV, TkOp, "/"],
@@ -360,7 +401,6 @@ module RDoc::RubyToken
[:TkSEMICOLON, Token, ";"],
[:TkCOMMENT, TkVal],
- [:TkRD_COMMENT],
[:TkSPACE, Token, " "],
[:TkNL, Token, "\n"],
[:TkEND_OF_SCRIPT],
@@ -401,7 +441,9 @@ module RDoc::RubyToken
def_token(*defs)
end
- NEWLINE_TOKEN = TkNL.new nil, 0, 0, "\n"
+ def_token :TkRD_COMMENT, TkCOMMENT
+
+ NEWLINE_TOKEN = TkNL.new 0, 0, 0, "\n"
class TkSYMBOL
diff --git a/lib/rdoc/rubygems_hook.rb b/lib/rdoc/rubygems_hook.rb
index 178ca1d2ae..90529848dc 100644
--- a/lib/rdoc/rubygems_hook.rb
+++ b/lib/rdoc/rubygems_hook.rb
@@ -73,7 +73,6 @@ class RDoc::RubygemsHook
def initialize spec, generate_rdoc = true, generate_ri = true
@doc_dir = spec.doc_dir
- @file_info = nil
@force = false
@rdoc = nil
@spec = spec
@@ -120,7 +119,7 @@ class RDoc::RubygemsHook
Dir.chdir options.op_dir do
begin
@rdoc.class.current = @rdoc
- @rdoc.generator.generate @file_info
+ @rdoc.generator.generate
ensure
@rdoc.class.current = nil
end
@@ -140,8 +139,8 @@ class RDoc::RubygemsHook
options = ::RDoc::Options.new
options.default_title = "#{@spec.full_name} Documentation"
options.files = []
- options.files.push(*@spec.require_paths)
- options.files.push(*@spec.extra_rdoc_files)
+ options.files.concat @spec.require_paths
+ options.files.concat @spec.extra_rdoc_files
args = @spec.rdoc_options
@@ -160,7 +159,7 @@ class RDoc::RubygemsHook
@rdoc.options = options
Dir.chdir @spec.full_gem_path do
- @file_info = @rdoc.parse_files options.files
+ @rdoc.parse_files options.files
end
document 'ri', options, @ri_dir if
diff --git a/lib/rdoc/servlet.rb b/lib/rdoc/servlet.rb
new file mode 100644
index 0000000000..a4aafeb252
--- /dev/null
+++ b/lib/rdoc/servlet.rb
@@ -0,0 +1,298 @@
+require 'rdoc'
+require 'time'
+require 'webrick'
+
+class RDoc::Servlet < WEBrick::HTTPServlet::AbstractServlet
+
+ @server_stores = Hash.new { |hash, server| hash[server] = {} }
+ @cache = Hash.new { |hash, store| hash[store] = {} }
+
+ attr_reader :asset_dirs
+
+ attr_reader :options
+
+ def self.get_instance server, *options
+ stores = @server_stores[server]
+
+ new server, stores, @cache, *options
+ end
+
+ def initialize server, stores, cache
+ super server
+
+ @stores = stores
+ @cache = cache
+ @options = RDoc::Options.new
+ @options.op_dir = '.'
+
+ darkfish_dir = nil
+
+ # HACK dup
+ $LOAD_PATH.each do |path|
+ darkfish_dir = File.join path, 'rdoc/generator/template/darkfish/'
+ next unless File.directory? darkfish_dir
+ @options.template_dir = darkfish_dir
+ break
+ end
+
+ @asset_dirs = {
+ :darkfish => darkfish_dir,
+ :json_index =>
+ File.expand_path('../generator/template/json_index/', __FILE__),
+ }
+ end
+
+ def asset generator_name, req, res
+ asset_dir = @asset_dirs[generator_name]
+
+ asset_path = File.join asset_dir, req.path
+
+ if_modified_since req, res, asset_path
+
+ res.body = File.read asset_path
+
+ res.content_type = case req.path
+ when /css$/ then 'text/css'
+ when /js$/ then 'application/javascript'
+ else 'application/octet-stream'
+ end
+ end
+
+ def do_GET req, res
+ case req.path
+ when '/' then
+ root req, res
+ when '/rdoc.css', '/js/darkfish.js', '/js/jquery.js', '/js/search.js',
+ %r%^/images/% then
+ asset :darkfish, req, res
+ when '/js/navigation.js', '/js/searcher.js' then
+ asset :json_index, req, res
+ when '/js/search_index.js' then
+ root_search req, res
+ else
+ show_documentation req, res
+ end
+ rescue WEBrick::HTTPStatus::Status
+ raise
+ rescue => e
+ error e, req, res
+ end
+
+ def documentation_page store, generator, path, req, res
+ name = path.sub(/.html$/, '').gsub '/', '::'
+
+ if klass = store.find_class_or_module(name) then
+ res.body = generator.generate_class klass
+ elsif page = store.find_text_page(name.sub(/_([^_]*)$/, '.\1')) then
+ res.body = generator.generate_page page
+ else
+ not_found generator, req, res
+ end
+ end
+
+ def documentation_search store, generator, req, res
+ json_index = @cache[store].fetch :json_index do
+ @cache[store][:json_index] =
+ JSON.dump generator.json_index.build_index
+ end
+
+ res.content_type = 'application/javascript'
+ res.body = "var search_data = #{json_index}"
+ end
+
+ def documentation_source path
+ _, source_name, path = path.split '/', 3
+
+ store = @stores[source_name]
+ return store, path if store
+
+ store = store_for source_name
+
+ store.load_all
+
+ @stores[source_name] = store
+
+ return store, path
+ end
+
+ def error e, req, res
+ backtrace = e.backtrace.join "\n"
+
+ res.content_type = 'text/html'
+ res.status = 500
+ res.body = <<-BODY
+<!DOCTYPE html>
+<html>
+<head>
+<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
+
+<title>Error - #{ERB::Util.html_escape e.class}</title>
+
+<link type="text/css" media="screen" href="/rdoc.css" rel="stylesheet">
+</head>
+<body>
+<h1>Error</h1>
+
+<p>While processing <code>#{ERB::Util.html_escape req.request_uri}</code> the
+RDoc server has encountered a <code>#{ERB::Util.html_escape e.class}</code>
+exception:
+
+<pre>#{ERB::Util.html_escape e.message}</pre>
+
+<p>Backtrace:
+
+<pre>#{ERB::Util.html_escape backtrace}</pre>
+
+</body>
+</html>
+ BODY
+ end
+
+ def generator_for store
+ generator = RDoc::Generator::Darkfish.new store, @options
+ generator.file_output = false
+ generator.asset_rel_path = '..'
+
+ rdoc = RDoc::RDoc.new
+ rdoc.store = store
+ rdoc.generator = generator
+ rdoc.options = @options
+
+ @options.main_page = store.main
+ @options.title = store.title
+
+ generator
+ end
+
+ def if_modified_since req, res, path = nil
+ last_modified = File.stat(path).mtime if path
+
+ res['last-modified'] = last_modified.httpdate
+
+ return unless ims = req['if-modified-since']
+
+ ims = Time.parse ims
+
+ unless ims < last_modified then
+ res.body = ''
+ raise WEBrick::HTTPStatus::NotModified
+ end
+ end
+
+ def installed_docs
+ ri_paths.map do |path, type|
+ store = RDoc::Store.new path, type
+ exists = File.exist? store.cache_path
+
+ case type
+ when :gem then
+ gem_path = path[%r%/([^/]*)/ri$%, 1]
+ [gem_path, "#{gem_path}/", exists, type, path]
+ when :system then
+ ['Ruby Documentation', 'ruby/', exists, type, path]
+ when :site then
+ ['Site Documentation', 'site/', exists, type, path]
+ when :home then
+ ['Home Documentation', 'home/', exists, type, path]
+ end
+ end
+ end
+
+ def not_found generator, req, res
+ res.body = generator.generate_servlet_not_found req.path
+ res.status = 404
+ end
+
+ def ri_paths &block
+ RDoc::RI::Paths.each true, true, true, :all, &block
+ end
+
+ def root req, res
+ generator = RDoc::Generator::Darkfish.new nil, @options
+
+ res.body = generator.generate_servlet_root installed_docs
+
+ res.content_type = 'text/html'
+ end
+
+ def root_search req, res
+ search_index = []
+ info = []
+
+ installed_docs.map do |name, href, exists, type, path|
+ next unless exists
+
+ search_index << name
+
+ comment = case type
+ when :gem
+ gemspec = path.gsub(%r%/doc/([^/]*?)/ri$%,
+ '/specifications/\1.gemspec')
+
+ spec = Gem::Specification.load gemspec
+
+ spec.summary
+ when :system then
+ 'Documentation for the Ruby standard library'
+ when :site then
+ 'Documentation for non-gem libraries'
+ when :home then
+ 'Documentation from your home directory'
+ end
+
+ info << [name, '', path, '', comment]
+ end
+
+ index = {
+ :index => {
+ :searchIndex => search_index,
+ :longSearchIndex => search_index,
+ :info => info,
+ }
+ }
+
+ res.body = "var search_data = #{JSON.dump index};"
+ res.content_type = 'application/javascript'
+ end
+
+ def show_documentation req, res
+ store, path = documentation_source req.path
+
+ if_modified_since req, res, store.cache_path
+
+ generator = generator_for store
+
+ case path
+ when nil, '', 'index.html' then
+ res.body = generator.generate_index
+ when 'table_of_contents.html' then
+ res.body = generator.generate_table_of_contents
+ when 'js/search_index.js' then
+ documentation_search store, generator, req, res
+ else
+ documentation_page store, generator, path, req, res
+ end
+ ensure
+ res.content_type ||= 'text/html'
+ end
+
+ def store_for source_name
+ case source_name
+ when 'ruby' then
+ RDoc::Store.new RDoc::RI::Paths.system_dir, :system
+ else
+ ri_dir, type = ri_paths.find do |dir, dir_type|
+ next unless dir_type == :gem
+
+ source_name == dir[%r%/([^/]*)/ri$%, 1]
+ end
+
+ raise "could not find ri documentation for #{source_name}" unless
+ ri_dir
+
+ RDoc::Store.new ri_dir, type
+ end
+ end
+
+end
+
diff --git a/lib/rdoc/single_class.rb b/lib/rdoc/single_class.rb
index e48758d9c8..9e77a65c73 100644
--- a/lib/rdoc/single_class.rb
+++ b/lib/rdoc/single_class.rb
@@ -1,5 +1,3 @@
-require 'rdoc/class_module'
-
##
# A singleton class
diff --git a/lib/rdoc/stats.rb b/lib/rdoc/stats.rb
index e6101bb457..4fa519d243 100644
--- a/lib/rdoc/stats.rb
+++ b/lib/rdoc/stats.rb
@@ -1,5 +1,3 @@
-require 'rdoc'
-
##
# RDoc statistics collector which prints a summary and report of a project's
# documentation totals.
@@ -25,17 +23,18 @@ class RDoc::Stats
# Creates a new Stats that will have +num_files+. +verbosity+ defaults to 1
# which will create an RDoc::Stats::Normal outputter.
- def initialize num_files, verbosity = 1
- @files_so_far = 0
+ def initialize store, num_files, verbosity = 1
@num_files = num_files
+ @store = store
- @coverage_level = 0
- @doc_items = nil
+ @coverage_level = 0
+ @doc_items = nil
+ @files_so_far = 0
@fully_documented = false
- @num_params = 0
- @percent_doc = nil
- @start = Time.now
- @undoc_params = 0
+ @num_params = 0
+ @percent_doc = nil
+ @start = Time.now
+ @undoc_params = 0
@display = case verbosity
when 0 then Quiet.new num_files
@@ -108,7 +107,10 @@ class RDoc::Stats
def calculate
return if @doc_items
- ucm = RDoc::TopLevel.unique_classes_and_modules
+ ucm = @store.unique_classes_and_modules
+
+ classes = @store.unique_classes.reject { |cm| cm.full_name == 'Object' }
+
constants = []
ucm.each { |cm| constants.concat cm.constants }
@@ -119,10 +121,10 @@ class RDoc::Stats
ucm.each { |cm| attributes.concat cm.attributes }
@num_attributes, @undoc_attributes = doc_stats attributes
- @num_classes, @undoc_classes = doc_stats RDoc::TopLevel.unique_classes
+ @num_classes, @undoc_classes = doc_stats classes
@num_constants, @undoc_constants = doc_stats constants
@num_methods, @undoc_methods = doc_stats methods
- @num_modules, @undoc_modules = doc_stats RDoc::TopLevel.unique_modules
+ @num_modules, @undoc_modules = doc_stats @store.unique_modules
@num_items =
@num_attributes +
@@ -160,7 +162,8 @@ class RDoc::Stats
# Returns the length and number of undocumented items in +collection+.
def doc_stats collection
- [collection.length, collection.count { |item| not item.documented? }]
+ visible = collection.select { |item| item.display? }
+ [visible.length, visible.count { |item| not item.documented? }]
end
##
@@ -211,9 +214,6 @@ class RDoc::Stats
def report
if @coverage_level > 0 then
- require 'rdoc/markup/to_tt_only'
- require 'rdoc/generator/markup'
- require 'rdoc/text'
extend RDoc::Text
end
@@ -225,7 +225,7 @@ class RDoc::Stats
return great_job if @num_items == @doc_items
end
- ucm = RDoc::TopLevel.unique_classes_and_modules
+ ucm = @store.unique_classes_and_modules
ucm.sort.each do |cm|
report << report_class_module(cm) {
@@ -259,8 +259,8 @@ class RDoc::Stats
cm.each_attribute do |attr|
next if attr.documented?
- report << " #{attr.definition} :#{attr.name} " \
- "# in file #{attr.file.full_name}"
+ line = attr.line ? ":#{attr.line}" : nil
+ report << " #{attr.definition} :#{attr.name} # in file #{attr.file.full_name}#{line}"
end
report
@@ -271,14 +271,14 @@ class RDoc::Stats
def report_class_module cm
return if cm.fully_documented? and @coverage_level.zero?
+ return unless cm.display?
report = []
if cm.in_files.empty? then
report << "# #{cm.definition} is referenced but empty."
- report << '#'
- report << '# It probably came from another project. ' \
- "I'm sorry I'm holding it against you."
+ report << "#"
+ report << "# It probably came from another project. I'm sorry I'm holding it against you."
report << nil
return report
@@ -321,7 +321,9 @@ class RDoc::Stats
# TODO constant aliases are listed in the summary but not reported
# figure out what to do here
next if constant.documented? || constant.is_alias_for
- report << " # in file #{constant.file.full_name}"
+
+ line = constant.line ? ":#{constant.line}" : line
+ report << " # in file #{constant.file.full_name}#{line}"
report << " #{constant.name} = nil"
end
@@ -353,9 +355,13 @@ class RDoc::Stats
end
next if method.documented? and not param_report
- report << " # in file #{method.file.full_name}"
+
+ line = method.line ? ":#{method.line}" : nil
+ scope = method.singleton ? 'self.' : nil
+
+ report << " # in file #{method.file.full_name}#{line}"
report << param_report if param_report
- report << " def #{method.name}#{method.params}; end"
+ report << " def #{scope}#{method.name}#{method.params}; end"
report << nil
end
diff --git a/lib/rdoc/store.rb b/lib/rdoc/store.rb
new file mode 100644
index 0000000000..ee58a4d873
--- /dev/null
+++ b/lib/rdoc/store.rb
@@ -0,0 +1,881 @@
+require 'fileutils'
+
+##
+# A set of rdoc data for a single project (gem, path, etc.).
+#
+# The store manages reading and writing ri data for a project and maintains a
+# cache of methods, classes and ancestors in the store.
+#
+# The store maintains a #cache of its contents for faster lookup. After
+# adding items to the store it must be flushed using #save_cache. The cache
+# contains the following structures:
+#
+# @cache = {
+# :ancestors => {}, # class name => ancestor names
+# :attributes => {}, # class name => attributes
+# :class_methods => {}, # class name => class methods
+# :instance_methods => {}, # class name => instance methods
+# :modules => [], # classes and modules in this store
+# :pages => [], # page names
+# }
+#--
+# TODO need to prune classes
+
+class RDoc::Store
+
+ ##
+ # Errors raised from loading or saving the store
+
+ class Error < RDoc::Error
+ end
+
+ ##
+ # Raised when a stored file for a class, module, page or method is missing.
+
+ class MissingFileError < Error
+
+ ##
+ # The store the file should exist in
+
+ attr_reader :store
+
+ ##
+ # The file the #name should be saved as
+
+ attr_reader :file
+
+ ##
+ # The name of the object the #file would be loaded from
+
+ attr_reader :name
+
+ ##
+ # Creates a new MissingFileError for the missing +file+ for the given
+ # +name+ that should have been in the +store+.
+
+ def initialize store, file, name
+ @store = store
+ @file = file
+ @name = name
+ end
+
+ def message
+ "store at #{@store.path} missing file #{@file} for #{@name}"
+ end
+
+ end
+
+ ##
+ # Stores the name of the C variable a class belongs to. This helps wire up
+ # classes defined from C across files.
+
+ attr_reader :c_enclosure_classes
+
+ ##
+ # If true this Store will not write any files
+
+ attr_accessor :dry_run
+
+ ##
+ # Path this store reads or writes
+
+ attr_accessor :path
+
+ ##
+ # The RDoc::RDoc driver for this parse tree. This allows classes consulting
+ # the documentation tree to access user-set options, for example.
+
+ attr_accessor :rdoc
+
+ ##
+ # Type of ri datastore this was loaded from. See RDoc::RI::Driver,
+ # RDoc::RI::Paths.
+
+ attr_accessor :type
+
+ ##
+ # The contents of the Store
+
+ attr_reader :cache
+
+ ##
+ # The encoding of the contents in the Store
+
+ attr_accessor :encoding
+
+ ##
+ # Creates a new Store of +type+ that will load or save to +path+
+
+ def initialize path = nil, type = nil
+ @dry_run = false
+ @encoding = nil
+ @path = path
+ @rdoc = nil
+ @type = type
+
+ @cache = {
+ :ancestors => {},
+ :attributes => {},
+ :class_methods => {},
+ :encoding => @encoding,
+ :instance_methods => {},
+ :main => nil,
+ :modules => [],
+ :pages => [],
+ :title => nil,
+ }
+
+ @classes_hash = {}
+ @modules_hash = {}
+ @files_hash = {}
+
+ @c_enclosure_classes = {}
+
+ @unique_classes = nil
+ @unique_modules = nil
+ end
+
+ ##
+ # Adds the file with +name+ as an RDoc::TopLevel to the store. Returns the
+ # created RDoc::TopLevel.
+
+ def add_file name
+ unless top_level = @files_hash[name] then
+ top_level = RDoc::TopLevel.new name
+ top_level.store = self
+ @files_hash[name] = top_level
+ end
+
+ top_level
+ end
+
+ ##
+ # Returns all classes discovered by RDoc
+
+ def all_classes
+ @classes_hash.values
+ end
+
+ ##
+ # Returns all classes and modules discovered by RDoc
+
+ def all_classes_and_modules
+ @classes_hash.values + @modules_hash.values
+ end
+
+ ##
+ # All TopLevels known to RDoc
+
+ def all_files
+ @files_hash.values
+ end
+
+ ##
+ # Returns all modules discovered by RDoc
+
+ def all_modules
+ modules_hash.values
+ end
+
+ ##
+ # Ancestors cache accessor. Maps a klass name to an Array of its ancestors
+ # in this store. If Foo in this store inherits from Object, Kernel won't be
+ # listed (it will be included from ruby's ri store).
+
+ def ancestors
+ @cache[:ancestors]
+ end
+
+ ##
+ # Attributes cache accessor. Maps a class to an Array of its attributes.
+
+ def attributes
+ @cache[:attributes]
+ end
+
+ ##
+ # Path to the cache file
+
+ def cache_path
+ File.join @path, 'cache.ri'
+ end
+
+ ##
+ # Path to the ri data for +klass_name+
+
+ def class_file klass_name
+ name = klass_name.split('::').last
+ File.join class_path(klass_name), "cdesc-#{name}.ri"
+ end
+
+ ##
+ # Class methods cache accessor. Maps a class to an Array of its class
+ # methods (not full name).
+
+ def class_methods
+ @cache[:class_methods]
+ end
+
+ ##
+ # Path where data for +klass_name+ will be stored (methods or class data)
+
+ def class_path klass_name
+ File.join @path, *klass_name.split('::')
+ end
+
+ ##
+ # Hash of all classes known to RDoc
+
+ def classes_hash
+ @classes_hash
+ end
+
+ ##
+ # Removes empty items and ensures item in each collection are unique and
+ # sorted
+
+ def clean_cache_collection collection # :nodoc:
+ collection.each do |name, item|
+ if item.empty? then
+ collection.delete name
+ else
+ # HACK mongrel-1.1.5 documents its files twice
+ item.uniq!
+ item.sort!
+ end
+ end
+ end
+
+ ##
+ # Prepares the RDoc code object tree for use by a generator.
+ #
+ # It finds unique classes/modules defined, and replaces classes/modules that
+ # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for
+ # set.
+ #
+ # It updates the RDoc::ClassModule#constant_aliases attribute of "real"
+ # classes or modules.
+ #
+ # It also completely removes the classes and modules that should be removed
+ # from the documentation and the methods that have a visibility below
+ # +min_visibility+, which is the <tt>--visibility</tt> option.
+ #
+ # See also RDoc::Context#remove_from_documentation?
+
+ def complete min_visibility
+ fix_basic_object_inheritance
+
+ # cache included modules before they are removed from the documentation
+ all_classes_and_modules.each { |cm| cm.ancestors }
+
+ remove_nodoc @classes_hash
+ remove_nodoc @modules_hash
+
+ @unique_classes = find_unique @classes_hash
+ @unique_modules = find_unique @modules_hash
+
+ unique_classes_and_modules.each do |cm|
+ cm.complete min_visibility
+ end
+
+ @files_hash.each_key do |file_name|
+ tl = @files_hash[file_name]
+
+ unless tl.text? then
+ tl.modules_hash.clear
+ tl.classes_hash.clear
+
+ tl.classes_or_modules.each do |cm|
+ name = cm.full_name
+ if cm.type == 'class' then
+ tl.classes_hash[name] = cm if @classes_hash[name]
+ else
+ tl.modules_hash[name] = cm if @modules_hash[name]
+ end
+ end
+ end
+ end
+ end
+
+ ##
+ # Hash of all files known to RDoc
+
+ def files_hash
+ @files_hash
+ end
+
+ ##
+ # Finds the class with +name+ in all discovered classes
+
+ def find_class_named name
+ @classes_hash[name]
+ end
+
+ ##
+ # Finds the class with +name+ starting in namespace +from+
+
+ def find_class_named_from name, from
+ from = find_class_named from unless RDoc::Context === from
+
+ until RDoc::TopLevel === from do
+ return nil unless from
+
+ klass = from.find_class_named name
+ return klass if klass
+
+ from = from.parent
+ end
+
+ find_class_named name
+ end
+
+ ##
+ # Finds the class or module with +name+
+
+ def find_class_or_module name
+ name = $' if name =~ /^::/
+ @classes_hash[name] || @modules_hash[name]
+ end
+
+ ##
+ # Finds the file with +name+ in all discovered files
+
+ def find_file_named name
+ @files_hash[name]
+ end
+
+ ##
+ # Finds the module with +name+ in all discovered modules
+
+ def find_module_named name
+ @modules_hash[name]
+ end
+
+ ##
+ # Returns the RDoc::TopLevel that is a text file and has the given
+ # +file_name+
+
+ def find_text_page file_name
+ @files_hash.each_value.find do |file|
+ file.text? and file.full_name == file_name
+ end
+ end
+
+ ##
+ # Finds unique classes/modules defined in +all_hash+,
+ # and returns them as an array. Performs the alias
+ # updates in +all_hash+: see ::complete.
+ #--
+ # TODO aliases should be registered by Context#add_module_alias
+
+ def find_unique all_hash
+ unique = []
+
+ all_hash.each_pair do |full_name, cm|
+ unique << cm if full_name == cm.full_name
+ end
+
+ unique
+ end
+
+ ##
+ # Fixes the erroneous <tt>BasicObject < Object</tt> in 1.9.
+ #
+ # Because we assumed all classes without a stated superclass
+ # inherit from Object, we have the above wrong inheritance.
+ #
+ # We fix BasicObject right away if we are running in a Ruby
+ # version >= 1.9. If not, we may be documenting 1.9 source
+ # while running under 1.8: we search the files of BasicObject
+ # for "object.c", and fix the inheritance if we find it.
+
+ def fix_basic_object_inheritance
+ basic = classes_hash['BasicObject']
+ return unless basic
+ if RUBY_VERSION >= '1.9'
+ basic.superclass = nil
+ elsif basic.in_files.any? { |f| File.basename(f.full_name) == 'object.c' }
+ basic.superclass = nil
+ end
+ end
+
+ ##
+ # Friendly rendition of #path
+
+ def friendly_path
+ case type
+ when :gem then
+ parent = File.expand_path '..', @path
+ "gem #{File.basename parent}"
+ when :home then '~/.rdoc'
+ when :site then 'ruby site'
+ when :system then 'ruby core'
+ else @path
+ end
+ end
+
+ def inspect # :nodoc:
+ "#<%s:0x%x %s %p>" % [self.class, object_id, @path, module_names.sort]
+ end
+
+ ##
+ # Instance methods cache accessor. Maps a class to an Array of its
+ # instance methods (not full name).
+
+ def instance_methods
+ @cache[:instance_methods]
+ end
+
+ ##
+ # Loads all items from this store into memory. This recreates a
+ # documentation tree for use by a generator
+
+ def load_all
+ load_cache
+
+ module_names.each do |module_name|
+ mod = find_class_or_module(module_name) || load_class(module_name)
+
+ # load method documentation since the loaded class/module does not have
+ # it
+ loaded_methods = mod.method_list.map do |method|
+ load_method module_name, method.full_name
+ end
+
+ mod.method_list.replace loaded_methods
+
+ loaded_attributes = mod.attributes.map do |attribute|
+ load_method module_name, attribute.full_name
+ end
+
+ mod.attributes.replace loaded_attributes
+ end
+
+ all_classes_and_modules.each do |mod|
+ descendent_re = /^#{mod.full_name}::[^:]+$/
+
+ module_names.each do |name|
+ next unless name =~ descendent_re
+
+ descendent = find_class_or_module name
+
+ case descendent
+ when RDoc::NormalClass then
+ mod.classes_hash[name] = descendent
+ when RDoc::NormalModule then
+ mod.modules_hash[name] = descendent
+ end
+ end
+ end
+
+ @cache[:pages].each do |page_name|
+ page = load_page page_name
+ @files_hash[page_name] = page
+ end
+ end
+
+ ##
+ # Loads cache file for this store
+
+ def load_cache
+ #orig_enc = @encoding
+
+ open cache_path, 'rb' do |io|
+ @cache = Marshal.load io.read
+ end
+
+ load_enc = @cache[:encoding]
+
+ # TODO this feature will be time-consuming to add:
+ # a) Encodings may be incompatible but transcodeable
+ # b) Need to warn in the appropriate spots, wherever they may be
+ # c) Need to handle cross-cache differences in encodings
+ # d) Need to warn when generating into a cache with different encodings
+ #
+ #if orig_enc and load_enc != orig_enc then
+ # warn "Cached encoding #{load_enc} is incompatible with #{orig_enc}\n" \
+ # "from #{path}/cache.ri" unless
+ # Encoding.compatible? orig_enc, load_enc
+ #end
+
+ @encoding = load_enc unless @encoding
+
+ @cache[:pages] ||= []
+ @cache[:main] ||= nil
+
+ @cache
+ rescue Errno::ENOENT
+ end
+
+ ##
+ # Loads ri data for +klass_name+
+
+ def load_class klass_name
+ file = class_file klass_name
+
+ obj = open file, 'rb' do |io|
+ Marshal.load io.read
+ end
+
+ obj.store = self
+
+ case obj
+ when RDoc::NormalClass then
+ @classes_hash[klass_name] = obj
+ when RDoc::NormalModule then
+ @modules_hash[klass_name] = obj
+ end
+ rescue Errno::ENOENT => e
+ error = MissingFileError.new(self, file, klass_name)
+ error.set_backtrace e.backtrace
+ raise error
+ end
+
+ ##
+ # Loads ri data for +method_name+ in +klass_name+
+
+ def load_method klass_name, method_name
+ file = method_file klass_name, method_name
+
+ open file, 'rb' do |io|
+ obj = Marshal.load io.read
+ obj.store = self
+ obj.parent =
+ find_class_or_module(klass_name) || load_class(klass_name) unless
+ obj.parent
+ obj
+ end
+ rescue Errno::ENOENT => e
+ error = MissingFileError.new(self, file, klass_name + method_name)
+ error.set_backtrace e.backtrace
+ raise error
+ end
+
+ ##
+ # Loads ri data for +page_name+
+
+ def load_page page_name
+ file = page_file page_name
+
+ open file, 'rb' do |io|
+ obj = Marshal.load io.read
+ obj.store = self
+ obj
+ end
+ rescue Errno::ENOENT => e
+ error = MissingFileError.new(self, file, page_name)
+ error.set_backtrace e.backtrace
+ raise error
+ end
+
+ ##
+ # Gets the main page for this RDoc store. This page is used as the root of
+ # the RDoc server.
+
+ def main
+ @cache[:main]
+ end
+
+ ##
+ # Sets the main page for this RDoc store.
+
+ def main= page
+ @cache[:main] = page
+ end
+
+ ##
+ # Path to the ri data for +method_name+ in +klass_name+
+
+ def method_file klass_name, method_name
+ method_name = method_name.split('::').last
+ method_name =~ /#(.*)/
+ method_type = $1 ? 'i' : 'c'
+ method_name = $1 if $1
+
+ method_name = if ''.respond_to? :ord then
+ method_name.gsub(/\W/) { "%%%02x" % $&[0].ord }
+ else
+ method_name.gsub(/\W/) { "%%%02x" % $&[0] }
+ end
+
+ File.join class_path(klass_name), "#{method_name}-#{method_type}.ri"
+ end
+
+ ##
+ # Modules cache accessor. An Array of all the module (and class) names in
+ # the store.
+
+ def module_names
+ @cache[:modules]
+ end
+
+ ##
+ # Hash of all modules known to RDoc
+
+ def modules_hash
+ @modules_hash
+ end
+
+ ##
+ # Returns the RDoc::TopLevel that is a text file and has the given +name+
+
+ def page name
+ @files_hash.each_value.find do |file|
+ file.text? and file.page_name == name
+ end
+ end
+
+ ##
+ # Path to the ri data for +page_name+
+
+ def page_file page_name
+ file_name = File.basename(page_name).gsub('.', '_')
+
+ File.join @path, File.dirname(page_name), "page-#{file_name}.ri"
+ end
+
+ ##
+ # Removes from +all_hash+ the contexts that are nodoc or have no content.
+ #
+ # See RDoc::Context#remove_from_documentation?
+
+ def remove_nodoc all_hash
+ all_hash.keys.each do |name|
+ context = all_hash[name]
+ all_hash.delete(name) if context.remove_from_documentation?
+ end
+ end
+
+ ##
+ # Saves all entries in the store
+
+ def save
+ load_cache
+
+ all_classes_and_modules.each do |klass|
+ save_class klass
+
+ klass.each_method do |method|
+ save_method klass, method
+ end
+
+ klass.each_attribute do |attribute|
+ save_method klass, attribute
+ end
+ end
+
+ all_files.each do |file|
+ save_page file
+ end
+
+ save_cache
+ end
+
+ ##
+ # Writes the cache file for this store
+
+ def save_cache
+ clean_cache_collection @cache[:ancestors]
+ clean_cache_collection @cache[:attributes]
+ clean_cache_collection @cache[:class_methods]
+ clean_cache_collection @cache[:instance_methods]
+
+ @cache[:modules].uniq!
+ @cache[:modules].sort!
+
+ @cache[:pages].uniq!
+ @cache[:pages].sort!
+
+ @cache[:encoding] = @encoding # this gets set twice due to assert_cache
+
+ return if @dry_run
+
+ marshal = Marshal.dump @cache
+
+ open cache_path, 'wb' do |io|
+ io.write marshal
+ end
+ end
+
+ ##
+ # Writes the ri data for +klass+ (or module)
+
+ def save_class klass
+ full_name = klass.full_name
+
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
+
+ @cache[:modules] << full_name
+
+ path = class_file full_name
+
+ begin
+ disk_klass = load_class full_name
+
+ klass = disk_klass.merge klass
+ rescue MissingFileError
+ end
+
+ # BasicObject has no ancestors
+ ancestors = klass.direct_ancestors.compact.map do |ancestor|
+ # HACK for classes we don't know about (class X < RuntimeError)
+ String === ancestor ? ancestor : ancestor.full_name
+ end
+
+ @cache[:ancestors][full_name] ||= []
+ @cache[:ancestors][full_name].concat ancestors
+
+ attributes = klass.attributes.map do |attribute|
+ "#{attribute.definition} #{attribute.name}"
+ end
+
+ unless attributes.empty? then
+ @cache[:attributes][full_name] ||= []
+ @cache[:attributes][full_name].concat attributes
+ end
+
+ to_delete = []
+
+ unless klass.method_list.empty? then
+ @cache[:class_methods][full_name] ||= []
+ @cache[:instance_methods][full_name] ||= []
+
+ class_methods, instance_methods =
+ klass.method_list.partition { |meth| meth.singleton }
+
+ class_methods = class_methods. map { |method| method.name }
+ instance_methods = instance_methods.map { |method| method.name }
+
+ old = @cache[:class_methods][full_name] - class_methods
+ to_delete.concat old.map { |method|
+ method_file full_name, "#{full_name}::#{method}"
+ }
+
+ old = @cache[:instance_methods][full_name] - instance_methods
+ to_delete.concat old.map { |method|
+ method_file full_name, "#{full_name}##{method}"
+ }
+
+ @cache[:class_methods][full_name] = class_methods
+ @cache[:instance_methods][full_name] = instance_methods
+ end
+
+ return if @dry_run
+
+ FileUtils.rm_f to_delete
+
+ marshal = Marshal.dump klass
+
+ open path, 'wb' do |io|
+ io.write marshal
+ end
+ end
+
+ ##
+ # Writes the ri data for +method+ on +klass+
+
+ def save_method klass, method
+ full_name = klass.full_name
+
+ FileUtils.mkdir_p class_path(full_name) unless @dry_run
+
+ cache = if method.singleton then
+ @cache[:class_methods]
+ else
+ @cache[:instance_methods]
+ end
+ cache[full_name] ||= []
+ cache[full_name] << method.name
+
+ return if @dry_run
+
+ marshal = Marshal.dump method
+
+ open method_file(full_name, method.full_name), 'wb' do |io|
+ io.write marshal
+ end
+ end
+
+ ##
+ # Writes the ri data for +page+
+
+ def save_page page
+ return unless page.text?
+
+ path = page_file page.full_name
+
+ FileUtils.mkdir_p File.dirname(path) unless @dry_run
+
+ cache[:pages] ||= []
+ cache[:pages] << page.full_name
+
+ return if @dry_run
+
+ marshal = Marshal.dump page
+
+ open path, 'wb' do |io|
+ io.write marshal
+ end
+ end
+
+ ##
+ # Source of the contents of this store.
+ #
+ # For a store from a gem the source is the gem name. For a store from the
+ # home directory the source is "home". For system ri store (the standard
+ # library documentation) the source is"ruby". For a store from the site
+ # ri directory the store is "site". For other stores the source is the
+ # #path.
+
+ def source
+ case type
+ when :gem then File.basename File.expand_path '..', @path
+ when :home then 'home'
+ when :site then 'site'
+ when :system then 'ruby'
+ else @path
+ end
+ end
+
+ ##
+ # Gets the title for this RDoc store. This is used as the title in each
+ # page on the RDoc server
+
+ def title
+ @cache[:title]
+ end
+
+ ##
+ # Sets the title page for this RDoc store.
+
+ def title= title
+ @cache[:title] = title
+ end
+
+ ##
+ # Returns the unique classes discovered by RDoc.
+ #
+ # ::complete must have been called prior to using this method.
+
+ def unique_classes
+ @unique_classes
+ end
+
+ ##
+ # Returns the unique classes and modules discovered by RDoc.
+ # ::complete must have been called prior to using this method.
+
+ def unique_classes_and_modules
+ @unique_classes + @unique_modules
+ end
+
+ ##
+ # Returns the unique modules discovered by RDoc.
+ # ::complete must have been called prior to using this method.
+
+ def unique_modules
+ @unique_modules
+ end
+
+end
+
diff --git a/lib/rdoc/task.rb b/lib/rdoc/task.rb
index b4ff3e99c6..d347e4d6ab 100644
--- a/lib/rdoc/task.rb
+++ b/lib/rdoc/task.rb
@@ -25,12 +25,12 @@ require 'rubygems'
begin
gem 'rdoc'
rescue Gem::LoadError
-end
+end unless defined?(RDoc)
begin
gem 'rake'
rescue Gem::LoadError
-end
+end unless defined?(Rake)
require 'rdoc'
require 'rake'
@@ -52,7 +52,6 @@ require 'rake/tasklib'
#
# Simple Example:
#
-# gem 'rdoc'
# require 'rdoc/task'
#
# RDoc::Task.new do |rdoc|
@@ -69,7 +68,6 @@ require 'rake/tasklib'
# generating two sets of documentation. For instance, if you want to have a
# development set of documentation including private methods:
#
-# gem 'rdoc'
# require 'rdoc/task'
#
# RDoc::Task.new :rdoc_dev do |rdoc|
@@ -87,7 +85,6 @@ require 'rake/tasklib'
#
# For example:
#
-# gem 'rdoc'
# require 'rdoc/task'
#
# RDoc::Task.new(:rdoc => "rdoc", :clobber_rdoc => "rdoc:clean",
@@ -104,6 +101,12 @@ class RDoc::Task < Rake::TaskLib
attr_accessor :name
##
+ # Comment markup format. rdoc, rd and tomdoc are supported. (default is
+ # 'rdoc')
+
+ attr_accessor :markup
+
+ ##
# Name of directory to receive the html output files. (default is "html")
attr_accessor :rdoc_dir
@@ -125,7 +128,8 @@ class RDoc::Task < Rake::TaskLib
attr_accessor :template
##
- # Name of format generator (--fmt) used by rdoc. (defaults to rdoc's default)
+ # Name of format generator (<tt>--format<tt>) used by rdoc. (defaults to
+ # rdoc's default)
attr_accessor :generator
@@ -241,7 +245,6 @@ class RDoc::Task < Rake::TaskLib
args = option_list + @rdoc_files
$stderr.puts "rdoc #{args.join ' '}" if Rake.application.options.trace
- require 'rdoc/rdoc'
RDoc::RDoc.new.document args
end
@@ -253,11 +256,12 @@ class RDoc::Task < Rake::TaskLib
def option_list
result = @options.dup
- result << "-o" << @rdoc_dir
- result << "--main" << main if main
- result << "--title" << title if title
- result << "-T" << template if template
- result << '-f' << generator if generator
+ result << "-o" << @rdoc_dir
+ result << "--main" << main if main
+ result << "--markup" << markup if markup
+ result << "--title" << title if title
+ result << "-T" << template if template
+ result << '-f' << generator if generator
result
end
@@ -316,8 +320,6 @@ end
# :stopdoc:
module Rake
- remove_const(:RDocTask) if defined?(RDocTask) # remove deprecated class
-
##
# For backwards compatibility
diff --git a/lib/rdoc/test_case.rb b/lib/rdoc/test_case.rb
new file mode 100644
index 0000000000..c2eb855d83
--- /dev/null
+++ b/lib/rdoc/test_case.rb
@@ -0,0 +1,162 @@
+require 'rubygems'
+require 'minitest/autorun'
+require 'minitest/benchmark' if ENV['BENCHMARK']
+
+require 'fileutils'
+require 'pp'
+require 'tempfile'
+require 'tmpdir'
+require 'stringio'
+
+require 'rdoc'
+
+##
+# RDoc::TestCase is an abstract TestCase to provide common setup and teardown
+# across all RDoc tests. The test case uses minitest, so all the assertions
+# of minitest may be used.
+#
+# The testcase provides the following:
+#
+# * A reset code-object tree
+# * A reset markup preprocessor (RDoc::Markup::PreProcess)
+# * The <code>@RM</code> alias of RDoc::Markup (for less typing)
+# * <code>@pwd</code> containing the current working directory
+# * FileUtils, pp, Tempfile, Dir.tmpdir and StringIO
+
+class RDoc::TestCase < MiniTest::Unit::TestCase
+
+ ##
+ # Abstract test-case setup
+
+ def setup
+ super
+
+ @top_level = nil
+
+ @RM = RDoc::Markup
+
+ RDoc::Markup::PreProcess.reset
+
+ @pwd = Dir.pwd
+
+ @store = RDoc::Store.new
+
+ @rdoc = RDoc::RDoc.new
+ @rdoc.store = @store
+
+ g = Object.new
+ def g.class_dir() end
+ def g.file_dir() end
+ @rdoc.generator = g
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::BlankLine.new
+
+ def blank_line
+ @RM::BlankLine.new
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::BlockQuote.new with +contents+
+
+ def block *contents
+ @RM::BlockQuote.new(*contents)
+ end
+
+ ##
+ # Creates an RDoc::Comment with +text+ which was defined on +top_level+.
+ # By default the comment has the 'rdoc' format.
+
+ def comment text, top_level = @top_level
+ RDoc::Comment.new text, top_level
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::Document.new with +contents+
+
+ def doc *contents
+ @RM::Document.new(*contents)
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::HardBreak.new
+
+ def hard_break
+ @RM::HardBreak.new
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::Heading.new with +level+ and +text+
+
+ def head level, text
+ @RM::Heading.new level, text
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::ListItem.new with +label+ and +parts+
+
+ def item label = nil, *parts
+ @RM::ListItem.new label, *parts
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::List.new with +type+ and +items+
+
+ def list type = nil, *items
+ @RM::List.new type, *items
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::Paragraph.new with +contents+
+
+ def para *a
+ @RM::Paragraph.new(*a)
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::Rule.new with +weight+
+
+ def rule weight
+ @RM::Rule.new weight
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::Raw.new with +contents+
+
+ def raw *contents
+ @RM::Raw.new(*contents)
+ end
+
+ ##
+ # Creates a temporary directory changes the current directory to it for the
+ # duration of the block.
+ #
+ # Depends upon Dir.mktmpdir
+
+ def temp_dir
+ skip "No Dir::mktmpdir, upgrade your ruby" unless Dir.respond_to? :mktmpdir
+
+ Dir.mktmpdir do |temp_dir|
+ Dir.chdir temp_dir do
+ yield temp_dir
+ end
+ end
+ end
+
+ ##
+ # Shortcut for RDoc::Markup::Verbatim.new with +parts+
+
+ def verb *parts
+ @RM::Verbatim.new(*parts)
+ end
+
+end
+
+# This hack allows autoload to work when Dir.pwd is changed for Ruby 1.8 since
+# -I paths are not expanded.
+$LOAD_PATH.each do |load_path|
+ break if load_path[0] == ?/
+ load_path.replace File.expand_path load_path
+end if RUBY_VERSION < '1.9'
+
diff --git a/lib/rdoc/text.rb b/lib/rdoc/text.rb
index 3ac55ed560..c731dde097 100644
--- a/lib/rdoc/text.rb
+++ b/lib/rdoc/text.rb
@@ -6,11 +6,34 @@
require 'strscan'
##
+# For RDoc::Text#snippet
+
+begin
+ gem 'json'
+rescue Gem::LoadError
+end
+
+require 'json'
+
+##
# Methods for manipulating comment text
module RDoc::Text
##
+ # Maps markup formats to classes that can parse them. If the format is
+ # unknown, "rdoc" format is used.
+
+ MARKUP_FORMAT = {
+ 'markdown' => RDoc::Markdown,
+ 'rdoc' => RDoc::Markup,
+ 'rd' => RDoc::RD,
+ 'tomdoc' => RDoc::TomDoc,
+ }
+
+ MARKUP_FORMAT.default = RDoc::Markup
+
+ ##
# Maps an encoding to a Hash of characters properly transcoded for that
# encoding.
#
@@ -45,7 +68,7 @@ module RDoc::Text
expanded = []
text.each_line do |line|
- line.gsub!(/^(.{8}*?)([^\t\r\n]{0,7})\t/) do
+ line.gsub!(/^((?:.{8})*?)([^\t\r\n]{0,7})\t/) do
r = "#{$1}#{$2}#{' ' * (8 - $2.size)}"
r.force_encoding text.encoding if Object.const_defined? :Encoding
r
@@ -80,9 +103,7 @@ module RDoc::Text
# Requires the including class to implement #formatter
def markup text
- document = parse text
-
- document.accept formatter
+ parse(text).accept formatter
end
##
@@ -91,9 +112,10 @@ module RDoc::Text
def normalize_comment text
return text if text.empty?
- text = strip_hashes text
- text = expand_tabs text
- text = flush_left text
+ text = strip_stars text
+ text = strip_hashes text
+ text = expand_tabs text
+ text = flush_left text
text = strip_newlines text
text
end
@@ -101,35 +123,24 @@ module RDoc::Text
##
# Normalizes +text+ then builds a RDoc::Markup::Document from it
- def parse text
+ def parse text, format = 'rdoc'
return text if RDoc::Markup::Document === text
+ return text.parse if RDoc::Comment === text
- text = normalize_comment text
+ text = normalize_comment text # TODO remove, should not be necessary
return RDoc::Markup::Document.new if text =~ /\A\n*\z/
- RDoc::Markup::Parser.parse text
- rescue RDoc::Markup::Parser::Error => e
- $stderr.puts <<-EOF
-While parsing markup, RDoc encountered a #{e.class}:
-
-#{e}
-\tfrom #{e.backtrace.join "\n\tfrom "}
-
----8<---
-#{text}
----8<---
-
-RDoc #{RDoc::VERSION}
-
-Ruby #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL} #{RUBY_RELEASE_DATE}
+ MARKUP_FORMAT[format].parse text
+ end
-Please file a bug report with the above information at:
+ ##
+ # The first +limit+ characters of +text+ as HTML
-https://github.com/rdoc/rdoc/issues
+ def snippet text, limit = 100
+ document = parse text
- EOF
- raise
+ RDoc::Markup::ToHtmlSnippet.new(limit).convert document
end
##
@@ -155,6 +166,8 @@ https://github.com/rdoc/rdoc/issues
# Strips /* */ style comments
def strip_stars text
+ return text unless text =~ %r%/\*.*\*/%m
+
encoding = text.encoding if Object.const_defined? :Encoding
text = text.gsub %r%Document-method:\s+[\w:.#=!?]+%, ''
@@ -202,10 +215,10 @@ https://github.com/rdoc/rdoc/issues
until s.eos? do
case
- when s.scan(/<tt>.*?<\/tt>/) then # skip contents of tt
+ when s.scan(/<(tt|code)>.*?<\/\1>/) then # skip contents of tt
html << s.matched.gsub('\\\\', '\\')
- when s.scan(/<tt>.*?/) then
- warn 'mismatched <tt> tag' # TODO signal file/line
+ when s.scan(/<(tt|code)>.*?/) then
+ warn "mismatched <#{s[1]}> tag" # TODO signal file/line
html << s.matched
when s.scan(/<[^>]+\/?s*>/) then # skip HTML tags
html << s.matched
diff --git a/lib/rdoc/token_stream.rb b/lib/rdoc/token_stream.rb
index fb887f2fa4..851bc05bf5 100644
--- a/lib/rdoc/token_stream.rb
+++ b/lib/rdoc/token_stream.rb
@@ -8,6 +8,51 @@
module RDoc::TokenStream
##
+ # Converts +token_stream+ to HTML wrapping various tokens with
+ # <tt><span></tt> elements. The following tokens types are wrapped in spans
+ # with the given class names:
+ #
+ # TkCONSTANT :: 'ruby-constant'
+ # TkKW :: 'ruby-keyword'
+ # TkIVAR :: 'ruby-ivar'
+ # TkOp :: 'ruby-operator'
+ # TkId :: 'ruby-identifier'
+ # TkNode :: 'ruby-node'
+ # TkCOMMENT :: 'ruby-comment'
+ # TkREGEXP :: 'ruby-regexp'
+ # TkSTRING :: 'ruby-string'
+ # TkVal :: 'ruby-value'
+ #
+ # Other token types are not wrapped in spans.
+
+ def self.to_html token_stream
+ token_stream.map do |t|
+ next unless t
+
+ style = case t
+ when RDoc::RubyToken::TkCONSTANT then 'ruby-constant'
+ when RDoc::RubyToken::TkKW then 'ruby-keyword'
+ when RDoc::RubyToken::TkIVAR then 'ruby-ivar'
+ when RDoc::RubyToken::TkOp then 'ruby-operator'
+ when RDoc::RubyToken::TkId then 'ruby-identifier'
+ when RDoc::RubyToken::TkNode then 'ruby-node'
+ when RDoc::RubyToken::TkCOMMENT then 'ruby-comment'
+ when RDoc::RubyToken::TkREGEXP then 'ruby-regexp'
+ when RDoc::RubyToken::TkSTRING then 'ruby-string'
+ when RDoc::RubyToken::TkVal then 'ruby-value'
+ end
+
+ text = CGI.escapeHTML t.text
+
+ if style then
+ "<span class=\"#{style}\">#{text}</span>"
+ else
+ text
+ end
+ end.join
+ end
+
+ ##
# Adds +tokens+ to the collected tokens
def add_tokens(*tokens)
diff --git a/lib/rdoc/tom_doc.rb b/lib/rdoc/tom_doc.rb
new file mode 100644
index 0000000000..b95ef25d99
--- /dev/null
+++ b/lib/rdoc/tom_doc.rb
@@ -0,0 +1,233 @@
+# :markup: tomdoc
+
+# A parser for TomDoc based on TomDoc 1.0.0-rc1 (02adef9b5a)
+#
+# The TomDoc specification can be found at:
+#
+# http://tomdoc.org
+#
+# The latest version of the TomDoc specification can be found at:
+#
+# https://github.com/mojombo/tomdoc/blob/master/tomdoc.md
+#
+# To choose TomDoc as your only default format see RDoc::Options@Saved+Options
+# for instructions on setting up a <code>.rdoc_options</code> file to store
+# your project default.
+#
+# There are a few differences between this parser and the specification. A
+# best-effort was made to follow the specification as closely as possible but
+# some choices to deviate were made.
+#
+# A future version of RDoc will warn when a MUST or MUST NOT is violated and
+# may warn when a SHOULD or SHOULD NOT is violated. RDoc will always try
+# to emit documentation even if given invalid TomDoc.
+#
+# Here are some implementation choices this parser currently makes:
+#
+# This parser allows rdoc-style inline markup but you should not depended on
+# it.
+#
+# This parser allows a space between the comment and the method body.
+#
+# This parser does not require the default value to be described for an
+# optional argument.
+#
+# This parser does not examine the order of sections. An Examples section may
+# precede the Arguments section.
+#
+# This class is documented in TomDoc format. Since this is a subclass of the
+# RDoc markup parser there isn't much to see here, unfortunately.
+
+class RDoc::TomDoc < RDoc::Markup::Parser
+
+ # Internal: Token accessor
+
+ attr_reader :tokens
+
+ # Internal: Adds a post-processor which sets the RDoc section based on the
+ # comment's status.
+ #
+ # Returns nothing.
+
+ def self.add_post_processor # :nodoc:
+ RDoc::Markup::PreProcess.post_process do |comment, code_object|
+ next unless code_object and
+ RDoc::Comment === comment and comment.format == 'tomdoc'
+
+ comment.text.gsub!(/(\A\s*# )(Public|Internal|Deprecated):\s+/) do
+ section = code_object.add_section $2
+ code_object.temporary_section = section
+
+ $1
+ end
+ end
+ end
+
+ add_post_processor
+
+ # Public: Parses TomDoc from text
+ #
+ # text - A String containing TomDoc-format text.
+ #
+ # Examples
+ #
+ # RDoc::TomDoc.parse <<-TOMDOC
+ # This method does some things
+ #
+ # Returns nothing.
+ # TOMDOC
+ # # => #<RDoc::Markup::Document:0xXXX @parts=[...], @file=nil>
+ #
+ # Returns an RDoc::Markup::Document representing the TomDoc format.
+
+ def self.parse text
+ parser = new
+
+ parser.tokenize text
+ doc = RDoc::Markup::Document.new
+ parser.parse doc
+ doc
+ end
+
+ # Internal: Extracts the Signature section's method signature
+ #
+ # comment - An RDoc::Comment that will be parsed and have the signature
+ # extracted
+ #
+ # Returns a String containing the signature and nil if not
+
+ def self.signature comment
+ return unless comment.tomdoc?
+
+ document = comment.parse
+
+ signature = nil
+ found_heading = false
+ found_signature = false
+
+ document.parts.delete_if do |part|
+ next false if found_signature
+
+ found_heading ||=
+ RDoc::Markup::Heading === part && part.text == 'Signature'
+
+ next false unless found_heading
+
+ next true if RDoc::Markup::BlankLine === part
+
+ if RDoc::Markup::Verbatim === part then
+ signature = part
+ found_signature = true
+ end
+ end
+
+ signature and signature.text
+ end
+
+ # Public: Creates a new TomDoc parser. See also RDoc::Markup::parse
+
+ def initialize
+ super
+
+ @section = nil
+ end
+
+ # Internal: Builds a heading from the token stream
+ #
+ # level - The level of heading to create
+ #
+ # Returns an RDoc::Markup::Heading
+
+ def build_heading level
+ heading = super
+
+ @section = heading.text
+
+ heading
+ end
+
+ # Internal: Builds a verbatim from the token stream. A verbatim in the
+ # Examples section will be marked as in ruby format.
+ #
+ # margin - The indentation from the margin for lines that belong to this
+ # verbatim section.
+ #
+ # Returns an RDoc::Markup::Verbatim
+
+ def build_verbatim margin
+ verbatim = super
+
+ verbatim.format = :ruby if @section == 'Examples'
+
+ verbatim
+ end
+
+ # Internal: Builds a paragraph from the token stream
+ #
+ # margin - Unused
+ #
+ # Returns an RDoc::Markup::Paragraph.
+
+ def build_paragraph margin
+ p :paragraph_start => margin if @debug
+
+ paragraph = RDoc::Markup::Paragraph.new
+
+ until @tokens.empty? do
+ type, data, = get
+
+ if type == :TEXT then
+ paragraph << data
+ skip :NEWLINE
+ else
+ unget
+ break
+ end
+ end
+
+ p :paragraph_end => margin if @debug
+
+ paragraph
+ end
+
+ # Internal: Turns text into an Array of tokens
+ #
+ # text - A String containing TomDoc-format text.
+ #
+ # Returns self.
+
+ def tokenize text
+ text.sub!(/\A(Public|Internal|Deprecated):\s+/, '')
+
+ setup_scanner text
+
+ until @s.eos? do
+ pos = @s.pos
+
+ # leading spaces will be reflected by the column of the next token
+ # the only thing we loose are trailing spaces at the end of the file
+ next if @s.scan(/ +/)
+
+ @tokens << case
+ when @s.scan(/\r?\n/) then
+ token = [:NEWLINE, @s.matched, *token_pos(pos)]
+ @line_pos = char_pos @s.pos
+ @line += 1
+ token
+ when @s.scan(/(Examples|Signature)$/) then
+ @tokens << [:HEADER, 3, *token_pos(pos)]
+
+ [:TEXT, @s[1], *token_pos(pos)]
+ when @s.scan(/([:\w]\w*)[ ]+- /) then
+ [:NOTE, @s[1], *token_pos(pos)]
+ else
+ @s.scan(/.*/)
+ [:TEXT, @s.matched.sub(/\r$/, ''), *token_pos(pos)]
+ end
+ end
+
+ self
+ end
+
+end
+
diff --git a/lib/rdoc/top_level.rb b/lib/rdoc/top_level.rb
index 3825a091fe..9cf38539de 100644
--- a/lib/rdoc/top_level.rb
+++ b/lib/rdoc/top_level.rb
@@ -1,10 +1,10 @@
-require 'rdoc/context'
-
##
# A TopLevel context is a representation of the contents of a single file
class RDoc::TopLevel < RDoc::Context
+ MARSHAL_VERSION = 0 # :nodoc:
+
##
# This TopLevel's File::Stat struct
@@ -35,267 +35,9 @@ class RDoc::TopLevel < RDoc::Context
attr_accessor :parser
##
- # Returns all classes discovered by RDoc
-
- def self.all_classes
- @all_classes_hash.values
- end
-
- ##
- # Returns all classes and modules discovered by RDoc
-
- def self.all_classes_and_modules
- @all_classes_hash.values + @all_modules_hash.values
- end
-
- ##
- # Hash of all classes known to RDoc
-
- def self.all_classes_hash
- @all_classes_hash
- end
-
- ##
- # All TopLevels known to RDoc
-
- def self.all_files
- @all_files_hash.values
- end
-
- ##
- # Hash of all files known to RDoc
-
- def self.all_files_hash
- @all_files_hash
- end
-
- ##
- # Returns all modules discovered by RDoc
-
- def self.all_modules
- all_modules_hash.values
- end
-
- ##
- # Hash of all modules known to RDoc
-
- def self.all_modules_hash
- @all_modules_hash
- end
-
- ##
- # Prepares the RDoc code object tree for use by a generator.
- #
- # It finds unique classes/modules defined, and replaces classes/modules that
- # are aliases for another one by a copy with RDoc::ClassModule#is_alias_for
- # set.
- #
- # It updates the RDoc::ClassModule#constant_aliases attribute of "real"
- # classes or modules.
- #
- # It also completely removes the classes and modules that should be removed
- # from the documentation and the methods that have a visibility below
- # +min_visibility+, which is the <tt>--visibility</tt> option.
- #
- # See also RDoc::Context#remove_from_documentation?
-
- def self.complete min_visibility
- fix_basic_object_inheritance
-
- # cache included modules before they are removed from the documentation
- all_classes_and_modules.each { |cm| cm.ancestors }
-
- remove_nodoc @all_classes_hash
- remove_nodoc @all_modules_hash
-
- @unique_classes = find_unique @all_classes_hash
- @unique_modules = find_unique @all_modules_hash
-
- unique_classes_and_modules.each do |cm|
- cm.complete min_visibility
- end
-
- @all_files_hash.each_key do |file_name|
- tl = @all_files_hash[file_name]
-
- unless RDoc::Parser::Simple === tl.parser then
- tl.modules_hash.clear
- tl.classes_hash.clear
-
- tl.classes_or_modules.each do |cm|
- name = cm.full_name
- if cm.type == 'class' then
- tl.classes_hash[name] = cm if @all_classes_hash[name]
- else
- tl.modules_hash[name] = cm if @all_modules_hash[name]
- end
- end
- end
- end
- end
-
- ##
- # Finds the class with +name+ in all discovered classes
-
- def self.find_class_named(name)
- @all_classes_hash[name]
- end
-
- ##
- # Finds the class with +name+ starting in namespace +from+
-
- def self.find_class_named_from name, from
- from = find_class_named from unless RDoc::Context === from
-
- until RDoc::TopLevel === from do
- return nil unless from
-
- klass = from.find_class_named name
- return klass if klass
-
- from = from.parent
- end
-
- find_class_named name
- end
-
- ##
- # Finds the class or module with +name+
-
- def self.find_class_or_module(name)
- name = $' if name =~ /^::/
- RDoc::TopLevel.classes_hash[name] || RDoc::TopLevel.modules_hash[name]
- end
-
- ##
- # Finds the file with +name+ in all discovered files
-
- def self.find_file_named(name)
- @all_files_hash[name]
- end
-
- ##
- # Finds the module with +name+ in all discovered modules
-
- def self.find_module_named(name)
- modules_hash[name]
- end
-
- ##
- # Finds unique classes/modules defined in +all_hash+,
- # and returns them as an array. Performs the alias
- # updates in +all_hash+: see ::complete.
- #--
- # TODO aliases should be registered by Context#add_module_alias
-
- def self.find_unique(all_hash)
- unique = []
-
- all_hash.each_pair do |full_name, cm|
- unique << cm if full_name == cm.full_name
- end
-
- unique
- end
-
- ##
- # Fixes the erroneous <tt>BasicObject < Object</tt> in 1.9.
- #
- # Because we assumed all classes without a stated superclass
- # inherit from Object, we have the above wrong inheritance.
- #
- # We fix BasicObject right away if we are running in a Ruby
- # version >= 1.9. If not, we may be documenting 1.9 source
- # while running under 1.8: we search the files of BasicObject
- # for "object.c", and fix the inheritance if we find it.
-
- def self.fix_basic_object_inheritance
- basic = all_classes_hash['BasicObject']
- return unless basic
- if RUBY_VERSION >= '1.9'
- basic.superclass = nil
- elsif basic.in_files.any? { |f| File.basename(f.full_name) == 'object.c' }
- basic.superclass = nil
- end
- end
-
- ##
- # Creates a new RDoc::TopLevel with +file_name+ only if one with the same
- # name does not exist in all_files.
-
- def self.new file_name
- if top_level = @all_files_hash[file_name] then
- top_level
- else
- top_level = super
- @all_files_hash[file_name] = top_level
- top_level
- end
- end
-
- ##
- # Removes from +all_hash+ the contexts that are nodoc or have no content.
- #
- # See RDoc::Context#remove_from_documentation?
-
- def self.remove_nodoc(all_hash)
- all_hash.keys.each do |name|
- context = all_hash[name]
- all_hash.delete(name) if context.remove_from_documentation?
- end
- end
-
- ##
- # Empties RDoc of stored class, module and file information
-
- def self.reset
- @all_classes_hash = {}
- @all_modules_hash = {}
- @all_files_hash = {}
- end
-
- ##
- # Returns the unique classes discovered by RDoc.
- #
- # ::complete must have been called prior to using this method.
-
- def self.unique_classes
- @unique_classes
- end
-
- ##
- # Returns the unique classes and modules discovered by RDoc.
- # ::complete must have been called prior to using this method.
-
- def self.unique_classes_and_modules
- @unique_classes + @unique_modules
- end
-
- ##
- # Returns the unique modules discovered by RDoc.
- # ::complete must have been called prior to using this method.
-
- def self.unique_modules
- @unique_modules
- end
-
- class << self
- alias classes all_classes
- alias classes_hash all_classes_hash
-
- alias files all_files
- alias files_hash all_files_hash
-
- alias modules all_modules
- alias modules_hash all_modules_hash
- end
-
- reset
-
- ##
# Creates a new TopLevel for +file_name+
- def initialize(file_name)
+ def initialize file_name
super()
@name = nil
@relative_name = file_name
@@ -305,15 +47,13 @@ class RDoc::TopLevel < RDoc::Context
@parser = nil
@classes_or_modules = []
-
- RDoc::TopLevel.files_hash[file_name] = self
end
##
# An RDoc::TopLevel is equal to another with the same absolute_name
def == other
- other.class === self and @absolute_name == other.absolute_name
+ self.class === other and @absolute_name == other.absolute_name
end
alias eql? ==
@@ -330,7 +70,7 @@ class RDoc::TopLevel < RDoc::Context
##
# Adds +constant+ to +Object+ instead of +self+.
- def add_constant(constant)
+ def add_constant constant
object_class.record_location self
return constant unless @document_self
object_class.add_constant constant
@@ -372,13 +112,21 @@ class RDoc::TopLevel < RDoc::Context
alias name base_name
##
+ # Only a TopLevel that contains text file) will be displayed. See also
+ # RDoc::CodeObject#display?
+
+ def display?
+ text? and super
+ end
+
+ ##
# See RDoc::TopLevel::find_class_or_module
#--
# TODO Why do we search through all classes/modules found, not just the
# ones of this instance?
def find_class_or_module name
- RDoc::TopLevel.find_class_or_module name
+ @store.find_class_or_module name
end
##
@@ -436,23 +184,56 @@ class RDoc::TopLevel < RDoc::Context
end
##
+ # Dumps this TopLevel for use by ri. See also #marshal_load
+ def marshal_dump
+ [
+ MARSHAL_VERSION,
+ @absolute_name,
+ @parser,
+ parse(@comment),
+ ]
+ end
+
+ ##
+ # Loads this TopLevel from +array+.
+
+ def marshal_load array # :nodoc:
+ initialize array[1]
+
+ @parser = array[2]
+ @comment = array[3]
+
+ @file_stat = nil
+ end
+
+ ##
# Returns the NormalClass "Object", creating it if not found.
#
# Records +self+ as a location in "Object".
def object_class
@object_class ||= begin
- oc = self.class.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object')
+ oc = @store.find_class_named('Object') || add_class(RDoc::NormalClass, 'Object')
oc.record_location self
oc
end
end
##
- # Path to this file
+ # Base name of this file without the extension
+
+ def page_name
+ basename = File.basename @absolute_name
+ basename =~ /\.[^.]*$/
+
+ $` || basename
+ end
+
+ ##
+ # Path to this file for use with HTML generator output.
def path
- http_url RDoc::RDoc.current.generator.file_dir
+ http_url @store.rdoc.generator.file_dir
end
def pretty_print q # :nodoc:
@@ -461,11 +242,35 @@ class RDoc::TopLevel < RDoc::Context
q.breakable
items = @modules.map { |n,m| m }
- items.push(*@modules.map { |n,c| c })
+ items.concat @modules.map { |n,c| c }
q.seplist items do |mod| q.pp mod end
end
end
+ ##
+ # Search record used by RDoc::Generator::JsonIndex
+
+ def search_record
+ return unless @parser < RDoc::Parser::Text
+
+ [
+ page_name,
+ '',
+ page_name,
+ '',
+ path,
+ '',
+ snippet(@comment),
+ ]
+ end
+
+ ##
+ # Is this TopLevel from a text file instead of a source code file?
+
+ def text?
+ @parser and @parser.ancestors.include? RDoc::Parser::Text
+ end
+
def to_s # :nodoc:
"file #{full_name}"
end