mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
Merge pull request #36 from tschaub/require
Use Rhino's require implementation.
This commit is contained in:
commit
a9574d413b
2
jsdoc
2
jsdoc
@ -3,6 +3,6 @@
|
||||
# rhino discards the path to the current script file, so we must add it back
|
||||
PWD=`pwd`
|
||||
BASEDIR=`dirname $0`
|
||||
java -classpath ${BASEDIR}/lib/js.jar org.mozilla.javascript.tools.shell.Main ${BASEDIR}/jsdoc.js --dirname=${PWD}/${BASEDIR} $@
|
||||
java -classpath ${BASEDIR}/lib/js.jar org.mozilla.javascript.tools.shell.Main -modules ${BASEDIR}/node_modules -modules ${BASEDIR}/rhino_modules ${BASEDIR}/jsdoc.js --dirname=${PWD}/${BASEDIR} $@
|
||||
|
||||
#java -classpath ${BASEDIR}/lib/js.jar org.mozilla.javascript.tools.debugger.Main -debug ${BASEDIR}/jsdoc.js --dirname=${PWD}/${BASEDIR} $@
|
||||
1
jsdoc.js
1
jsdoc.js
@ -30,7 +30,6 @@ for (var i = 0; i < arguments.length; i++) {
|
||||
}
|
||||
}
|
||||
|
||||
load(__dirname + '/lib/require.js');
|
||||
load(__dirname + '/lib/rhino-shim.js');
|
||||
|
||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||
|
||||
222
lib/require.js
222
lib/require.js
@ -1,222 +0,0 @@
|
||||
/*
|
||||
Rhino-Require is Public Domain
|
||||
<http://en.wikipedia.org/wiki/Public_Domain>
|
||||
|
||||
The author or authors of this code dedicate any and all copyright interest
|
||||
in this code to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and successors. We
|
||||
intend this dedication to be an overt act of relinquishment in perpetuity of
|
||||
all present and future rights to this code under copyright law.
|
||||
*/
|
||||
|
||||
(function(global) {
|
||||
|
||||
var require = global.require = function(id) {
|
||||
if (typeof arguments[0] !== 'string') throw 'USAGE: require(moduleId)';
|
||||
|
||||
var moduleContent = '',
|
||||
moduleUrl;
|
||||
|
||||
moduleUrl = require.resolve(id);
|
||||
moduleContent = '';
|
||||
|
||||
var file = new java.io.File(moduleUrl);
|
||||
try {
|
||||
var scanner = new java.util.Scanner(file).useDelimiter("\\Z");
|
||||
moduleContent = String( scanner.next() );
|
||||
}
|
||||
catch(e) {
|
||||
throw 'Unable to read file at: '+moduleUrl+', '+e;
|
||||
}
|
||||
|
||||
if (moduleContent) {
|
||||
try {
|
||||
var f = new Function('require', 'exports', 'module', '__dirname', moduleContent),
|
||||
exports = require.cache[moduleUrl] || {},
|
||||
module = { id: id, uri: moduleUrl, exports: exports };
|
||||
|
||||
require._root.unshift(toDir(moduleUrl));
|
||||
(function(__dirname) {
|
||||
|
||||
/*debug*///var lineno=1;print('\n== '+moduleUrl+' ===============\n1'+moduleContent.replace(/(\n)/g, function(m, i){return '\n'+(++lineno);}));
|
||||
f.call({}, require, exports, module, __dirname);
|
||||
})(require._root[0]);
|
||||
require._root.shift();
|
||||
}
|
||||
catch(e) {
|
||||
throw 'Unable to require source code from "' + moduleUrl + '": ' + e.toSource();
|
||||
}
|
||||
|
||||
exports = module.exports || exports;
|
||||
require.cache[id] = exports;
|
||||
}
|
||||
else {
|
||||
throw 'The requested module cannot be returned: no content for id: "' + id + '" in paths: ' + require.paths.join(', ');
|
||||
}
|
||||
|
||||
return exports;
|
||||
}
|
||||
require._root = [__dirname]; // the dir of the script that is calling require()
|
||||
require.paths = [];
|
||||
require.cache = {}; // cache module exports. Like: {id: exported}
|
||||
|
||||
var SLASH = Packages.java.io.File.separator;
|
||||
|
||||
/** Given a module id, try to find the path to the associated module.
|
||||
*/
|
||||
require.resolve = function(id) {
|
||||
var parts = id.match(/^(\.\/|\/)?(.+)$/),
|
||||
isRelative = false,
|
||||
isAbsolute = false,
|
||||
isInModule = false,
|
||||
basename = id,
|
||||
url = '';
|
||||
|
||||
if (parts) {
|
||||
isRelative = parts[1] === './';
|
||||
isAbsolute = parts[1] === '/';
|
||||
isInModule = !(isRelative || isAbsolute);
|
||||
basename = parts[2];
|
||||
}
|
||||
|
||||
if (typeof basename === 'undefined') {
|
||||
throw new Error('Malformed module identifier: '+id);
|
||||
}
|
||||
|
||||
if (isAbsolute) {
|
||||
rootedId = id;
|
||||
}
|
||||
else if (isRelative) {
|
||||
var root = require._root[0],
|
||||
rootedId = root + '/' + basename;
|
||||
}
|
||||
|
||||
if (rootedId) {
|
||||
if ( url = loadAsFile(rootedId) ) { return url; }
|
||||
else if ( url = loadAsDir(rootedId) ) { return url; }
|
||||
}
|
||||
else if (isInModule) {
|
||||
var url,
|
||||
paths = require.paths;
|
||||
|
||||
for (var i = 0, len = paths.length; i < len; i++) {
|
||||
rootedId = paths[i] + '/' + basename;
|
||||
|
||||
if ( url = loadAsFile(rootedId) ) { return url; }
|
||||
else if ( url = loadAsDir(rootedId) ) { return url; }
|
||||
}
|
||||
if (url = findInNodemodules(require._root[0], basename, 'rhino_modules')) { return url; }
|
||||
if (url = findInNodemodules(require._root[0], basename, 'node_modules')) { return url; }
|
||||
}
|
||||
|
||||
throw new Error('Module not found: '+id);
|
||||
}
|
||||
|
||||
function loadAsFile(id) {
|
||||
if ( isFile(id) ) { return id; }
|
||||
|
||||
if ( isFile(id + '.js') ) { return id + '.js'; }
|
||||
}
|
||||
|
||||
function loadAsDir(id) {
|
||||
// look for the "main" property of the package.json file
|
||||
if ( isFile(id + '/' + 'package.json') ) {
|
||||
var packageJson = readFileSync(id + '/' + 'package.json', 'utf-8');
|
||||
eval( 'packageJson = '+ packageJson);
|
||||
if (packageJson.hasOwnProperty('main')) {
|
||||
var main = deDotPath(id + '/' + packageJson.main);
|
||||
return require.resolve(main);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isFile(id + '/' + 'index.js') ) {
|
||||
return id + '/' + 'index.js';
|
||||
}
|
||||
}
|
||||
|
||||
function findInNodemodules(root, id, moduleFolderName) {
|
||||
var dirs = root.split('/'),
|
||||
dir = '',
|
||||
rootedId;
|
||||
|
||||
while (dirs.length) {
|
||||
dir = dirs.join('/');
|
||||
rootedId = dir + '/' + moduleFolderName + '/' + id;
|
||||
|
||||
if ( url = loadAsFile(rootedId) ) { return url; }
|
||||
else if ( url = loadAsDir(rootedId) ) { return url; }
|
||||
|
||||
dirs.pop();
|
||||
}
|
||||
}
|
||||
|
||||
/** Given a path, return the base directory of that path.
|
||||
@example toDir('/foo/bar/somefile.js'); => '/foo/bar'
|
||||
*/
|
||||
function toDir(path) {
|
||||
var file = new java.io.File(path);
|
||||
|
||||
if (file.isDirectory()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
var parts = path.split('/');
|
||||
parts.pop();
|
||||
return parts.join('/');
|
||||
}
|
||||
|
||||
/** Returns true if the given path exists and is a file.
|
||||
*/
|
||||
function isFile(path) {
|
||||
var file = new java.io.File(path);
|
||||
|
||||
if (file.isFile()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Returns true if the given path exists and is a directory.
|
||||
*/
|
||||
function isDir(path) {
|
||||
var file = new java.io.File(path);
|
||||
|
||||
if (file.isDirectory()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Resolve dots in filepaths.
|
||||
*/
|
||||
function deDotPath(path) {
|
||||
return String(path)
|
||||
.replace(/(\/|\\)[^\/\\]+\/\.\.(\/|\\)/g, '/')
|
||||
.replace(/(\/|\\)\.(\/|\\|$)/g, '/');
|
||||
}
|
||||
|
||||
function readFileSync(filename, encoding, callback) {
|
||||
if (typeof arguments[1] === 'function') {
|
||||
encoding = null;
|
||||
callback = arguments[1];
|
||||
}
|
||||
|
||||
encoding = encoding || java.lang.System.getProperty('file.encoding');
|
||||
|
||||
try {
|
||||
var content = new java.util.Scanner(
|
||||
new java.io.File(filename),
|
||||
encoding
|
||||
).useDelimiter("\\Z");
|
||||
|
||||
return String( content.next() );
|
||||
}
|
||||
catch (e) {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
})(this);
|
||||
@ -1,10 +1,10 @@
|
||||
function readFileSync(filename, encoding) {
|
||||
exports.readFileSync = function(filename, encoding) {
|
||||
encoding = encoding || 'utf-8';
|
||||
|
||||
return readFile(filename, encoding);
|
||||
}
|
||||
};
|
||||
|
||||
function readdirSync(path) {
|
||||
var readdirSync = exports.readdirSync = function(path) {
|
||||
var dir,
|
||||
files;
|
||||
|
||||
@ -14,9 +14,9 @@ function readdirSync(path) {
|
||||
files = dir.list();
|
||||
|
||||
return files;
|
||||
}
|
||||
};
|
||||
|
||||
function ls(dir, recurse, _allFiles, _path) {
|
||||
var ls = exports.ls = function(dir, recurse, _allFiles, _path) {
|
||||
var files,
|
||||
file;
|
||||
|
||||
@ -56,9 +56,9 @@ function ls(dir, recurse, _allFiles, _path) {
|
||||
}
|
||||
|
||||
return _allFiles;
|
||||
}
|
||||
};
|
||||
|
||||
function stat(path, encoding) {
|
||||
var stat = exports.stat = function(path, encoding) {
|
||||
var f = new java.io.File(path)
|
||||
return {
|
||||
isFile: function() {
|
||||
@ -69,9 +69,9 @@ function stat(path, encoding) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
function mkPath(/**Array*/ path) {
|
||||
exports.mkPath = function(/**Array*/ path) {
|
||||
if (path.constructor != Array) path = path.split(/[\\\/]/);
|
||||
var make = "";
|
||||
for (var i = 0, l = path.length; i < l; i++) {
|
||||
@ -80,7 +80,7 @@ function mkPath(/**Array*/ path) {
|
||||
makeDir(make);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function makeDir(/**string*/ path) {
|
||||
var dirPath = toDir(path);
|
||||
@ -102,7 +102,7 @@ function exists(path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
function toDir(path) {
|
||||
var toDir = exports.toDir = function(path) {
|
||||
var f = new java.io.File(path);
|
||||
|
||||
if (f.isDirectory()){
|
||||
@ -113,9 +113,9 @@ function toDir(path) {
|
||||
parts.pop();
|
||||
|
||||
return parts.join('/');
|
||||
}
|
||||
};
|
||||
|
||||
function copyFile(inFile, outDir, fileName) {
|
||||
exports.copyFile = function(inFile, outDir, fileName) {
|
||||
if (fileName == null) fileName = toFile(inFile);
|
||||
|
||||
outDir = toDir(outDir);
|
||||
@ -131,14 +131,14 @@ function copyFile(inFile, outDir, fileName) {
|
||||
}
|
||||
bos.close();
|
||||
bis.close();
|
||||
}
|
||||
};
|
||||
|
||||
function toFile(path) {
|
||||
var parts = path.split(/[\\\/]/);
|
||||
return parts.pop();
|
||||
}
|
||||
|
||||
function writeFileSync(filename, data, encoding) {
|
||||
exports.writeFileSync = function(filename, data, encoding) {
|
||||
encoding = encoding || 'utf-8';
|
||||
|
||||
var out = new Packages.java.io.PrintWriter(
|
||||
@ -155,16 +155,4 @@ function writeFileSync(filename, data, encoding) {
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readFileSync: readFileSync,
|
||||
writeFileSync: writeFileSync,
|
||||
readdirSync: readdirSync,
|
||||
stat: stat,
|
||||
|
||||
ls: ls,
|
||||
mkPath: mkPath,
|
||||
toDir: toDir,
|
||||
copyFile: copyFile
|
||||
};
|
||||
@ -4,67 +4,64 @@
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
(function() {
|
||||
|
||||
// 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;
|
||||
}
|
||||
});
|
||||
// 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.';
|
||||
}
|
||||
|
||||
/**
|
||||
Deep clone a simple object.
|
||||
@private
|
||||
*/
|
||||
function doop(o) {
|
||||
if (o instanceof Object && o.constructor != Function) {
|
||||
var clone = o instanceof Array ? [] : {}, prop;
|
||||
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);
|
||||
});
|
||||
|
||||
for (prop in o){
|
||||
if ( o.hasOwnProperty(prop) ) {
|
||||
clone[prop] = (o[prop] instanceof Object)? doop(o[prop]) : o[prop];
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
return o;
|
||||
};
|
||||
});
|
||||
|
||||
})();
|
||||
delete doc.borrowed;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
Deep clone a simple object.
|
||||
@private
|
||||
*/
|
||||
function doop(o) {
|
||||
if (o instanceof Object && o.constructor != Function) {
|
||||
var clone = o instanceof Array ? [] : {}, prop;
|
||||
|
||||
for (prop in o){
|
||||
if ( o.hasOwnProperty(prop) ) {
|
||||
clone[prop] = (o[prop] instanceof Object)? doop(o[prop]) : o[prop];
|
||||
}
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
return o;
|
||||
};
|
||||
|
||||
@ -10,298 +10,296 @@
|
||||
@requires jsdoc/name
|
||||
@requires jsdoc/tag/dictionary
|
||||
*/
|
||||
(function() {
|
||||
var jsdoc = {
|
||||
tag: {
|
||||
Tag: require('jsdoc/tag').Tag,
|
||||
dictionary: require('jsdoc/tag/dictionary')
|
||||
},
|
||||
name: require('jsdoc/name')
|
||||
};
|
||||
|
||||
/**
|
||||
@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 = [];
|
||||
var jsdoc = {
|
||||
tag: {
|
||||
Tag: require('jsdoc/tag').Tag,
|
||||
dictionary: require('jsdoc/tag/dictionary')
|
||||
},
|
||||
name: require('jsdoc/name')
|
||||
};
|
||||
|
||||
/** The original text of the comment from the source code. */
|
||||
this.comment = docletSrc;
|
||||
this.setMeta(meta);
|
||||
/**
|
||||
@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 = [];
|
||||
|
||||
docletSrc = unwrap(docletSrc);
|
||||
docletSrc = fixDescription(docletSrc);
|
||||
/** The original text of the comment from the source code. */
|
||||
this.comment = docletSrc;
|
||||
this.setMeta(meta);
|
||||
|
||||
newTags = toTags.call(this, docletSrc);
|
||||
docletSrc = unwrap(docletSrc);
|
||||
docletSrc = fixDescription(docletSrc);
|
||||
|
||||
for (var i = 0, leni = newTags.length; i < leni; i++) {
|
||||
this.addTag(newTags[i].title, newTags[i].text);
|
||||
}
|
||||
newTags = toTags.call(this, docletSrc);
|
||||
|
||||
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) );
|
||||
}
|
||||
}
|
||||
|
||||
/** 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.lineno) {
|
||||
/**
|
||||
The line number of the code associated with this doclet.
|
||||
@type number
|
||||
*/
|
||||
this.meta.lineno = meta.lineno;
|
||||
}
|
||||
|
||||
if (meta.lineno) {
|
||||
/**
|
||||
The name of the file containing the code associated with this doclet.
|
||||
@type string
|
||||
*/
|
||||
this.meta.filename = meta.filename;
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 'property';
|
||||
}
|
||||
|
||||
return kind;
|
||||
for (var i = 0, leni = newTags.length; i < leni; i++) {
|
||||
this.addTag(newTags[i].title, newTags[i].text);
|
||||
}
|
||||
|
||||
/**
|
||||
Convert the raw source of the doclet comment into an array of Tag objects.
|
||||
@private
|
||||
*/
|
||||
function toTags(docletSrc) {
|
||||
var tagSrcs,
|
||||
tags = [];
|
||||
this.postProcess();
|
||||
}
|
||||
|
||||
docletSrc = unwrap(docletSrc);
|
||||
tagSrcs = split(docletSrc);
|
||||
/** 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) );
|
||||
}
|
||||
}
|
||||
|
||||
for each(tagSrc in tagSrcs) {
|
||||
tags.push( {title: tagSrc.title, text: tagSrc.text} );
|
||||
}
|
||||
/** 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);
|
||||
|
||||
return tags;
|
||||
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.lineno) {
|
||||
/**
|
||||
The line number of the code associated with this doclet.
|
||||
@type number
|
||||
*/
|
||||
this.meta.lineno = meta.lineno;
|
||||
}
|
||||
|
||||
if (meta.lineno) {
|
||||
/**
|
||||
The name of the file containing the code associated with this doclet.
|
||||
@type string
|
||||
*/
|
||||
this.meta.filename = meta.filename;
|
||||
}
|
||||
|
||||
/**
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 'property';
|
||||
}
|
||||
|
||||
return kind;
|
||||
}
|
||||
|
||||
/**
|
||||
Convert the raw source of the doclet comment into an array of Tag objects.
|
||||
@private
|
||||
*/
|
||||
function toTags(docletSrc) {
|
||||
var tagSrcs,
|
||||
tags = [];
|
||||
|
||||
docletSrc = unwrap(docletSrc);
|
||||
tagSrcs = split(docletSrc);
|
||||
|
||||
for each(tagSrc in tagSrcs) {
|
||||
tags.push( {title: tagSrc.title, text: tagSrc.text} );
|
||||
}
|
||||
|
||||
return tags;
|
||||
}
|
||||
|
||||
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 fixDescription(docletSrc) {
|
||||
if (!/^\s*@/.test(docletSrc)) {
|
||||
docletSrc = '@description ' + docletSrc;
|
||||
}
|
||||
return docletSrc;
|
||||
}
|
||||
|
||||
function unwrap(docletSrc) {
|
||||
if (!docletSrc) { return ''; }
|
||||
function split(docletSrc) {
|
||||
var tagSrcs = [];
|
||||
|
||||
// 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
|
||||
// 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]*))?/);
|
||||
|
||||
return docletSrc;
|
||||
}
|
||||
if (parsedTag) {
|
||||
var [, tagTitle, tagText] = parsedTag;
|
||||
|
||||
function fixDescription(docletSrc) {
|
||||
if (!/^\s*@/.test(docletSrc)) {
|
||||
docletSrc = '@description ' + docletSrc;
|
||||
}
|
||||
return docletSrc;
|
||||
}
|
||||
|
||||
function split(docletSrc) {
|
||||
var tagSrcs = [];
|
||||
|
||||
// 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) {
|
||||
var [, tagTitle, tagText] = parsedTag;
|
||||
|
||||
if (tagTitle) {
|
||||
tagSrcs.push({
|
||||
title: tagTitle,
|
||||
text: tagText
|
||||
});
|
||||
}
|
||||
if (tagTitle) {
|
||||
tagSrcs.push({
|
||||
title: tagTitle,
|
||||
text: tagText
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return tagSrcs;
|
||||
}
|
||||
|
||||
})();
|
||||
return tagSrcs;
|
||||
}
|
||||
|
||||
@ -5,178 +5,177 @@
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
(function() {
|
||||
var jsdoc = {
|
||||
tagDictionary: require('jsdoc/tag/dictionary')
|
||||
};
|
||||
|
||||
var puncToScope = { '.': 'static', '~': 'inner', '#': 'instance' },
|
||||
scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' },
|
||||
Token = Packages.org.mozilla.javascript.Token;
|
||||
var jsdoc = {
|
||||
tagDictionary: require('jsdoc/tag/dictionary')
|
||||
};
|
||||
|
||||
/**
|
||||
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;
|
||||
var puncToScope = { '.': 'static', '~': 'inner', '#': 'instance' },
|
||||
scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' },
|
||||
Token = Packages.org.mozilla.javascript.Token;
|
||||
|
||||
name = name? (''+name).replace(/\.prototype\.?/g, '#') : '';
|
||||
/**
|
||||
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;
|
||||
|
||||
// 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;
|
||||
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) { // @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) {
|
||||
about = exports.shorten(name);
|
||||
}
|
||||
|
||||
if (memberof) { // @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) {
|
||||
about = exports.shorten(name);
|
||||
}
|
||||
else if (name && /([#.~])$/.test(memberof) ) { // like @memberof foo# or @memberof foo~
|
||||
about = exports.shorten(memberof + name);
|
||||
}
|
||||
else if (name && doclet.scope ) { // like @memberof foo# or @memberof foo~
|
||||
about = exports.shorten(memberof + scopeToPunc[doclet.scope] + name);
|
||||
}
|
||||
else if (name && /([#.~])$/.test(memberof) ) { // like @memberof foo# or @memberof foo~
|
||||
about = exports.shorten(memberof + name);
|
||||
}
|
||||
else { // no @memberof
|
||||
about = exports.shorten(name);
|
||||
else if (name && doclet.scope ) { // like @memberof foo# or @memberof foo~
|
||||
about = exports.shorten(memberof + scopeToPunc[doclet.scope] + name);
|
||||
}
|
||||
}
|
||||
else { // no @memberof
|
||||
about = exports.shorten(name);
|
||||
}
|
||||
|
||||
if (about.name) {
|
||||
doclet.name = about.name;
|
||||
}
|
||||
if (about.name) {
|
||||
doclet.name = about.name;
|
||||
}
|
||||
|
||||
if (about.memberof) {
|
||||
doclet.setMemberof(about.memberof);
|
||||
}
|
||||
if (about.memberof) {
|
||||
doclet.setMemberof(about.memberof);
|
||||
}
|
||||
|
||||
if (about.longname && !doclet.longname) {
|
||||
doclet.setLongname(about.longname);
|
||||
}
|
||||
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> ?
|
||||
delete doclet.scope;
|
||||
}
|
||||
else {
|
||||
doclet.scope = puncToScope[about.scope];
|
||||
}
|
||||
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> ?
|
||||
delete doclet.scope;
|
||||
}
|
||||
else {
|
||||
if (doclet.name && doclet.memberof && !doclet.longname) {
|
||||
doclet.scope = 'static'; // default scope when none is provided
|
||||
|
||||
doclet.setLongname(doclet.memberof + scopeToPunc[doclet.scope] + doclet.name);
|
||||
}
|
||||
doclet.scope = puncToScope[about.scope];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (doclet.name && doclet.memberof && !doclet.longname) {
|
||||
doclet.scope = 'static'; // default scope when none is provided
|
||||
|
||||
if (about.variation) {
|
||||
doclet.variation = about.variation;
|
||||
doclet.setLongname(doclet.memberof + scopeToPunc[doclet.scope] + doclet.name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@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, '"') + '"';
|
||||
}
|
||||
}
|
||||
if (about.variation) {
|
||||
doclet.variation = about.variation;
|
||||
}
|
||||
}
|
||||
|
||||
return name;
|
||||
/**
|
||||
@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, '"') + '"';
|
||||
}
|
||||
}
|
||||
|
||||
RegExp.escape = RegExp.escape || function(str) {
|
||||
var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
|
||||
return str.replace(specials, "\\$&");
|
||||
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 );
|
||||
}
|
||||
|
||||
/**
|
||||
@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;
|
||||
return longname;
|
||||
}
|
||||
|
||||
if ( !/^[a-zA-Z]+?:.+$/i.test(name) ) {
|
||||
longname = longname.replace( new RegExp(RegExp.escape(name)+'$'), ns + ':' + name );
|
||||
/**
|
||||
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
|
||||
@returns {object} Representing the properties of the given name.
|
||||
*/
|
||||
exports.shorten = function(longname) {
|
||||
// quoted strings in a longname are atomic, convert to tokens
|
||||
var atoms = [], token;
|
||||
|
||||
// handle quoted names like foo["bar"]
|
||||
longname = longname.replace(/(\[?".+?"\]?)/g, function($) {
|
||||
var dot = '';
|
||||
if ( /^\[/.test($) ) {
|
||||
dot = '.';
|
||||
$ = $.replace( /^\[/g, '' ).replace( /\]$/g, '' );
|
||||
}
|
||||
|
||||
return longname;
|
||||
token = '@{' + atoms.length + '}@';
|
||||
atoms.push($);
|
||||
|
||||
return dot + token; // foo["bar"] => foo.@{1}@
|
||||
});
|
||||
|
||||
longname = longname.replace( /\.prototype\.?/g, '#' );
|
||||
|
||||
var parts = longname?
|
||||
(longname.match( /^(:?(.+)([#.~]))?(.+?)$/ ) || []).reverse()
|
||||
: [''];
|
||||
|
||||
var 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] || '',
|
||||
variation;
|
||||
|
||||
// like /** @name foo.bar(2) */
|
||||
if ( /(.+)\(([^)]+)\)$/.test(name) ) {
|
||||
name = RegExp.$1, variation = RegExp.$2;
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
@returns {object} Representing the properties of the given name.
|
||||
*/
|
||||
exports.shorten = function(longname) {
|
||||
// quoted strings in a longname are atomic, convert to tokens
|
||||
var atoms = [], token;
|
||||
|
||||
// handle quoted names like 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}@
|
||||
});
|
||||
|
||||
longname = longname.replace( /\.prototype\.?/g, '#' );
|
||||
|
||||
var parts = longname?
|
||||
(longname.match( /^(:?(.+)([#.~]))?(.+?)$/ ) || []).reverse()
|
||||
: [''];
|
||||
|
||||
var 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] || '',
|
||||
variation;
|
||||
|
||||
// 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};
|
||||
//// 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};
|
||||
}
|
||||
|
||||
|
||||
@ -4,70 +4,69 @@
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
(function() {
|
||||
var common = {
|
||||
args: require('common/args')
|
||||
|
||||
var common = {
|
||||
args: require('common/args')
|
||||
};
|
||||
|
||||
var argParser = new common.args.ArgParser(),
|
||||
ourOptions,
|
||||
defaults = {
|
||||
template: 'default',
|
||||
destination: './out/'
|
||||
};
|
||||
|
||||
var argParser = new common.args.ArgParser(),
|
||||
ourOptions,
|
||||
defaults = {
|
||||
template: 'default',
|
||||
destination: './out/'
|
||||
};
|
||||
|
||||
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: utf-8');
|
||||
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: console');
|
||||
argParser.addOption('r', 'recurse', false, 'Recurse into subdirectories when scanning for source code files.');
|
||||
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, 'Provide a querystring to define custom variable names/values to add to the options hash.');
|
||||
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: utf-8');
|
||||
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: console');
|
||||
argParser.addOption('r', 'recurse', false, 'Recurse into subdirectories when scanning for source code files.');
|
||||
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, 'Provide a querystring to define custom variable names/values to add to the options hash.');
|
||||
|
||||
|
||||
// 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?
|
||||
|
||||
/**
|
||||
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 || [];
|
||||
/**
|
||||
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);
|
||||
}
|
||||
if (typeof args === 'string' || args.constructor === String) {
|
||||
args = (''+args).split(/\s+/g);
|
||||
}
|
||||
|
||||
ourOptions = argParser.parse(args, defaults);
|
||||
ourOptions = argParser.parse(args, defaults);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
Display help message for options.
|
||||
*/
|
||||
exports.help = function() {
|
||||
return argParser.help();
|
||||
else {
|
||||
return ourOptions[name];
|
||||
}
|
||||
|
||||
/**
|
||||
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];
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
@ -8,62 +8,61 @@
|
||||
@module jsdoc/package
|
||||
@see http://wiki.commonjs.org/wiki/Packages/1.0
|
||||
*/
|
||||
(function() {
|
||||
/**
|
||||
@class
|
||||
@classdesc Represents a JavaScript package.
|
||||
@param {string} json - The contents of package.json.
|
||||
*/
|
||||
exports.Package = function(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';
|
||||
/**
|
||||
@class
|
||||
@classdesc Represents a JavaScript package.
|
||||
@param {string} json - The contents of package.json.
|
||||
*/
|
||||
exports.Package = function(json) {
|
||||
/** The source files associated with this package.
|
||||
@type {Array<String>}
|
||||
*/
|
||||
this.files = [];
|
||||
|
||||
json = JSON.parse(json);
|
||||
/** The kind of this package.
|
||||
@readonly
|
||||
@default
|
||||
@type {string}
|
||||
*/
|
||||
this.kind = 'package';
|
||||
|
||||
/** 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;
|
||||
json = JSON.parse(json);
|
||||
|
||||
/** The longname of this package.
|
||||
@type {string}
|
||||
*/
|
||||
this.longname = this.kind + ':' + this.name;
|
||||
/** 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 description of this package.
|
||||
@type {string}
|
||||
*/
|
||||
this.description = json.description;
|
||||
/** The longname of this package.
|
||||
@type {string}
|
||||
*/
|
||||
this.longname = this.kind + ':' + this.name;
|
||||
|
||||
/**
|
||||
The hash summary of the source file.
|
||||
@type {string}
|
||||
@since 3.2.0
|
||||
*/
|
||||
this.version = json.version;
|
||||
/** The description of this package.
|
||||
@type {string}
|
||||
*/
|
||||
this.description = json.description;
|
||||
|
||||
/**
|
||||
* The licenses of this package.
|
||||
* @type {Array<Object>}
|
||||
* @example
|
||||
* "licenses": [
|
||||
* {
|
||||
* "type": "GPLv2",
|
||||
* "url": "http://www.example.com/licenses/gpl.html"
|
||||
* }
|
||||
* ]
|
||||
*/
|
||||
this.licenses = json.licenses;
|
||||
}
|
||||
/**
|
||||
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;
|
||||
}
|
||||
|
||||
})();
|
||||
@ -2,151 +2,151 @@
|
||||
@module jsdoc/src/handlers
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var currentModule = null;
|
||||
|
||||
/**
|
||||
Attach these event handlers to a particular instance of a parser.
|
||||
@param parser
|
||||
*/
|
||||
exports.attachTo = function(parser) {
|
||||
var jsdoc = {doclet: require('jsdoc/doclet')};
|
||||
var currentModule = null;
|
||||
|
||||
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
|
||||
parser.on('jsdocCommentFound', function(e) {
|
||||
var newDoclet = new jsdoc.doclet.Doclet(e.comment, e);
|
||||
/**
|
||||
Attach these event handlers to a particular instance of a parser.
|
||||
@param parser
|
||||
*/
|
||||
exports.attachTo = function(parser) {
|
||||
var jsdoc = {doclet: require('jsdoc/doclet')};
|
||||
|
||||
if (!newDoclet.name) {
|
||||
return false; // only interested in virtual comments (with a @name) here
|
||||
}
|
||||
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
|
||||
parser.on('jsdocCommentFound', function(e) {
|
||||
var newDoclet = new jsdoc.doclet.Doclet(e.comment, e);
|
||||
|
||||
addDoclet.call(this, newDoclet);
|
||||
if (newDoclet.kind === 'module') {
|
||||
currentModule = newDoclet.longname;
|
||||
}
|
||||
e.doclet = newDoclet;
|
||||
});
|
||||
if (!newDoclet.name) {
|
||||
return false; // only interested in virtual comments (with a @name) here
|
||||
}
|
||||
|
||||
// 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);
|
||||
addDoclet.call(this, newDoclet);
|
||||
if (newDoclet.kind === 'module') {
|
||||
currentModule = newDoclet.longname;
|
||||
}
|
||||
e.doclet = newDoclet;
|
||||
});
|
||||
|
||||
for (var i = 0, l = subDoclets.length; i < l; i++) {
|
||||
newSymbolDoclet.call(this, subDoclets[i], e);
|
||||
}
|
||||
});
|
||||
// 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);
|
||||
|
||||
function newSymbolDoclet(docletSrc, e) {
|
||||
var newDoclet = new jsdoc.doclet.Doclet(docletSrc, e);
|
||||
for (var i = 0, l = subDoclets.length; i < l; i++) {
|
||||
newSymbolDoclet.call(this, subDoclets[i], 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 = new jsdoc.doclet.Doclet(e.comment, e);
|
||||
}
|
||||
function newSymbolDoclet(docletSrc, e) {
|
||||
var newDoclet = new jsdoc.doclet.Doclet(docletSrc, e);
|
||||
|
||||
if (newDoclet.alias) {
|
||||
if (newDoclet.alias === '{@thisClass}') {
|
||||
memberofName = this.resolveThis(e.astnode);
|
||||
// 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 = new jsdoc.doclet.Doclet(e.comment, e);
|
||||
}
|
||||
|
||||
// "class" refers to the owner of the prototype, not the prototype itself
|
||||
if ( /^(.+?)(\.prototype|#)$/.test(memberofName) ) {
|
||||
memberofName = RegExp.$1;
|
||||
}
|
||||
newDoclet.alias = memberofName;
|
||||
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.addTag('name', newDoclet.alias);
|
||||
newDoclet.postProcess();
|
||||
newDoclet.alias = memberofName;
|
||||
}
|
||||
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 memberofName,
|
||||
scope;
|
||||
if ( /^((module.)?exports|this)(\.|$)/.test(newDoclet.name) ) {
|
||||
var nameStartsWith = RegExp.$1;
|
||||
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 memberofName,
|
||||
scope;
|
||||
if ( /^((module.)?exports|this)(\.|$)/.test(newDoclet.name) ) {
|
||||
var nameStartsWith = RegExp.$1;
|
||||
|
||||
newDoclet.name = newDoclet.name.replace(/^(exports|this)(\.|$)/, '');
|
||||
newDoclet.name = newDoclet.name.replace(/^(exports|this)(\.|$)/, '');
|
||||
|
||||
// like /** @module foo */ exports.bar = 1;
|
||||
if (nameStartsWith === 'exports' && currentModule) {
|
||||
// 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';
|
||||
}
|
||||
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 (memberofName) { newDoclet.addTag( 'memberof', memberofName); }
|
||||
else {
|
||||
if (currentModule) {
|
||||
if (!newDoclet.scope) newDoclet.addTag( 'inner');
|
||||
if (!newDoclet.memberof && newDoclet.scope !== 'global') newDoclet.addTag( 'memberof', currentModule);
|
||||
if (memberofName) {
|
||||
if (newDoclet.name) {
|
||||
newDoclet.name = memberofName + (scope === 'instance'? '#' : '.') + newDoclet.name;
|
||||
}
|
||||
else { newDoclet.name = memberofName; }
|
||||
}
|
||||
}
|
||||
else {
|
||||
memberofName = this.astnodeToMemberof(e.astnode);
|
||||
}
|
||||
|
||||
newDoclet.postProcess();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
addDoclet.call(this, newDoclet);
|
||||
e.doclet = newDoclet;
|
||||
}
|
||||
|
||||
//parser.on('fileBegin', function(e) { });
|
||||
|
||||
parser.on('fileComplete', function(e) {
|
||||
currentModule = null;
|
||||
});
|
||||
|
||||
function addDoclet(newDoclet) {
|
||||
if (newDoclet) {
|
||||
e = { doclet: newDoclet };
|
||||
this.fire('newDoclet', e);
|
||||
|
||||
if (!e.defaultPrevented) {
|
||||
if ( !filter(newDoclet) ) {
|
||||
this.addResult(newDoclet);
|
||||
if (memberofName) { newDoclet.addTag( 'memberof', memberofName); }
|
||||
else {
|
||||
if (currentModule) {
|
||||
if (!newDoclet.scope) newDoclet.addTag( 'inner');
|
||||
if (!newDoclet.memberof && newDoclet.scope !== 'global') newDoclet.addTag( 'memberof', currentModule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newDoclet.postProcess();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
addDoclet.call(this, newDoclet);
|
||||
e.doclet = newDoclet;
|
||||
}
|
||||
})();
|
||||
|
||||
//parser.on('fileBegin', function(e) { });
|
||||
|
||||
parser.on('fileComplete', function(e) {
|
||||
currentModule = null;
|
||||
});
|
||||
|
||||
function addDoclet(newDoclet) {
|
||||
if (newDoclet) {
|
||||
e = { doclet: newDoclet };
|
||||
this.fire('newDoclet', e);
|
||||
|
||||
if (!e.defaultPrevented) {
|
||||
if ( !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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -5,498 +5,495 @@
|
||||
* @requires common/events
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var Token = Packages.org.mozilla.javascript.Token,
|
||||
currentParser = null,
|
||||
currentSourceName = '';
|
||||
var Token = Packages.org.mozilla.javascript.Token,
|
||||
currentParser = null,
|
||||
currentSourceName = '';
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @mixes module:common/events
|
||||
*
|
||||
* @example <caption>Create a new parser.</caption>
|
||||
* var jsdocParser = new (require('jsdoc/src/parser').Parser)();
|
||||
*/
|
||||
exports.Parser = function() {
|
||||
this._resultBuffer = [];
|
||||
this.refs = {};
|
||||
}
|
||||
require('common/util').mixin(exports.Parser.prototype, require('common/events'));
|
||||
/**
|
||||
* @class
|
||||
* @mixes module:common/events
|
||||
*
|
||||
* @example <caption>Create a new parser.</caption>
|
||||
* var jsdocParser = new (require('jsdoc/src/parser').Parser)();
|
||||
*/
|
||||
exports.Parser = function() {
|
||||
this._resultBuffer = [];
|
||||
this.refs = {};
|
||||
}
|
||||
require('common/util').mixin(exports.Parser.prototype, require('common/events'));
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
const SCHEMA = 'javascript:';
|
||||
var sourceCode = '',
|
||||
filename = '';
|
||||
/**
|
||||
* 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) {
|
||||
const SCHEMA = 'javascript:';
|
||||
var sourceCode = '',
|
||||
filename = '';
|
||||
|
||||
if (typeof sourceFiles === 'string') { sourceFiles = [sourceFiles]; }
|
||||
if (typeof sourceFiles === 'string') { sourceFiles = [sourceFiles]; }
|
||||
|
||||
for (i = 0, leni = sourceFiles.length; i < leni; i++) {
|
||||
if (sourceFiles[i].indexOf(SCHEMA) === 0) {
|
||||
sourceCode = sourceFiles[i].substr(SCHEMA.length);
|
||||
filename = '[[string' + i + ']]';
|
||||
}
|
||||
else {
|
||||
filename = sourceFiles[i];
|
||||
try {
|
||||
sourceCode = require('fs').readFileSync(filename, encoding);
|
||||
}
|
||||
catch(e) {
|
||||
console.log('FILE READ ERROR: in module:jsdoc/parser.parseFiles: "' + filename + '" ' + e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
currentParser = this;
|
||||
this._parseSourceCode(sourceCode, filename);
|
||||
currentParser = null;
|
||||
}
|
||||
|
||||
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() {
|
||||
currentParser = null;
|
||||
currentSourceName = '';
|
||||
this._resultBuffer = [];
|
||||
}
|
||||
|
||||
/** @private */
|
||||
exports.Parser.prototype._parseSourceCode = function(sourceCode, sourceName) {
|
||||
currentSourceName = sourceName;
|
||||
|
||||
sourceCode = pretreat(sourceCode);
|
||||
|
||||
var ast = parserFactory().parse(sourceCode, sourceName, 1);
|
||||
|
||||
var e = {filename: currentSourceName};
|
||||
this.fire('fileBegin', e);
|
||||
|
||||
if (!e.defaultPrevented) {
|
||||
ast.visit(
|
||||
new Packages.org.mozilla.javascript.ast.NodeVisitor({
|
||||
visit: visitNode
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
this.fire('fileComplete', e);
|
||||
|
||||
currentSourceName = '';
|
||||
}
|
||||
|
||||
function pretreat(code) {
|
||||
return code
|
||||
// merge adjacent doclets
|
||||
.replace(/\*\/\/\*\*+/g, '@also')
|
||||
// make lent objectliterals documentable by giving them a dummy name
|
||||
.replace(/(\/\*\*[\s\S]*?@lends\b[\s\S]*?\*\/\s*)\{/g, '$1____ = {');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 memberof = {};
|
||||
|
||||
if (node.type === Token.VAR || node.type === Token.FUNCTION) {
|
||||
if (node.enclosingFunction) { // an inner var or func
|
||||
memberof.id = 'astnode'+node.enclosingFunction.hashCode();
|
||||
memberof.doclet = this.refs[memberof.id];
|
||||
if (!memberof.doclet) {
|
||||
return '<anonymous>~';
|
||||
}
|
||||
return (memberof.doclet.longname||memberof.doclet.name) + '~';
|
||||
}
|
||||
for (i = 0, leni = sourceFiles.length; i < leni; i++) {
|
||||
if (sourceFiles[i].indexOf(SCHEMA) === 0) {
|
||||
sourceCode = sourceFiles[i].substr(SCHEMA.length);
|
||||
filename = '[[string' + i + ']]';
|
||||
}
|
||||
else {
|
||||
memberof.id = 'astnode'+node.parent.hashCode();
|
||||
memberof.doclet = this.refs[memberof.id];
|
||||
if (!memberof.doclet) return ''; // global?
|
||||
return memberof.doclet.longname||memberof.doclet.name;
|
||||
filename = sourceFiles[i];
|
||||
try {
|
||||
sourceCode = require('fs').readFileSync(filename, encoding);
|
||||
}
|
||||
catch(e) {
|
||||
console.log('FILE READ ERROR: in module:jsdoc/parser.parseFiles: "' + filename + '" ' + e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
currentParser = this;
|
||||
this._parseSourceCode(sourceCode, filename);
|
||||
currentParser = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve what "this" refers too, 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 = {};
|
||||
return this._resultBuffer;
|
||||
}
|
||||
|
||||
if (node.enclosingFunction) {
|
||||
/**
|
||||
* @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() {
|
||||
currentParser = null;
|
||||
currentSourceName = '';
|
||||
this._resultBuffer = [];
|
||||
}
|
||||
|
||||
/** @private */
|
||||
exports.Parser.prototype._parseSourceCode = function(sourceCode, sourceName) {
|
||||
currentSourceName = sourceName;
|
||||
|
||||
sourceCode = pretreat(sourceCode);
|
||||
|
||||
var ast = parserFactory().parse(sourceCode, sourceName, 1);
|
||||
|
||||
var e = {filename: currentSourceName};
|
||||
this.fire('fileBegin', e);
|
||||
|
||||
if (!e.defaultPrevented) {
|
||||
ast.visit(
|
||||
new Packages.org.mozilla.javascript.ast.NodeVisitor({
|
||||
visit: visitNode
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
this.fire('fileComplete', e);
|
||||
|
||||
currentSourceName = '';
|
||||
}
|
||||
|
||||
function pretreat(code) {
|
||||
return code
|
||||
// merge adjacent doclets
|
||||
.replace(/\*\/\/\*\*+/g, '@also')
|
||||
// make lent objectliterals documentable by giving them a dummy name
|
||||
.replace(/(\/\*\*[\s\S]*?@lends\b[\s\S]*?\*\/\s*)\{/g, '$1____ = {');
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 memberof = {};
|
||||
|
||||
if (node.type === Token.VAR || node.type === Token.FUNCTION) {
|
||||
if (node.enclosingFunction) { // an inner var or func
|
||||
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){
|
||||
return this.resolveThis(node.enclosingFunction/*memberof.doclet.meta.code.val*/);
|
||||
}
|
||||
else return ''; // TODO handle global this?
|
||||
return '<anonymous>~';
|
||||
}
|
||||
return (memberof.doclet.longname||memberof.doclet.name) + '~';
|
||||
}
|
||||
else if (node.parent) {
|
||||
var parent = node.parent;
|
||||
if (parent.type === Token.COLON) parent = parent.parent; // go up one more
|
||||
}
|
||||
else {
|
||||
memberof.id = 'astnode'+node.parent.hashCode();
|
||||
memberof.doclet = this.refs[memberof.id];
|
||||
if (!memberof.doclet) return ''; // global?
|
||||
return memberof.doclet.longname||memberof.doclet.name;
|
||||
}
|
||||
}
|
||||
|
||||
memberof.id = 'astnode'+parent.hashCode();
|
||||
memberof.doclet = this.refs[memberof.id];
|
||||
/**
|
||||
* Resolve what "this" refers too, 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 = {};
|
||||
|
||||
if (!memberof.doclet) return ''; // global?
|
||||
if (node.enclosingFunction) {
|
||||
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 {
|
||||
return ''; // global?
|
||||
if (node.enclosingFunction){
|
||||
return this.resolveThis(node.enclosingFunction/*memberof.doclet.meta.code.val*/);
|
||||
}
|
||||
else return ''; // TODO handle global this?
|
||||
}
|
||||
}
|
||||
else if (node.parent) {
|
||||
var parent = node.parent;
|
||||
if (parent.type === Token.COLON) parent = parent.parent; // go up one more
|
||||
|
||||
/**
|
||||
* 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,
|
||||
enclosingFunction = node.enclosingFunction;
|
||||
memberof.id = 'astnode'+parent.hashCode();
|
||||
memberof.doclet = this.refs[memberof.id];
|
||||
|
||||
if (!enclosingFunction) { return ''; } // global
|
||||
doclet = this.refs['astnode'+enclosingFunction.hashCode()];
|
||||
if (!memberof.doclet) return ''; // global?
|
||||
|
||||
if ( doclet && doclet.meta.vars && ~doclet.meta.vars.indexOf(basename) ) {
|
||||
return doclet.longname;
|
||||
}
|
||||
return memberof.doclet.longname||memberof.doclet.name;
|
||||
}
|
||||
else {
|
||||
return ''; // global?
|
||||
}
|
||||
}
|
||||
|
||||
return this.resolveVar(enclosingFunction, basename);
|
||||
/**
|
||||
* 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,
|
||||
enclosingFunction = node.enclosingFunction;
|
||||
|
||||
if (!enclosingFunction) { return ''; } // global
|
||||
doclet = this.refs['astnode'+enclosingFunction.hashCode()];
|
||||
|
||||
if ( doclet && doclet.meta.vars && ~doclet.meta.vars.indexOf(basename) ) {
|
||||
return doclet.longname;
|
||||
}
|
||||
|
||||
/** @private */
|
||||
function visitNode(node) {
|
||||
var e,
|
||||
commentSrc;
|
||||
return this.resolveVar(enclosingFunction, basename);
|
||||
}
|
||||
|
||||
// look for stand-alone doc comments
|
||||
if (node.type === Token.SCRIPT && node.comments) {
|
||||
// note: ALL comments are seen in this block...
|
||||
for each(var comment in node.comments.toArray()) {
|
||||
if (comment.commentType !== Token.CommentType.JSDOC) {
|
||||
continue;
|
||||
}
|
||||
/** @private */
|
||||
function visitNode(node) {
|
||||
var e,
|
||||
commentSrc;
|
||||
|
||||
if (commentSrc = ''+comment.toSource()) {
|
||||
|
||||
e = {
|
||||
comment: commentSrc,
|
||||
lineno: comment.getLineno(),
|
||||
filename: currentSourceName
|
||||
};
|
||||
|
||||
if ( isValidJsdoc(commentSrc) ) {
|
||||
currentParser.fire('jsdocCommentFound', e, currentParser);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (node.type === Token.ASSIGN) {
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the ASSIGN node
|
||||
comment: String(node.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
var basename = e.code.name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
|
||||
|
||||
if (basename !== 'this') e.code.funcscope = currentParser.resolveVar(node, basename);
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
// look for stand-alone doc comments
|
||||
if (node.type === Token.SCRIPT && node.comments) {
|
||||
// note: ALL comments are seen in this block...
|
||||
for each(var comment in node.comments.toArray()) {
|
||||
if (comment.commentType !== Token.CommentType.JSDOC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
}
|
||||
else if (node.type === Token.COLON) { // assignment within an object literal
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the COLON node
|
||||
comment: String(node.left.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
if (commentSrc = ''+comment.toSource()) {
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
}
|
||||
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
|
||||
node.jsDoc = node.parent.jsDoc;
|
||||
}
|
||||
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the VARIABLE node
|
||||
comment: String(node.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
// keep track of vars in a function scope
|
||||
if (node.enclosingFunction) {
|
||||
var func = 'astnode'+node.enclosingFunction.hashCode(),
|
||||
funcDoc = currentParser.refs[func];
|
||||
|
||||
if (funcDoc) {
|
||||
funcDoc.meta.vars = funcDoc.meta.vars || [];
|
||||
funcDoc.meta.vars.push(e.code.name);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
}
|
||||
else if (node.type == Token.FUNCTION) {
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the COLON node
|
||||
comment: String(node.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
e.code.name = String(node.name) || '';
|
||||
|
||||
// keep track of vars in a function scope
|
||||
if (node.enclosingFunction) {
|
||||
var func = 'astnode'+node.enclosingFunction.hashCode(),
|
||||
funcDoc = currentParser.refs[func];
|
||||
|
||||
if (funcDoc) {
|
||||
funcDoc.meta.vars = funcDoc.meta.vars || [];
|
||||
funcDoc.meta.vars.push(e.code.name);
|
||||
}
|
||||
}
|
||||
|
||||
var basename = e.code.name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
|
||||
e.code.funcscope = currentParser.resolveVar(node, basename);
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
else if (!currentParser.refs['astnode'+e.code.node.hashCode()]) { // keep references to undocumented anonymous functions too as they might have scoped vars
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = {
|
||||
longname: '<anonymous>',
|
||||
meta: { code: e.code }
|
||||
e = {
|
||||
comment: commentSrc,
|
||||
lineno: comment.getLineno(),
|
||||
filename: currentSourceName
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find the name and type of the given node.
|
||||
* @private
|
||||
* @memberof module:src/parser.Parser
|
||||
*/
|
||||
function aboutNode(node) {
|
||||
about = {};
|
||||
|
||||
if (node.type == Token.FUNCTION) {
|
||||
about.name = '' + node.name;
|
||||
|
||||
about.type = 'function';
|
||||
about.node = node;
|
||||
|
||||
return about;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else { // like var i;
|
||||
about.node = node.target;
|
||||
about.value = nodeToString(about.node);
|
||||
about.type = 'undefined';
|
||||
}
|
||||
|
||||
return about;
|
||||
}
|
||||
|
||||
if (node.type === Token.ASSIGN || node.type === Token.COLON) {
|
||||
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, '\\"')+'"';
|
||||
if ( isValidJsdoc(commentSrc) ) {
|
||||
currentParser.fire('jsdocCommentFound', e, currentParser);
|
||||
}
|
||||
}
|
||||
about.node = node.right;
|
||||
about.value = nodeToString(about.node);
|
||||
about.type = getTypeName(node.right);
|
||||
return about;
|
||||
}
|
||||
}
|
||||
else if (node.type === Token.ASSIGN) {
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the ASSIGN node
|
||||
comment: String(node.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
var basename = e.code.name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
|
||||
|
||||
if (basename !== 'this') e.code.funcscope = currentParser.resolveVar(node, basename);
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
// type 39 (NAME)
|
||||
var string = nodeToString(node);
|
||||
if (string) {
|
||||
about.name = string;
|
||||
return about;
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
}
|
||||
else if (node.type === Token.COLON) { // assignment within an object literal
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the COLON node
|
||||
comment: String(node.left.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
}
|
||||
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
|
||||
node.jsDoc = node.parent.jsDoc;
|
||||
}
|
||||
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the VARIABLE node
|
||||
comment: String(node.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
// keep track of vars in a function scope
|
||||
if (node.enclosingFunction) {
|
||||
var func = 'astnode'+node.enclosingFunction.hashCode(),
|
||||
funcDoc = currentParser.refs[func];
|
||||
|
||||
if (funcDoc) {
|
||||
funcDoc.meta.vars = funcDoc.meta.vars || [];
|
||||
funcDoc.meta.vars.push(e.code.name);
|
||||
}
|
||||
}
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
}
|
||||
else if (node.type == Token.FUNCTION) {
|
||||
e = {
|
||||
id: 'astnode'+node.hashCode(), // the id of the COLON node
|
||||
comment: String(node.jsDoc||'@undocumented'),
|
||||
lineno: node.getLineno(),
|
||||
filename: currentSourceName,
|
||||
astnode: node,
|
||||
code: aboutNode(node)
|
||||
};
|
||||
|
||||
e.code.name = String(node.name) || '';
|
||||
|
||||
// keep track of vars in a function scope
|
||||
if (node.enclosingFunction) {
|
||||
var func = 'astnode'+node.enclosingFunction.hashCode(),
|
||||
funcDoc = currentParser.refs[func];
|
||||
|
||||
if (funcDoc) {
|
||||
funcDoc.meta.vars = funcDoc.meta.vars || [];
|
||||
funcDoc.meta.vars.push(e.code.name);
|
||||
}
|
||||
}
|
||||
|
||||
var basename = e.code.name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
|
||||
e.code.funcscope = currentParser.resolveVar(node, basename);
|
||||
|
||||
if ( isValidJsdoc(e.comment) ) {
|
||||
currentParser.fire('symbolFound', e, currentParser);
|
||||
}
|
||||
|
||||
if (e.doclet) {
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||
}
|
||||
else if (!currentParser.refs['astnode'+e.code.node.hashCode()]) { // keep references to undocumented anonymous functions too as they might have scoped vars
|
||||
currentParser.refs['astnode'+e.code.node.hashCode()] = {
|
||||
longname: '<anonymous>',
|
||||
meta: { code: e.code }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to find the name and type of the given node.
|
||||
* @private
|
||||
* @memberof module:src/parser.Parser
|
||||
*/
|
||||
function aboutNode(node) {
|
||||
about = {};
|
||||
|
||||
if (node.type == Token.FUNCTION) {
|
||||
about.name = '' + node.name;
|
||||
|
||||
about.type = 'function';
|
||||
about.node = node;
|
||||
|
||||
return about;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
else { // like var i;
|
||||
about.node = node.target;
|
||||
about.value = nodeToString(about.node);
|
||||
about.type = 'undefined';
|
||||
}
|
||||
|
||||
return about;
|
||||
}
|
||||
|
||||
/** @private
|
||||
@memberof module:src/parser.Parser
|
||||
*/
|
||||
function nodeToString(node) {
|
||||
var str;
|
||||
if (node.type === Token.ASSIGN || node.type === Token.COLON) {
|
||||
about.name = nodeToString(node.left);
|
||||
if (node.type === Token.COLON) {
|
||||
|
||||
if (!node) return;
|
||||
|
||||
if (node.type === Token.GETPROP) {
|
||||
str = [nodeToString(node.target), node.property.string].join('.');
|
||||
// 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, '\\"')+'"';
|
||||
}
|
||||
}
|
||||
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 {
|
||||
str = getTypeName(node);
|
||||
}
|
||||
|
||||
return '' + str;
|
||||
};
|
||||
|
||||
/** @private
|
||||
@memberof module:src/parser.Parser
|
||||
*/
|
||||
function getTypeName(node) {
|
||||
var type = '';
|
||||
|
||||
if (node) {
|
||||
type = ''+ Packages.org.mozilla.javascript.Token.typeToName(node.getType());
|
||||
}
|
||||
|
||||
return type;
|
||||
about.node = node.right;
|
||||
about.value = nodeToString(about.node);
|
||||
about.type = getTypeName(node.right);
|
||||
return about;
|
||||
}
|
||||
|
||||
/** @private
|
||||
@memberof module:src/parser.Parser
|
||||
*/
|
||||
function isValidJsdoc(commentSrc) {
|
||||
return commentSrc.indexOf('/***') !== 0; /*** ignore comments that start with many stars ***/
|
||||
// type 39 (NAME)
|
||||
var string = nodeToString(node);
|
||||
if (string) {
|
||||
about.name = string;
|
||||
return about;
|
||||
}
|
||||
|
||||
})();
|
||||
return about;
|
||||
}
|
||||
|
||||
/** @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 {
|
||||
str = getTypeName(node);
|
||||
}
|
||||
|
||||
return '' + str;
|
||||
};
|
||||
|
||||
/** @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 isValidJsdoc(commentSrc) {
|
||||
return commentSrc.indexOf('/***') !== 0; /*** ignore comments that start with many stars ***/
|
||||
}
|
||||
|
||||
/**
|
||||
Fired whenever the parser encounters a JSDoc comment in the current source code.
|
||||
@ -506,4 +503,4 @@
|
||||
@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.
|
||||
*/
|
||||
*/
|
||||
@ -6,64 +6,63 @@
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
var common = {
|
||||
mixin: require('common/util').mixin,
|
||||
events: require('common/events')
|
||||
};
|
||||
|
||||
var fs = require('fs');
|
||||
var common = {
|
||||
mixin: require('common/util').mixin,
|
||||
events: require('common/events')
|
||||
};
|
||||
|
||||
/**
|
||||
@constructor
|
||||
@mixes module:common.events
|
||||
*/
|
||||
exports.Scanner = function() {
|
||||
}
|
||||
common.mixin(exports.Scanner.prototype, common.events);
|
||||
var fs = require('fs');
|
||||
|
||||
/**
|
||||
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, includeMatch, excludeMatch) {
|
||||
var filePaths = [],
|
||||
that = this;
|
||||
/**
|
||||
@constructor
|
||||
@mixes module:common.events
|
||||
*/
|
||||
exports.Scanner = function() {
|
||||
}
|
||||
common.mixin(exports.Scanner.prototype, common.events);
|
||||
|
||||
searchPaths = searchPaths || [];
|
||||
depth = depth || 1;
|
||||
/**
|
||||
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, includeMatch, excludeMatch) {
|
||||
var filePaths = [],
|
||||
that = this;
|
||||
|
||||
searchPaths.forEach(function($) {
|
||||
if ( fs.stat($).isFile() ) {
|
||||
filePaths.push($);
|
||||
}
|
||||
else {
|
||||
filePaths = filePaths.concat(fs.ls($, depth));
|
||||
}
|
||||
});
|
||||
searchPaths = searchPaths || [];
|
||||
depth = depth || 1;
|
||||
|
||||
filePaths = filePaths.filter(function($) {
|
||||
if (includeMatch && !includeMatch.test($)) {
|
||||
return false
|
||||
}
|
||||
searchPaths.forEach(function($) {
|
||||
if ( fs.stat($).isFile() ) {
|
||||
filePaths.push($);
|
||||
}
|
||||
else {
|
||||
filePaths = filePaths.concat(fs.ls($, depth));
|
||||
}
|
||||
});
|
||||
|
||||
if (excludeMatch && excludeMatch.test($)) {
|
||||
return false
|
||||
}
|
||||
filePaths = filePaths.filter(function($) {
|
||||
if (includeMatch && !includeMatch.test($)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
if (excludeMatch && excludeMatch.test($)) {
|
||||
return false
|
||||
}
|
||||
|
||||
filePaths = filePaths.filter(function($) {
|
||||
var e = { fileName: $ };
|
||||
that.fire('sourceFileFound', e);
|
||||
return true;
|
||||
});
|
||||
|
||||
return !e.defaultPrevented;
|
||||
});
|
||||
filePaths = filePaths.filter(function($) {
|
||||
var e = { fileName: $ };
|
||||
that.fire('sourceFileFound', e);
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
return !e.defaultPrevented;
|
||||
});
|
||||
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
})();
|
||||
@ -11,126 +11,124 @@
|
||||
@requires jsdoc/tag/validator
|
||||
@requires jsdoc/tag/type
|
||||
*/
|
||||
(function() {
|
||||
|
||||
var jsdoc = {
|
||||
tag: {
|
||||
dictionary: require('jsdoc/tag/dictionary'),
|
||||
validator: require('jsdoc/tag/validator'),
|
||||
type: require('jsdoc/tag/type')
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
*/
|
||||
exports.Tag = function(tagTitle, tagBody, meta) {
|
||||
var tagDef = jsdoc.tag.dictionary.lookUp(tagTitle),
|
||||
meta = meta || {};
|
||||
var jsdoc = {
|
||||
tag: {
|
||||
dictionary: require('jsdoc/tag/dictionary'),
|
||||
validator: require('jsdoc/tag/validator'),
|
||||
type: require('jsdoc/tag/type')
|
||||
}
|
||||
};
|
||||
|
||||
this.originalTitle = trim(tagTitle);
|
||||
/**
|
||||
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
|
||||
*/
|
||||
exports.Tag = function(tagTitle, tagBody, meta) {
|
||||
var tagDef = jsdoc.tag.dictionary.lookUp(tagTitle),
|
||||
meta = meta || {};
|
||||
|
||||
/** The title part of the tag: @title text */
|
||||
this.title = jsdoc.tag.dictionary.normalise( this.originalTitle );
|
||||
this.originalTitle = trim(tagTitle);
|
||||
|
||||
/** The text part of the tag: @title text */
|
||||
this.text = trim(tagBody, tagDef.keepsWhitespace);
|
||||
/** The title part of the tag: @title text */
|
||||
this.title = jsdoc.tag.dictionary.normalise( this.originalTitle );
|
||||
|
||||
if (this.text) {
|
||||
/** The text part of the tag: @title text */
|
||||
this.text = trim(tagBody, tagDef.keepsWhitespace);
|
||||
|
||||
if (tagDef.onTagText) {
|
||||
this.text = tagDef.onTagText(this.text);
|
||||
}
|
||||
if (this.text) {
|
||||
|
||||
if (tagDef.canHaveType) {
|
||||
if (tagDef.onTagText) {
|
||||
this.text = tagDef.onTagText(this.text);
|
||||
}
|
||||
|
||||
/** The value propertiy represents the result of parsing the tag text. */
|
||||
this.value = {};
|
||||
if (tagDef.canHaveType) {
|
||||
|
||||
var [
|
||||
/*Array.<string>*/ typeNames,
|
||||
/*any*/ remainingText,
|
||||
/*?boolean*/ optional,
|
||||
/*?boolean*/ nullable,
|
||||
/*?boolean*/ variable
|
||||
] = jsdoc.tag.type.parse(this.text);
|
||||
/** The value propertiy represents the result of parsing the tag text. */
|
||||
this.value = {};
|
||||
|
||||
if (typeNames.length) {
|
||||
this.value.type = {
|
||||
names: typeNames,
|
||||
optional: optional,
|
||||
nullable: nullable,
|
||||
variable: variable
|
||||
};
|
||||
var [
|
||||
/*Array.<string>*/ typeNames,
|
||||
/*any*/ remainingText,
|
||||
/*?boolean*/ optional,
|
||||
/*?boolean*/ nullable,
|
||||
/*?boolean*/ variable
|
||||
] = jsdoc.tag.type.parse(this.text);
|
||||
|
||||
if (typeNames.length) {
|
||||
this.value.type = {
|
||||
names: typeNames,
|
||||
optional: optional,
|
||||
nullable: nullable,
|
||||
variable: variable
|
||||
};
|
||||
}
|
||||
|
||||
if (remainingText) {
|
||||
if (tagDef.canHaveName) {
|
||||
var [paramName, paramDesc, paramOptional, paramDefault]
|
||||
= parseParamText(remainingText);
|
||||
|
||||
// note the dash is a special case: as a param name it means "no name"
|
||||
if (paramName && paramName !== '-') { this.value.name = paramName; }
|
||||
|
||||
if (paramDesc) { this.value.description = paramDesc; }
|
||||
if (paramOptional) { this.value.optional = paramOptional; }
|
||||
if (paramDefault) { this.value.defaultvalue = paramDefault; }
|
||||
}
|
||||
|
||||
if (remainingText) {
|
||||
if (tagDef.canHaveName) {
|
||||
var [paramName, paramDesc, paramOptional, paramDefault]
|
||||
= parseParamText(remainingText);
|
||||
|
||||
// note the dash is a special case: as a param name it means "no name"
|
||||
if (paramName && paramName !== '-') { this.value.name = paramName; }
|
||||
|
||||
if (paramDesc) { this.value.description = paramDesc; }
|
||||
if (paramOptional) { this.value.optional = paramOptional; }
|
||||
if (paramDefault) { this.value.defaultvalue = paramDefault; }
|
||||
}
|
||||
else {
|
||||
this.value.description = remainingText;
|
||||
}
|
||||
else {
|
||||
this.value.description = remainingText;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.value = this.text;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.value = this.text;
|
||||
}
|
||||
}
|
||||
|
||||
jsdoc.tag.validator.validate(this, meta);
|
||||
jsdoc.tag.validator.validate(this, meta);
|
||||
}
|
||||
|
||||
function trim(text, newlines) {
|
||||
if (!text) { return ''; }
|
||||
|
||||
if (newlines) {
|
||||
return text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');
|
||||
}
|
||||
|
||||
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, '');
|
||||
}
|
||||
else {
|
||||
return text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Parse the parameter name and parameter desc from the tag text.
|
||||
@inner
|
||||
@method parseParamText
|
||||
@memberof module:jsdoc/tag
|
||||
@param {string} tagText
|
||||
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
||||
*/
|
||||
function parseParamText(tagText) {
|
||||
var pname, pdesc, poptional, pdefault;
|
||||
/**
|
||||
Parse the parameter name and parameter desc from the tag text.
|
||||
@inner
|
||||
@method parseParamText
|
||||
@memberof module:jsdoc/tag
|
||||
@param {string} tagText
|
||||
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
||||
*/
|
||||
function parseParamText(tagText) {
|
||||
var pname, pdesc, poptional, pdefault;
|
||||
|
||||
// like: pname, pname pdesc, or name - pdesc
|
||||
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
||||
// like: pname, pname pdesc, or name - pdesc
|
||||
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
||||
pname = RegExp.$1;
|
||||
pdesc = RegExp.$3;
|
||||
|
||||
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
||||
pname = RegExp.$1;
|
||||
pdesc = RegExp.$3;
|
||||
poptional = true;
|
||||
|
||||
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
||||
if ( /^(.+?)\s*=\s*(.+)$/.test(pname) ) {
|
||||
pname = RegExp.$1;
|
||||
poptional = true;
|
||||
|
||||
if ( /^(.+?)\s*=\s*(.+)$/.test(pname) ) {
|
||||
pname = RegExp.$1;
|
||||
pdefault = RegExp.$2;
|
||||
}
|
||||
pdefault = RegExp.$2;
|
||||
}
|
||||
return [pname, pdesc, poptional, pdefault];
|
||||
}
|
||||
|
||||
})();
|
||||
return [pname, pdesc, poptional, pdefault];
|
||||
}
|
||||
|
||||
@ -3,71 +3,74 @@
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
(function() {
|
||||
var _synonyms = {},
|
||||
_definitions = {},
|
||||
_namespaces = [];
|
||||
|
||||
function _TagDefinition(title, etc) {
|
||||
etc = etc || {};
|
||||
var _synonyms = {},
|
||||
_definitions = {},
|
||||
_namespaces = [];
|
||||
|
||||
this.title = dictionary.normalise(title);
|
||||
function _TagDefinition(title, etc) {
|
||||
etc = etc || {};
|
||||
|
||||
for (var p in etc) {
|
||||
if (etc.hasOwnProperty(p)) {
|
||||
this[p] = etc[p];
|
||||
}
|
||||
this.title = dictionary.normalise(title);
|
||||
|
||||
for (var p in etc) {
|
||||
if (etc.hasOwnProperty(p)) {
|
||||
this[p] = etc[p];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_TagDefinition.prototype.synonym = function(synonymName) {
|
||||
_synonyms[synonymName.toLowerCase()] = this.title;
|
||||
return this; // chainable
|
||||
}
|
||||
_TagDefinition.prototype.synonym = function(synonymName) {
|
||||
_synonyms[synonymName.toLowerCase()] = this.title;
|
||||
return this; // chainable
|
||||
}
|
||||
|
||||
/** @exports jsdoc/tag/dictionary */
|
||||
var dictionary = {
|
||||
/** @function */
|
||||
defineTag: function(title, opts) {
|
||||
_definitions[title] = new _TagDefinition(title, opts);
|
||||
/** @exports jsdoc/tag/dictionary */
|
||||
var dictionary = {
|
||||
/** @function */
|
||||
defineTag: function(title, opts) {
|
||||
_definitions[title] = new _TagDefinition(title, opts);
|
||||
|
||||
if (opts.isNamespace) {
|
||||
_namespaces.push(title);
|
||||
}
|
||||
|
||||
return _definitions[title];
|
||||
},
|
||||
|
||||
/** @function */
|
||||
lookUp: function(title) {
|
||||
title = dictionary.normalise(title);
|
||||
|
||||
if ( _definitions.hasOwnProperty(title) ) {
|
||||
return _definitions[title];
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/** @function */
|
||||
isNamespace: function(kind) {
|
||||
return ( ~ _namespaces.indexOf(kind) );
|
||||
},
|
||||
|
||||
/** @function */
|
||||
normalise: function(title) {
|
||||
canonicalName = title.toLowerCase();
|
||||
|
||||
if ( _synonyms.hasOwnProperty(canonicalName) ) {
|
||||
return _synonyms[canonicalName];
|
||||
}
|
||||
|
||||
return canonicalName;
|
||||
if (opts.isNamespace) {
|
||||
_namespaces.push(title);
|
||||
}
|
||||
};
|
||||
|
||||
require('jsdoc/tag/dictionary/definitions').defineTags(dictionary);
|
||||
return _definitions[title];
|
||||
},
|
||||
|
||||
module.exports = dictionary;
|
||||
/** @function */
|
||||
lookUp: function(title) {
|
||||
title = dictionary.normalise(title);
|
||||
|
||||
if ( _definitions.hasOwnProperty(title) ) {
|
||||
return _definitions[title];
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
/** @function */
|
||||
isNamespace: function(kind) {
|
||||
return ( ~ _namespaces.indexOf(kind) );
|
||||
},
|
||||
|
||||
/** @function */
|
||||
normalise: function(title) {
|
||||
canonicalName = title.toLowerCase();
|
||||
|
||||
if ( _synonyms.hasOwnProperty(canonicalName) ) {
|
||||
return _synonyms[canonicalName];
|
||||
}
|
||||
|
||||
return canonicalName;
|
||||
}
|
||||
};
|
||||
|
||||
require('jsdoc/tag/dictionary/definitions').defineTags(dictionary);
|
||||
|
||||
for (var prop in dictionary) {
|
||||
if (dictionary.hasOwnProperty(prop)) {
|
||||
exports[prop] = dictionary[prop];
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
File diff suppressed because it is too large
Load Diff
@ -5,109 +5,107 @@
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
/**
|
||||
@param {string} tagValue
|
||||
@returns {Array.<string>}
|
||||
*/
|
||||
exports.parse = function(tagValue) {
|
||||
if (typeof tagValue !== 'string') { tagValue = ''; }
|
||||
var type = '',
|
||||
text = '',
|
||||
count = 0,
|
||||
optional,
|
||||
nullable,
|
||||
variable;
|
||||
/**
|
||||
@param {string} tagValue
|
||||
@returns {Array.<string>}
|
||||
*/
|
||||
exports.parse = function(tagValue) {
|
||||
if (typeof tagValue !== 'string') { tagValue = ''; }
|
||||
var type = '',
|
||||
text = '',
|
||||
count = 0,
|
||||
optional,
|
||||
nullable,
|
||||
variable;
|
||||
|
||||
// type expressions start with '{'
|
||||
if (tagValue[0] === '{') {
|
||||
count++;
|
||||
// type expressions start with '{'
|
||||
if (tagValue[0] === '{') {
|
||||
count++;
|
||||
|
||||
// find matching closer '}'
|
||||
for (var i = 1, leni = tagValue.length; i < leni; i++) {
|
||||
if (tagValue[i] === '\\') { i++; continue; } // backslash escapes the next character
|
||||
// find matching closer '}'
|
||||
for (var i = 1, leni = tagValue.length; i < leni; i++) {
|
||||
if (tagValue[i] === '\\') { i++; continue; } // backslash escapes the next character
|
||||
|
||||
if (tagValue[i] === '{') { count++; }
|
||||
else if (tagValue[i] === '}') { count--; }
|
||||
if (tagValue[i] === '{') { count++; }
|
||||
else if (tagValue[i] === '}') { count--; }
|
||||
|
||||
if (count === 0) {
|
||||
type = trim(tagValue.slice(1, i))
|
||||
.replace(/\\\{/g, '{') // unescape escaped curly braces
|
||||
.replace(/\\\}/g, '}');
|
||||
text = trim(tagValue.slice(i+1));
|
||||
break;
|
||||
}
|
||||
if (count === 0) {
|
||||
type = trim(tagValue.slice(1, i))
|
||||
.replace(/\\\{/g, '{') // unescape escaped curly braces
|
||||
.replace(/\\\}/g, '}');
|
||||
text = trim(tagValue.slice(i+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (type === '') { text = tagValue; }
|
||||
|
||||
[type, optional] = parseOptional(type);
|
||||
[type, nullable] = parseNullable(type);
|
||||
[type, variable] = parseVariable(type);
|
||||
|
||||
type = parseTypes(type); // make it into an array
|
||||
|
||||
return [type, text, optional, nullable, variable];
|
||||
}
|
||||
|
||||
function parseOptional(type) {
|
||||
var optional = null;
|
||||
if (type === '') { text = tagValue; }
|
||||
|
||||
// {sometype=} means optional
|
||||
if ( /(.+)=$/.test(type) ) {
|
||||
[type, optional] = parseOptional(type);
|
||||
[type, nullable] = parseNullable(type);
|
||||
[type, variable] = parseVariable(type);
|
||||
|
||||
type = parseTypes(type); // make it into an array
|
||||
|
||||
return [type, text, optional, nullable, variable];
|
||||
}
|
||||
|
||||
function parseOptional(type) {
|
||||
var optional = null;
|
||||
|
||||
// {sometype=} means optional
|
||||
if ( /(.+)=$/.test(type) ) {
|
||||
type = RegExp.$1;
|
||||
optional = true;
|
||||
}
|
||||
|
||||
return [type, optional];
|
||||
}
|
||||
|
||||
function parseNullable(type) {
|
||||
var nullable = null;
|
||||
|
||||
// {?sometype} means nullable, {!sometype} means not-nullable
|
||||
if ( /^([\?\!])(.+)$/.test(type) ) {
|
||||
type = RegExp.$2;
|
||||
nullable = (RegExp.$1 === '?')? true : false;
|
||||
}
|
||||
|
||||
return [type, nullable];
|
||||
}
|
||||
|
||||
function parseVariable(type) {
|
||||
var variable = null;
|
||||
|
||||
// {...sometype} means variable number of that type
|
||||
if ( /^(\.\.\.)(.+)$/.test(type) ) {
|
||||
type = RegExp.$2;
|
||||
variable = true;
|
||||
}
|
||||
|
||||
return [type, variable];
|
||||
}
|
||||
|
||||
function parseTypes(type) {
|
||||
var types = [];
|
||||
|
||||
if ( ~type.indexOf('|') ) {
|
||||
// remove optional parens, like: { ( string | number ) }
|
||||
// see: http://code.google.com/closure/compiler/docs/js-for-compiler.html#types
|
||||
if ( /^\s*\(\s*(.+)\s*\)\s*$/.test(type) ) {
|
||||
type = RegExp.$1;
|
||||
optional = true;
|
||||
}
|
||||
|
||||
return [type, optional];
|
||||
types = type.split(/\s*\|\s*/g);
|
||||
}
|
||||
else if (type) {
|
||||
types = [type];
|
||||
}
|
||||
|
||||
function parseNullable(type) {
|
||||
var nullable = null;
|
||||
return types;
|
||||
}
|
||||
|
||||
// {?sometype} means nullable, {!sometype} means not-nullable
|
||||
if ( /^([\?\!])(.+)$/.test(type) ) {
|
||||
type = RegExp.$2;
|
||||
nullable = (RegExp.$1 === '?')? true : false;
|
||||
}
|
||||
|
||||
return [type, nullable];
|
||||
}
|
||||
|
||||
function parseVariable(type) {
|
||||
var variable = null;
|
||||
|
||||
// {...sometype} means variable number of that type
|
||||
if ( /^(\.\.\.)(.+)$/.test(type) ) {
|
||||
type = RegExp.$2;
|
||||
variable = true;
|
||||
}
|
||||
|
||||
return [type, variable];
|
||||
}
|
||||
|
||||
function parseTypes(type) {
|
||||
var types = [];
|
||||
|
||||
if ( ~type.indexOf('|') ) {
|
||||
// remove optional parens, like: { ( string | number ) }
|
||||
// see: http://code.google.com/closure/compiler/docs/js-for-compiler.html#types
|
||||
if ( /^\s*\(\s*(.+)\s*\)\s*$/.test(type) ) {
|
||||
type = RegExp.$1;
|
||||
}
|
||||
types = type.split(/\s*\|\s*/g);
|
||||
}
|
||||
else if (type) {
|
||||
types = [type];
|
||||
}
|
||||
|
||||
return types;
|
||||
}
|
||||
|
||||
/** @private */
|
||||
function trim(text) {
|
||||
return text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
})();
|
||||
/** @private */
|
||||
function trim(text) {
|
||||
return text.replace(/^\s+|\s+$/g, '');
|
||||
}
|
||||
|
||||
@ -5,48 +5,47 @@
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
(function() {
|
||||
|
||||
var dictionary = require('jsdoc/tag/dictionary');
|
||||
|
||||
/**
|
||||
Validate the given tag.
|
||||
*/
|
||||
exports.validate = function(tag, meta) {
|
||||
var tagDef = dictionary.lookUp(tag.title);
|
||||
var dictionary = require('jsdoc/tag/dictionary');
|
||||
|
||||
if (!tagDef && !env.conf.tags.allowUnknownTags) {
|
||||
throw new UnknownTagError(tag.title, meta);
|
||||
}
|
||||
/**
|
||||
Validate the given tag.
|
||||
*/
|
||||
exports.validate = function(tag, meta) {
|
||||
var tagDef = dictionary.lookUp(tag.title);
|
||||
|
||||
if (!tag.text) {
|
||||
if (tagDef.mustHaveValue) {
|
||||
throw new TagValueRequiredError(tag.title, meta);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (tagDef.mustNotHaveValue) {
|
||||
throw new TagValueNotPermittedError(tag.title, meta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function UnknownTagError(tagName, meta) {
|
||||
this.name = 'UnknownTagError';
|
||||
this.message = 'The @' + tagName + ' tag is not a known tag. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||
if (!tagDef && !env.conf.tags.allowUnknownTags) {
|
||||
throw new UnknownTagError(tag.title, meta);
|
||||
}
|
||||
UnknownTagError.prototype = Error.prototype;
|
||||
|
||||
function TagValueRequiredError(tagName, meta) {
|
||||
this.name = 'TagValueRequiredError';
|
||||
this.message = 'The @' + tagName + ' tag requires a value. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||
if (!tag.text) {
|
||||
if (tagDef.mustHaveValue) {
|
||||
throw new TagValueRequiredError(tag.title, meta);
|
||||
}
|
||||
}
|
||||
TagValueRequiredError.prototype = Error.prototype;
|
||||
|
||||
function TagValueNotPermittedError(tagName, message, meta) {
|
||||
this.name = 'TagValueNotPermittedError';
|
||||
this.message = 'The @' + tagName + ' tag does not permit a value: "' + message + '". File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||
else {
|
||||
if (tagDef.mustNotHaveValue) {
|
||||
throw new TagValueNotPermittedError(tag.title, meta);
|
||||
}
|
||||
}
|
||||
TagValueNotPermittedError.prototype = Error.prototype;
|
||||
}
|
||||
|
||||
function UnknownTagError(tagName, meta) {
|
||||
this.name = 'UnknownTagError';
|
||||
this.message = 'The @' + tagName + ' tag is not a known tag. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||
}
|
||||
UnknownTagError.prototype = Error.prototype;
|
||||
|
||||
function TagValueRequiredError(tagName, meta) {
|
||||
this.name = 'TagValueRequiredError';
|
||||
this.message = 'The @' + tagName + ' tag requires a value. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||
}
|
||||
TagValueRequiredError.prototype = Error.prototype;
|
||||
|
||||
function TagValueNotPermittedError(tagName, message, meta) {
|
||||
this.name = 'TagValueNotPermittedError';
|
||||
this.message = 'The @' + tagName + ' tag does not permit a value: "' + message + '". File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||
}
|
||||
TagValueNotPermittedError.prototype = Error.prototype;
|
||||
|
||||
})();
|
||||
@ -4,155 +4,154 @@
|
||||
@author Michael Mathews <micmath@gmail.com>
|
||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||
*/
|
||||
(function() {
|
||||
/**
|
||||
@param {any} object
|
||||
*/
|
||||
exports.dump = function(object) {
|
||||
indentBy = 0;
|
||||
output = '';
|
||||
|
||||
walk(object);
|
||||
outdent(false);
|
||||
return output;
|
||||
/**
|
||||
@param {any} object
|
||||
*/
|
||||
exports.dump = function(object) {
|
||||
indentBy = 0;
|
||||
output = '';
|
||||
|
||||
walk(object);
|
||||
outdent(false);
|
||||
return output;
|
||||
}
|
||||
|
||||
const INDENTATION = ' '; // 4 spaces
|
||||
var indentBy,
|
||||
output;
|
||||
|
||||
function pad(depth) {
|
||||
var padding = '';
|
||||
while (depth--) {
|
||||
padding += INDENTATION;
|
||||
}
|
||||
return padding;
|
||||
}
|
||||
|
||||
const INDENTATION = ' '; // 4 spaces
|
||||
var indentBy,
|
||||
output;
|
||||
/**
|
||||
@param {string} openingBrace - The opening brace to add, like "{".
|
||||
@private
|
||||
@inner
|
||||
@memberof module:common/dumper
|
||||
*/
|
||||
function indent(openingBrace) {
|
||||
indentBy++;
|
||||
if (openingBrace) output += openingBrace + '\n';
|
||||
}
|
||||
|
||||
function pad(depth) {
|
||||
var padding = '';
|
||||
while (depth--) {
|
||||
padding += INDENTATION;
|
||||
}
|
||||
return padding;
|
||||
/**
|
||||
@param {string|boolean} closingBrace - The closing brace to add, like "}" or if boolean
|
||||
`false` no closing brace or trailing newline.
|
||||
@private
|
||||
@inner
|
||||
@memberof module:common/dumper
|
||||
*/
|
||||
function outdent(closingBrace) {
|
||||
indentBy--;
|
||||
output = output.replace(/,\n$/, '\n'); // trim trailing comma
|
||||
if (closingBrace === false) { output = output.replace(/\n$/, ''); }
|
||||
else if (closingBrace) output += pad(indentBy) + closingBrace + ',\n';
|
||||
}
|
||||
|
||||
var seen = [];
|
||||
seen.has = function(object) {
|
||||
for (var i = 0, l = seen.length; i < l; i++) {
|
||||
if (seen[i] === object) { return true; }
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@param {string} openingBrace - The opening brace to add, like "{".
|
||||
@private
|
||||
@inner
|
||||
@memberof module:common/dumper
|
||||
*/
|
||||
function indent(openingBrace) {
|
||||
indentBy++;
|
||||
if (openingBrace) output += openingBrace + '\n';
|
||||
function walk(object) {
|
||||
var value;
|
||||
|
||||
if ( value = getValue(object) ) {
|
||||
output += value + ',\n';
|
||||
}
|
||||
|
||||
/**
|
||||
@param {string|boolean} closingBrace - The closing brace to add, like "}" or if boolean
|
||||
`false` no closing brace or trailing newline.
|
||||
@private
|
||||
@inner
|
||||
@memberof module:common/dumper
|
||||
*/
|
||||
function outdent(closingBrace) {
|
||||
indentBy--;
|
||||
output = output.replace(/,\n$/, '\n'); // trim trailing comma
|
||||
if (closingBrace === false) { output = output.replace(/\n$/, ''); }
|
||||
else if (closingBrace) output += pad(indentBy) + closingBrace + ',\n';
|
||||
else if ( isUnwalkable(object) ) {
|
||||
output += '<Object>,\n'
|
||||
}
|
||||
|
||||
var seen = [];
|
||||
seen.has = function(object) {
|
||||
for (var i = 0, l = seen.length; i < l; i++) {
|
||||
if (seen[i] === object) { return true; }
|
||||
}
|
||||
return false;
|
||||
else if ( isRegExp(object) ) {
|
||||
output += '<RegExp ' + object + '>,\n'
|
||||
}
|
||||
else if ( isDate(object) ) {
|
||||
output += '<Date ' + object.toUTCString() + '>,\n'
|
||||
}
|
||||
else if ( isFunction(object) ) {
|
||||
output += '<Function' + (object.name? ' '+ object.name : '') + '>,\n';
|
||||
}
|
||||
else if ( isArray(object) ) {
|
||||
if ( seen.has(object) ) {
|
||||
output += '<CircularRef>,\n';
|
||||
return;
|
||||
}
|
||||
else {
|
||||
seen.push(object);
|
||||
}
|
||||
|
||||
function walk(object) {
|
||||
var value;
|
||||
indent('[');
|
||||
for (var i = 0, leni = object.length; i < leni; i++) {
|
||||
output += pad(indentBy); // + i + ': ';
|
||||
walk( object[i] );
|
||||
}
|
||||
outdent(']');
|
||||
}
|
||||
else if ( isObject(object) ) {
|
||||
if ( seen.has(object) ) {
|
||||
output += '<CircularRef>,\n';
|
||||
return;
|
||||
}
|
||||
else {
|
||||
seen.push(object);
|
||||
}
|
||||
|
||||
if ( value = getValue(object) ) {
|
||||
output += value + ',\n';
|
||||
}
|
||||
else if ( isUnwalkable(object) ) {
|
||||
output += '<Object>,\n'
|
||||
}
|
||||
else if ( isRegExp(object) ) {
|
||||
output += '<RegExp ' + object + '>,\n'
|
||||
}
|
||||
else if ( isDate(object) ) {
|
||||
output += '<Date ' + object.toUTCString() + '>,\n'
|
||||
}
|
||||
else if ( isFunction(object) ) {
|
||||
output += '<Function' + (object.name? ' '+ object.name : '') + '>,\n';
|
||||
}
|
||||
else if ( isArray(object) ) {
|
||||
if ( seen.has(object) ) {
|
||||
output += '<CircularRef>,\n';
|
||||
return;
|
||||
indent('{');
|
||||
for (var p in object) {
|
||||
if ( object.hasOwnProperty(p) ) {
|
||||
output += pad(indentBy) + stringify(p) + ': ';
|
||||
walk( object[p] );
|
||||
}
|
||||
else {
|
||||
seen.push(object);
|
||||
}
|
||||
|
||||
indent('[');
|
||||
for (var i = 0, leni = object.length; i < leni; i++) {
|
||||
output += pad(indentBy); // + i + ': ';
|
||||
walk( object[i] );
|
||||
}
|
||||
outdent(']');
|
||||
}
|
||||
else if ( isObject(object) ) {
|
||||
if ( seen.has(object) ) {
|
||||
output += '<CircularRef>,\n';
|
||||
return;
|
||||
}
|
||||
else {
|
||||
seen.push(object);
|
||||
}
|
||||
|
||||
indent('{');
|
||||
for (var p in object) {
|
||||
if ( object.hasOwnProperty(p) ) {
|
||||
output += pad(indentBy) + stringify(p) + ': ';
|
||||
walk( object[p] );
|
||||
}
|
||||
}
|
||||
outdent('}');
|
||||
}
|
||||
outdent('}');
|
||||
}
|
||||
}
|
||||
|
||||
function getValue(o) { // see: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof
|
||||
if (o === null) { return 'null'; }
|
||||
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
|
||||
return ''+stringify(o);
|
||||
}
|
||||
function getValue(o) { // see: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof
|
||||
if (o === null) { return 'null'; }
|
||||
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
|
||||
return ''+stringify(o);
|
||||
}
|
||||
}
|
||||
|
||||
function stringify(o) {
|
||||
return JSON.stringify(o);
|
||||
}
|
||||
function stringify(o) {
|
||||
return JSON.stringify(o);
|
||||
}
|
||||
|
||||
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
|
||||
return (typeof o === 'object' && typeof o.constructor === 'undefined');
|
||||
}
|
||||
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
|
||||
return (typeof o === 'object' && typeof o.constructor === 'undefined');
|
||||
}
|
||||
|
||||
function isArray(o) {
|
||||
return o && (o instanceof Array) || o.constructor === Array;
|
||||
}
|
||||
function isArray(o) {
|
||||
return o && (o instanceof Array) || o.constructor === Array;
|
||||
}
|
||||
|
||||
function isRegExp(o) {
|
||||
return (o instanceof RegExp) ||
|
||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
|
||||
}
|
||||
function isRegExp(o) {
|
||||
return (o instanceof RegExp) ||
|
||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
|
||||
}
|
||||
|
||||
function isDate(o) {
|
||||
return o && (o instanceof Date) ||
|
||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
|
||||
}
|
||||
function isDate(o) {
|
||||
return o && (o instanceof Date) ||
|
||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
|
||||
}
|
||||
|
||||
function isFunction(o) {
|
||||
return o && (typeof o === 'function' || o instanceof Function);// ||
|
||||
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
|
||||
}
|
||||
function isFunction(o) {
|
||||
return o && (typeof o === 'function' || o instanceof Function);// ||
|
||||
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
|
||||
}
|
||||
|
||||
function isObject(o) {
|
||||
return o && o instanceof Object ||
|
||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
|
||||
}
|
||||
function isObject(o) {
|
||||
return o && o instanceof Object ||
|
||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
|
||||
}
|
||||
|
||||
})();
|
||||
17
rhino_modules/path.js
Normal file
17
rhino_modules/path.js
Normal file
@ -0,0 +1,17 @@
|
||||
|
||||
exports.basename = function(path) {
|
||||
var parts = path.split('/');
|
||||
parts.pop();
|
||||
path = parts.join('/');
|
||||
return path;
|
||||
};
|
||||
|
||||
exports.existsSync = function(path) {
|
||||
var file = new java.io.File(path);
|
||||
|
||||
if (file.isFile()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
@ -1,18 +0,0 @@
|
||||
|
||||
module.exports = {
|
||||
basename : function(path) {
|
||||
var parts = path.split('/');
|
||||
parts.pop();
|
||||
path = parts.join('/');
|
||||
return path;
|
||||
},
|
||||
existsSync: function(path) {
|
||||
var file = new java.io.File(path);
|
||||
|
||||
if (file.isFile()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
4
rhino_modules/sys.js
Normal file
4
rhino_modules/sys.js
Normal file
@ -0,0 +1,4 @@
|
||||
|
||||
exports.puts = function(str) {
|
||||
print(String(str));
|
||||
};
|
||||
@ -1,6 +0,0 @@
|
||||
|
||||
module.exports = {
|
||||
'puts' : function(str) {
|
||||
print(String(str));
|
||||
}
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user