- Προσθήκη αλγορίθμου υπολογισμού των ελεύθερων ωρών ενός πάροχου υπηρεσιών έτσι ώστε να μπορεί ο πελάτης να κλείσει ραντεβού μαζι του.

- Δημιουργία script για παραγωγή documention του κώδικα
- Μικρές διορθώσεις
This commit is contained in:
alextselegidis@gmail.com 2013-05-20 17:21:58 +00:00
parent deab8b490d
commit ab6c6d959d
493 changed files with 52847 additions and 113 deletions

View file

@ -0,0 +1,335 @@
/*
mustache.js Logic-less templates in JavaScript
See http://mustache.github.com/ for more info.
*/
var Mustache = function() {
var Renderer = function() {};
Renderer.prototype = {
otag: "{{",
ctag: "}}",
pragmas: {},
buffer: [],
pragmas_implemented: {
"IMPLICIT-ITERATOR": true,
"ARRAY-ORDINALS": true // define #first? and #last? when looping arrays
},
context: {},
render: function(template, context, partials, in_recursion) {
// reset buffer & set context
if(!in_recursion) {
this.context = context;
this.buffer = []; // TODO: make this non-lazy
}
// fail fast
if(!this.includes("", template)) {
if(in_recursion) {
return template;
} else {
this.send(template);
return;
}
}
template = this.render_pragmas(template);
var html = this.render_section(template, context, partials);
if(in_recursion) {
return this.render_tags(html, context, partials, in_recursion);
}
this.render_tags(html, context, partials, in_recursion);
},
/*
Sends parsed lines
*/
send: function(line) {
if(line != "") {
this.buffer.push(line);
}
},
/*
Looks for %PRAGMAS
*/
render_pragmas: function(template) {
// no pragmas
if(!this.includes("%", template)) {
return template;
}
var that = this;
var regex = new RegExp(this.otag + "%([\\w-]+) ?([\\w]+=[\\w]+)?" +
this.ctag);
return template.replace(regex, function(match, pragma, options) {
if(!that.pragmas_implemented[pragma]) {
throw({message:
"This implementation of mustache doesn't understand the '" +
pragma + "' pragma"});
}
that.pragmas[pragma] = {};
if(options) {
var opts = options.split("=");
that.pragmas[pragma][opts[0]] = opts[1];
}
return "";
// ignore unknown pragmas silently
});
},
/*
Tries to find a partial in the curent scope and render it
*/
render_partial: function(name, context, partials) {
name = this.trim(name);
if(!partials || partials[name] === undefined) {
throw({message: "unknown_partial '" + name + "'"});
}
if(typeof(context[name]) != "object") {
return this.render(partials[name], context, partials, true);
}
return this.render(partials[name], context[name], partials, true);
},
/*
Renders inverted (^) and normal (#) sections
*/
render_section: function(template, context, partials) {
if(!this.includes("#", template) && !this.includes("^", template)) {
return template;
}
var that = this;
// CSW - Added "+?" so it finds the tighest bound, not the widest
var regex = new RegExp(this.otag + "(\\^|\\#)\\s*(.+)\\s*" + this.ctag +
"\n*([\\s\\S]+?)" + this.otag + "\\/\\s*\\2\\s*" + this.ctag +
"\\s*", "mg");
// for each {{#foo}}{{/foo}} section do...
return template.replace(regex, function(match, type, name, content) {
var value = that.find(name, context);
if(type == "^") { // inverted section
if(!value || that.is_array(value) && value.length === 0) {
// false or empty list, render it
return that.render(content, context, partials, true);
} else {
return "";
}
} else if(type == "#") { // normal section
if(that.is_array(value)) { // Enumerable, Let's loop!
var len = value.length;
return value.map(function(row, i) {
return that.render(content, that.create_context(row, {first: i === 0, last: i === len-1}),
partials, true);
}).join("");
} else if(that.is_object(value)) { // Object, Use it as subcontext!
return that.render(content, that.create_context(value),
partials, true);
} else if(typeof value === "function") {
// higher order section
return value.call(context, content, function(text) {
return that.render(text, context, partials, true);
});
} else if(value) { // boolean section
return that.render(content, context, partials, true);
} else {
return "";
}
}
});
},
/*
Replace {{foo}} and friends with values from our view
*/
render_tags: function(template, context, partials, in_recursion) {
// tit for tat
var that = this;
var new_regex = function() {
return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\\/#\\^]+?)\\1?" +
that.ctag + "+", "g");
};
var regex = new_regex();
var tag_replace_callback = function(match, operator, name) {
switch(operator) {
case "!": // ignore comments
return "";
case "=": // set new delimiters, rebuild the replace regexp
that.set_delimiters(name);
regex = new_regex();
return "";
case ">": // render partial
return that.render_partial(name, context, partials);
case "{": // the triple mustache is unescaped
return that.find(name, context);
default: // escape the value
return that.escape(that.find(name, context));
}
};
var lines = template.split("\n");
for(var i = 0; i < lines.length; i++) {
lines[i] = lines[i].replace(regex, tag_replace_callback, this);
if(!in_recursion) {
this.send(lines[i]);
}
}
if(in_recursion) {
return lines.join("\n");
}
},
set_delimiters: function(delimiters) {
var dels = delimiters.split(" ");
this.otag = this.escape_regex(dels[0]);
this.ctag = this.escape_regex(dels[1]);
},
escape_regex: function(text) {
// thank you Simon Willison
if(!arguments.callee.sRE) {
var specials = [
'/', '.', '*', '+', '?', '|',
'(', ')', '[', ']', '{', '}', '\\'
];
arguments.callee.sRE = new RegExp(
'(\\' + specials.join('|\\') + ')', 'g'
);
}
return text.replace(arguments.callee.sRE, '\\$1');
},
/*
find `name` in current `context`. That is find me a value
from the view object
*/
find: function(name, context) {
name = this.trim(name);
// Checks whether a value is thruthy or false or 0
function is_kinda_truthy(bool) {
return bool === false || bool === 0 || bool;
}
var value;
if(is_kinda_truthy(context[name])) {
value = context[name];
} else if(is_kinda_truthy(this.context[name])) {
value = this.context[name];
}
if(typeof value === "function") {
return value.apply(context);
}
if(value !== undefined) {
return value;
}
// silently ignore unkown variables
return "";
},
// Utility methods
/* includes tag */
includes: function(needle, haystack) {
return haystack.indexOf(this.otag + needle) != -1;
},
/*
Does away with nasty characters
*/
escape: function(s) {
s = String(s === null ? "" : s);
return s.replace(/&(?!\w+;)|["'<>\\]/g, function(s) {
switch(s) {
case "&": return "&amp;";
case "\\": return "\\\\";
case '"': return '&quot;';
case "'": return '&#39;';
case "<": return "&lt;";
case ">": return "&gt;";
default: return s;
}
});
},
// by @langalex, support for arrays of strings
create_context: function(_context, opts) {
if(this.is_object(_context)) {
if (this.pragmas["ARRAY-ORDINALS"] && opts) {
_context['first?'] = opts.first || false;
_context['last?'] = opts.last || false;
}
return _context;
} else {
var iterator = ".";
if(this.pragmas["IMPLICIT-ITERATOR"]) {
iterator = this.pragmas["IMPLICIT-ITERATOR"].iterator;
}
var ctx = {};
ctx[iterator] = _context;
if (this.pragmas["ARRAY-ORDINALS"] && opts){
ctx['first?'] = opts.first || false;
ctx['last?'] = opts.last || false;
}
return ctx;
}
},
is_object: function(a) {
return a && typeof a == "object";
},
is_array: function(a) {
return Object.prototype.toString.call(a) === '[object Array]';
},
/*
Gets rid of leading and trailing whitespace
*/
trim: function(s) {
return s.replace(/^\s*|\s*$/g, "");
},
/*
Why, why, why? Because IE. Cry, cry cry.
*/
map: function(array, fn) {
if (typeof array.map == "function") {
return array.map(fn);
} else {
var r = [];
var l = array.length;
for(var i = 0; i < l; i++) {
r.push(fn(array[i]));
}
return r;
}
}
};
return({
name: "mustache.js",
version: "0.3.1-dev",
/*
Turns a template and view into HTML
*/
to_html: function(template, view, partials, send_fun) {
var renderer = new Renderer();
if(send_fun) {
renderer.send = send_fun;
}
renderer.render(template, view, partials);
if(!send_fun) {
return renderer.buffer.join("\n");
}
}
});
}();

View file

@ -0,0 +1,46 @@
{
"name": "{{appname}}",
"version": "{{appversion}}",
"revision": "{{timestamp}}",
"description": "An API documentation generator for JavaScript.",
"keywords": [ "documentation", "javascript" ],
"licenses": [
{
"type": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0"
}
],
"repositories": [
{
"type": "git",
"url": "https://github.com/jsdoc3/jsdoc"
}
],
"dependencies": {
"async": "0.1.22",
"catharsis": "0.5.6",
"crypto-browserify": "git+https://github.com/dominictarr/crypto-browserify.git#95c5d505",
"js2xmlparser": "0.1.0",
"jshint": "0.9.1",
"markdown": "git+https://github.com/jsdoc3/markdown-js.git",
"marked": "0.2.8",
"taffydb": "git+https://github.com/hegemonic/taffydb.git",
"underscore": "1.4.2",
"wrench": "1.3.9"
},
"bin": "./nodejs/bin/jsdoc",
"bugs": "https://github.com/jsdoc3/jsdoc/issues",
"author": {
"name": "Michael Mathews",
"email": "micmath@gmail.com"
},
"contributors": [
{
"url": "https://github.com/jsdoc3/jsdoc/graphs/contributors"
}
],
"maintainers": {
"name": "Jeff Williams",
"email": "jeffrey.l.williams@gmail.com"
}
}

View file

@ -0,0 +1,82 @@
/*global desc: true, fail: true, Mustache: true, task: true */
// see: https://github.com/mde/jake
desc('Updating package.json revision.');
task('default', [], function(params) {
/*jshint evil: true */
var fs = require('fs');
// import the Mustache template tool
eval(fs.readFileSync('Jake/lib/mustache.js', 'utf8'));
var templates = {
packagejson : fs.readFileSync('Jake/templates/package.json.tmpl', 'utf8')
};
var metadata = {
appname : 'jsdoc',
appversion : '3.2.0-dev',
timestamp : '' + new Date().getTime()
};
var outdir = './';
var rendered = Mustache.to_html(templates.packagejson, metadata);
fs.writeFileSync(outdir + 'package.json', rendered, 'utf8');
process.exit(0);
});
desc('Installs a plugin/template.');
task('install', [], function(loc) {
var fs = require('fs'),
util = require('util'),
path = require('path'),
wrench = require('wrench');
if(!loc) {
fail("You must specify the location of the plugin/template.");
}
if(!fs.existsSync(loc)) {
fail("plugin/template location [" + loc + "] is not valid.");
}
var pluginLoc = path.join(loc, "plugins"),
templateLoc = path.join(loc, "templates"),
jsdocLoc = process.cwd(),
name,
config;
//First the plugin
if(fs.existsSync(pluginLoc)) {
//copy it over
wrench.copyDirSyncRecursive(pluginLoc, path.join(jsdocLoc, "plugins"), {
preserve : true
});
//find out what it's called
name = fs.readdirSync(pluginLoc)[0].replace(".js", "");
//And finally edit the conf.json
try {
config = JSON.parse(fs.readFileSync(path.join(jsdocLoc, 'conf.json'), 'utf8'));
if(config.plugins.indexOf('plugins/' + name) == -1) {
config.plugins.push('plugins/' + name);
fs.writeFileSync(path.join(jsdocLoc, 'conf.json'), JSON.stringify(config, null, " "), 'utf8');
}
} catch (e) {
fail("Could not edit the conf.json file: " + e);
}
}
//Then the template
if(fs.existsSync(templateLoc)) {
wrench.copyDirSyncRecursive(templateLoc, path.join(jsdocLoc, "templates"), {
preserve : true
});
}
process.exit(0);
});

View file

@ -0,0 +1,344 @@
# License #
JSDoc 3 is free software, licensed under the Apache License, Version 2.0 (the
"License"). Commercial and non-commercial use are permitted in compliance with
the License.
Copyright (c) 2011-2012 Michael Mathews <micmath@gmail.com>
All rights reserved.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
In addition, a copy of the License is included with this distribution.
As stated in Section 7, "Disclaimer of Warranty," of the License:
> Licensor provides the Work (and each Contributor provides its Contributions)
> on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
> express or implied, including, without limitation, any warranties or
> conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
> PARTICULAR PURPOSE. You are solely responsible for determining the
> appropriateness of using or redistributing the Work and assume any risks
> associated with Your exercise of mpermissions under this License.
The source code for JSDoc 3 is available at:
https://github.com/jsdoc3/jsdoc
# Third-Party Software #
JSDoc 3 includes or depends upon the following third-party software, either in
whole or in part. Each third-party software package is provided under its own
license.
## MIT License ##
Several of the following software packages are distributed under the MIT
license, which is reproduced below:
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
## Async.js ##
Async.js is distributed under the MIT license, which is reproduced above.
Copyright (c) 2010 Caolan McMahon.
The source code for Async.js is available at:
https://github.com/caolan/async
## Catharsis ##
Catharsis is distributed under the MIT license, which is reproduced above.
Copyright (c) 2012-2013 Jeff Williams.
The source code for Catharsis is available at:
https://github.com/hegemonic/catharsis
## crypto-browserify ##
License information for crypto-browserify is not available. It is assumed that
the package is distributed under the MIT license or a similar open source
license.
The source code for crypto-browserify is available at:
https://github.com/dominictarr/crypto-browserify
## github-flavored-markdown ##
github-flavored-markdown is distributed under the BSD 3-clause license:
> Copyright (c) 2007, John Fraser <http://www.attacklab.net/> All rights
> reserved.
>
> Original Markdown copyright (c) 2004, John Gruber <http://daringfireball.net/>
> All rights reserved.
>
> Redistribution and use in source and binary forms, with or without
> modification, are permitted provided that the following conditions are met:
>
> - Redistributions of source code must retain the above copyright notice,
> this list of conditions and the following disclaimer.
>
> - Redistributions in binary form must reproduce the above copyright notice,
> this list of conditions and the following disclaimer in the documentation
> and/or other materials provided with the distribution.
> - Neither the name "Markdown" nor the names of its contributors may be used
> to endorse or promote products derived from this software without specific
> prior written permission.
>
> This software is provided by the copyright holders and contributors "as is"
> and any express or implied warranties, including, but not limited to, the
> implied warranties of merchantability and fitness for a particular purpose are
> disclaimed. In no event shall the copyright owner or contributors be liable
> for any direct, indirect, incidental, special, exemplary, or consequential
> damages (including, but not limited to, procurement of substitute goods or
> services; loss of use, data, or profits; or business interruption) however
> caused and on any theory of liability, whether in contract, strict liability,
> or tort (including negligence or otherwise) arising in any way out of the use
> of this software, even if advised of the possibility of such damage.
The source code for github-flavored-markdown is available at:
https://github.com/hegemonic/github-flavored-markdown
## Google Code Prettify ##
Google Code Prettify is distributed under the Apache License 2.0, which is
included with this package.
Copyright (c) 2006 Google Inc.
The source code for Google Code Prettify is available at:
https://code.google.com/p/google-code-prettify/
## Jasmine ##
Jasmine is distributed under the MIT license, which is reproduced above.
Copyright (c) 2008-2011 Pivotal Labs.
The source code for Jasmine is available at:
https://github.com/pivotal/jasmine
## jasmine-node ##
jasmine-node is distributed under the MIT license, which is reproduced above.
Copyright (c) 2010 Adam Abrons and Misko Hevery (http://getangular.com).
The source code for jasmine-node is available at:
https://github.com/mhevery/jasmine-node
## js2xmlparser ##
js2xmlparser is distributed under the MIT license, which is reproduced above.
Copyright (c) 2012 Michael Kourlas.
The source code for js2xmlparser is available at:
https://github.com/michaelkourlas/node-js2xmlparser
## JSHint ##
JSHint is distributed under the MIT license, which is reproduced above.
Portions of JSHint are derived from JSLint, which is distributed under a
modified MIT license:
> Copyright (c) 2002 Douglas Crockford (www.JSLint.com)
>
> Permission is hereby granted, free of charge, to any person obtaining a copy
> of this software and associated documentation files (the "Software"), to deal
> in the Software without restriction, including without limitation the rights
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> copies of the Software, and to permit persons to whom the Software is
> furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all
> copies or substantial portions of the Software.
>
> The Software shall be used for Good, not Evil.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> SOFTWARE.
The source code for JSHint is available at:
https://github.com/jshint/jshint
## markdown-js ##
markdown-js is distributed under the MIT license, which is reproduced above.
Copyright (c) 2009-2010 Dominic Baggott. Copyright (c) 2009-2010 Ash Berlin.
Copyright (c) 2011 Christoph Dorn <christoph@christophdorn.com>
(http://www.christophdorn.com).
The source code for markdown-js is available at:
https://github.com/evilstreak/markdown-js
## Node.js ##
Portions of the Node.js source code are incorporated into the following files:
- `rhino/fs.js`
- `rhino/path.js`
- `rhino/querystring.js`
- `rhino/util.js`
Node.js is distributed under the MIT license, which is reproduced above.
Copyright Joyent, Inc. and other Node contributors. All rights reserved.
The source code for Node.js is available at:
https://github.com/joyent/node
## node-browserify ##
Portions of the node-browserify source code are incorporated into the following
files:
- `rhino/events.js`
node-browserify is distributed under the MIT license, which is reproduced above.
The source code for node-browserify is available at:
https://github.com/substack/node-browserify
## TaffyDB ##
TaffyDB is distributed under a modified BSD license:
> All rights reserved.
>
> Redistribution and use of this software in source and binary forms, with or
> without modification, are permitted provided that the following condition is
> met:
>
> Redistributions of source code must retain the above copyright notice, this
> list of conditions and the following disclaimer.
>
> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
> LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
> SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
> INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
> CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
> ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
> POSSIBILITY OF SUCH DAMAGE.
The source code for TaffyDB is available at:
https://github.com/hegemonic/taffydb
## Tomorrow Theme for Google Code Prettify ##
License information for the Tomorrow Theme for Google Code Prettify is not
available. It is assumed that the package is distributed under an open source
license that is compatible with the Apache License 2.0.
Copyright (c) Yoshihide Jimbo.
The source code for the Tomorrow Theme is available at:
https://github.com/jmblog/color-themes-for-google-code-prettify
## Rhino ##
Rhino is distributed under the following licenses:
### MPL/GPL License ###
The majority of the source code for Rhino is available under a MPL 1.1/GPL 2.0
license. JSDoc 3 uses the source code under the MPL 1.1 license, which is
included in this distribution.
### License for portions of the Rhino debugger ###
Additionally, some files are available under the BSD 3-clause license:
> Copyright 1997, 1998 Sun Microsystems, Inc. All Rights Reserved.
>
> Redistribution and use in source and binary forms, with or without
> modification, are permitted provided that the following conditions are met:
>
> - Redistributions of source code must retain the above copyright notice,
> this list of conditions and the following disclaimer.
> - Redistributions in binary form must reproduce the above copyright
> notice, this list of conditions and the following disclaimer in the
> documentation and/or other materials provided with the distribution.
> - Neither the name of Sun Microsystems nor the names of its contributors
> may be used to endorse or promote products derived from this software
> without specific prior written permission.
>
> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
> FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
> SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
> CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
> OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
### Source Code ###
The source code for Rhino is available at:
https://github.com/hegemonic/rhino
## Underscore.js ##
Underscore.js is distributed under the MIT license, which is reproduced above.
Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud.
The source code for Underscore.js is available at:
https://github.com/documentcloud/underscore
## wrench-js ##
wrench-js is distributed under the MIT license, which is reproduced above.
Copyright (c) 2010 Ryan McGrath.
The source code for wrench-js is available at:
https://github.com/ryanmcgrath/wrench-js

View file

@ -0,0 +1,116 @@
JSDoc 3
=======
[![Build Status](https://secure.travis-ci.org/jsdoc3/jsdoc.png?branch=master)](http://travis-ci.org/jsdoc3/jsdoc)
An inline API documentation processor for JavaScript. JSDoc 3 is intended to be
an upgrade to JsDoc Toolkit (JSDoc 2).
Want to contribute to JSDoc? Please read `CONTRIBUTING.md`.
Installation
------------
Use git to clone the [official JSDoc repository](https://github.com/jsdoc3/jsdoc):
git clone git@github.com:jsdoc3/jsdoc.git
Alternatively, you can download a .zip file for the
[latest development version](https://github.com/jsdoc3/jsdoc/archive/master.zip)
or a [previous release](https://github.com/jsdoc3/jsdoc/tags).
You can also install JSDoc within a Node.js project's `node_modules` directory
using npm. To install the latest development version, change directories to your
Node.js project, then run the following command:
npm install git://github.com/jsdoc3/jsdoc.git
Or to install JSDoc globally:
npm install -g git://github.com/jsdoc3/jsdoc.git
**Note**: Although you can install JSDoc with npm, JSDoc does not currently run
on Node.js.
Usage
-----
This example assumes that your working directory is the JSDoc application base
directory:
./jsdoc yourSourceCodeFile.js
For information about the supported command-line options, use the `--help`
option.
./jsdoc --help
Generated documentation will appear in the folder specified by the
`--destination` option, or in a folder named "out" by default.
Dependencies
------------
JSDoc 3 uses the Mozilla Rhino engine, which requires Java. JSDoc 3 is known to
work with version 1.6.0_24 of Java.
JSDoc 3 uses advanced features in Mozilla Rhino that are only available in or
after version 1.7R3. In addition, JSDoc 3 requires several customizations to the
standard Rhino distribution. The customized version of Rhino is included with
JSDoc.
In rare cases, users may have their Java CLASSPATH configured to override the
included Rhino and point to an older version of Rhino instead. If this is the
case, simply correct the CLASSPATH to remove the older Rhino. (On OS X, you may
need to remove the file `~/Library/Java/Extensions/js.jar`.)
The version of Rhino distributed with JSDoc 3 can be found here:
https://github.com/hegemonic/rhino
Debugging
---------
Rhino is not always very friendly when it comes to reporting errors in
JavaScript. Luckily, it comes with a full-on debugger included that can be much
more useful than a simple stack trace. To invoke JSDoc with the debugger, run
the following command on Windows:
jsdoc --debug
Or on OS X, Linux, and other POSIX-compliant systems:
./jsdoc --debug
If you can't get the short-form commands to work, try invoking Java directly:
java -cp lib/js.jar org.mozilla.javascript.tools.debugger.Main \
-debug -modules node_modules -modules rhino -modules lib -modules . \
jsdoc.js your/script.js
Note: `--debug` must be the first argument to the short-form command.
This will open a debugging window. Click Debug > Break on Exceptions, then click
Run. If there is an error, you should see exactly where it is in the source
code.
See Also
--------
Project Documentation: <http://usejsdoc.org/> (under development)
Project Documentation Source: <https://github.com/jsdoc3/jsdoc3.github.com>
JSDoc User's Group: <http://groups.google.com/group/jsdoc-users>
JSDoc 3 Ant Task: <https://github.com/jannon/jsdoc3-ant-task>
Project Announcements: <http://twitter.com/jsdoc3>
License
-------
JSDoc 3 is copyright (c) 2011-2012 Michael Mathews <micmath@gmail.com>.
JSDoc 3 is free software, licensed under the Apache License, Version 2.0. See
the file `LICENSE.md` in this distribution for more details.

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,17 @@
{
"tags": {
"allowUnknownTags": true
},
"source": {
"includePattern": ".+\\.js(doc)?$",
"excludePattern": "(^|\\/|\\\\)_"
},
"plugins": [],
"templates": {
"cleverLinks": false,
"monospaceLinks": false,
"default": {
"outputSourceFiles": true
}
}
}

View file

@ -0,0 +1,122 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: app</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: app</h1>
<section>
<header>
<h2>
app
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Data that must be shared across the entire application.</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line82">line 82</a>
</li></ul></dd>
</dl>
</div>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="app.html">app</a></li><li><a href="env.html">env</a></li></ul><h3>Global</h3><ul><li><a href="global.html#main">main</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:20:54 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,720 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Class: bookAppointment</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Class: bookAppointment</h1>
<section>
<header>
<h2>
bookAppointment
</h2>
<div class="class-description">Implelements the js part of the appointment booking page.</div>
</header>
<article>
<div class="container-overview">
<dt>
<h4 class="name" id="bookAppointment"><span class="type-signature"></span>new bookAppointment<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
This class implements the book appointment page functionality.
Once the initialize() method is called the page is fully functional
and can serve the appointment booking process.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line8">line 8</a>
</li></ul></dd>
</dl>
</dd>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="bindEventHandlers"><span class="type-signature">&lt;static> </span>bindEventHandlers<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
This method binds the necessary event handlers
for the book appointments page.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line55">line 55</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="calcEndDatetime"><span class="type-signature">&lt;static> </span>calcEndDatetime<span class="signature">()</span><span class="type-signature"> &rarr; {string}</span></h4>
</dt>
<dd>
<div class="description">
This method calculates the end datetime of the current appointment.
End datetime is depending on the service and start datetime fieldss.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line288">line 288</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Returns the end datetime in string format.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">string</span>
</dd>
</dl>
</dd>
<dt>
<h4 class="name" id="getAvailableHours"><span class="type-signature">&lt;static> </span>getAvailableHours<span class="signature">(selDate)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
This function makes an ajax call and returns the available
hours for the selected service, provider and date.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>selDate</code></td>
<td class="type">
<span class="param-type">string</span>
</td>
<td class="description last">The selected date of which the available
hours we need to receive.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line155">line 155</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="initialize"><span class="type-signature">&lt;static> </span>initialize<span class="signature">(bindEventHandlers)</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
This method initializes the book appointment page.
</div>
<h5>Parameters:</h5>
<table class="params">
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td class="name"><code>bindEventHandlers</code></td>
<td class="type">
<span class="param-type">bool</span>
</td>
<td class="description last">(OPTIONAL) Determines wether
the default event handlers will be binded to the dom elements.</td>
</tr>
</tbody>
</table>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line15">line 15</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="updateConfirmData"><span class="type-signature">&lt;static> </span>updateConfirmData<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Every time this function is executed, it updates the confirmation
page with the latest customer settigns and input for the appointment
booking.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line233">line 233</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="validateCustomerDataForm"><span class="type-signature">&lt;static> </span>validateCustomerDataForm<span class="signature">()</span><span class="type-signature"> &rarr; {bool}</span></h4>
</dt>
<dd>
<div class="description">
This function validates the customer's data input.
It only checks for empty fields by the time.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="book_appointment.js.html">book_appointment.js</a>, <a href="book_appointment.js.html#line214">line 214</a>
</li></ul></dd>
</dl>
<h5>Returns:</h5>
<div class="param-desc">
Returns the validation result.
</div>
<dl>
<dt>
Type
</dt>
<dd>
<span class="param-type">bool</span>
</dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="bookAppointment.html">bookAppointment</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:24:34 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,362 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: book_appointment.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: book_appointment.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/**
* This class implements the book appointment page functionality.
* Once the initialize() method is called the page is fully functional
* and can serve the appointment booking process.
*
* @class Implelements the js part of the appointment booking page.
*/
var bookAppointment = {
/**
* This method initializes the book appointment page.
*
* @param {bool} bindEventHandlers (OPTIONAL) Determines wether
* the default event handlers will be binded to the dom elements.
*/
initialize : function(bindEventHandlers) {
if (bindEventHandlers == undefined) {
bindEventHandlers = true; // Default value
}
// Initialize page's components (tooltips, datepickers etc).
$('.book-step').qtip({
position: {
my: 'top center',
at: 'bottom center'
},
style: {
classes: 'qtip-green qtip-shadow custom-qtip'
}
});
$('#select-date').datepicker({
dateFormat : 'dd-mm-yy',
minDate : 0,
defaultDate : Date.today(),
onSelect : function(dateText, instance) {
bookAppointment.getAvailableHours(dateText);
bookAppointment.updateConfirmData();
}
});
// Bind the event handlers (might not be necessary every time
// we use this class).
if (bindEventHandlers) {
bookAppointment.bindEventHandlers();
}
// Execute other necessary operations on startup.
$('#select-service').trigger('change');
},
/**
* This method binds the necessary event handlers
* for the book appointments page.
*/
bindEventHandlers : function() {
/**
* Event : Selected Provider "Changed"
*/
$('#select-provider').change(function() {
bookAppointment.getAvailableHours(Date.today().toString('dd-MM-yyyy'));
bookAppointment.updateConfirmData();
});
/**
* Event : Selected Service "Changed"
*
* When the user clicks on a service, its available providers should
* become visible.
*/
$('#select-service').change(function() {
var currServiceId = $('#select-service').val();
$('#select-provider').empty();
$.each(GlobalVariables.providers, function(indexProvider, provider) {
$.each(provider['services'], function(indexService, serviceId) {
// If the current provider is able to provide the selected
// service, add him to the listbox.
if (serviceId == currServiceId) {
var optionHtml = '&lt;option value="' + provider['id'] + '">'
+ provider['last_name'] + ' ' + provider['first_name']
+ '&lt;/option>';
$('#select-provider').append(optionHtml);
}
});
});
bookAppointment.getAvailableHours(Date.today().toString('dd-MM-yyyy'));
bookAppointment.updateConfirmData();
});
/**
* Event : Next Step Button "Clicked"
*
* This handler is triggered every time the user pressed the
* "next" button on the book wizard. Some special tasks might
* be perfomed, depending the current wizard step.
*/
$('.button-next').click(function() {
// If we are on the 3rd tab then we will need to validate the user's
// input before proceeding to the next step.
if ($(this).attr('data-step_index') == '3') {
if (!bookAppointment.validateCustomerDataForm()) {
return; // Validation failed, do not continue.
} else {
bookAppointment.updateConfirmData();
}
}
// Display the next step tab (uses jquery animation effect).
var nextTabIndex = parseInt($(this).attr('data-step_index')) + 1;
$(this).parents().eq(1).hide('fade', function() {
$('.active-step').removeClass('active-step');
$('#step-' + nextTabIndex).addClass('active-step');
$('#book-appointment-' + nextTabIndex).show('fade');
});
});
/**
* Event : Back Step Button "Clicked"
*
* This handler is triggered every time the user pressed the
* "back" button on the book wizard.
*/
$('.button-back').click(function() {
var prevTabIndex = parseInt($(this).attr('data-step_index')) - 1;
$(this).parents().eq(1).hide('fade', function() {
$('.active-step').removeClass('active-step');
$('#step-' + prevTabIndex).addClass('active-step');
$('#book-appointment-' + prevTabIndex).show('fade');
});
});
/**
* Event : Available Hour "Click"
*
* Triggered whenever the user clicks on an available hour
* for his appointment.
*/
$('#available-hours').on('click', '.available-hour', function() {
$('.selected-hour').removeClass('selected-hour');
$(this).addClass('selected-hour');
bookAppointment.updateConfirmData();
});
},
/**
* This function makes an ajax call and returns the available
* hours for the selected service, provider and date.
*
* @param {string} selDate The selected date of which the available
* hours we need to receive.
*/
getAvailableHours : function(selDate) {
// Find the selected service duration (it is going to
// be send within the "postData" object.
var selServiceDuration = 15; // Default value of duration (in minutes).
$.each(GlobalVariables.services, function(index, service) {
if (service['id'] == $('#select-service').val()) {
selServiceDuration = service['duration'];
}
});
var postData = {
'service_id' : $('#select-service').val(),
'provider_id' : $('#select-provider').val(),
'selected_date' : selDate,
'service_duration' : selServiceDuration
};
// Make ajax post request and get the available hours.
var ajaxurl = GlobalVariables.baseUrl + 'appointments/ajax_get_available_hours';
jQuery.post(ajaxurl, postData, function(postResponse) {
////////////////////////////////////////////////////////////////////////////////
console.log('\n\n Get Available Hours Post Response :', postResponse, '\n\n');
////////////////////////////////////////////////////////////////////////////////
try {
var jsonResponse = jQuery.parseJSON(postResponse);
////////////////////////////////////////////////////////////////////////////////
//console.log('\n\n Get Available Hours JSON Response :', jsonResponse, '\n\n');
////////////////////////////////////////////////////////////////////////////////
// Fill the available time div
var currColumn = 1;
$('#available-hours').html('&lt;div style="width:50px; float:left;">&lt;/div>');
$.each(jsonResponse, function(index, availableHour) {
if ((currColumn * 10) &lt; (index + 1)) {
currColumn++;
$('#available-hours').append('&lt;div style="width:50px; float:left;">&lt;/div>');
}
$('#available-hours div:eq(' + (currColumn - 1) + ')')
.append('&lt;span class="available-hour">' + availableHour + '&lt;/span>&lt;br/>');
});
// Set the first item as selected.
$('.available-hour:eq(0)').addClass('selected-hour');
bookAppointment.updateConfirmData();
} catch(exception) {
GeneralFunctions.displayMessageBox('Unexpected Error', 'An unexpected error occured '
+ 'during the available hours calculation. Please refresh the page and try again.');
}
});
},
/**
* This function validates the customer's data input.
* It only checks for empty fields by the time.
*
* @return {bool} Returns the validation result.
*/
validateCustomerDataForm : function() {
var validationResult = true;
$('.required').css('border', '');
$('.required').each(function() {
if ($(this).val() == '') {
validationResult = false;
$(this).css('border', '2px solid red');
}
});
return validationResult;
},
/**
* Every time this function is executed, it updates the confirmation
* page with the latest customer settigns and input for the appointment
* booking.
*/
updateConfirmData : function() {
/*** SET APPOINTMENT INFO ***/
var selectedDate = $('#select-date').datepicker('getDate');
if (selectedDate !== null) {
selectedDate = Date.parse(selectedDate).toString('dd-MM-yyyy');
}
$('#appointment-info').html(
'&lt;h4>' + $('#select-service option:selected').text() + '&lt;/h4>' +
$('#select-provider option:selected').text() + '&lt;br/>' +
'&lt;strong class="text-info">' + selectedDate + ' '
+ $('.selected-hour').text() + '&lt;/strong>'
);
/*** SET CUSTOMER'S INFO ***/
$('#customer-info').html(
'&lt;h4>' + $('#last-name').val() + ' ' + $('#first-name').val() + '&lt;/h4>' +
'Phone: ' + $('#phone-number').val() + '&lt;br/>' +
'Email: ' + $('#email').val() + '&lt;br/>' +
'Address: ' + $('#address').val() + '&lt;br/>' +
'City: ' + $('#city').val() + '&lt;br/>' +
'Zip Code: ' + $('#zip-code').val()
);
/*** UPDATE FORM POST DATA ***/
var postData = new Object();
postData['customer'] = {
'last_name' : $('#last-name').val(),
'first_name' : $('#first-name').val(),
'email' : $('#email').val(),
'phone_number' : $('#phone-number').val(),
'address' : $('#address').val(),
'city' : $('#city').val(),
'zip_code' : $('#zip-code').val()
};
postData['appointment'] = {
'start_datetime' : $('#select-date').datepicker('getDate').toString('yyyy-MM-dd')
+ ' ' + $('.selected-hour').text() + ':00',
'end_datetime' : bookAppointment.calcEndDatetime(),
'notes' : $('#notes').val(),
'id_users_provider' : $('#select-provider').val(),
'id_services' : $('#select-service').val()
};
$('input[name="post_data"]').val(JSON.stringify(postData));
},
/**
* This method calculates the end datetime of the current appointment.
* End datetime is depending on the service and start datetime fieldss.
*
* @return {string} Returns the end datetime in string format.
*/
calcEndDatetime : function() {
// Find selected service duration.
var selServiceDuration = undefined;
$.each(GlobalVariables.services, function(index, service) {
if (service.id == $('#select-service').val()) {
selServiceDuration = service.duration;
return; // Stop searching ...
}
});
// Add the duration to the start datetime.
var startDatetime = $('#select-date').datepicker('getDate').toString('dd-MM-yyyy')
+ ' ' + $('.selected-hour').text();
startDatetime = Date.parseExact(startDatetime, 'dd-MM-yyyy HH:mm');
var endDatetime = undefined;
if (selServiceDuration !== undefined && startDatetime !== null) {
endDatetime = startDatetime.add({ 'minutes' : parseInt(selServiceDuration) });
} else {
endDatetime = new Date();
}
return endDatetime.toString('yyyy-MM-dd HH:mm:ss');
}
}</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="bookAppointment.html">bookAppointment</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:24:34 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,441 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Namespace: env</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Namespace: env</h1>
<section>
<header>
<h2>
env
</h2>
</header>
<article>
<div class="container-overview">
<div class="description">Data representing the environment in which this app is running.</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line8">line 8</a>
</li></ul></dd>
</dl>
</div>
<h3 class="subsection-title">Members</h3>
<dl>
<dt>
<h4 class="name" id="args"><span class="type-signature">&lt;static> </span>args<span class="type-signature"> :Array</span></h4>
</dt>
<dd>
<div class="description">
The command-line arguments passed into JSDoc.
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Array</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line35">line 35</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="conf"><span class="type-signature">&lt;static> </span>conf<span class="type-signature"> :Object</span></h4>
</dt>
<dd>
<div class="description">
The parsed JSON data from the configuration file.
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line43">line 43</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="opts"><span class="type-signature">&lt;static> </span>opts<span class="type-signature"> :Object</span></h4>
</dt>
<dd>
<div class="description">
The command-line arguments, parsed into a key/value hash.
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line62">line 62</a>
</li></ul></dd>
</dl>
<h5>Example</h5>
<pre class="prettyprint"><code> if (env.opts.help) { console.log('Helpful message.'); }</code></pre>
</dd>
<dt>
<h4 class="name" id="run"><span class="type-signature">&lt;static> </span>run<span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Running start and finish times.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line24">line 24</a>
</li></ul></dd>
</dl>
</dd>
<dt>
<h4 class="name" id="version"><span class="type-signature">&lt;static> </span>version<span class="type-signature"> :Object</span></h4>
</dt>
<dd>
<div class="description">
The JSDoc version number and revision date.
</div>
<h5>Type:</h5>
<ul>
<li>
<span class="param-type">Object</span>
</li>
</ul>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line70">line 70</a>
</li></ul></dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="app.html">app</a></li><li><a href="env.html">env</a></li></ul><h3>Global</h3><ul><li><a href="global.html#main">main</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:20:54 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,195 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Global</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Global</h1>
<section>
<header>
<h2>
</h2>
</header>
<article>
<div class="container-overview">
<dl class="details">
</dl>
</div>
<h3 class="subsection-title">Methods</h3>
<dl>
<dt>
<h4 class="name" id="main"><span class="type-signature"></span>main<span class="signature">()</span><span class="type-signature"></span></h4>
</dt>
<dd>
<div class="description">
Run the jsdoc application.
</div>
<dl class="details">
<dt class="tag-source">Source:</dt>
<dd class="tag-source"><ul class="dummy"><li>
<a href="jsdoc.js.html">jsdoc.js</a>, <a href="jsdoc.js.html#line117">line 117</a>
</li></ul></dd>
<dt class="tag-todo">To Do:</dt>
<dd class="tag-todo">
<ul>
<li>Refactor function (and require statements) into smaller functions</li>
</ul>
</dd>
</dl>
</dd>
</dl>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="app.html">app</a></li><li><a href="env.html">env</a></li></ul><h3>Global</h3><ul><li><a href="global.html#main">main</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:20:54 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Index</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Index</h1>
<h3> </h3>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Classes</h3><ul><li><a href="bookAppointment.html">bookAppointment</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:24:34 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,358 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>JSDoc: Source: jsdoc.js</title>
<script src="scripts/prettify/prettify.js"> </script>
<script src="scripts/prettify/lang-css.js"> </script>
<!--[if lt IE 9]>
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
</head>
<body>
<div id="main">
<h1 class="page-title">Source: jsdoc.js</h1>
<section>
<article>
<pre class="prettyprint source"><code>/*global app: true, args: true, env: true, publish: true */
/**
* @project jsdoc
* @author Michael Mathews &lt;micmath@gmail.com>
* @license See LICENSE.md file included in this distribution.
*/
// try: $ java -classpath build-files/java/classes/js.jar org.mozilla.javascript.tools.shell.Main main.js `pwd` script/to/parse.js
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Data representing the environment in which this app is running.
*
* @namespace
* @name env
*/
require('lib/jsdoc/util/global').env = {
/**
* Running start and finish times.
*
* @memberof env
*/
run: {
start: new Date(),
finish: null
},
/**
* The command-line arguments passed into JSDoc.
*
* @type Array
* @memberof env
*/
args: [],
/**
* The parsed JSON data from the configuration file.
*
* @type Object
* @memberof env
*/
conf: {},
/**
* The absolute path to the base directory of the JSDoc application.
*
* @private
* @deprecated Use `__dirname` instead.
* @type string
* @memberof env
*/
dirname: '.',
/**
* The command-line arguments, parsed into a key/value hash.
*
* @type Object
* @memberof env
* @example if (env.opts.help) { console.log('Helpful message.'); }
*/
opts: {},
/**
* The JSDoc version number and revision date.
*
* @type Object
* @memberof env
*/
version: {}
};
// initialize the environment for the current JavaScript VM
(function(args) {
var vm = require('jsdoc/util/vm').vm;
// TODO: may need to move this file to support Node.js
require('initialize')[vm](args);
})( Array.prototype.slice.call(arguments, 0) );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Data that must be shared across the entire application.
* @namespace
* @name app
*/
require('lib/jsdoc/util/global').app = {
jsdoc: {
scanner: new (require('jsdoc/src/scanner').Scanner)(),
parser: new (require('jsdoc/src/parser').Parser)(),
name: require('jsdoc/name')
}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
Try to recursively print out all key/values in an object.
@global
@private
@param {Object} ... Object/s to dump out to console.
*/
function dump() {
var doop = require('jsdoc/util/doop').doop;
var _dump = require('jsdoc/util/dumper').dump;
for (var i = 0, l = arguments.length; i &lt; l; i++) {
console.log( _dump(doop(arguments[i])) );
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Run the jsdoc application.
* @todo Refactor function (and require statements) into smaller functions
*/
function main() {
var _ = require('underscore');
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var taffy = require('taffydb').taffy;
var jsdoc = {
augment: require('jsdoc/augment'),
borrow: require('jsdoc/borrow'),
Config: require('jsdoc/config'),
opts: {
args: require('jsdoc/opts/args')
},
'package': require('jsdoc/package'),
plugins: require('jsdoc/plugins'),
Readme: require('jsdoc/readme'),
src: {
filter: require('jsdoc/src/filter'),
handlers: require('jsdoc/src/handlers')
},
tutorial: {
resolver: require('jsdoc/tutorial/resolver')
},
util: {
include: require('jsdoc/util/include')
}
};
var confPath;
var defaultOpts;
var docs;
var filter;
var i;
var info;
var l;
var packageDocs;
var packageJson;
var sourceFiles;
var template;
defaultOpts = {
destination: './out/',
encoding: 'utf8'
};
// get JSDoc version number
info = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
env.version = {
number: info.version,
revision: new Date(parseInt(info.revision, 10)).toUTCString()
};
env.opts = jsdoc.opts.args.parse(env.args);
confPath = env.opts.configure || path.join(__dirname, 'conf.json');
if ( !fs.statSync(confPath).isFile() ) {
confPath = path.join(__dirname, 'conf.json.EXAMPLE');
}
try {
env.conf = new jsdoc.Config( fs.readFileSync(confPath, 'utf8') )
.get();
}
catch (e) {
throw new Error('Cannot parse the config file ' + confPath + ': ' + e);
}
// look for options on the command line, in the config file, and in the defaults, in that order
env.opts = _.defaults(env.opts, env.conf.opts, defaultOpts);
if (env.opts.help) {
console.log( jsdoc.opts.args.help() );
process.exit(0);
} else if (env.opts.test) {
jsdoc.util.include('test/runner.js');
process.exit(0);
} else if (env.opts.version) {
console.log('JSDoc ' + env.version.number + ' (' + env.version.revision + ')');
process.exit(0);
}
if (env.conf.plugins) {
jsdoc.plugins.installPlugins(env.conf.plugins, app.jsdoc.parser);
}
if (env.conf.source && env.conf.source.include) {
env.opts._ = (env.opts._ || []).concat(env.conf.source.include);
}
// any source file named package.json or README.md is treated special
for (i = 0, l = env.opts._.length; i &lt; l; i++ ) {
if (/\bpackage\.json$/i.test(env.opts._[i])) {
packageJson = fs.readFileSync( env.opts._[i], 'utf8' );
env.opts._.splice(i--, 1);
}
if (/(\bREADME|\.md)$/i.test(env.opts._[i])) {
env.opts.readme = new jsdoc.Readme(env.opts._[i]).html;
env.opts._.splice(i--, 1);
}
}
if (env.conf.source && env.opts._.length > 0) { // are there any files to scan and parse?
filter = new jsdoc.src.filter.Filter(env.conf.source);
sourceFiles = app.jsdoc.scanner.scan(env.opts._, (env.opts.recurse? 10 : undefined), filter);
jsdoc.src.handlers.attachTo(app.jsdoc.parser);
docs = app.jsdoc.parser.parse(sourceFiles, env.opts.encoding);
//The files are ALWAYS useful for the templates to have
//If there is no package.json, just create an empty package
packageDocs = new jsdoc.package.Package(packageJson);
packageDocs.files = sourceFiles || [];
docs.push(packageDocs);
jsdoc.borrow.indexAll(docs);
jsdoc.augment.addInherited(docs);
jsdoc.borrow.resolveBorrows(docs);
if (env.opts.explain) {
dump(docs);
process.exit(0);
}
if (env.opts.tutorials) {
jsdoc.tutorial.resolver.load(env.opts.tutorials);
jsdoc.tutorial.resolver.resolve();
}
env.opts.template = (function() {
var publish = env.opts.template || 'templates/default';
// if we don't find it, keep the user-specified value so the error message is useful
return path.getResourcePath(publish) || env.opts.template;
})();
try {
template = require(env.opts.template + '/publish');
}
catch(e) {
throw new Error('Unable to load template: ' + e.message || e);
}
// templates should include a publish.js file that exports a "publish" function
if (template.publish && typeof template.publish === 'function') {
// convert this from a URI back to a path if necessary
env.opts.template = path._uriToPath(env.opts.template);
template.publish(
taffy(docs),
env.opts,
jsdoc.tutorial.resolver.root
);
}
else {
// old templates define a global "publish" function, which is deprecated
jsdoc.util.include(env.opts.template + '/publish.js');
if (publish && typeof publish === 'function') {
console.log( env.opts.template + ' uses a global "publish" function, which is ' +
'deprecated and may not be supported in future versions. ' +
'Please update the template to use "exports.publish" instead.' );
// convert this from a URI back to a path if necessary
env.opts.template = path._uriToPath(env.opts.template);
publish(
taffy(docs),
env.opts,
jsdoc.tutorial.resolver.root
);
}
else {
throw new Error( env.opts.template + ' does not export a "publish" function.' );
}
}
}
}
try {
main();
env.run.finish = new Date();
process.exit(0);
}
catch(e) {
env.run.finish = new Date();
if (e.rhinoException != null) {
e.rhinoException.printStackTrace();
process.exit(1);
} else {
throw e;
}
}
</code></pre>
</article>
</section>
</div>
<nav>
<h2><a href="index.html">Index</a></h2><h3>Namespaces</h3><ul><li><a href="app.html">app</a></li><li><a href="env.html">env</a></li></ul><h3>Global</h3><ul><li><a href="global.html#main">main</a></li></ul>
</nav>
<br clear="both">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.2.0-dev</a> on Mon May 20 2013 17:20:54 GMT+0300 (EEST)
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View file

@ -0,0 +1,17 @@
(function() {
var counter = 0;
var numbered;
var source = document.getElementsByClassName('prettyprint source');
if (source && source[0]) {
source = source[0].getElementsByTagName('code')[0];
numbered = source.innerHTML.split('\n');
numbered = numbered.map(function(item) {
counter++;
return '<span id="line' + counter + '"></span>' + item;
});
source.innerHTML = numbered.join('\n');
}
})();

View file

@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,2 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

View file

@ -0,0 +1,28 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

View file

@ -0,0 +1,283 @@
html
{
overflow: auto;
background-color: #fff;
}
body
{
font: 14px "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans serif;
line-height: 130%;
color: #000;
background-color: #fff;
}
a {
color: #444;
}
a:visited {
color: #444;
}
a:active {
color: #444;
}
header
{
display: block;
padding: 6px 4px;
}
.class-description {
font-style: italic;
font-family: Palatino, 'Palatino Linotype', serif;
font-size: 130%;
line-height: 140%;
margin-bottom: 1em;
margin-top: 1em;
}
#main {
float: left;
width: 100%;
}
section
{
display: block;
background-color: #fff;
padding: 12px 24px;
border-bottom: 1px solid #ccc;
margin-right: 240px;
}
.variation {
display: none;
}
.optional:after {
content: "opt";
font-size: 60%;
color: #aaa;
font-style: italic;
font-weight: lighter;
}
nav
{
display: block;
float: left;
margin-left: -230px;
margin-top: 28px;
width: 220px;
border-left: 1px solid #ccc;
padding-left: 9px;
}
nav ul {
font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
font-size: 100%;
line-height: 17px;
padding:0;
margin:0;
list-style-type:none;
}
nav h2 a, nav h2 a:visited {
color: #A35A00;
text-decoration: none;
}
nav h3 {
margin-top: 12px;
}
nav li {
margin-top: 6px;
}
nav a {
color: #5C5954;
}
nav a:visited {
color: #5C5954;
}
nav a:active {
color: #5C5954;
}
footer {
display: block;
padding: 6px;
margin-top: 12px;
font-style: italic;
font-size: 90%;
}
h1
{
font-size: 200%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 6px 0 9px 0;
}
h2
{
font-size: 170%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
}
h3
{
font-size: 150%;
font-weight: bold;
letter-spacing: -0.01em;
margin-top: 16px;
margin: 6px 0 3px 0;
}
h4
{
font-size: 130%;
font-weight: bold;
letter-spacing: -0.01em;
margin-top: 16px;
margin: 18px 0 3px 0;
color: #A35A00;
}
h5, .container-overview .subsection-title
{
font-size: 120%;
font-weight: bold;
letter-spacing: -0.01em;
margin: 8px 0 3px -16px;
}
h6
{
font-size: 100%;
letter-spacing: -0.01em;
margin: 6px 0 3px 0;
font-style: italic;
}
.ancestors { color: #999; }
.ancestors a
{
color: #999 !important;
text-decoration: none;
}
.important
{
font-weight: bold;
color: #950B02;
}
.yes-def {
text-indent: -1000px;
}
.type-signature {
color: #aaa;
}
.name, .signature {
font-family: Consolas, "Lucida Console", Monaco, monospace;
}
.details { margin-top: 14px; }
.details dt { width:100px; float:left; border-left: 2px solid #DDD; padding-left: 10px; padding-top: 6px; }
.details dd { margin-left: 50px; }
.details ul { margin: 0; }
.details ul { list-style-type: none; }
.details li { margin-left: 30px; padding-top: 6px; }
.description {
margin-bottom: 1em;
margin-left: -16px;
margin-top: 1em;
}
.code-caption
{
font-style: italic;
font-family: Palatino, 'Palatino Linotype', serif;
font-size: 107%;
margin: 0;
}
.prettyprint
{
border: 1px solid #ddd;
width: 80%;
overflow: auto;
}
.prettyprint.source {
width: inherit;
}
.prettyprint code
{
font-family: Consolas, 'Lucida Console', Monaco, monospace;
font-size: 100%;
line-height: 18px;
display: block;
padding: 4px 12px;
margin: 0;
background-color: #fff;
color: #000;
border-left: 3px #ddd solid;
}
.params, .props
{
border-spacing: 0;
border: 0;
border-collapse: collapse;
}
.params .name, .props .name, .name code {
color: #A35A00;
font-family: Consolas, 'Lucida Console', Monaco, monospace;
font-size: 100%;
}
.params td, .params th, .props td, .props th
{
border: 1px solid #ddd;
margin: 0px;
text-align: left;
vertical-align: top;
padding: 4px 6px;
display: table-cell;
}
.params thead tr, .props thead tr
{
background-color: #ddd;
font-weight: bold;
}
.params .params thead tr, .props .props thead tr
{
background-color: #fff;
font-weight: bold;
}
.params th, .props th { border-right: 1px solid #aaa; }
.params thead .last, .props thead .last { border-right: 1px solid #ddd; }
.disabled {
color: #454545;
}

View file

@ -0,0 +1,111 @@
/* JSDoc prettify.js theme */
/* plain text */
.pln {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* string content */
.str {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a keyword */
.kwd {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a comment */
.com {
font-weight: normal;
font-style: italic;
}
/* a type name */
.typ {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* a literal value */
.lit {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* punctuation */
.pun {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* lisp open bracket */
.opn {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* lisp close bracket */
.clo {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a markup tag name */
.tag {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a markup attribute name */
.atn {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a markup attribute value */
.atv {
color: #006400;
font-weight: normal;
font-style: normal;
}
/* a declaration */
.dec {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* a variable name */
.var {
color: #000000;
font-weight: normal;
font-style: normal;
}
/* a function name */
.fun {
color: #000000;
font-weight: bold;
font-style: normal;
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}

View file

@ -0,0 +1,132 @@
/* Tomorrow Theme */
/* Original theme - https://github.com/chriskempson/tomorrow-theme */
/* Pretty printing styles. Used with prettify.js. */
/* SPAN elements with the classes below are added by prettyprint. */
/* plain text */
.pln {
color: #4d4d4c; }
@media screen {
/* string content */
.str {
color: #718c00; }
/* a keyword */
.kwd {
color: #8959a8; }
/* a comment */
.com {
color: #8e908c; }
/* a type name */
.typ {
color: #4271ae; }
/* a literal value */
.lit {
color: #f5871f; }
/* punctuation */
.pun {
color: #4d4d4c; }
/* lisp open bracket */
.opn {
color: #4d4d4c; }
/* lisp close bracket */
.clo {
color: #4d4d4c; }
/* a markup tag name */
.tag {
color: #c82829; }
/* a markup attribute name */
.atn {
color: #f5871f; }
/* a markup attribute value */
.atv {
color: #3e999f; }
/* a declaration */
.dec {
color: #f5871f; }
/* a variable name */
.var {
color: #c82829; }
/* a function name */
.fun {
color: #4271ae; } }
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str {
color: #060; }
.kwd {
color: #006;
font-weight: bold; }
.com {
color: #600;
font-style: italic; }
.typ {
color: #404;
font-weight: bold; }
.lit {
color: #044; }
.pun, .opn, .clo {
color: #440; }
.tag {
color: #006;
font-weight: bold; }
.atn {
color: #404; }
.atv {
color: #060; } }
/* Style */
/*
pre.prettyprint {
background: white;
font-family: Menlo, Monaco, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
border: 1px solid #ccc;
padding: 10px; }
*/
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0; }
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */ }
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */ }

41
data/scripts/jsdoc/jsdoc Normal file
View file

@ -0,0 +1,41 @@
#!/bin/sh
# rhino discards the path to the current script file, so we must add it back
SOURCE="$0"
while [ -h "$SOURCE" ] ; do SOURCE="$(readlink "$SOURCE")"; done
# Get a Windows path under MinGW or Cygwin
BASEPATH="$( cd -P "$( dirname "$SOURCE" )" && (pwd -W 2>/dev/null || cygpath -w $(pwd) 2>/dev/null || pwd))"
if [ "${BASEPATH%${BASEPATH#?}}" != "/" ] ; then
BASEPATH="$( echo "$BASEPATH" | sed -e 's@\\@/@g' )"
# We need a extra slash for URLs
UBASEPATH="/$BASEPATH"
else
UBASEPATH="$BASEPATH"
fi
# for whatever reason, Rhino requires module paths to be valid URIs
URLPATH="file://$UBASEPATH"
URLPATH=`echo "$URLPATH" | sed -e 's/ /%20/g'`
ENCODEDBASEPATH=`echo "$BASEPATH" | sed -e 's/ /%20/g'`
if test "$1" = "--debug"
then
echo "Running Debug"
CMD="org.mozilla.javascript.tools.debugger.Main -debug"
# strip --debug argument
shift
else
CMD="org.mozilla.javascript.tools.shell.Main"
fi
#Conditionally execute different command lines depending on whether we're running tests or not
if test "$1" = "-T"
then
echo "Running Tests"
cd -P "$(dirname "$SOURCE")"
java -classpath "${BASEPATH}/rhino/js.jar" ${CMD} -opt -1 -modules "${URLPATH}/node_modules" -modules "${URLPATH}/rhino" -modules "${URLPATH}/lib" -modules "${URLPATH}" "${BASEPATH}/jsdoc.js" "$@" --dirname="${BASEPATH}/"
else
# normal mode should be quiet
java -classpath "${BASEPATH}/rhino/js.jar" ${CMD} -modules "${URLPATH}/node_modules" -modules "${URLPATH}/rhino" -modules "${URLPATH}/lib" -modules "${URLPATH}" "${BASEPATH}/jsdoc.js" "$@" --dirname="${BASEPATH}/"
fi

View file

@ -0,0 +1,45 @@
@ECHO OFF
SETLOCAL
REM jsdoc.js expects Unix-style paths without a trailing slash
SET _BASEPATH=%~dp0
SET _BASEPATH=%_BASEPATH:\=/%
SET _BASEPATH=%_BASEPATH:~0,-1%
REM for whatever reason, Rhino requires module paths to be valid URIs
SET _URLPATH=file:/%_BASEPATH%
IF "%_URLPATH%"=="%_URLPATH: =%" GOTO NO_SPACES
:ESCAPE_SPACE
SET _TRAILING=%_URLPATH:* =%
CALL SET _URLPATH=%%_URLPATH: %_TRAILING%=%%
SET _URLPATH=%_URLPATH%%%20%_TRAILING%
IF NOT "%_URLPATH%"=="%_URLPATH: =%" GOTO ESCAPE_SPACE
:NO_SPACES
IF [%1]==[--debug] (
ECHO Running Debug
SET CMD=org.mozilla.javascript.tools.debugger.Main -debug
REM `SHIFT` doesn't affect %*
:COLLECT_ARGS
IF [%2]==[] GOTO LAST_ARG
SET ARGS=%ARGS% %2
SHIFT
GOTO COLLECT_ARGS
) ELSE (
SET CMD=org.mozilla.javascript.tools.shell.Main
SET ARGS=%*
)
:LAST_ARG
IF [%1]==[-T] (
ECHO Running Tests
java -classpath "%_BASEPATH%/rhino/js.jar" %CMD% -opt -1 -modules "%_URLPATH%/node_modules" -modules "%_URLPATH%/rhino" -modules "%_URLPATH%/lib" -modules "%_URLPATH%" "%_BASEPATH%/jsdoc.js" %ARGS% --nocolor --dirname="%_BASEPATH%/
) ELSE (
REM normal mode should be quiet
java -classpath "%_BASEPATH%/rhino/js.jar" %CMD% -modules "%_URLPATH%/node_modules" -modules "%_URLPATH%/rhino" -modules "%_URLPATH%/lib" -modules "%_URLPATH%" "%_BASEPATH%/jsdoc.js" %ARGS% --dirname="%_BASEPATH%/
)
ENDLOCAL

308
data/scripts/jsdoc/jsdoc.js Normal file
View file

@ -0,0 +1,308 @@
/*global app: true, args: true, env: true, publish: true */
/**
* @project jsdoc
* @author Michael Mathews <micmath@gmail.com>
* @license See LICENSE.md file included in this distribution.
*/
// try: $ java -classpath build-files/java/classes/js.jar org.mozilla.javascript.tools.shell.Main main.js `pwd` script/to/parse.js
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Data representing the environment in which this app is running.
*
* @namespace
* @name env
*/
require('lib/jsdoc/util/global').env = {
/**
* Running start and finish times.
*
* @memberof env
*/
run: {
start: new Date(),
finish: null
},
/**
* The command-line arguments passed into JSDoc.
*
* @type Array
* @memberof env
*/
args: [],
/**
* The parsed JSON data from the configuration file.
*
* @type Object
* @memberof env
*/
conf: {},
/**
* The absolute path to the base directory of the JSDoc application.
*
* @private
* @deprecated Use `__dirname` instead.
* @type string
* @memberof env
*/
dirname: '.',
/**
* The command-line arguments, parsed into a key/value hash.
*
* @type Object
* @memberof env
* @example if (env.opts.help) { console.log('Helpful message.'); }
*/
opts: {},
/**
* The JSDoc version number and revision date.
*
* @type Object
* @memberof env
*/
version: {}
};
// initialize the environment for the current JavaScript VM
(function(args) {
var vm = require('jsdoc/util/vm').vm;
// TODO: may need to move this file to support Node.js
require('initialize')[vm](args);
})( Array.prototype.slice.call(arguments, 0) );
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Data that must be shared across the entire application.
* @namespace
* @name app
*/
require('lib/jsdoc/util/global').app = {
jsdoc: {
scanner: new (require('jsdoc/src/scanner').Scanner)(),
parser: new (require('jsdoc/src/parser').Parser)(),
name: require('jsdoc/name')
}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
Try to recursively print out all key/values in an object.
@global
@private
@param {Object} ... Object/s to dump out to console.
*/
function dump() {
var doop = require('jsdoc/util/doop').doop;
var _dump = require('jsdoc/util/dumper').dump;
for (var i = 0, l = arguments.length; i < l; i++) {
console.log( _dump(doop(arguments[i])) );
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
/**
* Run the jsdoc application.
* @todo Refactor function (and require statements) into smaller functions
*/
function main() {
var _ = require('underscore');
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var taffy = require('taffydb').taffy;
var jsdoc = {
augment: require('jsdoc/augment'),
borrow: require('jsdoc/borrow'),
Config: require('jsdoc/config'),
opts: {
args: require('jsdoc/opts/args')
},
'package': require('jsdoc/package'),
plugins: require('jsdoc/plugins'),
Readme: require('jsdoc/readme'),
src: {
filter: require('jsdoc/src/filter'),
handlers: require('jsdoc/src/handlers')
},
tutorial: {
resolver: require('jsdoc/tutorial/resolver')
},
util: {
include: require('jsdoc/util/include')
}
};
var confPath;
var defaultOpts;
var docs;
var filter;
var i;
var info;
var l;
var packageDocs;
var packageJson;
var sourceFiles;
var template;
defaultOpts = {
destination: './out/',
encoding: 'utf8'
};
// get JSDoc version number
info = JSON.parse(fs.readFileSync(path.join(__dirname, 'package.json'), 'utf8'));
env.version = {
number: info.version,
revision: new Date(parseInt(info.revision, 10)).toUTCString()
};
env.opts = jsdoc.opts.args.parse(env.args);
confPath = env.opts.configure || path.join(__dirname, 'conf.json');
if ( !fs.statSync(confPath).isFile() ) {
confPath = path.join(__dirname, 'conf.json.EXAMPLE');
}
try {
env.conf = new jsdoc.Config( fs.readFileSync(confPath, 'utf8') )
.get();
}
catch (e) {
throw new Error('Cannot parse the config file ' + confPath + ': ' + e);
}
// look for options on the command line, in the config file, and in the defaults, in that order
env.opts = _.defaults(env.opts, env.conf.opts, defaultOpts);
if (env.opts.help) {
console.log( jsdoc.opts.args.help() );
process.exit(0);
} else if (env.opts.test) {
jsdoc.util.include('test/runner.js');
process.exit(0);
} else if (env.opts.version) {
console.log('JSDoc ' + env.version.number + ' (' + env.version.revision + ')');
process.exit(0);
}
if (env.conf.plugins) {
jsdoc.plugins.installPlugins(env.conf.plugins, app.jsdoc.parser);
}
if (env.conf.source && env.conf.source.include) {
env.opts._ = (env.opts._ || []).concat(env.conf.source.include);
}
// any source file named package.json or README.md is treated special
for (i = 0, l = env.opts._.length; i < l; i++ ) {
if (/\bpackage\.json$/i.test(env.opts._[i])) {
packageJson = fs.readFileSync( env.opts._[i], 'utf8' );
env.opts._.splice(i--, 1);
}
if (/(\bREADME|\.md)$/i.test(env.opts._[i])) {
env.opts.readme = new jsdoc.Readme(env.opts._[i]).html;
env.opts._.splice(i--, 1);
}
}
if (env.conf.source && env.opts._.length > 0) { // are there any files to scan and parse?
filter = new jsdoc.src.filter.Filter(env.conf.source);
sourceFiles = app.jsdoc.scanner.scan(env.opts._, (env.opts.recurse? 10 : undefined), filter);
jsdoc.src.handlers.attachTo(app.jsdoc.parser);
docs = app.jsdoc.parser.parse(sourceFiles, env.opts.encoding);
//The files are ALWAYS useful for the templates to have
//If there is no package.json, just create an empty package
packageDocs = new jsdoc.package.Package(packageJson);
packageDocs.files = sourceFiles || [];
docs.push(packageDocs);
jsdoc.borrow.indexAll(docs);
jsdoc.augment.addInherited(docs);
jsdoc.borrow.resolveBorrows(docs);
if (env.opts.explain) {
dump(docs);
process.exit(0);
}
if (env.opts.tutorials) {
jsdoc.tutorial.resolver.load(env.opts.tutorials);
jsdoc.tutorial.resolver.resolve();
}
env.opts.template = (function() {
var publish = env.opts.template || 'templates/default';
// if we don't find it, keep the user-specified value so the error message is useful
return path.getResourcePath(publish) || env.opts.template;
})();
try {
template = require(env.opts.template + '/publish');
}
catch(e) {
throw new Error('Unable to load template: ' + e.message || e);
}
// templates should include a publish.js file that exports a "publish" function
if (template.publish && typeof template.publish === 'function') {
// convert this from a URI back to a path if necessary
env.opts.template = path._uriToPath(env.opts.template);
template.publish(
taffy(docs),
env.opts,
jsdoc.tutorial.resolver.root
);
}
else {
// old templates define a global "publish" function, which is deprecated
jsdoc.util.include(env.opts.template + '/publish.js');
if (publish && typeof publish === 'function') {
console.log( env.opts.template + ' uses a global "publish" function, which is ' +
'deprecated and may not be supported in future versions. ' +
'Please update the template to use "exports.publish" instead.' );
// convert this from a URI back to a path if necessary
env.opts.template = path._uriToPath(env.opts.template);
publish(
taffy(docs),
env.opts,
jsdoc.tutorial.resolver.root
);
}
else {
throw new Error( env.opts.template + ' does not export a "publish" function.' );
}
}
}
}
try {
main();
env.run.finish = new Date();
process.exit(0);
}
catch(e) {
env.run.finish = new Date();
if (e.rhinoException != null) {
e.rhinoException.printStackTrace();
process.exit(1);
} else {
throw e;
}
}

View file

@ -0,0 +1,40 @@
/*global env: true */
exports.rhino = function(args) {
var myGlobal = require('jsdoc/util/global');
// note: mutates args
function getDirname() {
var dirname;
// Rhino has no native way to get the base dirname of the current script,
// so this information must be manually passed in from the command line.
for (var i = 0; i < args.length; i++) {
if ( /^--dirname(?:=(.+?)(\/|\/\.)?)?$/i.test(args[i]) ) {
if (RegExp.$1) {
dirname = RegExp.$1; // last wins
args.splice(i--, 1); // remove --dirname opt from arguments
}
else {
dirname = args[i + 1];
args.splice(i--, 2);
}
}
}
return dirname;
}
myGlobal.__dirname = env.dirname = getDirname();
env.args = args;
require('jsdoc/util/include')(__dirname + '/rhino/rhino-shim.js');
};
exports.nodejs = function(args) {
throw new Error('Node.js is not currently supported!');
/*
env.dirname = __dirname;
env.args = args;
// TODO: add lib/ to the library paths
*/
};

View file

@ -0,0 +1,138 @@
var hasOwnProp = Object.prototype.hasOwnProperty;
function mapDependencies(index) {
var doclets, doc, len, dependencies = {};
Object.keys(index).forEach(function(name) {
doclets = index[name];
for (var i = 0, ii = doclets.length; i < ii; ++i) {
doc = doclets[i];
if (doc.kind === "class" || doc.kind === "external") {
dependencies[name] = {};
len = doc.augments && doc.augments.length || 0;
for (var j = 0; j < len; ++j) {
dependencies[name][doc.augments[j]] = true;
}
}
}
});
return dependencies;
}
function Sorter(dependencies) {
this.dependencies = dependencies;
this.visited = {};
this.sorted = [];
}
Sorter.prototype.visit = function(key) {
var self = this;
if (!(key in this.visited)) {
this.visited[key] = true;
if (this.dependencies[key]) {
Object.keys(this.dependencies[key]).forEach(function(path) {
self.visit(path);
});
}
this.sorted.push(key);
}
};
Sorter.prototype.sort = function() {
var self = this;
Object.keys(this.dependencies).forEach(function(key) {
self.visit(key);
});
return this.sorted;
};
function sort(dependencies) {
var sorter = new Sorter(dependencies);
return sorter.sort();
}
function getMembers(longname, docs) {
var candidate, members = [];
for (var i = 0, ii = docs.length; i < ii; ++i) {
candidate = docs[i];
if (candidate.memberof === longname && candidate.scope === "instance") {
members.push(candidate);
}
}
return members;
}
function getAdditions(doclets, docs, longnames) {
var doop = require("jsdoc/util/doop").doop;
var additions = [];
var doc;
var parents;
var members;
var member;
var parts;
// doclets will be undefined if the inherited symbol isn't documented
doclets = doclets || [];
for (var i = 0, ii = doclets.length; i < ii; i++) {
doc = doclets[i];
parents = doc.augments;
if (parents && doc.kind === "class") {
for (var j = 0, jj = parents.length; j < jj; j++) {
members = getMembers(parents[j], docs);
for (var k = 0, kk = members.length; k < kk; k++) {
member = doop(members[k]);
member.inherits = member.longname;
member.inherited = true;
member.memberof = doc.longname;
parts = member.longname.split("#");
parts[0] = doc.longname;
member.longname = parts.join("#");
// if the child doesn't override the parent member, add the parent member
if (longnames.indexOf(member.longname) === -1) {
additions.push(member);
}
}
}
}
}
return additions;
}
exports.addInherited = function(docs) {
var dependencies = mapDependencies(docs.index);
var sorted = sort(dependencies);
var longnames = [];
// only build the list of longnames if we'll actually need it
if (sorted.length) {
longnames = docs.map(function(doc) {
if (doc.longname) {
return doc.longname;
}
});
}
sorted.forEach(function(name) {
var doclets = docs.index[name];
var additions = getAdditions(doclets, docs, longnames);
additions.forEach(function(doc) {
var name = doc.longname;
if ( !hasOwnProp.call(docs.index, name) ) {
docs.index[name] = [];
}
docs.index[name].push(doc);
docs.push(doc);
});
});
};

View file

@ -0,0 +1,65 @@
/**
A collection of functions relating to resolving @borrows tags in JSDoc symbols.
@module jsdoc/borrow
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var doop = require("jsdoc/util/doop").doop;
var hasOwnProp = Object.prototype.hasOwnProperty;
exports.indexAll = function(docs) {
var lookupTable = {};
docs.forEach(function(doc) {
if ( !hasOwnProp.call(lookupTable, doc.longname) ) {
lookupTable[doc.longname] = [];
}
lookupTable[doc.longname].push(doc);
});
docs.index = lookupTable;
};
// requires docs to have been indexed: docs.index must be defined here
/**
Take a copy of the docs for borrowed symbols and attach them to the
docs for the borrowing symbol. This process changes the symbols involved,
moving docs from the "borrowed" array and into the general docs, then
deleting the "borrowed" array.
*/
exports.resolveBorrows = function(docs) {
if (!docs.index) {
throw 'Docs has not been indexed: docs.index must be defined here.';
}
docs.forEach(function(doc) {
if (doc.borrowed) {
doc.borrowed.forEach(function(b, i) {
var lent = docs.index[b.from], // lent is an array
asName = b.as || b.from;
if (lent) {
var cloned = doop(lent);
cloned.forEach(function(clone) {
asName = asName.replace(/^prototype\./, '#');
var parts = asName.split('#');
if (parts.length === 2) { clone.scope = 'instance'; }
else { clone.scope = 'static'; }
asName = parts.pop();
clone.name = asName;
clone.memberof = doc.longname;
clone.longname = clone.memberof + (clone.scope === 'instance'? '#': '.') + clone.name;
docs.push(clone);
});
}
});
delete doc.borrowed;
}
});
};

View file

@ -0,0 +1,58 @@
/**
@overview
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
@module jsdoc/config
*/
function mergeRecurse(target, source) {
Object.keys(source).forEach(function(p) {
if ( source[p].constructor === Object ) {
if ( !target[p] ) { target[p] = {}; }
mergeRecurse(target[p], source[p]);
}
else {
target[p] = source[p];
}
});
return target;
}
// required config values, override these defaults in your config.json if necessary
const defaults = {
"tags": {
"allowUnknownTags": true
},
"templates": {
"monospaceLinks": false,
"cleverLinks": false
},
"source": {
"includePattern": ".+\\.js(doc)?$",
"excludePattern": "(^|\\/)_"
},
"plugins": []
};
/**
@class
@classdesc Represents a JSDoc application configuration.
@param {string} [json] - The contents of config.json.
*/
function Config(json) {
json = JSON.parse( (json || "{}") );
this._config = mergeRecurse(defaults, json);
}
module.exports = Config;
/**
Get the merged configuration values.
*/
Config.prototype.get = function() {
return this._config;
};

View file

@ -0,0 +1,337 @@
/**
@overview
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
@module jsdoc/doclet
@requires jsdoc/tag
@requires jsdoc/name
@requires jsdoc/tag/dictionary
*/
var jsdoc = {
tag: {
Tag: require('jsdoc/tag').Tag,
dictionary: require('jsdoc/tag/dictionary')
},
name: require('jsdoc/name')
};
var path = require('path');
function applyTag(tag) {
if (tag.title === 'name') {
this.name = tag.value;
}
if (tag.title === 'kind') {
this.kind = tag.value;
}
if (tag.title === 'description') {
this.description = tag.value;
}
if (tag.title === 'scope') {
this.scope = tag.value;
}
}
// use the meta info about the source code to guess what the doclet kind should be
function codetypeToKind(type) {
var kind = (type || '').toLowerCase();
if (kind !== 'function') {
return 'member';
}
return kind;
}
function unwrap(docletSrc) {
if (!docletSrc) { return ''; }
// note: keep trailing whitespace for @examples
// extra opening/closing stars are ignored
// left margin is considered a star and a space
// use the /m flag on regex to avoid having to guess what this platform's newline is
docletSrc =
docletSrc.replace(/^\/\*\*+/, '') // remove opening slash+stars
.replace(/\**\*\/$/, "\\Z") // replace closing star slash with end-marker
.replace(/^\s*(\* ?|\\Z)/gm, '') // remove left margin like: spaces+star or spaces+end-marker
.replace(/\s*\\Z$/g, ''); // remove end-marker
return docletSrc;
}
function split(docletSrc) {
var tagSrcs = [],
tagText,
tagTitle;
// split out the basic tags, keep surrounding whitespace
// like: @tagTitle tagBody
docletSrc
.replace(/^(\s*)@(\S)/gm, '$1\\@$2') // replace splitter ats with an arbitrary sequence
.split('\\@') // then split on that arbitrary sequence
.forEach(function($) {
if ($) {
var parsedTag = $.match(/^(\S+)(:?\s+(\S[\s\S]*))?/);
if (parsedTag) {
// we don't need parsedTag[0]
tagTitle = parsedTag[1];
tagText = parsedTag[2];
if (tagTitle) {
tagSrcs.push({
title: tagTitle,
text: tagText
});
}
}
}
});
return tagSrcs;
}
/**
Convert the raw source of the doclet comment into an array of Tag objects.
@private
*/
function toTags(docletSrc) {
var tagSrcs,
tags = [];
tagSrcs = split(docletSrc);
for (var i = 0, l = tagSrcs.length; i < l; i++) {
tags.push( {title: tagSrcs[i].title, text: tagSrcs[i].text} );
}
return tags;
}
function fixDescription(docletSrc) {
if (!/^\s*@/.test(docletSrc)) {
docletSrc = '@description ' + docletSrc;
}
return docletSrc;
}
/**
@class
@classdesc Represents a single JSDoc comment.
@param {string} docletSrc - The raw source code of the jsdoc comment.
@param {object=} meta - Properties describing the code related to this comment.
*/
exports.Doclet = function(docletSrc, meta) {
var newTags = [];
/** The original text of the comment from the source code. */
this.comment = docletSrc;
this.setMeta(meta);
docletSrc = unwrap(docletSrc);
docletSrc = fixDescription(docletSrc);
newTags = toTags.call(this, docletSrc);
for (var i = 0, leni = newTags.length; i < leni; i++) {
this.addTag(newTags[i].title, newTags[i].text);
}
this.postProcess();
};
/** Called once after all tags have been added. */
exports.Doclet.prototype.postProcess = function() {
if (!this.preserveName) { jsdoc.name.resolve(this); }
if (this.name && !this.longname) {
this.setLongname(this.name);
}
if (this.memberof === '') {
delete(this.memberof);
}
if (!this.kind && this.meta && this.meta.code) {
this.addTag( 'kind', codetypeToKind(this.meta.code.type) );
}
if (this.variation && this.longname && !/\)$/.test(this.longname) ) {
this.longname += '('+this.variation+')';
}
// add in any missing param names
if (this.params && this.meta && this.meta.code && this.meta.code.paramnames) {
for (var i = 0, len = this.params.length; i < len; i++) {
if (!this.params[i].name) {
this.params[i].name = this.meta.code.paramnames[i] || '';
}
}
}
};
/** Add a tag to this doclet.
@param {string} title - The title of the tag being added.
@param {string} [text] - The text of the tag being added.
*/
exports.Doclet.prototype.addTag = function(title, text) {
var tagDef = jsdoc.tag.dictionary.lookUp(title),
newTag = new jsdoc.tag.Tag(title, text, this.meta);
if (tagDef && tagDef.onTagged) {
tagDef.onTagged(this, newTag);
}
if (!tagDef) {
this.tags = this.tags || [];
this.tags.push(newTag);
}
applyTag.call(this, newTag);
};
/** Set the `memberof` property of this doclet.
@param {string} sid - The longname of the symbol that this doclet is a member of.
*/
exports.Doclet.prototype.setMemberof = function(sid) {
if (/^<global>\.?/.test(sid)) { sid = sid.replace(/^<global>.?/, ''); }
/**
The longname of the symbol that contains this one, if any.
@type string
*/
this.memberof = sid.replace(/\.prototype/g, '#');
};
/** Set the `longname` property of this doclet.
@param {string} name
*/
exports.Doclet.prototype.setLongname = function(name) {
if (/^<global>\.?/.test(name)) { name = name.replace(/^<global>\.?/, ''); }
/**
The fully resolved symbol name.
@type string
*/
this.longname = name;
if (jsdoc.tag.dictionary.isNamespace(this.kind)) {
this.longname = jsdoc.name.applyNamespace(this.longname, this.kind);
}
};
/** Add a symbol to this doclet's `borrowed` array.
@param {string} source - The longname of the symbol that is the source.
@param {string} target - The name the symbol is being assigned to.
*/
exports.Doclet.prototype.borrow = function(source, target) {
var about = {from: source};
if (target) { about.as = target; }
if (!this.borrowed) {
/**
A list of symbols that are borrowed by this one, if any.
@type Array.<string>
*/
this.borrowed = [];
}
this.borrowed.push(about);
};
exports.Doclet.prototype.mix = function(source) {
if (!this.mixes) {
/**
A list of symbols that are mixed into this one, if any.
@type Array.<string>
*/
this.mixes = [];
}
this.mixes.push(source);
};
/** Add a symbol to this doclet's `augments` array.
@param {string} base - The longname of the base symbol.
*/
exports.Doclet.prototype.augment = function(base) {
if (!this.augments) {
/**
A list of symbols that are augmented by this one, if any.
@type Array.<string>
*/
this.augments = [];
}
this.augments.push(base);
};
/**
Set the `meta` property of this doclet.
@param {object} meta
*/
exports.Doclet.prototype.setMeta = function(meta) {
if (!this.meta) {
/**
Information about the source code associated with this doclet.
@namespace
*/
this.meta = {};
}
if (meta.range) {
/**
The positions of the first and last characters of the code associated with this doclet.
@type Array.<number>
*/
this.meta.range = meta.range.slice(0);
}
if (meta.lineno) {
/**
The name of the file containing the code associated with this doclet.
@type string
*/
this.meta.filename = path.basename(meta.filename);
/**
The line number of the code associated with this doclet.
@type number
*/
this.meta.lineno = meta.lineno;
var pathname = path.dirname(meta.filename);
if (pathname && pathname !== '.') {
this.meta.path = pathname;
}
}
/**
Information about the code symbol.
@namespace
*/
this.meta.code = (this.meta.code || {});
if (meta.id) { this.meta.code.id = meta.id; }
if (meta.code) {
if (meta.code.name) {
/** The name of the symbol in the source code. */
this.meta.code.name = meta.code.name;
}
if (meta.code.type) {
/** The type of the symbol in the source code. */
this.meta.code.type = meta.code.type;
}
if (meta.code.node) {
this.meta.code.node = meta.code.node;
}
if (meta.code.funcscope) {
this.meta.code.funcscope = meta.code.funcscope;
}
if (meta.code.value) {
/** The value of the symbol in the source code. */
this.meta.code.value = meta.code.value;
}
if (meta.code.paramnames) {
this.meta.code.paramnames = meta.code.paramnames.concat([]);
}
}
};

View file

@ -0,0 +1,14 @@
/**
* Extended version of the standard `fs` module.
* @module jsdoc/fs
*/
var fs = exports.fs = require('fs');
var vm = require('jsdoc/util/vm');
// export the VM-specific implementations of the extra methods
// TODO: document extra methods here
var extras = vm.getModule('fs');
Object.keys(extras).forEach(function(extra) {
exports[extra] = extras[extra];
});

View file

@ -0,0 +1,258 @@
/**
A collection of functions relating to JSDoc symbol name manipulation.
@module jsdoc/name
@requires jsdoc/tag/dictionary
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var jsdoc = {
tagDictionary: require('jsdoc/tag/dictionary')
};
var puncToScope = { '.': 'static', '~': 'inner', '#': 'instance' },
scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' };
var DEFAULT_SCOPE = 'static';
/**
Resolves the longname, memberof, variation and name values of the given doclet.
@param {module:jsdoc/doclet.Doclet} doclet
*/
exports.resolve = function(doclet) {
var name = doclet.name,
memberof = doclet.memberof || '',
about = {},
parentDoc;
doclet.name = name = name? (''+name).replace(/(^|\.)prototype\.?/g, '#') : '';
// member of a var in an outer scope?
if (name && !memberof && doclet.meta.code && doclet.meta.code.funcscope) {
name = doclet.longname = doclet.meta.code.funcscope + '~' + name;
}
if (memberof || doclet.forceMemberof) { // @memberof tag given
memberof = ('' || memberof).replace(/\.prototype\.?/g, '#');
// the name is a fullname, like @name foo.bar, @memberof foo
if (name && name.indexOf(memberof) === 0 && name !== memberof) {
about = exports.shorten(name, (doclet.forceMemberof ? memberof : undefined));
}
// the name and memberof are identical and refer to a module,
// like @name module:foo, @memberof module:foo (probably a member like 'var exports')
else if (name && name === memberof && name.indexOf('module:') === 0) {
about = exports.shorten(name, (doclet.forceMemberof ? memberof : undefined));
}
// the name and memberof are identical, like @name foo, @memberof foo
else if (name && name === memberof) {
doclet.scope = doclet.scope || DEFAULT_SCOPE;
name = memberof + scopeToPunc[doclet.scope] + name;
about = exports.shorten(name, (doclet.forceMemberof ? memberof : undefined));
}
// like @memberof foo# or @memberof foo~
else if (name && /([#.~])$/.test(memberof) ) {
about = exports.shorten(memberof + name, (doclet.forceMemberof ? memberof : undefined));
}
else if (name && doclet.scope) {
about = exports.shorten(memberof + (scopeToPunc[doclet.scope] || '') + name,
(doclet.forceMemberof ? memberof : undefined));
}
}
else { // no @memberof
about = exports.shorten(name);
}
if (about.name) {
doclet.name = about.name;
}
if (about.memberof) {
doclet.setMemberof(about.memberof);
}
if (about.longname && !doclet.longname) {
doclet.setLongname(about.longname);
}
if (doclet.scope === 'global') { // via @global tag?
doclet.setLongname(doclet.name);
delete doclet.memberof;
}
else if (about.scope) {
if (about.memberof === '<global>') { // via @memberof <global> ?
doclet.scope = 'global';
}
else {
doclet.scope = puncToScope[about.scope];
}
}
else {
if (doclet.name && doclet.memberof && !doclet.longname) {
if ( /^([#.~])/.test(doclet.name) ) {
doclet.scope = puncToScope[RegExp.$1];
doclet.name = doclet.name.substr(1);
}
else {
doclet.scope = DEFAULT_SCOPE;
}
doclet.setLongname(doclet.memberof + scopeToPunc[doclet.scope] + doclet.name);
}
}
if (about.variation) {
doclet.variation = about.variation;
}
};
/**
@inner
@memberof module:jsdoc/name
@param {string} name
@param {string} kind
@returns {string} The name with unsafe names enclosed in quotes.
*/
function quoteUnsafe(name, kind) { // docspaced names may have unsafe characters which need to be quoted by us
if ( (jsdoc.tagDictionary.lookUp(kind).setsDocletDocspace) && /[^$_a-zA-Z0-9\/]/.test(name) ) {
if (!/^[a-z_$-\/]+:\"/i.test(name)) {
return '"' + name.replace(/\"/g, '"') + '"';
}
}
return name;
}
RegExp.escape = RegExp.escape || function(str) {
var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
return str.replace(specials, "\\$&");
};
/**
@method module:jsdoc/name.applyNamespace
@param {string} longname The full longname of the symbol.
@param {string} ns The namespace to be applied.
@returns {string} The longname with the namespace applied.
*/
exports.applyNamespace = function(longname, ns) {
var nameParts = exports.shorten(longname),
name = nameParts.name;
longname = nameParts.longname;
if ( !/^[a-zA-Z]+?:.+$/i.test(name) ) {
longname = longname.replace( new RegExp(RegExp.escape(name)+'$'), ns + ':' + name );
}
return longname;
};
/**
Given a longname like "a.b#c(2)", slice it up into ["a.b", "#", 'c', '2'],
representing the memberof, the scope, the name, and variation.
@param {string} longname
@param {string} forcedMemberof
@returns {object} Representing the properties of the given name.
*/
exports.shorten = function(longname, forcedMemberof) {
// quoted strings in a longname are atomic, convert to tokens
var atoms = [], token;
// handle quoted names like foo["bar"] or foo['bar']
longname = longname.replace(/(\[?["'].+?["']\]?)/g, function($) {
var dot = '';
if ( /^\[/.test($) ) {
dot = '.';
$ = $.replace( /^\[/g, '' ).replace( /\]$/g, '' );
}
token = '@{' + atoms.length + '}@';
atoms.push($);
return dot + token; // foo["bar"] => foo.@{1}@
});
var name = '',
scope = '', // ., ~, or #
memberof = '',
parts,
variation;
longname = longname.replace( /\.prototype\.?/g, '#' );
if (typeof forcedMemberof !== 'undefined') {
name = longname.substr(forcedMemberof.length);
parts = forcedMemberof.match(/^(.*?)([#.~]?)$/);
if (parts[1]) { memberof = parts[1] || forcedMemberof; }
if (parts[2]) { scope = parts[2]; }
}
else {
parts = longname?
(longname.match( /^(:?(.+)([#.~]))?(.+?)$/ ) || []).reverse()
: [''];
name = parts[0] || ''; // ensure name is always initialised to avoid error being thrown when calling replace on undefined [gh-24]
scope = parts[1] || ''; // ., ~, or #
memberof = parts[2] || '';
}
// like /** @name foo.bar(2) */
if ( /(.+)\(([^)]+)\)$/.test(name) ) {
name = RegExp.$1, variation = RegExp.$2;
}
//// restore quoted strings back again
var i = atoms.length;
while (i--) {
longname = longname.replace('@{'+i+'}@', atoms[i]);
memberof = memberof.replace('@{'+i+'}@', atoms[i]);
scope = scope.replace('@{'+i+'}@', atoms[i]);
name = name.replace('@{'+i+'}@', atoms[i]);
}
////
return {longname: longname, memberof: memberof, scope: scope, name: name, variation: variation};
};
/**
Split a string that starts with a name and ends with a description, into its parts.
@param {string} nameDesc
@returns {object} Hash with "name" and "description" properties.
*/
exports.splitName = function(nameDesc) {
var name = '',
desc = '',
thisChar = '',
inQuote = false;
for (var i = 0, len = nameDesc.length; i < len; i++) {
thisChar = nameDesc.charAt(i);
if (thisChar === '\\') {
name += thisChar + nameDesc.charAt(++i);
continue;
}
if (thisChar === '"') {
inQuote = !inQuote;
}
if (inQuote) {
name += thisChar;
continue;
}
if (!inQuote) {
if ( /\s/.test(thisChar) ) {
desc = nameDesc.substr(i);
desc = desc.replace(/^[\s\-\s]+/, '').trim();
break;
}
else {
name += thisChar;
}
}
}
return { name: name, description: desc };
};

View file

@ -0,0 +1,179 @@
/**
Parse the command line arguments.
@module jsdoc/opts/argparser
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var _ = require('underscore');
var hasOwnProp = Object.prototype.hasOwnProperty;
/**
Create an instance of the parser.
@classdesc A parser to interpret the key-value pairs entered on the command
line.
@constructor
*/
var ArgParser = function() {
this._options = [];
this._shortNameIndex = {};
this._longNameIndex = {};
};
ArgParser.prototype._getOptionByShortName = function(name) {
if (hasOwnProp.call(this._shortNameIndex, name)) {
return this._options[this._shortNameIndex[name]];
}
return null;
};
ArgParser.prototype._getOptionByLongName = function(name) {
if (hasOwnProp.call(this._longNameIndex, name)) {
return this._options[this._longNameIndex[name]];
}
return null;
};
/**
* Provide information about a legal option.
* @param {character} shortName The short name of the option, entered like: -T.
* @param {string} longName The equivalent long name of the option, entered like: --test.
* @param {boolean} hasValue Does this option require a value? Like: -t templatename
* @param {string} helpText A brief description of the option.
* @param {boolean} [canHaveMultiple=false] Set to `true` if the option can be provided more than once.
* @param {function} [coercer] A function to coerce the given value to a specific type.
* @example
* myParser.addOption('t', 'template', true, 'The path to the template.');
* myParser.addOption('h', 'help', false, 'Show the help message.');
*/
ArgParser.prototype.addOption = function(shortName, longName, hasValue, helpText, canHaveMultiple, coercer) {
this._options.push({
shortName: shortName,
longName: longName,
hasValue: hasValue,
helpText: helpText,
canHaveMultiple: (canHaveMultiple || false),
coercer: coercer
});
if (shortName) {
this._shortNameIndex[shortName] = this._options.length - 1;
}
if (longName) {
this._longNameIndex[longName] = this._options.length - 1;
}
};
/**
Generate a summary of all the options with corresponding help text.
@returns {string}
*/
ArgParser.prototype.help = function() {
var helpArr = ['OPTIONS:'],
option, optionHelp;
for (var i = 0, leni = this._options.length; i < leni; i++) {
option = this._options[i];
optionHelp = '\t';
if (option.shortName) {
optionHelp += '-' + option.shortName + (option.longName ? ', ' : '');
}
if (option.longName) {
optionHelp += '--' + option.longName;
}
if (option.hasValue) {
optionHelp += ' <value>';
}
optionHelp += '\t\t' + option.helpText;
helpArr.push(optionHelp);
}
return helpArr.join('\n');
};
/**
Get the options.
@param {Array.<string>} args An array, like ['-x', 'hello']
@param {Object} [defaults={}] An optional collection of default values.
@returns {Object} The keys will be the longNames, or the shortName if
no longName is defined for that option. The values will be the values
provided, or `true` if the option accepts no value.
*/
ArgParser.prototype.parse = function(args, defaults) {
var result = defaults && _.defaults({}, defaults) || {};
result._ = [];
for (var i = 0, leni = args.length; i < leni; i++) {
var arg = '' + args[i],
next = (i < leni-1)? '' + args[i+1] : null,
option,
shortName = null,
longName,
name,
value = null;
// like -t
if (arg.charAt(0) === '-') {
// like --template
if (arg.charAt(1) === '-') {
name = longName = arg.slice(2);
option = this._getOptionByLongName(longName);
}
else {
name = shortName = arg.slice(1);
option = this._getOptionByShortName(shortName);
}
if (option === null) {
throw new Error( 'Unknown command line option found: ' + name );
}
if (option.hasValue) {
value = next;
i++;
if (value === null || value.charAt(0) === '-') {
throw new Error( 'Command line option requires a value: ' + name );
}
}
else {
value = true;
}
if (option.longName && shortName) {
name = option.longName;
}
if (typeof option.coercer === 'function') {
value = option.coercer(value);
}
// Allow for multiple options of the same type to be present
if (option.canHaveMultiple && hasOwnProp.call(result, name)) {
var val = result[name];
if (val instanceof Array) {
val.push(value);
} else {
result[name] = [val, value];
}
}
else {
result[name] = value;
}
}
else {
result._.push(arg);
}
}
return result;
};
module.exports = ArgParser;

View file

@ -0,0 +1,127 @@
/**
@module jsdoc/opts/args
@requires jsdoc/opts/argparser
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var ArgParser = require('jsdoc/opts/argparser'),
argParser = new ArgParser(),
hasOwnProp = Object.prototype.hasOwnProperty,
ourOptions,
querystring = require('querystring'),
util = require('util');
// cast strings to booleans or integers where appropriate
function castTypes(item) {
var result = item;
switch (result) {
case 'true':
return true;
case 'false':
return false;
default:
// might be an integer
var integer = parseInt(result, 10);
if (String(integer) === result && integer !== 'NaN') {
return integer;
} else {
return result;
}
}
}
// check for strings that we need to cast to other types
function fixTypes(item) {
var result = item;
// recursively process arrays and objects
if ( util.isArray(result) ) {
for (var i = 0, l = result.length; i < l; i++) {
result[i] = fixTypes(result[i]);
}
} else if (typeof result === 'object') {
Object.keys(result).forEach(function(prop) {
result[prop] = fixTypes(result[prop]);
});
} else {
result = castTypes(result);
}
return result;
}
function parseQuery(str) {
var result = querystring.parse(str);
Object.keys(result).forEach(function(prop) {
result[prop] = fixTypes(result[prop]);
});
return result;
}
argParser.addOption('t', 'template', true, 'The name of the template to use. Default: the "default" template');
argParser.addOption('c', 'configure', true, 'The path to the configuration file. Default: jsdoc __dirname + /conf.json');
argParser.addOption('e', 'encoding', true, 'Assume this encoding when reading all source files. Default: utf8');
argParser.addOption('T', 'test', false, 'Run all tests and quit.');
argParser.addOption('d', 'destination', true, 'The path to the output folder. Use "console" to dump data to the console. Default: ./out/');
argParser.addOption('p', 'private', false, 'Display symbols marked with the @private tag. Default: false');
argParser.addOption('r', 'recurse', false, 'Recurse into subdirectories when scanning for source code files.');
argParser.addOption('l', 'lenient', false, 'Continue to generate output if a doclet is incomplete or contains errors. Default: false');
argParser.addOption('h', 'help', false, 'Print this message and quit.');
argParser.addOption('X', 'explain', false, 'Dump all found doclet internals to console and quit.');
argParser.addOption('q', 'query', true, 'A query string to parse and store in env.opts.query. Example: foo=bar&baz=true', false, parseQuery);
argParser.addOption('u', 'tutorials', true, 'Directory in which JSDoc should search for tutorials.');
argParser.addOption('v', 'version', false, 'Display the version number and quit.');
//TODO [-R, recurseonly] = a number representing the depth to recurse
//TODO [-f, filter] = a regex to filter on <-- this can be better defined in the configs?
//Here are options specific to tests
argParser.addOption(null, 'verbose', false, 'Display verbose output for tests');
argParser.addOption(null, 'match', true, 'Only run tests containing <value>', true);
argParser.addOption(null, 'nocolor', false, 'Do not use color in console output from tests');
/**
Set the options for this app.
@throws {Error} Illegal arguments will throw errors.
@param {string|String[]} args The command line arguments for this app.
*/
exports.parse = function(args) {
args = args || [];
if (typeof args === 'string' || args.constructor === String) {
args = (''+args).split(/\s+/g);
}
ourOptions = argParser.parse(args);
return ourOptions;
};
/**
Display help message for options.
*/
exports.help = function() {
return argParser.help();
};
/**
Get a named option.
@param {string} name The name of the option.
@return {string} The value associated with the given name.
*//**
Get all the options for this app.
@return {Object} A collection of key/values representing all the options.
*/
exports.get = function(name) {
if (typeof name === 'undefined') {
return ourOptions;
}
else {
return ourOptions[name];
}
};

View file

@ -0,0 +1,69 @@
/**
@overview
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
@module jsdoc/package
@see http://wiki.commonjs.org/wiki/Packages/1.0
*/
/**
@class
@classdesc Represents a JavaScript package.
@param {string} json - The contents of package.json.
*/
exports.Package = function(json) {
json = json || "{}";
/** The source files associated with this package.
@type {Array<String>}
*/
this.files = [];
/** The kind of this package.
@readonly
@default
@type {string}
*/
this.kind = 'package';
json = JSON.parse(json);
/** The name of this package.
This value is found in the package.json file passed in as a command line option.
@type {string}
*/
this.name = json.name;
/** The longname of this package.
@type {string}
*/
this.longname = this.kind + ':' + this.name;
/** The description of this package.
@type {string}
*/
this.description = json.description;
/**
The hash summary of the source file.
@type {string}
@since 3.2.0
*/
this.version = json.version;
/**
* The licenses of this package.
* @type {Array<Object>}
* @example
* "licenses": [
* {
* "type": "GPLv2",
* "url": "http://www.example.com/licenses/gpl.html"
* }
* ]
*/
this.licenses = json.licenses;
};

View file

@ -0,0 +1,136 @@
/**
* Extended version of the standard `path` module.
* @module jsdoc/path
*/
var fs = require('fs');
var path = require('path');
var vm = require('jsdoc/util/vm');
function prefixReducer(previousPath, current) {
var currentPath = [];
// if previousPath is defined, but has zero length, there's no common prefix; move along
if (previousPath && !previousPath.length) {
return currentPath;
}
currentPath = path.resolve( process.cwd(), path.dirname(current) ).split(path.sep) || [];
if (previousPath && currentPath.length) {
// remove chunks that exceed the previous path's length
currentPath = currentPath.slice(0, previousPath.length);
// if a chunk doesn't match the previous path, remove everything from that chunk on
for (var i = 0, l = currentPath.length; i < l; i++) {
if (currentPath[i] !== previousPath[i]) {
currentPath.splice(i, currentPath.length - i);
break;
}
}
}
return currentPath;
}
/**
* Find the common prefix for an array of paths. If there is a common prefix, a trailing separator
* is appended to the prefix. Relative paths are resolved relative to the current working directory.
*
* For example, assuming that the current working directory is `/Users/jsdoc`:
*
* + For paths `foo/bar/baz/qux.js`, `foo/bar/baz/quux.js`, and `foo/bar/baz.js`, the common prefix
* is `/Users/jsdoc/foo/bar/`.
* + For paths `../jsdoc/foo/bar/baz/qux/quux/test.js`, `/Users/jsdoc/foo/bar/bazzy.js`, and
* `../../Users/jsdoc/foo/bar/foobar.js`, the common prefix is `/Users/jsdoc/foo/bar/`.
* + For paths `foo/bar/baz/qux.js` and `../../Library/foo/bar/baz.js`, there is no common prefix,
* and an empty string is returned.
*
* @param {Array.<string>} paths - The paths to search for a common prefix.
* @return {string} The common prefix, or an empty string if there is no common prefix.
*/
exports.commonPrefix = function(paths) {
var common = paths.reduce(prefixReducer, undefined);
// if there's anything left (other than a placeholder for a leading slash), add a placeholder
// for a trailing slash
if ( common.length && (common.length > 1 || common[0] !== '') ) {
common.push('');
}
return common.join(path.sep);
};
// TODO: do we need this?
/**
* If required by the current VM, convert a path to a URI that meets the operating system's
* requirements. Otherwise, return the original path.
* @function
* @private
* @param {string} path The path to convert.
* @return {string} A URI that meets the operating system's requirements, or the original path.
*/
var pathToUri = vm.getModule('jsdoc').pathToUri;
// TODO: do we need this? if so, any way to stop exporting it?
/**
* If required by the current VM, convert a URI to a path that meets the operating system's
* requirements. Otherwise, assume the "URI" is really a path, and return the original path.
* @function
* @private
* @param {string} uri The URI to convert.
* @return {string} A path that meets the operating system's requirements.
*/
exports._uriToPath = vm.getModule('jsdoc').uriToPath;
/**
* Retrieve the fully qualified path to the requested resource.
*
* If the resource path is specified as a relative path, JSDoc searches for the path in the current
* working directory, then in the JSDoc directory.
*
* If the resource path is specified as a fully qualified path, JSDoc uses the path as-is.
*
* @param {string} filepath - The path to the requested resource. May be an absolute path; a path
* relative to the JSDoc directory; or a path relative to the current working directory.
* @param {string} [filename] - The filename of the requested resource.
* @return {string} The fully qualified path (or, on Rhino, a URI) to the requested resource.
* Includes the filename if one was provided.
*/
exports.getResourcePath = function(filepath, filename) {
var result;
function pathExists(_path) {
try {
fs.readdirSync(_path);
}
catch(e) {
return false;
}
return true;
}
// first, try resolving it relative to the current working directory (or just normalize it
// if it's an absolute path)
result = path.resolve(filepath);
if ( !pathExists(result) ) {
// next, try resolving it relative to the JSDoc directory
result = path.resolve(__dirname, filepath);
if ( !pathExists(result) ) {
result = null;
}
}
if (result) {
result = filename ? path.join(result, filename) : result;
result = pathToUri(result);
}
return result;
};
Object.keys(path).forEach(function(member) {
exports[member] = path[member];
});

View file

@ -0,0 +1,45 @@
/*global app: true */
/**
* Utility functions to support the JSDoc plugin framework.
* @module jsdoc/plugins
*/
var error = require('jsdoc/util/error');
var path = require('jsdoc/path');
exports.installPlugins = function(plugins, p) {
var dictionary = require('jsdoc/tag/dictionary');
var parser = p;
var eventName;
var plugin;
var pluginPath;
for (var i = 0, l = plugins.length; i < l; i++) {
pluginPath = path.getResourcePath(path.dirname(plugins[i]), path.basename(plugins[i]));
if (!pluginPath) {
error.handle(new Error('Unable to find the plugin "' + plugins[i] + '"'));
}
else {
plugin = require(pluginPath);
// allow user-defined plugins to...
//...register event handlers
if (plugin.handlers) {
Object.keys(plugin.handlers).forEach(function(eventName) {
parser.on(eventName, plugin.handlers[eventName]);
});
}
//...define tags
if (plugin.defineTags) {
plugin.defineTags(dictionary);
}
//...add a node visitor
if (plugin.nodeVisitor) {
parser.addNodeVisitor(plugin.nodeVisitor);
}
}
}
};

View file

@ -0,0 +1,25 @@
/*global env: true */
/**
* Make the contents of a README file available to include in the output.
* @module jsdoc/readme
* @author Michael Mathews <micmath@gmail.com>
* @author Ben Blank <ben.blank@gmail.com>
*/
var fs = require('jsdoc/fs'),
markdown = require('jsdoc/util/markdown');
/**
* @class
* @classdesc Represents a README file.
* @param {string} path - The filepath to the README.
*/
function ReadMe(path) {
var content = fs.readFileSync(path, env.opts.encoding),
parse = markdown.getParser();
this.html = parse(content);
}
module.exports = ReadMe;

View file

@ -0,0 +1,308 @@
/**
@overview Schema for validating JSON produced by JSDoc Toolkit.
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
@see <http://tools.ietf.org/html/draft-zyp-json-schema-02>
*/
exports.jsdocSchema = {
"properties": {
"doc": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"author": {
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"path": { // unique identifier for each doc
"type": "string",
"maxItems": 1
},
"description": { // a description
"type": "string",
"optional": true,
"maxItems": 1
},
"classdesc": { // a description of the class that this constructor belongs to
"type": "string",
"optional": true,
"maxItems": 1
},
"name": { // probably a trailing substring of the path
"type": "string",
"maxItems": 1
},
"version": { // what is the version of this doc
"type": "string",
"optional": true,
"maxItems": 1
},
"since": { // at what previous version was this doc added?
"type": "string",
"optional": true,
"maxItems": 1
},
"see": { // some thing else to consider
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"tutorials": { // extended tutorials
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"deprecated": { // is usage of this symbol deprecated?
"type": ["string", "boolean"],
"optional": true
},
"scope": { // how is this symbol attached to it's enclosing scope?
"type": "string",
"maxItems": 1,
"enum": ["global", "static", "instance", "inner"]
},
"memberof": { // probably a leading substring of the path
"type": "string",
"optional": true,
"maxItems": 1
},
"extends": { // the path to another constructor
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"fires": { // the path to another doc object
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"requires": { // the symbol being documented requires another symbol
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"implements": {
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"kind": { // what kind of symbol is this?
"type": "string",
"maxItems": 1,
"enum": ["constructor", "module", "event", "namespace", "method", "member", "enum", "class", "interface", "constant", "mixin", "file", "version"]
},
"refersto": { // the path to another doc: this doc is simply a renamed alias to that
"type": "string",
"optional": true,
"maxItems": 1
},
"access": { // what access priviledges are allowed
"type": "string",
"optional": true,
"maxItems": 1,
"enum": ["private", "protected", "public"]
},
"virtual": { // is a member left to be implemented during inheritance?
"type": "boolean",
"optional": true,
"default": false
},
"attrib": { // other attributes, like "readonly"
"type": "string",
"optional": true
},
"type": { // what type is the value that this doc is associated with, like "number"
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"exception" : {
"optional": true,
"type": "object",
"properties": {
"type": { // what is the type of the value thrown?
"type": "array",
"optional": true,
"items": {
"type": "string"
}
},
"description": { // a description of the thrown value
"type": "string",
"optional": true
}
},
"additionalProperties": false
},
"returns" : {
"optional": true,
"type": "object",
"properties": {
"type": { // what is the type of the value returned?
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"description": { // a description of the returned value
"type": "string",
"optional": true
}
},
"additionalProperties": false
},
"param" : { // are there function parameters associated with this doc?
"type": "array",
"optional": true,
"items": {
"type": "object",
"properties": {
"type": { // what are the types of value expected for this parameter?
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"optional": { // is a value for this parameter optional?
"type": "boolean",
"optional": true,
"default": true
},
"nullable": { // can the value for this parameter be null?
"type": "boolean",
"optional": true,
"default": true
},
"defaultvalue": { // what is the default value for this parameter?
"type": "string",
"optional": true
},
"name": { // what name does this parameter have within the function?
"type": "string"
},
"description": { // a description of the parameter
"type": "string",
"optional": true
}
},
"additionalProperties": false
}
},
"thisobj": {
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"example": { // some thing else to consider
"type": ["string", "array"],
"optional": true,
"items": {
"type": "string"
}
},
"tags": { // arbitrary tags associated with this doc
"type": "array",
"optional": true,
"additionalProperties": false,
"items": {
"type": "string"
}
},
"meta": { // information about this doc
"type": "object",
"optional": true,
"maxItems": 1,
"properties": {
"file": { // what is the name of the file this doc appears in?
"type": "string",
"optional": true,
"maxItems": 1
},
"line": { // on what line of the file does this doc appear?
"type": "number",
"optional": true,
"maxItems": 1
}
},
"additionalProperties": false
}
}
}
},
"meta": { // information about the generation for all the docs
"type": "object",
"optional": true,
"maxItems": 1,
"properties": {
"project": { // to what project does this doc belong?
"type": "object",
"optional": true,
"maxItems": 1,
"properties": {
"name": { // the name of the project
"type": "string",
"maxItems": 1
},
"uri": { // the URI of the project
"type": "string",
"maxItems": 1,
"format": "uri"
},
"version": { // the version of the project
"type": "string",
"maxItems": 1
},
"lang": { // the programming language used in the project
"type": "string",
"maxItems": 1
}
},
"additionalProperties": false
},
"generated": { // some information about the running of the doc generator
"type": "object",
"optional": true,
"maxItems": 1,
"properties": {
"date": { // on what date and time was the doc generated?
"type": "string",
"maxItems": 1,
"optional": true,
"format": "date-time"
},
"parser": { // what tool was used to generate the doc?
"type": "string",
"maxItems": 1,
"optional": true
}
},
"additionalProperties": false
}
}
}
}
};

View file

@ -0,0 +1,53 @@
/**
@module jsdoc/src/filter
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var path = require('jsdoc/path');
/**
@constructor
@param {object} opts
@param {string[]} opts.exclude - Specific files to exclude.
@param {string|RegExp} opts.includePattern
@param {string|RegExp} opts.excludePattern
*/
exports.Filter = function(opts) {
var cwd = process.cwd();
this.exclude = opts.exclude && Array.isArray(opts.exclude) ?
opts.exclude.map(function($) {
return path.resolve(cwd, $);
}) :
null;
this.includePattern = opts.includePattern?
typeof opts.includePattern === 'string'? new RegExp(opts.includePattern) : opts.includePattern
: null;
this.excludePattern = opts.excludePattern?
typeof opts.excludePattern === 'string'? new RegExp(opts.excludePattern) : opts.excludePattern
: null;
};
/**
@param {string} filepath - The filepath to check.
@returns {boolean} Should the given file be included?
*/
exports.Filter.prototype.isIncluded = function(filepath) {
filepath = path.resolve(process.cwd(), filepath);
if ( this.includePattern && !this.includePattern.test(filepath) ) {
return false;
}
if ( this.excludePattern && this.excludePattern.test(filepath) ) {
return false;
}
if ( this.exclude && this.exclude.indexOf(filepath) > -1 ) {
return false;
}
return true;
};

View file

@ -0,0 +1,200 @@
/**
* @module jsdoc/src/handlers
*/
var currentModule = null;
function getNewDoclet(comment, e) {
var jsdoc = {doclet: require('jsdoc/doclet')};
var util = require('util');
var err;
try {
return new jsdoc.doclet.Doclet(comment, e);
}
catch (error) {
err = new Error( util.format('cannot create a doclet for the comment "%s": %s',
comment.replace(/[\r\n]/g, ''), error.message) );
require('jsdoc/util/error').handle(err);
return new jsdoc.doclet.Doclet('', {});
}
}
/**
* Attach these event handlers to a particular instance of a parser.
* @param parser
*/
exports.attachTo = function(parser) {
var jsdoc = {doclet: require('jsdoc/doclet'), name: require('jsdoc/name')};
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
parser.on('jsdocCommentFound', function(e) {
var newDoclet = getNewDoclet(e.comment, e);
if (!newDoclet.name) {
return false; // only interested in virtual comments (with a @name) here
}
addDoclet.call(this, newDoclet);
if (newDoclet.kind === 'module') {
currentModule = newDoclet.longname;
}
e.doclet = newDoclet;
//resolveProperties(newDoclet);
});
// handles named symbols in the code, may or may not have a JSDoc comment attached
parser.on('symbolFound', function(e) {
var subDoclets = e.comment.split(/@also\b/g);
for (var i = 0, l = subDoclets.length; i < l; i++) {
newSymbolDoclet.call(this, subDoclets[i], e);
}
});
// TODO: for clarity, decompose into smaller functions
function newSymbolDoclet(docletSrc, e) {
var memberofName = null,
newDoclet = getNewDoclet(docletSrc, e);
// an undocumented symbol right after a virtual comment? rhino mistakenly connected the two
if (newDoclet.name) { // there was a @name in comment
// try again, without the comment
e.comment = '@undocumented';
newDoclet = getNewDoclet(e.comment, e);
}
if (newDoclet.alias) {
if (newDoclet.alias === '{@thisClass}') {
memberofName = this.resolveThis(e.astnode);
// "class" refers to the owner of the prototype, not the prototype itself
if ( /^(.+?)(\.prototype|#)$/.test(memberofName) ) {
memberofName = RegExp.$1;
}
newDoclet.alias = memberofName;
}
newDoclet.addTag('name', newDoclet.alias);
newDoclet.postProcess();
}
else if (e.code && e.code.name) { // we need to get the symbol name from code
newDoclet.addTag('name', e.code.name);
if (!newDoclet.memberof && e.astnode) {
var basename = null,
scope = '';
if ( /^((module.)?exports|this)(\.|$)/.test(newDoclet.name) ) {
var nameStartsWith = RegExp.$1;
newDoclet.name = newDoclet.name.replace(/^(exports|this)(\.|$)/, '');
// like /** @module foo */ exports.bar = 1;
if (nameStartsWith === 'exports' && currentModule) {
memberofName = currentModule;
scope = 'static';
}
else if (newDoclet.name === 'module.exports' && currentModule) {
newDoclet.addTag('name', currentModule);
newDoclet.postProcess();
}
else {
// like /** @module foo */ exports = {bar: 1};
// or /** blah */ this.foo = 1;
memberofName = this.resolveThis(e.astnode);
scope = nameStartsWith === 'exports'? 'static' : 'instance';
// like /** @module foo */ this.bar = 1;
if (nameStartsWith === 'this' && currentModule && !memberofName) {
memberofName = currentModule;
scope = 'static';
}
}
if (memberofName) {
if (newDoclet.name) {
newDoclet.name = memberofName + (scope === 'instance'? '#' : '.') + newDoclet.name;
}
else { newDoclet.name = memberofName; }
}
}
else {
memberofName = this.astnodeToMemberof(e.astnode);
if( Array.isArray(memberofName) ) {
basename = memberofName[1];
memberofName = memberofName[0];
}
}
if (memberofName) {
newDoclet.addTag('memberof', memberofName);
if (basename) {
newDoclet.name = newDoclet.name.replace(new RegExp('^' + RegExp.escape(basename) + '.'), '');
}
}
else {
// add @inner and @memberof tags unless the current module exports only this symbol
if (currentModule && currentModule !== newDoclet.name) {
// add @inner unless the current module exports only this symbol
if (!newDoclet.scope) {
newDoclet.addTag('inner');
}
if (!newDoclet.memberof && newDoclet.scope !== 'global') {
newDoclet.addTag('memberof', currentModule);
}
}
}
}
newDoclet.postProcess();
}
else {
return false;
}
//resolveProperties(newDoclet);
// set the scope to global unless a) the doclet is a memberof something or b) the current
// module exports only this symbol
if (!newDoclet.memberof && currentModule !== newDoclet.name) {
newDoclet.scope = 'global';
}
addDoclet.call(this, newDoclet);
e.doclet = newDoclet;
}
//parser.on('fileBegin', function(e) { });
parser.on('fileComplete', function(e) {
currentModule = null;
});
function addDoclet(newDoclet) {
var e;
if (newDoclet) {
e = { doclet: newDoclet };
this.emit('newDoclet', e);
if ( !e.defaultPrevented && !filter(newDoclet) ) {
this.addResult(newDoclet);
}
}
}
function filter(doclet) {
// you can't document prototypes
if ( /#$/.test(doclet.longname) ) {
return true;
}
// you can't document symbols added by the parser with a dummy name
if (doclet.meta.code && doclet.meta.code.name === '____') {
return true;
}
return false;
}
function resolveProperties(newDoclet) {}
};

View file

@ -0,0 +1,779 @@
/*global env: true, Packages: true */
/**
* @module jsdoc/src/parser
* @requires fs
* @requires events
*/
var Token = Packages.org.mozilla.javascript.Token;
var hasOwnProp = Object.prototype.hasOwnProperty;
/**
* @class
* @mixes module:events
*
* @example <caption>Create a new parser.</caption>
* var jsdocParser = new (require('jsdoc/src/parser').Parser)();
*/
exports.Parser = function() {
this._currentSourceName = '';
this._resultBuffer = [];
this._comments = {
original: [],
modified: []
};
//Initialize a global ref to store global members
this.refs = {
__global__: {
meta: {}
}
};
this._visitors = [];
};
exports.Parser.prototype = Object.create( require('events').EventEmitter.prototype );
/**
* Parse the given source files for JSDoc comments.
* @param {Array.<string>} sourceFiles An array of filepaths to the JavaScript sources.
* @param {string} [encoding=utf8]
*
* @fires jsdocCommentFound
* @fires symbolFound
* @fires newDoclet
* @fires fileBegin
* @fires fileComplete
*
* @example <caption>Parse two source files.</caption>
* var myFiles = ['file1.js', 'file2.js'];
* var docs = jsdocParser.parse(myFiles);
*/
exports.Parser.prototype.parse = function(sourceFiles, encoding) {
encoding = encoding || env.conf.encoding || 'utf8';
const SCHEMA = 'javascript:';
var filename = '';
var sourceCode = '';
var parsedFiles = [];
var e = {};
if (typeof sourceFiles === 'string') {
sourceFiles = [sourceFiles];
}
e.sourcefiles = sourceFiles;
this.emit('parseBegin', e);
for (var i = 0, l = sourceFiles.length; i < l; i++) {
sourceCode = '';
if (sourceFiles[i].indexOf(SCHEMA) === 0) {
sourceCode = sourceFiles[i].substr(SCHEMA.length);
filename = '[[string' + i + ']]';
}
else {
filename = sourceFiles[i];
try {
sourceCode = require('jsdoc/fs').readFileSync(filename, encoding);
}
catch(e) {
console.log('FILE READ ERROR: in module:jsdoc/parser.parseFiles: "' + filename +
'" ' + e);
continue;
}
}
if (sourceCode.length) {
this._parseSourceCode(sourceCode, filename);
parsedFiles.push(filename);
}
}
this.emit('parseComplete', {
sourcefiles: parsedFiles
});
return this._resultBuffer;
};
/**
* @returns {Array<Doclet>} The accumulated results of any calls to parse.
*/
exports.Parser.prototype.results = function() {
return this._resultBuffer;
};
/**
* @param {Object} o The parse result to add to the result buffer.
*/
exports.Parser.prototype.addResult = function(o) {
this._resultBuffer.push(o);
};
/**
* Empty any accumulated results of calls to parse.
*/
exports.Parser.prototype.clear = function() {
this._currentSourceName = '';
this._resultBuffer = [];
this._comments = {
original: [],
modified: []
};
};
/**
* Adds a node visitor to use in parsing
*/
exports.Parser.prototype.addNodeVisitor = function(visitor) {
this._visitors.push(visitor);
};
/**
* Get the node visitors used in parsing
*/
exports.Parser.prototype.getVisitors = function() {
return this._visitors;
};
function pretreat(code) {
return code
// make starbangstar comments look like real jsdoc comments
.replace(/\/\*\!\*/g, '/**')
// merge adjacent doclets
.replace(/\*\/\/\*\*+/g, '@also')
// make lent object literals documentable by giving them a dummy name
// like return @lends {
.replace(/(\/\*\*[^\*\/]*?[\*\s]*@lends\s(?:[^\*]|\*(?!\/))*\*\/\s*)\{/g, '$1 ____ = {')
// like @lends return {
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/)(\s*)return(\s*)\{/g,
'$2$3 return $1 ____ = {');
}
var tkn = {
NAMEDFUNCTIONSTATEMENT: -1001
};
exports.Parser.tkn = tkn;
/** @private */
function parserFactory() {
var cx = Packages.org.mozilla.javascript.Context.getCurrentContext();
var ce = new Packages.org.mozilla.javascript.CompilerEnvirons();
ce.setRecordingComments(true);
ce.setRecordingLocalJsDocComments(true);
ce.setLanguageVersion(180);
ce.initFromContext(cx);
return new Packages.org.mozilla.javascript.Parser(ce, ce.getErrorReporter());
}
/** @private
@memberof module:src/parser.Parser
*/
function getTypeName(node) {
var type = '';
if (node) {
type = '' + Packages.org.mozilla.javascript.Token.typeToName(node.getType());
}
return type;
}
/** @private
@memberof module:src/parser.Parser
*/
function nodeToString(node) {
var str;
if (!node) {
return;
}
if (node.type === Token.GETPROP) {
str = [nodeToString(node.target), node.property.string].join('.');
}
else if (node.type === Token.VAR) {
str = nodeToString(node.target);
}
else if (node.type === Token.NAME) {
str = node.string;
}
else if (node.type === Token.STRING) {
str = node.value;
}
else if (node.type === Token.NUMBER) {
str = node.value;
}
else if (node.type === Token.THIS) {
str = 'this';
}
else if (node.type === Token.GETELEM) {
str = node.toSource(); // like: Foo['Bar']
}
else if (node.type === Token.NEG || node.type === Token.TRUE || node.type === Token.FALSE) {
str = node.toSource(); // like -1
}
else {
str = getTypeName(node);
}
return '' + str;
}
/**
* Attempts to find the name and type of the given node.
* @private
* @memberof module:src/parser.Parser
*/
function aboutNode(node) {
var about = {};
if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
about.name = node.type == tkn.NAMEDFUNCTIONSTATEMENT? '' : '' + node.name;
about.type = 'function';
about.node = node;
}
else if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
about.name = nodeToString(node.target);
if (node.initializer) { // like var i = 0;
about.node = node.initializer;
about.value = nodeToString(about.node);
about.type = getTypeName(node.initializer);
if (about.type === 'FUNCTION' && about.node.name) {
about.node.type = tkn.NAMEDFUNCTIONSTATEMENT;
}
}
else { // like var i;
about.node = node.target;
about.value = nodeToString(about.node);
about.type = 'undefined';
}
}
else if (node.type === Token.ASSIGN || node.type === Token.COLON ||
node.type === Token.GET || node.type === Token.SET) {
about.name = nodeToString(node.left);
if (node.type === Token.COLON) {
// objlit keys with unsafe variable-name characters must be quoted
if (!/^[$_a-z][$_a-z0-9]*$/i.test(about.name) ) {
about.name = '"'+about.name.replace(/"/g, '\\"')+'"';
}
}
about.node = node.right;
about.value = nodeToString(about.node);
// Getter and setter functions should be treated as properties
if (node.type === Token.GET || node.type === Token.SET) {
about.type = getTypeName(node);
} else {
about.type = getTypeName(node.right);
}
if (about.type === 'FUNCTION' && about.node.name) {
about.node.type = tkn.NAMEDFUNCTIONSTATEMENT;
}
}
else if (node.type === Token.GETPROP) {
about.node = node;
about.name = nodeToString(about.node);
about.type = getTypeName(node);
}
else {
// type 39 (NAME)
var string = nodeToString(node);
if (string) {
about.name = string;
}
}
// get names of the formal parameters declared for this function
if (about.node && about.node.getParamCount) {
var paramCount = about.node.getParamCount();
if (typeof paramCount === 'number') {
about.node.flattenSymbolTable(true);
var paramNames = [];
for (var i = 0, l = paramCount; i < l; i++) {
paramNames.push( '' + about.node.getParamOrVarName(i) );
}
about.paramnames = paramNames;
}
}
return about;
}
/** @private
@memberof module:src/parser.Parser
*/
function isValidJsdoc(commentSrc) {
/*** ignore comments that start with many stars ***/
return commentSrc && commentSrc.indexOf('/***') !== 0;
}
/** @private
* @memberof module:src/parser.Parser
*/
function makeVarsFinisher(funcDoc) {
return function(e) {
//no need to evaluate all things related to funcDoc again, just use it
if (funcDoc && e.doclet && e.doclet.alias) {
funcDoc.meta.vars[e.code.name] = e.doclet.longname;
}
};
}
/** @private
* @memberof module:src/parser.Parser
* @param {string} name Full symbol name.
* @return {string} Basename.
*/
function getBasename(name) {
if (name !== undefined) {
return name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
}
return name;
}
/** @private
* @memberof module:src/parser.Parser
* @param {object} node
* @return {Array.<number>} Start and end lines.
*/
function getRange(node) {
var range = [];
range[0] = parseInt(String(node.getAbsolutePosition()), 10);
range[1] = range[0] + parseInt(String(node.getLength()), 10);
return range;
}
/** @private
* @memberof module:src/parser.Parser
*/
exports.Parser.prototype._makeEvent = function(node, extras) {
extras = extras || {};
// fill in default values as needed. if we're overriding a property, don't execute the default
// code for that property, since it might blow up.
var result = {
id: extras.id || 'astnode' + node.hashCode(),
comment: extras.comment || String(node.getJsDoc() || '@undocumented'),
lineno: extras.lineno || node.left.getLineno(),
range: extras.range || getRange(node),
filename: extras.filename || this._currentSourceName,
astnode: extras.astnode || node,
code: extras.code || aboutNode(node),
event: extras.event || 'symbolFound',
finishers: extras.finishers || [this.addDocletRef]
};
// use the modified version of the comment
var idx = this._comments.original.indexOf(result.comment);
if (idx !== -1) {
result.comment = this._comments.modified[idx];
}
// make sure the result includes extras that don't have default values
Object.keys(extras).forEach(function(prop) {
result[prop] = extras[prop];
});
return result;
};
/** @private
* @memberof module:src/parser.Parser
*/
exports.Parser.prototype._trackVars = function(node, e) {
// keep track of vars in a function or global scope
var func = '__global__';
var funcDoc = null;
if (node.enclosingFunction) {
func = 'astnode' + node.enclosingFunction.hashCode();
}
funcDoc = this.refs[func];
if (funcDoc) {
funcDoc.meta.vars = funcDoc.meta.vars || {};
funcDoc.meta.vars[e.code.name] = false;
e.finishers.push(makeVarsFinisher(funcDoc));
}
};
/** @private */
exports.Parser.prototype._visitComment = function(comment) {
var e;
var original = String( comment.toSource() );
var modified;
if ( original && isValidJsdoc(original) ) {
this._comments.original.push(original);
e = {
comment: original,
lineno: comment.getLineno(),
filename: this._currentSourceName,
range: getRange(comment)
};
this.emit('jsdocCommentFound', e, this);
if (e.comment !== original) {
modified = e.comment;
}
this._comments.modified.push(modified || original);
}
return true;
};
/** @private */
exports.Parser.prototype._visitNode = function(node) {
var e,
extras,
basename,
func,
funcDoc,
i,
l;
if (node.type === Token.ASSIGN) {
e = this._makeEvent(node);
basename = getBasename(e.code.name);
if (basename !== 'this') {
e.code.funcscope = this.resolveVar(node, basename);
}
}
else if (node.type === Token.COLON) { // assignment within an object literal
extras = {
comment: String(node.left.getJsDoc() || '@undocumented'),
finishers: [this.addDocletRef, this.resolveEnum]
};
e = this._makeEvent(node, extras);
}
else if (node.type === Token.GET || node.type === Token.SET) { // assignment within an object literal
extras = {
comment: String(node.left.getJsDoc() || '@undocumented')
};
e = this._makeEvent(node, extras);
}
else if (node.type === Token.GETPROP) { // like 'obj.prop' in '/** @typedef {string} */ obj.prop;'
// this COULD be a Closure Compiler-style typedef, but it's probably not; to avoid filling
// the parse results with junk, only fire an event if there's a JSDoc comment attached
extras = {
lineno: node.getLineno()
};
if ( node.getJsDoc() ) {
e = this._makeEvent(node, extras);
}
}
else if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
if (node.variables) {
return true; // we'll get each var separately on future visits
}
if (node.parent.variables.toArray()[0] === node) { // like /** blah */ var a=1, b=2, c=3;
// the first var assignment gets any jsDoc before the whole var series
if (typeof node.setJsDoc !== 'undefined') { node.setJsDoc( node.parent.getJsDoc() ); }
}
extras = {
lineno: node.getLineno()
};
e = this._makeEvent(node, extras);
this._trackVars(node, e);
}
else if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
extras = {
lineno: node.getLineno()
};
e = this._makeEvent(node, extras);
e.code.name = (node.type == tkn.NAMEDFUNCTIONSTATEMENT)? '' : String(node.name) || '';
this._trackVars(node, e);
basename = getBasename(e.code.name);
e.code.funcscope = this.resolveVar(node, basename);
}
if (!e) {
e = {
finishers: []
};
}
for (i = 0, l = this._visitors.length; i < l; i++) {
this._visitors[i].visitNode(node, e, this, this._currentSourceName);
if (e.stopPropagation) { break; }
}
if (!e.preventDefault && isValidJsdoc(e.comment)) {
this.emit(e.event, e, this);
}
for (i = 0, l = e.finishers.length; i < l; i++) {
e.finishers[i].call(this, e);
}
return true;
};
/** @private */
exports.Parser.prototype._parseSourceCode = function(sourceCode, sourceName) {
var NodeVisitor = Packages.org.mozilla.javascript.ast.NodeVisitor;
var ast;
var e = {
filename: sourceName
};
this.emit('fileBegin', e);
if (!e.defaultPrevented) {
e = {
filename: sourceName,
source: sourceCode
};
this.emit('beforeParse', e);
sourceCode = e.source;
this._currentSourceName = sourceName = e.filename;
sourceCode = pretreat(e.source);
ast = parserFactory().parse(sourceCode, sourceName, 1);
ast.visitComments(
new NodeVisitor({
visit: this._visitComment.bind(this)
})
);
ast.visit(
new NodeVisitor({
visit: this._visitNode.bind(this)
})
);
}
this.emit('fileComplete', e);
this._currentSourceName = '';
};
/**
* Given a node, determine what the node is a member of.
* @param {astnode} node
* @returns {string} The long name of the node that this is a member of.
*/
exports.Parser.prototype.astnodeToMemberof = function(node) {
var id,
doclet,
alias;
if (node.type === Token.VAR || node.type === Token.FUNCTION ||
node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
if (node.enclosingFunction) { // an inner var or func
id = 'astnode' + node.enclosingFunction.hashCode();
doclet = this.refs[id];
if (!doclet) {
return '<anonymous>~';
}
return (doclet.longname || doclet.name) + '~';
}
}
else {
// check local references for aliases
var scope = node,
basename = getBasename(nodeToString(node.left));
while(scope.enclosingFunction) {
id = 'astnode' + scope.enclosingFunction.hashCode();
doclet = this.refs[id];
if ( doclet && doclet.meta.vars && hasOwnProp.call(doclet.meta.vars, basename) ) {
return [doclet.meta.vars[basename], basename];
}
// move up
scope = scope.enclosingFunction;
}
// First check to see if we have a global scope alias
doclet = this.refs.__global__;
if ( doclet && doclet.meta.vars && hasOwnProp.call(doclet.meta.vars, basename) ) {
return [doclet.meta.vars[basename], basename];
}
id = 'astnode' + node.parent.hashCode();
doclet = this.refs[id];
if (!doclet) {
return ''; // global?
}
return doclet.longname || doclet.name;
}
};
/**
* Resolve what "this" refers to relative to a node.
* @param {astnode} node - The "this" node
* @returns {string} The longname of the enclosing node.
*/
exports.Parser.prototype.resolveThis = function(node) {
var memberof = {};
var parent;
if (node.type !== Token.COLON && node.enclosingFunction) {
// get documentation for the enclosing function
memberof.id = 'astnode' + node.enclosingFunction.hashCode();
memberof.doclet = this.refs[memberof.id];
if (!memberof.doclet) {
return '<anonymous>'; // TODO handle global this?
}
if (memberof.doclet['this']) {
return memberof.doclet['this'];
}
// like: Foo.constructor = function(n) { /** blah */ this.name = n; }
else if (memberof.doclet.kind === 'function' && memberof.doclet.memberof) {
return memberof.doclet.memberof;
}
// walk up to the closest class we can find
else if (memberof.doclet.kind === 'class' || memberof.doclet.kind === 'module') {
return memberof.doclet.longname || memberof.doclet.name;
}
else {
if (node.enclosingFunction){
// memberof.doclet.meta.code.val
return this.resolveThis(node.enclosingFunction);
}
else {
return ''; // TODO handle global this?
}
}
}
else if (node.parent) {
if (node.parent.type === Token.COLON) {
parent = node.parent.parent;
}
else {
parent = node.parent;
}
memberof.id = 'astnode' + parent.hashCode();
memberof.doclet = this.refs[memberof.id];
if (!memberof.doclet) {
return ''; // global?
}
return memberof.doclet.longname || memberof.doclet.name;
}
else {
return ''; // global?
}
};
/**
* Given 'var foo = { x: 1 }', find foo from x.
*/
exports.Parser.prototype.resolvePropertyParent = function(node) {
var memberof = {};
var parent;
if (node.parent && node.parent.type === Token.COLON) {
parent = node.parent.parent;
}
else {
parent = node.parent;
}
if (parent) {
memberof.id = 'astnode' + parent.hashCode();
memberof.doclet = this.refs[memberof.id];
if (memberof.doclet) {
return memberof;
}
}
};
/**
* Resolve what function a var is limited to.
* @param {astnode} node
* @param {string} basename The leftmost name in the long name: in foo.bar.zip the basename is foo.
*/
exports.Parser.prototype.resolveVar = function(node, basename) {
var doclet;
var enclosingFunction = node.enclosingFunction;
if (!enclosingFunction) {
return ''; // global
}
doclet = this.refs['astnode'+enclosingFunction.hashCode()];
if (doclet && doclet.meta.vars && basename in doclet.meta.vars) {
return doclet.longname;
}
return this.resolveVar(enclosingFunction, basename);
};
exports.Parser.prototype.addDocletRef = function(e) {
var node = e.code.node;
// allow lookup from value => doclet
if (e.doclet) {
this.refs['astnode' + node.hashCode()] = e.doclet;
}
// keep references to undocumented anonymous functions, too, as they might have scoped vars
else if ((node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) &&
!this.refs['astnode' + node.hashCode()]) {
this.refs['astnode' + node.hashCode()] = {
longname: '<anonymous>',
meta: {
code: e.code
}
};
}
};
exports.Parser.prototype.resolveEnum = function(e) {
var parent = this.resolvePropertyParent(e.code.node);
if (parent && parent.doclet.isEnum) {
if (!parent.doclet.properties) {
parent.doclet.properties = [];
}
// members of an enum inherit the enum's type
if (parent.doclet.type && !e.doclet.type) {
e.doclet.type = parent.doclet.type;
}
delete e.doclet.undocumented;
e.doclet.defaultvalue = e.doclet.meta.code.value;
// add the doclet to the parent's properties
// use a copy of the doclet to avoid circular references
parent.doclet.properties.push( require('jsdoc/util/doop').doop(e.doclet) );
}
};
/**
Fired whenever the parser encounters a JSDoc comment in the current source code.
@event jsdocCommentFound
@memberof module:jsdoc/src/parser.Parser
@param {event} e
@param {string} e.comment The text content of the JSDoc comment
@param {number} e.lineno The line number associated with the found comment.
@param {string} e.filename The file name associated with the found comment.
*/

View file

@ -0,0 +1,58 @@
/**
@module jsdoc/src/scanner
@requires module:fs
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
/**
@constructor
@mixes module:events
*/
exports.Scanner = function() {};
exports.Scanner.prototype = Object.create( require('events').EventEmitter.prototype );
/**
Recursively searches the given searchPaths for js files.
@param {Array.<string>} searchPaths
@param {number} [depth=1]
@fires sourceFileFound
*/
exports.Scanner.prototype.scan = function(searchPaths, depth, filter) {
var cwd = process.cwd(),
filePaths = [],
self = this;
searchPaths = searchPaths || [];
depth = depth || 1;
searchPaths.forEach(function($) {
var filepath = decodeURIComponent($);
if ( fs.statSync(filepath).isFile() ) {
filePaths.push( path.resolve(cwd, filepath) );
}
else {
filePaths = filePaths.concat( fs.ls(filepath, depth).map(function(item) {
return path.resolve(cwd, item);
}) );
}
});
filePaths = filePaths.filter(function($) {
return filter.isIncluded($);
});
filePaths = filePaths.filter(function($) {
var e = { fileName: $ };
self.emit('sourceFileFound', e);
return !e.defaultPrevented;
});
return filePaths;
};

View file

@ -0,0 +1,103 @@
/*global env: true */
/**
@overview
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
Functionality related to JSDoc tags.
@module jsdoc/tag
@requires jsdoc/tag/dictionary
@requires jsdoc/tag/validator
@requires jsdoc/tag/type
*/
var jsdoc = {
tag: {
dictionary: require('jsdoc/tag/dictionary'),
validator: require('jsdoc/tag/validator'),
type: require('jsdoc/tag/type')
}
};
function trim(text, newlines) {
if (!text) { return ''; }
if (newlines) {
return text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');
}
else {
return text.replace(/^\s+|\s+$/g, '');
}
}
function processTagText(tag, tagDef) {
var tagType;
if (tagDef.onTagText) {
tag.text = tagDef.onTagText(tag.text);
}
if (tagDef.canHaveType || tagDef.canHaveName) {
/** The value property represents the result of parsing the tag text. */
tag.value = {};
tagType = jsdoc.tag.type.parse(tag.text, tagDef.canHaveName, tagDef.canHaveType);
// It is possible for a tag to *not* have a type but still have
// optional or defaultvalue, e.g. '@param [foo]'.
// Although tagType.type.length == 0 we should still copy the other properties.
if (tagType.type) {
if (tagType.type.length) {
tag.value.type = {
names: tagType.type
};
}
tag.value.optional = tagType.optional;
tag.value.nullable = tagType.nullable;
tag.value.variable = tagType.variable;
tag.value.defaultvalue = tagType.defaultvalue;
}
if (tagType.text && tagType.text.length) {
tag.value.description = tagType.text;
}
if (tagDef.canHaveName) {
// note the dash is a special case: as a param name it means "no name"
if (tagType.name && tagType.name !== '-') { tag.value.name = tagType.name; }
}
}
else {
tag.value = tag.text;
}
}
/**
Constructs a new tag object. Calls the tag validator.
@class
@classdesc Represents a single doclet tag.
@param {string} tagTitle
@param {string=} tagBody
@param {object=} meta
*/
var Tag = exports.Tag = function(tagTitle, tagBody, meta) {
meta = meta || {};
this.originalTitle = trim(tagTitle);
/** The title part of the tag: @title text */
this.title = jsdoc.tag.dictionary.normalise(this.originalTitle);
var tagDef = jsdoc.tag.dictionary.lookUp(this.title);
/** The text part of the tag: @title text */
this.text = trim(tagBody, tagDef.keepsWhitespace);
if (this.text) {
processTagText(this, tagDef);
}
jsdoc.tag.validator.validate(this, tagDef, meta);
};

View file

@ -0,0 +1,85 @@
/**
@overview
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var hasOwnProp = Object.prototype.hasOwnProperty;
var _tags = {};
var _tagSynonyms = {};
var _namespaces = [];
var dictionary;
/** @private */
function TagDefinition(title, etc) {
var self = this;
etc = etc || {};
this.title = dictionary.normalise(title);
Object.keys(etc).forEach(function(p) {
self[p] = etc[p];
});
}
/** @private */
TagDefinition.prototype.synonym = function(synonymName) {
_tagSynonyms[synonymName.toLowerCase()] = this.title;
return this; // chainable
};
/** @exports jsdoc/tag/dictionary */
dictionary = {
/** @function */
defineTag: function(title, opts) {
var def = new TagDefinition(title, opts);
// all the other dictionary functions use normalised names; we should too.
_tags[def.title] = def;
if (opts.isNamespace) {
_namespaces.push(def.title);
}
return _tags[def.title];
},
/** @function */
lookUp: function(title) {
title = dictionary.normalise(title);
if ( hasOwnProp.call(_tags, title) ) {
return _tags[title];
}
return false;
},
/** @function */
isNamespace: function(kind) {
if (kind) {
kind = dictionary.normalise(kind);
if ( _namespaces.indexOf(kind) !== -1) {
return true;
}
}
return false;
},
/** @function */
normalise: function(title) {
var canonicalName = title.toLowerCase();
if ( hasOwnProp.call(_tagSynonyms, canonicalName) ) {
return _tagSynonyms[canonicalName];
}
return canonicalName;
}
};
require('jsdoc/tag/dictionary/definitions').defineTags(dictionary);
module.exports = dictionary;

View file

@ -0,0 +1,677 @@
/*global app: true, env: true */
/**
Define tags that are known in JSDoc.
@module jsdoc/tag/dictionary/definitions
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var path = require('path');
/** @private */
function setDocletKindToTitle(doclet, tag) {
doclet.addTag( 'kind', tag.title );
}
function setDocletScopeToTitle(doclet, tag) {
doclet.addTag( 'scope', tag.title );
}
function setDocletNameToValue(doclet, tag) {
if (tag.value && tag.value.description) { // as in a long tag
doclet.addTag( 'name', tag.value.description);
}
else if (tag.text) { // or a short tag
doclet.addTag('name', tag.text);
}
}
function setDocletDescriptionToValue(doclet, tag) {
if (tag.value) {
doclet.addTag( 'description', tag.value );
}
}
function setNameToFile(doclet, tag) {
var name = '';
if (doclet.meta.filename) {
// TODO: find the shortest path shared by all input files, and remove that from
// doclet.meta.path
name += path.basename(doclet.meta.path) + '/';
doclet.addTag( 'name', name + doclet.meta.filename );
}
}
function setDocletMemberof(doclet, tag) {
if (tag.value && tag.value !== '<global>') {
doclet.setMemberof(tag.value);
}
}
function applyNamespace(docletOrNs, tag) {
if (typeof docletOrNs === 'string') { // ns
tag.value = app.jsdoc.name.applyNamespace(tag.value, docletOrNs);
}
else { // doclet
if (!docletOrNs.name) {
return; // error?
}
//doclet.displayname = doclet.name;
docletOrNs.longname = app.jsdoc.name.applyNamespace(docletOrNs.name, tag.title);
}
}
function setDocletNameToFilename(doclet, tag) {
// TODO: find the shortest path shared by all input files, and remove that from doclet.meta.path
var name = doclet.meta.path ? path.basename(doclet.meta.path) + '/' : '';
name += doclet.meta.filename;
name = name.replace(/\.js$/i, '');
for (var i = 0, len = env.opts._.length; i < len; i++) {
if (name.indexOf(env.opts._[i]) === 0) {
name = name.replace(env.opts._[0], '');
break;
}
}
doclet.name = name;
}
function parseBorrows(doclet, tag) {
var m = /^(\S+)(?:\s+as\s+(\S+))?$/.exec(tag.text);
if (m) {
if (m[1] && m[2]) {
return { target: m[1], source: m[2] };
}
else if (m[1]) {
return { target: m[1] };
}
} else {
return {};
}
}
function firstWordOf(string) {
var m = /^(\S+)/.exec(string);
if (m) { return m[1]; }
else { return ''; }
}
/** Populate the given dictionary with all known JSDoc tag definitions.
@param {module:jsdoc/tag/dictionary} dictionary
*/
exports.defineTags = function(dictionary) {
dictionary.defineTag('abstract', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
// since "abstract" is reserved word in JavaScript let's use "virtual" in code
doclet.virtual = true;
}
})
.synonym('virtual');
dictionary.defineTag('access', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
// only valid values are private and protected, public is default
if ( /^(private|protected)$/i.test(tag.value) ) {
doclet.access = tag.value.toLowerCase();
}
else {
delete doclet.access;
}
}
});
dictionary.defineTag('alias', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.alias = tag.value;
}
});
dictionary.defineTag('author', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.author) { doclet.author = []; }
doclet.author.push(tag.value);
}
});
// I add on to that
dictionary.defineTag('augments', {
mustHaveValue: true,
// Allow augments value to be specified as a normal type, e.g. {Type}
onTagText: function(text) {
var type = require('jsdoc/tag/type'),
tagType = type.parse(text, false, true);
return tagType.typeExpression || text;
},
onTagged: function(doclet, tag) {
doclet.augment( firstWordOf(tag.value) );
}
})
.synonym('extends');
// that adds on to me
dictionary.defineTag('borrows', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
var borrows = parseBorrows(doclet, tag);
doclet.borrow(borrows.target, borrows.source);
}
});
// that adds all of it's members to me
dictionary.defineTag('mixes', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
var source = firstWordOf(tag.value);
doclet.mix(source);
}
});
dictionary.defineTag('class', {
onTagged: function(doclet, tag) {
doclet.addTag('kind', 'class');
// handle special case where both @class and @constructor tags exist in same doclet
if (tag.originalTitle === 'class') {
var looksLikeDesc = (tag.value || '').match(/\S+\s+\S+/); // multiple words after @class?
if ( looksLikeDesc || /@construct(s|or)\b/i.test(doclet.comment) ) {
doclet.classdesc = tag.value; // treat the @class tag as a @classdesc tag instead
return;
}
}
setDocletNameToValue(doclet, tag);
}
})
.synonym('constructor');
dictionary.defineTag('classdesc', {
onTagged: function(doclet, tag) {
doclet.classdesc = tag.value;
}
});
dictionary.defineTag('constant', {
canHaveType: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
}
}
})
.synonym('const');
dictionary.defineTag('copyright', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.copyright = tag.value;
}
});
dictionary.defineTag('constructs', {
onTagged: function(doclet, tag) {
var ownerClassName;
if (!tag.value) {
ownerClassName = '{@thisClass}'; // this can be resolved later in the handlers
}
else {
ownerClassName = firstWordOf(tag.value);
}
doclet.addTag('alias', ownerClassName);
doclet.addTag('kind', 'class');
}
});
dictionary.defineTag('default', {
onTagged: function(doclet, tag) {
if (tag.value) {
doclet.defaultvalue = tag.value;
}
else if (doclet.meta && doclet.meta.code && typeof doclet.meta.code.value !== 'undefined') {
if (doclet.meta.code.type && /STRING|NUMBER|NAME|TRUE|FALSE/.test(doclet.meta.code.type)) {
doclet.defaultvalue = doclet.meta.code.value;
if (doclet.meta.code.type === 'STRING') {
// TODO: handle escaped quotes in values
doclet.defaultvalue = '"'+doclet.defaultvalue.replace(/"/g, '\\"')+'"';
}
if (doclet.defaultvalue === 'TRUE' || doclet.defaultvalue == 'FALSE') {
doclet.defaultvalue = doclet.defaultvalue.toLowerCase();
}
}
else if (doclet.meta.code.type === 'NULL') {
// TODO: handle escaped quotes in values
doclet.defaultvalue = 'null';
}
}
}
})
.synonym('defaultvalue');
dictionary.defineTag('deprecated', {
// value is optional
onTagged: function(doclet, tag) {
doclet.deprecated = tag.value || true;
}
});
dictionary.defineTag('description', {
mustHaveValue: true
})
.synonym('desc');
dictionary.defineTag('enum', {
canHaveType: true,
onTagged: function(doclet, tag) {
doclet.kind = 'member';
doclet.isEnum = true;
if (tag.value && tag.value.type) { doclet.type = tag.value.type; }
}
});
dictionary.defineTag('event', {
isNamespace: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
}
});
dictionary.defineTag('example', {
keepsWhitespace: true,
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.examples) { doclet.examples = []; }
doclet.examples.push(tag.value);
}
});
dictionary.defineTag('exception', {
mustHaveValue: true,
canHaveType: true,
onTagged: function(doclet, tag) {
if (!doclet.exceptions) { doclet.exceptions = []; }
doclet.exceptions.push(tag.value);
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
}
}
})
.synonym('throws');
dictionary.defineTag('external', {
canHaveType: true,
isNamespace: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
}
}
})
.synonym('host');
dictionary.defineTag('exports', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
var modName = firstWordOf(tag.value);
doclet.addTag('alias', modName);
doclet.addTag('kind', 'module');
}
});
dictionary.defineTag('file', {
onTagged: function(doclet, tag) {
setNameToFile(doclet, tag);
setDocletKindToTitle(doclet, tag);
setDocletDescriptionToValue(doclet, tag);
doclet.preserveName = true;
}
})
.synonym('fileoverview')
.synonym('overview');
dictionary.defineTag('fires', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.fires) { doclet.fires = []; }
applyNamespace('event', tag);
doclet.fires.push(tag.value);
}
})
.synonym('emits');
dictionary.defineTag('function', {
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
}
})
.synonym('func')
.synonym('method');
dictionary.defineTag('global', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
doclet.scope = 'global';
delete doclet.memberof;
}
});
dictionary.defineTag('ignore', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
doclet.ignore = true;
}
});
dictionary.defineTag('inner', {
onTagged: function(doclet, tag) {
setDocletScopeToTitle(doclet, tag);
}
});
dictionary.defineTag('instance', {
onTagged: function(doclet, tag) {
setDocletScopeToTitle(doclet, tag);
}
});
dictionary.defineTag('kind', {
mustHaveValue: true
});
dictionary.defineTag('lends', {
onTagged: function(doclet, tag) {
doclet.alias = tag.value || '<global>';
doclet.addTag('undocumented');
}
});
dictionary.defineTag('license', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.license = tag.value;
}
});
dictionary.defineTag('listens', {
mustHaveValue: true,
onTagged: function (doclet, tag) {
if (!doclet.listens) { doclet.listens = []; }
applyNamespace('event', tag);
doclet.listens.push(tag.value);
// TODO: verify that parameters match the event parameters?
}
});
dictionary.defineTag('member', {
canHaveType: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
}
}
})
.synonym('var');
dictionary.defineTag('memberof', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (tag.originalTitle === 'memberof!') {
doclet.forceMemberof = true;
if (tag.value === '<global>') {
doclet.addTag('global');
delete doclet.memberof;
}
}
setDocletMemberof(doclet, tag);
}
})
.synonym('memberof!');
dictionary.defineTag('mixin', {
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
}
});
dictionary.defineTag('module', {
canHaveType: true,
isNamespace: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
if (!doclet.name) {
setDocletNameToFilename(doclet, tag);
}
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
}
}
});
dictionary.defineTag('name', {
mustHaveValue: true
});
dictionary.defineTag('namespace', {
canHaveType: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
setDocletNameToValue(doclet, tag);
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
}
}
});
dictionary.defineTag('param', {
//mustHaveValue: true, // param name can be found in the source code if not provided
canHaveType: true,
canHaveName: true,
onTagged: function(doclet, tag) {
if (!doclet.params) { doclet.params = []; }
doclet.params.push(tag.value||{});
}
})
.synonym('argument')
.synonym('arg');
dictionary.defineTag('private', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
doclet.access = 'private';
}
});
dictionary.defineTag('property', {
mustHaveValue: true,
canHaveType: true,
canHaveName: true,
onTagged: function(doclet, tag) {
if (!doclet.properties) { doclet.properties = []; }
doclet.properties.push(tag.value);
}
})
.synonym('prop');
dictionary.defineTag('protected', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
doclet.access = 'protected';
}
});
dictionary.defineTag('public', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
delete doclet.access; // public is default
}
});
// use this instead of old deprecated @final tag
dictionary.defineTag('readonly', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
doclet.readonly = true;
}
});
dictionary.defineTag('requires', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
var modName = firstWordOf(tag.value);
if (modName.indexOf('module:') !== 0) {
modName = 'module:'+modName;
}
if (!doclet.requires) { doclet.requires = []; }
doclet.requires.push(modName);
}
});
dictionary.defineTag('returns', {
mustHaveValue: true,
canHaveType: true,
onTagged: function(doclet, tag) {
if (!doclet.returns) { doclet.returns = []; }
doclet.returns.push(tag.value);
}
})
.synonym('return');
dictionary.defineTag('see', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.see) { doclet.see = []; }
doclet.see.push(tag.value);
}
});
dictionary.defineTag('since', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.since = tag.value;
}
});
dictionary.defineTag('static', {
onTagged: function(doclet, tag) {
setDocletScopeToTitle(doclet, tag);
}
});
dictionary.defineTag('summary', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.summary = tag.value;
}
});
dictionary.defineTag('this', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.see) { doclet.see = []; }
doclet['this'] = firstWordOf(tag.value);
}
});
dictionary.defineTag('todo', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.todo) { doclet.todo = []; }
doclet.todo.push(tag.value);
}
});
dictionary.defineTag('tutorial', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
if (!doclet.tutorials) { doclet.tutorials = []; }
doclet.tutorials.push(tag.value);
}
});
dictionary.defineTag('type', {
mustHaveValue: true,
canHaveType: true,
onTagText: function(text) {
// any text must be formatted as a type, but for back compat braces are optional
if ( ! /^\{.+\}$/.test(text) ) {
text = '{ '+text+' }';
}
return text;
},
onTagged: function(doclet, tag) {
if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
if (doclet.kind === 'function') {
doclet.addTag('returns', tag.text); // for backwards compatibility we allow @type for functions to imply return type
}
}
}
});
dictionary.defineTag('typedef', {
canHaveType: true,
canHaveName: true,
onTagged: function(doclet, tag) {
setDocletKindToTitle(doclet, tag);
if (tag.value) {
if (tag.value.name) {
doclet.addTag('name', tag.value.name);
}
// callbacks are always type {function}
if (tag.originalTitle === 'callback') {
doclet.type = {
names: [
'function'
]
};
}
else if (tag.value.type) {
doclet.type = tag.value.type;
}
}
}
})
.synonym('callback');
dictionary.defineTag('undocumented', {
mustNotHaveValue: true,
onTagged: function(doclet, tag) {
doclet.undocumented = true;
doclet.comment = '';
}
});
dictionary.defineTag('variation', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.variation = tag.value;
}
});
dictionary.defineTag('version', {
mustHaveValue: true,
onTagged: function(doclet, tag) {
doclet.version = tag.value;
}
});
};

View file

@ -0,0 +1,107 @@
/**
* @module jsdoc/tag/inline
*
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
* Information about an inline tag that was found within a string.
*
* @typedef {Object} InlineTagInfo
* @memberof module:jsdoc/tag/inline
* @property {?string} completeTag - The entire inline tag, including its enclosing braces.
* @property {?string} tag - The tag whose text was found.
* @property {?string} text - The tag text that was found.
*/
/**
* Information about the results of replacing inline tags within a string.
*
* @typedef {Object} InlineTagResult
* @memberof module:jsdoc/tag/inline
* @property {Array.<module:jsdoc/tag/inline.InlineTagInfo>} tags - The inline tags that were found.
* @property {string} newString - The updated text string after extracting or replacing the inline
* tags.
*/
/**
* Text-replacing function for strings that contain an inline tag.
*
* @callback InlineTagReplacer
* @memberof module:jsdoc/tag/inline
* @param {string} string - The complete string containing the inline tag.
* @param {module:jsdoc/tag/inline.InlineTagInfo} tagInfo - Information about the inline tag.
* @return {string} An updated version of the complete string.
*/
/**
* Replace all instances of multiple inline tags with other text.
*
* @param {string} string - The string in which to replace the inline tags.
* @param {Object} replacers - The functions that are used to replace text in the string. The keys
* must contain tag names (for example, `link`), and the values must contain functions with the
* type {@link module:jsdoc/tag/inline.InlineTagReplacer}.
* @return {module:jsdoc/tag/inline.InlineTagResult} The updated string, as well as information
* about the inline tags that were found.
*/
exports.replaceInlineTags = function(string, replacers) {
var tagInfo = [];
function replaceMatch(replacer, tag, match, text) {
var matchedTag = {
completeTag: match,
tag: tag,
text: text
};
tagInfo.push(matchedTag);
return replacer.call(this, string, matchedTag);
}
string = string || '';
Object.keys(replacers).forEach(function(replacer) {
var tagRegExp = new RegExp('\\{@' + replacer + '\\s+(.+?)\\}', 'gi');
var matches;
// call the replacer once for each match
while ( (matches = tagRegExp.exec(string)) !== null ) {
string = replaceMatch(replacers[replacer], replacer, matches[0], matches[1]);
}
});
return {
tags: tagInfo,
newString: string.trim()
};
};
/**
* Replace all instances of an inline tag with other text.
*
* @param {string} string - The string in which to replace the inline tag.
* @param {string} tag - The name of the inline tag to replace.
* @param {module:jsdoc/tag/inline.InlineTagReplacer} replacer - The function that is used to
* replace text in the string.
* @return {module:jsdoc/tag/inline.InlineTagResult} The updated string, as well as information
* about the inline tags that were found.
*/
exports.replaceInlineTag = function(string, tag, replacer) {
var replacers = {};
replacers[tag] = replacer;
return exports.replaceInlineTags(string, replacers);
};
/**
* Extract inline tags from a string, replacing them with an empty string.
*
* @param {string} string - The string from which to extract text.
* @param {?string} tag - The inline tag to extract.
* @return {module:jsdoc/tag/inline.InlineTagResult} The updated string, as well as information
* about the inline tags that were found.
*/
exports.extractInlineTag = function(string, tag) {
return exports.replaceInlineTag(string, tag, function(str, tagInfo) {
return str.replace(tagInfo.completeTag, '');
});
};

View file

@ -0,0 +1,286 @@
/**
* @module jsdoc/tag/type
*
* @author Michael Mathews <micmath@gmail.com>
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
* Information about a type expression extracted from tag text.
*
* @typedef TypeExpressionInfo
* @memberof module:jsdoc/tag/type
* @property {string} expression - The type expression.
* @property {string} text - The updated tag text.
*/
/** @private */
function unescapeBraces(text) {
return text.replace(/\\\{/g, '{')
.replace(/\\\}/g, '}');
}
/**
* Extract a type expression from the tag text.
*
* @private
* @param {string} string - The tag text.
* @return {module:jsdoc/tag/type.TypeExpressionInfo} The type expression and updated tag text.
*/
function extractTypeExpression(string) {
string = string || '';
var completeExpression;
var count = 0;
var position = 0;
var expression = '';
var startIndex = string.indexOf('{');
var textStartIndex;
if (startIndex !== -1) {
// advance to the first character in the type expression
position = textStartIndex = startIndex + 1;
count++;
while (position < string.length) {
switch (string[position]) {
case '\\':
// backslash is an escape character, so skip the next character
position++;
break;
case '{':
count++;
break;
case '}':
count--;
break;
default:
// do nothing
}
if (count === 0) {
completeExpression = string.slice(startIndex, position + 1);
expression = string.slice(textStartIndex, position).trim();
break;
}
position++;
}
}
string = completeExpression ? string.replace(completeExpression, '') : string;
return {
expression: unescapeBraces(expression),
newString: string.trim()
};
}
/** @private */
function getTagInfo(tagValue, canHaveName, canHaveType) {
var name = '';
var typeExpression = '';
var text = tagValue;
var expressionAndText;
var typeOverride;
if (canHaveType) {
expressionAndText = extractTypeExpression(text);
typeExpression = expressionAndText.expression;
text = expressionAndText.newString;
}
if (canHaveName) {
// like: name, [name], name text, [name] text, name - text, or [name] - text
text.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
name = RegExp.$1;
text = RegExp.$3;
}
// an inline @type tag, like {@type Foo}, overrides the type expression
if (canHaveType) {
typeOverride = require('jsdoc/tag/inline').extractInlineTag(text, 'type');
if (typeOverride.tags && typeOverride.tags[0]) {
typeExpression = typeOverride.tags[0].text || typeExpression;
}
text = typeOverride.newString;
}
return {
name: name,
typeExpression: typeExpression,
text: text
};
}
/**
* Information provided in a JSDoc tag.
*
* @typedef {Object} TagInfo
* @memberof module:jsdoc/tag/type
* @property {string} TagInfo.defaultvalue - The default value of the member.
* @property {string} TagInfo.name - The name of the member (for example, `myParamName`).
* @property {boolean} TagInfo.nullable - Indicates whether the member can be set to `null` or
* `undefined`.
* @property {boolean} TagInfo.optional - Indicates whether the member is optional.
* @property {string} TagInfo.text - Descriptive text for the member (for example, `The user's email
* address.`).
* @property {Array.<string>} TagInfo.type - The type or types that the member can contain (for
* example, `string` or `MyNamespace.MyClass`).
* @property {string} TagInfo.typeExpression - The type expression that was parsed to identify the
* types.
* @property {boolean} TagInfo.variable - Indicates whether the number of members that are provided
* can vary (for example, in a function that accepts any number of parameters).
*/
/**
* Extract JSDoc-style type information from the name specified in the tag info, including the
* member name; whether the member is optional; and the default value of the member.
*
* @private
* @param {module:jsdoc/tag/type.TagInfo} tagInfo - Information contained in the tag.
* @return {module:jsdoc/tag/type.TagInfo} Updated information from the tag.
*/
function parseName(tagInfo) {
// like '[foo]' or '[ foo ]' or '[foo=bar]' or '[ foo=bar ]' or '[ foo = bar ]'
if ( /^\[\s*(.+?)\s*\]$/.test(tagInfo.name) ) {
tagInfo.name = RegExp.$1;
tagInfo.optional = true;
// like 'foo=bar' or 'foo = bar'
if ( /^(.+?)\s*=\s*(.+)$/.test(tagInfo.name) ) {
tagInfo.name = RegExp.$1;
tagInfo.defaultvalue = RegExp.$2;
}
}
return tagInfo;
}
/** @private */
function getTypeStrings(parsedType) {
var types = [];
var catharsis = require('catharsis');
var TYPES = catharsis.Types;
var util = require('util');
switch(parsedType.type) {
case TYPES.AllLiteral:
types.push('*');
break;
case TYPES.FunctionType:
types.push('function');
break;
case TYPES.NameExpression:
types.push(parsedType.name);
break;
case TYPES.NullLiteral:
types.push('null');
break;
case TYPES.RecordType:
types.push('Object');
break;
case TYPES.TypeApplication:
types.push( catharsis.stringify(parsedType) );
break;
case TYPES.TypeUnion:
parsedType.elements.forEach(function(element) {
types = types.concat( getTypeStrings(element) );
});
break;
case TYPES.UndefinedLiteral:
types.push('undefined');
break;
case TYPES.UnknownLiteral:
types.push('?');
break;
default:
// this shouldn't happen
throw new Error( util.format('unrecognized type %s in parsed type: %j', parsedType.type,
parsedType) );
}
return types;
}
/**
* Extract JSDoc-style and Closure Compiler-style type information from the type expression
* specified in the tag info.
*
* @private
* @param {module:jsdoc/tag/type.TagInfo} tagInfo - Information contained in the tag.
* @return {module:jsdoc/tag/type.TagInfo} Updated information from the tag.
*/
function parseTypeExpression(tagInfo) {
var catharsis = require('catharsis');
var util = require('util');
var errorMessage;
var parsedType;
// don't try to parse empty type expressions
if (!tagInfo.typeExpression) {
return tagInfo;
}
try {
parsedType = catharsis.parse(tagInfo.typeExpression, {jsdoc: true});
}
catch (e) {
// always re-throw so the caller has a chance to report which file was bad
throw new Error( util.format('unable to parse the type expression "%s": %s',
tagInfo.typeExpression, e.message) );
}
if (parsedType) {
tagInfo.type = tagInfo.type.concat( getTypeStrings(parsedType) );
// Catharsis and JSDoc use the same names for 'optional' and 'nullable'...
['optional', 'nullable'].forEach(function(key) {
if (parsedType[key] !== null && parsedType[key] !== undefined) {
tagInfo[key] = parsedType[key];
}
});
// ...but not 'variable'.
if (parsedType.repeatable !== null && parsedType.repeatable !== undefined) {
tagInfo.variable = parsedType.repeatable;
}
}
return tagInfo;
}
// TODO: allow users to add/remove type parsers (perhaps via plugins)
var typeParsers = [parseName, parseTypeExpression];
/**
* Parse the value of a JSDoc tag.
*
* @param {string} tagValue - The value of the tag. For example, the tag `@param {string} name` has
* a value of `{string} name`.
* @param {boolean} canHaveName - Indicates whether the value can include a symbol name.
* @param {boolean} canHaveType - Indicates whether the value can include a type expression that
* describes the symbol.
* @return {module:jsdoc/tag/type.TagInfo} Information obtained from the tag.
* @throws {Error} Thrown if a type expression cannot be parsed.
*/
exports.parse = function(tagValue, canHaveName, canHaveType) {
if (typeof tagValue !== 'string') { tagValue = ''; }
var tagInfo = getTagInfo(tagValue, canHaveName, canHaveType);
tagInfo.type = tagInfo.type || [];
typeParsers.forEach(function(parser) {
tagInfo = parser.call(this, tagInfo);
});
// if we wanted a type, but the parsers didn't add any type names, use the type expression
if (canHaveType && !tagInfo.type.length && tagInfo.typeExpression) {
tagInfo.type = [tagInfo.typeExpression];
}
return tagInfo;
};

View file

@ -0,0 +1,62 @@
/*global env: true */
/**
@module jsdoc/tag/validator
@requires jsdoc/tag/dictionary
@author Michael Mathews <micmath@gmail.com>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var dictionary = require('jsdoc/tag/dictionary');
var format = require('util').format;
function buildMessage(tagName, meta, desc) {
var result = format('The @%s tag %s. File: %s, line: %s', tagName, desc, meta.filename,
meta.lineno);
if (meta.comment) {
result += '\n' + meta.comment;
}
return result;
}
function UnknownTagError(tagName, meta) {
this.name = 'UnknownTagError';
this.message = buildMessage(tagName, meta, 'is not a known tag');
}
UnknownTagError.prototype = new Error();
UnknownTagError.prototype.constructor = UnknownTagError;
function TagValueRequiredError(tagName, meta) {
this.name = 'TagValueRequiredError';
this.message = buildMessage(tagName, meta, 'requires a value');
}
TagValueRequiredError.prototype = new Error();
TagValueRequiredError.prototype.constructor = TagValueRequiredError;
function TagValueNotPermittedError(tagName, meta) {
this.name = 'TagValueNotPermittedError';
this.message = buildMessage(tagName, meta, 'does not permit a value');
}
TagValueNotPermittedError.prototype = new Error();
TagValueNotPermittedError.prototype.constructor = TagValueNotPermittedError;
/**
* Validate the given tag.
*/
exports.validate = function(tag, tagDef, meta) {
if (!tagDef && !env.conf.tags.allowUnknownTags) {
require('jsdoc/util/error').handle( new UnknownTagError(tag.title, meta) );
}
if (!tag.text) {
if (tagDef.mustHaveValue) {
require('jsdoc/util/error').handle( new TagValueRequiredError(tag.title, meta) );
}
}
else {
if (tagDef.mustNotHaveValue) {
require('jsdoc/util/error').handle( new TagValueNotPermittedError(tag.title, meta) );
}
}
};

View file

@ -0,0 +1,84 @@
/**
* @file Wrapper for underscore's template utility to allow loading templates from files.
* @author Rafał Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
* @author <a href="mailto:matthewkastor@gmail.com">Matthew Christopher Kastor-Inare III</a>
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var _ = require('underscore'),
fs = require('jsdoc/fs'),
path = require('path');
/**
@module jsdoc/template
*/
/**
@class
@classdesc Underscore template helper.
@param {string} path - Templates directory.
*/
exports.Template = function(path) {
this.path = path;
this.layout = null;
this.cache = {};
// override default template tag settings
this.settings = {
evaluate : /<\?js([\s\S]+?)\?>/g,
interpolate: /<\?js=([\s\S]+?)\?>/g,
escape : /<\?js~([\s\S]+?)\?>/g
};
};
/** Loads template from given file.
@param {string} file - Template filename.
@return {function} Returns template closure.
*/
exports.Template.prototype.load = function(file) {
var _path = path.join(this.path, file);
return _.template(fs.readFileSync(_path, 'utf8'), null, this.settings);
};
/**
Renders template using given data.
This is low-level function, for rendering full templates use {@link Template.render()}.
@param {string} file - Template filename.
@param {object} data - Template variables (doesn't have to be object, but passing variables dictionary is best way and most common use).
@return {string} Rendered template.
*/
exports.Template.prototype.partial = function(file, data) {
// load template into cache
if (!(file in this.cache)) {
this.cache[file] = this.load(file);
}
// keep template helper context
return this.cache[file].call(this, data);
};
/**
Renders template with given data.
This method automaticaly applies layout if set.
@param {string} file - Template filename.
@param {object} data - Template variables (doesn't have to be object, but passing variables dictionary is best way and most common use).
@return {string} Rendered template.
*/
exports.Template.prototype.render = function(file, data) {
// main content
var content = this.partial(file, data);
// apply layout
if (this.layout) {
data.content = content;
content = this.partial(this.layout, data);
}
return content;
};

View file

@ -0,0 +1,110 @@
/**
@overview
@author Rafał Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var markdown = require('jsdoc/util/markdown');
/** Removes child tutorial from the parent. Does *not* unset child.parent though.
@param {Tutorial} parent - parent tutorial.
@param {Tutorial} child - Old child.
@private
*/
function removeChild(parent, child) {
var index = parent.children.indexOf(child);
if (index != -1) {
parent.children.splice(index, 1);
}
}
/** Adds a child to the parent tutorial. Does *not* set child.parent though.
@param {Tutorial} parent - parent tutorial.
@param {Tutorial} child - New child.
@private
*/
function addChild(parent, child) {
parent.children.push(child);
}
/**
@module jsdoc/tutorial
*/
/**
@class
@classdesc Represents a single JSDoc tutorial.
@param {string} name - Tutorial name.
@param {string} content - Text content.
@param {number} type - Source formating.
*/
exports.Tutorial = function(name, content, type) {
this.title = this.name = name;
this.content = content;
this.type = type;
// default values
this.parent = null;
this.children = [];
};
/** Moves children from current parent to different one.
@param {?Tutorial} parent - New parent. If null, the tutorial has no parent.
*/
exports.Tutorial.prototype.setParent = function(parent) {
// removes node from old parent
if (this.parent) {
removeChild(this.parent, this);
}
this.parent = parent;
if (parent) {
addChild(parent, this);
}
};
/** Removes children from current node.
@param {Tutorial} child - Old child.
*/
exports.Tutorial.prototype.removeChild = function(child) {
child.setParent(null);
};
/** Adds new children to current node.
@param {Tutorial} child - New child.
*/
exports.Tutorial.prototype.addChild = function(child) {
child.setParent(this);
};
/** Prepares source.
@return {string} HTML source.
*/
exports.Tutorial.prototype.parse = function() {
switch (this.type) {
// nothing to do
case exports.TYPES.HTML:
return this.content;
// markdown
case exports.TYPES.MARKDOWN:
var mdParse = markdown.getParser();
return mdParse(this.content)
.replace(/&amp;/g, '&') // because markdown escapes these
.replace(/&lt;/g, '<')
.replace(/&gt;/g, '>');
// uhm... should we react somehow?
// if not then this case can be merged with TYPES.HTML
default:
return this.content;
}
};
/** Tutorial source types.
@enum {number}
*/
exports.TYPES = {
HTML: 1,
MARKDOWN: 2
};

View file

@ -0,0 +1,190 @@
/*global env: true */
/**
@overview
@author Rafa&#322; Wrzeszcz <rafal.wrzeszcz@wrzasq.pl>
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
/**
@module jsdoc/tutorial/resolver
*/
var tutorial = require('jsdoc/tutorial'),
fs = require('jsdoc/fs'),
error = require('jsdoc/util/error'),
path = require('path'),
hasOwnProp = Object.prototype.hasOwnProperty,
conf = {},
tutorials = {},
finder = /^(.*)\.(x(?:ht)?ml|html?|md|markdown|json)$/i;
/** checks if `conf` is the metadata for a single tutorial.
* A tutorial's metadata has a property 'title' and/or a property 'children'.
* @param {object} json - the object we want to test (typically from JSON.parse)
* @returns {boolean} whether `json` could be the metadata for a tutorial.
*/
function isTutorialJSON(json) {
// if conf.title exists or conf.children exists, it is metadata for a tutorial
return (hasOwnProp.call(json, 'title') || hasOwnProp.call(json, 'children'));
}
/** Helper function that adds tutorial configuration to the `conf` variable.
* This helps when multiple tutorial configurations are specified in one object,
* or when a tutorial's children are specified as tutorial configurations as
* opposed to an array of tutorial names.
*
* Recurses as necessary to ensure all tutorials are added.
*
* @param {string} name - if `meta` is a configuration for a single tutorial,
* this is that tutorial's name.
* @param {object} meta - object that contains tutorial information.
* Can either be for a single tutorial, or for multiple
* (where each key in `meta` is the tutorial name and each
* value is the information for a single tutorial).
* Additionally, a tutorial's 'children' property may
* either be an array of strings (names of the child tutorials),
* OR an object giving the configuration for the child tutorials.
*/
function addTutorialConf(name, meta) {
var names, i;
if (isTutorialJSON(meta)) {
// if the children are themselves tutorial defintions as opposed to an
// array of strings, add each child.
if (hasOwnProp.call(meta, 'children') && !Array.isArray(meta.children)) {
names = Object.keys(meta.children);
for (i = 0; i < names.length; ++i) {
addTutorialConf(names[i], meta.children[names[i]]);
}
// replace with an array of names.
meta.children = names;
}
// check if the tutorial has already been defined...
if (hasOwnProp.call(conf, name)) {
error.handle(new Error("Tutorial " + name + "'s metadata is defined multiple times, only the first will be used."));
} else {
conf[name] = meta;
}
} else {
// it's an object of tutorials, the keys are th etutorial names.
names = Object.keys(meta);
for (i = 0; i < names.length; ++i) {
addTutorialConf(names[i], meta[names[i]]);
}
}
}
/** Adds new tutorial.
@param {tutorial.Tutorial} current - New tutorial.
*/
exports.addTutorial = function(current) {
if (hasOwnProp.call(tutorials, current.name)) {
error.handle(new Error("Tutorial with name " + current.name + " exists more than once, not adding (same name, different file extensions?)"));
} else {
tutorials[current.name] = current;
// default temporary parent
current.setParent(exports.root);
}
};
/** Root tutorial.
@type tutorial.Tutorial
*/
exports.root = new tutorial.Tutorial('', '');
/** Additional instance method for root node.
@param {string} name - Tutorial name.
@return {tutorial.Tutorial} Tutorial instance.
*/
exports.root.getByName = function(name) {
return hasOwnProp.call(tutorials, name) && tutorials[name];
};
/** Load tutorials from given path.
@param {string} _path - Tutorials directory.
*/
exports.load = function(_path) {
var match,
type,
name,
content,
current,
files = fs.ls(_path);
// tutorials handling
files.forEach(function(file) {
match = file.match(finder);
// any filetype that can apply to tutorials
if (match) {
name = path.basename(match[1]);
content = fs.readFileSync(file, env.opts.encoding);
switch (match[2].toLowerCase()) {
// HTML type
case 'xml':
case 'xhtml':
case 'html':
case 'htm':
type = tutorial.TYPES.HTML;
break;
// Markdown typs
case 'md':
case 'markdown':
type = tutorial.TYPES.MARKDOWN;
break;
// configuration file
case 'json':
var meta = JSON.parse(content);
addTutorialConf(name, meta);
// don't add this as a tutorial
return;
// how can it be? check `finder' regexp
default:
// not a file we want to work with
return;
}
current = new tutorial.Tutorial(name, content, type);
exports.addTutorial(current);
}
});
};
/** Resolves hierarchical structure.
*/
exports.resolve = function() {
var item,
current;
for (var name in conf) {
if ( hasOwnProp.call(conf, name) ) {
// TODO: should we complain about this?
if (!hasOwnProp.call(tutorials, name)) {
continue;
}
item = conf[name];
current = tutorials[name];
// set title
if (item.title) {
current.title = item.title;
}
// add children
if (item.children) {
item.children.forEach(function(child) {
if (!hasOwnProp.call(tutorials, child)) {
error.handle( new Error("Missing child tutorial: " + child) );
}
else {
tutorials[child].setParent(current);
}
});
}
}
}
};

View file

@ -0,0 +1,20 @@
/**
Deep clone a simple object.
@private
*/
var doop = exports.doop = function(o) {
var clone,
prop;
if (o instanceof Object && o.constructor != Function) {
clone = o instanceof Array ? [] : {};
Object.keys(o).forEach(function(prop) {
clone[prop] = (o[prop] instanceof Object) ? doop(o[prop]) : o[prop];
});
return clone;
}
return o;
};

View file

@ -0,0 +1,94 @@
/**
* Recursively print out all names and values in a data structure.
* @module jsdoc/util/dumper
* @author Michael Mathews <micmath@gmail.com>
* @license Apache License 2.0 - See file 'LICENSE.md' in this project.
*/
var util = require('util');
var seenItems = [];
function seen(object) {
if (seenItems.indexOf(object) !== -1) {
return true;
}
return false;
}
// some objects are unwalkable, like Java native objects
function isUnwalkable(o) {
return (o && typeof o === 'object' && typeof o.constructor === 'undefined');
}
function isFunction(o) {
return (o && typeof o === 'function' || o instanceof Function);
}
function isObject(o) {
return o && o instanceof Object ||
(o && typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
}
function checkCircularRefs(o, func) {
if ( seen(o) ) {
return '<CircularRef>';
}
else {
seenItems.push(o);
return func.call(this, o);
}
}
function walk(o) {
var result;
if ( isUnwalkable(o) ) {
result = '<Object>';
}
else if ( o === undefined ) {
result = 'undefined';
}
else if ( Array.isArray(o) ) {
result = checkCircularRefs(o, function(arr) {
var newArray = [];
arr.forEach(function(item) {
newArray.push( walk(item) );
});
return newArray;
});
}
else if ( util.isRegExp(o) ) {
result = '<RegExp ' + o + '>';
}
else if ( util.isDate(o) ) {
result = '<Date ' + o.toUTCString() + '>';
}
else if ( isFunction(o) ) {
result = '<Function' + (o.name ? ' ' + o.name : '') + '>';
}
else if ( isObject(o) && o !== null ) {
result = checkCircularRefs(o, function(obj) {
var newObj = {};
Object.keys(obj).forEach(function(key) {
newObj[key] = walk(obj[key]);
});
return newObj;
});
}
// should be safe to JSON.stringify() everything else
else {
result = o;
}
return result;
}
/**
* @param {*} object
*/
exports.dump = function(object) {
return JSON.stringify(walk(object), null, 4);
};

View file

@ -0,0 +1,32 @@
/*global env: true */
/**
Helper functions for handling errors.
@module jsdoc/util/error
*/
/**
Handle an exception appropriately based on whether lenient mode is enabled:
+ If lenient mode is enabled, log the exception to the console.
+ If lenient mode is not enabled, re-throw the exception.
@param {Error} e - The exception to handle.
@exception {Error} Re-throws the original exception unless lenient mode is enabled.
@memberof module:jsdoc/util/error
*/
exports.handle = function(e) {
var msg;
if (env.opts.lenient) {
msg = e.message || JSON.stringify(e);
// include the error type if it's an Error object
if (e instanceof Error) {
msg = e.name + ': ' + msg;
}
console.log(msg);
}
else {
throw e;
}
};

View file

@ -0,0 +1,7 @@
/**
* The global object to which functions and properties can be assigned.
* @private
*/
module.exports = (function() {
return this;
}).call(null);

View file

@ -0,0 +1,19 @@
var path = require('path');
var vm = require('jsdoc/util/vm');
/**
* Read and execute a JavaScript file in global scope.
* @private
* @param {string} filepath The path to the JavaScript file. May contain an absolute path or a
* path relative to env.dirname.
*/
module.exports = function(filepath) {
filepath = path.resolve(__dirname, filepath);
try {
vm.getModule('jsdoc/util/include')(filepath);
}
catch (e) {
console.log('Cannot include ' + filepath + ': ' + e);
}
};

View file

@ -0,0 +1,112 @@
/*global env: true */
/**
* Provides access to Markdown-related functions.
* @module jsdoc/util/markdown
* @author Michael Mathews <micmath@gmail.com>
* @author Ben Blank <ben.blank@gmail.com>
*/
/**
* Enumeration of Markdown parsers that are available.
* @enum {String}
*/
var parsers = {
/** The "[markdown-js](https://github.com/evilstreak/markdown-js)" (aka "evilstreak") parser. */
evilstreak: "markdown",
/**
* The "GitHub-flavored Markdown" parser.
* @deprecated Replaced by "marked."
*/
gfm: "marked",
/**
* The "[Marked](https://github.com/chjj/marked)" parser.
*/
marked: "marked"
};
/**
* Escape underscores that occur within {@ ... } in order to protect them
* from the markdown parser(s).
* @param {String} source the source text to sanitize.
* @returns {String} `source` where underscores within {@ ... } have been
* protected with a preceding backslash (i.e. \_) -- the markdown parsers
* will strip the backslash and protect the underscore.
*/
function escapeUnderscores(source) {
return source.replace(/\{@[^}\r\n]+\}/g, function (wholeMatch) {
return wholeMatch.replace(/(^|[^\\])_/g, '$1\\_');
});
}
/**
* Retrieve a function that accepts a single parameter containing Markdown source. The function uses
* the specified parser to transform the Markdown source to HTML, then returns the HTML as a string.
*
* @private
* @param {String} parser The name of the selected parser.
* @param {Object} [conf] Configuration for the selected parser, if any.
* @returns {Function} A function that accepts Markdown source, feeds it to the selected parser, and
* returns the resulting HTML.
* @throws {Error} If the name does not correspond to a known parser.
*/
function getParseFunction(parser, conf) {
conf = conf || {};
var parse;
if (parser === parsers.marked) {
parser = require(parser);
parser.setOptions({
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: true,
smartLists: true,
langPrefix: 'lang-'
});
parse = function(source) {
source = escapeUnderscores(source);
return parser(source)
.replace(/\s+$/, '')
.replace(/&#39;/g, "'");
};
parse._parser = parsers.marked;
return parse;
} else if (parser === parsers.evilstreak) {
parser = require(parser).markdown;
parse = function(source) {
source = escapeUnderscores(source);
// evilstreak parser expects line endings to be \n
source = source.replace(/\r\n|\r/g, '\n');
return parser.toHTML(source, conf.dialect);
};
parse._parser = parsers.evilstreak;
return parse;
} else {
throw new Error("unknown Markdown parser: '" + parser + "'");
}
}
/**
* Retrieve a Markdown parsing function based on the value of the `conf.json` file's
* `env.conf.markdown` property. The parsing function accepts a single parameter containing Markdown
* source. The function uses the parser specified in `conf.json` to transform the Markdown source to
* HTML, then returns the HTML as a string.
* @returns {Function} A function that accepts Markdown source, feeds it to the selected parser, and
* returns the resulting HTML.
* @throws {Error} If the value of `env.conf.markdown.parser` does not correspond to a known parser.
*/
exports.getParser = function() {
var conf = env.conf.markdown;
if (conf && conf.parser) {
return getParseFunction(parsers[conf.parser], conf);
} else if (conf && conf.githubRepoOwner && conf.githubRepoName) {
// use GitHub-friendly parser if GitHub-specific options are present
return getParseFunction(parsers.gfm, conf);
} else {
// evilstreak is the default parser
return getParseFunction(parsers.evilstreak, conf);
}
};

View file

@ -0,0 +1,711 @@
/*global env: true */
/**
* @module jsdoc/util/templateHelper
*/
var dictionary = require('jsdoc/tag/dictionary');
var util = require('util');
var hasOwnProp = Object.prototype.hasOwnProperty;
var files = {};
// each container gets its own html file
var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
var tutorials;
/** Sets tutorials map.
@param {jsdoc.tutorial.Tutorial} root - Root tutorial node.
*/
exports.setTutorials = function(root) {
tutorials = root;
};
exports.globalName = 'global';
exports.fileExtension = '.html';
exports.scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' };
function getNamespace(kind) {
if (dictionary.isNamespace(kind)) {
return kind + ':';
}
return '';
}
function makeFilenameUnique(filename, str) {
var key = filename.toLowerCase();
var nonUnique = true;
// append enough underscores to make the filename unique
while (nonUnique) {
if ( files[key] && hasOwnProp.call(files, key) ) {
filename += '_';
key = filename.toLowerCase();
} else {
nonUnique = false;
}
}
files[key] = str;
return filename;
}
// compute it here just once
var nsprefix = /^(event|module|external):/;
var htmlsafe = exports.htmlsafe = function(str) {
return str.replace(/</g, '&lt;');
};
/**
* Convert a string to a unique filename, including an extension.
*
* Filenames are cached to ensure that they are used only once. For example, if the same string is
* passed in twice, two different filenames will be returned.
*
* Also, filenames are not considered unique if they are capitalized differently but are otherwise
* identical.
* @param {string} str The string to convert.
* @return {string} The filename to use for the string.
*/
var getUniqueFilename = exports.getUniqueFilename = function(str) {
// allow for namespace prefix
var basename = str.replace(nsprefix, '$1-')
// use - instead of ~ to denote 'inner'
.replace(/~/g, '-')
// remove the variation, if any
.replace(/\([\s\S]*\)$/, '');
// if the basename includes characters that we can't use in a filepath, remove everything up to
// and including the last bad character
var regexp = /[^$a-z0-9._\-](?=[$a-z0-9._\-]*$)/i;
var result = regexp.exec(basename);
if (result && result.index) {
basename = basename.substr(result.index + 1);
}
// make sure we don't create hidden files on POSIX systems
basename = basename.replace(/^\./, '');
// and in case we've now stripped the entire basename (uncommon, but possible):
basename = basename.length ? basename : '_';
return makeFilenameUnique(basename, str) + exports.fileExtension;
};
// two-way lookup
var linkMap = {
longnameToUrl: {},
urlToLongname: {}
};
var tutorialLinkMap = {
nameToUrl: {},
urlToName: {}
};
var longnameToUrl = exports.longnameToUrl = linkMap.longnameToUrl;
function parseType(longname) {
var catharsis = require('catharsis');
var err;
try {
return catharsis.parse(longname, {jsdoc: true});
}
catch (e) {
err = new Error('unable to parse ' + longname + ': ' + e.message);
require('jsdoc/util/error').handle(err);
return longname;
}
}
function stringifyType(parsedType, cssClass, linkMap) {
return require('catharsis').stringify(parsedType, {
cssClass: cssClass,
htmlSafe: true,
links: linkMap
});
}
function hasUrlPrefix(text) {
return (/^(http|ftp)s?:\/\//).test(text);
}
/**
* Build an HTML link to the symbol with the specified longname. If the longname is not
* associated with a URL, this method simply returns the link text, if provided, or the longname.
*
* The `longname` parameter can also contain a URL rather than a symbol's longname.
*
* This method supports type applications that can contain one or more types, such as
* `Array.<MyClass>` or `Array.<(MyClass|YourClass)>`. In these examples, the method attempts to
* replace `Array`, `MyClass`, and `YourClass` with links to the appropriate types. The link text
* is ignored for type applications.
*
* @param {string} longname - The longname (or URL) that is the target of the link.
* @param {string=} linkText - The text to display for the link, or `longname` if no text is
* provided.
* @param {Object} options - Options for building the link.
* @param {string=} options.cssClass - The CSS class (or classes) to include in the link's `<a>`
* tag.
* @param {string=} options.fragmentId - The fragment identifier (for example, `name` in
* `foo.html#name`) to append to the link target.
* @param {string=} options.linkMap - The link map in which to look up the longname.
* @param {boolean=} options.monospace - Indicates whether to display the link text in a monospace
* font.
* @return {string} The HTML link, or the link text if the link is not available.
*/
function buildLink(longname, linkText, options) {
var catharsis = require('catharsis');
var classString = options.cssClass ? util.format(' class="%s"', options.cssClass) : '';
var fragmentString = options.fragmentId ? '#' + options.fragmentId : '';
var stripped;
var text;
var url;
var parsedType;
// handle cases like:
// @see <http://example.org>
// @see http://example.org
stripped = longname ? longname.replace(/^<|>$/g, '') : '';
if ( hasUrlPrefix(stripped) ) {
url = stripped;
text = linkText || stripped;
}
// handle complex type expressions that may require multiple links
// (but skip anything that looks like an inline tag)
else if (longname && longname.search(/[<{(]/) !== -1 && /\{\@.+\}/.test(longname) === false) {
parsedType = parseType(longname);
return stringifyType(parsedType, options.cssClass, options.linkMap);
}
else {
url = hasOwnProp.call(options.linkMap, longname) ? options.linkMap[longname] : '';
text = linkText || longname;
}
text = options.monospace ? '<code>' + text + '</code>' : text;
if (!url) {
return text;
}
else {
return util.format('<a href="%s%s"%s>%s</a>', url, fragmentString, classString, text);
}
}
/**
* Retrieve an HTML link to the symbol with the specified longname. If the longname is not
* associated with a URL, this method simply returns the link text, if provided, or the longname.
*
* The `longname` parameter can also contain a URL rather than a symbol's longname.
*
* This method supports type applications that can contain one or more types, such as
* `Array.<MyClass>` or `Array.<(MyClass|YourClass)>`. In these examples, the method attempts to
* replace `Array`, `MyClass`, and `YourClass` with links to the appropriate types. The link text
* is ignored for type applications.
*
* @param {string} longname - The longname (or URL) that is the target of the link.
* @param {string=} linkText - The text to display for the link, or `longname` if no text is
* provided.
* @param {string=} cssClass - The CSS class (or classes) to include in the link's `<a>` tag.
* @param {string=} fragmentId - The fragment identifier (for example, `name` in `foo.html#name`) to
* append to the link target.
* @return {string} The HTML link, or a plain-text string if the link is not available.
*/
var linkto = exports.linkto = function(longname, linkText, cssClass, fragmentId) {
return buildLink(longname, linkText, {
cssClass: cssClass,
fragmentId: fragmentId,
linkMap: longnameToUrl
});
};
function useMonospace(tag, text) {
var cleverLinks;
var monospaceLinks;
var result;
if ( hasUrlPrefix(text) ) {
result = false;
}
else if (tag === 'linkplain') {
result = false;
}
else if (tag === 'linkcode') {
result = true;
}
else {
cleverLinks = env.conf.templates.cleverLinks;
monospaceLinks = env.conf.templates.monospaceLinks;
if (monospaceLinks || cleverLinks) {
result = true;
}
}
return result || false;
}
function splitLinkText(text) {
var linkText;
var target;
var splitIndex;
// if a pipe is not present, we split on the first space
splitIndex = text.indexOf('|');
if (splitIndex === -1) {
splitIndex = text.indexOf(' ');
}
if (splitIndex !== -1) {
linkText = text.substr(splitIndex + 1);
target = text.substr(0, splitIndex);
}
return {
linkText: linkText,
target: target || text
};
}
var tutorialToUrl = exports.tutorialToUrl = function(tutorial) {
var node = tutorials.getByName(tutorial);
// no such tutorial
if (!node) {
require('jsdoc/util/error').handle( new Error('No such tutorial: '+tutorial) );
return;
}
var url;
// define the URL if necessary
if (!hasOwnProp.call(tutorialLinkMap.nameToUrl, node.name)) {
url = 'tutorial-' + getUniqueFilename(node.name);
tutorialLinkMap.nameToUrl[node.name] = url;
tutorialLinkMap.urlToName[url] = node.name;
}
return tutorialLinkMap.nameToUrl[node.name];
};
/**
* Retrieve a link to a tutorial, or the name of the tutorial if the tutorial is missing. If the
* `missingOpts` parameter is supplied, the names of missing tutorials will be prefixed by the
* specified text and wrapped in the specified HTML tag and CSS class.
*
* @todo Deprecate missingOpts once we have a better error-reporting mechanism.
* @param {string} tutorial The name of the tutorial.
* @param {string} content The link text to use.
* @param {object} [missingOpts] Options for displaying the name of a missing tutorial.
* @param {string} missingOpts.classname The CSS class to wrap around the tutorial name.
* @param {string} missingOpts.prefix The prefix to add to the tutorial name.
* @param {string} missingOpts.tag The tag to wrap around the tutorial name.
* @return {string} An HTML link to the tutorial, or the name of the tutorial with the specified
* options.
*/
var toTutorial = exports.toTutorial = function(tutorial, content, missingOpts) {
if (!tutorial) {
require('jsdoc/util/error').handle( new Error('Missing required parameter: tutorial') );
return;
}
var node = tutorials.getByName(tutorial);
// no such tutorial
if (!node) {
missingOpts = missingOpts || {};
var tag = missingOpts.tag;
var classname = missingOpts.classname;
var link = tutorial;
if (missingOpts.prefix) {
link = missingOpts.prefix + link;
}
if (tag) {
link = '<' + tag + (classname ? (' class="' + classname + '">') : '>') + link;
link += '</' + tag + '>';
}
return link;
}
content = content || node.title;
return '<a href="' + tutorialToUrl(tutorial) + '">' + content + '</a>';
};
/** Find symbol {@link ...} and {@tutorial ...} strings in text and turn into html links */
exports.resolveLinks = function(str) {
var replaceInlineTags = require('jsdoc/tag/inline').replaceInlineTags;
function extractLeadingText(string, completeTag) {
var tagIndex = string.indexOf(completeTag);
var leadingText = null;
var leadingTextInfo = /\[(.+?)\]/.exec(string);
// did we find leading text, and if so, does it immediately precede the tag?
if ( leadingTextInfo && leadingTextInfo.index &&
(leadingTextInfo.index + leadingTextInfo[0].length === tagIndex) ) {
string = string.replace(leadingTextInfo[0], '');
leadingText = leadingTextInfo[1];
}
return {
leadingText: leadingText,
string: string
};
}
function processLink(string, tagInfo) {
var leading = extractLeadingText(string, tagInfo.completeTag);
var linkText = leading.leadingText;
var monospace;
var split;
var target;
string = leading.string;
split = splitLinkText(tagInfo.text);
target = split.target;
linkText = linkText || split.linkText;
monospace = useMonospace(tagInfo.tag, tagInfo.text);
return string.replace( tagInfo.completeTag, buildLink(target, linkText, {
linkMap: longnameToUrl,
monospace: monospace
}) );
}
function processTutorial(string, tagInfo) {
var leading = extractLeadingText(string, tagInfo.completeTag);
string = leading.string;
return string.replace( tagInfo.completeTag, toTutorial(tagInfo.text, leading.leadingText) );
}
var replacers = {
link: processLink,
linkcode: processLink,
linkplain: processLink,
tutorial: processTutorial
};
return replaceInlineTags(str, replacers).newString;
};
/** Convert tag text like "Jane Doe <jdoe@example.org>" into a mailto link */
exports.resolveAuthorLinks = function(str) {
var author;
var matches = str.match(/^\s?([\s\S]+)\b\s+<(\S+@\S+)>\s?$/);
if (matches && matches.length === 3) {
author = '<a href="mailto:' + matches[2] + '">' + htmlsafe(matches[1]) + '</a>';
}
else {
author = htmlsafe(str);
}
return author;
};
/**
* Find items in a TaffyDB database that match the specified key-value pairs.
* @param {TAFFY} data The TaffyDB database to search.
* @param {object|function} spec Key-value pairs to match against (for example,
* `{ longname: 'foo' }`), or a function that returns `true` if a value matches or `false` if it
* does not match.
* @return {array<object>} The matching items.
*/
var find = exports.find = function(data, spec) {
return data(spec).get();
};
/**
* Check whether a symbol is a function and is the only symbol exported by a module (as in
* `module.exports = function() {};`).
*
* @private
* @param {module:jsdoc/doclet.Doclet} doclet - The doclet for the symbol.
* @return {boolean} `true` if the symbol is a function and is the only symbol exported by a module;
* otherwise, `false`.
*/
function isModuleFunction(doclet) {
return doclet.longname && doclet.longname === doclet.name &&
doclet.longname.indexOf('module:') === 0 && doclet.kind === 'function';
}
/**
* Retrieve all of the following types of members from a set of doclets:
*
* + Classes
* + Externals
* + Globals
* + Mixins
* + Modules
* + Namespaces
* + Events
* @param {TAFFY} data The TaffyDB database to search.
* @return {object} An object with `classes`, `externals`, `globals`, `mixins`, `modules`,
* `events`, and `namespaces` properties. Each property contains an array of objects.
*/
exports.getMembers = function(data) {
var members = {
classes: find( data, {kind: 'class'} ),
externals: find( data, {kind: 'external'} ),
events: find( data, {kind: 'event'} ),
globals: find(data, {
kind: ['member', 'function', 'constant', 'typedef'],
memberof: { isUndefined: true }
}),
mixins: find( data, {kind: 'mixin'} ),
modules: find( data, {kind: 'module'} ),
namespaces: find( data, {kind: 'namespace'} )
};
// functions that are also modules (as in "module.exports = function() {};") are not globals
members.globals = members.globals.filter(function(doclet) {
if ( isModuleFunction(doclet) ) {
return false;
}
return true;
});
return members;
};
/**
* Retrieve the member attributes for a doclet (for example, `virtual`, `static`, and
* `readonly`).
* @param {object} d The doclet whose attributes will be retrieved.
* @return {array<string>} The member attributes for the doclet.
*/
exports.getAttribs = function(d) {
var attribs = [];
if (d.virtual) {
attribs.push('virtual');
}
if (d.access && d.access !== 'public') {
attribs.push(d.access);
}
if (d.scope && d.scope !== 'instance' && d.scope !== 'global') {
if (d.kind == 'function' || d.kind == 'member' || d.kind == 'constant') {
attribs.push(d.scope);
}
}
if (d.readonly === true) {
if (d.kind == 'member') {
attribs.push('readonly');
}
}
if (d.kind === 'constant') {
attribs.push('constant');
}
return attribs;
};
/**
* Retrieve links to allowed types for the member.
*
* @param {Object} d - The doclet whose types will be retrieved.
* @param {string} [cssClass] - The CSS class to include in the `class` attribute for each link.
* @return {Array.<string>} HTML links to allowed types for the member.
*/
exports.getSignatureTypes = function(d, cssClass) {
var types = [];
if (d.type && d.type.names) {
types = d.type.names;
}
if (types && types.length) {
types = types.map(function(t) {
return linkto(t, htmlsafe(t), cssClass);
});
}
return types;
};
/**
* Retrieve names of the parameters that the member accepts. If a value is provided for `optClass`,
* the names of optional parameters will be wrapped in a `<span>` tag with that class.
* @param {object} d The doclet whose parameter names will be retrieved.
* @param {string} [optClass] The class to assign to the `<span>` tag that is wrapped around the
* names of optional parameters. If a value is not provided, optional parameter names will not be
* wrapped with a `<span>` tag. Must be a legal value for a CSS class name.
* @return {array<string>} An array of parameter names, with or without `<span>` tags wrapping the
* names of optional parameters.
*/
exports.getSignatureParams = function(d, optClass) {
var pnames = [];
if (d.params) {
d.params.forEach(function(p) {
if (p.name && p.name.indexOf('.') === -1) {
if (p.optional && optClass) {
pnames.push('<span class="' + optClass + '">' + p.name + '</span>');
}
else {
pnames.push(p.name);
}
}
});
}
return pnames;
};
/**
* Retrieve links to types that the member can return.
*
* @param {Object} d - The doclet whose types will be retrieved.
* @param {string} [cssClass] - The CSS class to include in the `class` attribute for each link.
* @return {Array.<string>} HTML links to types that the member can return.
*/
exports.getSignatureReturns = function(d, cssClass) {
var returnTypes = [];
if (d.returns) {
d.returns.forEach(function(r) {
if (r.type && r.type.names) {
if (!returnTypes.length) {
returnTypes = r.type.names;
}
}
});
}
if (returnTypes && returnTypes.length) {
returnTypes = returnTypes.map(function(r) {
return linkto(r, htmlsafe(r), cssClass);
});
}
return returnTypes;
};
/**
* Retrieve links to a member's ancestors.
*
* @param {TAFFY} data - The TaffyDB database to search.
* @param {Object} doclet - The doclet whose ancestors will be retrieved.
* @param {string} [cssClass] - The CSS class to include in the `class` attribute for each link.
* @return {Array.<string>} HTML links to a member's ancestors.
*/
exports.getAncestorLinks = function(data, doclet, cssClass) {
var ancestors = [],
doc = doclet.memberof;
while (doc) {
doc = find( data, {longname: doc}, false );
if (doc) { doc = doc[0]; }
if (!doc) { break; }
ancestors.unshift( linkto(doc.longname, (exports.scopeToPunc[doc.scope] || '') + doc.name,
cssClass) );
doc = doc.memberof;
}
if (ancestors.length) {
ancestors[ancestors.length - 1] += (exports.scopeToPunc[doclet.scope] || '');
}
return ancestors;
};
/**
* Iterates through all the doclets in `data`, ensuring that if a method
* @listens to an event, then that event has a 'listeners' array with the
* longname of the listener in it.
*
* @param {TAFFY} data - The TaffyDB database to search.
*/
exports.addEventListeners = function(data) {
// TODO: do this on the *pruned* data
// find all doclets that @listen to something.
var listeners = find(data, function () { return this.listens && this.listens.length; });
if (!listeners.length) {
return;
}
var doc,
l,
_events = {}; // just a cache to prevent me doing so many lookups
listeners.forEach(function (listener) {
l = listener.listens;
l.forEach(function (eventLongname) {
doc = _events[eventLongname] || find(data, {longname: eventLongname, kind: 'event'})[0];
if (doc) {
if (!doc.listeners) {
doc.listeners = [listener.longname];
} else {
doc.listeners.push(listener.longname);
}
_events[eventLongname] = _events[eventLongname] || doc;
}
});
});
};
/**
* Remove members that will not be included in the output, including:
*
* + Undocumented members.
* + Members tagged `@ignore`.
* + Members of anonymous classes.
* + Members tagged `@private`, unless the `private` option is enabled.
* @param {TAFFY} data The TaffyDB database to prune.
* @return {TAFFY} The pruned database.
*/
exports.prune = function(data) {
data({undocumented: true}).remove();
data({ignore: true}).remove();
if (!env.opts.private) { data({access: 'private'}).remove(); }
data({memberof: '<anonymous>'}).remove();
return data;
};
var registerLink = exports.registerLink = function(longname, url) {
linkMap.longnameToUrl[longname] = url;
linkMap.urlToLongname[url] = longname;
};
/**
* Get a longname's filename if one has been registered; otherwise, generate a unique filename, then
* register the filename.
* @private
*/
function getFilename(longname) {
var url;
if ( longnameToUrl[longname] && hasOwnProp.call(longnameToUrl, longname) ) {
url = longnameToUrl[longname];
} else {
url = getUniqueFilename(longname);
registerLink(longname, url);
}
return url;
}
/** Turn a doclet into a URL. */
exports.createLink = function(doclet) {
var url = '';
var longname = doclet.longname;
var filename;
if ( containers.indexOf(doclet.kind) !== -1 || isModuleFunction(doclet) ) {
url = getFilename(longname);
}
else {
filename = getFilename(doclet.memberof || exports.globalName);
url = filename + '#' + getNamespace(doclet.kind) + doclet.name;
}
return url;
};

View file

@ -0,0 +1,83 @@
/*global Packages: true */
/**
* Helper functions to enable JSDoc to run on multiple JavaScript virtual machines.
* @module jsdoc/util/vm
*/
var os = require('os');
// These strings represent directory names; do not modify them!
/** @private */
const RHINO = exports.RHINO = 'rhino';
/** @private */
const NODEJS = exports.NODEJS = 'nodejs';
// hacky conversion from Windows path to URI
function pathToUri(filepath) {
var uri = filepath;
// get drive
var drive = uri.match(/^[A-Za-z]/)[0] || '';
// strip drive/colon (if present; UNC paths won't have either)
uri = uri.replace(/^:?([A-Za-z]\:)?/, '');
// replace spaces with %20
uri = uri.replace(/\s/g, '%20');
// prepend drive (if present)
if (drive) {
uri = drive + ':' + uri;
}
// prepend URI scheme
uri = 'file:/' + uri;
return uri;
}
/**
* The JavaScript VM that is executing JSDoc:
*
* + `module:jsdoc/util/vm.RHINO`: Mozilla Rhino.
* + `module:jsdoc/util/vm.NODEJS`: Node.js (not currently supported).
*/
var vm = exports.vm = (function() {
if (Packages && typeof Packages === 'object' &&
Object.prototype.toString.call(Packages) === '[object JavaPackage]') {
return RHINO;
} else if ( require && require.main && module && (require.main === module) ) {
return NODEJS;
} else {
// unknown VM
throw new Error('Unable to identify the current JavaScript VM.');
}
})();
/**
* Load the VM-specific implementation of a module.
*
* @param {string} modulePath - The relative path to the module. Use the same format as when calling
* `require()`.
* @return {object} An object containing VM-specific functions for the requested module.
*/
exports.getModule = function(modulePath) {
modulePath = [__dirname, vm, modulePath].join('/').replace(/ /g, '%20');
if (os.platform() === 'win32') {
modulePath = pathToUri(modulePath);
}
return require(modulePath);
};
/**
* Check whether Mozilla Rhino is running JSDoc.
* @return {boolean} Set to `true` if the current VM is Mozilla Rhino.
*/
exports.isRhino = function() {
return vm === RHINO;
};
/**
* Check whether Node.js is running JSDoc. (Node.js is not currently supported.)
* @return {boolean} Set to `true` if the current VM is Node.js.
*/
exports.isNodejs = function() {
return vm === NODEJS;
};

19
data/scripts/jsdoc/node_modules/async/LICENSE generated vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2010 Caolan McMahon
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

3
data/scripts/jsdoc/node_modules/async/index.js generated vendored Normal file
View file

@ -0,0 +1,3 @@
// This file is just added for convenience so this repository can be
// directly checked out into a project's deps folder
module.exports = require('./lib/async');

692
data/scripts/jsdoc/node_modules/async/lib/async.js generated vendored Normal file
View file

@ -0,0 +1,692 @@
/*global setTimeout: false, console: false */
(function () {
var async = {};
// global on the server, window in the browser
var root = this,
previous_async = root.async;
if (typeof module !== 'undefined' && module.exports) {
module.exports = async;
}
else {
root.async = async;
}
async.noConflict = function () {
root.async = previous_async;
return async;
};
//// cross-browser compatiblity functions ////
var _forEach = function (arr, iterator) {
if (arr.forEach) {
return arr.forEach(iterator);
}
for (var i = 0; i < arr.length; i += 1) {
iterator(arr[i], i, arr);
}
};
var _map = function (arr, iterator) {
if (arr.map) {
return arr.map(iterator);
}
var results = [];
_forEach(arr, function (x, i, a) {
results.push(iterator(x, i, a));
});
return results;
};
var _reduce = function (arr, iterator, memo) {
if (arr.reduce) {
return arr.reduce(iterator, memo);
}
_forEach(arr, function (x, i, a) {
memo = iterator(memo, x, i, a);
});
return memo;
};
var _keys = function (obj) {
if (Object.keys) {
return Object.keys(obj);
}
var keys = [];
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
}
return keys;
};
//// exported async module functions ////
//// nextTick implementation with browser-compatible fallback ////
if (typeof process === 'undefined' || !(process.nextTick)) {
async.nextTick = function (fn) {
setTimeout(fn, 0);
};
}
else {
async.nextTick = process.nextTick;
}
async.forEach = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
var completed = 0;
_forEach(arr, function (x) {
iterator(x, function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
if (completed === arr.length) {
callback(null);
}
}
});
});
};
async.forEachSeries = function (arr, iterator, callback) {
callback = callback || function () {};
if (!arr.length) {
return callback();
}
var completed = 0;
var iterate = function () {
iterator(arr[completed], function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
if (completed === arr.length) {
callback(null);
}
else {
iterate();
}
}
});
};
iterate();
};
async.forEachLimit = function (arr, limit, iterator, callback) {
callback = callback || function () {};
if (!arr.length || limit <= 0) {
return callback();
}
var completed = 0;
var started = 0;
var running = 0;
(function replenish () {
if (completed === arr.length) {
return callback();
}
while (running < limit && started < arr.length) {
started += 1;
running += 1;
iterator(arr[started - 1], function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
completed += 1;
running -= 1;
if (completed === arr.length) {
callback();
}
else {
replenish();
}
}
});
}
})();
};
var doParallel = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(null, [async.forEach].concat(args));
};
};
var doSeries = function (fn) {
return function () {
var args = Array.prototype.slice.call(arguments);
return fn.apply(null, [async.forEachSeries].concat(args));
};
};
var _asyncMap = function (eachfn, arr, iterator, callback) {
var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
eachfn(arr, function (x, callback) {
iterator(x.value, function (err, v) {
results[x.index] = v;
callback(err);
});
}, function (err) {
callback(err, results);
});
};
async.map = doParallel(_asyncMap);
async.mapSeries = doSeries(_asyncMap);
// reduce only has a series version, as doing reduce in parallel won't
// work in many situations.
async.reduce = function (arr, memo, iterator, callback) {
async.forEachSeries(arr, function (x, callback) {
iterator(memo, x, function (err, v) {
memo = v;
callback(err);
});
}, function (err) {
callback(err, memo);
});
};
// inject alias
async.inject = async.reduce;
// foldl alias
async.foldl = async.reduce;
async.reduceRight = function (arr, memo, iterator, callback) {
var reversed = _map(arr, function (x) {
return x;
}).reverse();
async.reduce(reversed, memo, iterator, callback);
};
// foldr alias
async.foldr = async.reduceRight;
var _filter = function (eachfn, arr, iterator, callback) {
var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
eachfn(arr, function (x, callback) {
iterator(x.value, function (v) {
if (v) {
results.push(x);
}
callback();
});
}, function (err) {
callback(_map(results.sort(function (a, b) {
return a.index - b.index;
}), function (x) {
return x.value;
}));
});
};
async.filter = doParallel(_filter);
async.filterSeries = doSeries(_filter);
// select alias
async.select = async.filter;
async.selectSeries = async.filterSeries;
var _reject = function (eachfn, arr, iterator, callback) {
var results = [];
arr = _map(arr, function (x, i) {
return {index: i, value: x};
});
eachfn(arr, function (x, callback) {
iterator(x.value, function (v) {
if (!v) {
results.push(x);
}
callback();
});
}, function (err) {
callback(_map(results.sort(function (a, b) {
return a.index - b.index;
}), function (x) {
return x.value;
}));
});
};
async.reject = doParallel(_reject);
async.rejectSeries = doSeries(_reject);
var _detect = function (eachfn, arr, iterator, main_callback) {
eachfn(arr, function (x, callback) {
iterator(x, function (result) {
if (result) {
main_callback(x);
main_callback = function () {};
}
else {
callback();
}
});
}, function (err) {
main_callback();
});
};
async.detect = doParallel(_detect);
async.detectSeries = doSeries(_detect);
async.some = function (arr, iterator, main_callback) {
async.forEach(arr, function (x, callback) {
iterator(x, function (v) {
if (v) {
main_callback(true);
main_callback = function () {};
}
callback();
});
}, function (err) {
main_callback(false);
});
};
// any alias
async.any = async.some;
async.every = function (arr, iterator, main_callback) {
async.forEach(arr, function (x, callback) {
iterator(x, function (v) {
if (!v) {
main_callback(false);
main_callback = function () {};
}
callback();
});
}, function (err) {
main_callback(true);
});
};
// all alias
async.all = async.every;
async.sortBy = function (arr, iterator, callback) {
async.map(arr, function (x, callback) {
iterator(x, function (err, criteria) {
if (err) {
callback(err);
}
else {
callback(null, {value: x, criteria: criteria});
}
});
}, function (err, results) {
if (err) {
return callback(err);
}
else {
var fn = function (left, right) {
var a = left.criteria, b = right.criteria;
return a < b ? -1 : a > b ? 1 : 0;
};
callback(null, _map(results.sort(fn), function (x) {
return x.value;
}));
}
});
};
async.auto = function (tasks, callback) {
callback = callback || function () {};
var keys = _keys(tasks);
if (!keys.length) {
return callback(null);
}
var results = {};
var listeners = [];
var addListener = function (fn) {
listeners.unshift(fn);
};
var removeListener = function (fn) {
for (var i = 0; i < listeners.length; i += 1) {
if (listeners[i] === fn) {
listeners.splice(i, 1);
return;
}
}
};
var taskComplete = function () {
_forEach(listeners.slice(0), function (fn) {
fn();
});
};
addListener(function () {
if (_keys(results).length === keys.length) {
callback(null, results);
callback = function () {};
}
});
_forEach(keys, function (k) {
var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
var taskCallback = function (err) {
if (err) {
callback(err);
// stop subsequent errors hitting callback multiple times
callback = function () {};
}
else {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
results[k] = args;
taskComplete();
}
};
var requires = task.slice(0, Math.abs(task.length - 1)) || [];
var ready = function () {
return _reduce(requires, function (a, x) {
return (a && results.hasOwnProperty(x));
}, true) && !results.hasOwnProperty(k);
};
if (ready()) {
task[task.length - 1](taskCallback, results);
}
else {
var listener = function () {
if (ready()) {
removeListener(listener);
task[task.length - 1](taskCallback, results);
}
};
addListener(listener);
}
});
};
async.waterfall = function (tasks, callback) {
callback = callback || function () {};
if (!tasks.length) {
return callback();
}
var wrapIterator = function (iterator) {
return function (err) {
if (err) {
callback(err);
callback = function () {};
}
else {
var args = Array.prototype.slice.call(arguments, 1);
var next = iterator.next();
if (next) {
args.push(wrapIterator(next));
}
else {
args.push(callback);
}
async.nextTick(function () {
iterator.apply(null, args);
});
}
};
};
wrapIterator(async.iterator(tasks))();
};
async.parallel = function (tasks, callback) {
callback = callback || function () {};
if (tasks.constructor === Array) {
async.map(tasks, function (fn, callback) {
if (fn) {
fn(function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
callback.call(null, err, args);
});
}
}, callback);
}
else {
var results = {};
async.forEach(_keys(tasks), function (k, callback) {
tasks[k](function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
results[k] = args;
callback(err);
});
}, function (err) {
callback(err, results);
});
}
};
async.series = function (tasks, callback) {
callback = callback || function () {};
if (tasks.constructor === Array) {
async.mapSeries(tasks, function (fn, callback) {
if (fn) {
fn(function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
callback.call(null, err, args);
});
}
}, callback);
}
else {
var results = {};
async.forEachSeries(_keys(tasks), function (k, callback) {
tasks[k](function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (args.length <= 1) {
args = args[0];
}
results[k] = args;
callback(err);
});
}, function (err) {
callback(err, results);
});
}
};
async.iterator = function (tasks) {
var makeCallback = function (index) {
var fn = function () {
if (tasks.length) {
tasks[index].apply(null, arguments);
}
return fn.next();
};
fn.next = function () {
return (index < tasks.length - 1) ? makeCallback(index + 1): null;
};
return fn;
};
return makeCallback(0);
};
async.apply = function (fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
return fn.apply(
null, args.concat(Array.prototype.slice.call(arguments))
);
};
};
var _concat = function (eachfn, arr, fn, callback) {
var r = [];
eachfn(arr, function (x, cb) {
fn(x, function (err, y) {
r = r.concat(y || []);
cb(err);
});
}, function (err) {
callback(err, r);
});
};
async.concat = doParallel(_concat);
async.concatSeries = doSeries(_concat);
async.whilst = function (test, iterator, callback) {
if (test()) {
iterator(function (err) {
if (err) {
return callback(err);
}
async.whilst(test, iterator, callback);
});
}
else {
callback();
}
};
async.until = function (test, iterator, callback) {
if (!test()) {
iterator(function (err) {
if (err) {
return callback(err);
}
async.until(test, iterator, callback);
});
}
else {
callback();
}
};
async.queue = function (worker, concurrency) {
var workers = 0;
var q = {
tasks: [],
concurrency: concurrency,
saturated: null,
empty: null,
drain: null,
push: function (data, callback) {
if(data.constructor !== Array) {
data = [data];
}
_forEach(data, function(task) {
q.tasks.push({
data: task,
callback: typeof callback === 'function' ? callback : null
});
if (q.saturated && q.tasks.length == concurrency) {
q.saturated();
}
async.nextTick(q.process);
});
},
process: function () {
if (workers < q.concurrency && q.tasks.length) {
var task = q.tasks.shift();
if(q.empty && q.tasks.length == 0) q.empty();
workers += 1;
worker(task.data, function () {
workers -= 1;
if (task.callback) {
task.callback.apply(task, arguments);
}
if(q.drain && q.tasks.length + workers == 0) q.drain();
q.process();
});
}
},
length: function () {
return q.tasks.length;
},
running: function () {
return workers;
}
};
return q;
};
var _console_fn = function (name) {
return function (fn) {
var args = Array.prototype.slice.call(arguments, 1);
fn.apply(null, args.concat([function (err) {
var args = Array.prototype.slice.call(arguments, 1);
if (typeof console !== 'undefined') {
if (err) {
if (console.error) {
console.error(err);
}
}
else if (console[name]) {
_forEach(args, function (x) {
console[name](x);
});
}
}
}]));
};
};
async.log = _console_fn('log');
async.dir = _console_fn('dir');
/*async.info = _console_fn('info');
async.warn = _console_fn('warn');
async.error = _console_fn('error');*/
async.memoize = function (fn, hasher) {
var memo = {};
var queues = {};
hasher = hasher || function (x) {
return x;
};
var memoized = function () {
var args = Array.prototype.slice.call(arguments);
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
callback.apply(null, memo[key]);
}
else if (key in queues) {
queues[key].push(callback);
}
else {
queues[key] = [callback];
fn.apply(null, args.concat([function () {
memo[key] = arguments;
var q = queues[key];
delete queues[key];
for (var i = 0, l = q.length; i < l; i++) {
q[i].apply(null, arguments);
}
}]));
}
};
memoized.unmemoized = fn;
return memoized;
};
async.unmemoize = function (fn) {
return function () {
return (fn.unmemoized || fn).apply(null, arguments);
};
};
}());

30
data/scripts/jsdoc/node_modules/async/package.json generated vendored Normal file

File diff suppressed because one or more lines are too long

16
data/scripts/jsdoc/node_modules/catharsis/LICENSE generated vendored Normal file
View file

@ -0,0 +1,16 @@
Copyright (c) 2012-2013 Jeff Williams
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

123
data/scripts/jsdoc/node_modules/catharsis/catharsis.js generated vendored Normal file
View file

@ -0,0 +1,123 @@
/**
* Catharsis
* A parser for Google Closure Compiler type expressions, powered by PEG.js.
*
* @author Jeff Williams <jeffrey.l.williams@gmail.com>
* @license MIT License <http://opensource.org/licenses/mit-license.php/>
*/
'use strict';
var parse = require('./lib/parser').parse;
var stringify = require('./lib/stringify');
var typeExpressionCache = {
normal: {},
jsdoc: {}
};
var parsedTypeCache = {
normal: {},
htmlSafe: {}
};
function getTypeExpressionCache(options) {
if (options.useCache === false) {
return null;
} else if (options.jsdoc === true) {
return typeExpressionCache.jsdoc;
} else {
return typeExpressionCache.normal;
}
}
function getParsedTypeCache(options) {
if (options.useCache === false || options.links !== null || options.links !== undefined) {
return null;
} else if (options.htmlSafe === true) {
return parsedTypeCache.htmlSafe;
} else {
return parsedTypeCache.normal;
}
}
// can't return the original if any of the following are true:
// 1. restringification was requested
// 2. htmlSafe option was requested
// 3. links option was provided
// 4. typeExpression property is missing
function canReturnOriginalExpression(parsedType, options) {
return options.restringify !== true && options.htmlSafe !== true &&
(options.links === null || options.links === undefined) &&
Object.prototype.hasOwnProperty.call(parsedType, 'typeExpression');
}
function cachedParse(expr, options) {
var cache = getTypeExpressionCache(options);
var parsedType;
if (cache && cache[expr]) {
return cache[expr];
} else {
parsedType = parse(expr, options);
Object.defineProperties(parsedType, {
typeExpression: {
value: expr
},
jsdoc: {
value: options.jsdoc === true ? true : false
}
});
parsedType = Object.freeze(parsedType);
if (cache) {
cache[expr] = parsedType;
}
return parsedType;
}
}
function cachedStringify(parsedType, options) {
var cache = getParsedTypeCache(options);
var json;
if (canReturnOriginalExpression(parsedType, options)) {
return parsedType.typeExpression;
} else if (cache) {
json = JSON.stringify(parsedType);
cache[json] = cache[json] || stringify(parsedType, options);
return cache[json];
} else {
return stringify(parsedType, options);
}
}
function Catharsis() {
this.Types = require('./lib/types');
}
Catharsis.prototype.parse = function(typeExpr, options) {
options = options || {};
typeExpr = typeExpr.replace(/[\r\n]/g, '')
.replace(/\s+/g, ' ')
.trim();
return cachedParse(typeExpr, options);
};
Catharsis.prototype.stringify = function(parsedType, options) {
options = options || {};
var result;
result = cachedStringify(parsedType, options);
if (options.validate) {
this.parse(result, options);
}
return result;
};
module.exports = new Catharsis();

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,257 @@
'use strict';
var Types = require('./types');
function Stringifier(options) {
this._options = options || {};
// in a list of function signature params, repeatable params are stringified differently
this._inFunctionSignatureParams = false;
}
Stringifier.prototype.applications = function(applications) {
if (!applications) {
return '';
}
var parsedApplications = [];
var result = '';
for (var i = 0, l = applications.length; i < l; i++) {
parsedApplications.push(this.type(applications[i]));
}
if (this._options.htmlSafe) {
result = '.&lt;';
} else {
result = '.<';
}
result += parsedApplications.join(', ') + '>';
return result;
};
Stringifier.prototype.elements = function(elements) {
if (!elements) {
return '';
}
var result = [];
for (var i = 0, l = elements.length; i < l; i++) {
result.push(this.type(elements[i]));
}
return '(' + result.join('|') + ')';
};
Stringifier.prototype.name = function(name) {
return name || '';
};
Stringifier.prototype['new'] = function(funcNew) {
return funcNew ? 'new:' + this.type(funcNew) : '';
};
Stringifier.prototype.nullable = function(nullable) {
switch (nullable) {
case true:
return '?';
case false:
return '!';
default:
return '';
}
};
Stringifier.prototype.optional = function(optional) {
/*jshint boss: true */ // TODO: remove after JSHint releases the fix for jshint/jshint#878
if (optional === true) {
return '=';
} else {
return '';
}
};
Stringifier.prototype.params = function(params) {
if (!params || params.length === 0) {
return '';
}
var result = [];
var param;
for (var i = 0, l = params.length; i < l; i++) {
result.push(this.type(params[i]));
}
return result.join(', ');
};
Stringifier.prototype.properties = function(props) {
if (!props) {
return '';
}
var result = [];
for (var i = 0, l = props.length; i < l; i++) {
result.push(this._formatNameAndType(props[i].name, props[i].type));
}
return result;
};
Stringifier.prototype.result = function(result) {
return result ? ': ' + this.type(result) : '';
};
Stringifier.prototype['this'] = function(funcThis) {
return funcThis ? 'this:' + this.type(funcThis) : '';
};
Stringifier.prototype.type = function(type) {
if (!type) {
return '';
}
// nullable comes first
var result = this.nullable(type.nullable);
// next portion varies by type
switch(type.type) {
case Types.AllLiteral:
result += this._formatNameAndType(type, '*');
break;
case Types.FunctionType:
result += this._signature(type);
break;
case Types.NullLiteral:
result += this._formatNameAndType(type, 'null');
break;
case Types.RecordType:
result += this._record(type);
break;
case Types.TypeApplication:
result += this.type(type.expression);
result += this.applications(type.applications);
break;
case Types.UndefinedLiteral:
result += this._formatNameAndType(type, 'undefined');
break;
case Types.TypeUnion:
result += this.elements(type.elements);
break;
case Types.UnknownLiteral:
result += this._formatNameAndType(type, '?');
break;
default:
result += this._formatNameAndType(type);
}
// finally, optionality
result += this.optional(type.optional);
return result;
};
Stringifier.prototype.stringify = Stringifier.prototype.type;
Stringifier.prototype.key = Stringifier.prototype.type;
Stringifier.prototype._record = function(type) {
var fields = this._recordFields(type.fields);
return '{' + fields.join(', ') + '}';
};
Stringifier.prototype._recordFields = function(fields) {
if (!fields) {
return '';
}
var result = [];
var field;
var keyAndValue;
for (var i = 0, l = fields.length; i < l; i++) {
field = fields[i];
keyAndValue = this.key(field.key);
keyAndValue += field.value ? ': ' + this.type(field.value) : '';
result.push(keyAndValue);
}
return result;
};
function combineNameAndType(nameString, typeString) {
var separator = (nameString && typeString) ? ':' : '';
return nameString + separator + typeString;
}
Stringifier.prototype._formatRepeatable = function(nameString, typeString) {
var open = this._inFunctionSignatureParams ? '...[' : '...';
var close = this._inFunctionSignatureParams ? ']' : '';
return open + combineNameAndType(nameString, typeString) + close;
};
Stringifier.prototype._formatNameAndType = function(type, literal) {
var nameString = type.name || literal || '';
var typeString = type.type ? this.type(type.type) : '';
var cssClass;
var openTag;
// replace the type with an HTML link if necessary
if (this._options.links && Object.prototype.hasOwnProperty.call(this._options.links,
nameString)) {
cssClass = this._options.cssClass ? ' class="' + this._options.cssClass + '"' : '';
openTag = '<a href="' + this._options.links[nameString] + '"' + cssClass + '>';
nameString = openTag + nameString + '</a>';
}
if (type.repeatable === true) {
return this._formatRepeatable(nameString, typeString);
} else {
return combineNameAndType(nameString, typeString);
}
};
Stringifier.prototype._signature = function(type) {
var params = [];
var param;
var result;
// these go within the signature's parens, in this order
var props = [
'new',
'this',
'params'
];
var prop;
this._inFunctionSignatureParams = true;
for (var i = 0, l = props.length; i < l; i++) {
prop = props[i];
param = this[prop](type[prop]);
if (param.length > 0) {
params.push(param);
}
}
this._inFunctionSignatureParams = false;
result = 'function(' + params.join(', ') + ')';
result += this.result(type.result);
return result;
};
module.exports = function(type, options) {
return new Stringifier(options).stringify(type);
};

24
data/scripts/jsdoc/node_modules/catharsis/lib/types.js generated vendored Normal file
View file

@ -0,0 +1,24 @@
'use strict';
module.exports = Object.freeze({
// `*`
AllLiteral: 'AllLiteral',
// like `blah` in `{blah: string}`
FieldType: 'FieldType',
// like `function(string): string`
FunctionType: 'FunctionType',
// any string literal, such as `string` or `My.Namespace`
NameExpression: 'NameExpression',
// null
NullLiteral: 'NullLiteral',
// like `{foo: string}`
RecordType: 'RecordType',
// like `Array.<string>`
TypeApplication: 'TypeApplication',
// like `(number|string)`
TypeUnion: 'TypeUnion',
// undefined
UndefinedLiteral: 'UndefinedLiteral',
// `?`
UnknownLiteral: 'UnknownLiteral'
});

44
data/scripts/jsdoc/node_modules/catharsis/package.json generated vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,68 @@
var sha = require('./sha')
var rng = require('./rng')
var algorithms = {
sha1: {
hex: sha.hex_sha1,
binary: sha.b64_sha1,
ascii: sha.str_sha1
}
}
function error () {
var m = [].slice.call(arguments).join(' ')
throw new Error([
m,
'we accept pull requests',
'http://github.com/dominictarr/crypto-browserify'
].join('\n'))
}
exports.createHash = function (alg) {
alg = alg || 'sha1'
if(!algorithms[alg])
error('algorithm:', alg, 'is not yet supported')
var s = ''
var _alg = algorithms[alg]
return {
update: function (data) {
s += data
return this
},
digest: function (enc) {
enc = enc || 'binary'
var fn
if(!(fn = _alg[enc]))
error('encoding:', enc , 'is not yet supported for algorithm', alg)
var r = fn(s)
s = null //not meant to use the hash after you've called digest.
return r
}
}
}
exports.randomBytes = function(size, callback) {
if (callback && callback.call) {
try {
callback.call(this, undefined, rng(size));
} catch (err) { callback(err); }
} else {
return rng(size);
}
}
// the least I can do is make error messages for the rest of the node.js/crypto api.
;['createCredentials'
, 'createHmac'
, 'createCypher'
, 'createCypheriv'
, 'createDecipher'
, 'createDecipheriv'
, 'createSign'
, 'createVerify'
, 'createDeffieHellman'
, 'pbkdf2'].forEach(function (name) {
exports[name] = function () {
error('sorry,', name, 'is not implemented yet')
}
})

View file

@ -0,0 +1,29 @@
{
"author": {
"name": "Dominic Tarr",
"email": "dominic.tarr@gmail.com",
"url": "dominictarr.com"
},
"name": "crypto-browserify",
"description": "partial implementation of crypto for the browser",
"version": "0.1.1",
"homepage": "https://github.com/dominictarr/crypto-browserify",
"repository": {
"url": ""
},
"scripts": {
"test": "node test/simple.js"
},
"engines": {
"node": "*"
},
"dependencies": {},
"devDependencies": {},
"optionalDependencies": {},
"readme": "# crypto-browserify\n\nA (partial) port of `crypto` to the browser.\n\nBasically, I found some crypto implemented in JS lieing on the internet somewhere\nand wrapped it in the part of the `crypto` api that I am currently using.\n\nIn a way that will be compatible with [browserify](https://github.com/substack/node-browserify/).\n\nI will extend this if I need more features, or if anyone else wants to extend this,\nI will add you as a maintainer.\n\nProvided that you agree that it should replicate the [node.js/crypto](http://nodejs.org/api/crypto.html) api exactly, of course.\n\n",
"_id": "crypto-browserify@0.1.1",
"dist": {
"shasum": "251b240c6bd0e95db0654fbc8b178b855cbef45e"
},
"_from": "crypto-browserify@git://github.com/dominictarr/crypto-browserify.git#95c5d505"
}

View file

@ -0,0 +1,37 @@
// Original code adapted from Robert Kieffer.
// details at https://github.com/broofa/node-uuid
(function() {
var _global = this;
var mathRNG, whatwgRNG;
// NOTE: Math.random() does not guarantee "cryptographic quality"
mathRNG = function(size) {
var bytes = new Array(size);
var r;
for (var i = 0, r; i < size; i++) {
if ((i & 0x03) == 0) r = Math.random() * 0x100000000;
bytes[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return bytes;
}
// currently only available in webkit-based browsers.
if (_global.crypto && crypto.getRandomValues) {
var _rnds = new Uint32Array(4);
whatwgRNG = function(size) {
var bytes = new Array(size);
crypto.getRandomValues(_rnds);
for (var c = 0 ; c < size; c++) {
bytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff;
}
return bytes;
}
}
module.exports = whatwgRNG || mathRNG;
}())

View file

@ -0,0 +1,210 @@
/*
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
* in FIPS PUB 180-1
* Version 2.1a Copyright Paul Johnston 2000 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for details.
*/
exports.hex_sha1 = hex_sha1;
exports.b64_sha1 = b64_sha1;
exports.str_sha1 = str_sha1;
exports.hex_hmac_sha1 = hex_hmac_sha1;
exports.b64_hmac_sha1 = b64_hmac_sha1;
exports.str_hmac_sha1 = str_hmac_sha1;
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}
/*
* Perform a simple self-test to see if the VM is working
*/
function sha1_vm_test()
{
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";
}
/*
* Calculate the SHA-1 of an array of big-endian words, and a bit length
*/
function core_sha1(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << (24 - len % 32);
x[((len + 64 >> 9) << 4) + 15] = len;
var w = Array(80);
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
var e = -1009589776;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
var olde = e;
for(var j = 0; j < 80; j++)
{
if(j < 16) w[j] = x[i + j];
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),
safe_add(safe_add(e, w[j]), sha1_kt(j)));
e = d;
d = c;
c = rol(b, 30);
b = a;
a = t;
}
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
e = safe_add(e, olde);
}
return Array(a, b, c, d, e);
}
/*
* Perform the appropriate triplet combination function for the current
* iteration
*/
function sha1_ft(t, b, c, d)
{
if(t < 20) return (b & c) | ((~b) & d);
if(t < 40) return b ^ c ^ d;
if(t < 60) return (b & c) | (b & d) | (c & d);
return b ^ c ^ d;
}
/*
* Determine the appropriate additive constant for the current iteration
*/
function sha1_kt(t)
{
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
(t < 60) ? -1894007588 : -899497514;
}
/*
* Calculate the HMAC-SHA1 of a key and some data
*/
function core_hmac_sha1(key, data)
{
var bkey = str2binb(key);
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);
return core_sha1(opad.concat(hash), 512 + 160);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert an 8-bit or 16-bit string to an array of big-endian words
* In 8-bit function, characters >255 have their hi-byte silently ignored.
*/
function str2binb(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);
return bin;
}
/*
* Convert an array of big-endian words to a string
*/
function binb2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);
return str;
}
/*
* Convert an array of big-endian words to a hex string.
*/
function binb2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of big-endian words to a base-64 string
*/
function binb2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}

View file

@ -0,0 +1,16 @@
js2xmlparser is licensed under the MIT license:
> Copyright (C) 2012 Michael Kourlas
>
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
> documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
> rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
> persons to whom the Software is furnished to do so, subject to the following conditions:
>
> The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
> Software.
>
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
> WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
> COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
> OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,223 @@
var xmlDeclaration = true;
var xmlVersion = "1.0";
var xmlEncoding = "UTF-8";
var attributeString = "@";
var valueString = "#";
var prettyPrinting = true;
var indentString = "\t";
module.exports = function (root, data, options) {
return toXML(init(root, data, options));
};
// Initialization
var init = function(root, data, options) {
// Error checking for root element
if (typeof root !== "string")
throw new Error("root element must be a string");
// Error checking and variable initialization for options
if (typeof options === "object" && options !== null) {
if ("declaration" in options) {
if ("include" in options.declaration) {
if (typeof options.declaration.include === "boolean")
xmlDeclaration = options.declaration.include;
else
throw new Error("declaration.include option must be a boolean");
}
if ("encoding" in options.declaration) {
if (typeof options.declaration.encoding === "string" || options.declaration.encoding === null)
xmlEncoding = options.declaration.encoding;
else
throw new Error("declaration.encoding option must be a string or null");
}
}
if ("attributeString" in options) {
if (typeof options.attributeString === "string")
attributeString = options.attributeString;
else
throw new Error("attributeString option must be a string");
}
if ("valueString" in options) {
if (typeof options.valueString === "string")
valueString = options.valueString;
else
throw new Error("valueString option must be a string");
}
if ("prettyPrinting" in options) {
if ("enabled" in options.prettyPrinting) {
if (typeof options.prettyPrinting.enabled === "boolean")
prettyPrinting = options.prettyPrinting.enabled;
else
throw new Error("prettyPrinting.enabled option must be a boolean");
}
if ("indentString" in options.prettyPrinting) {
if (typeof options.prettyPrinting.indentString === "string")
indentString = options.prettyPrinting.indentString;
else
throw new Error("prettyPrinting.indentString option must be a string");
}
}
}
// Error checking and variable initialization for data
if (typeof data !== "string" && typeof data !== "object")
throw new Error("data must be an object or a string");
if (typeof data === "string")
data = JSON.parse(data);
var tempData = {};
tempData[root] = data; // Add root element to object
return tempData;
};
// Convert object to XML
var toXML = function(object) {
// Initialize arguments, if necessary
var xml = arguments[1] || "";
var level = arguments[2] || 0;
for (var property in object) {
// Arrays
if (Object.prototype.toString.call(object[property]) === "[object Array]") {
// Create separate object for each array element and pass to this function
for (var i = 0; i < object[property].length; i++) {
var obj = {};
obj[property] = object[property][i];
xml = toXML(obj, xml, level);
}
}
// JSON-type objects with properties
else if (Object.prototype.toString.call(object[property]) === "[object Object]") {
xml += addIndent("<" + property, level);
// Add attributes
var lengthExcludingAttributes = Object.keys(object[property]).length;
if (Object.prototype.toString.call(object[property][attributeString]) === "[object Object]") {
lengthExcludingAttributes -= 1;
for (var attribute in object[property][attributeString])
xml += " " + attribute + "=\"" + toString(object[property][attributeString][attribute]) + "\"";
}
if (lengthExcludingAttributes === 0) // Empty object
xml += addBreak("/>");
else if (lengthExcludingAttributes === 1 && valueString in object[property]) // Value string only
xml += addBreak(">" + toString(object[property][valueString]) + "</" + property + ">");
else { // Object with properties
xml += addBreak(">");
// Create separate object for each property and pass to this function
for (var subProperty in object[property]) {
if (subProperty !== attributeString) {
var tempObject = {};
tempObject[subProperty] = object[property][subProperty];
xml = toXML(tempObject, xml, level + 1);
}
}
xml += addBreak(addIndent("</" + property + ">", level));
}
}
// Everything else
else {
xml += addBreak(addIndent("<" + property + ">" + toString(object[property]) + "</" + property + ">", level));
}
}
// Finalize XML at end of process
if (level === 0) {
// Remove extra line break at end of file
xml = xml.substring(0, xml.length - 1);
// Add XML declaration
if (xmlDeclaration)
if (xmlEncoding === null)
xml = addBreak("<?xml version=\"" + xmlVersion + "\"?>") + xml;
else
xml = addBreak("<?xml version=\"" + xmlVersion + "\" encoding=\"" + xmlEncoding + "\"?>") + xml;
}
return xml;
};
// Add indenting to data for pretty printing
var addIndent = function(data, level) {
if (prettyPrinting) {
var indent = "";
for (var i = 0; i < level; i++) {
indent += indentString;
}
data = indent + data;
}
return data;
};
// Add line break to data for pretty printing
var addBreak = function(data) {
return prettyPrinting ? data + "\n" : data;
};
// Convert anything into a valid XML string representation
var toString = function(data) {
// Recursive function used to handle nested functions
var functionHelper = function(data) {
if (Object.prototype.toString.call(data) === "[object Function]")
return (data() === undefined) ? data.toString() : functionHelper(data());
else
return data;
};
// Functions
if (Object.prototype.toString.call(data) === "[object Function]")
data = functionHelper(data);
// Empty objects
else if (Object.prototype.toString.call(data) === "[object Object]" && Object.keys(data).length === 0)
data = "";
// Cast data to string
if (typeof data !== "string")
data = data.toString();
// Escape illegal XML characters
data = data.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&apos;");
return data;
};

View file

@ -0,0 +1,30 @@
{
"name": "js2xmlparser",
"description": "Parses JavaScript objects into XML",
"keywords": [
"convert",
"converter",
"js",
"json",
"object",
"objects",
"parse",
"parser",
"xml"
],
"homepage": "http://www.kourlas.net",
"version": "0.1.0",
"author": {
"name": "Michael Kourlas",
"email": "michaelkourlas@gmail.com"
},
"main": "./lib/js2xmlparser.js",
"repository": {
"type": "git",
"url": "git://github.com/michaelkourlas/node-js2xmlparser.git"
},
"license": "MIT",
"readme": "# node-js2xmlparser #\r\n\r\n## Overview ##\r\n\r\njs2xmlparser is a Node.js module that parses JavaScript objects into XML.\r\n\r\n## Features ##\r\n\r\nSince XML is a data-interchange format, js2xmlparser is designed primarily for JSON-type objects, arrays and primitive\r\ndata types, like many of the other JavaScript to XML parsers currently available for Node.js.\r\n\r\nHowever, js2xmlparser is capable of parsing any object, including native JavaScript objects such as Date and RegExp, by\r\ntaking advantage of each object's toString function. Functions are a special case where the return value of the function\r\nitself is used instead of the toString function, if available.\r\n\r\njs2xmlparser also supports a number of constructs unique to XML:\r\n\r\n* attributes (through a unique attribute property in objects)\r\n* mixed content (through a unique value property in objects)\r\n* multiple elements with the same name (through arrays)\r\n\r\njs2xmlparser can also pretty-print the XML it outputs with the option of customizing the indent string.\r\n\r\n## Installation ##\r\n\r\nThe easiest way to install js2xmlparser is to use npm: `npm install js2xmlparser`.\r\n\r\nAlternatively, you may download the source from GitHub and copy it to a folder named \"js2xmlparser\" within your\r\n\"node_modules\" directory.\r\n\r\n## Usage ##\r\n\r\nThe js2xmlparser module contains one function which takes the following arguments:\r\n\r\n* `root` - string containing the root element of the XML\r\n* `data` - object or JSON string to be converted to XML\r\n* `options` - object containing options (optional)\r\n * `declaration` - XML declaration options object (optional)\r\n * `include` - boolean representing whether an XML declaration is included (optional, default: true)\r\n * `encoding` - string representing the XML encoding for the corresponding attribute in the declaration; a value\r\n of null represents no encoding attribute (optional, default: \"UTF-8\")\r\n * `attributeString` - string containing the attribute property (optional, default: \"@\")\r\n * `valueString` - string containing the value property (optional, default: \"#\")\r\n * `prettyPrinting` - pretty-printing options object (optional)\r\n * `enabled` - boolean representing whether pretty-printing is enabled (optional, default: true)\r\n * `indentString` - string representing the indent (optional, default: \"\\t\")\r\n\r\n## Example ##\r\n\r\nThe following example illustrates the basic usage of js2xmlparser:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"firstName\": \"John\",\r\n \"lastName\": \"Smith\"\r\n };\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n > <person>\r\n > <firstName>John</firstName>\r\n > <lastName>Smith</lastName>\r\n > </person>\r\n\r\nHere's a more complex example that builds on the first:\r\n\r\n var js2xmlparser = require(\"js2xmlparser\");\r\n\r\n var data = {\r\n \"firstName\": \"John\",\r\n \"lastName\": \"Smith\",\r\n \"dateOfBirth\": new Date(1964, 07, 26),\r\n \"address\": {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"streetAddress\": \"3212 22nd St\",\r\n \"city\": \"Chicago\",\r\n \"state\": \"Illinois\",\r\n \"zip\": 10000\r\n },\r\n \"phone\": [\r\n {\r\n \"@\": {\r\n \"type\": \"home\"\r\n },\r\n \"#\": \"123-555-4567\"\r\n },\r\n {\r\n \"@\": {\r\n \"type\": \"cell\"\r\n },\r\n \"#\": \"456-555-7890\"\r\n }\r\n ],\r\n \"email\": function() {return \"john@smith.com\";}\r\n }\r\n\r\n console.log(js2xmlparser(\"person\", data));\r\n\r\n > <?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n > <person>\r\n > <firstName>John</firstName>\r\n > <lastName>Smith</lastName>\r\n > <dateOfBirth>Wed Aug 26 1964 00:00:00 GMT-0400 (Eastern Daylight Time)</dateOfBirth>\r\n > <address type=\"home\">\r\n > <streetAddress>3212 22nd St</streetAddress>\r\n > <city>Chicago</city>\r\n > <state>Illinois</state>\r\n > <zip>10000</zip>\r\n > </address>\r\n > <phone type=\"home\">123-555-4567</phone>\r\n > <phone type=\"cell\">456-555-7890</phone>\r\n > <email>john@smith.com</email>\r\n > </person>",
"_id": "js2xmlparser@0.1.0",
"_from": "js2xmlparser"
}

1
data/scripts/jsdoc/node_modules/jsdoc generated vendored Normal file
View file

@ -0,0 +1 @@
../lib/jsdoc

4
data/scripts/jsdoc/node_modules/jshint/LICENSE generated vendored Normal file
View file

@ -0,0 +1,4 @@
** Licensed Under **
The MIT License
http://www.opensource.org/licenses/mit-license.php

43
data/scripts/jsdoc/node_modules/jshint/package.json generated vendored Normal file
View file

@ -0,0 +1,43 @@
{
"name": "jshint",
"version": "0.9.1",
"description": "A CLI for JSHint",
"homepage": "http://github.com/jshint/node-jshint",
"author": {
"name": "Brent Lintner",
"email": "brent.lintner@gmail.com",
"url": "http://github.com/brentlintner"
},
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"bin": {
"jshint": "./bin/hint"
},
"main": "packages/jshint/jshint",
"files": [
"packages/jshint/README.markdown",
"packages/jshint/jshint.js",
"README.md",
"LICENSE",
"bin/hint",
"lib"
],
"dependencies": {
"cli": "0.4.3",
"minimatch": "0.0.x"
},
"devDependencies": {
"jasmine-node": "1.0.x"
},
"preferGlobal": true,
"readme": "# node-jshint\n\nA command line interface and npm package for jshint.\n\n## Install\n\nTo use jshint from any location (for npm v1.x) you need to install using the global (-g) flag.\n\n npm install -g jshint\n\n## Usage\n\n jshint -h\n\nYou can also require JSHint itself as a module.\n\n var jshint = require('jshint');\n\nNote: If you are using npm v1.x be sure to install jshint locally (without the -g flag) or link it globally.\n\n## Text Editor Plugins\n\n* [gedit-node-jshint](https://github.com/niftylettuce/gedit-node-jshint) - Simply use CTRL+J in gedit to run JSHint using `node-jshint`.\n* [vim syntastic](https://github.com/scrooloose/syntastic) - Run node-jshint at each file save.\n* [sublime-jshint](https://github.com/uipoet/sublime-jshint) - `F7` or `command-B` on any .js file. `F4` next error line,column. `shift-F4` previous error line,column.\n\n## Custom Reporters\n\nSpecify a custom reporter module (see example/reporter.js).\n\n --reporter path/to/reporter.js\n\nUse a jslint compatible xml reporter.\n\n --jslint-reporter\n\nShow additional non-error data generated by jshint (unused globals etc).\n\n --show-non-errors\n\n## Configuration Options\n\n**Note:** This behavior described below is very different from versions prior to `0.6`.\n\nThe CLI uses the default options that come with JSHint. \n\nOnly one extra option is unique to node-jshint: `globals` \nallows you to define an object of globals that get ignored for every file.\nTo see an example you can look at how whitelisted globals are defined\nin the [jshint code](https://github.com/jshint/jshint/blob/c047ea1b01097fcc220fcd1a55c41f67ae2e6e81/jshint.js#L556)\n\nTo have your own configuration apply, there are several methods you can use:\n\n### Specify Manually\n\nSetting the `--config=/path/to/your/config` command line option to specify your own configuration file outside of the directory tree for your project.\n\n### Within your Project's Directory Tree\n\nWhen the CLI is called, and a configuration file isn't specified already, `node-jshint` will attempt to locate one for you starting in `pwd`. (or \"present working directory\") If this does not yield a `.jshintrc` file, it will move one level up (`..`) the directory tree all the way up to the filesystem root. If a file is found, it stops immediately and uses that set of configuration.\n\nThis setup allows you to set up **one** configuration file for your entire project. (place it in the root folder) As long as you run `jshint` from anywhere within your project directory tree, the same configuration file will be used.\n\n### Home Directory\n\nIf all the methods above do not yield a `.jshintrc` to use, the last place that will be checked is your user's `$HOME` directory.\n\n## File Extensions\n\nDefault extension for files is \".js\". If you want to use JSHint with other file extensions (.json), you need to pass this extra extension as an option :\n\n --extra-ext .json\n\n## Ignoring Files and Directories\n\nIf there is a .jshintignore file in your project's directory tree, (also provided you run `jshint` from within your project's directory) then any directories or files specified will be skipped over. (behaves just like a `.gitignore` file)\n\n**Note:** Pattern matching uses minimatch, with the nocase [option](https://github.com/isaacs/minimatch). When there is no match, it performs a left side match (when no forward slashes present and path is a directory).\n\n## Installing dependencies for development\n\n ./configure\n\n## Build Commands\n\n jake -T\n\n## Project Guidelines\n\n* All tests are passing.\n* No (new) JSHint errors are introduced.\n",
"_id": "jshint@0.9.1",
"dist": {
"shasum": "ea05fb7d6dae4f2d0d0392ad89b06f7b72eb497e"
},
"_from": "jshint"
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,115 @@
markdown-js
===========
Yet another markdown parser, this time for JavaScript. There's a few
options that precede this project but they all treat markdown to HTML
conversion as a single step process. You pass markdown in and get HTML
out, end of story. We had some pretty particular views on how the
process should actually look, which include:
* producing well-formed HTML. This means that em and strong nesting is
important, as is the ability to output as both HTML and XHTML
* having an intermediate representation to allow processing of parsed
data (we in fact have two, both [JsonML]: a markdown tree and an
HTML tree)
* being easily extensible to add new dialects without having to
rewrite the entire parsing mechanics
* having a good test suite. The only test suites we could find tested
massive blocks of input, and passing depended on outputting the HTML
with exactly the same whitespace as the original implementation
[JsonML]: http://jsonml.org/ "JSON Markup Language"
## Installation
Just the `markdown` library:
npm install markdown
Also install `md2html` to `/usr/local/bin` (or wherever)
npm install -g markdown
## Usage
The simple way to use it with CommonJS is:
var input = "# Heading\n\nParagraph";
var output = require( "markdown" ).markdown.toHTML( input );
print( output );
If you want more control check out the documentation in
[lib/markdown.js] which details all the methods and parameters
available (including examples!). One day we'll get the docs generated
and hosted somewhere for nicer browsing.
It also works in a browser; here is a complete example:
<!DOCTYPE html>
<html>
<body>
<textarea id="text-input" oninput="this.editor.update()"
rows="6" cols="60">Type **Markdown** here.</textarea>
<div id="preview"> </div>
<script src="lib/markdown.js"></script>
<script>
function Editor(input, preview)
{
this.update = function () {
preview.innerHTML = markdown.toHTML(input.value);
}
input.editor = this;
this.update();
}
var $ = function (id) { return document.getElementById(id); };
new Editor($("text-input"), $("preview"));
</script>
</body>
</html>
### md2html
md2html /path/to/doc.md > /path/to/doc.html
[lib/markdown.js]: http://github.com/evilstreak/markdown-js/blob/master/lib/markdown.js
## Intermediate Representation
Internally the process to convert a chunk of markdown into a chunk of
HTML has three steps:
1. Parse the markdown into a JsonML tree. Any references found in the
parsing are stored in the attribute hash of the root node under the
key `references`.
2. Convert the markdown tree into an HTML tree. Rename any nodes that
need it (`bulletlist` to `ul` for example) and lookup any references
used by links or images. Remove the references attribute once done.
3. Stringify the HTML tree being careful not to wreck whitespace where
whitespace is important (surrounding inline elements for example).
Each step of this process can be called individually if you need to do
some processing or modification of the data at an intermediate stage.
For example, you may want to grab a list of all URLs linked to in the
document before rendering it to HTML which you could do by recursing
through the HTML tree looking for `a` nodes.
## Running tests
To run the tests under node you will need tap installed (it's listed as a
devDependencies so `npm install` from the checkout should be enough), then do
$ ./node_modules/.bin/tap test/*.t.js
## Contributing
Do the usual github fork and pull request dance. Add yourself to the
contributors section of package.json too if you want to.
## License
Released under the MIT license.

View file

@ -0,0 +1,3 @@
// super simple module for the most common nodejs use case.
exports.markdown = require("./markdown");
exports.parse = exports.markdown.toHTML;

1616
data/scripts/jsdoc/node_modules/markdown/lib/markdown.js generated vendored Normal file

File diff suppressed because it is too large Load diff

68
data/scripts/jsdoc/node_modules/markdown/package.json generated vendored Normal file
View file

@ -0,0 +1,68 @@
{
"name": "markdown",
"version": "0.4.0",
"description": "A sensible Markdown parser for javascript",
"keywords": [
"markdown",
"text processing",
"ast"
],
"maintainers": [
{
"name": "Dominic Baggott",
"email": "dominic.baggott@gmail.com",
"url": "http://evilstreak.co.uk"
},
{
"name": "Ash Berlin",
"email": "ash_markdownjs@firemirror.com",
"url": "http://ashberlin.com"
}
],
"contributors": [
{
"name": "Dominic Baggott",
"email": "dominic.baggott@gmail.com",
"url": "http://evilstreak.co.uk"
},
{
"name": "Ash Berlin",
"email": "ash_markdownjs@firemirror.com",
"url": "http://ashberlin.com"
}
],
"bugs": {
"url": "http://github.com/evilstreak/markdown-js/issues"
},
"licenses": [
{
"type": "MIT",
"url": "http://www.opensource.org/licenses/mit-license.php"
}
],
"repository": {
"type": "git",
"url": "git://github.com/evilstreak/markdown-js.git"
},
"main": "./lib/index.js",
"bin": {
"md2html": "./bin/md2html.js"
},
"dependencies": {
"nopt": "1"
},
"devDependencies": {
"tap": "0"
},
"scripts": {
"test": "tap test/*.t.js"
},
"readme": "markdown-js\n===========\n\nYet another markdown parser, this time for JavaScript. There's a few\noptions that precede this project but they all treat markdown to HTML\nconversion as a single step process. You pass markdown in and get HTML\nout, end of story. We had some pretty particular views on how the\nprocess should actually look, which include:\n\n * producing well-formed HTML. This means that em and strong nesting is\n important, as is the ability to output as both HTML and XHTML\n\n * having an intermediate representation to allow processing of parsed\n data (we in fact have two, both [JsonML]: a markdown tree and an\n HTML tree)\n\n * being easily extensible to add new dialects without having to\n rewrite the entire parsing mechanics\n\n * having a good test suite. The only test suites we could find tested\n massive blocks of input, and passing depended on outputting the HTML\n with exactly the same whitespace as the original implementation\n\n[JsonML]: http://jsonml.org/ \"JSON Markup Language\"\n\n## Installation\n\nJust the `markdown` library:\n\n npm install markdown\n\nAlso install `md2html` to `/usr/local/bin` (or wherever)\n\n npm install -g markdown\n\n## Usage\n\nThe simple way to use it with CommonJS is:\n\n var input = \"# Heading\\n\\nParagraph\";\n var output = require( \"markdown\" ).markdown.toHTML( input );\n print( output );\n\nIf you want more control check out the documentation in\n[lib/markdown.js] which details all the methods and parameters\navailable (including examples!). One day we'll get the docs generated\nand hosted somewhere for nicer browsing.\n\nIt also works in a browser; here is a complete example:\n\n <!DOCTYPE html>\n <html>\n <body>\n <textarea id=\"text-input\" oninput=\"this.editor.update()\"\n rows=\"6\" cols=\"60\">Type **Markdown** here.</textarea>\n <div id=\"preview\"> </div>\n <script src=\"lib/markdown.js\"></script>\n <script>\n function Editor(input, preview)\n {\n this.update = function () {\n preview.innerHTML = markdown.toHTML(input.value);\n }\n input.editor = this;\n this.update();\n }\n var $ = function (id) { return document.getElementById(id); };\n new Editor($(\"text-input\"), $(\"preview\"));\n </script>\n </body>\n </html>\n\n### md2html\n\n md2html /path/to/doc.md > /path/to/doc.html\n\n[lib/markdown.js]: http://github.com/evilstreak/markdown-js/blob/master/lib/markdown.js\n\n## Intermediate Representation\n\nInternally the process to convert a chunk of markdown into a chunk of\nHTML has three steps:\n\n 1. Parse the markdown into a JsonML tree. Any references found in the\n parsing are stored in the attribute hash of the root node under the\n key `references`.\n\n 2. Convert the markdown tree into an HTML tree. Rename any nodes that\n need it (`bulletlist` to `ul` for example) and lookup any references\n used by links or images. Remove the references attribute once done.\n\n 3. Stringify the HTML tree being careful not to wreck whitespace where\n whitespace is important (surrounding inline elements for example).\n\nEach step of this process can be called individually if you need to do\nsome processing or modification of the data at an intermediate stage.\nFor example, you may want to grab a list of all URLs linked to in the\ndocument before rendering it to HTML which you could do by recursing\nthrough the HTML tree looking for `a` nodes.\n\n## Running tests\n\nTo run the tests under node you will need tap installed (it's listed as a\ndevDependencies so `npm install` from the checkout should be enough), then do\n\n $ ./node_modules/.bin/tap test/*.t.js\n\n## Contributing\n\nDo the usual github fork and pull request dance. Add yourself to the\ncontributors section of package.json too if you want to.\n\n## License\n\nReleased under the MIT license.\n",
"readmeFilename": "README.markdown",
"_id": "markdown@0.4.0",
"dist": {
"shasum": "6a5d7cb751c1d1e6adc374d40e9d358474b59a8e"
},
"_resolved": "git://github.com/jsdoc3/markdown-js.git#fd27f4c979f3f71e82e1fe76ffe6415980b31f00",
"_from": "git://github.com/jsdoc3/markdown-js.git"
}

19
data/scripts/jsdoc/node_modules/marked/LICENSE generated vendored Normal file
View file

@ -0,0 +1,19 @@
Copyright (c) 2011-2013, Christopher Jeffrey (https://github.com/chjj/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

1
data/scripts/jsdoc/node_modules/marked/index.js generated vendored Normal file
View file

@ -0,0 +1 @@
module.exports = require('./lib/marked');

1076
data/scripts/jsdoc/node_modules/marked/lib/marked.js generated vendored Normal file

File diff suppressed because it is too large Load diff

46
data/scripts/jsdoc/node_modules/marked/package.json generated vendored Normal file
View file

@ -0,0 +1,46 @@
{
"name": "marked",
"description": "A markdown parser built for speed",
"author": {
"name": "Christopher Jeffrey"
},
"version": "0.2.8",
"main": "./lib/marked.js",
"bin": {
"marked": "./bin/marked"
},
"man": [
"./man/marked.1"
],
"preferGlobal": true,
"repository": {
"type": "git",
"url": "git://github.com/chjj/marked.git"
},
"homepage": "https://github.com/chjj/marked",
"bugs": {
"url": "http://github.com/chjj/marked/issues"
},
"keywords": [
"markdown",
"markup",
"html"
],
"tags": [
"markdown",
"markup",
"html"
],
"scripts": {
"test": "node test",
"bench": "node test --bench"
},
"readme": "# marked\n\nA full-featured markdown parser and compiler, written in javascript.\nBuilt for speed.\n\n## Benchmarks\n\nnode v0.4.x\n\n``` bash\n$ node test --bench\nmarked completed in 12071ms.\nshowdown (reuse converter) completed in 27387ms.\nshowdown (new converter) completed in 75617ms.\nmarkdown-js completed in 70069ms.\n```\n\nnode v0.6.x\n\n``` bash\n$ node test --bench\nmarked completed in 6448ms.\nmarked (gfm) completed in 7357ms.\nmarked (pedantic) completed in 6092ms.\ndiscount completed in 7314ms.\nshowdown (reuse converter) completed in 16018ms.\nshowdown (new converter) completed in 18234ms.\nmarkdown-js completed in 24270ms.\n```\n\n__Marked is now faster than Discount, which is written in C.__\n\nFor those feeling skeptical: These benchmarks run the entire markdown test suite\n1000 times. The test suite tests every feature. It doesn't cater to specific\naspects.\n\n## Install\n\n``` bash\n$ npm install marked\n```\n\n## Another Javascript Markdown Parser\n\nThe point of marked was to create a markdown compiler where it was possible to\nfrequently parse huge chunks of markdown without having to worry about\ncaching the compiled output somehow...or blocking for an unnecesarily long time.\n\nmarked is very concise and still implements all markdown features. It is also\nnow fully compatible with the client-side.\n\nmarked more or less passes the official markdown test suite in its\nentirety. This is important because a surprising number of markdown compilers\ncannot pass more than a few tests. It was very difficult to get marked as\ncompliant as it is. It could have cut corners in several areas for the sake\nof performance, but did not in order to be exactly what you expect in terms\nof a markdown rendering. In fact, this is why marked could be considered at a\ndisadvantage in the benchmarks above.\n\nAlong with implementing every markdown feature, marked also implements\n[GFM features](http://github.github.com/github-flavored-markdown/).\n\n## Options\n\nmarked has a few different switches which change behavior.\n\n- __pedantic__: Conform to obscure parts of `markdown.pl` as much as possible.\n Don't fix any of the original markdown bugs or poor behavior.\n- __gfm__: Enable github flavored markdown (enabled by default).\n- __sanitize__: Sanitize the output. Ignore any HTML that has been input.\n- __highlight__: A callback to highlight code blocks.\n- __tables__: Enable GFM tables. This is enabled by default. (Requires the\n `gfm` option in order to be enabled).\n- __breaks__: Enable GFM line breaks. Disabled by default.\n- __smartLists__: Use smarter list behavior than the original markdown.\n Disabled by default. May eventually be default with the old behavior\n moved into `pedantic`.\n- __langPrefix__: Set the prefix for code block classes. Defaults to `lang-`.\n\n## Usage\n\n``` js\n// Set default options\nmarked.setOptions({\n gfm: true,\n tables: true,\n breaks: false,\n pedantic: false,\n sanitize: true,\n smartLists: true,\n langPrefix: 'language-',\n highlight: function(code, lang) {\n if (lang === 'js') {\n return highlighter.javascript(code);\n }\n return code;\n }\n});\nconsole.log(marked('i am using __markdown__.'));\n```\n\nYou also have direct access to the lexer and parser if you so desire.\n\n``` js\nvar tokens = marked.lexer(text, options);\nconsole.log(marked.parser(tokens));\n```\n\n``` js\nvar lexer = new marked.Lexer(options);\nvar tokens = lexer.lex(text);\nconsole.log(tokens);\nconsole.log(lexer.rules);\n```\n\n``` bash\n$ node\n> require('marked').lexer('> i am using marked.')\n[ { type: 'blockquote_start' },\n { type: 'paragraph',\n text: 'i am using marked.' },\n { type: 'blockquote_end' },\n links: {} ]\n```\n\n## CLI\n\n``` bash\n$ marked -o hello.html\nhello world\n^D\n$ cat hello.html\n<p>hello world</p>\n```\n\n## License\n\nCopyright (c) 2011-2013, Christopher Jeffrey. (MIT License)\n\nSee LICENSE for more info.\n",
"readmeFilename": "README.md",
"_id": "marked@0.2.8",
"dist": {
"shasum": "740103e3cd0e98050c99cd1cc2b8d823bf640aee"
},
"_from": "marked@0.2.8",
"_resolved": "https://registry.npmjs.org/marked/-/marked-0.2.8.tgz"
}

1
data/scripts/jsdoc/node_modules/taffydb/README.md generated vendored Normal file
View file

@ -0,0 +1 @@
See [http://taffydb.com](http://taffydb.com).

17
data/scripts/jsdoc/node_modules/taffydb/package.json generated vendored Normal file
View file

@ -0,0 +1,17 @@
{
"name": "taffydb",
"version": "2.6.2",
"description": "An open-source library that brings database features into your JavaScript applications.",
"main": "taffy.js",
"repository": {
"type": "git",
"url": "git://github.com/hegemonic/taffydb.git"
},
"license": "BSD",
"readme": "See [http://taffydb.com](http://taffydb.com).",
"_id": "taffydb@2.6.2",
"dist": {
"shasum": "4ffeb4b49fd82c123fb5804606b0928f3e9e30b1"
},
"_from": "taffydb@git://github.com/hegemonic/taffydb.git"
}

View file

@ -0,0 +1,84 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>taffy test</title>
<script src="./taffy.js"></script>
<script>
// recursive object compare, for future use
Object.prototype.equals = function (x) {
var p;
for(p in this) {
if(typeof(x[p])=='undefined') {return false;}
}
for(p in this) {
if (this[p]) {
switch(typeof(this[p])) {
case 'object':
if (! this[p].equals(x[p])) { return false; }
break;
case 'function':
if (typeof(x[p])=='undefined' ||
(p != 'equals' && this[p].toString() != x[p].toString())
){ return false; }
break;
default:
if (this[p] != x[p]) { return false; }
}
}
else {
if (x[p]){ return false; }
}
}
for(p in x) {
if(typeof(this[p])=='undefined') {return false;}
}
return true;
};
var key_name, data_val, friends_table, taffy_map;
friends_table = TAFFY([
{"id":1,"gender":"M","first":"John","last":"Smith","city":"Seattle, WA","status":"Active"},
{"id":2,"gender":"F","first":"Kelly","last":"Ruth","city":"Dallas, TX","status":"Active"},
{"id":3,"gender":"M","first":"Jeff","last":"Stevenson","city":"Washington, D.C.","status":"Active"},
{"id":4,"gender":"F","first":"Jennifer","last":"Gill","city":"Seattle, WA","status":"Active"}
]);
taffy_map = {
t_by_city : friends_table({city:"Seattle, WA"}),
t_by_id : friends_table({id:1}),
t_by_id_f : friends_table({id:'1'}),
t_by_name : friends_table({first:'John',last:'Smith'}),
kelly_by_id : friends_table({id:2}).first(),
kelly_last_name : friends_table({id:2}).first().last,
id_list : friends_table().select('id'),
city_list : friends_table().distinct('city'),
};
for ( key_name in taffy_map ){
if ( taffy_map.hasOwnProperty(key_name) ){
data_val = taffy_map[key_name];
console.warn(key_name, data_val);
if ( data_val.hasOwnProperty('get') ){
console.warn(JSON.stringify(data_val.get()));
}
console.warn('----------------');
}
}
</script>
</head>
<body>
<div>
Please open your javascript console to see test results
</div>
</body>
</html>

1973
data/scripts/jsdoc/node_modules/taffydb/taffy.js generated vendored Normal file

File diff suppressed because it is too large Load diff

22
data/scripts/jsdoc/node_modules/underscore/LICENSE generated vendored Normal file
View file

@ -0,0 +1,22 @@
Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,25 @@
{
"name": "underscore",
"description": "JavaScript's functional programming helper library.",
"homepage": "http://underscorejs.org",
"keywords": [
"util",
"functional",
"server",
"client",
"browser"
],
"author": {
"name": "Jeremy Ashkenas",
"email": "jeremy@documentcloud.org"
},
"repository": {
"type": "git",
"url": "git://github.com/documentcloud/underscore.git"
},
"main": "underscore.js",
"version": "1.4.2",
"readme": " __\n /\\ \\ __\n __ __ ___ \\_\\ \\ __ _ __ ____ ___ ___ _ __ __ /\\_\\ ____\n /\\ \\/\\ \\ /' _ `\\ /'_ \\ /'__`\\/\\ __\\/ ,__\\ / ___\\ / __`\\/\\ __\\/'__`\\ \\/\\ \\ /',__\\\n \\ \\ \\_\\ \\/\\ \\/\\ \\/\\ \\ \\ \\/\\ __/\\ \\ \\//\\__, `\\/\\ \\__//\\ \\ \\ \\ \\ \\//\\ __/ __ \\ \\ \\/\\__, `\\\n \\ \\____/\\ \\_\\ \\_\\ \\___,_\\ \\____\\\\ \\_\\\\/\\____/\\ \\____\\ \\____/\\ \\_\\\\ \\____\\/\\_\\ _\\ \\ \\/\\____/\n \\/___/ \\/_/\\/_/\\/__,_ /\\/____/ \\/_/ \\/___/ \\/____/\\/___/ \\/_/ \\/____/\\/_//\\ \\_\\ \\/___/\n \\ \\____/\n \\/___/\n\nUnderscore.js is a utility-belt library for JavaScript that provides\nsupport for the usual functional suspects (each, map, reduce, filter...)\nwithout extending any core JavaScript objects.\n\nFor Docs, License, Tests, and pre-packed downloads, see:\nhttp://underscorejs.org\n\nMany thanks to our contributors:\nhttps://github.com/documentcloud/underscore/contributors\n",
"_id": "underscore@1.4.2",
"_from": "underscore"
}

1200
data/scripts/jsdoc/node_modules/underscore/underscore.js generated vendored Normal file

File diff suppressed because it is too large Load diff

21
data/scripts/jsdoc/node_modules/wrench/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2010 Ryan McGrath
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

399
data/scripts/jsdoc/node_modules/wrench/lib/wrench.js generated vendored Normal file
View file

@ -0,0 +1,399 @@
/* wrench.js
*
* A collection of various utility functions I've found myself in need of
* for use with Node.js (http://nodejs.org/). This includes things like:
*
* - Recursively deleting directories in Node.js (Sync, not Async)
* - Recursively copying directories in Node.js (Sync, not Async)
* - Recursively chmoding a directory structure from Node.js (Sync, not Async)
* - Other things that I'll add here as time goes on. Shhhh...
*
* ~ Ryan McGrath (ryan [at] venodesigns.net)
*/
var fs = require("fs"),
_path = require("path");
/* wrench.readdirSyncRecursive("directory_path");
*
* Recursively dives through directories and read the contents of all the
* children directories.
*/
exports.readdirSyncRecursive = function(baseDir) {
baseDir = baseDir.replace(/\/$/, '');
var readdirSyncRecursive = function(baseDir) {
var files = [],
curFiles,
nextDirs,
isDir = function(fname){
return fs.statSync( _path.join(baseDir, fname) ).isDirectory();
},
prependBaseDir = function(fname){
return _path.join(baseDir, fname);
};
curFiles = fs.readdirSync(baseDir);
nextDirs = curFiles.filter(isDir);
curFiles = curFiles.map(prependBaseDir);
files = files.concat( curFiles );
while (nextDirs.length) {
files = files.concat( readdirSyncRecursive( _path.join(baseDir, nextDirs.shift()) ) );
}
return files;
};
// convert absolute paths to relative
var fileList = readdirSyncRecursive(baseDir).map(function(val){
return _path.relative(baseDir, val);
});
return fileList;
};
/* wrench.readdirRecursive("directory_path", function(error, files) {});
*
* Recursively dives through directories and read the contents of all the
* children directories.
*
* Asynchronous, so returns results/error in callback.
* Callback receives the of files in currently recursed directory.
* When no more directories are left, callback is called with null for all arguments.
*
*/
exports.readdirRecursive = function(baseDir, fn) {
baseDir = baseDir.replace(/\/$/, '');
var waitCount = 0;
function readdirRecursive(curDir) {
var files = [],
curFiles,
nextDirs,
prependcurDir = function(fname){
return _path.join(curDir, fname);
};
waitCount++;
fs.readdir(curDir, function(e, curFiles) {
waitCount--;
curFiles = curFiles.map(prependcurDir);
curFiles.forEach(function(it) {
waitCount++;
fs.stat(it, function(e, stat) {
waitCount--;
if (e) {
fn(e);
} else {
if (stat.isDirectory()) {
readdirRecursive(it);
}
}
if (waitCount == 0) {
fn(null, null);
}
});
});
fn(null, curFiles.map(function(val) {
// convert absolute paths to relative
return _path.relative(baseDir, val);
}));
if (waitCount == 0) {
fn(null, null);
}
});
};
readdirRecursive(baseDir);
};
/* wrench.rmdirSyncRecursive("directory_path", forceDelete, failSilent);
*
* Recursively dives through directories and obliterates everything about it. This is a
* Sync-function, which blocks things until it's done. No idea why anybody would want an
* Asynchronous version. :\
*/
exports.rmdirSyncRecursive = function(path, failSilent) {
var files;
try {
files = fs.readdirSync(path);
} catch (err) {
if(failSilent) return;
throw new Error(err.message);
}
/* Loop through and delete everything in the sub-tree after checking it */
for(var i = 0; i < files.length; i++) {
var currFile = fs.lstatSync(path + "/" + files[i]);
if(currFile.isDirectory()) // Recursive function back to the beginning
exports.rmdirSyncRecursive(path + "/" + files[i]);
else if(currFile.isSymbolicLink()) // Unlink symlinks
fs.unlinkSync(path + "/" + files[i]);
else // Assume it's a file - perhaps a try/catch belongs here?
fs.unlinkSync(path + "/" + files[i]);
}
/* Now that we know everything in the sub-tree has been deleted, we can delete the main
directory. Huzzah for the shopkeep. */
return fs.rmdirSync(path);
};
/* wrench.copyDirSyncRecursive("directory_to_copy", "new_directory_location", opts);
*
* Recursively dives through a directory and moves all its files to a new location. This is a
* Synchronous function, which blocks things until it's done. If you need/want to do this in
* an Asynchronous manner, look at wrench.copyDirRecursively() below.
*
* Note: Directories should be passed to this function without a trailing slash.
*/
exports.copyDirSyncRecursive = function(sourceDir, newDirLocation, opts) {
if (!opts || !opts.preserve) {
try {
if(fs.statSync(newDirLocation).isDirectory()) exports.rmdirSyncRecursive(newDirLocation);
} catch(e) { }
}
/* Create the directory where all our junk is moving to; read the mode of the source directory and mirror it */
var checkDir = fs.statSync(sourceDir);
try {
fs.mkdirSync(newDirLocation, checkDir.mode);
} catch (e) {
//if the directory already exists, that's okay
if (e.code !== 'EEXIST') throw e;
}
var files = fs.readdirSync(sourceDir);
for(var i = 0; i < files.length; i++) {
var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
if(currFile.isDirectory()) {
/* recursion this thing right on back. */
exports.copyDirSyncRecursive(sourceDir + "/" + files[i], newDirLocation + "/" + files[i], opts);
} else if(currFile.isSymbolicLink()) {
var symlinkFull = fs.readlinkSync(sourceDir + "/" + files[i]);
fs.symlinkSync(symlinkFull, newDirLocation + "/" + files[i]);
} else {
/* At this point, we've hit a file actually worth copying... so copy it on over. */
var contents = fs.readFileSync(sourceDir + "/" + files[i]);
fs.writeFileSync(newDirLocation + "/" + files[i], contents);
}
}
};
/* wrench.chmodSyncRecursive("directory", filemode);
*
* Recursively dives through a directory and chmods everything to the desired mode. This is a
* Synchronous function, which blocks things until it's done.
*
* Note: Directories should be passed to this function without a trailing slash.
*/
exports.chmodSyncRecursive = function(sourceDir, filemode) {
var files = fs.readdirSync(sourceDir);
for(var i = 0; i < files.length; i++) {
var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
if(currFile.isDirectory()) {
/* ...and recursion this thing right on back. */
exports.chmodSyncRecursive(sourceDir + "/" + files[i], filemode);
} else {
/* At this point, we've hit a file actually worth copying... so copy it on over. */
fs.chmod(sourceDir + "/" + files[i], filemode);
}
}
/* Finally, chmod the parent directory */
fs.chmod(sourceDir, filemode);
};
/* wrench.chownSyncRecursive("directory", uid, gid);
*
* Recursively dives through a directory and chowns everything to the desired user and group. This is a
* Synchronous function, which blocks things until it's done.
*
* Note: Directories should be passed to this function without a trailing slash.
*/
exports.chownSyncRecursive = function(sourceDir, uid, gid) {
var files = fs.readdirSync(sourceDir);
for(var i = 0; i < files.length; i++) {
var currFile = fs.lstatSync(sourceDir + "/" + files[i]);
if(currFile.isDirectory()) {
/* ...and recursion this thing right on back. */
exports.chownSyncRecursive(sourceDir + "/" + files[i], uid, gid);
} else {
/* At this point, we've hit a file actually worth chowning... so own it. */
fs.chownSync(sourceDir + "/" + files[i], uid, gid);
}
}
/* Finally, chown the parent directory */
fs.chownSync(sourceDir, uid, gid);
};
/* wrench.rmdirRecursive("directory_path", callback);
*
* Recursively dives through directories and obliterates everything about it.
*/
exports.rmdirRecursive = function rmdirRecursive(dir, clbk){
fs.readdir(dir, function(err, files){
if (err) return clbk(err);
(function rmFile(err){
if (err) return clbk(err);
var filename = files.shift();
if (filename === null || typeof filename == 'undefined')
return fs.rmdir(dir, clbk);
var file = dir+'/'+filename;
fs.stat(file, function(err, stat){
if (err) return clbk(err);
if (stat.isDirectory())
rmdirRecursive(file, rmFile);
else
fs.unlink(file, rmFile);
});
})();
});
};
/* wrench.copyDirRecursive("directory_to_copy", "new_location", callback);
*
* Recursively dives through a directory and moves all its files to a new
* location.
*
* Note: Directories should be passed to this function without a trailing slash.
*/
exports.copyDirRecursive = function copyDirRecursive(srcDir, newDir, clbk) {
fs.stat(newDir, function(err, newDirStat){
if (!err) return exports.rmdirRecursive(newDir, function(err){
copyDirRecursive(srcDir, newDir, clbk);
});
fs.stat(srcDir, function(err, srcDirStat){
if (err) return clbk(err);
fs.mkdir(newDir, srcDirStat.mode, function(err){
if (err) return clbk(err);
fs.readdir(srcDir, function(err, files){
if (err) return clbk(err);
(function copyFiles(err){
if (err) return clbk(err);
var filename = files.shift();
if (filename === null || typeof filename == 'undefined')
return clbk();
var file = srcDir+'/'+filename,
newFile = newDir+'/'+filename;
fs.stat(file, function(err, fileStat){
if (fileStat.isDirectory())
copyDirRecursive(file, newFile, copyFiles);
else if (fileStat.isSymbolicLink())
fs.readlink(file, function(err, link){
fs.symlink(link, newFile, copyFiles);
});
else
fs.readFile(file, function(err, data){
fs.writeFile(newFile, data, copyFiles);
});
});
})();
});
});
});
});
};
var mkdirSyncRecursive = function(path, mode) {
var self = this;
try {
fs.mkdirSync(path, mode);
} catch(err) {
if(err.code == "ENOENT") {
var slashIdx = path.lastIndexOf("/");
if(slashIdx < 0) {
slashIdx = path.lastIndexOf("\\");
}
if(slashIdx > 0) {
var parentPath = path.substring(0, slashIdx);
mkdirSyncRecursive(parentPath, mode);
mkdirSyncRecursive(path, mode);
} else {
throw err;
}
} else if(err.code == "EEXIST") {
return;
} else {
throw err;
}
}
};
exports.mkdirSyncRecursive = mkdirSyncRecursive;
exports.LineReader = function(filename, bufferSize) {
this.bufferSize = bufferSize || 8192;
this.buffer = "";
this.fd = fs.openSync(filename, "r");
this.currentPosition = 0;
};
exports.LineReader.prototype = {
getBufferAndSetCurrentPosition: function(position) {
var res = fs.readSync(this.fd, this.bufferSize, position, "ascii");
this.buffer += res[0];
if(res[1] === 0) {
this.currentPosition = -1;
} else {
this.currentPosition = position + res[1];
}
return this.currentPosition;
},
hasNextLine: function() {
while(this.buffer.indexOf('\n') === -1) {
this.getBufferAndSetCurrentPosition(this.currentPosition);
if(this.currentPosition === -1) return false;
}
if(this.buffer.indexOf("\n") > -1) return true;
return false;
},
getNextLine: function() {
var lineEnd = this.buffer.indexOf("\n"),
result = this.buffer.substring(0, lineEnd);
this.buffer = this.buffer.substring(result.length + 1, this.buffer.length);
return result;
}
};
// vim: et ts=4 sw=4

39
data/scripts/jsdoc/node_modules/wrench/package.json generated vendored Normal file
View file

@ -0,0 +1,39 @@
{
"name": "wrench",
"description": "Recursive filesystem (and other) operations that Node *should* have.",
"version": "1.3.9",
"author": {
"name": "Ryan McGrath",
"email": "ryan@venodesigns.net"
},
"repository": {
"type": "git",
"url": "https://ryanmcgrath@github.com/ryanmcgrath/wrench-js.git"
},
"bugs": {
"url": "http://github.com/ryanmcgrath/wrench-js/issues"
},
"directories": {
"lib": "./lib/"
},
"dependencies": {},
"devDependencies": {
"nodeunit": ">= 0.6.4"
},
"main": "./lib/wrench",
"engines": {
"node": ">=0.1.97"
},
"scripts": {
"test": "nodeunit tests/runner.js"
},
"licenses": [
{
"type": "MIT",
"url": "http://github.com/ryanmcgrath/wrench-js/raw/master/LICENSE"
}
],
"readme": "wrench.js - Recursive file operations in Node.js\n----------------------------------------------------------------------------\nWhile I love Node.js, I've found myself missing some functions. Things like\nrecursively deleting/chmodding a directory (or even deep copying a directory),\nor even a basic line reader, shouldn't need to be re-invented time and time again.\n\nThat said, here's my attempt at a re-usable solution, at least until something\nmore formalized gets integrated into Node.js (*hint hint*). wrench.js is fairly simple\nto use - check out the documentation/examples below:\n\nInstallation\n-----------------------------------------------------------------------------\n\n npm install wrench\n\nUsage\n-----------------------------------------------------------------------------\n``` javascript\nvar wrench = require('wrench'),\n\tutil = require('util');\n```\n\n### Synchronous operations\n``` javascript\n// Recursively create directories, sub-trees and all.\nwrench.mkdirSyncRecursive(dir, 0777);\n\n// Recursively delete the entire sub-tree of a directory, then kill the directory\nwrench.rmdirSyncRecursive('my_directory_name', failSilently);\n\n// Recursively read directories contents.\nwrench.readdirSyncRecursive('my_directory_name');\n\n// Recursively chmod the entire sub-tree of a directory\nwrench.chmodSyncRecursive('my_directory_name', 0755);\n\n// Recursively chown the entire sub-tree of a directory\nwrench.chownSyncRecursive(\"directory\", uid, gid);\n\n// Deep-copy an existing directory\nwrench.copyDirSyncRecursive('directory_to_copy', 'location_where_copy_should_end_up');\n\n// Read lines in from a file until you hit the end\nvar f = new wrench.LineReader('x.txt');\nwhile(f.hasNextLine()) {\n\tutil.puts(x.getNextLine());\n}\n```\n\n### Asynchronous operations\n``` javascript\n// Recursively read directories contents\nvar files = [];\nwrench.readdirRecursive('my_directory_name', function(error, curFiles) {\n // curFiles is what you want\n});\n\n```\n\nQuestions, comments? Hit me up. (ryan [at] venodesigns.net | http://twitter.com/ryanmcgrath)\n",
"_id": "wrench@1.3.9",
"_from": "wrench"
}

View file

@ -0,0 +1,26 @@
#!/usr/bin/env node
// This wrapper script allows JSDoc to be installed with 'npm install -g'.
// Note that JSDoc will still run on Mozilla Rhino, NOT Node.js.
var fs = require('fs');
var os = require('os');
var path = require('path');
var spawnProc = require('child_process').spawn;
var args = process.argv.slice(2);
var script = path.normalize( path.join( path.dirname(fs.realpathSync(process.argv[1])), '..', '..',
'jsdoc' ) );
var jsdoc;
if (process.platform === 'win32') {
jsdoc = spawnProc(script + '.cmd', args, {stdio: 'inherit'});
}
else {
jsdoc = spawnProc(script, args, {stdio: 'inherit'});
}
jsdoc.on('close', function(code) {
process.exit(code);
});

View file

@ -0,0 +1,17 @@
var e = ' is not implemented for Node.js!';
exports.ls = function() {
throw new Error('fs.ls' + e);
};
exports.toDir = function() {
throw new Error('fs.toDir' + e);
};
exports.mkPath = function() {
throw new Error('fs.mkpath' + e);
};
exports.copyFileSync = function() {
throw new Error('fs.copyFileSync' + e);
};

Some files were not shown because too many files have changed in this diff Show more