mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
First code commit.
This commit is contained in:
parent
bf9c65d03d
commit
3af2c46d72
81
LICENSE.md
Normal file
81
LICENSE.md
Normal file
@ -0,0 +1,81 @@
|
||||
License
|
||||
=======
|
||||
|
||||
JSDoc Toolkit Version 3 is free software.
|
||||
|
||||
Copyright 2010 (c) Michael Mathews <micmath@gmail.com>
|
||||
|
||||
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.
|
||||
|
||||
In Addition
|
||||
===========
|
||||
|
||||
Third party software is included, used by or distributed
|
||||
with JSDoc Toolkit Version 3. Each is provided under its own license
|
||||
and/or has source available from other locations.
|
||||
|
||||
Rhino
|
||||
-----
|
||||
|
||||
Rhino is open source and licensed by Mozilla under the MPL 1.1 or
|
||||
later/GPL 2.0 or later licenses.
|
||||
|
||||
https://developer.mozilla.org/en/Rhino_License
|
||||
|
||||
You can obtain the source code for Rhino from the Mozilla web site at
|
||||
http://www.mozilla.org/rhino/download.html
|
||||
|
||||
Normal Template
|
||||
---------------
|
||||
|
||||
The source code for Normal Template is hosted at
|
||||
http://github.com/gmosx/normal-template
|
||||
|
||||
Normal Template is Copyright (c) 2010 George Moschovitis
|
||||
|
||||
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 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.
|
||||
|
||||
jsDump
|
||||
------
|
||||
|
||||
jsDump is copyright (c) 2008 Ariel Flesler, aflesler(at)gmail(dot)com
|
||||
|
||||
Licensed under BSD http://www.opensource.org/licenses/bsd-license.php
|
||||
|
||||
json2xml
|
||||
--------
|
||||
|
||||
json2xml is copyright (c) Stefan Goessner 2006
|
||||
|
||||
json2xml is licensed under Creative Commons GNU LGPL License,
|
||||
http://creativecommons.org/licenses/LGPL/2.1/
|
||||
|
||||
http://goessner.net/
|
||||
http://goessner.net/download/prj/jsonxml/
|
||||
23
README.md
23
README.md
@ -0,0 +1,23 @@
|
||||
JSDoc Toolkit Version 3
|
||||
=======================
|
||||
|
||||
This is pre-release software, under active development. It is not intended for
|
||||
general use.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
$ java -jar jsdoc.jar -d jsdoc.json myscript.js
|
||||
|
||||
See
|
||||
---
|
||||
|
||||
Project Wiki: <http://code.google.com/p/jsdoc-toolkit-3/w/list>
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
JSDoc Toolkit Version 3 is copyright 2010
|
||||
(c) Michael Mathews <micmath@gmail.com>
|
||||
|
||||
See file "LICENSE.md" in this distribution for more details about terms of use.
|
||||
6
about.json
Normal file
6
about.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"app": {
|
||||
"name": "jsdoc-toolkit-3",
|
||||
"version": "0.0.0+2010-06-06-2109"
|
||||
}
|
||||
}
|
||||
22
build.xml
Normal file
22
build.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<project name="JSDoc Toolkit" default="about">
|
||||
<property file="build/build.properties" />
|
||||
<property name="build.templates" location="build/templates" />
|
||||
<tstamp>
|
||||
<format property="NOW" pattern="yyyy-MM-dd-HHmm" locale="en,UK"/>
|
||||
</tstamp>
|
||||
|
||||
<target name="about">
|
||||
<delete file="about.json" quiet="true"/>
|
||||
<copy file="${build.templates}/about.json" tofile="about.json" >
|
||||
<filterchain>
|
||||
<replacetokens>
|
||||
<token key="app.name" value="${app.name}" />
|
||||
<token key="app.version" value="${app.version}" />
|
||||
<token key="timestamp" value="${NOW}" />
|
||||
</replacetokens>
|
||||
</filterchain>
|
||||
</copy>
|
||||
</target>
|
||||
</project>
|
||||
2
build/build.properties
Normal file
2
build/build.properties
Normal file
@ -0,0 +1,2 @@
|
||||
app.name=jsdoc-toolkit-3
|
||||
app.version=0.0.0
|
||||
6
build/templates/about.json
Normal file
6
build/templates/about.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"app": {
|
||||
"name": "@app.name@",
|
||||
"version": "@app.version@+@timestamp@"
|
||||
}
|
||||
}
|
||||
25
java/build.xml
Normal file
25
java/build.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<project default="clean-build">
|
||||
<target name="clean">
|
||||
<delete dir="build"/>
|
||||
</target>
|
||||
|
||||
<target name="compile">
|
||||
<mkdir dir="build/classes"/>
|
||||
<javac
|
||||
srcdir="src" destdir="build/classes"
|
||||
classpath="./classes/js.jar"
|
||||
/>
|
||||
</target>
|
||||
|
||||
<target name="jar">
|
||||
<mkdir dir="build/jar"/>
|
||||
<jar destfile="build/jar/jsdoc.jar" basedir="build/classes">
|
||||
<manifest>
|
||||
<attribute name="Main-Class" value="Run"/>
|
||||
<attribute name="Class-Path" value="./java/classes/js.jar"/>
|
||||
</manifest>
|
||||
</jar>
|
||||
</target>
|
||||
|
||||
<target name="clean-build" depends="clean,compile,jar"/>
|
||||
</project>
|
||||
BIN
java/classes/js.jar
Normal file
BIN
java/classes/js.jar
Normal file
Binary file not shown.
56
java/src/Run.java
Normal file
56
java/src/Run.java
Normal file
@ -0,0 +1,56 @@
|
||||
/*
|
||||
OVERVIEW:
|
||||
A bootstrap tool for running main.js. Assumes main.js is in
|
||||
the same directory as the run.jar file.
|
||||
|
||||
Its duty is simply to add the absolute path for main.js as
|
||||
the first argument to the main.js script itself. This enables
|
||||
the script to know it's own directory, useful for accessing
|
||||
resources via relative filepaths.
|
||||
|
||||
AUTHOR: Michael Mathews <micmath@gmail.com>
|
||||
LICENSE: Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
USAGE: java -jar run.jar <args>
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
public class Run {
|
||||
|
||||
// requires java.io.File, java.net.URL
|
||||
public static void main(String[] args) throws java.io.IOException {
|
||||
// get the absolute file path to the jar file containing this class
|
||||
ClassLoader loader = Run.class.getClassLoader();
|
||||
|
||||
// url is like "file:/Users/michael/WorkArea/jsdoc/run.jar!/Run.class"
|
||||
String jarUrl = loader.getResource("Run.class").getPath();
|
||||
|
||||
// parse the filepath out of the URL
|
||||
String delims = "[:!]";
|
||||
String[] tokens = jarUrl.split(delims);
|
||||
String jarPath = tokens[1];
|
||||
|
||||
// the base directory, assumed to contain main.js
|
||||
String jarDir = new File(jarPath).getParent();
|
||||
String mainPath = jarDir + "/main.js";
|
||||
|
||||
// Rhino eats the first arg (the path to the script file it is running)
|
||||
// so we add it twice: one for Rhino the next for us
|
||||
String[] mainArgs = {mainPath, mainPath};
|
||||
String[] allArgs = concat(mainArgs, args);
|
||||
|
||||
// main.js will now get arguments like:
|
||||
// ["/abs/path/to/main.js", "-a", "aval", "-b", "bval"]
|
||||
org.mozilla.javascript.tools.shell.Main.main(allArgs);
|
||||
}
|
||||
|
||||
// requires java.util
|
||||
public static String[] concat(String[] a, String[] b) {
|
||||
List<String> ab = new ArrayList<String>(a.length + b.length);
|
||||
Collections.addAll(ab, a);
|
||||
Collections.addAll(ab, b);
|
||||
return ab.toArray(new String[] {});
|
||||
}
|
||||
}
|
||||
49
main.js
Normal file
49
main.js
Normal file
@ -0,0 +1,49 @@
|
||||
//// bootstrap
|
||||
function require(id) {
|
||||
var path = require.base + id + '.js',
|
||||
source = '';
|
||||
|
||||
try {
|
||||
var file = new java.io.File(path),
|
||||
scanner = new java.util.Scanner(file).useDelimiter('\Z'),
|
||||
source = String( scanner.next() );
|
||||
}
|
||||
catch (e) { print(e); }
|
||||
|
||||
var f = new Function('require', 'exports', 'module', source),
|
||||
exports = require.cache[path] || {},
|
||||
module = { id: id, uri: path };
|
||||
|
||||
require.cache[path] = exports;
|
||||
f.call({}, require, exports, module);
|
||||
|
||||
return exports;
|
||||
}
|
||||
require.base = 'modules/';
|
||||
require.cache = {};
|
||||
|
||||
function print(msg) {
|
||||
java.lang.System.out.println(msg);
|
||||
}
|
||||
|
||||
const BASE = arguments[0]; // path to application base folder
|
||||
var args = arguments.slice(1);
|
||||
////
|
||||
|
||||
(function() {
|
||||
var jsdoc = {
|
||||
parser: require('jsdoc/parser'),
|
||||
opts: require('jsdoc/opts'),
|
||||
src: require('jsdoc/src')
|
||||
},
|
||||
opts,
|
||||
sourceFiles,
|
||||
fs = require('common/fs');
|
||||
|
||||
opts = jsdoc.opts.set(args);
|
||||
sourceFiles = jsdoc.src.getFilePaths(opts._);
|
||||
|
||||
jsdoc.parser.parseFiles(sourceFiles);
|
||||
|
||||
print( jsdoc.parser.result.asString(opts.destination) );
|
||||
})();
|
||||
144
modules/common/args.js
Normal file
144
modules/common/args.js
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
@overview Parse command line options.
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
/**
|
||||
@module common/args
|
||||
*/
|
||||
(function() {
|
||||
|
||||
/**
|
||||
Create an instance of the parser.
|
||||
@constructor
|
||||
*/
|
||||
exports.Parser = function() {
|
||||
this._options = [];
|
||||
}
|
||||
|
||||
exports.Parser.prototype._getOptionByShortName = function(name) {
|
||||
for (var i = this._options.length; i--;) {
|
||||
if (this._options[i].shortName === name) { return this._options[i]; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
exports.Parser.prototype._getOptionByLongName = function(name) {
|
||||
for (var i = this._options.length; i--;) {
|
||||
if (this._options[i].longName === name) { return this._options[i]; }
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide information about a legal option.
|
||||
* @method Parser#addOption
|
||||
* @param shortName
|
||||
* @param longName
|
||||
* @param hasValue
|
||||
* @param helpText
|
||||
* @example
|
||||
* myParser.addOption('t', 'template', true, 'The path to the template.');
|
||||
* myParser.addOption('h', 'help', false, 'Show the help message.');
|
||||
*/
|
||||
exports.Parser.prototype.addOption = function(shortName, longName, hasValue, helpText) {
|
||||
this._options.push({shortName: shortName, longName: longName, hasValue: hasValue, helpText: helpText});
|
||||
};
|
||||
|
||||
/**
|
||||
Generate a summary of all the options with corresponding help text.
|
||||
@method Parser#help
|
||||
@returns {string}
|
||||
*/
|
||||
exports.Parser.prototype.help = function() {
|
||||
var help = 'OPTIONS:\n',
|
||||
option;
|
||||
|
||||
for (var i = this._options.length; i--;) {
|
||||
option = this._options[i];
|
||||
|
||||
if (option.shortName) {
|
||||
help += '-' + option.shortName + (option.longName? ' or ' : '');
|
||||
}
|
||||
|
||||
if (option.longName) {
|
||||
help += '--' + option.longName;
|
||||
}
|
||||
|
||||
if (option.hasValue) {
|
||||
help += ' <value>';
|
||||
}
|
||||
|
||||
help += ' ' + option.helpText + '\n';
|
||||
}
|
||||
|
||||
return help;
|
||||
};
|
||||
|
||||
/**
|
||||
Get the options.
|
||||
@method Parser#parse
|
||||
@param args An array, like ['-x', 'hello']
|
||||
@param 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.
|
||||
*/
|
||||
exports.Parser.prototype.parse = function(args, defaults) {
|
||||
var result = 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,
|
||||
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;
|
||||
}
|
||||
|
||||
result[name] = value;
|
||||
}
|
||||
else {
|
||||
result._.push(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
})();
|
||||
109
modules/common/fs.js
Normal file
109
modules/common/fs.js
Normal file
@ -0,0 +1,109 @@
|
||||
/**
|
||||
@overview File system stuff.
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var slash = java.lang.System.getProperty('file.separator') || '/',
|
||||
File = Packages.java.io.File,
|
||||
defaultEncoding = java.lang.System.getProperty('file.encoding');
|
||||
|
||||
exports.read = function(path, options) {
|
||||
var options = options || {},
|
||||
encoding = options.encoding || defaultEncoding;
|
||||
|
||||
return readFile(path, encoding);
|
||||
}
|
||||
|
||||
exports.write = function(path, content, options) {
|
||||
var options = options || {},
|
||||
encoding = options.encoding || defaultEncoding,
|
||||
out;
|
||||
|
||||
out = new Packages.java.io.PrintWriter(
|
||||
new Packages.java.io.OutputStreamWriter(
|
||||
new Packages.java.io.FileOutputStream(path),
|
||||
encoding
|
||||
)
|
||||
);
|
||||
|
||||
out.write(content);
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a file exists.
|
||||
* @param {string} path The file to check.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
exports.exists = function(path) {
|
||||
var file = new File(path);
|
||||
|
||||
if (file.isDirectory()){
|
||||
return true;
|
||||
}
|
||||
if (!file.exists()){
|
||||
return false;
|
||||
}
|
||||
if (!file.canRead()){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all files in a given directory. Will not include files that
|
||||
* start with a dot.
|
||||
* @type string[]
|
||||
* @param {string} dir The starting directory to look in.
|
||||
* @param {number} [recurse=1] How many levels deep to scan.
|
||||
* @returns {string[]} An array of {string} paths to the files in the given directory.
|
||||
*/
|
||||
exports.ls = function(dir, recurse, _allFiles, _path) {
|
||||
var files,
|
||||
file;
|
||||
|
||||
if (typeof _path === 'undefined') { // initially
|
||||
_allFiles = [];
|
||||
_path = [dir];
|
||||
}
|
||||
|
||||
if (_path.length === 0) { return _allFiles; }
|
||||
if (typeof recurse === 'undefined') { recurse = 1; }
|
||||
|
||||
dir = new File(dir);
|
||||
if (!dir.directory) { return [String(dir)]; }
|
||||
files = dir.list();
|
||||
|
||||
for (var f = 0, lenf = files.length; f < lenf; f++) {
|
||||
file = String(files[f]);
|
||||
|
||||
if (file.match(/^\.[^\.\/\\]/)) { continue; } // skip dot files
|
||||
|
||||
if ((new File(_path.join(slash) + slash + file)).list()) { // it's a directory
|
||||
_path.push(file);
|
||||
|
||||
if (_path.length - 1 < recurse) {
|
||||
exports.ls(_path.join(slash), recurse, _allFiles, _path);
|
||||
}
|
||||
_path.pop();
|
||||
}
|
||||
else { // it's a file
|
||||
_allFiles.push(
|
||||
fixSlash( (_path.join(slash) + slash + file) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return _allFiles;
|
||||
}
|
||||
|
||||
// fix multiple slashes, like one//two
|
||||
function fixSlash(path) {
|
||||
return path.replace(/[\/\\]+/g, slash);
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
168
modules/flesler/jsdump.js
Normal file
168
modules/flesler/jsdump.js
Normal file
@ -0,0 +1,168 @@
|
||||
|
||||
// Ported by Tom Robinson
|
||||
|
||||
/**
|
||||
* jsDump
|
||||
* Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
||||
* Licensed under BSD (http://www.opensource.org/licenses/bsd-license.php)
|
||||
* Date: 5/15/2008
|
||||
* @projectDescription Advanced and extensible data dumping for Javascript.
|
||||
* @version 1.0.0
|
||||
* @author Ariel Flesler
|
||||
*/
|
||||
var jsDump;
|
||||
|
||||
(function(){
|
||||
function quote( str ){
|
||||
return '"' + str.toString().replace(/"/g, '\\"') + '"';
|
||||
};
|
||||
function literal( o ){
|
||||
return o + '';
|
||||
};
|
||||
function join( pre, arr, post ){
|
||||
var s = jsDump.separator(),
|
||||
base = jsDump.indent(),
|
||||
inner = jsDump.indent(1);
|
||||
if( arr.join )
|
||||
arr = arr.join( ',' + s + inner );
|
||||
if( !arr )
|
||||
return pre + post;
|
||||
return [ pre, inner + arr, base + post ].join(s);
|
||||
};
|
||||
function array( arr ){
|
||||
var i = arr.length, ret = Array(i);
|
||||
this.up();
|
||||
while( i-- )
|
||||
ret[i] = this.parse( arr[i] );
|
||||
this.down();
|
||||
return join( '[', ret, ']' );
|
||||
};
|
||||
|
||||
var reName = /^function (\w+)/;
|
||||
|
||||
jsDump = {
|
||||
parse:function( obj, type ){//type is used mostly internally, you can fix a (custom)type in advance
|
||||
var parser = this.parsers[ type || this.typeOf(obj) ];
|
||||
type = typeof parser;
|
||||
|
||||
return type == 'function' ? parser.call( this, obj ) :
|
||||
type == 'string' ? parser :
|
||||
this.parsers.error;
|
||||
},
|
||||
typeOf:function( obj ){
|
||||
var type = typeof obj,
|
||||
f = 'function';//we'll use it 3 times, save it
|
||||
return type != 'object' && type != f ? type :
|
||||
!obj ? 'null' :
|
||||
obj.exec ? 'regexp' :// some browsers (FF) consider regexps functions
|
||||
obj.getHours ? 'date' :
|
||||
obj.scrollBy ? 'window' :
|
||||
obj.nodeName == '#document' ? 'document' :
|
||||
obj.nodeName ? 'node' :
|
||||
obj.item ? 'nodelist' : // Safari reports nodelists as functions
|
||||
obj.callee ? 'arguments' :
|
||||
obj.call || obj.constructor != Array && //an array would also fall on this hack
|
||||
(obj+'').indexOf(f) != -1 ? f : //IE reports functions like alert, as objects
|
||||
'length' in obj ? 'array' :
|
||||
type;
|
||||
},
|
||||
separator:function(){
|
||||
return this.multiline ? this.HTML ? '<br />' : '\n' : this.HTML ? ' ' : ' ';
|
||||
},
|
||||
indent:function( extra ){// extra can be a number, shortcut for increasing-calling-decreasing
|
||||
if( !this.multiline )
|
||||
return '';
|
||||
var chr = this.indentChar;
|
||||
if( this.HTML )
|
||||
chr = chr.replace(/\t/g,' ').replace(/ /g,' ');
|
||||
return Array( this._depth_ + (extra||0) ).join(chr);
|
||||
},
|
||||
up:function( a ){
|
||||
this._depth_ += a || 1;
|
||||
},
|
||||
down:function( a ){
|
||||
this._depth_ -= a || 1;
|
||||
},
|
||||
setParser:function( name, parser ){
|
||||
this.parsers[name] = parser;
|
||||
},
|
||||
// The next 3 are exposed so you can use them
|
||||
quote:quote,
|
||||
literal:literal,
|
||||
join:join,
|
||||
//
|
||||
_depth_: 1,
|
||||
// This is the list of parsers, to modify them, use jsDump.setParser
|
||||
parsers:{
|
||||
window: '[Window]',
|
||||
document: '[Document]',
|
||||
error:'[ERROR]', //when no parser is found, shouldn't happen
|
||||
unknown: '[Unknown]',
|
||||
'null':'null',
|
||||
undefined:'undefined',
|
||||
'function':function( fn ){
|
||||
var ret = 'function',
|
||||
name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE
|
||||
if( name )
|
||||
ret += ' ' + name;
|
||||
ret += '(';
|
||||
|
||||
ret = [ ret, this.parse( fn, 'functionArgs' ), '){'].join('');
|
||||
return join( ret, this.parse(fn,'functionCode'), '}' );
|
||||
},
|
||||
array: array,
|
||||
nodelist: array,
|
||||
arguments: array,
|
||||
object:function( map ){
|
||||
var ret = [ ];
|
||||
this.up();
|
||||
for( var key in map )
|
||||
ret.push( this.parse(key,'key') + ': ' + this.parse(map[key]) );
|
||||
this.down();
|
||||
return join( '{', ret, '}' );
|
||||
},
|
||||
node:function( node ){
|
||||
var open = this.HTML ? '<' : '<',
|
||||
close = this.HTML ? '>' : '>';
|
||||
|
||||
var tag = node.nodeName.toLowerCase(),
|
||||
ret = open + tag;
|
||||
|
||||
for( var a in this.DOMAttrs ){
|
||||
var val = node[this.DOMAttrs[a]];
|
||||
if( val )
|
||||
ret += ' ' + a + '=' + this.parse( val, 'attribute' );
|
||||
}
|
||||
return ret + close + open + '/' + tag + close;
|
||||
},
|
||||
functionArgs:function( fn ){//function calls it internally, it's the arguments part of the function
|
||||
var l = fn.length;
|
||||
if( !l ) return '';
|
||||
|
||||
var args = Array(l);
|
||||
while( l-- )
|
||||
args[l] = String.fromCharCode(97+l);//97 is 'a'
|
||||
return ' ' + args.join(', ') + ' ';
|
||||
},
|
||||
key:quote, //object calls it internally, the key part of an item in a map
|
||||
functionCode:'[code]', //function calls it internally, it's the content of the function
|
||||
attribute:quote, //onode calls it internally, it's an html attribute value
|
||||
string:quote,
|
||||
date:quote,
|
||||
regexp:literal, //regex
|
||||
number:literal,
|
||||
'boolean':literal
|
||||
},
|
||||
DOMAttrs:{//attributes to dump from nodes, name=>realName
|
||||
id:'id',
|
||||
name:'name',
|
||||
'class':'className'
|
||||
},
|
||||
HTML:false,//if true, entities are escaped ( <, >, \t, space and \n )
|
||||
indentChar:' ',//indentation unit
|
||||
multiline:true //if true, items in a collection, are separated by a \n, else just a space.
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
exports.jsDump = jsDump;
|
||||
56
modules/goessner/json2xml.js
Normal file
56
modules/goessner/json2xml.js
Normal file
@ -0,0 +1,56 @@
|
||||
/* This work is licensed under Creative Commons GNU LGPL License.
|
||||
|
||||
License: http://creativecommons.org/licenses/LGPL/2.1/
|
||||
Version: 0.9/modified to conform to commonjs modules pattern
|
||||
Author: Stefan Goessner/2006
|
||||
Web: http://goessner.net/
|
||||
*/
|
||||
|
||||
var json2xml = (typeof exports === 'undefined')? {} : exports; // like commonjs
|
||||
|
||||
(function() {
|
||||
|
||||
json2xml.convert = function(o) {
|
||||
var toXml = function(v, name, ind) {
|
||||
var xml = "";
|
||||
if (v instanceof Array) {
|
||||
for (var i=0, n=v.length; i<n; i++)
|
||||
xml += toXml(v[i], name, ind+"");
|
||||
}
|
||||
else if (typeof(v) == "object") {
|
||||
var hasChild = false;
|
||||
xml += ind + "<" + name;
|
||||
for (var m in v) {
|
||||
if (m.charAt(0) == "@")
|
||||
xml += " " + m.substr(1) + "=\"" + v[m].toString() + "\"";
|
||||
else
|
||||
hasChild = true;
|
||||
}
|
||||
xml += hasChild ? ">\n" : "/>";
|
||||
if (hasChild) {
|
||||
for (var m in v) {
|
||||
if (m == "#text")
|
||||
xml += v[m];
|
||||
else if (m == "#cdata")
|
||||
xml += "<![CDATA[" + v[m] + "]]>";
|
||||
else if (m.charAt(0) != "@")
|
||||
xml += toXml(v[m], m, ind+"\t");
|
||||
}
|
||||
xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
xml += ind + "<" + name + ">" + v.toString().replace(/</g, '<') + "</" + name + ">\n";
|
||||
}
|
||||
return xml;
|
||||
},
|
||||
xml="";
|
||||
|
||||
for (var m in o) {
|
||||
xml += toXml(o[m], m, "");
|
||||
}
|
||||
|
||||
return xml;
|
||||
}
|
||||
|
||||
})();
|
||||
346
modules/jsdoc/doclet.js
Normal file
346
modules/jsdoc/doclet.js
Normal file
@ -0,0 +1,346 @@
|
||||
/**
|
||||
@overview
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
/**
|
||||
Functionality relating to jsdoc comments and their tags.
|
||||
@module jsdoc/doclet
|
||||
*/
|
||||
(function() {
|
||||
var name = require('jsdoc/name'),
|
||||
tag = require('jsdoc/tag');
|
||||
|
||||
/**
|
||||
Factory that builds a Doclet object.
|
||||
@param {string} commentSrc
|
||||
@param {ASTNode} node
|
||||
@param {string} sourceName
|
||||
@returns {Doclet}
|
||||
*/
|
||||
exports.makeDoclet = function(commentSrc, node, sourceName) {
|
||||
var tags = [],
|
||||
doclet;
|
||||
|
||||
commentSrc = unwrapComment(commentSrc);
|
||||
commentSrc = fixDesc(commentSrc);
|
||||
|
||||
tags = parseTags(commentSrc);
|
||||
preprocess(tags);
|
||||
|
||||
doclet = new Doclet(tags);
|
||||
|
||||
postprocess(doclet);
|
||||
|
||||
name.resolve(doclet);
|
||||
|
||||
doclet.meta = {
|
||||
line: node.getLineno(),
|
||||
file: sourceName
|
||||
};
|
||||
|
||||
return doclet
|
||||
}
|
||||
|
||||
/**
|
||||
@private
|
||||
@constructor Doclet
|
||||
@param {Array.<Object>} tags
|
||||
*/
|
||||
function Doclet(tags) {
|
||||
/**
|
||||
An array of Objects representing tags.
|
||||
@type Array.<Tag>
|
||||
@property Doclet#tags
|
||||
*/
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
/**
|
||||
Set the name of the Doclet.
|
||||
@method Doclet#setName
|
||||
@param {string name
|
||||
*/
|
||||
Doclet.prototype.setName = function(nameToSet) {
|
||||
this.tagText('name', nameToSet);
|
||||
|
||||
nameToSet = name.resolve(this);
|
||||
}
|
||||
|
||||
/**
|
||||
Return the text of the first tag with the given name.
|
||||
@method Doclet#tagText
|
||||
@param {String} tagName
|
||||
@returns {String} The text of the found tag.
|
||||
*/
|
||||
Doclet.prototype.tagText = function(tagName, text) {
|
||||
var i = this.tags.length;
|
||||
while(i--) {
|
||||
if (this.tags[i].name === tagName) {
|
||||
if (text) { this.tags[i].text = text; }
|
||||
return this.tags[i].text;
|
||||
}
|
||||
}
|
||||
|
||||
// still here?
|
||||
if (text) {
|
||||
this.tags.push( tag.fromTagText(tagName + ' ' + text) );
|
||||
return text;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
Does a tag with the given name exist in this doclet?
|
||||
@method Doclet#hasTag
|
||||
@param {String} tagName
|
||||
@returns {boolean} True if the tag is found, false otherwise.
|
||||
*/
|
||||
Doclet.prototype.hasTag = function(tagName) {
|
||||
var i = this.tags.length;
|
||||
while(i--) {
|
||||
if (this.tags[i].name === tagName) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// safe to export to JSON
|
||||
var exportTags = ['name', 'path', 'kind', 'desc', 'type', 'param', 'returns', 'exports', 'requires', 'memberof', 'access', 'attribute'];
|
||||
|
||||
/**
|
||||
Get a JSON-compatible object representing this Doclet.
|
||||
@method Doclet#toObject
|
||||
@returns {Object}
|
||||
*/
|
||||
Doclet.prototype.toObject = function() {
|
||||
var tag, tagName, tagValue,
|
||||
o = {};
|
||||
|
||||
for (var i = 0, leni = this.tags.length; i < leni; i++) {
|
||||
if (exportTags.indexOf(this.tags[i].name) === -1) { continue; }
|
||||
|
||||
tag = this.tags[i];
|
||||
tagName = tag.name;
|
||||
tagValue = {};
|
||||
|
||||
if (tag.type) {
|
||||
tagValue.type = tag.type;
|
||||
// not a long tag
|
||||
if (!tag.pname && tag.text) { tagValue.text = tag.text; }
|
||||
}
|
||||
// a long tag
|
||||
if (tag.pname) { tagValue.name = tag.pname; }
|
||||
if (tag.pdesc) { tagValue.desc = tag.pdesc; }
|
||||
|
||||
// tag value is not an object, it's just a simple string
|
||||
if (!tag.pname && !tag.type) { tagValue = tag.text; }
|
||||
|
||||
if (!o[tagName]) { o[tagName] = tagValue; }
|
||||
else if (o[tagName].push) { o[tagName].push(tagValue); }
|
||||
else {
|
||||
o[tagName] = [ o[tagName] ];
|
||||
o[tagName].push(tagValue);
|
||||
}
|
||||
|
||||
o.meta = this.meta;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove JsDoc comment slash-stars. Trims white space.
|
||||
@private
|
||||
@function unwrapComment
|
||||
@param {string} commentSrc
|
||||
@return {string} Coment wit stars and slashes removed.
|
||||
*/
|
||||
function unwrapComment(commentSrc) {
|
||||
if (!commentSrc) { return ''; }
|
||||
|
||||
// TODO keep leading white space for @examples
|
||||
return commentSrc ? commentSrc.replace(/(^\/\*\*+\s*|\s*\**\*\/$)/g, "").replace(/^\s*\* ?/gm, "") : "";
|
||||
}
|
||||
|
||||
/**
|
||||
Add a @desc tag if none exists on untagged text at start of comment.
|
||||
@private
|
||||
@function fixDesc
|
||||
@param {string} commentSrc
|
||||
@return {string} With needed @desc tag added.
|
||||
*/
|
||||
function fixDesc(commentSrc) {
|
||||
if (!/^\s*@/.test(commentSrc)) {
|
||||
commentSrc = '@desc ' + commentSrc;
|
||||
}
|
||||
return commentSrc;
|
||||
}
|
||||
|
||||
/**
|
||||
Given the source of a jsdoc comment, finds the tags.
|
||||
@private
|
||||
@function parseTags
|
||||
@param {string} commentSrc Unwrapped.
|
||||
@returns Array.<Object>
|
||||
*/
|
||||
function parseTags(commentSrc) {
|
||||
var tags = [];
|
||||
|
||||
// split out the basic tags
|
||||
commentSrc
|
||||
.split(/(^|[\r\n])\s*@/)
|
||||
.filter( function($){ return $.match(/\S/); } )
|
||||
.forEach(function($) {
|
||||
var newTag = tag.fromTagText($);
|
||||
|
||||
if (newTag.name) {
|
||||
tags.push(newTag);
|
||||
}
|
||||
});
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
// other tags that can provide the memberof
|
||||
var memberofs = {methodof: 'method', propertyof: 'property', eventof: 'event'};
|
||||
// other tags that can provide the symbol name
|
||||
var nameables = ['constructor', 'module', 'event', 'namespace', 'method', 'property', 'function', 'variable', 'enum'];
|
||||
|
||||
/**
|
||||
Expand some shortcut tags. Modifies the tags argument in-place.
|
||||
@private
|
||||
@method preprocess
|
||||
@param {Array.<Object>} tags
|
||||
@returns undefined
|
||||
*/
|
||||
function preprocess(tags) {
|
||||
var name = '',
|
||||
taggedName = '',
|
||||
kind = '',
|
||||
taggedKind = '',
|
||||
memberof = '',
|
||||
taggedMemberof = '';
|
||||
|
||||
var i = tags.length;
|
||||
while(i--) {
|
||||
|
||||
if (tags[i].name === 'private') {
|
||||
tags[tags.length] = tag.fromTagText('access private');
|
||||
}
|
||||
else if (tags[i].name === 'protected') {
|
||||
tags[tags.length] = tag.fromTagText('access protected');
|
||||
}
|
||||
else if (tags[i].name === 'const') {
|
||||
tags[tags.length] = tag.fromTagText('attribute constant');
|
||||
}
|
||||
else if (tags[i].name === 'readonly') {
|
||||
tags[tags.length] = tag.fromTagText('attribute readonly');
|
||||
}
|
||||
else if (tags[i].name === 'name') {
|
||||
if (name && name !== tags[i].text) { tooManyNames(name, tags[i].text); }
|
||||
taggedName = name = tags[i].text;
|
||||
}
|
||||
else if (tags[i].name === 'kind') {
|
||||
if (kind && kind !== tags[i].text) { tooManyKinds(kind, tags[i].text); }
|
||||
taggedKind = kind = tags[i].text;
|
||||
}
|
||||
else if (tags[i].name === 'memberof') {
|
||||
if (memberof) { tooManyTags('memberof'); }
|
||||
taggedMemberof = memberof = tags[i].text;
|
||||
}
|
||||
|
||||
if ( nameables.indexOf(tags[i].name) > -1 ) {
|
||||
if (tags[i].text) {
|
||||
if (name && name !== tags[i].text) { tooManyNames(name, tags[i].text); }
|
||||
name = tags[i].text;
|
||||
}
|
||||
|
||||
if (tags[i].type) {
|
||||
tags[tags.length] = tag.fromTagText('type ' + tags[i].type);
|
||||
}
|
||||
|
||||
if (kind && kind !== tags[i].name) { tooManyKinds(kind, tags[i].name); }
|
||||
kind = tags[i].name;
|
||||
}
|
||||
|
||||
if ( memberofs.hasOwnProperty(tags[i].name) ) {
|
||||
if (tags[i].text) {
|
||||
if (memberof) { tooManyTags(tags[i].name); }
|
||||
memberof = tags[i].text;
|
||||
}
|
||||
|
||||
if (kind && kind !== memberofs[tags[i].name]) { tooManyKinds(kind, memberofs[tags[i].name]); }
|
||||
kind = memberofs[tags[i].name];
|
||||
}
|
||||
}
|
||||
|
||||
if (name && !taggedName) {
|
||||
tags[tags.length] = tag.fromTagText('name ' + name);
|
||||
}
|
||||
|
||||
if (kind && !taggedKind) {
|
||||
tags[tags.length] = tag.fromTagText('kind ' + kind);
|
||||
}
|
||||
|
||||
if (memberof && !taggedMemberof) {
|
||||
tags[tags.length] = tag.fromTagText('memberof ' + memberof);
|
||||
}
|
||||
}
|
||||
|
||||
function postprocess(doclet) {
|
||||
if ( doclet.hasTag('class') && !doclet.hasTag('constructor') ) {
|
||||
doclet.tags[doclet.tags.length] = tag.fromTagText('kind constructor');
|
||||
}
|
||||
|
||||
if ( doclet.hasTag('enum')) {
|
||||
if (!doclet.hasTag('type')) {
|
||||
doclet.tags[doclet.tags.length] = tag.fromTagText('type number');
|
||||
}
|
||||
|
||||
if (!doclet.hasTag('readonly') && !doclet.hasTag('const')) {
|
||||
doclet.tags[doclet.tags.length] = tag.fromTagText('attribute constant');
|
||||
}
|
||||
}
|
||||
|
||||
if ( doclet.hasTag('const')) {
|
||||
if (!doclet.hasTag('kind')) {
|
||||
doclet.tags[doclet.tags.length] = tag.fromTagText('kind property');
|
||||
}
|
||||
|
||||
if (!doclet.hasTag('readonly') && !doclet.hasTag('const')) {
|
||||
doclet.tags[doclet.tags.length] = tag.fromTagText('attribute constant');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Throw error when two conflicting names are defined in the same doc.
|
||||
@private
|
||||
@function tooManyNames
|
||||
*/
|
||||
function tooManyNames(name1, name2) {
|
||||
throw new Error('Conflicting names in documentation: '+name1+', '+name2);
|
||||
}
|
||||
|
||||
/**
|
||||
Throw error when two conflicting kinds are defined in the same doc.
|
||||
@private
|
||||
@function tooManyKinds
|
||||
*/
|
||||
function tooManyKinds(kind1, kind2) {
|
||||
throw new Error('Conflicting kinds in documentation: '+kind1+', '+kind2);
|
||||
}
|
||||
|
||||
/**
|
||||
Throw error when conflicting tags are found.
|
||||
@private
|
||||
@function tooManyTags
|
||||
*/
|
||||
function tooManyTags(tagName) {
|
||||
throw new Error('Symbol has too many tags of type: @'+tagName);
|
||||
}
|
||||
})();
|
||||
61
modules/jsdoc/docset.js
Normal file
61
modules/jsdoc/docset.js
Normal file
@ -0,0 +1,61 @@
|
||||
(function() {
|
||||
var dumper = require('flesler/jsdump'),
|
||||
xml = require('goessner/json2xml'),
|
||||
doclets = exports.doclets = [];
|
||||
|
||||
doclets.getDocsByName = function getDocsByName(docName) {
|
||||
var foundDocs = [],
|
||||
i = doclets.length;
|
||||
|
||||
while (i--) {
|
||||
if (doclets[i].tagText('path') === docName) {
|
||||
foundDocs.unshift( doclets[i] );
|
||||
}
|
||||
}
|
||||
|
||||
return foundDocs;
|
||||
}
|
||||
|
||||
doclets.toObject = function toObject() {
|
||||
var docsObjects = [],
|
||||
i = doclets.length;
|
||||
|
||||
while (i--) {
|
||||
docsObjects.unshift( doclets[i].toObject() );
|
||||
}
|
||||
|
||||
return { doc: docsObjects };
|
||||
}
|
||||
|
||||
doclets.asString = function asString(destinationName) {
|
||||
if ( /xml$/i.test(destinationName) ) {
|
||||
return doclets.toXML();
|
||||
}
|
||||
else { // default
|
||||
return doclets.toJSON();
|
||||
}
|
||||
}
|
||||
|
||||
doclets.toJSON = function toJSON() {
|
||||
return dumper.jsDump.parse( doclets.toObject() );
|
||||
}
|
||||
|
||||
doclets.toXML = function toXML() {
|
||||
var o = doclets.toObject();
|
||||
|
||||
// make `id` an attribute of the doc tag
|
||||
for (var i = 0, leni = o.doc.length; i < leni; i++) {
|
||||
for (var p in o.doc[i]) {
|
||||
if (p === 'id') {
|
||||
o.doc[i]['@id'] = o.doc[i].id;
|
||||
delete o.doc[i].id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return xml.convert(
|
||||
{ jsdoc: o }
|
||||
);
|
||||
}
|
||||
|
||||
})();
|
||||
163
modules/jsdoc/name.js
Normal file
163
modules/jsdoc/name.js
Normal file
@ -0,0 +1,163 @@
|
||||
/**
|
||||
@overview
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
/**
|
||||
Functionality relating to symbol name manipulation.
|
||||
@module jsdoc/name
|
||||
*/
|
||||
(function() {
|
||||
var Token = Packages.org.mozilla.javascript.Token,
|
||||
currentModule = '';
|
||||
|
||||
exports.setCurrentModule = function(moduleName) {
|
||||
currentModule = moduleName;
|
||||
}
|
||||
|
||||
/**
|
||||
@method resolve
|
||||
@param {Doclet} doclet
|
||||
*/
|
||||
exports.resolve = function(doclet) {
|
||||
var kind = doclet.tagText('kind'),
|
||||
name = doclet.tagText('name'),
|
||||
memberof = doclet.tagText('memberof'),
|
||||
path,
|
||||
shortname,
|
||||
prefix,
|
||||
supportedNamespaces = ['module', 'event'];
|
||||
|
||||
// only keep the first word of the tagged name
|
||||
name = doclet.tagText('name', name.split(/\s+/g)[0]);
|
||||
|
||||
if (currentModule) {
|
||||
name = name.replace(/^exports\.(?=.+$)/, currentModule + '.');
|
||||
}
|
||||
|
||||
name = name.replace(/\.prototype\.?/g, '#');
|
||||
|
||||
// if name doesn't already have a doc-namespace and needs one
|
||||
if (!/^[a-z_$-]+:\S+/i.test(name) && supportedNamespaces.indexOf(kind) > -1) {
|
||||
// add doc-namespace to path
|
||||
name = kind + '(' + name + ')';
|
||||
}
|
||||
|
||||
path = shortname = name;
|
||||
|
||||
doclet.tagText('name', shortname);
|
||||
|
||||
if (memberof) {
|
||||
if (name.indexOf(memberof) === 0) {
|
||||
path = name;
|
||||
[prefix, shortname] = exports.shorten(name);
|
||||
doclet.tagText('name', shortname);
|
||||
}
|
||||
}
|
||||
else {
|
||||
[prefix, shortname] = exports.shorten(name);
|
||||
doclet.tagText('memberof', prefix);
|
||||
doclet.tagText('name', shortname);
|
||||
}
|
||||
|
||||
// overlapping member of, like @name foo.Bar, @memberof foo
|
||||
if (memberof && name.indexOf(memberof) !== 0) {
|
||||
path = memberof + (/#$/.test(memberof)? '' : '.') + name;
|
||||
}
|
||||
|
||||
if (path) doclet.tagText('path', path);
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
exports.shorten = function(path) {
|
||||
var shortname = path.split(/([#.-])/).pop(),
|
||||
splitOn = RegExp.$1,
|
||||
splitAt = path.lastIndexOf(splitOn),
|
||||
prefix = (splitAt === -1)? '' : path.slice(0, splitAt);
|
||||
|
||||
if (splitOn === '#') { prefix = prefix + splitOn; }
|
||||
return [prefix, shortname];
|
||||
}
|
||||
|
||||
/**
|
||||
Resolve how to document the `this.` portion of a symbol name.
|
||||
*/
|
||||
exports.resolveThis = function(name, node, doclet) {
|
||||
var enclosing,
|
||||
enclosingDoc,
|
||||
memberof = (doclet.tagText('memberof') || '').replace(/\.prototype\.?/g, '#');
|
||||
|
||||
if (node.parent && node.parent.type === Token.OBJECTLIT) {
|
||||
if (enclosing = node.parent) {
|
||||
enclosingDoc = exports.docFromNode(enclosing) || {};
|
||||
memberof = (enclosingDoc.tagText('path') || '').replace(/\.prototype\.?/g, '#');
|
||||
|
||||
if (!memberof) {
|
||||
memberof = enclosingDoc.path;
|
||||
memberof = memberof || '[[anonymousObject]]';
|
||||
}
|
||||
|
||||
if (memberof) {
|
||||
name = memberof + (memberof[memberof.length-1] === '#'?'':'.') + name;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (name.indexOf('this.') === 0) { // assume `this` refers to innermost constructor
|
||||
if (!memberof || memberof === 'this') {
|
||||
enclosing = node.getEnclosingFunction()
|
||||
|
||||
enclosingDoc = exports.docFromNode(enclosing);
|
||||
memberof = enclosingDoc? enclosingDoc.tagText('path') : '';
|
||||
|
||||
if (enclosing && !memberof) {
|
||||
memberof = ''; //[[anonymousFunction]]
|
||||
name = name.slice(5); // remove `this.`
|
||||
}
|
||||
else if (!enclosing) {
|
||||
memberof = ''; // [[globalObject]]
|
||||
}
|
||||
|
||||
if (memberof || !enclosing) {
|
||||
// `this` refers to nearest instance in the name path
|
||||
if (enclosingDoc && enclosingDoc.tagText('kind') !== 'constructor') {
|
||||
var parts = memberof.split('#');
|
||||
parts.pop();
|
||||
memberof = parts.join('#');
|
||||
}
|
||||
|
||||
name = memberof + (memberof? '#':'') + name.slice(5); // replace `this.` with memberof
|
||||
}
|
||||
}
|
||||
else {
|
||||
name = name.slice(5);
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
Keep track of anonymous functions that have been assigned to documented symbols.
|
||||
@private
|
||||
@method docFromNode
|
||||
@param {org.mozilla.javascript.ast.AstNode} node
|
||||
@return {Object} The associated doclet.
|
||||
*/
|
||||
exports.docFromNode = function(node) {
|
||||
var i = exports.refs.length;
|
||||
while (i--) {
|
||||
if (exports.refs[i][0] === node) {
|
||||
return exports.refs[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
// tuples, like [ [noderef, doclet], [noderef, doclet] ]
|
||||
exports.refs = [];
|
||||
|
||||
function getTypeName(node) {
|
||||
return node ? ''+org.mozilla.javascript.Token.typeToName(node.getType()) : '' ;
|
||||
}
|
||||
})();
|
||||
66
modules/jsdoc/opts.js
Normal file
66
modules/jsdoc/opts.js
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
@overview Get or set options for this app.
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
/**
|
||||
@module jsdoc/opts
|
||||
@requires common/args
|
||||
*/
|
||||
(function() {
|
||||
var args = args || require('common/args');
|
||||
|
||||
var argsParser = new args.Parser(),
|
||||
ourOptions,
|
||||
defaults = {
|
||||
template: 'default',
|
||||
destination: 'jsdoc.xml'
|
||||
};
|
||||
|
||||
argsParser.addOption('t', 'template', true, 'The name of the template to use.');
|
||||
argsParser.addOption('T', 'test', false, 'Run unit tests and quit.');
|
||||
argsParser.addOption('d', 'destination', true, 'The path to output folder.');
|
||||
argsParser.addOption('h', 'help', false, 'Print help message and quit.');
|
||||
argsParser.addOption('V', 'validate', false, 'Validate the results produced by parsing the source code.');
|
||||
|
||||
/**
|
||||
Set the options for this app.
|
||||
@method set
|
||||
@throws {Error} Illegal arguments will throw errors.
|
||||
@param {string|String[]} args The command line arguments for this app.
|
||||
*/
|
||||
exports.set = function(args) {
|
||||
args = args || [];
|
||||
|
||||
if (typeof args === 'string' || args.constructor === String) {
|
||||
args = (''+args).split(/\s+/g);
|
||||
}
|
||||
|
||||
ourOptions = argsParser.parse(args, defaults);
|
||||
|
||||
return ourOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
Display help message for options.
|
||||
@method help
|
||||
*/
|
||||
exports.help = function() { return argsParser.help(); }
|
||||
|
||||
/**
|
||||
Get a single option or all the options for this app.
|
||||
@method get
|
||||
@param {String} [name] The name of the option.
|
||||
@return {String|Object} Either the value associated with the given name,
|
||||
or a collection of key/values representing all the options.
|
||||
*/
|
||||
exports.get = function(name) {
|
||||
if (typeof name === 'undefined') {
|
||||
return ourOptions;
|
||||
}
|
||||
else {
|
||||
return ourOptions[name];
|
||||
}
|
||||
}
|
||||
})();
|
||||
203
modules/jsdoc/parser.js
Normal file
203
modules/jsdoc/parser.js
Normal file
@ -0,0 +1,203 @@
|
||||
(function() {
|
||||
var name = require('jsdoc/name'),
|
||||
doclet = require('jsdoc/doclet'),
|
||||
doclets = require('jsdoc/docset').doclets,
|
||||
Token = Packages.org.mozilla.javascript.Token;
|
||||
|
||||
exports.result = doclets;
|
||||
|
||||
/**
|
||||
*/
|
||||
function visitNode(node) {
|
||||
var commentSrc = '',
|
||||
thisDoclet = null,
|
||||
thisDocletName = '';
|
||||
|
||||
// look for all comments that have names provided
|
||||
if (node.type === Token.SCRIPT && node.comments) {
|
||||
for each (var comment in node.comments.toArray()) {
|
||||
if (comment.commentType === Token.CommentType.JSDOC) {
|
||||
commentSrc = '' + comment.toSource();
|
||||
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, node, currentSourceName);
|
||||
if ( thisDoclet.hasTag('name') ) {
|
||||
doclets.push(thisDoclet);
|
||||
if (thisDoclet.tagText('kind') === 'module') {
|
||||
name.setCurrentModule( thisDoclet.tagText('path') );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// like function foo() {}
|
||||
if (node.type == Token.FUNCTION) {
|
||||
if (node.jsDoc) {
|
||||
commentSrc = '' + node.jsDoc;
|
||||
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, node, currentSourceName);
|
||||
thisDocletName = thisDoclet.tagText('path');
|
||||
|
||||
if (!thisDocletName) {
|
||||
thisDoclet.setName('' + node.name);
|
||||
doclets.push(thisDoclet);
|
||||
}
|
||||
|
||||
name.refs.push([node, thisDoclet]);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// like foo = function(){} or foo: function(){}
|
||||
if (node.type === Token.ASSIGN || node.type === Token.COLON) {
|
||||
var nodeName = nodeToString(node.left),
|
||||
nodeKind = '';
|
||||
commentSrc = node.jsDoc || node.left.jsDoc;
|
||||
|
||||
if (commentSrc) {
|
||||
commentSrc = '' + commentSrc;
|
||||
|
||||
thisDoclet = doclet.makeDoclet(commentSrc, node, currentSourceName);
|
||||
thisDocletName = thisDoclet.tagText('name');
|
||||
nodeKind = thisDoclet.tagText('kind');
|
||||
|
||||
if (!thisDocletName) {
|
||||
nodeName = name.resolveThis( nodeName, node, thisDoclet );
|
||||
thisDoclet.setName(nodeName);
|
||||
doclets.push(thisDoclet);
|
||||
}
|
||||
name.refs.push([node.right, thisDoclet]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// like var foo = function(){} or var bar = {}
|
||||
if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
|
||||
var counter = 0,
|
||||
nodeKind;
|
||||
|
||||
if (node.variables) for each (var n in node.variables.toArray()) {
|
||||
|
||||
if (n.target.type === Token.NAME && n.initializer) {
|
||||
commentSrc = (counter++ === 0 && !n.jsDoc)? node.jsDoc : n.jsDoc;
|
||||
if (commentSrc) {
|
||||
thisDoclet = doclet.makeDoclet('' + commentSrc, node, currentSourceName);
|
||||
thisDocletName = thisDoclet.tagText('path');
|
||||
nodeKind = thisDoclet.tagText('kind');
|
||||
|
||||
if ( !thisDocletName ) {
|
||||
thisDocletName = n.target.string;
|
||||
thisDoclet.setName(thisDocletName);
|
||||
doclets.push(thisDoclet);
|
||||
}
|
||||
}
|
||||
}
|
||||
name.refs.push([n.initializer, thisDoclet]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
currentSourceName = '';
|
||||
|
||||
/**
|
||||
*/
|
||||
exports.parseSource = function(source, sourceName) {
|
||||
currentSourceName = sourceName;
|
||||
var ast = getParser().parse(source, sourceName, 1);
|
||||
|
||||
ast.visit(
|
||||
new Packages.org.mozilla.javascript.ast.NodeVisitor({
|
||||
visit: visitNode
|
||||
})
|
||||
);
|
||||
|
||||
currentSourceName = '';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
exports.parseFiles = function(sourceFiles) {
|
||||
var ast = getParser(),
|
||||
fs = require('common/fs'),
|
||||
source = '';
|
||||
|
||||
for (i = 0, leni = sourceFiles.length; i < leni; i++) {
|
||||
try {
|
||||
source = fs.read(sourceFiles[i]);
|
||||
}
|
||||
catch(e) {
|
||||
print('ERROR: ' + e);
|
||||
continue;
|
||||
}
|
||||
|
||||
exports.parseSource(source, sourceFiles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@private
|
||||
@function getParser
|
||||
*/
|
||||
function getParser() {
|
||||
var cx = Packages.org.mozilla.javascript.Context.getCurrentContext();
|
||||
|
||||
var ce = new Packages.org.mozilla.javascript.CompilerEnvirons();
|
||||
ce.setRecordingComments(true);
|
||||
ce.setRecordingLocalJsDocComments(true);
|
||||
ce.initFromContext(cx);
|
||||
return new Packages.org.mozilla.javascript.Parser(ce, ce.getErrorReporter());
|
||||
}
|
||||
|
||||
/**
|
||||
@private
|
||||
@function nodeToString
|
||||
@param {org.mozilla.javascript.ast.AstNode} node
|
||||
@returns {string}
|
||||
*/
|
||||
// credit: ringojs ninjas
|
||||
function nodeToString(node) {
|
||||
var str;
|
||||
|
||||
if (node.type === Token.GETPROP) {
|
||||
str = [nodeToString(node.target), node.property.string].join('.');
|
||||
}
|
||||
else if (node.type === Token.NAME) {
|
||||
str = node.string;
|
||||
}
|
||||
else if (node.type === Token.STRING) {
|
||||
str = node.value;
|
||||
}
|
||||
else if (node.type === Token.THIS) {
|
||||
str = 'this';
|
||||
}
|
||||
else if (node.type === Token.GETELEM) {
|
||||
str = node.toSource(); // like: Foo['Bar']
|
||||
}
|
||||
else {
|
||||
str = getTypeName(node);
|
||||
}
|
||||
|
||||
return '' + str;
|
||||
};
|
||||
|
||||
/**
|
||||
@private
|
||||
@function getTypeName
|
||||
@param {org.mozilla.javascript.ast.AstNode} node
|
||||
@returns {string}
|
||||
*/
|
||||
// credit: ringojs ninjas
|
||||
function getTypeName(node) {
|
||||
return node ? ''+Packages.org.mozilla.javascript.Token.typeToName(node.getType()) : '' ;
|
||||
}
|
||||
|
||||
})();
|
||||
42
modules/jsdoc/src.js
Normal file
42
modules/jsdoc/src.js
Normal file
@ -0,0 +1,42 @@
|
||||
/**
|
||||
@overview Find source files to be parsed for docs.
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
/**
|
||||
@module jsdoc/src
|
||||
@namespace jsdoc.src
|
||||
@requires common/fs
|
||||
*/
|
||||
var jsdoc = jsdoc || {};
|
||||
jsdoc.src = (typeof exports === 'undefined')? {} : exports; // like commonjs
|
||||
|
||||
(function() {
|
||||
var fs = fs || require('common/fs');
|
||||
|
||||
/**
|
||||
Recursively searches the given searchPaths for js files.
|
||||
@method getFilePaths
|
||||
@param {Array.<string>} searchPaths
|
||||
@param {number} [depth=1]
|
||||
*/
|
||||
jsdoc.src.getFilePaths = function(searchPaths, depth) {
|
||||
var filePaths = [];
|
||||
|
||||
searchPaths = searchPaths || [];
|
||||
depth = depth || 1;
|
||||
|
||||
searchPaths.forEach(function($) {
|
||||
filePaths = filePaths.concat(fs.ls($, depth));
|
||||
});
|
||||
|
||||
// TODO: allow user-defined filtering of files
|
||||
filePaths = filePaths.filter(function($) {
|
||||
return /.+\.js(doc)?$/i.test($);
|
||||
});
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
})();
|
||||
133
modules/jsdoc/tag.js
Normal file
133
modules/jsdoc/tag.js
Normal file
@ -0,0 +1,133 @@
|
||||
/**
|
||||
@overview
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.markdown' in this project.
|
||||
*/
|
||||
|
||||
/**
|
||||
Create tag objects.
|
||||
@module jsdoc/tag
|
||||
*/
|
||||
(function() {
|
||||
|
||||
exports.fromCommentText = function(commentText) {
|
||||
var tag,
|
||||
tags = [];
|
||||
|
||||
// split out the basic tags
|
||||
commentText
|
||||
.split(/(^|[\r\n])\s*@/)
|
||||
.filter( function($){ return $.match(/\S/); } )
|
||||
.forEach(function($) {
|
||||
tag = fromTagText($);
|
||||
|
||||
if (tag.name) {
|
||||
tags.push(tag);
|
||||
}
|
||||
else {
|
||||
// TODO: warn about tag with no name?
|
||||
}
|
||||
});
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
exports.fromTagText = function(tagText) {
|
||||
return new Tag(tagText);
|
||||
}
|
||||
|
||||
/**
|
||||
@private
|
||||
@constructor Tag
|
||||
@param {string} tagText
|
||||
*/
|
||||
function Tag(tagText) {
|
||||
this.name = '';
|
||||
this.type = '';
|
||||
this.text = '';
|
||||
this.pname = '';
|
||||
this.pdesc = '';
|
||||
|
||||
// tagText is like: "tagname tag text"
|
||||
var bits = tagText.match(/^(\S+)(?:\s+([\s\S]*))?$/);
|
||||
|
||||
if (bits) {
|
||||
|
||||
this.name = (bits[1] || '').toLowerCase();
|
||||
this.text = bits[2] || '';
|
||||
|
||||
var typeText = splitType(this.text);
|
||||
|
||||
// @type tags are the only tag that is not allowed to have a {type}!
|
||||
if (this.name === 'type') {
|
||||
typeText.text = typeText.text || typeText.type;
|
||||
delete typeText.type;
|
||||
}
|
||||
|
||||
this.type = typeText.type;
|
||||
|
||||
this.text = trim(typeText.text);
|
||||
|
||||
if (this.name === 'param') { // is a parameter w/ long format
|
||||
var [pname, pdesc] = splitPname(this.text);
|
||||
this.pname = pname;
|
||||
this.pdesc = pdesc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Split the parameter name and parameter desc from the tag text.
|
||||
@private
|
||||
@method splitPname
|
||||
@param {string} tagText
|
||||
@returns Array.<string> The pname and the pdesc.
|
||||
*/
|
||||
function splitPname(tagText) {
|
||||
tagText.match(/^(\S+)(\s+(\S.*))?$/);
|
||||
|
||||
return [RegExp.$1, RegExp.$3];
|
||||
}
|
||||
|
||||
/**
|
||||
Split the tag type and remaining tag text from the tag text.
|
||||
@private
|
||||
@method splitType
|
||||
@param {string} tagText
|
||||
@returns Object Like {type: tagType, text: tagText}
|
||||
*/
|
||||
function splitType(tagText) {
|
||||
var type = '',
|
||||
text = tagText,
|
||||
count = 0;
|
||||
|
||||
// I reserve the right to use {@whatever ...} for something unrelated to type
|
||||
if (tagText[0] === '{' && tagText[1] !== '@') {
|
||||
count++;
|
||||
|
||||
for (var i = 1, leni = tagText.length; i < leni; i++) {
|
||||
if (tagText[i] === '{') { count++; }
|
||||
if (tagText[i] === '}') { count--; }
|
||||
if (count === 0) {
|
||||
type = trim(tagText.slice(1, i));
|
||||
text = trim(tagText.slice(i+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { type: type, text: text };
|
||||
}
|
||||
|
||||
/**
|
||||
Remove leading and trailing whitespace.
|
||||
@private
|
||||
@method trim
|
||||
@param {string} text
|
||||
@returns {string}
|
||||
*/
|
||||
function trim(text) {
|
||||
return text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
|
||||
})();
|
||||
Loading…
x
Reference in New Issue
Block a user