[Mapbender-commits] r2119 - in trunk/build: . JSDoc JSDoc/JSDoc
JSDoc/JavaScript JSDoc/JavaScript/Syntax
svn_mapbender at osgeo.org
svn_mapbender at osgeo.org
Wed Feb 20 06:31:03 EST 2008
Author: christoph
Date: 2008-02-20 06:31:02 -0500 (Wed, 20 Feb 2008)
New Revision: 2119
Added:
trunk/build/JSDoc/
trunk/build/JSDoc/.jsdoc_config
trunk/build/JSDoc/CHANGES
trunk/build/JSDoc/JSDoc.pm
trunk/build/JSDoc/JSDoc/
trunk/build/JSDoc/JSDoc/XMI.pm
trunk/build/JSDoc/JSDoc/XML.pm
trunk/build/JSDoc/JSDoc/xmi.tmpl
trunk/build/JSDoc/JSDoc/xml.tmpl
trunk/build/JSDoc/JavaScript/
trunk/build/JSDoc/JavaScript/Syntax/
trunk/build/JSDoc/JavaScript/Syntax/HTML.pm
trunk/build/JSDoc/README
trunk/build/JSDoc/TODO
trunk/build/JSDoc/TestJSDoc.pl
trunk/build/JSDoc/allclasses-frame.tmpl
trunk/build/JSDoc/allclasses-noframe.tmpl
trunk/build/JSDoc/constant-values.tmpl
trunk/build/JSDoc/help-doc.tmpl
trunk/build/JSDoc/index-all.tmpl
trunk/build/JSDoc/index.tmpl
trunk/build/JSDoc/jsdoc.pl
trunk/build/JSDoc/main.tmpl
trunk/build/JSDoc/overview-frame.tmpl
trunk/build/JSDoc/overview-summary.tmpl
trunk/build/JSDoc/overview-tree.tmpl
trunk/build/JSDoc/stylesheet.css
trunk/build/JSDoc/test.js
Log:
JSDoc
Added: trunk/build/JSDoc/.jsdoc_config
===================================================================
--- trunk/build/JSDoc/.jsdoc_config (rev 0)
+++ trunk/build/JSDoc/.jsdoc_config 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,47 @@
+#
+# Configuration file for JSDoc
+#
+# The following hashes are used for supplying user-defined @attribute tags
+# that will be parsed. Non-standard attributes (such as @subclass) can be
+# added into these hashes, along with a code reference. The return value
+# from the code reference will be included in the documentation. All
+# non-standard tags that are not in the below hashes will be ignored.
+# The code reference will receive a reference to an array of
+# values that were supplied with the @... tag
+#
+
+# Class attributes
+#eval {
+# $CLASS_ATTRS_MAP{subclass} =
+# # subclass is the name of the @... tag
+# sub {
+# # Body from which a string is returned
+# '<DT><B>Subclasses:</B><DD>-' .
+# join('<DD>-',
+# map ({"<A HREF=\"$_.html\">$_</A>"}
+# map ( { s/\s*(\w+)\s*/$1/; $_} @{@_->[0]})
+# )
+# ) . '<P>'
+# };
+#
+# $CLASS_ATTRS_MAP{with} =
+# sub {
+# 'This class has a \'@with\' attribute'
+# };
+#};
+
+# Method attributes
+# eval {
+#
+# Uncomment this to allow the filename to be displayed for
+# each function
+#
+# $METHOD_ATTRS_MAP{filename} =
+# sub {
+# '<DT><B>Filename:</B> ' . $_[0] . '<P>'
+# };
+# $CLASS_ATTRS_MAP{filename} = $METHOD_ATTRS_MAP{filename};
+#
+# };
+#
+
Added: trunk/build/JSDoc/CHANGES
===================================================================
--- trunk/build/JSDoc/CHANGES (rev 0)
+++ trunk/build/JSDoc/CHANGES 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,622 @@
+JSDoc 1.10.2
+============
+
+- Fixed broken links to non-existant classes
+
+JSDoc 1.10.1
+============
+
+- Added support for @singleton tag, as supplied by Jeffrey To
+- Fixes to constants templates as supplied by Jeffrey To
+
+JSDoc 1.10
+==========
+
+- Added nested directory structure, as requested by Nitobi
+- Added @implements tag, as requested by Nitobi
+
+JSDoc 1.9.9.2
+=============
+
+- Fixed disappearing argument list for package-style class constructors
+
+JSDoc 1.9.9.1
+=============
+
+- Fixed bug in template dir designation that caused JSDoc to crash if
+ run from an absolute path
+
+JSDoc 1.9.9
+===========
+
+- Added a commandline parameter for supplying a template directory
+
+- Adding sorting of class names on overview-summary-$filename.js
+ (sf.net bug #1416564)
+
+- Fix for broken anchors from the overview-summary-$filename page to static
+ methods (SF.net bug #1416543)
+
+JSDoc 1.9.8.1
+=============
+
+- Don't touch the file source (src) when processing the file overview data
+
+- Pick up functions as constructors of the @class tag is used
+
+JSDoc 1.9.8
+===========
+
+- Allow the @base tag to accept the form: @base ClassName URL (RFE 1114510)
+
+- Be more lenient with @param and @return types (RFE 1104728)
+
+- Corrected CSS error, changed "pts" to "pt"
+
+JSDoc 1.9.7
+===========
+
+- Added "--no-lexical-privates" option to ignore locally-defined values
+ from within constructors
+
+- Fixed linking to static fields/methods
+
+JSDoc 1.9.6.2
+=============
+
+- Set correct permissions on files in packaging script
+
+- Fixed compile error on some versions of perl
+
+- Create distinct anchors for static methods and fields in HTML so that
+ if there is a static and instance method of the same name, the links work
+ correctly
+
+JSDoc 1.9.6.1
+=============
+
+- Updated unit tests for clearing of function contents
+
+- Removed collapsing of string literals; this was originally added for version
+ 1.9.5.1 to avoid segfaults, but the decision has been made that it is up
+ to the user to use a version of perl that doesn't segfault instead of
+ trying to work around it in perl code.
+
+- Added (experimental) @exec tag for initialization blocks that should be 'run'
+
+JSDoc 1.9.6
+===========
+
+- Fix for incorrect return type and parameter types for static method
+ listing in file overview
+
+- Clear out unused nested functions with the preprocessor to avoid problems
+
+JSDoc 1.9.5.8
+=============
+
+- Yet another fix for __defineGetter__ and __defineSetter__
+
+JSDoc 1.9.5.7
+=============
+
+- Fixed bug in syntax highlighting for single-line inline comments
+
+- Fixed bug in preprocessing of __defineGetter__ and __defineSetter__
+
+JSDoc 1.9.5.6
+=============
+
+- Fixed incorrect listing of private classes when --private not enabled
+
+JSDoc 1.9.5.4
+=============
+
+- Corrected bug with function assignment inside constructor
+
+JSDoc 1.9.5.3
+=============
+
+- Added ability to specify different file extensions on commandline
+
+JSDoc 1.9.5.2
+=============
+
+- Fixed formatted text munging for @class description
+
+- Added support for @package tag to be used with XMI export
+
+JSDoc 1.9.5.1
+=============
+
+- Added collapsing of string literals during preprocessing
+
+JSDoc 1.9.5
+===========
+
+- Added listing of global (static) methods to file overview summary, code
+ submitted by Jeremy Gillick
+
+- Allow a global variable to be defined as a class from an anonymous
+ function declaration
+
+JSDoc 1.9.4.2.1
+===============
+
+- Further fix for typed parameter names starting with a dollar sign
+
+JSDoc 1.9.4.2
+=============
+
+- Added ability to handle parameter names starting with a dollar sign
+
+JSDoc 1.9.4.1
+=============
+
+- Only use the first sentence for file and class summary on the
+ overview pages
+
+- Add a non-breaking space in the overview summary tables when there is no
+ appropriate value to display
+
+JSDoc 1.9.4
+===========
+
+- If there are multiple source files documented, the index page defaults
+ to the overview summary for the main frame
+
+- Made JSDoc site link open in parent frame
+
+- Added overview and file summary tables (similar to package overview table
+ in JavaDoc)
+
+JSDoc 1.9.3.1
+=============
+
+- Fixed duplicate class-tree output
+
+JSDoc 1.9.3
+===========
+
+- Added alpha release of XML and XMI output formats
+
+- Upgrade a function to a class if the @base tag is used
+
+- Fixed issue with sub-package nested classes requiring the @addon tag
+
+- Added the implicit "Object" class to the inheritance tree, as well as
+ other classes that are referenced but not defined
+
+JSDoc 1.9.2.1
+=============
+
+- Added @addon tag, which is used when adding static methods to core classes
+ or classes not defined within the files being documented
+
+- Fix for the base class of nested classes not being properly set
+
+- Fix for infinite recursion when all classes are private
+
+
+JSDoc 1.9.2
+===========
+
+- Removed unecessary table from overview-summary.tmpl
+
+- Added the @ignore tag to allow total hiding of functions
+
+- Fix for incorrect marking of methods as void when the return value is
+ enclosed in parentheses
+
+- Fix so that methods with a @return tag but without a return statement
+ are not marked as void
+
+- Fixed issue with not all files being listed in the file listing
+
+
+JSDoc 1.9.1.3
+=============
+
+- Fixed issue with backslashes in path
+
+- Fixed issue with <pre> tags and JavaScript code within fileoverview sections
+
+- Made documented versions of a method take precedence over a
+ non-documented version
+
+- Added support for prototype assignment without parentheses
+
+- Added new @return label {type typeLink} Description... syntax
+
+JSDoc 1.9.1.2
+=============
+
+- Further improvements to mark_void_method
+
+- Improved handling of dynamically-bound methods within functions
+
+- Improved handling of erroneous documenting of 'this'
+
+- Fixed quoting on error message
+
+- Added a few new unit tests for testing general behaviour
+
+JSDoc 1.9.1.1
+=============
+
+- Fix for embarrassing bug in mark_void_method
+
+JSDoc 1.9.1
+===========
+
+- Fix for the incorrect void marking of methods that return a string literal
+
+- Fix to stop dynamic prototyping from adding non-dynamic classes
+
+- Added ability to add a link to parameter-type data, as follows:
+ @param {TypeName http://my.link.com/} myParam Description of parameter
+
+JSDoc 1.9
+=========
+
+- Added support for a Constant Values page like in Javadoc
+
+- Added support for private classes (by marking the constructor with
+ the @private attribute)
+
+- Added a "File" page with links to it in the navbar. The "File" page includes
+ the file overview if one has been supplied, as well as the source view
+ (unless jsdoc has been invoked with the --no-sources flag)
+
+- Added a --no-sources commandline option to not show the sourcecode for
+ the JavaScript files
+
+- Added --package-naming commandline option, which specifies that the path
+ leading to each source file will be preserved. This allows for the same
+ filename to be used in different directories. Using the same class name
+ in different packages is _not_ supported (yet)
+
+- Added JSDoc link and creation time in the footer of each page
+
+- Added support for @member tag to explicitly mark a method as a member of
+ a class
+
+JSDoc 1.8.4
+===========
+
+- Added step in prepocessing to attempt to add missing @constructor tags where
+ the 'new' operator is used in combination with a function name elsewhere
+ in the source.
+
+- Only the first @extends marking (or assignment of an instance to a sub-
+ class's prototype) will be used in determining the base class of a class.
+
+- Updated test.js to show off more features of JSDoc, as well as a general
+ clean-up.
+
+- Changed the parser to consider a method to be a class declaration if its
+ documentation contains a @class tag (in addition to the @constructor tag)
+
+JSDoc 1.8.3.1
+=============
+
+- Some general code cleanup and refactoring.
+
+- Properly fixed marking of void/non-void methods, and at the same time
+ re-introduced recursive regexes (this time non-dynamic, as dynamic seem
+ to be much too unstable)
+
+JSDoc 1.8.3
+===========
+
+- Changed the handling for __defineGetter__ and __defineSetter__
+ to define a property instead of a method in the documentation
+
+- Fixed bug in parse_jsdoc_comment that didn't allow for email addresses
+ to be entered verbatim (instead, the domain of the address was parsed
+ as a tag)
+
+- Re-did the @fileoverview parsing, now other tags and inner {@link...}
+ tags are included. Additionally, if only one file is processed and there
+ is no project overview file included, the file's overview (if it exists)
+ is used as the project overview. Thanks to Robert Flaherty for input
+ and bug reports on this issue.
+
+JSDoc 1.8.2.1
+=============
+
+- Got rid of extra '*' with @fileoverview
+
+JSDoc 1.8.2
+=============
+
+- Fixed bug where other @tags were included as part of the @fileoverview
+
+- Added support for @version in method documentation
+
+- Partial fix for incorrect marking of void methods
+
+- Made field and return @type handling more robust and flexible
+
+JSDoc 1.8.1
+===========
+
+- Added @extends as a synonym for @base
+
+- Fixed doubled-up <UL> tags in hierarchy tree code (thanks to Robert Flaherty)
+
+- Fixed bug where a class's base class would not get recorded if
+ there was a forward assignment of a static value to the class
+ (thanks to Robert Flaherty)
+
+
+JSDoc 1.8
+=========
+
+- Remove the GLOBALS class if it is empty
+
+- Fixed case-sensitive sort in index
+
+- Added support for comments with long blocks of '*'s in the opening and
+ closing of the doc string
+
+- Added sourcecode view
+
+- Fixed bug where named anonymous functions were not recognized as methods
+ when assigned to prototypes
+
+- Allow for singletons to be declared with var
+
+- Allow for binding static properties to classes before they are defined
+
+- Added @overviewfile attribute for class documentation, inlines html or
+ textfiles into the documentation
+
+- Added beginnings of unit testing
+
+- Don't add 'constructor' as an instance or class property
+
+- Added an @overviewfile tag which can be put in an independent
+ jsdoc-comment block at the top of each file. This results in a project
+ overview page for each file with an overview, similar to JavaDoc's
+ package pages.
+
+- Added support for Mozilla's __defineGetter__ and __defineSetter__
+
+- Return type for methods is now Object, and is displayed instead of the
+ 'function' declaration. The 'void' type is shown if no return can be
+ found in the function and no other type is defined. The defaulting to
+ Object also goes for fields, and is shown instead of the 'var' declaration
+
+- Allow usage of the {@link url label} construct for the @type tag
+
+
+JSDoc 1.7.2.1
+=============
+
+- Fixed segfault problem in huge constructors with deconstruct_constructor
+ selection regex
+
+
+JSDoc 1.7.2
+===========
+
+- Added a @class tag to constructors, for providing class-specific information
+
+- Added handling for Singleton classes
+
+- Added handler for @base tag to denote inheritance
+
+JSDoc 1.7.1.4
+=============
+
+- Fixed bug introduced by refactoring of &format_link
+
+JSDoc 1.7.1.3
+=============
+
+- Added workaround in &format_link for apparent bug in some builds of
+ perl 5.8.0
+
+- Fixed bug in handling of --recursive (was always recursive)
+
+JSDoc 1.7.1.2
+=============
+
+- Fixed problems with new preprocessor when confronted with nested classes
+
+JSDoc 1.7.1.1
+=============
+
+- Fixed bug where {@link}s inside of @params weren't processed
+
+JSDoc 1.7.1
+===========
+
+- Added --quiet switch and message to signify ending of successful execution
+
+- Fixed problem with perl segfaulting on big class prototype block definitions
+
+- Fixed incorrectly formatted {@link}s nested in other @attributes
+
+- Added preprocessor for handling private methods to replace bulky
+ and buggy evaluate_constructor method
+
+JSDoc 1.7
+=========
+
+- Added usage of strict and warnings in JSDoc.pm
+
+- Added ability to set type information for method parameters
+ (e.g. /** @param {String} userName The name of the current user */ )
+
+- Added support for class prototype initialization blocks (finally!)
+
+JSDoc 1.6.3.1
+=============
+
+- Fixed bug where static fields initialized to 0 are not picked up
+
+JSDoc 1.6.3
+===========
+
+- Removed the constraint that a nested class constructor must be marked
+ with the @constructor attribute
+
+- Allow @constructor attribute to mark nested class constructors which would
+ otherwise be considered static methods
+
+- Allow newlines as well as semi-colon for line-endings
+
+- Allow a leading '$' for field names
+
+
+JSDoc 1.6.2.1
+=============
+
+- Fixed splicing error for nested classes, thanks again to jdber
+
+
+JSDoc 1.6.2
+===========
+
+- Carry over overridden method description attributes even if there is
+ no text description to carry over
+
+- Improved HTML in main.tmpl
+
+- Fixed infinite loop and recognition for when static inner class construct is
+ used (thanks to jdber for the patch)
+
+- Added a Nested Class Summary section to the output documentation to display
+ inner classes
+
+JSDoc 1.6.1.1
+=============
+
+- Fixed bug in carrying over description of overridden methods
+
+JSDoc 1.6.1
+===========
+
+- Improved the format_link function in jsdoc.pl so that {@links} will
+ not be made to non-existent resources, and parentheses are not placed
+ after a field name (as opposed to a method name)
+
+- Carry over method documentation for overridden methods if no new
+ documentation has been supplied for the method. This is in following with
+ javadoc functionality
+
+- Fixed /* functionality(whatever) bug
+
+- Fixed remaining problems with comments inside of parameter lists
+
+JSDoc 1.6
+=========
+
+- Big cleanup in jsdoc.pl in terms of writing templates to file
+
+- Fixed bug where multi-line @params don't work
+
+- Added filename-scoped frame, as well as the name of the filename for
+ each class
+
+- Improved the linking implementation for @link and @see to do a better job
+ in terms of not building broken links
+
+JSDoc 1.5.2
+===========
+
+- Changed the name '[default context]' for non-class functions to be
+ GLOBALS, also made this name configurable with command-line parameters
+
+- Made jsdoc easily runnable from anywhere on the filesystem, without
+ requiring installing JSDoc.pm in the @INC
+
+JSDoc 1.5.1
+===========
+
+- Added support for @requires in methods
+
+- Generic '@' attributes now work for constructors, such as @see and @throws.
+ Also added support for @return and @returns for constructors
+
+- Fixed the @link construct to allow custom labels
+
+- Added standard support for @author in methods as well as classes
+ (Thanks for Rainer Eschen for bringing me to my senses)
+
+- Fixed spacing for @author attributes
+
+
+JSDoc 1.5
+===========
+
+- Fixed bug that would break HTML links within documentation
+
+- Fixed bug in path to logo in IMG tags
+
+- Added support for type information for both methods and fields
+
+- Added suppport for @private in instance fields
+
+- Fixed bug where private methods would show up in the inherited methods list
+ in subclasses
+
+- Private class methods are now also supported
+
+- Method parameters details are displayed in the same order as the parameter
+ list for a method
+
+- Moved more info into the 'vars' member of methods, and away from the parser
+
+- Added @final (with synonym @const) for class and instance properties
+
+- Fix in parser where string literals bound to classes in a constructor were
+ not caught by the parser
+
+
+
+JSDoc 1.4
+=========
+
+- Added @attributes: @author, @deprecated, @see, @version, @requires, @throws
+
+- Updated pod (removed documentation for non-existant parse_jsdoc_source,
+added a small example)
+
+- Added function to reset the parser (reset_parser)
+
+- Fixed bug where the same property could be bound to a class's prototype
+more than once
+
+- Fixed bug where embedded // comments would break the parser
+
+- Added ability to set project name, page footer, logo and project summary
+(thanks to Jeff Conrad for code and suggestions)
+
+- Added overview summary (thanks to Jeff Conrad for code)
+
+- Split up loading/parsing of sources file to prevent crashes that were caused
+by overloading the regex engine
+
+- Added overview-tree (thanks to Jeff Conrad for the code contribution)
+
+- Fixed bug where some assignments of methods to instances in a constructor
+would get lost
+
+- Fix in doc-parsing where a line with only a star and a newline would get
+passed over
+
+- Added ability to 'hide' methods with @private
+
+
+JSDoc 1.3
+=========
+
+- When a function is marked with @constructor, it will always be dealt
+with as a class
+
+- Improved doc regex
+
+- Added recursive directory handling
Added: trunk/build/JSDoc/JSDoc/XMI.pm
===================================================================
--- trunk/build/JSDoc/JSDoc/XMI.pm (rev 0)
+++ trunk/build/JSDoc/JSDoc/XMI.pm 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,291 @@
+package JSDoc::XMI;
+
+use strict;
+use warnings;
+use HTML::Template;
+use Data::Dumper;
+
+=head1 DESCRIPTION
+
+ @packages
+
+ @classes
+ $classname
+ $classid
+ $classuuid
+ $classvisibility (public|protected|private)
+
+ @specializationids
+ $specializationid
+
+ $generalizationid
+
+ @attributes
+ $attributeid
+ $attributeuuid
+ $attributename
+ $attributevisibility (public|protected|private)
+ $ownerscope (instance|classifier)
+ $classid
+ $typeid
+
+ @methods
+ $methodid
+ $methoduuid
+ $methodname
+ $methodvisibility (public|protected|private)
+ $ownerscope (instance|classifier)
+ $returnid
+ $returnuuid
+ $returntypeid
+
+ @datatypes
+ $datatypeid
+ $datatypeuuid
+ $datatypename
+
+ @generalizations
+ $generalizationid
+ $generalizationuuid
+ $generalizationchild
+ $generalizationparent
+
+=cut
+
+sub new {
+ my ($package, $location) = @_;
+ bless {
+ location => "${location}JSDoc/",
+ idcounter => 2,
+ types => {},
+ classes => {},
+ generalizations => {}
+ }, $package;
+}
+
+sub output {
+ my ($self, $classes) = @_;
+
+ my $template = HTML::Template->new(
+ filename => $self->{location} . 'xmi.tmpl',
+ die_on_bad_params => 1);
+
+ my @packages = $self->get_packages($classes);
+ my @datatypes = $self->get_datatypes;
+ my @generalizations = $self->get_generalizations;
+
+ $template->param(
+ packages => \@packages,
+ datatypes => \@datatypes,
+ generalizations => \@generalizations );
+ return $template->output;
+}
+
+sub get_id {
+ 'xmi.' . shift->{idcounter}++;
+}
+
+sub get_uuid {
+ my @chars = ('A'..'Z', 'a'..'z', 0..9);
+ my @uuid;
+ for (1..32){
+ push @uuid, $chars[rand(@chars)];
+ }
+ join("", @uuid);
+}
+
+sub get_packages {
+ my ($self, $classes) = @_;
+ my %packages;
+ push(@{$packages{$_->{package}}}, $_)
+ for $self->get_classes($classes);
+ map {
+ name => $_,
+ classes => $packages{$_},
+ packageid => $self->get_id,
+ packageuuid => $self->get_uuid
+ }, keys %packages;
+}
+
+sub get_classes {
+ my ($self, $classes) = @_;
+ my @classes;
+
+ # Store all the class-ids before we start on anything else
+ $self->add_class($_) for keys %$classes;
+
+ for my $cname (keys %$classes){
+ my $class = {
+ classname => $cname,
+ classid => $self->add_class($cname),
+ classuuid => $self->get_uuid,
+ classvisibility =>
+ defined($classes->{$cname}->{constructor_vars}->{private})
+ ? 'private' : 'public'
+ };
+ $class->{attributes} = $self->get_attributes(
+ $class->{classid},
+ $classes->{$cname});
+
+ $class->{methods} = $self->get_methods(
+ $class->{classid},
+ $classes->{$cname});
+
+ $class->{generalizationid} =
+ $self->get_generalizationid($classes->{$cname});
+
+ $class->{package} =
+ defined($classes->{$cname}->{constructor_vars}->{package})
+ ? $classes->{$cname}->{constructor_vars}->{package}->[0] : '';
+
+ push @classes, $class;
+ }
+
+ for my $class (@classes){
+ $class->{specializationids} = $self->get_specializationids($class);
+ }
+
+ @classes;
+}
+
+sub get_methods {
+ my ($self, $classid, $class) = @_;
+ my @methods;
+
+ for my $k (qw(instance class)){
+ for my $method (@{$class->{"${k}_methods"}}){
+ my $type = defined($method->{vars}->{type})
+ ? $method->{vars}->{type}->[0] : 'Object';
+ my $meth = {
+ methodid => $self->get_id,
+ methoduuid => $self->get_uuid,
+ methodname => $method->{mapped_name},
+ methodvisibility =>
+ defined($method->{vars}->{private})
+ ? 'private' : 'public',
+ ownerscope =>
+ $k eq 'class' ? 'classifier' : 'instance',
+ returnid => $self->get_id,
+ returnuuid => $self->get_uuid,
+ returntypeid => $self->add_type($type)
+ };
+ push @methods, $meth;
+ }
+ }
+ return \@methods;
+}
+
+sub get_attributes {
+ my ($self, $classid, $class) = @_;
+ my @attributes;
+ for my $k (qw(instance class)){
+ for my $field (@{$class->{"${k}_fields"}}){
+ my $type = defined($field->{field_vars}->{type})
+ ? $field->{field_vars}->{type}->[0] : 'Object';
+ my $attr = {
+ attributeid => $self->get_id,
+ attributeuuid => $self->get_uuid,
+ attributename => $field->{field_name},
+ attributevisibility =>
+ defined($field->{field_vars}->{private})
+ ? 'private' : 'public',
+ ownerscope =>
+ $k eq 'class' ? 'classifier' : 'instance',
+ classid => $classid,
+ typeid => $self->add_type($type)
+ };
+ push @attributes, $attr;
+ }
+ }
+ \@attributes;
+}
+
+sub get_generalizationid {
+ my ($self, $class) = @_;
+
+ if ($class->{extends}){
+ return $self->add_generalization(
+ $class->{classname},
+ $class->{extends});
+ }
+ '';
+}
+
+sub get_specializationids {
+ my ($self, $class) = @_;
+ my $cname = $class->{classname};
+ my $cid = $self->add_class($cname);
+
+ my @specializationids;
+
+ for my $id (keys %{$self->{generalizations}}){
+ my $generalization = $self->{generalizations}->{$id};
+ if ($generalization->{parent} eq $cid){
+ push @specializationids, { specializationid => $id };
+ }
+ }
+ \@specializationids;
+}
+
+sub get_datatypes {
+ my ($self) = @_;
+ my @datatypes;
+
+ while (my ($type, $id) = each(%{$self->{types}})){
+ push @datatypes, {
+ datatypeid => $id,
+ datatypeuuid => $self->get_uuid,
+ datatypename => $type };
+ }
+ @datatypes;
+}
+
+sub get_generalizations {
+ my ($self) = @_;
+ my @generalizations;
+
+ while (my ($id, $generalization) = each(%{$self->{generalizations}})){
+ push @generalizations, {
+ generalizationid => $id,
+ generalizationuuid => $self->get_uuid,
+ generalizationchild => $generalization->{parent},
+ generalizationparent => $generalization->{child}};
+ }
+ @generalizations;
+}
+
+sub add_type {
+ my ($self, $type) = @_;
+ $type =~ s/^\s*(\S+)\s*$/$1/;
+ if (defined($self->{classes}->{$type})){
+ return $self->add_class($type);
+ } elsif (defined($self->{types}->{$type})){
+ return $self->{types}->{$type};
+ }
+ $self->{types}->{$type} = $self->get_id;
+}
+
+sub add_class {
+ my ($self, $class) = @_;
+ $class =~ s/^\s*(\S+)\s*$/$1/;
+ if (defined($self->{classes}->{$class})){
+ return $self->{classes}->{$class};
+ }
+ $self->{classes}->{$class} = $self->get_id;
+}
+
+sub add_generalization {
+ my ($self, $subclassname, $superclassname) = @_;
+ my $subclassid = $self->add_class($subclassname);
+ my $superclassid = $self->add_class($superclassname);
+
+ my $generalization = {
+ child => $subclassid,
+ parent => $superclassid };
+
+ my $generalizationid = $self->get_id;
+ $self->{generalizations}->{$generalizationid} = $generalization;
+ $generalizationid;
+}
+
+1;
Added: trunk/build/JSDoc/JSDoc/XML.pm
===================================================================
--- trunk/build/JSDoc/JSDoc/XML.pm (rev 0)
+++ trunk/build/JSDoc/JSDoc/XML.pm 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,72 @@
+package JSDoc::XML;
+
+use strict;
+use warnings;
+use HTML::Template;
+
+sub new {
+ my ($package, $location) = @_;
+ bless { location => "${location}JSDoc/" }, $package;
+}
+
+sub output {
+ my ($self, $classes) = @_;
+ my @classes = _preprocess(
+ grep {defined($_->{classname})} values %$classes);
+ my $template = HTML::Template->new(
+ filename => $self->{location} . 'xml.tmpl',
+ die_on_bad_params => 1);
+
+ $template->param(classes => \@classes);
+ return $template->output;
+}
+
+sub _preprocess {
+ my @classes = @_;
+ for (@classes){
+ $_->{inherits} = _preprocess_inherits($_->{inherits});
+ $_->{constructor_vars} = _preprocess_vars($_->{constructor_vars});
+ for my $method (@{$_->{instance_methods}}, @{$_->{class_methods}}){
+ $method->{vars} = _preprocess_vars($method->{vars});
+ }
+ for my $field (@{$_->{instance_fields}}, @{$_->{class_fields}}){
+ $field->{field_vars} = _preprocess_vars($field->{field_vars});
+ }
+ }
+ @classes;
+}
+
+sub _preprocess_inherits {
+ my ($inherits) = @_;
+ my @inherits;
+ for my $class (keys %$inherits){
+ my $inherit = {
+ class => $class,
+ methods => [map { name => $_ },
+ @{$inherits->{$class}->{instance_methods}}]};
+ push @inherits, $inherit;
+ }
+ \@inherits;
+}
+
+sub _preprocess_vars {
+ my ($vars) = @_;
+ return $vars if ref($vars) eq 'ARRAY';
+ my @vars;
+ for my $key (keys %$vars){
+ my $var;
+ if (ref($vars->{$key}) eq 'ARRAY'){
+ $var = {
+ '@name' => $key,
+ values => [map { val => $_ }, @{$vars->{$key}}] };
+ } else {
+ $var = {
+ '@name' => $key,
+ values => [ { val => $vars->{$key} } ] };
+ }
+ push @vars, $var;
+ }
+ \@vars;
+}
+
+1;
Added: trunk/build/JSDoc/JSDoc/xmi.tmpl
===================================================================
--- trunk/build/JSDoc/JSDoc/xmi.tmpl (rev 0)
+++ trunk/build/JSDoc/JSDoc/xmi.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<XMI xmi.version="1.0">
+ <XMI.header>
+ <XMI.documentation>
+ <XMI.exporter>JSDoc XMI Export</XMI.exporter>
+ <XMI.exporterVersion>0.1</XMI.exporterVersion>
+ </XMI.documentation>
+ <XMI.metamodel xmi.name="UML" xmi.version="1.3"/>
+ </XMI.header>
+ <XMI.content>
+ <Model_Management.Model xmi.id="xmi.1" xmi.uuid="10-0-0-5-3605f878:101c2e18bff:-8000">
+ <Foundation.Core.ModelElement.name>JSDoc</Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isRoot xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isLeaf xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isAbstract xmi.value="false"/>
+ <Foundation.Core.Namespace.ownedElement>
+
+ <!-- BEGIN PACKAGES -->
+ <TMPL_LOOP NAME="packages">
+
+ <TMPL_IF NAME="name">
+ <Model_Management.Package
+ xmi.id="<TMPL_VAR NAME="packageid">"
+ xmi.uuid="<TMPL_VAR NAME="packageuuid">">
+ <Foundation.Core.ModelElement.name><TMPL_VAR NAME="name"></Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isRoot xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isLeaf xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isAbstract xmi.value="false"/>
+ <Foundation.Core.ModelElement.namespace>
+ <Foundation.Core.Namespace xmi.idref="xmi.1"/>
+ </Foundation.Core.ModelElement.namespace>
+
+ </TMPL_IF>
+
+ <!-- BEGIN CLASS DESCRIPTIONS -->
+ <TMPL_LOOP NAME="classes">
+ <TMPL_IF NAME="package">
+ <Foundation.Core.Namespace.ownedElement>
+ </TMPL_IF>
+
+ <!-- BEGIN CLASS -->
+ <Foundation.Core.Class
+ xmi.id="<TMPL_VAR NAME=classid>"
+ xmi.uuid="<TMPL_VAR NAME=classuuid>">
+
+ <!-- CLASS NAME -->
+ <Foundation.Core.ModelElement.name><!-- TMPL_VAR NAME="classname" --></Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.visibility
+ xmi.value="<TMPL_VAR NAME=classvisibility>"/>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isRoot xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isLeaf xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isAbstract xmi.value="false"/>
+ <Foundation.Core.Class.isActive xmi.value="false"/>
+ <Foundation.Core.ModelElement.namespace>
+ <Foundation.Core.Namespace xmi.idref="xmi.1"/>
+ </Foundation.Core.ModelElement.namespace>
+
+ <!-- BEGIN REFERENCE TO INHERITANCE -->
+ <TMPL_IF NAME="generalizationid">
+ <Foundation.Core.GeneralizableElement.generalization>
+ <Foundation.Core.Generalization
+ xmi.idref="<TMPL_VAR NAME=generalizationid >"/>
+ </Foundation.Core.GeneralizableElement.generalization>
+ </TMPL_IF>
+
+ <TMPL_LOOP NAME="specializationids">
+ <Foundation.Core.GeneralizableElement.specialization>
+ <Foundation.Core.Generalization
+ xmi.idref="<TMPL_VAR NAME=specializationid >"/>
+ </Foundation.Core.GeneralizableElement.specialization>
+ </TMPL_LOOP>
+ <!-- END REFERENCE TO INHERITANCE -->
+
+ <Foundation.Core.Classifier.feature>
+
+ <!-- BEGIN ATTRIBUTES -->
+ <TMPL_LOOP NAME="attributes">
+
+ <!-- BEGIN ATTRIBUTE -->
+ <Foundation.Core.Attribute
+ xmi.id="<TMPL_VAR NAME=attributeid>"
+ xmi.uuid="<TMPL_VAR NAME=attributeuuid>">
+ <Foundation.Core.ModelElement.name><!-- TMPL_VAR NAME="attributename" --></Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.visibility xmi.value="<TMPL_VAR NAME=attributevisibility>"/>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.Feature.ownerScope
+ xmi.value="<TMPL_VAR NAME=ownerscope>"/>
+ <!--Foundation.Core.StructuralFeature.multiplicity>
+ <Foundation.Data_Types.Multiplicity xmi.id="xmi.5">
+ <Foundation.Data_Types.Multiplicity.range>
+ <Foundation.Data_Types.MultiplicityRange xmi.id="xmi.6">
+ <Foundation.Data_Types.MultiplicityRange.lower>1</Foundation.Data_Types.MultiplicityRange.lower>
+ <Foundation.Data_Types.MultiplicityRange.upper>1</Foundation.Data_Types.MultiplicityRange.upper>
+ </Foundation.Data_Types.MultiplicityRange>
+ </Foundation.Data_Types.Multiplicity.range>
+ </Foundation.Data_Types.Multiplicity>
+ </Foundation.Core.StructuralFeature.multiplicity-->
+ <Foundation.Core.StructuralFeature.changeability xmi.value="changeable"/>
+ <Foundation.Core.StructuralFeature.targetScope xmi.value="instance"/>
+ <Foundation.Core.Feature.owner>
+ <Foundation.Core.Classifier
+ xmi.idref="<TMPL_VAR NAME=classid>"/>
+ </Foundation.Core.Feature.owner>
+ <Foundation.Core.StructuralFeature.type>
+ <Foundation.Core.Classifier
+ xmi.idref="<TMPL_VAR NAME=typeid>"/>
+ </Foundation.Core.StructuralFeature.type>
+ <!--Foundation.Core.ModelElement.taggedValue>
+ <Foundation.Extension_Mechanisms.TaggedValue xmi.id="xmi.8">
+ <Foundation.Extension_Mechanisms.TaggedValue.tag>transient</Foundation.Extension_Mechanisms.TaggedValue.tag>
+ <Foundation.Extension_Mechanisms.TaggedValue.value>false</Foundation.Extension_Mechanisms.TaggedValue.value>
+ <Foundation.Extension_Mechanisms.TaggedValue.modelElement>
+ <Foundation.Core.ModelElement xmi.idref="xmi.4"/>
+ </Foundation.Extension_Mechanisms.TaggedValue.modelElement>
+ </Foundation.Extension_Mechanisms.TaggedValue>
+ <Foundation.Extension_Mechanisms.TaggedValue xmi.id="xmi.9">
+ <Foundation.Extension_Mechanisms.TaggedValue.tag>volatile</Foundation.Extension_Mechanisms.TaggedValue.tag>
+ <Foundation.Extension_Mechanisms.TaggedValue.value>false</Foundation.Extension_Mechanisms.TaggedValue.value>
+ <Foundation.Extension_Mechanisms.TaggedValue.modelElement>
+ <Foundation.Core.ModelElement xmi.idref="xmi.4"/>
+ </Foundation.Extension_Mechanisms.TaggedValue.modelElement>
+ </Foundation.Extension_Mechanisms.TaggedValue>
+ </Foundation.Core.ModelElement.taggedValue-->
+ </Foundation.Core.Attribute>
+ <!-- END ATTRIBUTE -->
+
+ </TMPL_LOOP>
+ <!-- END ATTRIBUTES -->
+
+ <!-- BEGIN METHODS -->
+ <TMPL_LOOP NAME="methods">
+
+ <!-- BEGIN METHOD -->
+ <Foundation.Core.Operation
+ xmi.id="<TMPL_VAR NAME=methodid>"
+ xmi.uuid="<TMPL_VAR NAME=methoduuid>">
+
+ <Foundation.Core.ModelElement.name><!-- TMPL_VAR NAME="methodname" --></Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.visibility
+ xmi.value="<TMPL_VAR NAME=methodvisibility>"/>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.Feature.ownerScope
+ xmi.value="<TMPL_VAR NAME=ownerscope>"/>
+ <Foundation.Core.BehavioralFeature.isQuery xmi.value="false"/>
+ <Foundation.Core.Operation.concurrency xmi.value="sequential"/>
+ <Foundation.Core.Operation.isRoot xmi.value="false"/>
+ <Foundation.Core.Operation.isLeaf xmi.value="false"/>
+ <Foundation.Core.Operation.isAbstract xmi.value="false"/>
+ <Foundation.Core.Feature.owner>
+ <Foundation.Core.Classifier
+ xmi.idref="<TMPL_VAR NAME=classid>"/>
+ </Foundation.Core.Feature.owner>
+ <Foundation.Core.BehavioralFeature.parameter>
+
+ <!-- BEGIN RETURN TYPE -->
+ <Foundation.Core.Parameter
+ xmi.id="<TMPL_VAR NAME=returnid>"
+ xmi.uuid="<TMPL_VAR NAME=returnuuid>">
+ <Foundation.Core.ModelElement.name>return</Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.Parameter.kind xmi.value="return"/>
+ <!--Foundation.Core.Parameter.behavioralFeature>
+ <Foundation.Core.BehavioralFeature xmi.idref="xmi.10"/>
+ </Foundation.Core.Parameter.behavioralFeature-->
+ <Foundation.Core.Parameter.type>
+ <Foundation.Core.Classifier
+ xmi.idref="<TMPL_VAR NAME=returntypeid>"/>
+ </Foundation.Core.Parameter.type>
+ </Foundation.Core.Parameter>
+ <!-- END RETURN TYPE -->
+
+ </Foundation.Core.BehavioralFeature.parameter>
+ </Foundation.Core.Operation>
+ <!-- END METHOD -->
+
+ </TMPL_LOOP>
+ <!-- END METHODS -->
+
+ </Foundation.Core.Classifier.feature>
+ </Foundation.Core.Class>
+ <!-- END CLASS -->
+
+ <TMPL_IF NAME="package">
+ </Foundation.Core.Namespace.ownedElement>
+ </TMPL_IF>
+
+ </TMPL_LOOP>
+ <!-- END CLASS DESCRIPTIONS -->
+
+ <TMPL_IF name="name">
+ </Model_Management.Package>
+ </TMPL_IF>
+
+ </TMPL_LOOP>
+ <!-- END PACKAGES -->
+
+ <!-- BEGIN DATATYPE DESCRIPTIONS -->
+ <TMPL_LOOP name="datatypes">
+
+ <!-- BEGIN DATATYPE -->
+ <Foundation.Core.DataType
+ xmi.id="<TMPL_VAR NAME=datatypeid>"
+ xmi.uuid="<TMPL_VAR NAME=datatypeuuid>">
+
+ <Foundation.Core.ModelElement.name><!-- TMPL_VAR NAME="datatypename" --></Foundation.Core.ModelElement.name>
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isRoot xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isLeaf xmi.value="false"/>
+ <Foundation.Core.GeneralizableElement.isAbstract xmi.value="false"/>
+ <Foundation.Core.ModelElement.namespace>
+ <Foundation.Core.Namespace xmi.idref="xmi.1"/>
+ </Foundation.Core.ModelElement.namespace>
+ </Foundation.Core.DataType>
+ <!-- END DATATYPE -->
+
+ </TMPL_LOOP>
+ <!-- END DATATYPE DESCRIPTIONS -->
+
+
+ <!-- BEGIN GENERALIZATIONS -->
+ <TMPL_LOOP NAME="generalizations">
+ <!-- BEGIN GENERALIZATION -->
+ <Foundation.Core.Generalization
+ xmi.id="<TMPL_VAR NAME=generalizationid >"
+ xmi.uuid="<TMPL_VAR NAME=generalizationuuid >" >
+
+ <Foundation.Core.ModelElement.isSpecification xmi.value="false"/>
+ <Foundation.Core.ModelElement.namespace>
+ <Foundation.Core.Namespace xmi.idref="xmi.1"/>
+ </Foundation.Core.ModelElement.namespace>
+ <Foundation.Core.Generalization.child>
+ <Foundation.Core.GeneralizableElement
+ xmi.idref="<TMPL_VAR NAME=generalizationchild >"/>
+ </Foundation.Core.Generalization.child>
+ <Foundation.Core.Generalization.parent>
+ <Foundation.Core.GeneralizableElement
+ xmi.idref="<TMPL_VAR NAME=generalizationparent >"/>
+ </Foundation.Core.Generalization.parent>
+ </Foundation.Core.Generalization>
+ <!-- END GENERALIZATION -->
+ </TMPL_LOOP>
+ <!-- END GENERALIZATIONS -->
+
+ </Foundation.Core.Namespace.ownedElement>
+ </Model_Management.Model>
+ </XMI.content>
+</XMI>
Added: trunk/build/JSDoc/JSDoc/xml.tmpl
===================================================================
--- trunk/build/JSDoc/JSDoc/xml.tmpl (rev 0)
+++ trunk/build/JSDoc/JSDoc/xml.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,128 @@
+<?xml version="1.0"?>
+<javascript>
+ <classes>
+ <TMPL_LOOP NAME="classes">
+ <class
+ name="<TMPL_VAR NAME="classname">"
+ <TMPL_IF NAME="extends">extends="<TMPL_VAR NAME='extends'>"</TMPL_IF> >
+ <constructor_args><!-- TMPL_VAR NAME="constructor_args" --></constructor_args>
+ <constructor_vars>
+ <TMPL_LOOP NAME="constructor_vars">
+ <var name="<TMPL_VAR NAME='@name'>">
+ <TMPL_LOOP NAME="values">
+ <value><![CDATA[<TMPL_VAR NAME="val">]]></value>
+ </TMPL_LOOP>
+ </var>
+ </TMPL_LOOP>
+ </constructor_vars>
+
+ <constructor_detail><![CDATA[<TMPL_VAR NAME="constructor_detail">]]></constructor_detail>
+
+ <instance-methods>
+ <TMPL_LOOP NAME="instance_methods">
+ <method mapped_name="<TMPL_VAR NAME='mapped_name'>">
+ <description><![CDATA[<TMPL_VAR NAME="description">]]></description>
+ <argument_list><!--
+ TMPL_VAR NAME="argument_list"
+ --></argument_list>
+ <vars>
+ <TMPL_LOOP NAME="vars">
+ <var name="<TMPL_VAR NAME='@name'>">
+ <TMPL_LOOP NAME="values">
+ <value><![CDATA[<TMPL_VAR NAME="val">]]></value>
+ </TMPL_LOOP>
+ </var>
+ </TMPL_LOOP>
+ </vars>
+ </method>
+ </TMPL_LOOP>
+ </instance-methods>
+
+ <instance-fields>
+ <TMPL_LOOP NAME="instance_fields">
+ <field name="<TMPL_VAR NAME='field_name'>">
+ <field-value><![CDATA[<TMPL_VAR NAME="field_value">]]></field-value>
+ <field-description><![CDATA[<TMPL_VAR NAME="field_description">]]></field-description>
+ <vars>
+ <TMPL_LOOP NAME="field_vars">
+ <var name="<TMPL_VAR NAME='@name'>">
+ <TMPL_LOOP NAME="values">
+ <value><![CDATA[<TMPL_VAR NAME="val">]]></value>
+ </TMPL_LOOP>
+ </var>
+ </TMPL_LOOP>
+ </vars>
+ </field>
+ </TMPL_LOOP>
+ </instance-fields>
+
+ <class-methods>
+ <TMPL_LOOP NAME="class_methods">
+ <method mapped_name="<TMPL_VAR NAME='mapped_name'>">
+ <description><![CDATA[<TMPL_VAR NAME="description">]]></description>
+ <argument_list><!--
+ TMPL_VAR NAME="argument_list"
+ --></argument_list>
+ <vars>
+ <TMPL_LOOP NAME="vars">
+ <var name="<TMPL_VAR NAME='@name'>">
+ <TMPL_LOOP NAME="values">
+ <value><![CDATA[<TMPL_VAR NAME="val">]]></value>
+ </TMPL_LOOP>
+ </var>
+ </TMPL_LOOP>
+ </vars>
+ </method>
+
+ </TMPL_LOOP>
+
+
+ </class-methods>
+
+ <class-fields>
+ <TMPL_LOOP NAME="class_fields">
+
+ <field name="<TMPL_VAR NAME='field_name'>">
+ <field-value><![CDATA[<TMPL_VAR NAME="field_value">]]></field-value>
+ <field-description><![CDATA[<TMPL_VAR NAME="field_description">]]></field-description>
+ <vars>
+ <TMPL_LOOP NAME="field_vars">
+ <var name="<TMPL_VAR NAME='@name'>">
+ <TMPL_LOOP NAME="values">
+ <value><![CDATA[<TMPL_VAR NAME="val">]]></value>
+ </TMPL_LOOP>
+ </var>
+ </TMPL_LOOP>
+ </vars>
+ </field>
+ </TMPL_LOOP>
+
+ </class-fields>
+
+ <inner-classes>
+ <TMPL_LOOP NAME="inner_classes">
+ <class name="<TMPL_VAR NAME='class_name'>"/>
+ </TMPL_LOOP>
+ </inner-classes>
+
+ <TMPL_LOOP NAME="inherits">
+ <inherits from="<TMPL_VAR NAME='class'>">
+ <TMPL_IF NAME="methods">
+ <methods>
+ <TMPL_LOOP NAME="methods">
+ <method><!-- TMPL_VAR NAME="name" --></method>
+ </TMPL_LOOP>
+ </methods>
+ </TMPL_IF>
+
+ <TMPL_IF NAME="fields">
+ <fields>
+ </fields>
+ </TMPL_IF>
+ </inherits>
+
+ </TMPL_LOOP>
+ </class>
+ </TMPL_LOOP>
+ </classes>
+</javascript>
Added: trunk/build/JSDoc/JSDoc.pm
===================================================================
--- trunk/build/JSDoc/JSDoc.pm (rev 0)
+++ trunk/build/JSDoc/JSDoc.pm 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,1090 @@
+package JSDoc;
+
+=head1 NAME
+
+JSDoc - parse JavaScript source file for JSDoc comments
+
+=head1 SYNOPSIS
+
+Create JavaScript sourcefiles commented in a manner similar to javadoc
+(ie. with documentation starting with '/**' and then pass a list of references
+to JavaScript source to parse_code_tree:
+
+ /**
+ * This is a class for example purposes
+ * @param name Name for the new object
+ * @constructor
+ */
+ function MyClass(name){
+ this.name = name;
+ }
+
+ $code_tree = parse_code_tree(@src_refs);
+
+A tree structure describing the code layout, inheritance and documentation
+is returned
+
+To clear the cache of classes and functions in the parser:
+
+ reset_parser();
+
+
+=head1 DESCRIPTION
+
+The C<parse_code_tree> function requires a ref to a string holding the
+souce code of a javascript object file or files. It returns a data structure
+that describes the object hierarchy contained in the source file, as well
+as included documentation for all fields and methods. The resulting
+data structure has the following form (for each class):
+
+ Class
+ |
+ +- classname
+ |
+ +- constructor_args
+ |
+ +- extends
+ |
+ +- constructor_detail
+ |
+ +- constructor_vars
+ |
+ +- class_methods
+ | |
+ | +- description
+ | |
+ | +- mapped_name
+ | |
+ | +- argument_list
+ | |
+ | +- vars
+ |
+ +- instance_methods
+ | |
+ | +- description
+ | |
+ | +- mapped_name
+ | |
+ | +- argument_list
+ | |
+ | +- vars
+ |
+ +- class_fields
+ | |
+ | +- field_description
+ | |
+ | +- field_name
+ | |
+ | +- field_value
+ | |
+ | +- field_vars
+ |
+ +- instance_fields
+ | |
+ | +- field_description
+ | |
+ | +- field_name
+ | |
+ | +- field_value
+ | |
+ | +- field_vars
+ |
+ +- inner_classes
+ | |
+ | +- class_name
+ |
+ +- inherits
+ |
+ +- Class
+ |
+ +- instance_fields
+ |
+ +- instance_methods
+
+
+There is also an additional entry under the key __FILES__ that contains
+keyed entries for each @tag that was defined in the first JSDoc comment
+block with a @fileoverview tag. Each entry under __FILES__ is keyed by
+filename, and is a hash reference.
+
+=head1 AUTHORS
+
+Gabriel Reid gab_reid at users.sourceforge.net,
+Michael Mathews michael at mathews.net
+
+=cut
+
+require 5.000;
+use strict;
+use warnings;
+use Exporter;
+
+# Recursion limit for recursive regexes
+use constant RECURSION => 10;
+
+use vars qw/ @ISA @EXPORT /;
+
+ at ISA = qw(Exporter);
+ at EXPORT = qw(parse_code_tree configure_parser reset_parser);
+
+# State
+use vars qw/ %CLASSES %FUNCTIONS %CONFIG $CTX_FILE /;
+
+# Regexes
+use vars qw/ $BAL_PAREN $BAL_BRACE $BAL_SQUAR $SQUOTE $DQUOTE $NONQUOTE
+ $FUNC_DEF $RET_FUNC_DEF $ANON_FUNCTION $LITERAL $FUNC_CALL
+ $JSDOC_COMMENT $MLINE_COMMENT $SLINE_COMMENT /;
+
+# This limits nested braces to 30 levels, but is much more
+# stable than using a dynamic regex
+$BAL_BRACE = qr/\{(?:[^\{\}])*\}/;
+$BAL_PAREN = qr/\((?:[^()])*\)/;
+$BAL_SQUAR = qr/\[(?:[^[\]])*\]/;
+for (1..RECURSION){
+ $BAL_BRACE = qr/\{(?:[^\{\}]|$BAL_BRACE)*\}/;
+ $BAL_PAREN = qr/\((?:[^()]|$BAL_PAREN)*\)/;
+ $BAL_SQUAR = qr/\[(?:[^[\]]|$BAL_SQUAR)*\]/;
+}
+$SQUOTE = qr{'[^'\\]*(?:\\.[^'\\]*)*'};
+$DQUOTE = qr{"[^"\\]*(?:\\.[^"\\]*)*"};
+$NONQUOTE = qr{[^"'/]};
+$FUNC_DEF = qr/function\s+\w+(?:\.\w+)*\s*$BAL_PAREN\s*$BAL_BRACE/;
+$RET_FUNC_DEF = qr/function\s+(\w+(?:\.\w+)*)\s*($BAL_PAREN)\s*($BAL_BRACE)/;
+$ANON_FUNCTION = qr/function\s*$BAL_PAREN\s*$BAL_BRACE/;
+$LITERAL = qr/$DQUOTE|$SQUOTE|\d+/;
+$FUNC_CALL = qr/(?:new\s+)?\w+(?:\.\w+)*\s*$BAL_PAREN/;
+$JSDOC_COMMENT = qr{/\*\*[^*]*\*+(?:[^/*][^*]*\*+)*/};
+$MLINE_COMMENT = qr{/\*[^*]*\*+(?:[^/*][^*]*\*+)*/};
+$SLINE_COMMENT = qr{//[^\n]*};
+
+
+#
+# Public function that returns a datastructure representing the JS classes
+# and their documentation
+#
+sub parse_code_tree {
+
+ &initialize_parser;
+
+ #
+ # This (I mean the "<<$_>>") is pretty hacky, but I've made it this
+ # way to maintain backwards compatibility with anyone who's automatically
+ # expecting this to work when they throw an array of refs to it. If you're
+ # using this for your own work, please don't expect to be able to
+ # put the context file in like this in the future
+ #
+ for my $js_src (map { ref and ${$_} or "<<$_>>" } @_){
+ if ($js_src =~ /^<<(.+)>>$/){
+ $CTX_FILE = $1;
+ next;
+ }
+
+ # perlify os line-endings
+ $js_src =~ s/(\r\n|\r)/\n/g;
+
+ &parse_file_info($js_src);
+ $js_src = &preprocess_source($js_src);
+ &fetch_funcs_and_classes($js_src);
+ }
+
+ &map_all_properties();
+ &build_class_hierarchy();
+ &set_class_constructors();
+ &filter_globals;
+
+ while (my ($classname, $class) = each %CLASSES){
+ delete $class->{_class_properties};
+ delete $class->{_instance_properties};
+ $class->{classname} = $classname unless $classname eq '__FILES__';
+ }
+ return \%CLASSES;
+}
+
+#
+# Parses up a a jsdoc comment into its component parts
+# PARAM: The document string to be parsed
+#
+sub parse_jsdoc_comment {
+ my ($doc, $raw) = @_;
+
+ # Remove excess '*' characters
+ $doc =~ s/^[*\s]*([^*].*?)[*\s]*$/$1/s;
+ $doc =~ s/^\s*\*//gm;
+
+ my %parsed = (); # remember each part that is parsed
+
+ # the first paragraph could be a summary statement
+ # a paragraph may follow of variable defs (variable names start with "@")
+ my ($summary, $variable_str) = $doc =~
+ /^\s*
+ (
+ (?:[^{@]|(?:\{[^@]))*
+ (?:\{\@
+ (?:[^{@]|(?:\{[^@]))*)*
+ )
+ \s*
+ (.*)
+ $/xs;
+ $summary =~ s/^\s*(\S.*?)\s*$/$1/s;
+ $parsed{summary} = $summary;
+
+ # two types of variable def can be dealt with here:
+ # a @argument has a two-part value -- the arg name and a description
+ # all other @<variables> only have a single value each (although there may
+ # be many variables with the same name)
+ if($variable_str) {
+ my %vars = ();
+ while ($variable_str =~ /
+ (?<![\{\w])\@(\w+) # The @attribute, but not a {@link}
+ \s*
+ ((?:\{\@|\w\@|[^\@])*) # Everything up to the next @attribute
+ /gsx) {
+ my ($name, $val) = ($1, $2);
+ $vars{$name} = [] unless defined $vars{$name};
+ $val =~ s/\n/ /g unless $raw or $name eq 'class';
+ push(@{$vars{$name}}, ($val =~ /^\s*(.*)\s*$/s)[0]);
+ }
+ $parsed{vars} = \%vars;
+ }
+ return \%parsed;
+}
+
+#
+# Builds up the global FUNCTION and CLASSES hashes
+# with the names of functions and classes
+#
+sub fetch_funcs_and_classes {
+ my $js_src = shift;
+
+ while ($js_src =~ m!
+ # Documentation
+ (?:
+ /\*\* # Opening of docs
+ ([^/]+
+ (?:(?:[^*]/)+[^/]+)*
+ )
+ \*/\s*\n\s* # Closing of docs
+ )?
+
+ # Function
+ (?:(?:function\s+(\w+)\s*(\(.*?\))\s*\{)|
+
+ # Anonymous function
+ (?:(\w+(?:\.\w+)*?)(\.prototype)?\.(\w+)\s*=\s*function\s*
+ (?:\w+\s*)?(\(.*?\)))|
+
+ # Instance property
+ (?:(\w+(?:\.\w+)*?)\.prototype\.(\$?\w+)\s*=\s*(.*?)\s*[;\n])|
+
+ #Inheritance
+ (?:(\w+(?:\.\w+)*?)\.prototype\s*=
+ \s*new\s*(\w+(?:\.\w+)*?)(?:\(.*?\))?\s*[;\n])|
+
+ # Class property
+ (?:(\w+(?:\.\w+)*?)\.(\$?\w+)\s*=\s*(.*?)\s*[;\n]))
+ !gsx){
+
+ my ($doc, $fname1, $arglist1, $cname1, $prototype, $fname2, $arglist2)
+ = ($1 || '', $2, $3, $4, $5, $6, $7);
+ my ($cname2, $propname1, $propval1) = ($8, $9, $10);
+ my ($cname3, $baseclass) = ($11, $12);
+ my ($cname4, $propname2, $propval2) = ($13, $14, $15);
+ next if $doc =~ /\@ignore\b/;
+
+ if ($fname1){
+ &add_function($doc, $fname1, $arglist1);
+ if ($doc =~ /\@(?:constructor|class|base)\b/){
+ # Add all @constructor and @class methods as classes
+ &add_class($fname1, $doc);
+ }
+ } elsif ($cname1 && $fname2 && $FUNCTIONS{$cname1}){
+ # Anonymous functions added onto a class or class prototype
+ &add_anonymous_function($doc, $cname1, $fname2,
+ $arglist2, not defined($prototype));
+
+ } elsif ($cname1 && $fname2 && not defined($FUNCTIONS{$cname1})){
+ if ($doc =~ /\@(addon|base|constructor)\b/
+ || $prototype || $CLASSES{$cname1}){
+ # Called for methods added to the prototype of core classes
+ &add_anonymous_function($doc, $cname1, $fname2,
+ $arglist2, not defined($prototype));
+ }
+
+ } elsif ($cname2 && $propname1 && defined($propval1)) {
+ &add_property($doc, $cname2, $propname1, $propval1, 0);
+ } elsif ($cname3 && $baseclass){
+ &set_base_class($cname3, $baseclass);
+ } elsif ($cname4 && $propname2 && defined($propval2)
+ && $propname2 ne 'prototype'
+ && $cname4 ne 'this'){
+
+ if ($FUNCTIONS{$cname4}
+ || $CLASSES{$cname4}
+ || $js_src =~ /function\s*\Q$cname4\E\b/){
+ &add_property($doc, $cname4, $propname2, $propval2, 1);
+ }
+ }
+ }
+}
+
+#
+# Add a function that is given as Class.prototype.blah = function(){...}
+#
+sub add_anonymous_function {
+ my ($doc, $class, $function_name, $arg_list, $is_class_prop) = @_;
+
+ # Just get out if the class is called 'this'. Reason for this is that
+ # binding methods to 'this' should already be converted to binding methods
+ # to the prototype, therefore binding to 'this' is only possible in
+ # member functions, and is therefore not considered static or consistent
+ # enough to be documented.
+ return unless $class ne 'this';
+ &add_class($class);
+ my $fake_name = "__$class.$function_name";
+
+ # This is dirty
+ my $is_private = $doc =~ /\@private\b/;
+
+ &add_function($doc, $fake_name, $arg_list, $is_private) and
+ &add_property($doc, $class, $function_name, $fake_name, $is_class_prop);
+
+ &add_class("$class.$function_name", $doc)
+ if $doc =~ /\@(?:constructor|class)\b/;
+}
+
+
+#
+# Add a class to the global CLASSES hash
+#
+sub add_class {
+ my $class = shift;
+ warn "Can't add 'this' as a class, please file a bug report!"
+ if $class eq 'this';
+ my $class_doc = shift || '';
+ if (!$CLASSES{$class}){
+ $CLASSES{$class} = {};
+ $CLASSES{$class}->{$_} = [] for qw(instance_fields class_fields
+ instance_methods class_methods
+ inner_classes);
+ }
+ unless ($CLASSES{$class}->{extends}){
+ &set_base_class($class, $1)
+ if $class_doc =~ /\@base\s+(\w+(?:\.\w+)*)/;
+ }
+}
+
+#
+# Set the base class for a given class
+#
+sub set_base_class {
+ my ($class, $base_class) = @_;
+ &add_class($class);
+ $CLASSES{$class}->{extends} = $base_class
+ unless $CLASSES{$class}->{extends};
+}
+
+#
+# Add a property, either a class or instance method or field
+#
+sub add_property {
+ my ($doc, $class, $property, $value, $is_class_property) = @_;
+ &add_class($class);
+ return if $property eq 'constructor';
+ my $parsed_doc = &parse_jsdoc_comment($doc);
+ $doc = $parsed_doc->{summary};
+ my $key = $is_class_property ? '_class_properties' : '_instance_properties';
+ for my $classref (@{$CLASSES{$class}->{$key}}){
+ if ($classref->{property_name} eq $property){
+ # Whine about rebinding functions to classes
+ if ($FUNCTIONS{$value}){
+ warn "Already bound property '$property' to '$class'\n";
+ return;
+ }
+
+ # Only take on new attributes
+ $classref->{property_doc} ||= $doc;
+ $classref->{property_vars} ||= $parsed_doc->{vars};
+ return;
+ }
+ }
+
+ push @{$CLASSES{$class}->{$key}}, {
+ property_doc => $doc,
+ property_name => $property,
+ property_value => $value,
+ property_vars => $parsed_doc->{vars}
+ };
+}
+
+
+#
+# Add a function and its documentation to the global FUNCTION hash
+#
+sub add_function {
+ my ($doc, $function, $arg_list, $is_private) = @_;
+
+ # clean remaining comments out of arg list
+ # (all others are already gone)
+ # Again, taken from Jeffrey Friedl's "Mastering Regular Expressions"
+ {
+ no warnings;
+ $arg_list =~ s/
+ ($NONQUOTE+|
+ $DQUOTE$NONQUOTE*|
+ $SQUOTE$NONQUOTE*)
+ |$MLINE_COMMENT|$SLINE_COMMENT/$1/gx;
+ }
+
+ if ($FUNCTIONS{$function}){
+ warn "Function '$function' already declared\n";
+ unless ($doc && !$FUNCTIONS{$function}->{documentation}->{summary}){
+ return 0;
+ }
+ }
+ $FUNCTIONS{$function} = {};
+ my $func = $FUNCTIONS{$function};
+ $arg_list and $func->{argument_list} = join(" ", split("\\s+", $arg_list))
+ or $func->{argument_list} = "()";
+
+ my $documentation = parse_jsdoc_comment($doc);
+ if ($documentation->{vars}->{member}){
+ my ($classname) = map { s/^\s*(\S*)\s*$/$1/; $_ }
+ @{$documentation->{vars}->{member}};
+ &add_property($doc, $classname, $function, $function, 0)
+ if $classname =~ /\w+/;
+ }
+ my $function_ref = $FUNCTIONS{$function};
+
+ $function_ref->{documentation} = $documentation;
+ $function_ref->{description} = $documentation->{summary};
+ $function_ref->{vars} = $function_ref->{documentation}->{vars};
+ $function_ref->{vars}->{filename} = $CTX_FILE;
+ $function_ref->{vars}->{private} = 1 if $is_private;
+ 1;
+}
+
+
+#
+# Map all the class and instance properties to their implementation
+#
+sub map_all_properties {
+ for my $type (qw(_class_properties _instance_properties)){
+ for my $class (keys %CLASSES){
+ &map_single_property(
+ $class,
+ $_->{property_name},
+ $_->{property_value},
+ $_->{property_doc},
+ $_->{property_vars}, $type eq '_class_properties')
+ for @{$CLASSES{$class}->{$type}}
+ }
+ }
+
+ # Map all the unattached functions
+ my $classname = $CONFIG{GLOBALS_NAME} || 'GLOBALS';
+ &add_class($classname);
+ for my $function
+ (grep !($FUNCTIONS{$_}->{is_mapped} || $CLASSES{$_}), keys %FUNCTIONS){
+ &map_single_property(
+ $classname, $function, $function, '', undef, 1);
+ }
+
+ # Map static inner classes
+ for $classname (keys %CLASSES){
+ my $i = 0;
+ my @to_remove;
+ for my $cprop (@{$CLASSES{$classname}->{class_methods}}){
+ my $propname = $cprop->{mapped_name};
+ if ($CLASSES{"$classname.$propname"}){
+ push @to_remove, $i;
+ push @{$CLASSES{$classname}->{inner_classes}},
+ {class_name => "$classname." . $cprop->{mapped_name}};
+ $FUNCTIONS{"$classname.$propname"} =
+ delete $FUNCTIONS{"__$classname.$propname"};
+ }
+ $i++;
+ }
+ splice(@{$CLASSES{$classname}->{class_methods}}, $_, 1)
+ for reverse @to_remove;
+ }
+}
+
+#
+# Map a single instance or class field or method
+#
+sub map_single_property {
+ my ($class, $prop_name, $prop_val,
+ $description, $vars, $is_class_prop) = @_;
+ if (!$FUNCTIONS{$prop_val}){
+ push @{$CLASSES{$class}->{$is_class_prop
+ ? 'class_fields' : 'instance_fields'}}, {
+ field_name => $prop_name,
+ field_description => $description,
+ field_value => $prop_val,
+ field_vars => $vars };
+ return;
+ }
+ my %method;
+ my $function = $FUNCTIONS{$prop_val};
+ $function->{is_mapped} = 1;
+ $method{mapped_name} = $prop_name;
+
+ $method{$_} = $function->{$_} for
+ qw/ argument_list description vars /;
+
+ push @{$CLASSES{$class}->{$is_class_prop
+ ? 'class_methods'
+ : 'instance_methods'}}, \%method;
+}
+
+
+
+#
+# Build up the full hierarchy of classes, including figuring out
+# what methods are overridden by subclasses, etc
+# PARAM: The JS source code
+#
+sub build_class_hierarchy {
+ # Find out what is inherited
+ for my $class (map($CLASSES{$_}, sort keys %CLASSES)){
+ my $superclassname = $class->{extends};
+ !$superclassname and next;
+ my $superclass = $CLASSES{$superclassname};
+ $class->{inherits} = {};
+ while ($superclass){
+ $class->{inherits}->{$superclassname} = {};
+ my @instance_fields;
+ my @instance_methods;
+
+ &handle_instance_methods($superclass, $superclassname,
+ $class, \@instance_methods);
+
+ &handle_instance_fields($superclass, $superclassname,
+ $class, \@instance_fields);
+
+ $superclassname = $superclass->{extends};
+ $superclass = $superclassname ? $CLASSES{$superclassname} : undef;
+ }
+ }
+}
+
+#
+# This is just a helper function for build_class_hierarchy
+# because that function was getting way oversized
+#
+sub handle_instance_methods {
+ my ($superclass, $superclassname, $class, $instance_methods) = @_;
+ if ($superclass->{instance_methods}){
+ INSTANCE_METHODS:
+ for my $base_method (@{$superclass->{instance_methods}}){
+ for my $method (@{$class->{instance_methods}}){
+ if ($$base_method{mapped_name} eq $$method{mapped_name}){
+
+ # Carry over the description for overridden methods with
+ # no description (to be javadoc compliant)
+ if (($base_method->{description} or $base_method->{vars})
+ and not $method->{description}){
+
+ $method->{description} = $base_method->{description};
+ for my $varkey (keys(%{$base_method->{vars}})){
+ $method->{vars}->{$varkey}
+ = $base_method->{vars}->{$varkey}
+ unless $method->{vars}->{$varkey};
+ }
+ }
+ next INSTANCE_METHODS;
+ }
+ }
+ for (keys %{$class->{inherits}}){
+ my $inherited = $class->{inherits}->{$_};
+ for my $method (@{$inherited->{instance_methods}}){
+ next INSTANCE_METHODS
+ if $$base_method{mapped_name} eq $method;
+ }
+ }
+ push @$instance_methods, $$base_method{mapped_name};
+ }
+ $class->{inherits}->{$superclassname}->{instance_methods}
+ = $instance_methods;
+ }
+}
+
+#
+# This is just a helper function for build_class_hierarchy
+# because that function was getting way oversized
+#
+sub handle_instance_fields {
+ my ($superclass, $superclassname, $class, $instance_fields) = @_;
+ if ($superclass->{instance_fields}){
+ INSTANCE_FIELDS:
+ for my $base_field (@{$superclass->{instance_fields}}){
+ for my $field (@{$class->{instance_fields}}){
+ next INSTANCE_FIELDS if $field eq $base_field;
+ }
+ push @$instance_fields, $base_field->{field_name};
+ }
+ $class->{inherits}->{$superclassname}->{instance_fields}
+ = $instance_fields;
+ }
+}
+
+#
+# Set all the class constructors
+#
+sub set_class_constructors {
+ for my $classname (keys %CLASSES){
+ my $constructor = $FUNCTIONS{$classname};
+ $CLASSES{$classname}->{constructor_args} =
+ $constructor->{argument_list};
+ $CLASSES{$classname}->{constructor_detail}
+ = $constructor->{description};
+
+ $CLASSES{$classname}->{constructor_vars} = $constructor->{vars} || {};
+ }
+}
+
+#
+# Clear out everything from the parsed classes and functions
+#
+sub reset_parser {
+ %CLASSES = ();
+ %FUNCTIONS = ();
+}
+
+#
+# Set global parameters for the parser
+#
+sub configure_parser {
+ %CONFIG = @_;
+}
+
+#
+# Set the initial defaults for the parser
+#
+sub initialize_parser {
+ $CONFIG{GLOBALS_NAME} ||= 'GLOBALS';
+}
+
+#
+# Run through the source and convert 'confusing' JavaScript constructs
+# into ones that are understood by the parser, as well as stripping
+# out unwanted comment blocks.
+#
+# For example:
+#
+# Foo.prototype = {
+# bar: function(){ return "Eep!"; },
+# baz: "Ha!"
+# }
+#
+# becomes
+#
+# Foo.prototype.bar = function(){ return "Eep!"; };
+# Foo.prototype.baz = "Ha!";
+#
+sub preprocess_source {
+ my ($src) = @_;
+
+ # Make all the @extends tags into @base tags
+ $src =~ s/\@extends\b/\@base/g;
+
+ # This had better not break anything!
+ $src = &deconstruct_getset($src);
+
+ # Convert:
+ # /** @singleton */
+ # Foo = {...};
+ # to:
+ # /** @singleton */
+ # Foo = function(){}
+ # Foo.prototype = {...};
+ $src =~ s!
+ ($JSDOC_COMMENT\s*)
+ (?:var\s*)?(\w+(?:\.\w+)*?)
+ \s*=\s*{
+ !index($1, '@singleton') == -1 ? "$1$2 = {" : "$1$2 = function(){}\n$2.prototype = {"!egx;
+
+
+ # Convert:
+ # /** @constructor */
+ # Foo.Bar = function(){...}
+ # to:
+ # /** @constroctor */
+ # Foo.Bar = function(){}
+ # /** @constructor */
+ # function Foo.Bar(){...}
+ #
+ # Note that we have to keep the original declaration so that Foo.Bar
+ # can be recognized as a nested class. Yes, I know it's bad...
+ $src =~ s!
+ ($JSDOC_COMMENT\s*)
+ (?:var\s*)?(\w+(?:\.\w+)*?)
+ \s*=
+ (\s*function)(?=\s*($BAL_PAREN)\s*\{)
+ !index($1, '@constructor') == -1 ? "$1$2 = $3" : "$1$2 = function$4 {};\n$1$3 $2"!egx;
+
+ # remove all uninteresting comments, but only if they're not inside
+ # of other comments
+ # (adapted from Jeffrey Friedl's "Mastering Regular Expressions"
+ {
+ no warnings;
+ $src =~ s/
+ ($NONQUOTE+|
+ $JSDOC_COMMENT$NONQUOTE*|
+ $DQUOTE$NONQUOTE*|
+ $SQUOTE$NONQUOTE*)
+ |$MLINE_COMMENT|$SLINE_COMMENT/$1/gx;
+
+ 1 while $src =~ s/$JSDOC_COMMENT\s*($JSDOC_COMMENT)/$1/g;
+ }
+
+ # Alter the prototype-initialization blocks
+ $src =~ s/
+ (\w+(?:\.\w+)*)\.prototype
+ \s*=\s*($BAL_BRACE)/deconstruct_prototype($1, $2)/egx;
+
+ # Mark all constructors based on 'new' statements
+ my %seen;
+ my @classnames = grep { not $seen{$_}++ }
+ $src =~ /\bnew\s+(\w+(?:\.\w+)*)\s*\(/g;
+ for my $cname (@classnames){
+ $src =~ s/($JSDOC_COMMENT?)
+ (?=\s*function\s+\Q$cname\E\s*$BAL_PAREN
+ \s*$BAL_BRACE)
+ /&annotate_comment($1, '@constructor')/ex;
+ }
+
+ $src =~ s/
+ ($JSDOC_COMMENT?)\s*
+ (function\s+\w+(?:\.\w+)*\s*$BAL_PAREN\s*)
+ ($BAL_BRACE)
+ /&deconstruct_constructor($1, "$2$3")/egx;
+
+ $src =~ s!
+ (?:var\s+)?(\w+(?:\.\w+)*)
+ \s*=\s*
+ new\s+
+ ($ANON_FUNCTION)!&deconstruct_singleton($1, $2)!egx;
+
+ $src = &remove_dynamic_bindings($src);
+
+ # Mark all void methods with "@type void"
+ $src =~ s/($JSDOC_COMMENT?)\s*
+ ((?:
+ (?:function\s+\w+(?:\.\w+)*\s*$BAL_PAREN\s*)
+ |
+ (?:\w+(?:\.\w+)*\s*=\s*function\s*(?:\w+\s*)?$BAL_PAREN\s*)
+ )$BAL_BRACE)
+ /&mark_void_method($1, $2)/egx;
+
+ # Clear nested functions (will save trouble later on)
+ $src =~ s/($JSDOC_COMMENT?)\s*
+ (\w+(?:\.\w+)*\s*=\s*)?
+ (function(?:\s+\w+(?:\.\w+)*)?\s*$BAL_PAREN\s*)
+ ($BAL_BRACE)
+ /&clear_nested($1, $2, $3, $4)/egx;
+
+ return $src;
+}
+
+sub clear_nested {
+ my ($doc, $assign_to, $declaration, $funcbody) = @_;
+ $assign_to ||= '';
+ if ($doc =~ /^(?=.*\@constructor|\@class)(?=.*\@exec)/){
+ warn "\@constructor or \@class can't be used together with \@exec\n";
+ }
+ if ($doc !~ /\@(constructor|class|exec)/
+ or $assign_to =~ /^\w+\.prototype\./) {
+ return "$doc\n$assign_to$declaration" . "{}\n";
+ } elsif ($doc =~ /\@(constructor|class)/) {
+ return "$doc\n$assign_to$declaration$funcbody";
+ } else {
+ my @visible_funcs = $funcbody =~ /
+ ((?:$JSDOC_COMMENT)?
+ (?:\w+\.\w+(?:\.\w+)*)\s*=\s*
+ (?:
+ $FUNC_DEF
+ |
+ $ANON_FUNCTION
+ |
+ $FUNC_CALL
+ |
+ \w+
+ )\s*;)/gx;
+ return join("\n", @visible_funcs);
+ }
+}
+
+#
+# Remove dynamic binding.
+# Change this:
+#
+# function MyFunc(class){
+# var x = 2;
+# class.prototype.func = function(){};
+# return x;
+# }
+#
+# to:
+#
+# function MyFunc(class){
+# var x = 2;
+#
+# return x;
+# }
+#
+# and change this:
+#
+# function BindMethod(obj){
+# obj.someFunc = function(){ return null; };
+# return obj;
+# }
+#
+# to:
+#
+# function BindMethod(obj){
+#
+# return obj;
+# }
+#
+sub remove_dynamic_bindings {
+ my ($src) = @_;
+ while ($src =~ /$RET_FUNC_DEF/g){
+ my ($fname, $params, $definition) = ($1, $2, $3);
+ next unless $definition =~ /\bfunction\b|\w+\.prototype\./;
+ my @params = split(/\s*,\s*/, substr($params, 1, length($params) - 2));
+ for my $param (@params){
+ $src =~ s/\b$param\.prototype\.[^;\n]*[;\n]//g;
+ $src =~ s/\b$param\.\w+ = $ANON_FUNCTION//g;
+ }
+ }
+ $src;
+}
+
+#
+# Annotate a method as being void if no @type can be found, and there is no
+# statement to return a value in the method itself.
+#
+sub mark_void_method {
+ my ($doc, $funcdef) = @_;
+ return "$doc\n$funcdef" if $doc =~ /\@(constructor|type|returns?)\b/;
+ my ($fbody) = $funcdef =~ /^[^{]*($BAL_BRACE)/;
+ $fbody =~ s/$FUNC_DEF/function x(){}/g;
+ $fbody =~ s/$ANON_FUNCTION/function (){}/g;
+ $doc = &annotate_comment($doc, '@type void')
+ if $fbody !~ /\breturn\s+(?:(?:\w+)|(?:(["']).*?\1)|$BAL_PAREN)/;
+ "$doc\n$funcdef";
+}
+
+#
+# A helper to change singleton declarations like
+#
+# MySingleton = new function(){this.x=function(){}}
+#
+# into:
+#
+# function MySingleton(){}
+# MySingleton.prototype.x = function(){};
+#
+sub deconstruct_singleton {
+ my ($classname, $definition) = @_;
+ $definition =~ s/function\s*$BAL_PAREN\s*\{(.*)\}\s*$/$1/s;
+ $definition =~ s/\bthis\./$classname.prototype\./g;
+ qq#
+ function $classname(){}
+ $definition;
+ #;
+}
+
+#
+# A helper to preprocess_source, change prototype-initialization
+# blocks into multiple prototype-property assignments
+#
+sub deconstruct_prototype {
+ my ($class, $src) = @_;
+ $src =~ s/^\{(.*)\}$/$1/s;
+ $src =~ s!
+ (\w+)
+ \s*:\s*
+ (
+ $ANON_FUNCTION
+ |
+ $FUNC_DEF
+ |
+ $FUNC_CALL
+ |
+ $LITERAL
+ |
+ $BAL_SQUAR
+ |
+ $BAL_BRACE
+ |
+ [-\w.+]+
+ )
+ \s*,?
+ !$class.prototype.$1 = $2;!gsx;
+
+ $src;
+}
+
+#
+# Unpacks a constructor into separate calls
+#
+sub deconstruct_constructor {
+ my ($doc, $func_def) = @_;
+ return "$doc$func_def" unless $doc =~ /\@(constructor|class)/;
+ my ($classname) = $func_def =~ /function\s+(\w+(?:\.\w+)*)/;
+ $func_def =~ s/
+ (\{.*\})$
+ /&deconstruct_inner_constructor($classname, $1)/esx;
+ "$doc$func_def";
+}
+
+sub deconstruct_inner_constructor {
+ my ($classname, $inner_src) = @_;
+ $inner_src = substr($inner_src, 1, -1);
+ my @doc_n_fnames = $inner_src =~ /($JSDOC_COMMENT?)\s*function\s+(\w+)/g;
+
+ unless ($CONFIG{NO_LEXICAL_PRIVATES}){
+ $inner_src =~ s/
+ ($JSDOC_COMMENT)?
+ \s*
+ var
+ \s+
+ (\w+)/&annotate_comment($1) . "\n$classname\.prototype\.$2"/egx;
+
+ $inner_src =~ s/
+ ($JSDOC_COMMENT)?\s*
+ ^\s*
+ function
+ \s+
+ (\w+)
+ /&annotate_comment($1) .
+ "\n$classname\.prototype\.$2 = function"/egmx;
+ }
+
+ {
+ no warnings;
+ $inner_src =~ s/
+ ($JSDOC_COMMENT\s*)?
+ ^\s*this(?=\.)
+ /$1$classname.prototype/gmx;
+ }
+
+ # Replace all bindings of private methods to public names
+ for (my $i = 0; $i < @doc_n_fnames; $i += 2)
+ {
+ my ($doc, $fname) = @doc_n_fnames[$i, $i + 1];
+ $inner_src =~ s/
+ ($JSDOC_COMMENT\s*
+ $classname\.prototype\.\w+)
+ \s*=\s*
+ $fname\s*[\n;]
+ /$1 = function(){}/gx;
+
+ $inner_src =~ s/
+ ($classname\.prototype\.\w+)
+ \s*=\s*
+ $fname\s*[\n;]
+ /$doc\n$1 = function(){}/gx;
+ }
+ "{}\n$inner_src";
+}
+
+#
+# Deconstruct mozilla's __defineGetter__ and __defineSetter__
+# (Yes, I know this goes against my principles...)
+#
+sub deconstruct_getset {
+ my ($src) = @_;
+ # Crack open the assignments for define(Getter|Setter)
+ my $crack = sub {
+ my $code = shift; $code =~ s/^.(.*).$/$1/s;
+ my ($name) = split ",", $code;
+ $name = ($name =~ /.*?(['"])([^'"]+)\1/)[1];
+ $name;
+ };
+ for my $prefix ('get', 'set'){
+ my $fname = "define\u${prefix}ter";
+ $src =~ s/
+ (\w+(?:\.\w+)*
+ \.prototype)
+ \.__${fname}__\s*($BAL_PAREN)/
+ my $name = $crack->($2);
+ "$1.$name = null"/gex;
+ }
+ $src;
+}
+
+
+#
+# Add an annotation (@tag) to a documentation block. The block is assumed to
+# be a valid JSDoc documentation block ==> /^\/\*\*.*\*\/$/
+# and no checking is done to verify this
+#
+sub annotate_comment {
+ my $annotation = $_[1] || '@private';
+ return "\n/** $annotation */" unless $_[0];
+ substr($_[0], 0, -2) . " \n$annotation \n*/";
+}
+
+#
+# This is here to stop perl from segfaulting from deep recursion in regexes
+# The first character in the text _should_ be open_token, as everything
+# before open_token will be discarded, unless there is no matching text
+# at all.
+#
+sub find_balanced_block {
+ my ($open_token, $close_token, $text) = @_;
+ my ($count, $open, $close) = (0, 0, 0);
+ return ('', $text) unless $text =~ /\Q$open_token\E/;
+ $text =~ s/^.*?(?=\Q$open_token\E)//s;
+ for (split //, $text){
+ $count++;
+ $open++ if $_ eq $open_token;
+ $close++ if $_ eq $close_token;
+ last unless ($open != $close);
+ }
+ warn "Unbalanced block\n" if ($open != $close);
+ (substr($text, 0, $count), substr($text, $count));
+}
+
+#
+# Remove the $CONFIG{GLOBALS_NAME} class if it doesn't contain anything
+#
+sub filter_globals {
+ my $global = $CLASSES{$CONFIG{GLOBALS_NAME}};
+ delete $CLASSES{$CONFIG{GLOBALS_NAME}} if
+ not (defined $global->{constructor_args} ||
+ defined $global->{constructor_detail})
+ && not (@{$global->{instance_methods}} ||
+ @{$global->{instance_fields}} ||
+ @{$global->{class_methods}} ||
+ @{$global->{class_fields}});
+
+ # Also get rid of extra info under the '__files__' key
+ delete $CLASSES{__FILES__}->{$_} for qw(constructor_params constructor_args
+ constructor_detail class_methods
+ constructor_vars);
+}
+
+
+#
+# Try to grab the first block comment from the file that has a @fileoverview
+# tag in it, and get the file info from there
+#
+sub parse_file_info {
+ my ($src) = @_;
+ my %fileinfo = ( src => $src );
+ while ($src =~ /($JSDOC_COMMENT)/g){
+ local $_ = substr($1, 3, length($1) - 5); # Get the actual content
+ if (/\@fileoverview\b/){
+ my $doc = parse_jsdoc_comment($_, 1);
+ %fileinfo = (%{$doc->{vars}}, %fileinfo);
+ last;
+ }
+ }
+ $CLASSES{__FILES__}->{$CTX_FILE} = \%fileinfo if $CTX_FILE;
+}
+
+1;
Added: trunk/build/JSDoc/JavaScript/Syntax/HTML.pm
===================================================================
--- trunk/build/JSDoc/JavaScript/Syntax/HTML.pm (rev 0)
+++ trunk/build/JSDoc/JavaScript/Syntax/HTML.pm 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,95 @@
+package JavaScript::Syntax::HTML;
+
+=head1 NAME
+
+JavaScript::Syntax::HTML - Convert JavaScript sourcecode to HTML
+
+=head1 SYNOPSIS
+
+ use JavaScript::Syntax::HTML qw(to_html to_html_document);
+ my $html_fragment = to_html($js_src);
+ my $html_doc = output_html_document($js_src);
+
+=head1 DESCRIPTION
+
+JavaScript::Syntax::HTML processes JavaScript code and outputs HTML with
+all reserved words marked up.
+
+The to_html method only outputs an HTML fragment (no <body> or <html> tags),
+and only marks up the reserved words with CSS styles.
+
+The to_html_document method outputs a full HTML document, and does include
+style information for the reserved words markup.
+
+The style classes that can be defined for use with to_html are C<comment>,
+C<literal>, and C<reserved>.
+
+=head1 AUTHOR
+
+Gabriel Reid gab_reid at users.sourceforge.net
+
+=cut
+
+use warnings;
+use strict;
+use Exporter;
+
+our @ISA = qw(Exporter);
+our @EXPORT_OK = qw(to_html to_html_document);
+
+sub to_html {
+ local $_ = shift;
+ s/\&/&/g;
+ s/</</g;
+ s/>/>/g;
+ s/
+ ((?:\/\*.*?\*\/)
+ |
+ (?:\/\/[^\n]*$))
+ |
+ ('[^']*'|"[^"]*")
+ |
+ \b(function|for|if|while|return|else|prototype|this)\b
+ / get_substitution($1, $2, $3) /egsxm;
+ $_;
+}
+
+sub get_substitution {
+ my ($comment, $stringliteral, $resword) = @_;
+ my $content;
+ if ($comment){
+ $comment =~ s/(\@\w+)\b/get_span('attrib', $1)/eg;
+ return get_span('comment', $comment);
+ } elsif ($stringliteral){
+ return get_span('literal', $stringliteral);
+ } elsif ($resword){
+ return get_span('reserved', $resword);
+ }
+}
+
+sub get_span {
+ my ($class, $inner) = @_;
+ qq(<span class="$class">$inner</span>);
+}
+
+sub to_html_document {
+ my ($src) = @_;
+ $src = &to_html($src);
+ qq(
+<html>
+ <head>
+ <style>
+ body { background: #FFFFFF }
+ .reserved { color: #DD3333 }
+ .comment { color: #339933 }
+ .attrib { color: #FF0000 }
+ .literal { color: #5555FF }
+ </style>
+ </head>
+ <body>
+ <pre>
+$src
+ </pre>
+ </body>
+</html>);
+}
Added: trunk/build/JSDoc/README
===================================================================
--- trunk/build/JSDoc/README (rev 0)
+++ trunk/build/JSDoc/README 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,30 @@
+README for jsdoc.pl
+
+jsdoc.pl is a script that produces javadoc-style documentation from well-formed
+JavaScript sourcefiles. At the moment, this means it supports sourcefiles where
+all functions are mapped to a class using prototype-based inheritance.
+Anonymous function definitions
+(e.g. Circle.prototype.getRadius = function(){ ...} ) are supported.
+
+This application requires Perl5, as well as one non-standard addon module:
+ - HTML::Template, which is available from CPAN (cpan.org)
+
+Invocation is simple: Just run the application, giving one or more well-formed
+OO JavaScript sourcefilename(s) as arguments. A sample JS sourcefile, test.js,
+is given along with this application. An example of running the application is
+shown below:
+
+ $ ./jsdoc.pl test.js
+
+OR
+ perl jsdoc.pl test.js
+
+Further information about using JsDoc can be found at
+http://jsdoc.sourceforge.net
+
+If there are any questions, comments, problems or anything else, please mail
+the jsdoc-user mailing list; more information can be found at
+http://sourceforge.net/mail/?group_id=30801. This application has been
+successfully tested on Linux (Debian and Redhat), and Windows 2000 with
+ActivePerl.
+
Added: trunk/build/JSDoc/TODO
===================================================================
--- trunk/build/JSDoc/TODO (rev 0)
+++ trunk/build/JSDoc/TODO 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,46 @@
+TODO for JSDoc
+
+- XML / XMI export
+
+- Improve the --package-naming option so that there are separate namespaces
+ for each package (so that you can have the same class name defined in
+ different packages)
+
+- Fix some spacing/table issues in the navbar in the templates (use a td
+ border in the stylesheet to debug)
+
+- Introduce a more generalized system for generating the navbar
+
+- Handle additional information (such as @see) for fields
+
+- Uncallable methods/functions should be marked as private, or show the scope
+ from which they can be called
+
+- Dynamic handling of assignment of prototype to a temp variable (preprocessor)
+
+- Add support for interfaces, but first this has to be better defined
+
+- Top-level var documenting (maybe add a '@global' tag to force toplevel vars
+ to be documented
+
+- Add an FAQ, more and better documentation
+
+- Java port (someday...)
+
+- Make a more polished API for using other doclets, like javadoc
+
+- Add a deprecated page, make deprecated support more like javadoc
+
+- Add support for js files without .js extension
+
+- Support for a time stamp
+
+- Some of the ->{vars} are set to undef, should always be an empty map
+
+- Add command line params --dump-tree, --dump-xml
+
+- Add command line param --stylesheet
+
+- Make navbar links selective so they are never broken
+
+- Update the help doc
Added: trunk/build/JSDoc/TestJSDoc.pl
===================================================================
--- trunk/build/JSDoc/TestJSDoc.pl (rev 0)
+++ trunk/build/JSDoc/TestJSDoc.pl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,696 @@
+#!/usr/bin/perl
+
+package JSDoc;
+#
+# Unit testing of JSDoc
+#
+# Run with 'perl TestJSDoc.pl' or './TestJSDoc.pl'
+#
+
+use strict;
+use warnings;
+
+
+
+use JSDoc;
+use Data::Dumper;
+use Test::More qw(no_plan);
+
+$|++;
+
+# parse_jsdoc_comment
+diag("Testing parse_jsdoc_comment");
+is_deeply(parse_jsdoc_comment(''), {summary => ''},
+ "Ensure only summary is filled in");
+
+is(parse_jsdoc_comment('')->{summary}, '', 'Empty comment value');
+
+
+is(parse_jsdoc_comment(
+ '************************* test *************')->{summary},
+ 'test', 'long leading and trailing stars');
+
+
+# annotate_comment
+diag("Testing annotate_comment");
+is(annotate_comment, "\n/** \@private */", 'annotate_comment w/o arg');
+like(annotate_comment("/** This is a test */"),
+ qr#^/\s*\*\*\s*This is a test\s+\@private\s*\*/\s*$#,
+ 'annotate_comment w/ arg');
+like(annotate_comment("/** This is a test */", '@testtag value'),
+ qr#^/\s*\*\*\s*This is a test\s+\@testtag\svalue\s*\*/\s*$#,
+ 'annotate_comment w/ tag argument');
+
+# find_balanced_block
+diag("Testing find_balanced_block");
+my @blocks = (
+ # basic simple input
+ ['{', '}', '{ this is in the braces } {this is after}{{',
+ ['{ this is in the braces }', ' {this is after}{{'] ,
+ 'basic input'],
+
+ # discard leading chars before opening char
+ ['{', '}', 'discard {inner} after',
+ ['{inner}', ' after'], 'discard leading chars'],
+
+ # empty input string
+ ['{', '}', '',
+ ['', ''], 'empty input string'],
+
+ # nothing to match at all
+ ['{', '}', 'there is nothing to match',
+ ['', 'there is nothing to match'], 'nothing to match'],
+ );
+for my $test (@blocks){
+ my @args = @{$test}[0..2];
+ my ($expect, $explain) = @{$test}[3,4];
+ is_deeply([find_balanced_block(@args)], $expect, $explain);
+}
+
+#
+# Test the @member tag
+#
+diag('Testing the @member tag');
+reset_parser();
+my $src = q#
+/** @constructor */
+function Foo(){
+ this.x = function(){return null;};
+}
+/** Unrelated */
+function myfunc(){return null;}
+#;
+my $classes = parse_code_tree(\$src);
+my %method_names = map { $_->{mapped_name} => 1 }
+ @{$classes->{Foo}->{instance_methods}};
+ok(not(defined($method_names{myfunc})),
+ 'Unrelated method is not added to class without @member tag');
+reset_parser();
+$src = q#
+/** @constructor */
+function Foo(){
+ this.x = function(){return null;};
+}
+/**
+ * @member Foo
+ */
+function myfunc(){return null;}
+#;
+$classes = parse_code_tree(\$src);
+%method_names = map { $_->{mapped_name} => 1 }
+ @{$classes->{Foo}->{instance_methods}};
+ok(defined($method_names{myfunc}),
+ 'Add method marked with @member to class');
+reset_parser();
+
+#
+# preprocess_source
+#
+
+diag("Testing preprocess_source");
+
+# Make sure that:
+#
+# Foo.prototype = {
+# bar: function(){ return "Eep!"; },
+# baz: "Ha!"
+# }
+#
+# becomes:
+#
+# Foo.prototype.bar = function(){ return "Eep!"; };
+# Foo.prototype.baz = "Ha!";
+
+my $before = q/
+ Foo.prototype = {
+ bar: function(){ return "Eep!"; },
+ baz: "Ha!"
+ } /;
+
+my $after_re = qr/^\s*(?:$JSDOC_COMMENT)?\s*Foo.prototype.bar
+ \s*=\s*
+ function\(\s*\)\s*\{[^\}]*}\s*;\s*
+ Foo\.prototype\.baz\s*=\s*"[^"]+"\s*;\s*$/x;
+
+like(preprocess_source($before), $after_re,
+ 'Unpack prototype block assignment');
+
+#
+# Make sure that:
+#
+# /** @constructor */
+# Foo.Bar = function(){this.x = 2;var y = 3;}
+# becomes:
+# /** @constructor */
+# Foo.Bar = function(){};
+#
+# /** @constructor */
+# function Foo.Bar(){}
+#
+# Foo.Bar.prototype.x = 2;
+#
+# /** @private */
+# Foo.Bar.prototype.y = 3;
+#
+$before = q#
+ /** @constructor */
+ Foo.Bar = function(){this.x = 2; var y = 3; }#;
+$after_re = qr{
+ ^\s*/\*\*\s*\@constructor\s*\*/\s*
+ Foo\.Bar\s*=\s*function\s*\(\s*\)\s*\{\s*\}\s*;\s*
+ /\*\*\s*\@constructor\s*\*/\s*
+ function\s+Foo\.Bar\s*\(\s*\)\s*\{\s*\}
+ \s*
+ Foo\.Bar\.prototype\.x\s*=\s*2\s*;\s*
+ /\*\*\s*\@private\s*\*/\s*
+ Foo\.Bar\.prototype\.y\s*=\s*3\s*;\s*$
+ }x;
+like(preprocess_source($before), $after_re,
+ 'Unpack nested class');
+
+#
+# Make sure that:
+# MySingleton = new function(){this.x=function(){}}
+# and
+# var MySingleton = new function(){this.x=function(){}}
+# become:
+# function MySingleton(){}
+# MySingleton.prototype.x = function(){};
+#
+$before = q# MySingleton = new function(){this.x=function(){}} #;
+$after_re = qr{
+ ^\s*(?:$JSDOC_COMMENT)?
+ \s*function\s*MySingleton\s*\(\)\s*\{\s*\}\s*
+ (?:$JSDOC_COMMENT)?\s*
+ MySingleton\.prototype\.x\s*=\s*function\s*\(\s*\)\s*\{\s*\}\s*;\s*$}x;
+like(preprocess_source($before), $after_re,
+ 'Unpack singleton');
+
+# Same thing, but with var before the declaration
+$before = q#var MySingleton = new function(){this.x=function(){}} #;
+like(preprocess_source($before), $after_re,
+ "Unpack var'd singleton");
+
+
+#
+# Test unpacking a constructor into a bunch of
+# prototype-based declarations
+#
+
+$before = q#
+ /**
+ * @constructor
+ */
+ function MyClass(){
+ /** Private variable 'x' */
+ var x = 3;
+ /**
+ * This is my function
+ */
+ this.myFunction = function(){ return null; };
+
+ /**
+ * This is a private function
+ */
+ function myPrivateFunction(x){
+ return null;
+ }
+ }
+#;
+$after_re = qr{
+ /\*\*\s*
+ \*\s*\@constructor\s*
+ \*/\s*
+ function\s+MyClass\s*\(\s*\)\s*\{\s*\}\s*
+
+ /\*\*\s*Private\svariable\s'x'\s*
+ \@private\s*\*/\s*
+ MyClass\.prototype\.x\s*=\s*3\s*;\s*
+
+ /\*\*\s*
+ \*\s*This\sis\smy\sfunction\s*\*/\s*
+ MyClass\.prototype\.myFunction\s*=\s*function\s*\(\s*\)\s*\{
+ [^\}]*\}\s*;\s*
+
+ /\*\*\s*
+ \*\s*This\sis\sa\sprivate\sfunction\s*
+ \@private\s*\*/\s*
+ MyClass\.prototype\.myPrivateFunction\s*=\s*function\(\s*x\s*\)\s*
+ \{[^\}]*\}\s*$
+}x;
+
+like(preprocess_source($before), $after_re,
+ 'Testing unpacking a constructor into prototype-based assignments');
+
+
+#
+# Test the marking of void methods
+#
+$before = q'function MyFunc(){}';
+$after_re = qr{/\*\*\s*\@type\s+void\s*\*/\s*function\s+MyFunc\s*\(\)\{\}};
+like(preprocess_source($before), $after_re,
+ "Testing basic marking of void method without a docstring");
+
+$before = q'
+/** Method */
+function MyFunc(){}
+';
+$after_re = qr{/\*\*\s*Method\s+\@type\s+void\s*\*/\s*
+ function\s+MyFunc\(\)\{\}}x;
+like(preprocess_source($before), $after_re,
+ "Testing basic marking of void methods");
+
+$before = '/** Method */
+ Shape.prototype.MyFunc = function(){}';
+$after_re = qr{
+ /\*\*\s*
+ Method\s+
+ \@type\s+void\s*
+ \*/\s*Shape\.prototype\.MyFunc\s*=\s*function\(\)\{\}}x;
+like(preprocess_source($before), $after_re,
+ "Testing marking of void anonymous method");
+
+$before = 'Shape.prototype.MyFunc = function(){return null;}';
+$after_re = qr{^\s*Shape\.prototype\.MyFunc\s*=
+ \s*function\(\)\{[^\}]*\}}x;
+like(preprocess_source($before), $after_re,
+ "Testing marking of void anonymous method");
+
+$before = "function x(){return null;}";
+$after_re = qr{\s*function\sx\(\)\s*\{[^\}]*\}\s*$};
+like(preprocess_source($before), $after_re,
+ "Leave non-void methods without docstrings alone");
+
+$before = "/** My test function */\nfunction x(){return null;}";
+$after_re = qr{\s*/\*\*\s*My\stest\sfunction\s*\*/\s*
+ function\sx\(\)\s*\{[^\}]*\}\s*$}x;
+like(preprocess_source($before), $after_re,
+ "Leave non-void methods with docstrings alone");
+
+reset_parser();
+$src = q#
+/**
+ * @constructor
+ */
+function MyClass(){
+ this.af = afunc;
+ this.bf = bfunc;
+ this.cf = cfunc;
+ function afunc(){}
+ function bfunc(){}
+ function cfunc(){}
+}
+#;
+$classes = parse_code_tree(\$src);
+ok(eq_set(
+ [ map { $_->{mapped_name} }
+ @{$classes->{MyClass}->{instance_methods}}],
+ ['af', 'bf', 'cf', 'afunc', 'bfunc', 'cfunc']),
+ "Ensure instance methods in constructor are correctly assigned");
+
+
+
+reset_parser();
+$src = 'function MyFunction(){ return ""; }';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{GLOBALS}->{class_methods}->[0]->{vars}->{type}),
+ "Ensure a function returning an empty string is not marked as void");
+
+reset_parser();
+$src = 'function A(){ var x = "x"; }';
+$classes = parse_code_tree(\$src);
+ok($classes->{GLOBALS}->{class_methods}->[0]->{vars}->{type}->[0] eq 'void',
+ "Ensure a global void is void");
+
+reset_parser();
+$src = 'function A(c){ c.someFunc = function(){ return 2; }; }';
+$classes = parse_code_tree(\$src);
+ok($classes->{GLOBALS}->{class_methods}->[0]->{vars}->{type}->[0] eq 'void',
+ "Ensure inner function definitions don't affect the return type");
+
+reset_parser();
+$src = 'function A(c){ c.someFunc = function(){ return 2; }; return ""; }';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{GLOBALS}->{class_methods}->[0]->{vars}->{type}->[0]),
+ "Ensure inner-function measures don't affect non-void functions");
+
+reset_parser();
+$src = '/** @return {int} Description */function f(){}';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{GLOBALS}->{class_methods}->[0]->{vars}->{type}->[0]),
+ 'Methods with a @return tag but no return statement are not marked void');
+
+reset_parser();
+$src = 'function f(){ return (true ? "t" : "f");}';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{GLOBALS}->{class_methods}->[0]->{vars}->{type}->[0]),
+ "Non-void with non-trivial return statement is not marked as void");
+
+#
+# Try huge constructor input
+#
+my @testsrc = (q#
+/**
+ * @class This is class information
+ * @constructor
+ */
+ function MyClass(){
+
+#);
+for (1..30){
+ push @testsrc, "
+ /** This is a private method */
+ function f$_(){ return null; }
+
+ /**
+ * THis is function number $_
+ * \@return Nothing
+ */
+ this.func$_ = function(){if(true){if(false){return null;}}} ;\n";
+}
+push @testsrc, "\n}\n";
+my $testsrc = join("\n", @testsrc);
+# This could crash everything
+preprocess_source($testsrc);
+pass("Process huge constructor with preprocess_source");
+
+
+#
+# Huge constructor with unbalanced input
+#
+ at testsrc = (q#
+/**
+ * @class This is class information
+ * @constructor
+ */
+ function MyClass(){
+
+#);
+for (1..100){
+ push @testsrc, "
+ /**
+ * THis is function number $_
+ * \@return Nothing
+ */
+ this.func$_ = function(){if(true){if(false){return null;}};\n";
+}
+push @testsrc, "\n}\n";
+$testsrc = join("\n", @testsrc);
+# This could crash everything
+preprocess_source($testsrc);
+pass("Process huge unbalanced constructor with preprocess_source");
+
+#
+# deconstruct_mozilla_getset
+#
+$before = 'MyClass.prototype.__defineGetter__("myProp", function(){return null;});';
+$after_re = qr{
+ ^\s*MyClass\.prototype\.myProp\s*=\s*null\s*;\s*$}x;
+ #\s*function\s*\(\s*\)\s*\{\s*return\s+null\s*;\s*\}\s*;\s*$}x;
+
+like(deconstruct_getset($before), $after_re,
+ "Testing behaviour of __defineGetter__");
+like(preprocess_source($before), $after_re,
+ "Testing behaviour of __defineGetter__ in preprocess_source");
+
+$before = 'MyClass.prototype.__defineSetter__("myProp", function(){return null;});';
+$after_re = qr{
+ ^\s*MyClass\.prototype\.myProp\s*=\s*null\s*;\s*$}x;
+
+like(deconstruct_getset($before), $after_re,
+ "Testing behaviour of __defineSetter__");
+like(preprocess_source($before), $after_re,
+ "Testing behaviour of __defineSetter__ in preprocess_source");
+
+reset_parser();
+$src = "
+ function MyFunc(theclass){
+ var x = 2;
+ theclass.prototype.f = function(){};
+ return x;
+ }
+ MyClass.prototype.f = function(){};
+";
+$classes = parse_code_tree(\$src);
+ok(not(defined($classes->{theclass})),
+ "Ensure that dynamic prototyping doesn't add classes");
+ok(defined($classes->{MyClass}),
+ "Ensure that normal classes are added with static prototyping");
+
+
+# Test @singleton handling
+reset_parser();
+$src = q#
+ /** @singleton */
+ var SingletonClass = {
+ funcA: function(){},
+ funcB: function(){} };
+#;
+$classes = parse_code_tree(\$src);
+ok(defined($classes->{SingletonClass}));
+my @fnames = sort map { $_->{mapped_name}}
+ @{$classes->{SingletonClass}->{instance_methods}};
+is(scalar(@fnames), 2);
+ok(eq_array(\@fnames, ["funcA", "funcB"]));
+
+
+#
+# miscellaneous tests
+#
+diag("Miscellaneous tests");
+reset_parser();
+$src = "
+ /** \@constructor */
+ function A(){}
+ /** \@constructor */
+ function C(){}
+ /** \@constructor
+ \@extends A
+ */
+ function B(){}
+ B.prototype = new C();";
+
+$classes = parse_code_tree(\$src);
+is($classes->{B}->{extends}, 'A',
+ "Test that the first extends marking is the good one, others are ignored");
+
+reset_parser();
+$src = "function A(){ this.n = function(){return 2};}
+ var a = new A(); ";
+$classes = parse_code_tree(\$src);
+ok(defined($classes->{A}),
+ "Functions are later used with 'new' must be treated as a constructor");
+
+ok(!defined($classes->{this}), "'this' cannot be added as a class");
+
+
+#
+# Ensure using the @base tag automatically qualifies a function as a class,
+# even if the base class isn't defined
+#
+reset_parser();
+$src = '/** @base SomeOtherClass */
+function MyClass(){}';
+$classes = parse_code_tree(\$src);
+ok(defined($classes->{MyClass}),
+ 'A function must be upgraded to a class if the @base tag is used');
+
+#
+# Allow an anonymous function to be assigned to a global variable,
+# resulting in a new class
+#
+reset_parser();
+$src = '
+/**
+ * Some function
+ * @constructor
+ */
+var SomeClass = function(){ this.x = 2; }
+';
+$classes = parse_code_tree(\$src);
+ok(defined($classes->{SomeClass}),
+ "Allow anonymous function to be assigned to a global variable");
+
+#
+# Make sure that dynamically binding methods to a object at a later time
+# do not affect the documentation
+#
+reset_parser();
+$src = '
+function AddCallback(obj){
+ obj.callback = function(){ return null; };
+}';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{obj}),
+ "Don't add passed-in objects as classes when doing dynamic binding");
+
+reset_parser();
+$src = '
+/** @constructor */
+function A(){}
+A.prototype.setup = A_Setup;
+A.prototype.tearDown = A_TearDown;
+function A_Setup(){
+ this.callback = function(){ return null; };
+}
+function A_TearDown(){
+ this.tornDown = true;
+}';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{this}),
+ "Don't add 'this' as a class when dynamically adding methods in a method");
+
+#
+# Test block prototype assignment
+#
+diag("Test block prototype assignment");
+reset_parser();
+$src = '
+SomeClass.prototype = {
+ funcA: function(){ return null; },
+ valA: 3,
+ funcB: function(){ return null; },
+ valB: "just testing",
+ funcC: function(){}
+};';
+$classes = parse_code_tree(\$src);
+ok(eq_set(
+ [ map { $_->{mapped_name} }
+ @{$classes->{SomeClass}->{instance_methods}}],
+ ['funcA', 'funcB', 'funcC']),
+ "Ensure instance methods are assigned in prototype definition block");
+ok(eq_set(
+ [ map { $_->{field_name} }
+ @{$classes->{SomeClass}->{instance_fields}}],
+ ['valA', 'valB']),
+ "Ensure instance fields are assigned in prototype definition block");
+
+#
+# Test prototype assignment
+#
+diag("Test prototype assignment");
+reset_parser();
+$src = '
+function Base(){}
+function Sub(){}
+Sub.prototype = new Base();
+';
+$classes = parse_code_tree(\$src);
+ok($classes->{Sub}->{extends} eq 'Base',
+ "Prototype assignment results in inheritance");
+
+reset_parser();
+$src = '
+function Base(){}
+function Sub(){}
+Sub.prototype = new Base;
+';
+$classes = parse_code_tree(\$src);
+ok($classes->{Sub}->{extends} eq 'Base',
+ "Prototype assignment results in inheritance (2)");
+
+#
+# Test the handling of methods defined more than once
+#
+reset_parser();
+$src = '
+function f(){}
+/** doc */
+function f(){}
+';
+$classes = parse_code_tree(\$src);
+ok($classes->{GLOBALS}->{class_methods}->[0]->{description} eq 'doc',
+ "In case of double function definition, the one with most info wins");
+
+reset_parser();
+$src = '
+/** doc */
+function f(){}
+function f(){}
+';
+$classes = parse_code_tree(\$src);
+ok($classes->{GLOBALS}->{class_methods}->[0]->{description} eq 'doc',
+ "In case of double function definition, the one with most info wins (2)");
+
+#
+# Make sure that extra JSDoc-style comment blocks are not viewed as source
+#
+reset_parser();
+$src = '
+/** @constructor */
+function x(){}
+
+/** more doc
+function y(){}
+*/
+
+/** @constructor */
+function z(){}
+';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{GLOBALS}->{class_methods}->[0]),
+ "Ignore JSDoc in extra JSDoc-comment blocks");
+
+
+#
+# Test the behaviour of the @ignore tag
+#
+reset_parser();
+$src = '
+/** This method is normal */
+function Normal(){}
+
+/** @ignore */
+function Hidden(){}
+';
+$classes = parse_code_tree(\$src);
+my %fnames = map { $_->{mapped_name} => 1 }
+ @{$classes->{GLOBALS}->{class_methods}};
+ok(defined $fnames{Normal}, "A normal method is picked up and documented");
+ok(!defined $fnames{Hidden}, 'An @ignored method is not picked up');
+
+#
+# Test the behaviour of the @addon tag
+#
+reset_parser();
+$src = '
+/**
+ * Should be ignored
+ */
+ClassOne.funcOne = function(){};
+
+/**
+ * Should not be ignored
+ * @addon
+ */
+ClassTwo.funcOne = function(){};
+
+ClassThree.prototype = new Object();
+ClassThree.funcThree = function(){}';
+$classes = parse_code_tree(\$src);
+ok(!defined($classes->{ClassOne}),
+ 'Extensions to undefined classes/objects without @addon are ignored');
+ok(defined($classes->{ClassTwo}),
+ 'Extensions to undefined classes/objects with @addon are not ignored');
+ok($classes->{ClassThree}->{class_methods}->[0]->{mapped_name} eq 'funcThree',
+ 'Class methods without @addon work on pre-defined classes');
+
+#
+# Ensure enclosing package-classes are still recognized without using @addon
+#
+reset_parser();
+$src = '
+/**
+ * @constructor
+ */
+package.MyClass = function MyClass(){}
+
+package.MyClass.prototype.foo = function foo(){}
+';
+$classes = parse_code_tree(\$src);
+ok(defined($classes->{package}),
+ 'Super-package-classes must be recognized without the @addon tag');
+ok(defined($classes->{'package.MyClass'}),
+ 'Sub-package-classes must be recognized without the @addon tag');
+
+
Added: trunk/build/JSDoc/allclasses-frame.tmpl
===================================================================
--- trunk/build/JSDoc/allclasses-frame.tmpl (rev 0)
+++ trunk/build/JSDoc/allclasses-frame.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<TITLE>
+<TMPL_VAR NAME="project_name"> <TMPL_VAR NAME="filename">
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="<TMPL_VAR NAME="project_name"> <TMPL_VAR NAME="filename">";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+<TMPL_IF NAME="logo">
+ <IMG SRC="<TMPL_VAR NAME="logo">"/>
+</TMPL_IF>
+<H3 class="FrameHeadingFont"><B><TMPL_VAR NAME="project_name"></B></H3>
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B><TMPL_VAR NAME="fname_link"></B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%">
+
+<TMPL_LOOP name="classnames">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="<TMPL_VAR name="classlink">" TARGET="classFrame"><TMPL_VAR name="classname"></A>
+<BR>
+</FONT></TD>
+</TR>
+</TMPL_LOOP>
+</TABLE>
+
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/allclasses-noframe.tmpl
===================================================================
--- trunk/build/JSDoc/allclasses-noframe.tmpl (rev 0)
+++ trunk/build/JSDoc/allclasses-noframe.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>
+<TMPL_VAR NAME="project_name"> All Classes
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="<TMPL_VAR NAME="project_name"> All Classes";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+<TMPL_IF NAME="logo">
+ <IMG SRC="<TMPL_VAR NAME="logo">"/>
+</TMPL_IF>
+<H3 CLASS="FrameHeadingFont"><TMPL_VAR NAME="project_name"></H3>
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B><a href="overview-summary.html">All Classes</a></B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%">
+
+<TMPL_LOOP name="classnames">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="<TMPL_VAR name="classlink">" ><TMPL_VAR name="classname"></A>
+<BR>
+</FONT></TD>
+</TR>
+</TMPL_LOOP>
+</TABLE>
+
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/constant-values.tmpl
===================================================================
--- trunk/build/JSDoc/constant-values.tmpl (rev 0)
+++ trunk/build/JSDoc/constant-values.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>
+<TMPL_VAR NAME="project_name"> Constant Values
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="<TMPL_VAR NAME="project_help"> Constant Values";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD-->
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER> <H1>Constant Field Values</H1> </CENTER>
+<HR>
+<UL>
+<TMPL_LOOP NAME="classnames">
+ <LI><A HREF="#<TMPL_VAR NAME="name">"><TMPL_VAR NAME="name"></A></LI>
+</TMPL_LOOP>
+</UL>
+
+<HR>
+
+<TMPL_LOOP NAME="static_finals">
+ <A NAME="<TMPL_VAR NAME="classname">"></A>
+ <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0">
+ <TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+ <TD colspan="2">
+ <B><A HREF="<TMPL_VAR NAME="classname">.html"><TMPL_VAR NAME="classname"></A></B>
+ </TD>
+ </TR>
+
+ <TMPL_LOOP NAME="static_values">
+ <TR>
+ <A NAME="<TMPL_VAR NAME="classname">.!s!<TMPL_VAR NAME="name">"></A><TD><CODE><A HREF="<TMPL_VAR NAME="classname">.html#<TMPL_VAR NAME="name">"><TMPL_VAR NAME="name"></A></CODE></TD>
+ <TD ALIGN="right"><CODE><TMPL_VAR NAME="value"></CODE></TD>
+ </TR>
+ </TMPL_LOOP>
+ </TABLE>
+ <P>
+
+ <P>
+</TMPL_LOOP>
+
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><b>Tree</b></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD-->
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<FONT SIZE="-1">
+<TMPL_VAR NAME="page_footer">
+</FONT>
+<div class="jsdoc_ctime">Documentation generated by <a href="http://jsdoc.sourceforge.net/" target="_parent">JSDoc</a> on <TMPL_VAR NAME="ctime"></div>
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/help-doc.tmpl
===================================================================
--- trunk/build/JSDoc/help-doc.tmpl (rev 0)
+++ trunk/build/JSDoc/help-doc.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,160 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>
+<TMPL_VAR NAME="project_name"> API Help
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="<TMPL_VAR NAME="project_help"> API Help";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD-->
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H1>
+How This API Document Is Organized</H1>
+</CENTER>
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.<H3>
+Class</H3>
+<BLOCKQUOTE>
+
+<P>
+Each class has its own separate page. Each of these pages has three sections consisting of a class description, summary tables, and detailed member descriptions:<UL>
+<LI>Class inheritance diagram<LI>Direct Subclasses<LI>Class declaration<LI>Class description
+<P>
+<LI>Field Summary<LI>Constructor Summary<LI>Method Summary
+<P>
+<LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL>
+Each summary entry contains the first sentence from the detailed description for that item. </BLOCKQUOTE>
+<!--H3>
+Tree (Class Hierarchy)</H3>
+<BLOCKQUOTE>
+There is a <A HREF="overview-tree.html">Class Hierarchy</A> page for all classes. The hierarchy page contains a list of classes. The classes are organized by inheritance structure starting with <code>Object</code>.<UL>
+</BLOCKQUOTE-->
+<!-- H3>
+Deprecated API</H3>
+<BLOCKQUOTE>
+The <A HREF="deprecated-list.html">Deprecated API</A> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</BLOCKQUOTE-->
+<H3>
+Index</H3>
+<BLOCKQUOTE>
+The <A HREF="index-all.html">Index</A> contains an alphabetic list of all classes, constructors, methods, and fields.</BLOCKQUOTE>
+<H3>
+Prev/Next</H3>
+These links take you to the next or previous class, interface, package, or related page.<H3>
+Frames/No Frames</H3>
+These links show and hide the HTML frames. All pages are available with or without frames.
+<P>
+<FONT SIZE="-1">
+<EM>
+This help file applies to API documentation generated using the standard doclet.</EM>
+</FONT>
+<BR>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><b>Tree</b></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD-->
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<FONT SIZE="-1">
+<TMPL_VAR NAME="page_footer">
+</FONT>
+<div class="jsdoc_ctime">Documentation generated by <a href="http://jsdoc.sourceforge.net/" target="_parent">JSDoc</a> on <TMPL_VAR NAME="ctime"></div>
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/index-all.tmpl
===================================================================
--- trunk/build/JSDoc/index-all.tmpl (rev 0)
+++ trunk/build/JSDoc/index-all.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,142 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<TITLE>
+Index ()
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Index ()";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD-->
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="index-all.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+<TMPL_IF NAME="letters">
+<!--
+ Listing of letters
+-->
+<TMPL_LOOP NAME="letters"> <A HREF="index-all.html#__<TMPL_VAR NAME="letter_name">__"><TMPL_VAR NAME="letter_name"></A></TMPL_LOOP>
+<HR>
+<!-- End letter listing -->
+<TMPL_LOOP NAME="index_list">
+<A NAME="__<TMPL_VAR NAME="letter">__"><!-- --></A><H2>
+<B><TMPL_VAR NAME="letter"></B></H2>
+<TMPL_LOOP NAME="value">
+<DL>
+<DT><A HREF="<TMPL_VAR NAME="classlink">#<TMPL_VAR NAME="linkname">"><B><TMPL_VAR NAME="name"></B></A> -
+<TMPL_VAR NAME="type"> class <A HREF="<TMPL_VAR NAME="classlink">"><TMPL_VAR NAME="class"></A>
+<DD>
+</DL>
+</TMPL_LOOP>
+<HR>
+</TMPL_LOOP>
+<!--
+ Listing of letters
+-->
+<TMPL_LOOP NAME="letters"> <A HREF="index-all.html#__<TMPL_VAR NAME="letter_name">__"><TMPL_VAR NAME="letter_name"></A></TMPL_LOOP>
+
+</TMPL_IF>
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><b>Tree</b></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A> </TD-->
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="index-all.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<FONT SIZE="-1">
+<TMPL_VAR NAME="page_footer">
+</FONT>
+<div class="jsdoc_ctime">Documentation generated by <a href="http://jsdoc.sourceforge.net/">JSDoc</a> on <TMPL_VAR NAME="ctime"></div>
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/index.tmpl
===================================================================
--- trunk/build/JSDoc/index.tmpl (rev 0)
+++ trunk/build/JSDoc/index.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>
+Generated Javascript Documentation
+</TITLE>
+</HEAD>
+<FRAMESET cols="20%,80%">
+<TMPL_IF NAME="multifile">
+<FRAMESET rows="40%,50%">
+<FRAME src="overview-frame.html" name="overviewFrame">
+</TMPL_IF>
+<FRAME src="allclasses-frame.html" name="packageFrame">
+<TMPL_IF NAME="multifile">
+</FRAMESET>
+</TMPL_IF>
+<FRAME src="<TMPL_VAR name="default_classname">" name="classFrame">
+</FRAMESET>
+<NOFRAMES>
+<H2>
+Frame Alert</H2>
+
+<P>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<BR>
+Link to <A HREF="allclasses-frame.html">Non-frame version.</A></NOFRAMES>
+</HTML>
Added: trunk/build/JSDoc/jsdoc.pl
===================================================================
--- trunk/build/JSDoc/jsdoc.pl (rev 0)
+++ trunk/build/JSDoc/jsdoc.pl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,1569 @@
+#!/usr/bin/perl -w
+
+#
+# This program makes use of the JSDoc module to make a JavaDoc equivalent
+# for JavaScript. The template that is used is based on the JavaDoc
+# doclet. This program only needs to be invoked with one or more
+# JS OO sourcefiles as command-line args.
+#
+
+use strict;
+use HTML::Template;
+use File::Copy;
+use File::Basename;
+use File::Path;
+use Getopt::Long;
+use File::Find;
+use lib dirname($0);
+use JSDoc;
+use JSDoc::XML;
+use JSDoc::XMI;
+use JavaScript::Syntax::HTML qw(to_html);
+
+
+use constant LOCATION => dirname($0) . '/';
+use constant MAIN_TMPL => "main.tmpl";
+use constant ALLCLASSES_TMPL => 'allclasses-frame.tmpl';
+use constant ALLCLASSES_NOFRAME_TMPL => 'allclasses-noframe.tmpl';
+use constant OVERVIEW_FRAME_TMPL => 'overview-frame.tmpl';
+use constant TREE_TMPL => 'overview-tree.tmpl';
+use constant OVERVIEW_TMPL => 'overview-summary.tmpl';
+use constant INDEX_TMPL => 'index.tmpl';
+use constant DEFAULT_DEST_DIR => 'js_docs_out/';
+use constant STYLESHEET => 'stylesheet.css';
+use constant HELP_TMPL => 'help-doc.tmpl';
+use constant INDEX_ALL_TMPL => 'index-all.tmpl';
+use constant CONSTANTS_TMPL => 'constant-values.tmpl';
+
+use vars qw/ $CLASSES $DEFAULT_CLASSNAME @CLASSNAMES @INDEX %TMPL_CACHE
+ %CLASS_ATTRS_MAP %METHOD_ATTRS_MAP %FILE_ATTRS_MAP %OPTIONS
+ @FILENAMES %FILE_OVERVIEWS $TIME $CURRENT_CLASS /;
+
+#
+# Begin main execution
+#
+
+&parse_cmdline;
+&initialize_param_maps;
+$TIME = localtime();
+do '.jsdoc_config';
+warn "Error parsing config file: $@\n" if $@;
+
+my @sources;
+
+mkdir($OPTIONS{OUTPUT})
+ or die "Can't create output directory $OPTIONS{OUTPUT}: $!\n"
+ unless (-e $OPTIONS{OUTPUT} && -d $OPTIONS{OUTPUT});
+
+
+if (@ARGV < 1 || $OPTIONS{HELP} || !(@sources = &load_sources())){
+ warn "No sourcefiles supplied\n" if !$OPTIONS{HELP};
+ &show_usage();
+ exit(1);
+}
+
+# Parse the code tree
+&configure_parser(
+ GLOBALS_NAME => $OPTIONS{GLOBALS_NAME},
+ NO_LEXICAL_PRIVATES => $OPTIONS{NO_LEXICAL_PRIVATES});
+$CLASSES = &parse_code_tree(@sources);
+%FILE_OVERVIEWS = %{delete $CLASSES->{__FILES__}};
+&map_implementation_classes();
+die "Nothing to document, exiting\n" unless keys %{$CLASSES};
+
+if ($OPTIONS{FORMAT} eq 'html'){
+ &output_html;
+} elsif ($OPTIONS{FORMAT} eq 'xml') {
+ &output_xml;
+} elsif ($OPTIONS{FORMAT} eq 'xmi'){
+ &output_xmi;
+} else {
+ die "Unknown data format '$OPTIONS{FORMAT}'\n";
+}
+&_log('Completed generating documentation');
+
+#
+# End main execution
+#
+
+
+sub map_implementation_classes {
+ my (%implementations, %implementors);
+ for my $class (keys %$CLASSES){
+ my $implements = $CLASSES->{$class}->{constructor_vars}->{implements};
+ if ($implements){
+ for my $iname (map {strip($_)} @$implements){
+ push @{$implementations{$class}}, $iname;
+ push @{$implementors{$iname}}, $class;
+ }
+ }
+ }
+
+ sub add_method_to_subclasses {
+ my ($cname, $method, $subclasses_of) = @_;
+ $subclasses_of ||= $cname;
+ for my $subclass (keys %$CLASSES){
+ if (($CLASSES->{$subclass}->{extends} || '') eq $subclasses_of){
+ if (not has_method($subclass, $method)){
+ my $inherits_hash = $CLASSES->{$subclass}->{inherits};
+ push @{$inherits_hash->{$cname}->{instance_methods}},
+ $method;
+ add_method_to_subclasses($cname, $method, $subclass);
+ }
+ }
+ }
+ }
+
+ sub get_instance_method {
+ my ($classname, $methodname) = @_;
+ my $class = $CLASSES->{$classname} or return undef;
+ for my $method (@{$class->{instance_methods}}){
+ if ($method->{mapped_name} eq $methodname){
+ return $method;
+ }
+ }
+ return undef;
+ }
+
+ # Copy the methods to the implementor
+ for my $class (keys %implementations){
+ for my $interface (map {$CLASSES->{$_}} @{$implementations{$class}}){
+ my @interface_methods = @{$interface->{instance_methods} || []};
+ for my $superclass (keys %{$interface->{inherits} || {}}){
+
+ push @interface_methods,
+ map { get_instance_method($superclass, $_) }
+ @{$interface->{inherits}->{$superclass}->
+ {instance_methods}};
+ }
+
+ for my $interface_method (@interface_methods){
+ if (not has_method($class, $interface_method->{mapped_name})){
+ push @{$CLASSES->{$class}->{instance_methods}},
+ $interface_method;
+ add_method_to_subclasses($class,
+ $interface_method->{mapped_name});
+ }
+ }
+ }
+ }
+
+ # Put a flag on interfaces to say who they're implemented by
+ for my $interface (keys %implementors){
+ my $interface_class = $CLASSES->{$interface};
+ push @{$interface_class->{constructor_vars}->{implemented_by}}, $_
+ for @{$implementors{$interface}};
+ }
+}
+
+#
+# Output a single template
+#
+sub output_template {
+ my ($tmplname, $outname, $params, $relaxed) = (@_);
+
+ $OPTIONS{TEMPLATEDIR} =~ s/(\S+)\/$/$1/;
+
+ $tmplname = $OPTIONS{TEMPLATEDIR} . "/$tmplname";
+ die "Template file '$tmplname' not found" unless -e $tmplname;
+
+ # Caching templates seems to improve performance quite a lot
+ if (!$TMPL_CACHE{$tmplname}){
+ $TMPL_CACHE{$tmplname} = new HTML::Template(
+ die_on_bad_params => !$relaxed,
+ filename => $tmplname);
+ }
+ my $tmpl = $TMPL_CACHE{$tmplname};
+ $tmpl->param($params);
+ $outname = sprintf('%s%s', $OPTIONS{OUTPUT}, $outname);
+ &print_file($outname, $tmpl->output);
+}
+
+
+#
+# Output data to a file
+#
+sub print_file {
+ my ($fname, $data) = @_;
+ open FILE, ">$fname"
+ or die "Couldn't open '$fname' to write: $!\n";
+ print FILE $data;
+ close FILE;
+}
+
+#
+# Output HTML documentation in the output directory
+#
+sub output_html {
+ &set_file_paths();
+ &output_class_templates();
+ &output_index_template();
+ &output_aux_templates();
+ &output_tree_template();
+}
+
+#
+# Output XMI in the output directory
+#
+sub output_xmi {
+ my $xmi = JSDoc::XMI->new(LOCATION);
+ &print_file("$OPTIONS{OUTPUT}/jsdoc.xmi", $xmi->output($CLASSES));
+}
+
+#
+# Output XML in the output directory
+#
+sub output_xml {
+ my $xml = JSDoc::XML->new(LOCATION);
+ &print_file("$OPTIONS{OUTPUT}/jsdoc.xml", $xml->output($CLASSES));
+}
+
+sub set_file_paths {
+ for my $classname (keys %$CLASSES){
+ my $class = $CLASSES->{$classname};
+ my $filepath = $classname;
+ $filepath =~ s/\./\//g;
+ $filepath = "$filepath.html";
+ my $dirpath = dirname($filepath);
+ $class->{filepath} = $filepath;
+ $class->{dirpath} = $dirpath;
+ my $fullpath = "$OPTIONS{OUTPUT}$dirpath";
+ mkpath($fullpath) unless -e $fullpath;
+ $class->{ispackage} = @{$class->{inner_classes}}
+ && not (@{$class->{instance_methods} || []}
+ or @{$class->{instance_fields} || []});
+ }
+}
+
+#
+# Gather information for each class and output its template
+#
+sub output_class_templates {
+
+ # Note the class name for later, including classes that aren't defined
+ # but are used for inheritance
+ my %seen;
+ @CLASSNAMES = sort { lc $a->{classname} cmp lc $b->{classname}}
+ grep { !$seen{$_->{classname}}++ }
+ (map {classname => $_,
+ classlink => link_to_class($_) } ,
+ grep { not defined $CLASSES->{$_}->{constructor_vars}->{private}
+ or $OPTIONS{PRIVATE} }
+ keys %$CLASSES),
+ (map { classname => $_ }, grep { !defined($$CLASSES{$_}) }
+ map { $_->{extends} } grep { defined($_->{extends}) }
+ values %$CLASSES);
+ die "Nothing to document, exiting\n" unless @CLASSNAMES;
+
+
+
+ @FILENAMES = map {filename => $_, mangledfilename => mangle($_)},
+ sort {lc($a) cmp lc($b)} grep {length $_} keys %FILE_OVERVIEWS;
+ for (my $i = 0; $i < @CLASSNAMES; $i++){
+
+ my $classname = $CLASSNAMES[$i]->{classname};
+ $CURRENT_CLASS = $classname;
+ next unless $$CLASSES{$classname};
+
+ # Template Parameters
+ my ($class, $subclasses, $class_summary, $constructor_params,
+ $next_class, $prev_class, $constructor_attrs,
+ $constructor_detail, $constructor_args);
+
+ $class= $$CLASSES{$classname};
+ next unless is_class_linkable($classname);
+ &add_to_index($class, $classname);
+
+ # Set up the constructor and class information
+ &resolve_synonyms($class->{constructor_vars});
+ &format_vars($class->{constructor_vars});
+ ($constructor_params, $constructor_args) =
+ &fetch_args($class->{constructor_vars},
+ $class->{constructor_args});
+ $constructor_attrs =
+ &format_method_attributes($class->{constructor_vars});
+ $constructor_detail =
+ &resolve_inner_links($class->{constructor_detail});
+ $class_summary = &format_class_attributes($class->{constructor_vars});
+ $class_summary = &resolve_inner_links($class_summary);
+
+ # Navbar information
+ $next_class = $i + 1 < @CLASSNAMES
+ ? link_to_class($CLASSNAMES[$i + 1]->{classname}, $classname)
+ : undef;
+ $prev_class = $i > 0
+ ? link_to_class($CLASSNAMES[$i - 1]->{classname}, $classname)
+ : undef;
+
+ my $superclass = $class->{extends} || '';
+
+ if ($superclass && $$CLASSES{$superclass}){
+ $superclass = make_link($superclass, $classname)
+ unless (!$OPTIONS{PRIVATE}
+ && $$CLASSES{$superclass}->{constructor_vars}->{private});
+ }
+
+ my $file_overview = $class->{constructor_vars}->{filename} ?
+ sprintf('overview-summary-%s.html',
+ mangle($class->{constructor_vars}->{filename}))
+ : '';
+
+ my @inner_classes = map {
+ classname => $_->{class_name},
+ classlink => link_to_class($_->{class_name}, $classname)
+ }, @{$class->{inner_classes} || []};
+
+ &output_template(MAIN_TMPL, $class->{filepath}, {
+ path_to_base => path_to_base($classname),
+ next_class => $next_class,
+ prev_class => $prev_class,
+ file_overview => $file_overview,
+ superclass => $superclass,
+ constructor_args => $constructor_args,
+ constructor_params => $constructor_params,
+ constructor_attrs => $constructor_attrs,
+ constructor_returns => $class->{constructor_vars}->{returns}[0],
+ class_summary => $class_summary,
+ class_attribs => $class->{constructor_vars}->{private} ?
+ '<private>' : '',
+ constructor_detail => $constructor_detail,
+ constructor_summary => &get_summary($constructor_detail),
+ classname => $classname,
+ hierarchy_meta => get_class_hierarchy_metadata($classname),
+ class_tree => &build_class_tree($classname, $CLASSES),
+ fields => &map_fields($class),
+ methods => &map_methods($class),
+ method_inheritance => &map_method_inheritance($class),
+ field_inheritance => &map_field_inheritance($class),
+ inner_classes => \@inner_classes,
+ project_name => $OPTIONS{PROJECT_NAME},
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME
+ }, 1);
+ }
+
+}
+
+#
+# Handle cleaning up / resolving inner links in FILE_OVERVIEWS
+#
+sub process_file_overviews {
+ for my $filename (map{$_->{filename}} @FILENAMES){
+ my $overview = $FILE_OVERVIEWS{$filename};
+ my $src = $overview->{src};
+ $overview->{src} = '';
+ format_vars($overview);
+ $overview =
+ resolve_inner_links($FILE_OVERVIEWS{$filename});
+ $overview->{src} = $src;
+ $FILE_OVERVIEWS{$filename} = $overview;
+ }
+}
+
+#
+# Output all the non-class template files
+#
+sub output_aux_templates(){
+
+ unless ($OPTIONS{LOGO} and -f $OPTIONS{LOGO} and -r $OPTIONS{LOGO}){
+ $OPTIONS{LOGO} and warn "Can't read $OPTIONS{LOGO}";
+ $OPTIONS{LOGO} = '';
+ }
+ $OPTIONS{LOGO} and copy $OPTIONS{LOGO}, $OPTIONS{OUTPUT};
+
+ &process_file_overviews;
+ $DEFAULT_CLASSNAME =
+ (grep {
+ is_class_linkable($_->{classname}) } @CLASSNAMES)[0]->{classname};
+
+ my $summary = &get_overall_summary;
+
+ &output_classes_frames_templates;
+ &output_multiple_files_templates
+ if (@FILENAMES > 1 || $OPTIONS{PACKAGENAMING});
+ &output_index_and_help_templates($summary);
+ &output_overview_summaries($summary);
+ &output_const_summary();
+ my $stylesheet = LOCATION . STYLESHEET;
+ if ($OPTIONS{TEMPLATEDIR} ne LOCATION){
+ $stylesheet = $OPTIONS{TEMPLATEDIR} . '/' . STYLESHEET;
+ die "Stylesheet '$stylesheet' not found" unless -e $stylesheet;
+ }
+ copy ($stylesheet, $OPTIONS{OUTPUT} . STYLESHEET);
+}
+
+sub get_overall_summary {
+ my $summary;
+ if ($OPTIONS{PROJECT_SUMMARY}){
+ if (-f $OPTIONS{PROJECT_SUMMARY} and
+ open SUMMARY, $OPTIONS{PROJECT_SUMMARY}){
+ local $/ = undef;
+ $summary = <SUMMARY>;
+ close SUMMARY;
+ } else {
+ warn "Can't open $OPTIONS{PROJECT_SUMMARY}";
+ }
+ } elsif (@FILENAMES == 1) {
+ # If we only have one file and it has an overview, use that overview
+ my $filename = $FILENAMES[0]->{filename};
+ if ($FILE_OVERVIEWS{$filename}->{fileoverview}){
+ $summary = $FILE_OVERVIEWS{$filename}->{fileoverview}[0];
+ $summary .= "<BR/><BR/>";
+
+ while (my ($name, $val) = each %{$FILE_OVERVIEWS{$filename}}){
+ $summary .= &{$FILE_ATTRS_MAP{$name}}($val)
+ if $FILE_ATTRS_MAP{$name};
+ }
+ }
+ }
+ $summary;
+}
+
+#
+# Output the main (default) page and the help template
+#
+sub output_index_and_help_templates {
+
+ my ($summary) = @_;
+ my $numpackages = scalar(grep {$_->{ispackage}} values %$CLASSES);
+
+ # Output the main index template
+ &output_template(INDEX_TMPL, 'index.html', {
+ DEFAULT_CLASSNAME => @FILENAMES > 1
+ ? 'overview-summary.html'
+ : link_to_class($DEFAULT_CLASSNAME),
+ multifile => (@FILENAMES > 1
+ || ($numpackages && $OPTIONS{PACKAGENAMING}))});
+
+ # Output the help document template
+ &output_template(HELP_TMPL, 'help-doc.html', {
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME,
+ project_name => $OPTIONS{PROJECT_NAME} });
+
+}
+
+#
+# Output the frames listing all the classes
+#
+sub output_classes_frames_templates {
+ my @classnames = grep { is_class_linkable($_->{classname}) } @CLASSNAMES;
+
+ if ($OPTIONS{PACKAGENAMING}){
+ @classnames = grep { !($CLASSES->{$_->{classname}}->{ispackage}) }
+ @classnames;
+ }
+ my $params = {
+ filename => 'All Classes',
+ fname_link => '<a href="overview-summary.html" ' .
+ 'target="classFrame">All Classes</a>',
+ CLASSNAMES => \@classnames };
+ if (@FILENAMES < 2 && !$OPTIONS{PACKAGENAMING}){
+ $params->{project_name} = $OPTIONS{PROJECT_NAME};
+ $params->{logo} = basename($OPTIONS{LOGO});
+ }
+ &output_template(ALLCLASSES_TMPL, 'allclasses-frame.html', $params);
+
+ &output_template(ALLCLASSES_NOFRAME_TMPL, 'allclasses-noframe.html', {
+ CLASSNAMES => \@classnames,
+ project_name => $OPTIONS{PROJECT_NAME},
+ logo => basename($OPTIONS{LOGO}) });
+
+}
+
+#
+# Output the overview summary templates
+#
+sub output_overview_summaries {
+ my ($summary) = @_;
+
+ my @overviews = map {
+ name => $_,
+ link => &mangle("overview-summary-$_.html"),
+ overview =>
+ get_summary(
+ $FILE_OVERVIEWS{$_}{fileoverview}[0] || ' ')
+ }, sort {lc($a) cmp lc($b)} keys(%FILE_OVERVIEWS);
+
+ &output_template(OVERVIEW_TMPL, 'overview-summary.html', {
+ generic => 1,
+ project_name => $OPTIONS{PROJECT_NAME},
+ project_title => $OPTIONS{PROJECT_NAME},
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME,
+ project_summary => $summary,
+ is_file_summary => 0,
+ overviews => \@overviews });
+
+ for my $filename (keys %FILE_OVERVIEWS){
+ my @classes = grep {
+ ($$CLASSES{$_}->{constructor_vars}->{filename} || '') eq $filename
+ } keys %$CLASSES;
+ my @class_overviews = sort { lc($a->{name}) cmp lc($b->{name}) }
+ map {
+ name => $_,
+ link => link_to_class($_),
+ overview => get_summary(
+ $CLASSES->{$_}->{constructor_vars}->{class}[0] || ' ')
+ }, grep { !$CLASSES->{$_}->{constructor_vars}->{private}
+ || $OPTIONS{PRIVATE} } @classes;
+ my %overview = %{$FILE_OVERVIEWS{$filename}};
+ my $src = delete $overview{src};
+ my $summary = $overview{fileoverview}[0] ||
+ "No overview generated for '$filename'";
+ $summary .= "<BR/><BR/>";
+ while (my ($name, $val) = each %overview){
+ $summary .= &{$FILE_ATTRS_MAP{$name}}($val)
+ if $FILE_ATTRS_MAP{$name};
+ }
+ my @methods =
+ map {
+ is_private => $_->{is_private},
+ method_summary => $_->{method_summary},
+ is_class_method => $_->{is_class_method},
+ method_anchor =>
+ sprintf('%s%s', $_->{is_class_method} ? '!s!' : '',
+ $_->{method_name}),
+ method_arguments=> $_->{method_arguments},
+ method_name => $_->{method_name},
+ type => $_->{type},
+ file_link => $OPTIONS{GLOBALS_NAME} . ".html"
+ }, @{&map_methods($$CLASSES{$OPTIONS{GLOBALS_NAME}}, $filename)};
+
+ &output_template(OVERVIEW_TMPL, "overview-summary-$filename.html", {
+ generic => 0,
+ sourcecode => $OPTIONS{NO_SRC} ? '' : &to_html($src),
+ project_name => $OPTIONS{PROJECT_NAME},
+ project_title => $filename,
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME,
+ project_summary => $summary,
+ is_file_summary => 1,
+ methods => \@methods,
+ overviews => \@class_overviews });
+ }
+
+}
+
+#
+# Output a summary page about the 'static constant' field values for all
+# classes
+#
+sub output_const_summary {
+ my @static_params;
+ for my $classname (sort { uc($a) cmp uc($b) } keys %$CLASSES){
+ my $class = $CLASSES->{$classname};
+ my @statics = grep { $_->{field_value} =~ /^(?:\d+)|(?:(['"]).*\1)$/}
+ grep { $_->{field_vars}->{final}} @{$class->{class_fields}};
+ if (@statics){
+ push @static_params, {
+ classname => $classname,
+ static_values => [map {
+ name => $_->{field_name},
+ value => $_->{field_value},
+ classname => $classname}, @statics] };
+ }
+ }
+ &output_template(CONSTANTS_TMPL, 'constant-values.html', {
+ project_name => $OPTIONS{PROJECT_NAME},
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME,
+ classnames => [map {name => $_->{classname}}, @static_params],
+ static_finals => \@static_params
+ }
+ ) if @static_params;
+}
+
+#
+# Method to handle outputting file overview template if
+# more than one sourcefile is being processed
+#
+sub output_multiple_files_templates {
+ my %params = (
+ logo => basename($OPTIONS{LOGO}),
+ project_name => $OPTIONS{PROJECT_NAME});
+
+ if ($OPTIONS{PACKAGENAMING}){
+ my @packagenames = sort { $a->{filename} cmp $b->{filename} }
+ map {
+ filelink => "overview-$_->{classname}.html",
+ filename => $_->{classname} }, grep { $_->{ispackage} }
+ values %$CLASSES;
+ $params{filenames} = \@packagenames;
+ $params{heading} = "Packages";
+ } else {
+ my @filenames = map {
+ filelink => "overview-$_->{mangledfilename}.html",
+ filename => $_->{filename} }, @FILENAMES;
+ $params{filenames} = \@filenames;
+ $params{heading} = "Files";
+ }
+
+ &output_template(OVERVIEW_FRAME_TMPL, 'overview-frame.html', \%params);
+
+ if (!$OPTIONS{PACKAGENAMING}){
+
+ for my $fname (map { $_->{filename}} @FILENAMES){
+ my @classes = grep {
+ ($$CLASSES{$_}->{constructor_vars}->{filename} || '')
+ eq $fname
+ } keys %$CLASSES;
+
+ #methods under GLOBAL (detached) class
+ my @methods;
+ for (my $i = 0; $i < @CLASSNAMES; $i++){
+ if($CLASSNAMES[$i]->{classname} eq $OPTIONS{GLOBALS_NAME}){
+ my $class = $$CLASSES{$CLASSNAMES[$i]->{classname}};
+ for my $method (
+ sort {lc $a->{mapped_name}
+ cmp lc $b->{mapped_name} }
+ @{$class->{class_methods}}){
+ if(defined($fname)
+ && $fname eq $method->{vars}->{filename}){
+ $method->{filename} = $fname;
+ push(@methods, $method);
+ }
+ }
+ last;
+ }
+ }
+
+ &output_template(ALLCLASSES_TMPL,
+ sprintf('overview-%s.html', $fname), {
+ filename => $fname,
+ fname_link => $FILE_OVERVIEWS{$fname}
+ ? sprintf(
+ '<a href="overview-summary-%s.html"
+ target="classFrame">%s</a>',
+ mangle($fname), $fname)
+ : $fname,
+ CLASSNAMES => [map {
+ classname => $_,
+ classlink => link_to_class($_)
+ },
+ grep { !$$CLASSES{$_}->{constructor_vars}->{private}
+ || $OPTIONS{PRIVATE} } sort @classes] });
+ }
+ }
+
+ if ($OPTIONS{PACKAGENAMING}){
+ my @packages = grep { $_->{ispackage} } values %$CLASSES;
+ for my $package (@packages){
+ my $name = $package->{classname};
+ my %params = (
+ filename => $name,
+ fname_link => sprintf(
+ '<a href="%s" target="classFrame">%s</a>',
+ link_to_class($name), $name));
+ my @inner_classes = sort {
+ $a->{classname} cmp $b->{classname}} map {
+ classname => $_,
+ classlink => link_to_class($_) },
+ map { $_->{class_name} } @{$package->{inner_classes}};
+ $params{CLASSNAMES} = \@inner_classes;
+ output_template(ALLCLASSES_TMPL, "overview-$name.html", \%params);
+
+ }
+ }
+}
+
+#
+# Mangle a file path so that it can be used as a filename
+#
+sub mangle {
+ my $input = shift;
+ local $_ = $input;
+ tr{/\\}{_};
+ die if $input ne $_;
+ $_;
+}
+
+#
+# Build the tree representation of the inheritance
+# PARAM: Name of the class
+#
+sub build_class_tree {
+ my $classname = shift;
+ my $class = $$CLASSES{$classname};
+ my $tree = "";
+ my @family;
+ push @family, $classname;
+ while ($class->{extends} and $class->{extends} ne ""){
+ my $base = $class->{extends};
+ if ($$CLASSES{$base} and is_class_linkable($base)){
+ $base = sprintf("<a href='%s'>$base</a>",
+ link_to_class($base, $classname))
+ unless (!$OPTIONS{PRIVATE}
+ && $$CLASSES{$base}->{constructor_vars}->{private});
+ } elsif ($class->{constructor_vars}->{base}){
+ if (my ($bcname, $url) =
+ $class->{constructor_vars}->{base}->[0]
+ =~ /^(\S+)\s(\S.*)$/){
+ $base = "<a href='$url'>$base</a>";
+ }
+ }
+ push @family, $base;
+ $class = $$CLASSES{$class->{extends}};
+ }
+ push @family, "Object";
+ my $indent = 3;
+ $tree = (pop @family) . "\n";
+ my $name = $_;
+ while ($name = pop (@family)){
+ my $instr = " " x $indent;
+ $tree .= sprintf "%s|\n%s+--%s%s%s\n", $instr, $instr,
+ $name eq $classname ? "<b>" : "", $name,
+ $name eq $classname ? "</b>" : "";
+ $indent += 6;
+ }
+ $tree;
+}
+
+#
+# Shown if no commandline args are given
+#
+sub show_usage(){
+ print qq{Usage: jsdoc [OPTIONS] <js sourcefiles and/or directories>+
+
+ -h | --help Show this message and exit
+ -r | --recursive Recurse through given directories
+ -p | --private Show private methods and fields
+ -d | --directory Specify output directory (defaults to js_docs_out)
+ -q | --quiet Suppress normal output
+
+ --page-footer Specify (html) footer string that will be added to
+ all docs
+ --project-name Specify project name for that will be added to docs
+ --logo Specify a path to a logo to be used in the docs
+ --project-summary Specify a path to a text file that contains an
+ overview summary of the project
+
+ --no-sources Don't include the source code view
+
+ --extensions Provide a comma-separated list of file extensions
+ to be considered as JavaScript source files
+
+ --nested-file-naming Use package-style naming (i.e. keep directory
+ names in the file path). This is useful if you
+ have multiple files with the same name, but in
+ different directories. This option is only useful
+ if --recursive is also used.
+
+ --globals-name Specify a 'class name' under which all unattached
+ methods will be classified. The defaults to GLOBALS
+
+ --format Set the output format. The options are html, xml
+ and xmi, defaulting to html. The others are currently
+ alpha software.
+
+ --template-dir Provide another directory containing HTML templates
+
+ --no-lexical-privates Ignore "private" variables and functions that are
+ lexically defined within constructors
+
+ --package-naming Use packages, with a package being defined as a class
+ that only contains nested classes and possibly
+ static members.
+
+ \n};
+
+}
+
+#
+# Take all the command line args as filenames and add them to @SOURCESFILES
+#
+sub load_sources(){
+ my (@filenames, @sources);
+ my $ext_re = sprintf('%s',
+ join '|', split /\s*,\s*/, $OPTIONS{EXTENSIONS});
+ for my $arg (@ARGV){
+ if (-d $arg) {
+ $arg =~ s/(.*[^\/])$/$1\//;
+ find( {
+ wanted => sub {
+ push @filenames, {
+ name => $_,
+ relname => $OPTIONS{NESTEDFILENAMING}
+ ? substr($_, length($arg))
+ : (fileparse($_))[0]
+ } if ((-f and -r and /.+\.$ext_re$/oi) &&
+ (/^\Q$arg\E[^\/]+$/ || $OPTIONS{RECURSIVE}))
+ },
+ no_chdir => 1 }, $arg);
+ } elsif (-f $arg){
+ my $relname = (fileparse($arg))[0];
+ push @filenames, { name => $arg, relname => $relname };
+ }
+ }
+ for (@filenames){
+ &_log(sprintf 'Loading sources from %s', $_->{name});
+ open SRC, '<', $_->{name}
+ or (warn sprintf("Can't open %s, skipping: $!\n", $_->{name})
+ and next);
+ local $/ = undef;
+ push @sources, $_->{relname};
+ push @sources, \<SRC>;
+ close SRC;
+ }
+ @sources;
+}
+
+#
+# Once all sources have been parsed, finds all subclasses
+# of $classname
+#
+sub find_subclasses {
+ my ($classname) = @_;
+ my @subclasses;
+ for my $class (keys %$CLASSES){
+ my $subclassname = $$CLASSES{$class}->{extends};
+ if ($$CLASSES{$class}->{extends} and
+ $$CLASSES{$class}->{extends} eq $classname){
+ push @subclasses, $class;
+ }
+ }
+ \@subclasses;
+}
+
+#
+# Make a summary of a description, cutting it off either at the first
+# double newline or the first period followed by whitespace.
+# PARAM: $description
+#
+sub get_summary {
+ my ($description) = @_;
+ my $summary;
+ if ($description){
+ ($summary) = $description =~ /^(.*?(?:[?!.](?=\s)|\n\n)).*$/gs
+ or $summary = $description;
+ } else {
+ $summary = "";
+ }
+ $summary;
+}
+
+
+#
+# Set up all the instance and class methods for one template
+# PARAM: A reference to a class
+# PARAM: Optional filename, only maps methods for that file (used for GLOBAL)
+#
+sub map_methods{
+ my ($class, $fname) = @_;
+ my @methods;
+ for my $mtype (qw(instance_methods class_methods)){
+ next unless $class->{$mtype};
+
+ for my $method (
+ sort {lc $a->{mapped_name} cmp lc $b->{mapped_name} }
+ @{$class->{$mtype}}){
+ next if $fname && $fname ne $method->{vars}->{filename};
+ &resolve_synonyms($method->{vars});
+ next if (!$OPTIONS{PRIVATE} && $method->{vars}->{private});
+
+ $method->{vars}->{returns}[0] =
+ $method->{vars}->{returns}[0] || $method->{vars}->{return};
+
+ my ($args, $arglist) =
+ &fetch_args($method->{vars}, $method->{argument_list});
+ $args = [map { &format_vars($_); $_ } @{$args}];
+
+ &format_vars($method->{vars});
+ my $desc = &resolve_inner_links($method->{description});
+ my $type = &map_return_type($method);
+ my $ret = $method->{vars}->{returns}[0];
+ my $attrs = &format_method_attributes($method->{vars});
+
+ push @methods, {
+ method_description => $desc,
+ method_summary => &get_summary($desc),
+ method_name => $method->{mapped_name},
+ method_arguments => $arglist,
+ method_params => $args,
+ method_returns => $ret,
+ is_class_method => $mtype eq 'class_methods',
+ is_private => defined($method->{vars}->{private}),
+ attributes => $attrs,
+ type => $type };
+ }
+ }
+ return \@methods;
+}
+
+#
+# Map a function return type
+#
+sub map_return_type {
+ my ($method) = @_;
+ #return 'Object' unless $method->{vars}->{type}[0];
+ my $name = 'Object';
+ my $link = '';
+ if (defined($method->{vars}->{type})){
+ $name = $method->{vars}->{type}[0];
+ } elsif (defined($method->{vars}->{returns}[0])){
+ if ($method->{vars}->{returns}[0] =~ s/\s*\{(\S+)(?:\s+([^}]+))?\}//){
+ $name = $1;
+ $link = $2;
+ }
+ $method->{vars}->{type} = [$name];
+ }
+ $name =~ s/^\s*(\S.*?)\s*$/$1/;
+ if ($$CLASSES{$name} || $link){
+ $link ||= link_to_class($name, $CURRENT_CLASS);
+ return qq|<a href="$link">$name</a>|;
+ }
+ $name;
+}
+
+#
+# Set up all the instance and class methods for one template
+# PARAM: A reference to a class
+#
+sub map_fields {
+ my $class = shift;
+ my @fields;
+ # Set up the instance fields
+ for my $type (qw(instance_fields class_fields)){
+ next unless $class->{$type};
+ for (sort {lc $a->{field_name} cmp lc $b->{field_name} }
+ @{$class->{$type}}){
+
+ &resolve_synonyms($_->{field_vars});
+ next if (!$OPTIONS{PRIVATE} && $_->{field_vars}->{private});
+ my $description = &resolve_inner_links($_->{field_description});
+ my $const_link = ($_->{field_vars}->{final} &&
+ ($_->{field_value} =~ /^\-?\d+(\.\d+)?$/
+ || $_->{field_value} =~ /^(["']).*\1$/))
+ ? $class->{classname} : '';
+ push @fields, {
+ field_name => $_->{field_name},
+ field_description => $description,
+ field_summary => &get_summary($description),
+ is_final => defined($_->{field_vars}->{final}),
+ is_private => defined($_->{field_vars}->{private}),
+ is_class_field => $type eq 'class_fields',
+ type => &map_field_type($_),
+ const_link => $const_link};
+ }
+ }
+ \@fields;
+}
+
+#
+# Map a field type
+#
+sub map_field_type {
+ my ($field) = @_;
+ return 'Object' unless $field->{field_vars}->{type}[0];
+ my $name = $field->{field_vars}->{type}[0];
+ $name =~ s/^\s*(\S.*?)\s*$/$1/;
+ return sprintf('<a href="%s">%s</a>',
+ link_to_class($name, $CURRENT_CLASS), $name)
+ if $$CLASSES{$name};
+ $name;
+}
+
+#
+# Map all the inherited methods to a template parameter
+# PARAM: A reference to a class
+#
+sub map_method_inheritance {
+ my $class = shift;
+ my @method_inheritance;
+ # Set up the inherited methods
+ if ($class->{inherits}){
+ my $superclassname = $class->{extends};
+ my $superclass = $$CLASSES{$superclassname};
+ while ($superclass){
+ if (!$superclass->{constructor_vars}->{private}
+ || $OPTIONS{PRIVATE}){
+ my $methods =
+ $class->{inherits}->{$superclassname}->{instance_methods};
+ push @method_inheritance, {
+ superclass_name => $superclassname,
+ superclass_link => link_to_class(
+ $superclassname,
+ $class->{classname}),
+ inherited_methods => join(', ',
+ map(sprintf("<a href='%s#%s'>%s</a>",
+ link_to_class(
+ $superclassname, $class->{classname}),
+ $_, $_),
+ &filter_private_methods(
+ $methods, $superclassname)))}
+ if ($methods and @$methods);
+ }
+ $superclassname = $superclass->{extends};
+ $superclass = $superclassname ? $$CLASSES{$superclassname} : undef;
+ }
+ }
+ \@method_inheritance;
+}
+
+#
+# Map all the inherited fields to a template parameter
+# PARAM: A reference to a class
+#
+sub map_field_inheritance {
+ my $class = shift;
+ my @field_inheritance;
+ # Set up the inherited fields
+ if ($class->{inherits}){
+ my $superclassname = $class->{extends};
+ my $superclass = $$CLASSES{$superclassname};
+ while ($superclass){
+ if (!$superclass->{constructor_vars}->{private}
+ || $OPTIONS{PRIVATE}){
+ my $fields =
+ $class->{inherits}->{$superclassname}->{instance_fields};
+ push @field_inheritance, {
+ superclass_name => $superclassname,
+ superclass_link => link_to_class(
+ $superclassname,
+ $class->{classname}),
+ inherited_fields => join(', ',
+ map(sprintf("<a href='%s#%s'>%s</a>",
+ link_to_class(
+ $superclassname, $class->{classname}),
+ $_, $_),
+ &filter_private_fields($fields, $superclassname)))}
+ if ($fields and @$fields);
+ }
+ $superclassname = $superclass->{extends};
+ $superclass = $superclassname ? $$CLASSES{$superclassname} : undef;
+ }
+ }
+ \@field_inheritance;
+}
+
+#
+# Filter out private inherited methods
+#
+sub filter_private_methods {
+ my ($methods, $superclassname) = @_;
+ my @visible_methods;
+ for my $method(@$methods){
+ for my $super_method
+ (@{$$CLASSES{$superclassname}->{instance_methods}}){
+ push @visible_methods, $method
+ if $method eq $super_method->{mapped_name} and
+ (!$super_method->{vars}->{private} || $OPTIONS{PRIVATE});
+ }
+ }
+ @visible_methods;
+}
+
+#
+# Filter out private inherited fields
+#
+sub filter_private_fields {
+ my ($fields, $superclassname) = @_;
+ my @visible_fields;
+ for my $field (@$fields){
+ for my $super_field(@{$$CLASSES{$superclassname}->{instance_fields}}){
+ push @visible_fields, $field
+ if $field eq $super_field->{field_name} and
+ (!$super_field->{field_vars}->{private}
+ || $OPTIONS{PRIVATE});
+ }
+ }
+ @visible_fields;
+}
+
+
+#
+# Builds up the listing of subclasses, implemented interfaces, and
+# who implements this interface
+#
+sub get_class_hierarchy_metadata {
+ my ($classname) = @_;
+ my $class = $CLASSES->{$classname};
+ my @meta;
+
+ # Find all the direct subclasses
+ my $subclasses = join(', ',
+ map { make_link($_, $classname) } @{&find_subclasses($classname)});
+
+ if ($subclasses){
+ push @meta, { title => 'Direct Known Subclasses',
+ data => $subclasses };
+ }
+
+ my $implemented_interfaces = join(', ',
+ map { make_link($_, $classname) }
+ @{$class->{constructor_vars}->{implements} || []});
+
+ if ($implemented_interfaces){
+ push @meta, { title => 'All Implemented Interfaces',
+ data => $implemented_interfaces };
+ }
+
+ my $implemented_by = join(', ',
+ map { make_link($_, $classname) }
+ @{$class->{constructor_vars}->{implemented_by} || []});
+
+ if ($implemented_by){
+ push @meta, { title => 'All Known Implementing Classes',
+ data => $implemented_by };
+ }
+
+ return \@meta;
+}
+
+
+#
+# Adds a class's information to the global INDEX list
+#
+sub add_to_index {
+ my ($class, $classname) = @_;
+ push @INDEX, {
+ name => $classname,
+ class => $classname,
+ classlink => link_to_class($classname),
+ type => '', linkname => ''
+ };
+
+ if (!$class->{constructor_args}){
+ $class->{constructor_args} = '';
+ } else {
+ push @INDEX, {
+ name => "$classname$class->{constructor_args}",
+ class => $classname,
+ classlink => link_to_class($classname),
+ type => 'Constructor in ',
+ linkname => 'constructor_detail' };
+ }
+ for my $mtype (qw(class_methods instance_methods)){
+ my $type = sprintf('%s method in ',
+ $mtype eq 'class_methods' ? 'Class' : 'Instance');
+ push @INDEX, {
+ name => "$_->{mapped_name}$_->{argument_list}",
+ class => $classname,
+ classlink => link_to_class($classname),
+ type => $type,
+ linkname => $_->{mapped_name}}
+ for grep {
+ not($_->{vars}->{private} and not $OPTIONS{PRIVATE})
+ } @{$class->{$mtype}};
+
+ }
+ for my $ftype (qw(class_fields instance_fields)){
+ my $type = sprintf('%s field in ',
+ $ftype eq 'class_fields' ? 'Class' : 'Instance');
+ push @INDEX, {
+ name => $_->{field_name},
+ class => $classname,
+ classlink => link_to_class($classname),
+ type => $type,
+ linkname => $_->{field_name}}
+ for grep {
+ not($_->{field_vars}->{private} and not $OPTIONS{PRIVATE})
+ } @{$class->{$ftype}};
+ }
+}
+
+#
+# Outputs the index page
+#
+sub output_index_template {
+ @INDEX = sort {lc $a->{name} cmp lc $b->{name}} @INDEX;
+ my %letters;
+ for my $item (@INDEX){
+ my $letter = uc(substr($item->{name}, 0, 1));
+ $letter = uc(substr($item->{class}, 0, 1)) if $letter eq '';
+ push @{$letters{$letter}}, $item;
+ }
+
+ my $letter_list = [map {letter_name => $_},
+ sort {lc $a cmp lc $b} keys %letters];
+ &output_template(INDEX_ALL_TMPL, 'index-all.html', {
+ letters => $letter_list,
+ project_name => $OPTIONS{PROJECT_NAME},
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME,
+ index_list => [map {
+ letter => $_->{letter_name},
+ value => $letters{$_->{letter_name}}
+ }, @{$letter_list}] });
+}
+
+
+sub is_class_linkable {
+ my ($cname) = @_;
+ my $ret_val = defined($$CLASSES{$cname}) && $$CLASSES{$cname}->{filepath};
+ $ret_val ||= 0;
+ return $ret_val;
+}
+
+#
+# Recursively builds up the overview tree
+#
+sub build_tree {
+ my $parentclassname = shift || '';
+ my $ret = "";
+ for my $cname (map {$_->{classname}} @CLASSNAMES) {
+ next if $cname eq $OPTIONS{GLOBALS_NAME};
+ my $class = $$CLASSES{$cname};
+ my $parent = $class->{extends} || '-';
+ if ((!$parentclassname && $parent eq '-')
+ or ($parent eq $parentclassname)) {
+ $ret .= is_class_linkable($cname) ? sprintf(qq{
+ <LI TYPE="circle"><B>%s</B></LI> },
+ make_link($cname))
+ : qq{
+ <LI TYPE="circle">
+ $cname</LI>
+ };
+ my $childrentree .= &build_tree($cname);
+ $ret = "$ret$childrentree" if $childrentree;
+ }
+ }
+ $ret = "<UL>$ret</UL>" unless not $ret;
+ if ($parentclassname eq ''){
+ $ret = qq{<UL><LI TYPE="circle">Object</LI>$ret</UL>};
+ }
+ $ret;
+}
+
+#
+# Outputs the overview tree
+#
+sub output_tree_template {
+ my $tree = &build_tree();
+ &output_template(TREE_TMPL, 'overview-tree.html', {
+ classtrees => $tree,
+ project_name => $OPTIONS{PROJECT_NAME},
+ page_footer => $OPTIONS{PAGE_FOOTER},
+ ctime => $TIME }, 1);
+}
+
+#
+# Formats additional non-standard attributes for methods according to user
+# configuration
+#
+sub format_method_attributes {
+ my ($attrs) = shift;
+ my $attributes = '';
+ while (my ($name, $val) = each %{$attrs}) {
+ $attributes .= &{$METHOD_ATTRS_MAP{$name}}($val)
+ if $METHOD_ATTRS_MAP{$name};
+ }
+ $attributes;
+}
+
+#
+# Formats additional non-standard attributes for classes according to user
+# configuration
+#
+sub format_class_attributes {
+ my ($attrs) = shift;
+ my $attributes;
+ if ($attrs->{class} && @{ $attrs->{class} }){
+ $attributes = sprintf('<BR/>%s<BR/>', $attrs->{class}[0] || '')
+ }
+ while (my ($name, $val) = each %{$attrs}) {
+ $attributes .= &{$CLASS_ATTRS_MAP{$name}}($val)
+ if $CLASS_ATTRS_MAP{$name};
+ }
+ $attributes;
+}
+
+#
+# Parses the command line options
+#
+sub parse_cmdline {
+ $OPTIONS{OUTPUT} = DEFAULT_DEST_DIR;
+ $OPTIONS{PROJECT_NAME} = '';
+ $OPTIONS{COPYRIGHT} = '';
+ $OPTIONS{PROJECT_SUMMARY} = '';
+ $OPTIONS{LOGO} = '';
+ $OPTIONS{GLOBALS_NAME} = 'GLOBALS';
+ $OPTIONS{FORMAT} = 'html';
+ $OPTIONS{EXTENSIONS} = 'js';
+ $OPTIONS{TEMPLATEDIR} = LOCATION;
+ GetOptions(
+ 'private|p' => \$OPTIONS{PRIVATE},
+ 'directory|d=s' => \$OPTIONS{OUTPUT},
+ 'help|h' => \$OPTIONS{HELP},
+ 'recursive|r' => \$OPTIONS{RECURSIVE},
+ 'page-footer=s' => \$OPTIONS{PAGE_FOOTER},
+ 'project-name=s' => \$OPTIONS{PROJECT_NAME},
+ 'project-summary=s' => \$OPTIONS{PROJECT_SUMMARY},
+ 'logo=s' => \$OPTIONS{LOGO},
+ 'globals-name=s' => \$OPTIONS{GLOBALS_NAME},
+ 'quiet|q' => \$OPTIONS{QUIET},
+ 'no-sources' => \$OPTIONS{NO_SRC},
+ 'nested-file-naming' => \$OPTIONS{NESTEDFILENAMING},
+ 'format=s' => \$OPTIONS{FORMAT},
+ 'extensions=s' => \$OPTIONS{EXTENSIONS},
+ 'no-lexical-privates' => \$OPTIONS{NO_LEXICAL_PRIVATES},
+ 'template-dir=s' => \$OPTIONS{TEMPLATEDIR},
+ 'package-naming' => \$OPTIONS{PACKAGENAMING});
+ $OPTIONS{OUTPUT} =~ s/([^\/])$/$1\//;
+}
+
+#
+# Resolves links for {@link } items
+#
+sub resolve_inner_links {
+ my $doc = shift;
+ $doc =~ s{\{\@link\s+([^\}]+)\}}{&format_link($1)}eg if $doc;
+ return $doc;
+}
+
+sub link_to_class {
+ my ($toclass, $fromclass) = @_;
+ $fromclass ||= '';
+ $toclass = strip($toclass);
+ $fromclass = strip($fromclass);
+ $toclass = $CLASSES->{$toclass}->{filepath};
+ $fromclass = $CLASSES->{$fromclass}->{filepath} if $fromclass;
+ my $fromslashes = ($fromclass =~ tr/\///);
+ my $link = ('../' x $fromslashes);
+ $link .= $toclass if $toclass;
+ return $link;
+}
+
+sub make_link {
+ my ($toclass, $fromclass) = @_;
+ if (is_class_linkable($toclass)){
+ my $link = link_to_class($toclass, $fromclass);
+ return "<a href='$link'>$toclass</a>";
+ }
+ return $toclass;
+}
+
+sub path_to_base {
+ my ($fromclass) = @_;
+ $fromclass = $CLASSES->{$fromclass}->{filepath};
+ my $fromslashes = ($fromclass =~ tr/\///);
+ my $path = '../' x $fromslashes;
+ return $path;
+}
+
+
+#
+# Formats a {@link } item
+#
+sub format_link {
+ my ($link) = shift;
+ die unless $CURRENT_CLASS;
+ $link = strip($link);
+ $link =~ s/<[^>]*>//g;
+ my ($class, $method, $label, $url);
+ my $class_re = qr/\w+(?:\.\w+)*/;
+ unless ((($class, $method, $label) =
+ $link =~ /^($class_re)?#($class_re)\s*(.*)$/)
+ or (($class, $label) = $link =~ /^($class_re)(?:\s+(.*))?$/)){
+ if (($url, $label) = $link =~ /^(https?:\/\/\S+)\s+(.*?)\s*$/){
+ return "<a href='$url'>$label</a>";
+ } else {
+ return $link;
+ }
+ }
+ if ($class){
+ unless ($$CLASSES{$class}){
+ warn "\@link can't find reference $class\n";
+ return $link;
+ }
+ }
+ my $classlink = ($class && defined($$CLASSES{$class}))
+ ? link_to_class($class, $CURRENT_CLASS) : '';
+ if (!$method){
+ $label = $class unless $label;
+ qq{<a href="$classlink#">$label</a>};
+ } else {
+ my $clss = $CLASSES->{$class || $CURRENT_CLASS};
+ my @methods = (@{$clss->{instance_methods}},
+ @{$clss->{class_methods}});
+ my @fields = (@{$clss->{instance_fields}}, @{$clss->{class_fields}});
+ my @statics = (@{$clss->{class_methods}}, @{$clss->{class_fields}});
+ my $ismethod = grep { $_->{mapped_name} eq $method } @methods;
+ my $isfield = grep { $_->{field_name} eq $method } @fields
+ unless $ismethod;
+ my $isstatic = grep {
+ ($_->{field_name} || $_->{mapped_name}) eq $method } @statics;
+ if ($class){
+ $label = "$class.$method" . ($ismethod ? '()' : '') unless $label;
+ if ($ismethod or $isfield){
+ $method = ($isstatic ? "!s!" : "") . $method;
+ return qq{<a href="$classlink#$method">$label</a>};
+ } else {
+ warn "\@link can't find reference $method in $class\n";
+ return $link;
+ }
+ } else {
+ $label = $method . ($ismethod ? "()" : "") unless $label;
+ $method = ($isstatic ? "!s!" : "") . $method;
+ return qq{<a href="#$method">$label</a>};
+ }
+ }
+}
+
+
+#
+# Initializes the customizable maps for @attributes
+#
+sub initialize_param_maps {
+ %CLASS_ATTRS_MAP = (
+ author =>
+ sub {
+ '<B>Author:</B> ' .
+ join(', ', @{$_[0]}) . "<BR/>"
+ },
+ deprecated =>
+ sub {
+ '<B>Deprecated</B> <I>' . ($_[0] ? $_[0]->[0] : '') .
+ "</I><BR/><BR/>";
+ },
+ see =>
+ sub {
+ '<B>See:</B><UL>- ' .
+ join('<BR/>- ', map {&format_link($_)} @{$_[0]}) . "</UL>"
+ },
+ version =>
+ sub {
+ '<B>Version: </B>' .
+ join(', ', @{$_[0]}) . '<BR/><BR/>'
+ },
+ requires =>
+ sub {
+ '<B>Requires:</B><UL>- ' .
+ join('<BR/>- ', map {&format_link($_)} @{$_[0]}) . "</UL>"
+ },
+ filename =>
+ sub {
+ sprintf '<I>Defined in %s</I><BR/><BR/>',
+ sprintf("<a href='%soverview-summary-%s.html'>%s</a>",
+ path_to_base($CURRENT_CLASS),mangle($_[0]), $_[0]);
+ },
+ overviewfile =>
+ sub {
+ my ($content, $fh) = "";
+ my $fname = $_[0][0] or return '';
+ unless(open $fh, "$fname"){
+ warn "Can't open overview file '$fname' : $!\n";
+ return '';
+ }
+ { local $/ = undef; $content .= <$fh> }
+ close $fh or warn "Couldn't close overview file '$fname'\n";
+ # Crude manner to strip out extra HTML
+ $content =~ s/<body>(.*)<\/body>/$1/si;
+ "$content<br/>";
+ }
+ );
+
+ %METHOD_ATTRS_MAP = (
+ throws =>
+ sub {
+ "<B>Throws:</B><UL>- " .
+ join("<BR>- ", @{$_[0]}) . "</UL>"
+ },
+ );
+ $METHOD_ATTRS_MAP{exception} = $METHOD_ATTRS_MAP{throws};
+ $METHOD_ATTRS_MAP{$_} = $CLASS_ATTRS_MAP{$_} for qw(author version
+ deprecated see requires);
+ $FILE_ATTRS_MAP{$_} = $CLASS_ATTRS_MAP{$_} for qw(author version
+ see requires);
+}
+
+#
+# Parse the @param or @argument values into name/value pairs and
+# return the list of them
+#
+sub fetch_args {
+ my ($vars, $arg_list) = @_;
+ return ([], $arg_list) unless $vars and $arg_list;
+ my (@args, %used);
+ for my $arg (split /\W+(?<!\$)/, ($arg_list =~ /\(([^)]*)/)[0]){
+ for (@{$vars->{param}}){
+ my ($type, $link, $name, $value) =
+ /(?:
+ \{\s*
+ (\S+) # type name
+ (?:\s+(\S+)\s*)? # optional link
+ \})?
+ \s*
+ (\$?\w+) # parameter name
+ (.*) # description
+ /x;
+ next unless $name eq $arg;
+ $used{$name} = 1;
+ $type ||= '';
+ if ($$CLASSES{$type} || $link){
+ $link ||= $type;
+ if ($CLASSES->{$link}){
+ $type = sprintf('<a href="%s">%s</a>',
+ link_to_class($link, $CURRENT_CLASS), $type);
+ } else {
+ $type = sprintf('<a href="%s">%s</a>',
+ "$link.html", $type);
+ }
+ }
+ my $type_regex = qr{\Q$arg\E\b};
+ $arg_list =~ s/(?<!gt; )($type_regex)/<$type> $1/
+ if $type;
+ push @args, { varname => $name, vardescrip => $value};
+ }
+ }
+ for (@{$vars->{param}}){
+ my ($type, $link, $name, $value)
+ = /(?:\{\s*(\S+)(?:\s+(\S+)\s*)?\})?\s*(\$?\w+)(.*)/;
+ next if $used{$name};
+ push @args, { varname => $name, vardescrip => $value };
+ }
+ return (\@args, $arg_list);
+}
+
+sub resolve_synonyms {
+ my ($item) = @_;
+ $item->{param} = $item->{param} || $item->{argument};
+ $item->{returns} = $item->{return} || $item->{returns};
+ $item->{final} = $item->{final} || $item->{const};
+}
+
+#
+# Log a message to STDOUT if the --quiet switch is not used
+#
+sub _log {
+ print $_[0], "\n" unless $OPTIONS{QUIET};
+}
+
+#
+# Takes a vars hash and resolves {@link}s within it
+#
+sub format_vars {
+ my ($vars) = @_;
+ for my $key (keys %$vars){
+ if (ref($vars->{$key}) eq 'ARRAY'){
+ for (0..$#{$vars->{$key}}){
+ $vars->{$key}->[$_] = &resolve_inner_links($vars->{$key}->[$_]);
+ }
+ } else {
+ $vars->{$key} = &resolve_inner_links($vars->{$key});
+ }
+ }
+}
+
+#
+# Util methods
+#
+
+sub strip {
+ my ($value) = @_;
+ return $value unless $value;
+ $value =~ s/^\s*(.*?)\s*$/$1/;
+ return $value;
+}
+
+sub has_method {
+ my ($classname, $mname) = @_;
+ my $class = $CLASSES->{$classname};
+ for my $method (@{$class->{instance_methods}}){
+ if ($method->{mapped_name} eq $mname){
+ return 1;
+ }
+ }
+ return 0;
+}
+
Property changes on: trunk/build/JSDoc/jsdoc.pl
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/build/JSDoc/main.tmpl
===================================================================
--- trunk/build/JSDoc/main.tmpl (rev 0)
+++ trunk/build/JSDoc/main.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,448 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<TITLE>
+<TMPL_VAR name="classname">
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="<TMPL_VAR NAME="path_to_base">stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="<TMPL_VAR name="classname">";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <TMPL_IF NAME="file_overview"> <A HREF="<TMPL_VAR NAME="path_to_base"><TMPL_VAR NAME="file_overview">"></TMPL_IF><FONT CLASS="NavBarFont1"><TMPL_IF NAME="file_overview"><B></TMPL_IF>File<TMPL_IF NAME="file_overview"></B></TMPL_IF></FONT><TMPL_IF NAME="file_overview"></A></TMPL_IF> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"--> <!--A HREF="deprecated-list.html"--><!--FONT CLASS="NavBarFont1">Deprecated</FONT--><!--/A--><!-- </TD-->
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">index-all.html"--><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <TMPL_IF NAME="prev_class"><A HREF="<TMPL_VAR NAME="prev_class">"></TMPL_IF><B>PREV CLASS</B><TMPL_IF NAME="prev_class"></A></TMPL_IF><!--
+ NEXT CLASS
+-->
+ <TMPL_IF NAME="next_class"><A HREF="<TMPL_VAR NAME="next_class">"></TMPL_IF><B>NEXT CLASS</B><TMPL_IF NAME="next_class"></A></TMPL_IF></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="<TMPL_VAR NAME="path_to_base">index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="<TMPL_VAR NAME="path_to_base">allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="<TMPL_VAR NAME="path_to_base">allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY: <A HREF="#field_summary">FIELD</A> | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL: <A HREF="#field_detail">FIELD</A> | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+<HR>
+
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>Class <TMPL_VAR NAME="classname"></H2>
+<PRE><TMPL_VAR name="class_tree"></PRE>
+<TMPL_IF NAME="hierarchy_meta">
+ <TMPL_LOOP NAME="hierarchy_meta">
+ <DL>
+ <DT>
+ <B><TMPL_VAR NAME="title">:</B>
+ <DD>
+ <TMPL_VAR NAME="data">
+ </DD>
+ </DL>
+ </TMPL_LOOP>
+</TMPL_IF>
+
+<HR>
+<DL>
+ <!-- Class definition -->
+ <DT><TMPL_IF NAME="class_attribs"><TMPL_VAR NAME="class_attribs"> </TMPL_IF>class
+ <B><TMPL_VAR NAME="classname"></B>
+ <TMPL_IF NAME="superclass">
+ <DT>extends <TMPL_VAR NAME="superclass">
+ </TMPL_IF>
+
+</DL>
+ <TMPL_IF NAME="class_summary">
+ <P>
+ <TMPL_VAR name="class_summary">
+ </P>
+ </TMPL_IF>
+ <HR>
+
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+<TMPL_IF NAME="inner_classes">
+<A NAME="inner_classes"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Nested Class Summary</B></FONT></TD>
+</TR>
+<TMPL_LOOP name="inner_classes">
+ <TR BGCOLOR="white" CLASS="TableRowColor">
+ <TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+ <CODE><static class></CODE></FONT></TD>
+ <TD><CODE><B><A HREF="<TMPL_VAR name="classlink">"><TMPL_VAR name="classname"></A></B></CODE></TD>
+ </TR>
+</TMPL_LOOP>
+</TABLE>
+
+</TMPL_IF>
+<!-- ======== END NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+<TMPL_IF NAME="fields">
+ <A NAME="field_summary"><!-- --></A>
+ <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+ <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+ <TD COLSPAN=2><FONT SIZE="+2">
+ <B>Field Summary</B></FONT></TD>
+ </TR>
+
+ <!-- This is one instance field summary -->
+ <TMPL_LOOP name="fields">
+ <TR BGCOLOR="white" CLASS="TableRowColor">
+ <TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+ <CODE><TMPL_IF NAME="is_private"><private> </TMPL_IF><TMPL_IF NAME="is_class_field"><static> </TMPL_IF><TMPL_IF NAME="is_final"> <final></TMPL_IF> <TMPL_VAR NAME="type"></CODE></FONT></TD>
+ <TD><CODE><B><A HREF="#<TMPL_IF NAME="is_class_field">!s!</TMPL_IF><TMPL_VAR name="field_name">"><TMPL_VAR name="field_name"></A></B></CODE>
+ <BR>
+ <TMPL_VAR name="field_summary"></TD>
+ </TR>
+ </TMPL_LOOP>
+
+ </TABLE>
+
+ </TMPL_IF>
+
+ <TMPL_LOOP name="field_inheritance">
+ <TMPL_IF NAME="inherited_fields">
+ <A NAME=""><!-- --></A>
+ <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+ <TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+ <TD><B>Fields inherited from class <A HREF="<TMPL_VAR name="superclass_link">"><TMPL_VAR name="superclass_name"></A></B></TD>
+ </TR>
+ <TR BGCOLOR="white" CLASS="TableRowColor">
+ <TD><CODE>
+ <TMPL_VAR NAME="inherited_fields">
+ </CODE></TD>
+ </TR>
+</TABLE>
+
+</TMPL_IF>
+</TMPL_LOOP>
+
+<!-- =========== END FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+<TMPL_IF NAME="constructor_args">
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+ <TD>
+ <CODE>
+ <B>
+ <A HREF="#<TMPL_VAR name="classname">()"><TMPL_VAR name="classname"></A></B><TMPL_VAR name="constructor_args">
+ </CODE>
+ <BR>
+
+ <TMPL_VAR name="constructor_summary">
+ </TD>
+</TR>
+</TABLE>
+</TMPL_IF>
+<!-- ======== END CONSTRUCTOR SUMMARY ======== -->
+
+
+
+<!-- ========== METHOD SUMMARY =========== -->
+<TMPL_IF NAME="methods">
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+
+<TMPL_LOOP name="methods">
+ <TR BGCOLOR="white" CLASS="TableRowColor">
+ <TD ALIGN="right" VALIGN="top" WIDTH="1%">
+ <FONT SIZE="-1">
+ <CODE><TMPL_IF NAME="is_class_method"><static></TMPL_IF><TMPL_IF NAME="is_private"> <private> </TMPL_IF> <TMPL_VAR NAME="type"></CODE>
+ </FONT>
+ </TD>
+ <TD>
+ <CODE>
+ <B>
+ <A HREF="#<TMPL_IF NAME="is_class_method">!s!</TMPL_IF><TMPL_VAR name="method_name">"><TMPL_VAR name="method_name"></A></B><TMPL_VAR name="method_arguments">
+ </CODE>
+ <BR>
+
+ <TMPL_VAR name="method_summary">
+ </TD>
+ </TR>
+</TMPL_LOOP>
+
+</TABLE>
+</TMPL_IF>
+
+<TMPL_LOOP name="method_inheritance">
+ <A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class <a href="<TMPL_VAR name="superclass_link">"><TMPL_VAR name="superclass_name"></a></B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>
+<!-- Inherited methods -->
+<TMPL_VAR NAME="inherited_methods">
+</CODE></TD>
+</TR>
+</TABLE>
+
+</TMPL_LOOP>
+<P>
+<!-- ========== END METHOD SUMMARY =========== -->
+
+
+<!-- ============ FIELD DETAIL START =========== -->
+<TMPL_IF NAME="fields">
+ <A NAME="field_detail"><!-- --></A>
+ <TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+ <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+ <TD COLSPAN=1><FONT SIZE="+2"><B>Field Detail</B></FONT></TD>
+ </TR>
+ </TABLE>
+
+ <TMPL_LOOP NAME="fields">
+ <A NAME="<TMPL_IF NAME="is_class_field">!s!</TMPL_IF><TMPL_VAR NAME="field_name">"><!-- --></A>
+ <H3><TMPL_VAR NAME="field_name"></H3>
+ <PRE><TMPL_IF NAME="is_private"><private> </TMPL_IF><TMPL_IF NAME="is_class_field"><static> </TMPL_IF><TMPL_IF NAME="is_final"><final> </TMPL_IF><TMPL_VAR NAME="type"> <B><TMPL_VAR NAME="field_name"></B></PRE>
+ <UL>
+ <TMPL_VAR NAME="field_description">
+ <TMPL_IF NAME="const_link">
+ <P>
+ <DL>
+ <DT><B>See Also:</B><DD><A HREF="constant-values.html#<TMPL_VAR NAME="const_link">.<TMPL_IF NAME="is_class_field">!s!</TMPL_IF><TMPL_VAR NAME="field_name">">Constant Field Values</A></DL>
+ </DL>
+
+ </TMPL_IF>
+ </UL>
+ <HR>
+ </TMPL_LOOP>
+</TMPL_IF>
+
+<!-- ============ FIELD DETAIL END =========== -->
+
+ <!-- ========= CONSTRUCTOR DETAIL START ======== -->
+<TMPL_IF NAME="constructor_args">
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+ <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+ <TD COLSPAN=1>
+ <FONT SIZE="+2"><B>Constructor Detail</B></FONT>
+ </TD>
+ </TR>
+</TABLE>
+
+<A NAME="<TMPL_VAR name="classname">()"><!-- --></A><H3>
+<TMPL_VAR name="classname"></H3>
+<PRE><B><TMPL_VAR name="classname"></B><TMPL_VAR name="constructor_args"></PRE>
+
+<TMPL_IF NAME="constructor_detail">
+<UL>
+ <TMPL_VAR name="constructor_detail">
+</UL>
+</TMPL_IF>
+
+<TMPL_IF name="constructor_params">
+ <UL>
+ <B>Parameters:</B>
+ <TMPL_LOOP name="constructor_params">
+ <UL><CODE><TMPL_VAR name="varname"></CODE> - <TMPL_VAR name="vardescrip">
+ </UL>
+ </TMPL_LOOP>
+ </TMPL_IF>
+ </UL>
+</TMPL_IF>
+
+<!-- Constructor return value(s) -->
+<TMPL_IF name="constructor_returns">
+ <UL>
+ <B>Returns:</B>
+ <UL>
+ <TMPL_VAR name="constructor_returns">
+ </UL>
+ </UL>
+</TMPL_IF>
+<!-- End constructor return value(s) -->
+
+<!-- ADDITIONAL ATTRIBUTES -->
+<TMPL_IF name="constructor_attrs">
+<UL>
+<TMPL_VAR name="constructor_attrs">
+</UL>
+</TMPL_IF>
+<HR/>
+<!-- END ADDITIONAL ATTRIBUTES -->
+
+<!-- ========= CONSTRUCTOR DETAIL END ======== -->
+
+
+<!-- ============ METHOD DETAIL START ========== -->
+<TMPL_IF NAME="methods">
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+ <TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+ <TD COLSPAN=1><FONT SIZE="+2">
+ <B>Method Detail</B></FONT>
+ </TD>
+ </TR>
+</TABLE>
+
+<!-- One single method detail entry -->
+<TMPL_LOOP name="methods">
+ <A NAME="<TMPL_IF NAME="is_class_method">!s!</TMPL_IF><TMPL_VAR name="method_name">"><!-- --></A>
+ <H3><TMPL_VAR name="method_name"></H3>
+ <PRE><TMPL_IF NAME="is_class_method"><static> </TMPL_IF><TMPL_IF NAME="is_private"> <private> </TMPL_IF><TMPL_VAR NAME="type"> <B><TMPL_VAR name="method_name"></B><TMPL_VAR name="method_arguments"></PRE>
+ <TMPL_IF name="method_description">
+ <UL><TMPL_VAR name="method_description"></UL>
+ </TMPL_IF>
+
+ <!-- METHOD PARAMETERS START -->
+ <TMPL_IF name="method_params">
+ <UL>
+ <B>Parameters:</B>
+ <TMPL_LOOP name="method_params">
+ <UL><CODE><TMPL_VAR name="varname"></CODE> - <TMPL_VAR name="vardescrip">
+ </UL>
+ </TMPL_LOOP>
+ </UL>
+ </TMPL_IF>
+ <!-- METHOD PARAMETERS END -->
+
+ <TMPL_IF name="method_returns">
+ <UL>
+ <B>Returns:</B>
+ <UL>
+ <TMPL_VAR name="method_returns">
+ </UL>
+ </UL>
+ </TMPL_IF>
+
+ <!-- ADDITIONAL ATTRIBUTES START -->
+ <TMPL_IF name="attributes">
+ <UL>
+ <TMPL_VAR name="attributes">
+ </UL>
+ </TMPL_IF>
+ <!-- ADDITIONAL ATTRIBUTES END -->
+<HR>
+</TMPL_LOOP>
+</TMPL_IF>
+
+<!-- ============ METHOD DETAIL END ========== -->
+
+<!-- ========= END OF CLASS DATA ========= -->
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">overview-summary.html"><FONT CLASS="NavBarFont1"><B>Overview</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <TMPL_IF NAME="file_overview"> <A HREF="<TMPL_VAR NAME="path_to_base"><TMPL_VAR NAME="file_overview">"></TMPL_IF><FONT CLASS="NavBarFont1"><TMPL_IF NAME="file_overview"><B></TMPL_IF>File<TMPL_IF NAME="file_overview"></B></TMPL_IF></FONT><TMPL_IF NAME="file_overview"></A></TMPL_IF> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">overview-tree.html"><FONT CLASS="NavBarFont1"><b>Tree</b></FONT></A> </TD>
+ <!--TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"--> <!--A HREF="deprecated-list.html"--><!--FONT CLASS="NavBarFont1">Deprecated</FONT--><!--/A--><!-- </TD-->
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="<TMPL_VAR NAME="path_to_base">help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+<B><TMPL_VAR NAME="project_name"></B>
+</EM>
+</TD
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <TMPL_IF NAME="prev_class"><A HREF="<TMPL_VAR NAME="prev_class">"></TMPL_IF><B>PREV CLASS</B><TMPL_IF NAME="prev_class"></A></TMPL_IF><!--
+ NEXT CLASS
+-->
+ <TMPL_IF NAME="next_class"><A HREF="<TMPL_VAR NAME="next_class">"></TMPL_IF><B>NEXT CLASS</B><TMPL_IF NAME="next_class"></A></TMPL_IF></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="<TMPL_VAR NAME="path_to_base">index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="<TMPL_VAR NAME="path_to_base">allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="<TMPL_VAR NAME="path_to_base">allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+ SUMMARY: <A HREF="#field_summary">FIELD</A> | <A HREF="#constructor_summary">CONSTR</A> | <A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL: <A HREF="#field_detail">FIELD</A> | <A HREF="#constructor_detail">CONSTR</A> | <A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<FONT SIZE="-1">
+<TMPL_VAR NAME="page_footer">
+</FONT>
+<div class="jsdoc_ctime">Documentation generated by <a href="http://jsdoc.sourceforge.net/" target="_parent">JSDoc</a> on <TMPL_VAR NAME="ctime"></div>
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/overview-frame.tmpl
===================================================================
--- trunk/build/JSDoc/overview-frame.tmpl (rev 0)
+++ trunk/build/JSDoc/overview-frame.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,43 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<HTML>
+<HEAD>
+<TITLE>
+Overview ()
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Overview ()";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+<TMPL_IF NAME="logo">
+ <IMG SRC="<TMPL_VAR NAME="logo">"/>
+</TMPL_IF>
+<H3 class="FrameHeadingFont"><B><TMPL_VAR NAME="project_name"></B></H3>
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<B></B></FONT></TD>
+</TR>
+</TABLE>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="allclasses-frame.html" TARGET="packageFrame">All Classes</A></FONT>
+<P>
+<FONT size="+1" CLASS="FrameHeadingFont">
+<TMPL_VAR NAME="heading"></FONT>
+<BR>
+<TMPL_LOOP name="filenames">
+<FONT CLASS="FrameItemFont"><A HREF="<TMPL_VAR NAME="filelink">" TARGET="packageFrame"><TMPL_VAR NAME="filename"></A></FONT><BR>
+</TMPL_LOOP>
+</TD>
+</TR>
+</TABLE>
+
+<P>
+
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/overview-summary.tmpl
===================================================================
--- trunk/build/JSDoc/overview-summary.tmpl (rev 0)
+++ trunk/build/JSDoc/overview-summary.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,222 @@
+<!doctype html public "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
+<html>
+<head>
+<title>
+<tmpl_var name="project_name"> Overview
+</title>
+<link rel ="stylesheet" type="text/css" href="stylesheet.css" title="Style">
+<script>
+function asd() {
+ <tmpl_if name="is_file_summary">
+ parent.document.title="<tmpl_var name="project_title"> Overview";
+ <tmpl_else>
+ parent.document.title="<tmpl_var name="project_name"> Overview";
+ </tmpl_if>
+}
+</script>
+</head>
+<body bgcolor="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<a name="navbar_top"><!-- --></a>
+<table border="0" width="100%" cellpadding="1" cellspacing="0">
+<tr>
+<td colspan=2 bgcolor="#EEEEFF" class="NavBarCell1">
+<a name="navbar_top_firstrow"><!-- --></a>
+<table border="0" cellpadding="0" cellspacing="3">
+ <tr align="center" valign="top">
+
+ <tmpl_unless name="is_file_summary">
+ <td bgcolor="#FFFFFF" class="NavBarCell1Rev"> <font class="NavBarFont1Rev"><b>Overview</b></font> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <font class="NavBarFont1">File</font> </td>
+ <tmpl_else>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="overview-summary.html"><font class="NavBarFont1"><b>Overview</b></font></a> </td>
+ <td bgcolor="#FFFFFF" class="NavBarCell1Rev"> <font class="NavBarFont1Rev"><b>File</b></font> </td>
+ </tmpl_unless>
+
+ <td bgcolor="#FFFFFF" class="NavBarCell1"> <font class="NavBarFont1">Class</font> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="overview-tree.html"><font class="NavBarFont1"><b>Tree</b></font></a> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="index-all.html"--><font class="NavBarFont1"><b>Index</b></font></a> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="help-doc.html"><font class="NavBarFont1"><b>Help</b></font></a> </td>
+ </tr>
+</table>
+</td>
+<td bgcolor="#EEEEFF" align="right" valign="top">
+<em>
+<b><tmpl_var name="project_name"></b></em>
+</td>
+</tr>
+
+<tr>
+<td bgcolor="white" class="NavBarCell2"><font size="-2">
+ PREV
+ NEXT</font></td>
+<td bgcolor="white" class="NavBarCell2"><font size="-2">
+ <a href="index.html" target="_top"><b>FRAMES</b></a>
+ <a href="overview-summary.html" target="_top"><b>NO FRAMES</b></a>
+
+<script>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</script>
+<noscript>
+<a href="allclasses-noframe.html" target=""><b>All Classes</b></a>
+</noscript>
+</font></td>
+</tr>
+</table>
+<!-- =========== END OF NAVBAR =========== -->
+
+<hr>
+<center>
+ <tmpl_if name="project_title">
+ <h2><tmpl_var name="project_title"></h2>
+ <tmpl_else>
+ <h2>JSDoc Documentation</h2>
+ </tmpl_if>
+</center>
+<tmpl_if name="project_title">
+ <tmpl_if name="generic">
+ <p>
+ This document is the API Specification for
+ <tmpl_var name="project_title">.
+ </p>
+ </tmpl_if>
+</tmpl_if>
+
+<h4>Summary</h4>
+<p>
+ <tmpl_if name="project_summary">
+ <tmpl_var name="project_summary">
+ <tmpl_else>
+ No summary generated for these documents.
+ </tmpl_if>
+</p>
+
+<hr>
+
+<tmpl_if name="overviews">
+ <table border="1" cellpadding="3" cellspacing="0" width="100%">
+ <tr bgcolor="#CCCCFF" class="TableHeadingColor">
+ <td colspan=2><font size="+2">
+ <tmpl_if name="is_file_summary">
+ <b>Class Summary</b>
+ <tmpl_else>
+ <b>File Summary</b>
+ </tmpl_if>
+ </font></td>
+ </tr>
+ <tmpl_loop name="overviews">
+ <tr bgcolor="white" class="TableRowColor">
+ <td width="15%"><b><a href="<TMPL_VAR NAME="link">"><tmpl_var name="name"></a></b></td>
+ <td><tmpl_var name="overview"></td>
+ </tr>
+ </tmpl_loop>
+ </table>
+ <hr/>
+</tmpl_if>
+
+<!-- ========== METHOD SUMMARY =========== -->
+<tmpl_if name="methods">
+ <a name="method_summary"><!-- --></a>
+ <table border="1" cellpadding="3" cellspacing="0" width="100%">
+ <tr bgcolor="#CCCCFF" class="TableHeadingColor">
+ <td colspan=2>
+ <font size="+2">
+ <b>Method Summary</b>
+ </font>
+ </td>
+ </tr>
+
+ <tmpl_loop name="methods">
+ <tr bgcolor="white" class="TableRowColor">
+ <td align="right" valign="top" width="1%">
+ <font size="-1">
+ <code><tmpl_if name="is_class_method">static</tmpl_if><tmpl_if name="is_private"> private </tmpl_if> <tmpl_var name="type"></code>
+ </font>
+ </td>
+ <td>
+ <code>
+ <b>
+ <a href="<TMPL_VAR NAME="file_link">#<TMPL_VAR name="method_anchor">"><tmpl_var name="method_name"></a></b><tmpl_var name="method_arguments">
+ </code>
+ <br>
+
+ <tmpl_var name="method_summary">
+ </td>
+ </tr>
+ </tmpl_loop>
+
+ </table>
+ <p>
+</tmpl_if>
+<!-- ========== END METHOD SUMMARY =========== -->
+
+<tmpl_if name="sourcecode">
+ <pre class="sourceview"><tmpl_var name="sourcecode"></pre>
+ <hr>
+</tmpl_if>
+
+
+<!-- ========== START OF NAVBAR ========== -->
+<a name="navbar_top"><!-- --></a>
+<table border="0" width="100%" cellpadding="1" cellspacing="0">
+<tr>
+<td colspan=2 bgcolor="#EEEEFF" class="NavBarCell1">
+<a name="navbar_top_firstrow"><!-- --></a>
+<table border="0" cellpadding="0" cellspacing="3">
+ <tr align="center" valign="top">
+
+ <tmpl_unless name="is_file_summary">
+ <td bgcolor="#FFFFFF" class="NavBarCell1Rev"> <font class="NavBarFont1Rev"><b>Overview</b></font> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <font class="NavBarFont1">File</font> </td>
+ <tmpl_else>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="overview-summary.html"><font class="NavBarFont1"><b>Overview</b></font></a> </td>
+ <td bgcolor="#FFFFFF" class="NavBarCell1Rev"> <font class="NavBarFont1Rev"><b>File</b></font> </td>
+ </tmpl_unless>
+
+ <td bgcolor="#FFFFFF" class="NavBarCell1"> <font class="NavBarFont1">Class</font> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="overview-tree.html"><font class="NavBarFont1"><b>Tree</b></font></a> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="index-all.html"--><font class="NavBarFont1"><b>Index</b></font></a> </td>
+ <td bgcolor="#EEEEFF" class="NavBarCell1"> <a href="help-doc.html"><font class="NavBarFont1"><b>Help</b></font></a> </td>
+ </tr>
+</table>
+</td>
+<td bgcolor="#EEEEFF" align="right" valign="top"><em>
+<b><tmpl_var name="project_name"></b></em>
+</td>
+</tr>
+
+<tr>
+<td bgcolor="white" class="NavBarCell2"><font size="-2">
+ PREV
+ NEXT</font></td>
+<td bgcolor="white" class="NavBarCell2"><font size="-2">
+ <a href="index.html" target="_top"><b>FRAMES</b></a>
+ <a href="overview-summary.html" target="_top"><b>NO FRAMES</b></a>
+
+<script>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</script>
+<noscript>
+<a href="allclasses-noframe.html" target=""><b>All Classes</b></a>
+</noscript>
+</font></td>
+</tr>
+</table>
+<!-- =========== END OF NAVBAR =========== -->
+
+<hr>
+<font size="-1">
+<tmpl_var name="page_footer">
+</font>
+<div class="jsdoc_ctime">Documentation generated by <a href="http://jsdoc.sourceforge.net/" target="_parent">JSDoc</a> on <tmpl_var name="ctime"></div>
+</body>
+</html>
Added: trunk/build/JSDoc/overview-tree.tmpl
===================================================================
--- trunk/build/JSDoc/overview-tree.tmpl (rev 0)
+++ trunk/build/JSDoc/overview-tree.tmpl 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN""http://www.w3.org/TR/REC-html40/frameset.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<TITLE>
+<TMPL_VAR name="project_name"> Class Hierarchy
+</TITLE>
+<LINK REL="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+<SCRIPT>
+function asd()
+{
+parent.document.title="<TMPL_VAR NAME="project_name"> Class Hierarchy";
+}
+</SCRIPT>
+</HEAD>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"><A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><b>Overview</b></A></FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><b>Tree</b></FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"--><FONT CLASS="NavBarFont1"><b>Index</b></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><b>Help</b></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD BGCOLOR="#FFFFFF" ALIGN="right" VALIGN="top"><EM>
+<B><TMPL_VAR NAME="project_name"></B></EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="overview-summary.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<H2>Class Hierarchy</H2>
+
+<TMPL_VAR name="classtrees">
+
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=2 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+ <TR ALIGN="center" VALIGN="top">
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"><A HREF="overview-summary.html"><FONT CLASS="NavBarFont1"><b>Overview</b></A></FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">File</FONT> </TD>
+ <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1"> <FONT CLASS="NavBarFont1">Class</FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1Rev"> <FONT CLASS="NavBarFont1Rev"><b>Tree</b></FONT> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="index-all.html"--><FONT CLASS="NavBarFont1"><b>Index</b></FONT></A> </TD>
+ <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1"> <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><b>Help</b></FONT></A> </TD>
+ </TR>
+</TABLE>
+</TD>
+<TD BGCOLOR="#FFFFFF" ALIGN="right" VALIGN="top"><EM>
+<B><TMPL_VAR NAME="project_name"></B></EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ PREV
+ NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+ <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>
+ <A HREF="overview-summary.html" TARGET="_top"><B>NO FRAMES</B></A>
+
+<SCRIPT>
+ <!--
+ if(window==top) {
+ document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+ }
+ //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<hr>
+<FONT SIZE="-1">
+<TMPL_VAR NAME="page_footer">
+</FONT>
+<div class="jsdoc_ctime">Documentation generated by <a href="http://jsdoc.sourceforge.net/" parent="_parent">JSDoc</a> on <TMPL_VAR NAME="ctime"></div>
+</BODY>
+</HTML>
Added: trunk/build/JSDoc/stylesheet.css
===================================================================
--- trunk/build/JSDoc/stylesheet.css (rev 0)
+++ trunk/build/JSDoc/stylesheet.css 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,39 @@
+/* JSDoc style sheet */
+
+/* Define colors, fonts and other style attributes here to override the defaults */
+
+/* Page background color */
+body { background-color: #FFFFFF }
+
+/* Table colors */
+.TableHeadingColor { background: #CCCCFF } /* Dark mauve */
+.TableSubHeadingColor { background: #EEEEFF } /* Light mauve */
+.TableRowColor { background: #FFFFFF } /* White */
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont { font-size: 10pt; font-family: Helvetica, Arial, san-serif }
+.FrameHeadingFont { font-size: 10pt; font-family: Helvetica, Arial, san-serif }
+.FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, san-serif }
+
+/* Example of smaller, sans-serif font in frames */
+/* .FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */
+
+/* Navigation bar fonts and colors */
+.NavBarCell1 { background-color:#EEEEFF;}/* Light mauve */
+.NavBarCell1Rev { background-color:#00008B;}/* Dark Blue */
+.NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;}
+.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}
+
+.NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
+.NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
+
+.jsdoc_ctime { font-family: Arial, Helvetica, sans-serif; font-size: 9pt;
+ text-align: right }
+
+/* Sourcecode view */
+.sourceview { background: #FFFFFF }
+.attrib { color: #DD7777 }
+.comment { color: #55AA55 }
+.reserved { color: #FF5555 }
+.literal { color: #5555FF }
+
Added: trunk/build/JSDoc/test.js
===================================================================
--- trunk/build/JSDoc/test.js (rev 0)
+++ trunk/build/JSDoc/test.js 2008-02-20 11:31:02 UTC (rev 2119)
@@ -0,0 +1,505 @@
+/**
+ * @fileoverview This file is to be used for testing the JSDoc parser
+ * It is not intended to be an example of good JavaScript OO-programming,
+ * nor is it intended to fulfill any specific purpose apart from
+ * demonstrating the functionality of the
+ * {@link http://sourceforge.net/projects/jsdoc JSDoc} parser
+ *
+ * @author Gabriel Reid gab_reid at users.sourceforge.net
+ * @version 0.1
+ */
+
+
+/**
+ * Construct a new Shape object.
+ * @class This is the basic Shape class.
+ * It can be considered an abstract class, even though no such thing
+ * really existing in JavaScript
+ * @constructor
+ * @throws MemoryException if there is no more memory
+ * @throws GeneralShapeException rarely (if ever)
+ * @return A new shape
+ */
+function Shape(){
+
+ /**
+ * This is an example of a function that is not given as a property
+ * of a prototype, but instead it is assigned within a constructor.
+ * For inner functions like this to be picked up by the parser, the
+ * function that acts as a constructor <b>must</b> be denoted with
+ * the <b>@constructor</b> tag in its comment.
+ * @type String
+ */
+ this.getClassName = function(){
+ return "Shape";
+ }
+
+ /**
+ * This is a private method, just used here as an example
+ */
+ function addReference(){
+ // Do nothing...
+ }
+
+}
+
+/**
+ * Create a new Hexagon instance.
+ * @extends Shape
+ * @class Hexagon is a class that is a <i>logical</i> sublcass of
+ * {@link Shape} (thanks to the <code>@extends</code> tag), but in
+ * reality it is completely unrelated to Shape.
+ * @param {int} sideLength The length of one side for the new Hexagon
+ */
+function Hexagon(sideLength) {
+}
+
+
+/**
+ * This is an unattached (static) function that adds two integers together.
+ * @param {int} One The first number to add
+ * @param {int http://jsdoc.sourceforge.net/} Two The second number to add
+ * @author Gabriel Reid
+ * @deprecated So you shouldn't use it anymore!
+ */
+function Add(One, Two){
+ return One + Two;
+}
+
+
+/**
+ * The color of this shape
+ * @type Color
+ */
+Shape.prototype.color = null;
+
+/**
+ * The border of this shape.
+ * @type int
+ */
+Shape.prototype.border = null;
+
+/*
+ * The assignment of function implementations for Shape, documentation will
+ * be taken over from the method declaration.
+ */
+
+Shape.prototype.getCoords = Shape_GetCoords;
+
+Shape.prototype.getColor = Shape_GetColor;
+
+Shape.prototype.setCoords = Shape_SetCoords;
+
+Shape.prototype.setColor = Shape_SetColor;
+
+/*
+ * These are all the instance method implementations for Shape
+ */
+
+/**
+ * Get the coordinates of this shape. It is assumed that we're always talking
+ * about shapes in a 2D location here.
+ * @requires Shape The shape class
+ * @returns A Coordinate object representing the location of this Shape
+ * @type Coordinate
+ */
+function Shape_GetCoords(){
+ return this.coords;
+}
+
+/**
+ * Get the color of this shape.
+ * @see #setColor
+ * @type Color
+ */
+function Shape_GetColor(){
+ return this.color;
+}
+
+/**
+ * Set the coordinates for this Shape
+ * @param {Coordinate} coordinates The coordinates to set for this Shape
+ */
+function Shape_SetCoords(coordinates){
+ this.coords = coordinates;
+}
+
+/**
+ * Set the color for this Shape
+ * @param {Color} color The color to set for this Shape
+ * @param other There is no other param, but it can still be documented if
+ * optional parameters are used
+ * @throws NonExistantColorException (no, not really!)
+ * @see #getColor
+ */
+function Shape_SetColor(color){
+ this.color = color;
+}
+
+/**
+ * Clone this shape
+ * @returns A copy of this shape
+ * @type Shape
+ * @author Gabriel Reid
+ */
+Shape.prototype.clone = function(){
+ return new Shape();
+}
+
+/**
+ * Create a new Rectangle instance.
+ * @class A basic rectangle class, inherits from Shape.
+ * This class could be considered a concrete implementation class
+ * @constructor
+ * @param {int} width The optional width for this Rectangle
+ * @param {int} height Thie optional height for this Rectangle
+ * @author Gabriel Reid
+ * @see Shape Shape is the base class for this
+ */
+function Rectangle(width, // This is the width
+ height // This is the height
+ ){
+ if (width){
+ this.width = width;
+ if (height){
+ this.height = height;
+ }
+ }
+}
+
+
+/* Inherit from Shape */
+Rectangle.prototype = new Shape();
+
+/**
+ * Value to represent the width of the Rectangle.
+ * <br>Text in <b>bold</b> and <i>italic</i> and a
+ * link to <a href="http://sf.net">SourceForge</a>
+ * @private
+ * @type int
+ */
+Rectangle.prototype.width = 0;
+
+/**
+ * Value to represent the height of the Rectangle
+ * @private
+ * @type int
+ */
+Rectangle.prototype.height = 0;
+
+/**
+ * Get the type of this object.
+ * @type String
+ */
+Rectangle.prototype.getClassName= function(){
+ return "Rectangle";
+}
+
+/*
+ * These are all the instance method implementations for Rectangle
+ */
+
+Rectangle.prototype.getWidth = Rectangle_GetWidth;
+
+Rectangle.prototype.getHeight = Rectangle_GetHeight;
+
+Rectangle.prototype.setWidth = Rectangle_SetWidth;
+
+Rectangle.prototype.setHeight = Rectangle_SetHeight;
+
+Rectangle.prototype.getArea = Rectangle_GetArea;
+
+
+/**
+ * Get the value of the width for the Rectangle
+ * @type int
+ * @see #setWidth
+ */
+function Rectangle_GetWidth(){
+ return this.width;
+}
+
+/**
+ * Get the value of the height for the Rectangle.
+ * Another getter is the {@link Shape#getColor} method in the
+ * {@link Shape base Shape class}.
+ * @return The height of this Rectangle
+ * @type int
+ * @see #setHeight
+ */
+function Rectangle_GetHeight(){
+ return this.height;
+}
+
+/**
+ * Set the width value for this Rectangle.
+ * @param {int} width The width value to be set
+ * @see #getWidth
+ */
+function Rectangle_SetWidth(width){
+ this.width = width;
+}
+
+/**
+ * Set the height value for this Rectangle.
+ * @param {int} height The height value to be set
+ * @see #getHeight
+ */
+function Rectangle_SetHeight(height){
+ this.height = height;
+}
+
+/**
+ * Get the value for the total area of this Rectangle
+ * @return total area of this Rectangle
+ * @type int
+ */
+function Rectangle_GetArea(){
+ return width * height;
+}
+
+
+/**
+ * Create a new Square instance.
+ * @class A Square is a subclass of {@link Rectangle}
+ * @param {int} width The optional width for this Rectangle
+ * @param {int} height The optional height for this Rectangle
+ */
+function Square(width, height){
+ if (width){
+ this.width = width;
+ if (height){
+ this.height = height;
+ }
+ }
+
+}
+
+/* Square is a subclass of Rectangle */
+Square.prototype = new Rectangle();
+
+
+/*
+ * The assignment of function implementation for Shape.
+ */
+Square.prototype.setWidth = Square_SetWidth;
+
+Square.prototype.setHeight = Square_SetHeight;
+
+
+
+/**
+ * Set the width value for this Square.
+ * @param {int} width The width value to be set
+ * @see #getWidth
+ */
+function Square_SetWidth(width){
+ this.width = this.height = width;
+}
+
+/**
+ * Set the height value for this Square
+ * Sets the {@link Rectangle#height height} attribute in the Rectangle.
+ * @param {int} height The height value to be set
+ */
+function Square_SetHeight(height){
+ this.height = this.width = height;
+}
+
+
+/**
+ * Create a new Circle instance based on a radius.
+ * @class Circle class is another subclass of Shape
+ * @param {int} radius The optional radius of this Circle
+ */
+function Circle(radius){
+ if (radius){
+ this.radius = radius;
+ }
+}
+
+/* Circle inherits from Shape */
+Circle.prototype = new Shape();
+
+/**
+ * The radius value for this Circle
+ * @private
+ * @type int
+ */
+Circle.prototype.radius = 0;
+
+/**
+ * A very simple class (static) field that is also a constant
+ * @final
+ * @type float
+ */
+Circle.PI = 3.14;
+
+Circle.createCircle = Circle_CreateCircle;
+
+Circle.prototype.getRadius = Circle_GetRadius;
+
+Circle.prototype.setRadius = Circle_SetRadius;
+
+/**
+ * Get the radius value for this Circle
+ * @type int
+ * @see #setRadius
+ */
+function Circle_GetRadius(){
+ return this.radius;
+}
+
+/**
+ * Set the radius value for this Circle
+ * @param {int} radius The radius value to set
+ * @see #getRadius
+ */
+function Circle_SetRadius(radius){
+ this.radius = radius;
+}
+
+/**
+ * An example of a class (static) method that acts as a factory for Circle
+ * objects. Given a radius value, this method creates a new Circle.
+ * @param {int} radius The radius value to use for the new Circle.
+ * @type Circle
+ */
+function Circle_CreateCircle(radius){
+ return new Circle(radius);
+}
+
+
+/**
+ * Create a new Coordinate instance based on x and y grid data.
+ * @class Coordinate is a class that can encapsulate location information.
+ * @param {int} x The optional x portion of the Coordinate
+ * @param {int} y The optinal y portion of the Coordinate
+ */
+function Coordinate(x, y){
+ if (x){
+ this.x = x;
+ if (y){
+ this.y = y;
+ }
+ }
+}
+
+/**
+ * The x portion of the Coordinate
+ * @type int
+ * @see #getX
+ * @see #setX
+ */
+Coordinate.prototype.x = 0;
+
+/**
+ * The y portion of the Coordinate
+ * @type int
+ * @see #getY
+ * @see #setY
+ */
+Coordinate.prototype.y = 0;
+
+Coordinate.prototype.getX = Coordinate_GetX;
+Coordinate.prototype.getY = Coordinate_GetY;
+Coordinate.prototype.setX = Coordinate_SetX;
+Coordinate.prototype.setY = Coordinate_SetY;
+
+/**
+ * Gets the x portion of the Coordinate.
+ * @type int
+ * @see #setX
+ */
+function Coordinate_GetX(){
+ return this.x;
+}
+
+/**
+ * Get the y portion of the Coordinate.
+ * @type int
+ * @see #setY
+ */
+function Coordinate_GetY(){
+ return this.y;
+}
+
+/**
+ * Sets the x portion of the Coordinate.
+ * @param {int} x The x value to set
+ * @see #getX
+ */
+function Coordinate_SetX(x){
+ this.x = x;
+}
+
+/**
+ * Sets the y portion of the Coordinate.
+ * @param {int} y The y value to set
+ * @see #getY
+ */
+function Coordinate_SetY(y){
+ this.y = y;
+}
+
+/**
+ * @class This class exists to demonstrate the assignment of a class prototype
+ * as an anonymous block.
+ */
+function ShapeFactory(){
+}
+
+ShapeFactory.prototype = {
+ /**
+ * Creates a new {@link Shape} instance.
+ * @return A new {@link Shape}
+ * @type Shape
+ */
+ createShape: function(){
+ return new Shape();
+ }
+}
+
+/**
+ * An example of a singleton class
+ */
+MySingletonShapeFactory = new function(){
+
+ /**
+ * Get the next {@link Shape}
+ * @type Shape
+ * @return A new {@link Shape}
+ */
+ this.getShape = function(){
+ return null;
+ }
+
+}
+
+
+/**
+ * Create a new Foo instance.
+ * @class This is the Foo class. It exists to demonstrate 'nested' classes.
+ * @constructor
+ * @see Foo.Bar
+ */
+function Foo(){}
+
+/**
+ * Creates a new instance of Bar.
+ * @class This class exists to demonstrate 'nested' classes.
+ * @constructor
+ * @see Foo.Bar
+ */
+function Bar(){}
+
+/**
+ * Nested class
+ * @constructor
+ */
+Foo.Bar = function(){this.x = 2;}
+
+Foo.Bar.prototype = new Bar();
+
+Foo.Bar.prototype.y = '3';
+
More information about the Mapbender_commits
mailing list