diff options
author | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-11-27 04:28:14 +0000 |
---|---|---|
committer | drbrain <drbrain@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-11-27 04:28:14 +0000 |
commit | 1c279a7d2753949c725754e1302f791b76358114 (patch) | |
tree | 36aa3bdde250e564445eba5f2e25fcb96bcb6cef /lib/rdoc | |
parent | c72f0daa877808e4fa5018b3191ca09d4b97c03d (diff) | |
download | ruby-1c279a7d2753949c725754e1302f791b76358114.tar.gz |
* lib/rdoc*: Updated to RDoc 4.0 (pre-release)
* bin/rdoc: ditto
* test/rdoc: ditto
* NEWS: Updated with RDoc 4.0 information
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@37889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'lib/rdoc')
132 files changed, 30161 insertions, 3441 deletions
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">↑ 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(/(.*)[-=]>/, '\1→') %> + </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&height=550&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">↑ 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(/->/, '→').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 Binary files differnew file mode 100755 index 0000000000..6332fefea4 --- /dev/null +++ b/lib/rdoc/generator/template/darkfish/images/add.png diff --git a/lib/rdoc/generator/template/darkfish/images/arrow_up.png b/lib/rdoc/generator/template/darkfish/images/arrow_up.png Binary files differnew file mode 100755 index 0000000000..1ebb193243 --- /dev/null +++ b/lib/rdoc/generator/template/darkfish/images/arrow_up.png diff --git a/lib/rdoc/generator/template/darkfish/images/delete.png b/lib/rdoc/generator/template/darkfish/images/delete.png Binary files differnew file mode 100755 index 0000000000..08f249365a --- /dev/null +++ b/lib/rdoc/generator/template/darkfish/images/delete.png diff --git a/lib/rdoc/generator/template/darkfish/images/tag_blue.png b/lib/rdoc/generator/template/darkfish/images/tag_blue.png Binary files differnew file mode 100755 index 0000000000..3f02b5f8f8 --- /dev/null +++ b/lib/rdoc/generator/template/darkfish/images/tag_blue.png diff --git a/lib/rdoc/generator/template/darkfish/images/transparent.png b/lib/rdoc/generator/template/darkfish/images/transparent.png Binary files differnew file mode 100644 index 0000000000..d665e179ef --- /dev/null +++ b/lib/rdoc/generator/template/darkfish/images/transparent.png 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 %> — <%= 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&©&&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&¬xml&&!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&¬xml&&name=="style")return jQuery.attr(elem.style,"cssText",value);if(set)elem.setAttribute(name,""+value);var attr=msie&¬xml&&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 %> — <%= 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 << " — " 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 |