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
|
# rhino discards the path to the current script file, so we must add it back
|
||||||
PWD=`pwd`
|
PWD=`pwd`
|
||||||
BASEDIR=`dirname $0`
|
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} $@
|
#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');
|
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';
|
encoding = encoding || 'utf-8';
|
||||||
|
|
||||||
return readFile(filename, encoding);
|
return readFile(filename, encoding);
|
||||||
}
|
};
|
||||||
|
|
||||||
function readdirSync(path) {
|
var readdirSync = exports.readdirSync = function(path) {
|
||||||
var dir,
|
var dir,
|
||||||
files;
|
files;
|
||||||
|
|
||||||
@ -14,9 +14,9 @@ function readdirSync(path) {
|
|||||||
files = dir.list();
|
files = dir.list();
|
||||||
|
|
||||||
return files;
|
return files;
|
||||||
}
|
};
|
||||||
|
|
||||||
function ls(dir, recurse, _allFiles, _path) {
|
var ls = exports.ls = function(dir, recurse, _allFiles, _path) {
|
||||||
var files,
|
var files,
|
||||||
file;
|
file;
|
||||||
|
|
||||||
@ -56,9 +56,9 @@ function ls(dir, recurse, _allFiles, _path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return _allFiles;
|
return _allFiles;
|
||||||
}
|
};
|
||||||
|
|
||||||
function stat(path, encoding) {
|
var stat = exports.stat = function(path, encoding) {
|
||||||
var f = new java.io.File(path)
|
var f = new java.io.File(path)
|
||||||
return {
|
return {
|
||||||
isFile: function() {
|
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(/[\\\/]/);
|
if (path.constructor != Array) path = path.split(/[\\\/]/);
|
||||||
var make = "";
|
var make = "";
|
||||||
for (var i = 0, l = path.length; i < l; i++) {
|
for (var i = 0, l = path.length; i < l; i++) {
|
||||||
@ -80,7 +80,7 @@ function mkPath(/**Array*/ path) {
|
|||||||
makeDir(make);
|
makeDir(make);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
function makeDir(/**string*/ path) {
|
function makeDir(/**string*/ path) {
|
||||||
var dirPath = toDir(path);
|
var dirPath = toDir(path);
|
||||||
@ -102,7 +102,7 @@ function exists(path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function toDir(path) {
|
var toDir = exports.toDir = function(path) {
|
||||||
var f = new java.io.File(path);
|
var f = new java.io.File(path);
|
||||||
|
|
||||||
if (f.isDirectory()){
|
if (f.isDirectory()){
|
||||||
@ -113,9 +113,9 @@ function toDir(path) {
|
|||||||
parts.pop();
|
parts.pop();
|
||||||
|
|
||||||
return parts.join('/');
|
return parts.join('/');
|
||||||
}
|
};
|
||||||
|
|
||||||
function copyFile(inFile, outDir, fileName) {
|
exports.copyFile = function(inFile, outDir, fileName) {
|
||||||
if (fileName == null) fileName = toFile(inFile);
|
if (fileName == null) fileName = toFile(inFile);
|
||||||
|
|
||||||
outDir = toDir(outDir);
|
outDir = toDir(outDir);
|
||||||
@ -131,14 +131,14 @@ function copyFile(inFile, outDir, fileName) {
|
|||||||
}
|
}
|
||||||
bos.close();
|
bos.close();
|
||||||
bis.close();
|
bis.close();
|
||||||
}
|
};
|
||||||
|
|
||||||
function toFile(path) {
|
function toFile(path) {
|
||||||
var parts = path.split(/[\\\/]/);
|
var parts = path.split(/[\\\/]/);
|
||||||
return parts.pop();
|
return parts.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeFileSync(filename, data, encoding) {
|
exports.writeFileSync = function(filename, data, encoding) {
|
||||||
encoding = encoding || 'utf-8';
|
encoding = encoding || 'utf-8';
|
||||||
|
|
||||||
var out = new Packages.java.io.PrintWriter(
|
var out = new Packages.java.io.PrintWriter(
|
||||||
@ -155,16 +155,4 @@ function writeFileSync(filename, data, encoding) {
|
|||||||
out.flush();
|
out.flush();
|
||||||
out.close();
|
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>
|
@author Michael Mathews <micmath@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@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
|
// 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
|
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,
|
docs for the borrowing symbol. This process changes the symbols involved,
|
||||||
moving docs from the "borrowed" array and into the general docs, then
|
moving docs from the "borrowed" array and into the general docs, then
|
||||||
deleting the "borrowed" array.
|
deleting the "borrowed" array.
|
||||||
*/
|
*/
|
||||||
exports.resolveBorrows = function(docs) {
|
exports.resolveBorrows = function(docs) {
|
||||||
if (!docs.index) {
|
if (!docs.index) {
|
||||||
throw 'Docs has not been indexed: docs.index must be defined here.';
|
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
docs.forEach(function(doc) {
|
||||||
Deep clone a simple object.
|
if (doc.borrowed) {
|
||||||
@private
|
doc.borrowed.forEach(function(b, i) {
|
||||||
*/
|
var lent = docs.index[b.from], // lent is an array
|
||||||
function doop(o) {
|
asName = b['as'] || b.from;
|
||||||
if (o instanceof Object && o.constructor != Function) {
|
|
||||||
var clone = o instanceof Array ? [] : {}, prop;
|
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/name
|
||||||
@requires jsdoc/tag/dictionary
|
@requires jsdoc/tag/dictionary
|
||||||
*/
|
*/
|
||||||
(function() {
|
|
||||||
var jsdoc = {
|
|
||||||
tag: {
|
|
||||||
Tag: require('jsdoc/tag').Tag,
|
|
||||||
dictionary: require('jsdoc/tag/dictionary')
|
|
||||||
},
|
|
||||||
name: require('jsdoc/name')
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
var jsdoc = {
|
||||||
@class
|
tag: {
|
||||||
@classdesc Represents a single JSDoc comment.
|
Tag: require('jsdoc/tag').Tag,
|
||||||
@param {string} docletSrc - The raw source code of the jsdoc comment.
|
dictionary: require('jsdoc/tag/dictionary')
|
||||||
@param {object=} meta - Properties describing the code related to this comment.
|
},
|
||||||
*/
|
name: require('jsdoc/name')
|
||||||
exports.Doclet = function(docletSrc, meta) {
|
};
|
||||||
var newTags = [];
|
|
||||||
|
|
||||||
/** The original text of the comment from the source code. */
|
/**
|
||||||
this.comment = docletSrc;
|
@class
|
||||||
this.setMeta(meta);
|
@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);
|
/** The original text of the comment from the source code. */
|
||||||
docletSrc = fixDescription(docletSrc);
|
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++) {
|
newTags = toTags.call(this, docletSrc);
|
||||||
this.addTag(newTags[i].title, newTags[i].text);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.postProcess();
|
for (var i = 0, leni = newTags.length; i < leni; i++) {
|
||||||
}
|
this.addTag(newTags[i].title, newTags[i].text);
|
||||||
|
|
||||||
/** 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
this.postProcess();
|
||||||
Convert the raw source of the doclet comment into an array of Tag objects.
|
}
|
||||||
@private
|
|
||||||
*/
|
|
||||||
function toTags(docletSrc) {
|
|
||||||
var tagSrcs,
|
|
||||||
tags = [];
|
|
||||||
|
|
||||||
docletSrc = unwrap(docletSrc);
|
/** Called once after all tags have been added. */
|
||||||
tagSrcs = split(docletSrc);
|
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) {
|
/** Add a tag to this doclet.
|
||||||
tags.push( {title: tagSrc.title, text: tagSrc.text} );
|
@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) {
|
function split(docletSrc) {
|
||||||
if (!docletSrc) { return ''; }
|
var tagSrcs = [];
|
||||||
|
|
||||||
// note: keep trailing whitespace for @examples
|
// split out the basic tags, keep surrounding whitespace
|
||||||
// extra opening/closing stars are ignored
|
// like: @tagTitle tagBody
|
||||||
// left margin is considered a star and a space
|
docletSrc
|
||||||
// use the /m flag on regex to avoid having to guess what this platform's newline is
|
.replace(/^(\s*)@(\S)/gm, '$1\\@$2') // replace splitter ats with an arbitrary sequence
|
||||||
docletSrc =
|
.split('\\@') // then split on that arbitrary sequence
|
||||||
docletSrc.replace(/^\/\*\*+/, '') // remove opening slash+stars
|
.forEach(function($) {
|
||||||
.replace(/\**\*\/$/, "\\Z") // replace closing star slash with end-marker
|
if ($) {
|
||||||
.replace(/^\s*(\* ?|\\Z)/gm, '') // remove left margin like: spaces+star or spaces+end-marker
|
var parsedTag = $.match(/^(\S+)(:?\s+(\S[\s\S]*))?/);
|
||||||
.replace(/\s*\\Z$/g, ''); // remove end-marker
|
|
||||||
|
|
||||||
return docletSrc;
|
if (parsedTag) {
|
||||||
}
|
var [, tagTitle, tagText] = parsedTag;
|
||||||
|
|
||||||
function fixDescription(docletSrc) {
|
if (tagTitle) {
|
||||||
if (!/^\s*@/.test(docletSrc)) {
|
tagSrcs.push({
|
||||||
docletSrc = '@description ' + docletSrc;
|
title: tagTitle,
|
||||||
}
|
text: tagText
|
||||||
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
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return tagSrcs;
|
return tagSrcs;
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
|
||||||
|
|||||||
@ -5,178 +5,177 @@
|
|||||||
@author Michael Mathews <micmath@gmail.com>
|
@author Michael Mathews <micmath@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@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' },
|
var jsdoc = {
|
||||||
scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' },
|
tagDictionary: require('jsdoc/tag/dictionary')
|
||||||
Token = Packages.org.mozilla.javascript.Token;
|
};
|
||||||
|
|
||||||
/**
|
var puncToScope = { '.': 'static', '~': 'inner', '#': 'instance' },
|
||||||
Resolves the longname, memberof, variation and name values of the given doclet.
|
scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' },
|
||||||
@param {module:jsdoc/doclet.Doclet} doclet
|
Token = Packages.org.mozilla.javascript.Token;
|
||||||
*/
|
|
||||||
exports.resolve = function(doclet) {
|
|
||||||
var name = doclet.name,
|
|
||||||
memberof = doclet.memberof || '',
|
|
||||||
about = {},
|
|
||||||
parentDoc;
|
|
||||||
|
|
||||||
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?
|
name = name? (''+name).replace(/\.prototype\.?/g, '#') : '';
|
||||||
if (name && !memberof && doclet.meta.code && doclet.meta.code.funcscope) {
|
|
||||||
name = doclet.longname = doclet.meta.code.funcscope + '~' + name;
|
// 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);
|
||||||
}
|
}
|
||||||
|
else if (name && /([#.~])$/.test(memberof) ) { // like @memberof foo# or @memberof foo~
|
||||||
if (memberof) { // @memberof tag given
|
about = exports.shorten(memberof + name);
|
||||||
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 { // no @memberof
|
else if (name && doclet.scope ) { // like @memberof foo# or @memberof foo~
|
||||||
about = exports.shorten(name);
|
about = exports.shorten(memberof + scopeToPunc[doclet.scope] + name);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else { // no @memberof
|
||||||
|
about = exports.shorten(name);
|
||||||
|
}
|
||||||
|
|
||||||
if (about.name) {
|
if (about.name) {
|
||||||
doclet.name = about.name;
|
doclet.name = about.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (about.memberof) {
|
if (about.memberof) {
|
||||||
doclet.setMemberof(about.memberof);
|
doclet.setMemberof(about.memberof);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (about.longname && !doclet.longname) {
|
if (about.longname && !doclet.longname) {
|
||||||
doclet.setLongname(about.longname);
|
doclet.setLongname(about.longname);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doclet.scope === 'global') { // via @global tag?
|
if (doclet.scope === 'global') { // via @global tag?
|
||||||
doclet.setLongname(doclet.name);
|
doclet.setLongname(doclet.name);
|
||||||
delete doclet.memberof;
|
delete doclet.memberof;
|
||||||
}
|
}
|
||||||
else if (about.scope) {
|
else if (about.scope) {
|
||||||
if (about.memberof === '<global>') { // via @memberof <global> ?
|
if (about.memberof === '<global>') { // via @memberof <global> ?
|
||||||
delete doclet.scope;
|
delete doclet.scope;
|
||||||
}
|
|
||||||
else {
|
|
||||||
doclet.scope = puncToScope[about.scope];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (doclet.name && doclet.memberof && !doclet.longname) {
|
doclet.scope = puncToScope[about.scope];
|
||||||
doclet.scope = 'static'; // default scope when none is provided
|
|
||||||
|
|
||||||
doclet.setLongname(doclet.memberof + scopeToPunc[doclet.scope] + doclet.name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (doclet.name && doclet.memberof && !doclet.longname) {
|
||||||
|
doclet.scope = 'static'; // default scope when none is provided
|
||||||
|
|
||||||
if (about.variation) {
|
doclet.setLongname(doclet.memberof + scopeToPunc[doclet.scope] + doclet.name);
|
||||||
doclet.variation = about.variation;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
if (about.variation) {
|
||||||
@inner
|
doclet.variation = about.variation;
|
||||||
@memberof module:jsdoc/name
|
}
|
||||||
@param {string} name
|
}
|
||||||
@param {string} kind
|
|
||||||
@returns {string} The name with unsafe names enclosed in quotes.
|
|
||||||
*/
|
|
||||||
function quoteUnsafe(name, kind) { // docspaced names may have unsafe characters which need to be quoted by us
|
|
||||||
if ( (jsdoc.tagDictionary.lookUp(kind).setsDocletDocspace) && /[^$_a-zA-Z0-9\/]/.test(name) ) {
|
|
||||||
if (!/^[a-z_$-\/]+:\"/i.test(name)) {
|
|
||||||
return '"' + name.replace(/\"/g, '"') + '"';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return name;
|
/**
|
||||||
|
@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) {
|
return name;
|
||||||
var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
|
}
|
||||||
return str.replace(specials, "\\$&");
|
|
||||||
|
RegExp.escape = RegExp.escape || function(str) {
|
||||||
|
var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
|
||||||
|
return str.replace(specials, "\\$&");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@method module:jsdoc/name.applyNamespace
|
||||||
|
@param {string} longname The full longname of the symbol.
|
||||||
|
@param {string} ns The namespace to be applied.
|
||||||
|
@returns {string} The longname with the namespace applied.
|
||||||
|
*/
|
||||||
|
exports.applyNamespace = function(longname, ns) {
|
||||||
|
var nameParts = exports.shorten(longname),
|
||||||
|
name = nameParts.name,
|
||||||
|
longname = nameParts.longname;
|
||||||
|
|
||||||
|
if ( !/^[a-zA-Z]+?:.+$/i.test(name) ) {
|
||||||
|
longname = longname.replace( new RegExp(RegExp.escape(name)+'$'), ns + ':' + name );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return longname;
|
||||||
@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 );
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
//// restore quoted strings back again
|
||||||
Given a longname like "a.b#c(2)", slice it up into ["a.b", "#", 'c', '2'],
|
var i = atoms.length;
|
||||||
representing the memberof, the scope, the name, and variation.
|
while (i--) {
|
||||||
@param {string} longname
|
longname = longname.replace('@{'+i+'}@', atoms[i]);
|
||||||
@returns {object} Representing the properties of the given name.
|
memberof = memberof.replace('@{'+i+'}@', atoms[i]);
|
||||||
*/
|
scope = scope.replace('@{'+i+'}@', atoms[i]);
|
||||||
exports.shorten = function(longname) {
|
name = name.replace('@{'+i+'}@', atoms[i]);
|
||||||
// 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};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
})();
|
////
|
||||||
|
return {longname: longname, memberof: memberof, scope: scope, name: name, variation: variation};
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,70 +4,69 @@
|
|||||||
@author Michael Mathews <micmath@gmail.com>
|
@author Michael Mathews <micmath@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
(function() {
|
|
||||||
var common = {
|
var common = {
|
||||||
args: require('common/args')
|
args: require('common/args')
|
||||||
|
};
|
||||||
|
|
||||||
|
var argParser = new common.args.ArgParser(),
|
||||||
|
ourOptions,
|
||||||
|
defaults = {
|
||||||
|
template: 'default',
|
||||||
|
destination: './out/'
|
||||||
};
|
};
|
||||||
|
|
||||||
var argParser = new common.args.ArgParser(),
|
argParser.addOption('t', 'template', true, 'The name of the template to use. Default: the "default" template');
|
||||||
ourOptions,
|
argParser.addOption('c', 'configure', true, 'The path to the configuration file. Default: jsdoc __dirname + /conf.json');
|
||||||
defaults = {
|
argParser.addOption('e', 'encoding', true, 'Assume this encoding when reading all source files. Default: utf-8');
|
||||||
template: 'default',
|
argParser.addOption('T', 'test', false, 'Run all tests and quit.');
|
||||||
destination: './out/'
|
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('t', 'template', true, 'The name of the template to use. Default: the "default" template');
|
argParser.addOption('X', 'explain', false, 'Dump all found doclet internals to console and quit.');
|
||||||
argParser.addOption('c', 'configure', true, 'The path to the configuration file. Default: jsdoc __dirname + /conf.json');
|
argParser.addOption('q', 'query', true, 'Provide a querystring to define custom variable names/values to add to the options hash.');
|
||||||
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 [-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?
|
// TODO [-f, filter] = a regex to filter on <-- this can be better defined in the configs?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Set the options for this app.
|
Set the options for this app.
|
||||||
@throws {Error} Illegal arguments will throw errors.
|
@throws {Error} Illegal arguments will throw errors.
|
||||||
@param {string|String[]} args The command line arguments for this app.
|
@param {string|String[]} args The command line arguments for this app.
|
||||||
*/
|
*/
|
||||||
exports.parse = function(args) {
|
exports.parse = function(args) {
|
||||||
args = args || [];
|
args = args || [];
|
||||||
|
|
||||||
if (typeof args === 'string' || args.constructor === String) {
|
if (typeof args === 'string' || args.constructor === String) {
|
||||||
args = (''+args).split(/\s+/g);
|
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;
|
return ourOptions;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
/**
|
return ourOptions[name];
|
||||||
Display help message for options.
|
|
||||||
*/
|
|
||||||
exports.help = function() {
|
|
||||||
return argParser.help();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
Get a named option.
|
|
||||||
@param {string} name The name of the option.
|
|
||||||
@return {string} The value associated with the given name.
|
|
||||||
*//**
|
|
||||||
Get all the options for this app.
|
|
||||||
@return {Object} A collection of key/values representing all the options.
|
|
||||||
*/
|
|
||||||
exports.get = function(name) {
|
|
||||||
if (typeof name === 'undefined') {
|
|
||||||
return ourOptions;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return ourOptions[name];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|||||||
@ -8,62 +8,61 @@
|
|||||||
@module jsdoc/package
|
@module jsdoc/package
|
||||||
@see http://wiki.commonjs.org/wiki/Packages/1.0
|
@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
|
@class
|
||||||
@default
|
@classdesc Represents a JavaScript package.
|
||||||
@type {string}
|
@param {string} json - The contents of package.json.
|
||||||
*/
|
*/
|
||||||
this.kind = 'package';
|
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.
|
json = JSON.parse(json);
|
||||||
This value is found in the package.json file passed in as a command line option.
|
|
||||||
@type {string}
|
|
||||||
*/
|
|
||||||
this.name = json.name;
|
|
||||||
|
|
||||||
/** The longname of this package.
|
/** The name of this package.
|
||||||
@type {string}
|
This value is found in the package.json file passed in as a command line option.
|
||||||
*/
|
@type {string}
|
||||||
this.longname = this.kind + ':' + this.name;
|
*/
|
||||||
|
this.name = json.name;
|
||||||
|
|
||||||
/** The description of this package.
|
/** The longname of this package.
|
||||||
@type {string}
|
@type {string}
|
||||||
*/
|
*/
|
||||||
this.description = json.description;
|
this.longname = this.kind + ':' + this.name;
|
||||||
|
|
||||||
/**
|
/** The description of this package.
|
||||||
The hash summary of the source file.
|
@type {string}
|
||||||
@type {string}
|
*/
|
||||||
@since 3.2.0
|
this.description = json.description;
|
||||||
*/
|
|
||||||
this.version = json.version;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The licenses of this package.
|
The hash summary of the source file.
|
||||||
* @type {Array<Object>}
|
@type {string}
|
||||||
* @example
|
@since 3.2.0
|
||||||
* "licenses": [
|
*/
|
||||||
* {
|
this.version = json.version;
|
||||||
* "type": "GPLv2",
|
|
||||||
* "url": "http://www.example.com/licenses/gpl.html"
|
/**
|
||||||
* }
|
* The licenses of this package.
|
||||||
* ]
|
* @type {Array<Object>}
|
||||||
*/
|
* @example
|
||||||
this.licenses = json.licenses;
|
* "licenses": [
|
||||||
}
|
* {
|
||||||
|
* "type": "GPLv2",
|
||||||
|
* "url": "http://www.example.com/licenses/gpl.html"
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
*/
|
||||||
|
this.licenses = json.licenses;
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
|
||||||
@ -2,151 +2,151 @@
|
|||||||
@module jsdoc/src/handlers
|
@module jsdoc/src/handlers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
|
||||||
var currentModule = null;
|
|
||||||
|
|
||||||
/**
|
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')};
|
|
||||||
|
|
||||||
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
|
/**
|
||||||
parser.on('jsdocCommentFound', function(e) {
|
Attach these event handlers to a particular instance of a parser.
|
||||||
var newDoclet = new jsdoc.doclet.Doclet(e.comment, e);
|
@param parser
|
||||||
|
*/
|
||||||
|
exports.attachTo = function(parser) {
|
||||||
|
var jsdoc = {doclet: require('jsdoc/doclet')};
|
||||||
|
|
||||||
if (!newDoclet.name) {
|
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
|
||||||
return false; // only interested in virtual comments (with a @name) here
|
parser.on('jsdocCommentFound', function(e) {
|
||||||
}
|
var newDoclet = new jsdoc.doclet.Doclet(e.comment, e);
|
||||||
|
|
||||||
addDoclet.call(this, newDoclet);
|
if (!newDoclet.name) {
|
||||||
if (newDoclet.kind === 'module') {
|
return false; // only interested in virtual comments (with a @name) here
|
||||||
currentModule = newDoclet.longname;
|
}
|
||||||
}
|
|
||||||
e.doclet = newDoclet;
|
|
||||||
});
|
|
||||||
|
|
||||||
// handles named symbols in the code, may or may not have a JSDoc comment attached
|
addDoclet.call(this, newDoclet);
|
||||||
parser.on('symbolFound', function(e) {
|
if (newDoclet.kind === 'module') {
|
||||||
var subDoclets = e.comment.split(/@also\b/g);
|
currentModule = newDoclet.longname;
|
||||||
|
}
|
||||||
|
e.doclet = newDoclet;
|
||||||
|
});
|
||||||
|
|
||||||
for (var i = 0, l = subDoclets.length; i < l; i++) {
|
// handles named symbols in the code, may or may not have a JSDoc comment attached
|
||||||
newSymbolDoclet.call(this, subDoclets[i], e);
|
parser.on('symbolFound', function(e) {
|
||||||
}
|
var subDoclets = e.comment.split(/@also\b/g);
|
||||||
});
|
|
||||||
|
|
||||||
function newSymbolDoclet(docletSrc, e) {
|
for (var i = 0, l = subDoclets.length; i < l; i++) {
|
||||||
var newDoclet = new jsdoc.doclet.Doclet(docletSrc, e);
|
newSymbolDoclet.call(this, subDoclets[i], e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// an undocumented symbol right after a virtual comment? rhino mistakenly connected the two
|
function newSymbolDoclet(docletSrc, e) {
|
||||||
if (newDoclet.name) { // there was a @name in comment
|
var newDoclet = new jsdoc.doclet.Doclet(docletSrc, e);
|
||||||
// try again, without the comment
|
|
||||||
e.comment = '@undocumented';
|
|
||||||
newDoclet = new jsdoc.doclet.Doclet(e.comment, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newDoclet.alias) {
|
// an undocumented symbol right after a virtual comment? rhino mistakenly connected the two
|
||||||
if (newDoclet.alias === '{@thisClass}') {
|
if (newDoclet.name) { // there was a @name in comment
|
||||||
memberofName = this.resolveThis(e.astnode);
|
// 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 (newDoclet.alias) {
|
||||||
if ( /^(.+?)(\.prototype|#)$/.test(memberofName) ) {
|
if (newDoclet.alias === '{@thisClass}') {
|
||||||
memberofName = RegExp.$1;
|
memberofName = this.resolveThis(e.astnode);
|
||||||
}
|
|
||||||
newDoclet.alias = memberofName;
|
// "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.alias = memberofName;
|
||||||
newDoclet.postProcess();
|
|
||||||
}
|
}
|
||||||
else if (e.code && e.code.name) { // we need to get the symbol name from code
|
newDoclet.addTag('name', newDoclet.alias);
|
||||||
newDoclet.addTag('name', e.code.name);
|
newDoclet.postProcess();
|
||||||
if (!newDoclet.memberof && e.astnode) {
|
}
|
||||||
var memberofName,
|
else if (e.code && e.code.name) { // we need to get the symbol name from code
|
||||||
scope;
|
newDoclet.addTag('name', e.code.name);
|
||||||
if ( /^((module.)?exports|this)(\.|$)/.test(newDoclet.name) ) {
|
if (!newDoclet.memberof && e.astnode) {
|
||||||
var nameStartsWith = RegExp.$1;
|
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;
|
// like /** @module foo */ exports.bar = 1;
|
||||||
if (nameStartsWith === 'exports' && currentModule) {
|
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;
|
memberofName = currentModule;
|
||||||
scope = 'static';
|
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); }
|
if (memberofName) {
|
||||||
else {
|
if (newDoclet.name) {
|
||||||
if (currentModule) {
|
newDoclet.name = memberofName + (scope === 'instance'? '#' : '.') + newDoclet.name;
|
||||||
if (!newDoclet.scope) newDoclet.addTag( 'inner');
|
|
||||||
if (!newDoclet.memberof && newDoclet.scope !== 'global') newDoclet.addTag( 'memberof', currentModule);
|
|
||||||
}
|
}
|
||||||
|
else { newDoclet.name = memberofName; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
memberofName = this.astnodeToMemberof(e.astnode);
|
||||||
|
}
|
||||||
|
|
||||||
newDoclet.postProcess();
|
if (memberofName) { newDoclet.addTag( 'memberof', memberofName); }
|
||||||
}
|
else {
|
||||||
else {
|
if (currentModule) {
|
||||||
return false;
|
if (!newDoclet.scope) newDoclet.addTag( 'inner');
|
||||||
}
|
if (!newDoclet.memberof && newDoclet.scope !== 'global') newDoclet.addTag( 'memberof', currentModule);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
newDoclet.postProcess();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
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;
|
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
|
* @requires common/events
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
var Token = Packages.org.mozilla.javascript.Token,
|
||||||
var Token = Packages.org.mozilla.javascript.Token,
|
currentParser = null,
|
||||||
currentParser = null,
|
currentSourceName = '';
|
||||||
currentSourceName = '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class
|
* @class
|
||||||
* @mixes module:common/events
|
* @mixes module:common/events
|
||||||
*
|
*
|
||||||
* @example <caption>Create a new parser.</caption>
|
* @example <caption>Create a new parser.</caption>
|
||||||
* var jsdocParser = new (require('jsdoc/src/parser').Parser)();
|
* var jsdocParser = new (require('jsdoc/src/parser').Parser)();
|
||||||
*/
|
*/
|
||||||
exports.Parser = function() {
|
exports.Parser = function() {
|
||||||
this._resultBuffer = [];
|
this._resultBuffer = [];
|
||||||
this.refs = {};
|
this.refs = {};
|
||||||
}
|
}
|
||||||
require('common/util').mixin(exports.Parser.prototype, require('common/events'));
|
require('common/util').mixin(exports.Parser.prototype, require('common/events'));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse the given source files for JSDoc comments.
|
* Parse the given source files for JSDoc comments.
|
||||||
* @param {Array.<string>} sourceFiles An array of filepaths to the JavaScript sources.
|
* @param {Array.<string>} sourceFiles An array of filepaths to the JavaScript sources.
|
||||||
* @param {string} [encoding=utf8]
|
* @param {string} [encoding=utf8]
|
||||||
*
|
*
|
||||||
* @fires jsdocCommentFound
|
* @fires jsdocCommentFound
|
||||||
* @fires symbolFound
|
* @fires symbolFound
|
||||||
* @fires newDoclet
|
* @fires newDoclet
|
||||||
* @fires fileBegin
|
* @fires fileBegin
|
||||||
* @fires fileComplete
|
* @fires fileComplete
|
||||||
*
|
*
|
||||||
* @example <caption>Parse two source files.</caption>
|
* @example <caption>Parse two source files.</caption>
|
||||||
* var myFiles = ['file1.js', 'file2.js'];
|
* var myFiles = ['file1.js', 'file2.js'];
|
||||||
* var docs = jsdocParser.parse(myFiles);
|
* var docs = jsdocParser.parse(myFiles);
|
||||||
*/
|
*/
|
||||||
exports.Parser.prototype.parse = function(sourceFiles, encoding) {
|
exports.Parser.prototype.parse = function(sourceFiles, encoding) {
|
||||||
const SCHEMA = 'javascript:';
|
const SCHEMA = 'javascript:';
|
||||||
var sourceCode = '',
|
var sourceCode = '',
|
||||||
filename = '';
|
filename = '';
|
||||||
|
|
||||||
if (typeof sourceFiles === 'string') { sourceFiles = [sourceFiles]; }
|
if (typeof sourceFiles === 'string') { sourceFiles = [sourceFiles]; }
|
||||||
|
|
||||||
for (i = 0, leni = sourceFiles.length; i < leni; i++) {
|
for (i = 0, leni = sourceFiles.length; i < leni; i++) {
|
||||||
if (sourceFiles[i].indexOf(SCHEMA) === 0) {
|
if (sourceFiles[i].indexOf(SCHEMA) === 0) {
|
||||||
sourceCode = sourceFiles[i].substr(SCHEMA.length);
|
sourceCode = sourceFiles[i].substr(SCHEMA.length);
|
||||||
filename = '[[string' + i + ']]';
|
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) + '~';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
memberof.id = 'astnode'+node.parent.hashCode();
|
filename = sourceFiles[i];
|
||||||
memberof.doclet = this.refs[memberof.id];
|
try {
|
||||||
if (!memberof.doclet) return ''; // global?
|
sourceCode = require('fs').readFileSync(filename, encoding);
|
||||||
return memberof.doclet.longname||memberof.doclet.name;
|
}
|
||||||
|
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;
|
||||||
* 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 (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.id = 'astnode'+node.enclosingFunction.hashCode();
|
||||||
memberof.doclet = this.refs[memberof.id];
|
memberof.doclet = this.refs[memberof.id];
|
||||||
|
|
||||||
if (!memberof.doclet) {
|
if (!memberof.doclet) {
|
||||||
return '<anonymous>'; // TODO handle global this?
|
return '<anonymous>~';
|
||||||
}
|
|
||||||
|
|
||||||
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 (memberof.doclet.longname||memberof.doclet.name) + '~';
|
||||||
}
|
}
|
||||||
else if (node.parent) {
|
}
|
||||||
var parent = node.parent;
|
else {
|
||||||
if (parent.type === Token.COLON) parent = parent.parent; // go up one more
|
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;
|
return memberof.doclet.longname||memberof.doclet.name;
|
||||||
}
|
}
|
||||||
else {
|
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
|
||||||
|
|
||||||
/**
|
memberof.id = 'astnode'+parent.hashCode();
|
||||||
* Resolve what function a var is limited to.
|
memberof.doclet = this.refs[memberof.id];
|
||||||
* @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
|
if (!memberof.doclet) return ''; // global?
|
||||||
doclet = this.refs['astnode'+enclosingFunction.hashCode()];
|
|
||||||
|
|
||||||
if ( doclet && doclet.meta.vars && ~doclet.meta.vars.indexOf(basename) ) {
|
return memberof.doclet.longname||memberof.doclet.name;
|
||||||
return doclet.longname;
|
}
|
||||||
}
|
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 */
|
return this.resolveVar(enclosingFunction, basename);
|
||||||
function visitNode(node) {
|
}
|
||||||
var e,
|
|
||||||
commentSrc;
|
|
||||||
|
|
||||||
// look for stand-alone doc comments
|
/** @private */
|
||||||
if (node.type === Token.SCRIPT && node.comments) {
|
function visitNode(node) {
|
||||||
// note: ALL comments are seen in this block...
|
var e,
|
||||||
for each(var comment in node.comments.toArray()) {
|
commentSrc;
|
||||||
if (comment.commentType !== Token.CommentType.JSDOC) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commentSrc = ''+comment.toSource()) {
|
// look for stand-alone doc comments
|
||||||
|
if (node.type === Token.SCRIPT && node.comments) {
|
||||||
e = {
|
// note: ALL comments are seen in this block...
|
||||||
comment: commentSrc,
|
for each(var comment in node.comments.toArray()) {
|
||||||
lineno: comment.getLineno(),
|
if (comment.commentType !== Token.CommentType.JSDOC) {
|
||||||
filename: currentSourceName
|
continue;
|
||||||
};
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.doclet) {
|
if (commentSrc = ''+comment.toSource()) {
|
||||||
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) ) {
|
e = {
|
||||||
currentParser.fire('symbolFound', e, currentParser);
|
comment: commentSrc,
|
||||||
}
|
lineno: comment.getLineno(),
|
||||||
|
filename: currentSourceName
|
||||||
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;
|
if ( isValidJsdoc(commentSrc) ) {
|
||||||
}
|
currentParser.fire('jsdocCommentFound', e, currentParser);
|
||||||
|
|
||||||
/** @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, '\\"')+'"';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
about.node = node.right;
|
}
|
||||||
about.value = nodeToString(about.node);
|
}
|
||||||
about.type = getTypeName(node.right);
|
else if (node.type === Token.ASSIGN) {
|
||||||
return about;
|
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)
|
if (e.doclet) {
|
||||||
var string = nodeToString(node);
|
currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet
|
||||||
if (string) {
|
}
|
||||||
about.name = string;
|
}
|
||||||
return about;
|
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;
|
return about;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private
|
if (node.type === Token.ASSIGN || node.type === Token.COLON) {
|
||||||
@memberof module:src/parser.Parser
|
about.name = nodeToString(node.left);
|
||||||
*/
|
if (node.type === Token.COLON) {
|
||||||
function nodeToString(node) {
|
|
||||||
var str;
|
|
||||||
|
|
||||||
if (!node) return;
|
// objlit keys with unsafe variable-name characters must be quoted
|
||||||
|
if (!/^[$_a-z][$_a-z0-9]*$/i.test(about.name) ) {
|
||||||
if (node.type === Token.GETPROP) {
|
about.name = '"'+about.name.replace(/"/g, '\\"')+'"';
|
||||||
str = [nodeToString(node.target), node.property.string].join('.');
|
}
|
||||||
}
|
}
|
||||||
else if (node.type === Token.VAR) {
|
about.node = node.right;
|
||||||
str = nodeToString(node.target)
|
about.value = nodeToString(about.node);
|
||||||
}
|
about.type = getTypeName(node.right);
|
||||||
else if (node.type === Token.NAME) {
|
return about;
|
||||||
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
|
// type 39 (NAME)
|
||||||
@memberof module:src/parser.Parser
|
var string = nodeToString(node);
|
||||||
*/
|
if (string) {
|
||||||
function isValidJsdoc(commentSrc) {
|
about.name = string;
|
||||||
return commentSrc.indexOf('/***') !== 0; /*** ignore comments that start with many stars ***/
|
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.
|
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 {string} e.comment The text content of the JSDoc comment
|
||||||
@param {number} e.lineno The line number associated with the found 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.
|
@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.
|
@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')
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
var fs = require('fs');
|
||||||
@constructor
|
|
||||||
@mixes module:common.events
|
|
||||||
*/
|
|
||||||
exports.Scanner = function() {
|
|
||||||
}
|
|
||||||
common.mixin(exports.Scanner.prototype, common.events);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Recursively searches the given searchPaths for js files.
|
@constructor
|
||||||
@param {Array.<string>} searchPaths
|
@mixes module:common.events
|
||||||
@param {number} [depth=1]
|
*/
|
||||||
@fires sourceFileFound
|
exports.Scanner = function() {
|
||||||
*/
|
}
|
||||||
exports.Scanner.prototype.scan = function(searchPaths, depth, includeMatch, excludeMatch) {
|
common.mixin(exports.Scanner.prototype, common.events);
|
||||||
var filePaths = [],
|
|
||||||
that = this;
|
|
||||||
|
|
||||||
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($) {
|
searchPaths = searchPaths || [];
|
||||||
if ( fs.stat($).isFile() ) {
|
depth = depth || 1;
|
||||||
filePaths.push($);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
filePaths = filePaths.concat(fs.ls($, depth));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
filePaths = filePaths.filter(function($) {
|
searchPaths.forEach(function($) {
|
||||||
if (includeMatch && !includeMatch.test($)) {
|
if ( fs.stat($).isFile() ) {
|
||||||
return false
|
filePaths.push($);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
filePaths = filePaths.concat(fs.ls($, depth));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (excludeMatch && excludeMatch.test($)) {
|
filePaths = filePaths.filter(function($) {
|
||||||
return false
|
if (includeMatch && !includeMatch.test($)) {
|
||||||
}
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
if (excludeMatch && excludeMatch.test($)) {
|
||||||
});
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
filePaths = filePaths.filter(function($) {
|
return true;
|
||||||
var e = { fileName: $ };
|
});
|
||||||
that.fire('sourceFileFound', e);
|
|
||||||
|
|
||||||
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/validator
|
||||||
@requires jsdoc/tag/type
|
@requires jsdoc/tag/type
|
||||||
*/
|
*/
|
||||||
(function() {
|
|
||||||
|
|
||||||
var jsdoc = {
|
|
||||||
tag: {
|
|
||||||
dictionary: require('jsdoc/tag/dictionary'),
|
|
||||||
validator: require('jsdoc/tag/validator'),
|
|
||||||
type: require('jsdoc/tag/type')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
var jsdoc = {
|
||||||
Constructs a new tag object. Calls the tag validator.
|
tag: {
|
||||||
@class
|
dictionary: require('jsdoc/tag/dictionary'),
|
||||||
@classdesc Represents a single doclet tag.
|
validator: require('jsdoc/tag/validator'),
|
||||||
@param {string} tagTitle
|
type: require('jsdoc/tag/type')
|
||||||
@param {string=} tagBody
|
}
|
||||||
@param {object=} meta
|
};
|
||||||
*/
|
|
||||||
exports.Tag = function(tagTitle, tagBody, meta) {
|
|
||||||
var tagDef = jsdoc.tag.dictionary.lookUp(tagTitle),
|
|
||||||
meta = meta || {};
|
|
||||||
|
|
||||||
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.originalTitle = trim(tagTitle);
|
||||||
this.title = jsdoc.tag.dictionary.normalise( this.originalTitle );
|
|
||||||
|
|
||||||
/** The text part of the tag: @title text */
|
/** The title part of the tag: @title text */
|
||||||
this.text = trim(tagBody, tagDef.keepsWhitespace);
|
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) {
|
if (this.text) {
|
||||||
this.text = tagDef.onTagText(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. */
|
if (tagDef.canHaveType) {
|
||||||
this.value = {};
|
|
||||||
|
|
||||||
var [
|
/** The value propertiy represents the result of parsing the tag text. */
|
||||||
/*Array.<string>*/ typeNames,
|
this.value = {};
|
||||||
/*any*/ remainingText,
|
|
||||||
/*?boolean*/ optional,
|
|
||||||
/*?boolean*/ nullable,
|
|
||||||
/*?boolean*/ variable
|
|
||||||
] = jsdoc.tag.type.parse(this.text);
|
|
||||||
|
|
||||||
if (typeNames.length) {
|
var [
|
||||||
this.value.type = {
|
/*Array.<string>*/ typeNames,
|
||||||
names: typeNames,
|
/*any*/ remainingText,
|
||||||
optional: optional,
|
/*?boolean*/ optional,
|
||||||
nullable: nullable,
|
/*?boolean*/ nullable,
|
||||||
variable: variable
|
/*?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; }
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
if (remainingText) {
|
this.value.description = 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 = 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, '');
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
function trim(text, newlines) {
|
return text.replace(/^\s+|\s+$/g, '');
|
||||||
if (!text) { return ''; }
|
|
||||||
|
|
||||||
if (newlines) {
|
|
||||||
return text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return text.replace(/^\s+|\s+$/g, '');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Parse the parameter name and parameter desc from the tag text.
|
Parse the parameter name and parameter desc from the tag text.
|
||||||
@inner
|
@inner
|
||||||
@method parseParamText
|
@method parseParamText
|
||||||
@memberof module:jsdoc/tag
|
@memberof module:jsdoc/tag
|
||||||
@param {string} tagText
|
@param {string} tagText
|
||||||
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
||||||
*/
|
*/
|
||||||
function parseParamText(tagText) {
|
function parseParamText(tagText) {
|
||||||
var pname, pdesc, poptional, pdefault;
|
var pname, pdesc, poptional, pdefault;
|
||||||
|
|
||||||
// like: pname, pname pdesc, or name - pdesc
|
// like: pname, pname pdesc, or name - pdesc
|
||||||
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
||||||
|
pname = RegExp.$1;
|
||||||
|
pdesc = RegExp.$3;
|
||||||
|
|
||||||
|
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
||||||
pname = RegExp.$1;
|
pname = RegExp.$1;
|
||||||
pdesc = RegExp.$3;
|
poptional = true;
|
||||||
|
|
||||||
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
if ( /^(.+?)\s*=\s*(.+)$/.test(pname) ) {
|
||||||
pname = RegExp.$1;
|
pname = RegExp.$1;
|
||||||
poptional = true;
|
pdefault = RegExp.$2;
|
||||||
|
|
||||||
if ( /^(.+?)\s*=\s*(.+)$/.test(pname) ) {
|
|
||||||
pname = RegExp.$1;
|
|
||||||
pdefault = RegExp.$2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return [pname, pdesc, poptional, pdefault];
|
|
||||||
}
|
}
|
||||||
|
return [pname, pdesc, poptional, pdefault];
|
||||||
})();
|
}
|
||||||
|
|||||||
@ -3,71 +3,74 @@
|
|||||||
@author Michael Mathews <micmath@gmail.com>
|
@author Michael Mathews <micmath@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
(function() {
|
|
||||||
var _synonyms = {},
|
|
||||||
_definitions = {},
|
|
||||||
_namespaces = [];
|
|
||||||
|
|
||||||
function _TagDefinition(title, etc) {
|
var _synonyms = {},
|
||||||
etc = etc || {};
|
_definitions = {},
|
||||||
|
_namespaces = [];
|
||||||
|
|
||||||
this.title = dictionary.normalise(title);
|
function _TagDefinition(title, etc) {
|
||||||
|
etc = etc || {};
|
||||||
|
|
||||||
for (var p in etc) {
|
this.title = dictionary.normalise(title);
|
||||||
if (etc.hasOwnProperty(p)) {
|
|
||||||
this[p] = etc[p];
|
for (var p in etc) {
|
||||||
}
|
if (etc.hasOwnProperty(p)) {
|
||||||
|
this[p] = etc[p];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_TagDefinition.prototype.synonym = function(synonymName) {
|
_TagDefinition.prototype.synonym = function(synonymName) {
|
||||||
_synonyms[synonymName.toLowerCase()] = this.title;
|
_synonyms[synonymName.toLowerCase()] = this.title;
|
||||||
return this; // chainable
|
return this; // chainable
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @exports jsdoc/tag/dictionary */
|
/** @exports jsdoc/tag/dictionary */
|
||||||
var dictionary = {
|
var dictionary = {
|
||||||
/** @function */
|
/** @function */
|
||||||
defineTag: function(title, opts) {
|
defineTag: function(title, opts) {
|
||||||
_definitions[title] = new _TagDefinition(title, opts);
|
_definitions[title] = new _TagDefinition(title, opts);
|
||||||
|
|
||||||
if (opts.isNamespace) {
|
if (opts.isNamespace) {
|
||||||
_namespaces.push(title);
|
_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;
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
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.
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
(function() {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@param {string} tagValue
|
@param {string} tagValue
|
||||||
@returns {Array.<string>}
|
@returns {Array.<string>}
|
||||||
*/
|
*/
|
||||||
exports.parse = function(tagValue) {
|
exports.parse = function(tagValue) {
|
||||||
if (typeof tagValue !== 'string') { tagValue = ''; }
|
if (typeof tagValue !== 'string') { tagValue = ''; }
|
||||||
var type = '',
|
var type = '',
|
||||||
text = '',
|
text = '',
|
||||||
count = 0,
|
count = 0,
|
||||||
optional,
|
optional,
|
||||||
nullable,
|
nullable,
|
||||||
variable;
|
variable;
|
||||||
|
|
||||||
// type expressions start with '{'
|
// type expressions start with '{'
|
||||||
if (tagValue[0] === '{') {
|
if (tagValue[0] === '{') {
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
// find matching closer '}'
|
// find matching closer '}'
|
||||||
for (var i = 1, leni = tagValue.length; i < leni; i++) {
|
for (var i = 1, leni = tagValue.length; i < leni; i++) {
|
||||||
if (tagValue[i] === '\\') { i++; continue; } // backslash escapes the next character
|
if (tagValue[i] === '\\') { i++; continue; } // backslash escapes the next character
|
||||||
|
|
||||||
if (tagValue[i] === '{') { count++; }
|
if (tagValue[i] === '{') { count++; }
|
||||||
else if (tagValue[i] === '}') { count--; }
|
else if (tagValue[i] === '}') { count--; }
|
||||||
|
|
||||||
if (count === 0) {
|
if (count === 0) {
|
||||||
type = trim(tagValue.slice(1, i))
|
type = trim(tagValue.slice(1, i))
|
||||||
.replace(/\\\{/g, '{') // unescape escaped curly braces
|
.replace(/\\\{/g, '{') // unescape escaped curly braces
|
||||||
.replace(/\\\}/g, '}');
|
.replace(/\\\}/g, '}');
|
||||||
text = trim(tagValue.slice(i+1));
|
text = trim(tagValue.slice(i+1));
|
||||||
break;
|
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) {
|
if (type === '') { text = tagValue; }
|
||||||
var optional = null;
|
|
||||||
|
|
||||||
// {sometype=} means optional
|
[type, optional] = parseOptional(type);
|
||||||
if ( /(.+)=$/.test(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;
|
type = RegExp.$1;
|
||||||
optional = true;
|
|
||||||
}
|
}
|
||||||
|
types = type.split(/\s*\|\s*/g);
|
||||||
return [type, optional];
|
}
|
||||||
|
else if (type) {
|
||||||
|
types = [type];
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseNullable(type) {
|
return types;
|
||||||
var nullable = null;
|
}
|
||||||
|
|
||||||
// {?sometype} means nullable, {!sometype} means not-nullable
|
/** @private */
|
||||||
if ( /^([\?\!])(.+)$/.test(type) ) {
|
function trim(text) {
|
||||||
type = RegExp.$2;
|
return text.replace(/^\s+|\s+$/g, '');
|
||||||
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, '');
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|||||||
@ -5,48 +5,47 @@
|
|||||||
@author Michael Mathews <micmath@gmail.com>
|
@author Michael Mathews <micmath@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
(function() {
|
|
||||||
|
|
||||||
var dictionary = require('jsdoc/tag/dictionary');
|
|
||||||
|
|
||||||
/**
|
var dictionary = require('jsdoc/tag/dictionary');
|
||||||
Validate the given tag.
|
|
||||||
*/
|
|
||||||
exports.validate = function(tag, meta) {
|
|
||||||
var tagDef = dictionary.lookUp(tag.title);
|
|
||||||
|
|
||||||
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 && !env.conf.tags.allowUnknownTags) {
|
||||||
if (tagDef.mustHaveValue) {
|
throw new UnknownTagError(tag.title, meta);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
UnknownTagError.prototype = Error.prototype;
|
|
||||||
|
|
||||||
function TagValueRequiredError(tagName, meta) {
|
if (!tag.text) {
|
||||||
this.name = 'TagValueRequiredError';
|
if (tagDef.mustHaveValue) {
|
||||||
this.message = 'The @' + tagName + ' tag requires a value. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
throw new TagValueRequiredError(tag.title, meta);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
TagValueRequiredError.prototype = Error.prototype;
|
else {
|
||||||
|
if (tagDef.mustNotHaveValue) {
|
||||||
function TagValueNotPermittedError(tagName, message, meta) {
|
throw new TagValueNotPermittedError(tag.title, 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;
|
}
|
||||||
|
|
||||||
|
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>
|
@author Michael Mathews <micmath@gmail.com>
|
||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@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);
|
@param {any} object
|
||||||
return output;
|
*/
|
||||||
|
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,
|
@param {string} openingBrace - The opening brace to add, like "{".
|
||||||
output;
|
@private
|
||||||
|
@inner
|
||||||
|
@memberof module:common/dumper
|
||||||
|
*/
|
||||||
|
function indent(openingBrace) {
|
||||||
|
indentBy++;
|
||||||
|
if (openingBrace) output += openingBrace + '\n';
|
||||||
|
}
|
||||||
|
|
||||||
function pad(depth) {
|
/**
|
||||||
var padding = '';
|
@param {string|boolean} closingBrace - The closing brace to add, like "}" or if boolean
|
||||||
while (depth--) {
|
`false` no closing brace or trailing newline.
|
||||||
padding += INDENTATION;
|
@private
|
||||||
}
|
@inner
|
||||||
return padding;
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
function walk(object) {
|
||||||
@param {string} openingBrace - The opening brace to add, like "{".
|
var value;
|
||||||
@private
|
|
||||||
@inner
|
if ( value = getValue(object) ) {
|
||||||
@memberof module:common/dumper
|
output += value + ',\n';
|
||||||
*/
|
|
||||||
function indent(openingBrace) {
|
|
||||||
indentBy++;
|
|
||||||
if (openingBrace) output += openingBrace + '\n';
|
|
||||||
}
|
}
|
||||||
|
else if ( isUnwalkable(object) ) {
|
||||||
/**
|
output += '<Object>,\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 ( isRegExp(object) ) {
|
||||||
var seen = [];
|
output += '<RegExp ' + object + '>,\n'
|
||||||
seen.has = function(object) {
|
|
||||||
for (var i = 0, l = seen.length; i < l; i++) {
|
|
||||||
if (seen[i] === object) { return true; }
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
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) {
|
indent('[');
|
||||||
var value;
|
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) ) {
|
indent('{');
|
||||||
output += value + ',\n';
|
for (var p in object) {
|
||||||
}
|
if ( object.hasOwnProperty(p) ) {
|
||||||
else if ( isUnwalkable(object) ) {
|
output += pad(indentBy) + stringify(p) + ': ';
|
||||||
output += '<Object>,\n'
|
walk( object[p] );
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
function getValue(o) { // see: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof
|
||||||
if (o === null) { return 'null'; }
|
if (o === null) { return 'null'; }
|
||||||
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
|
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
|
||||||
return ''+stringify(o);
|
return ''+stringify(o);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function stringify(o) {
|
function stringify(o) {
|
||||||
return JSON.stringify(o);
|
return JSON.stringify(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
|
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
|
||||||
return (typeof o === 'object' && typeof o.constructor === 'undefined');
|
return (typeof o === 'object' && typeof o.constructor === 'undefined');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isArray(o) {
|
function isArray(o) {
|
||||||
return o && (o instanceof Array) || o.constructor === Array;
|
return o && (o instanceof Array) || o.constructor === Array;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isRegExp(o) {
|
function isRegExp(o) {
|
||||||
return (o instanceof RegExp) ||
|
return (o instanceof RegExp) ||
|
||||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
|
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDate(o) {
|
function isDate(o) {
|
||||||
return o && (o instanceof Date) ||
|
return o && (o instanceof Date) ||
|
||||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
|
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isFunction(o) {
|
function isFunction(o) {
|
||||||
return o && (typeof o === 'function' || o instanceof Function);// ||
|
return o && (typeof o === 'function' || o instanceof Function);// ||
|
||||||
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
|
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
|
||||||
}
|
}
|
||||||
|
|
||||||
function isObject(o) {
|
function isObject(o) {
|
||||||
return o && o instanceof Object ||
|
return o && o instanceof Object ||
|
||||||
(typeof o.constructor !== 'undefined' && o.constructor.name === '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