mirror of
https://github.com/jsdoc/jsdoc.git
synced 2025-12-08 19:46:11 +00:00
Merge branch 'master' of github.com:jsdoc3/jsdoc
This commit is contained in:
commit
fdf37fe137
@ -4,7 +4,7 @@
|
|||||||
"eqeqeq": false,
|
"eqeqeq": false,
|
||||||
"forin": true,
|
"forin": true,
|
||||||
"immed": true,
|
"immed": true,
|
||||||
"latedef": false,
|
"latedef": true,
|
||||||
"newcap": true,
|
"newcap": true,
|
||||||
"noarg": true,
|
"noarg": true,
|
||||||
"noempty": false,
|
"noempty": false,
|
||||||
|
|||||||
46
jsdoc.js
46
jsdoc.js
@ -91,29 +91,6 @@ include.resolve = function(filepath) {
|
|||||||
return env.dirname + '/' + filepath;
|
return env.dirname + '/' + filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Data that must be shared across the entire application.
|
|
||||||
@namespace
|
|
||||||
*/
|
|
||||||
app = {
|
|
||||||
jsdoc: {
|
|
||||||
scanner: new (require('jsdoc/src/scanner').Scanner)(),
|
|
||||||
parser: new (require('jsdoc/src/parser').Parser)(),
|
|
||||||
name: require('jsdoc/name')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try { main(); }
|
|
||||||
catch(e) {
|
|
||||||
if (e.rhinoException != null) {
|
|
||||||
e.rhinoException.printStackTrace();
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally { env.run.finish = new Date(); }
|
|
||||||
|
|
||||||
/** Print string/s out to the console.
|
/** Print string/s out to the console.
|
||||||
@param {string} ... String/s to print out to console.
|
@param {string} ... String/s to print out to console.
|
||||||
*/
|
*/
|
||||||
@ -185,6 +162,19 @@ function indexAll(docs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Data that must be shared across the entire application.
|
||||||
|
@namespace
|
||||||
|
*/
|
||||||
|
app = {
|
||||||
|
jsdoc: {
|
||||||
|
scanner: new (require('jsdoc/src/scanner').Scanner)(),
|
||||||
|
parser: new (require('jsdoc/src/parser').Parser)(),
|
||||||
|
name: require('jsdoc/name')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
|
||||||
|
|
||||||
|
|
||||||
@ -324,3 +314,13 @@ function main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try { main(); }
|
||||||
|
catch(e) {
|
||||||
|
if (e.rhinoException != null) {
|
||||||
|
e.rhinoException.printStackTrace();
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally { env.run.finish = new Date(); }
|
||||||
|
|||||||
@ -5,6 +5,19 @@ exports.readFileSync = function(filename, encoding) {
|
|||||||
return readFile(filename, encoding);
|
return readFile(filename, encoding);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var stat = exports.stat = exports.statSync = function(path, encoding) {
|
||||||
|
var f = new java.io.File(path);
|
||||||
|
return {
|
||||||
|
isFile: function() {
|
||||||
|
return f.isFile();
|
||||||
|
},
|
||||||
|
isDirectory: function() {
|
||||||
|
return f.isDirectory();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
var readdirSync = exports.readdirSync = function(path) {
|
var readdirSync = exports.readdirSync = function(path) {
|
||||||
var dir,
|
var dir,
|
||||||
files;
|
files;
|
||||||
@ -64,28 +77,17 @@ var ls = exports.ls = function(dir, recurse, _allFiles, _path) {
|
|||||||
return _allFiles;
|
return _allFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
var stat = exports.stat = exports.statSync = function(path, encoding) {
|
var toDir = exports.toDir = function(path) {
|
||||||
var f = new java.io.File(path);
|
var f = new java.io.File(path);
|
||||||
return {
|
|
||||||
isFile: function() {
|
|
||||||
return f.isFile();
|
|
||||||
},
|
|
||||||
isDirectory: function() {
|
|
||||||
return f.isDirectory();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
if (f.isDirectory()){
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
exports.mkPath = function(/**Array*/ path) {
|
var parts = path.split(/[\\\/]/);
|
||||||
if (path.constructor != Array){path = path.split(/[\\\/]/);}
|
parts.pop();
|
||||||
var make = "";
|
|
||||||
for (var i = 0, l = path.length; i < l; i++) {
|
return parts.join('/');
|
||||||
make += path[i] + '/';
|
|
||||||
if (! exists(make)) {
|
|
||||||
makeDir(make);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function makeDir(/**string*/ path) {
|
function makeDir(/**string*/ path) {
|
||||||
@ -108,17 +110,20 @@ function exists(path) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var toDir = exports.toDir = function(path) {
|
exports.mkPath = function(/**Array*/ path) {
|
||||||
var f = new java.io.File(path);
|
if (path.constructor != Array){path = path.split(/[\\\/]/);}
|
||||||
|
var make = "";
|
||||||
if (f.isDirectory()){
|
for (var i = 0, l = path.length; i < l; i++) {
|
||||||
return path;
|
make += path[i] + '/';
|
||||||
|
if (! exists(make)) {
|
||||||
|
makeDir(make);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var toFile = exports.toFile = function(path) {
|
||||||
var parts = path.split(/[\\\/]/);
|
var parts = path.split(/[\\\/]/);
|
||||||
parts.pop();
|
return parts.pop();
|
||||||
|
|
||||||
return parts.join('/');
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.copyFile = function(inFile, outDir, fileName) {
|
exports.copyFile = function(inFile, outDir, fileName) {
|
||||||
@ -139,11 +144,6 @@ exports.copyFile = function(inFile, outDir, fileName) {
|
|||||||
bis.close();
|
bis.close();
|
||||||
};
|
};
|
||||||
|
|
||||||
var toFile = exports.toFile = function(path) {
|
|
||||||
var parts = path.split(/[\\\/]/);
|
|
||||||
return parts.pop();
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.writeFileSync = function(filename, data, encoding) {
|
exports.writeFileSync = function(filename, data, encoding) {
|
||||||
encoding = encoding || 'utf-8';
|
encoding = encoding || 'utf-8';
|
||||||
|
|
||||||
|
|||||||
@ -21,8 +21,6 @@ const defaults = {
|
|||||||
"jsVersion": 180
|
"jsVersion": 180
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = Config;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class
|
@class
|
||||||
@classdesc Represents a JSDoc application configuration.
|
@classdesc Represents a JSDoc application configuration.
|
||||||
@ -34,6 +32,8 @@ function Config(json) {
|
|||||||
this._config = util.mergeRecurse(defaults, json);
|
this._config = util.mergeRecurse(defaults, json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get the merged configuration values.
|
Get the merged configuration values.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -19,6 +19,108 @@ var jsdoc = {
|
|||||||
name: require('jsdoc/name')
|
name: require('jsdoc/name')
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function applyTag(tag) {
|
||||||
|
if (tag.title === 'name') {
|
||||||
|
this.name = tag.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.title === 'kind') {
|
||||||
|
this.kind = tag.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.title === 'description') {
|
||||||
|
this.description = tag.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tag.title === 'scope') {
|
||||||
|
this.scope = tag.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// use the meta info about the source code to guess what the doclet kind should be
|
||||||
|
function codetypeToKind(type) {
|
||||||
|
var kind = (type || '').toLowerCase();
|
||||||
|
|
||||||
|
if (kind !== 'function') {
|
||||||
|
return 'member';
|
||||||
|
}
|
||||||
|
|
||||||
|
return kind;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unwrap(docletSrc) {
|
||||||
|
if (!docletSrc) { return ''; }
|
||||||
|
|
||||||
|
// note: keep trailing whitespace for @examples
|
||||||
|
// extra opening/closing stars are ignored
|
||||||
|
// left margin is considered a star and a space
|
||||||
|
// use the /m flag on regex to avoid having to guess what this platform's newline is
|
||||||
|
docletSrc =
|
||||||
|
docletSrc.replace(/^\/\*\*+/, '') // remove opening slash+stars
|
||||||
|
.replace(/\**\*\/$/, "\\Z") // replace closing star slash with end-marker
|
||||||
|
.replace(/^\s*(\* ?|\\Z)/gm, '') // remove left margin like: spaces+star or spaces+end-marker
|
||||||
|
.replace(/\s*\\Z$/g, ''); // remove end-marker
|
||||||
|
|
||||||
|
return docletSrc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function split(docletSrc) {
|
||||||
|
var tagSrcs = [],
|
||||||
|
tagText,
|
||||||
|
tagTitle;
|
||||||
|
|
||||||
|
// split out the basic tags, keep surrounding whitespace
|
||||||
|
// like: @tagTitle tagBody
|
||||||
|
docletSrc
|
||||||
|
.replace(/^(\s*)@(\S)/gm, '$1\\@$2') // replace splitter ats with an arbitrary sequence
|
||||||
|
.split('\\@') // then split on that arbitrary sequence
|
||||||
|
.forEach(function($) {
|
||||||
|
if ($) {
|
||||||
|
var parsedTag = $.match(/^(\S+)(:?\s+(\S[\s\S]*))?/);
|
||||||
|
|
||||||
|
if (parsedTag) {
|
||||||
|
// we don't need parsedTag[0]
|
||||||
|
tagTitle = parsedTag[1];
|
||||||
|
tagText = parsedTag[2];
|
||||||
|
|
||||||
|
if (tagTitle) {
|
||||||
|
tagSrcs.push({
|
||||||
|
title: tagTitle,
|
||||||
|
text: tagText
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return tagSrcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert the raw source of the doclet comment into an array of Tag objects.
|
||||||
|
@private
|
||||||
|
*/
|
||||||
|
function toTags(docletSrc) {
|
||||||
|
var tagSrcs,
|
||||||
|
tags = [];
|
||||||
|
|
||||||
|
docletSrc = unwrap(docletSrc);
|
||||||
|
tagSrcs = split(docletSrc);
|
||||||
|
|
||||||
|
for (var i = 0, l = tagSrcs.length; i < l; i++) {
|
||||||
|
tags.push( {title: tagSrcs[i].title, text: tagSrcs[i].text} );
|
||||||
|
}
|
||||||
|
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
function fixDescription(docletSrc) {
|
||||||
|
if (!/^\s*@/.test(docletSrc)) {
|
||||||
|
docletSrc = '@description ' + docletSrc;
|
||||||
|
}
|
||||||
|
return docletSrc;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@class
|
@class
|
||||||
@classdesc Represents a single JSDoc comment.
|
@classdesc Represents a single JSDoc comment.
|
||||||
@ -228,105 +330,3 @@ exports.Doclet.prototype.setMeta = function(meta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyTag(tag) {
|
|
||||||
if (tag.title === 'name') {
|
|
||||||
this.name = tag.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag.title === 'kind') {
|
|
||||||
this.kind = tag.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag.title === 'description') {
|
|
||||||
this.description = tag.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tag.title === 'scope') {
|
|
||||||
this.scope = tag.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// use the meta info about the source code to guess what the doclet kind should be
|
|
||||||
function codetypeToKind(type) {
|
|
||||||
var kind = (type || '').toLowerCase();
|
|
||||||
|
|
||||||
if (kind !== 'function') {
|
|
||||||
return 'member';
|
|
||||||
}
|
|
||||||
|
|
||||||
return kind;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 (var i = 0, l = tagSrcs.length; i < l; i++) {
|
|
||||||
tags.push( {title: tagSrcs[i].title, text: tagSrcs[i].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 split(docletSrc) {
|
|
||||||
var tagSrcs = [],
|
|
||||||
tagText,
|
|
||||||
tagTitle;
|
|
||||||
|
|
||||||
// split out the basic tags, keep surrounding whitespace
|
|
||||||
// like: @tagTitle tagBody
|
|
||||||
docletSrc
|
|
||||||
.replace(/^(\s*)@(\S)/gm, '$1\\@$2') // replace splitter ats with an arbitrary sequence
|
|
||||||
.split('\\@') // then split on that arbitrary sequence
|
|
||||||
.forEach(function($) {
|
|
||||||
if ($) {
|
|
||||||
var parsedTag = $.match(/^(\S+)(:?\s+(\S[\s\S]*))?/);
|
|
||||||
|
|
||||||
if (parsedTag) {
|
|
||||||
// we don't need parsedTag[0]
|
|
||||||
tagTitle = parsedTag[1];
|
|
||||||
tagText = parsedTag[2];
|
|
||||||
|
|
||||||
if (tagTitle) {
|
|
||||||
tagSrcs.push({
|
|
||||||
title: tagTitle,
|
|
||||||
text: tagText
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return tagSrcs;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -12,35 +12,9 @@
|
|||||||
@author Ben Blank <ben.blank@gmail.com>
|
@author Ben Blank <ben.blank@gmail.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
module.exports = ReadMe;
|
|
||||||
|
|
||||||
var fs = require('fs'),
|
var fs = require('fs'),
|
||||||
conf = env.conf.markdown;
|
conf = env.conf.markdown;
|
||||||
|
|
||||||
/**
|
|
||||||
@class
|
|
||||||
@classdesc Represents a README file.
|
|
||||||
@param {string} path - The filepath to the README.
|
|
||||||
*/
|
|
||||||
function ReadMe(path) {
|
|
||||||
var content = fs.readFileSync(path),
|
|
||||||
parse;
|
|
||||||
|
|
||||||
// determine which parser should be used based on configuration options, if any
|
|
||||||
if (conf && conf.parser) {
|
|
||||||
parse = getParser(conf.parser, conf);
|
|
||||||
} else if (conf && conf.githubRepoOwner && conf.githubRepoName) {
|
|
||||||
// use GitHub-friendly parser if GitHub-specific options are present
|
|
||||||
parse = getParser('gfm', conf);
|
|
||||||
} else {
|
|
||||||
// evilstreak is the default parser
|
|
||||||
parse = getParser('evilstreak', conf);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.html = parse(content);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function getParser(parser, conf) {
|
function getParser(parser, conf) {
|
||||||
conf = conf || {};
|
conf = conf || {};
|
||||||
|
|
||||||
@ -66,3 +40,28 @@ function getParser(parser, conf) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@class
|
||||||
|
@classdesc Represents a README file.
|
||||||
|
@param {string} path - The filepath to the README.
|
||||||
|
*/
|
||||||
|
function ReadMe(path) {
|
||||||
|
var content = fs.readFileSync(path),
|
||||||
|
parse;
|
||||||
|
|
||||||
|
// determine which parser should be used based on configuration options, if any
|
||||||
|
if (conf && conf.parser) {
|
||||||
|
parse = getParser(conf.parser, conf);
|
||||||
|
} else if (conf && conf.githubRepoOwner && conf.githubRepoName) {
|
||||||
|
// use GitHub-friendly parser if GitHub-specific options are present
|
||||||
|
parse = getParser('gfm', conf);
|
||||||
|
} else {
|
||||||
|
// evilstreak is the default parser
|
||||||
|
parse = getParser('evilstreak', conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.html = parse(content);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ReadMe;
|
||||||
|
|||||||
@ -39,7 +39,8 @@ exports.attachTo = function(parser) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
function newSymbolDoclet(docletSrc, e) {
|
function newSymbolDoclet(docletSrc, e) {
|
||||||
var newDoclet = new jsdoc.doclet.Doclet(docletSrc, e);
|
var memberofName = null,
|
||||||
|
newDoclet = new jsdoc.doclet.Doclet(docletSrc, e);
|
||||||
|
|
||||||
// an undocumented symbol right after a virtual comment? rhino mistakenly connected the two
|
// an undocumented symbol right after a virtual comment? rhino mistakenly connected the two
|
||||||
if (newDoclet.name) { // there was a @name in comment
|
if (newDoclet.name) { // there was a @name in comment
|
||||||
@ -64,8 +65,7 @@ exports.attachTo = function(parser) {
|
|||||||
else if (e.code && e.code.name) { // we need to get the symbol name from code
|
else if (e.code && e.code.name) { // we need to get the symbol name from code
|
||||||
newDoclet.addTag('name', e.code.name);
|
newDoclet.addTag('name', e.code.name);
|
||||||
if (!newDoclet.memberof && e.astnode) {
|
if (!newDoclet.memberof && e.astnode) {
|
||||||
var memberofName = null,
|
var basename = null,
|
||||||
basename = null,
|
|
||||||
scope = '';
|
scope = '';
|
||||||
if ( /^((module.)?exports|this)(\.|$)/.test(newDoclet.name) ) {
|
if ( /^((module.)?exports|this)(\.|$)/.test(newDoclet.name) ) {
|
||||||
var nameStartsWith = RegExp.$1;
|
var nameStartsWith = RegExp.$1;
|
||||||
|
|||||||
@ -115,6 +115,337 @@ exports.Parser.prototype.getVisitors = function() {
|
|||||||
return this._visitors;
|
return this._visitors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function pretreat(code) {
|
||||||
|
return code
|
||||||
|
// make starbangstar comments look like real jsdoc comments
|
||||||
|
.replace(/\/\*\!\*/g, '/**')
|
||||||
|
|
||||||
|
// merge adjacent doclets
|
||||||
|
.replace(/\*\/\/\*\*+/g, '@also')
|
||||||
|
// make lent objectliterals documentable by giving them a dummy name
|
||||||
|
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/\s*)\{/g, '$1 ____ = {') // like return @lends {
|
||||||
|
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/)(\s*)return(\s*)\{/g, '$2$3 return $1 ____ = {'); // like @lends return {
|
||||||
|
}
|
||||||
|
|
||||||
|
var tkn = { NAMEDFUNCTIONSTATEMENT: -1001 };
|
||||||
|
exports.Parser.tkn = tkn;
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
function parserFactory() {
|
||||||
|
var cx = Packages.org.mozilla.javascript.Context.getCurrentContext();
|
||||||
|
|
||||||
|
var ce = new Packages.org.mozilla.javascript.CompilerEnvirons();
|
||||||
|
ce.setRecordingComments(true);
|
||||||
|
ce.setRecordingLocalJsDocComments(true);
|
||||||
|
ce.setLanguageVersion(180);
|
||||||
|
|
||||||
|
ce.initFromContext(cx);
|
||||||
|
return new Packages.org.mozilla.javascript.Parser(ce, ce.getErrorReporter());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private
|
||||||
|
@memberof module:src/parser.Parser
|
||||||
|
*/
|
||||||
|
function getTypeName(node) {
|
||||||
|
var type = '';
|
||||||
|
|
||||||
|
if (node) {
|
||||||
|
type = ''+ Packages.org.mozilla.javascript.Token.typeToName(node.getType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private
|
||||||
|
@memberof module:src/parser.Parser
|
||||||
|
*/
|
||||||
|
function nodeToString(node) {
|
||||||
|
var str;
|
||||||
|
|
||||||
|
if (!node) { return; }
|
||||||
|
|
||||||
|
if (node.type === Token.GETPROP) {
|
||||||
|
str = [nodeToString(node.target), node.property.string].join('.');
|
||||||
|
}
|
||||||
|
else if (node.type === Token.VAR) {
|
||||||
|
str = nodeToString(node.target)
|
||||||
|
}
|
||||||
|
else if (node.type === Token.NAME) {
|
||||||
|
str = node.string;
|
||||||
|
}
|
||||||
|
else if (node.type === Token.STRING) {
|
||||||
|
str = node.value;
|
||||||
|
}
|
||||||
|
else if (node.type === Token.NUMBER) {
|
||||||
|
str = node.value;
|
||||||
|
}
|
||||||
|
else if (node.type === Token.THIS) {
|
||||||
|
str = 'this';
|
||||||
|
}
|
||||||
|
else if (node.type === Token.GETELEM) {
|
||||||
|
str = node.toSource(); // like: Foo['Bar']
|
||||||
|
}
|
||||||
|
else if (node.type === Token.NEG || node.type === Token.TRUE || node.type === Token.FALSE) {
|
||||||
|
str = node.toSource(); // like -1
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
str = getTypeName(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '' + str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to find the name and type of the given node.
|
||||||
|
* @private
|
||||||
|
* @memberof module:src/parser.Parser
|
||||||
|
*/
|
||||||
|
function aboutNode(node) {
|
||||||
|
var about = {};
|
||||||
|
|
||||||
|
if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
|
||||||
|
about.name = node.type == tkn.NAMEDFUNCTIONSTATEMENT? '' : '' + node.name;
|
||||||
|
about.type = 'function';
|
||||||
|
about.node = node;
|
||||||
|
}
|
||||||
|
else if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
|
||||||
|
about.name = nodeToString(node.target);
|
||||||
|
if (node.initializer) { // like var i = 0;
|
||||||
|
about.node = node.initializer;
|
||||||
|
about.value = nodeToString(about.node);
|
||||||
|
about.type = getTypeName(node.initializer);
|
||||||
|
if (about.type === 'FUNCTION' && about.node.name) {
|
||||||
|
about.node.type = tkn.NAMEDFUNCTIONSTATEMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // like var i;
|
||||||
|
about.node = node.target;
|
||||||
|
about.value = nodeToString(about.node);
|
||||||
|
about.type = 'undefined';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node.type === Token.ASSIGN || node.type === Token.COLON) {
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (about.type === 'FUNCTION' && about.node.name) {
|
||||||
|
about.node.type = tkn.NAMEDFUNCTIONSTATEMENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// type 39 (NAME)
|
||||||
|
var string = nodeToString(node);
|
||||||
|
if (string) {
|
||||||
|
about.name = string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// get names of the formal parameters declared for this function
|
||||||
|
if (about.node && about.node.getParamCount) {
|
||||||
|
var paramCount = about.node.getParamCount();
|
||||||
|
if (typeof paramCount === 'number') {
|
||||||
|
about.node.flattenSymbolTable(true);
|
||||||
|
var paramNames = [];
|
||||||
|
for (var i = 0, len = paramCount; i < len; i++) {
|
||||||
|
paramNames.push(''+about.node.getParamOrVarName(i));
|
||||||
|
}
|
||||||
|
about.paramnames = paramNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return about;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private
|
||||||
|
@memberof module:src/parser.Parser
|
||||||
|
*/
|
||||||
|
function isValidJsdoc(commentSrc) {
|
||||||
|
return commentSrc && commentSrc.indexOf('/***') !== 0; /*** ignore comments that start with many stars ***/
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private
|
||||||
|
* @memberof module:src/parser.Parser
|
||||||
|
*/
|
||||||
|
function makeVarsFinisher(funcDoc) {
|
||||||
|
var func = function(e) {
|
||||||
|
//no need to evaluate all things related to funcDoc again, just use it
|
||||||
|
if (funcDoc && e.doclet && e.doclet.alias) {
|
||||||
|
funcDoc.meta.vars[e.code.name] = e.doclet.longname;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private
|
||||||
|
* @memberof module:src/parser.Parser
|
||||||
|
* @param {string} name Full symbol name.
|
||||||
|
* @return {string} Basename.
|
||||||
|
*/
|
||||||
|
function getBasename(name) {
|
||||||
|
if (name !== undefined) {
|
||||||
|
return name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
function visitNode(node) {
|
||||||
|
var e,
|
||||||
|
nodeComments,
|
||||||
|
comment,
|
||||||
|
commentSrc,
|
||||||
|
i,
|
||||||
|
l;
|
||||||
|
|
||||||
|
// look for stand-alone doc comments
|
||||||
|
if (node.type === Token.SCRIPT && node.comments) {
|
||||||
|
// note: ALL comments are seen in this block...
|
||||||
|
nodeComments = node.comments.toArray();
|
||||||
|
for (i = 0, l = nodeComments.length; i < l; i++) {
|
||||||
|
comment = nodeComments[i];
|
||||||
|
if (comment.commentType !== Token.CommentType.JSDOC) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentSrc = ''+comment.toSource()) {
|
||||||
|
|
||||||
|
e = {
|
||||||
|
comment: commentSrc,
|
||||||
|
lineno: comment.getLineno(),
|
||||||
|
filename: currentSourceName
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( isValidJsdoc(commentSrc) ) {
|
||||||
|
currentParser.fire('jsdocCommentFound', e, currentParser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e = null;
|
||||||
|
}
|
||||||
|
else if (node.type === Token.ASSIGN) {
|
||||||
|
e = {
|
||||||
|
id: 'astnode'+node.hashCode(), // the id of the ASSIGN node
|
||||||
|
comment: String(node.getJsDoc()||'@undocumented'),
|
||||||
|
lineno: node.left.getLineno(),
|
||||||
|
filename: currentSourceName,
|
||||||
|
astnode: node,
|
||||||
|
code: aboutNode(node),
|
||||||
|
event: "symbolFound",
|
||||||
|
finishers: [currentParser.addDocletRef]
|
||||||
|
};
|
||||||
|
|
||||||
|
var basename = getBasename(e.code.name);
|
||||||
|
|
||||||
|
if (basename !== 'this') {
|
||||||
|
e.code.funcscope = currentParser.resolveVar(node, basename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.getJsDoc()||'@undocumented'),
|
||||||
|
lineno: node.left.getLineno(),
|
||||||
|
filename: currentSourceName,
|
||||||
|
astnode: node,
|
||||||
|
code: aboutNode(node),
|
||||||
|
event: "symbolFound",
|
||||||
|
finishers: [currentParser.addDocletRef, currentParser.resolveEnum]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
|
||||||
|
|
||||||
|
if (node.variables) {
|
||||||
|
return true; // we'll get each var separately on future visits
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.parent.variables.toArray()[0] === node) { // like /** blah */ var a=1, b=2, c=3;
|
||||||
|
// the first var assignment gets any jsDoc before the whole var series
|
||||||
|
if (typeof node.setJsDoc !== 'undefined') { node.setJsDoc( node.parent.getJsDoc() ); }
|
||||||
|
//node.jsDoc = node.parent.jsDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
e = {
|
||||||
|
id: 'astnode'+node.hashCode(), // the id of the VARIABLE node
|
||||||
|
comment: String(node.getJsDoc()||'@undocumented'),
|
||||||
|
lineno: node.getLineno(),
|
||||||
|
filename: currentSourceName,
|
||||||
|
astnode: node,
|
||||||
|
code: aboutNode(node),
|
||||||
|
event: "symbolFound",
|
||||||
|
finishers: [currentParser.addDocletRef]
|
||||||
|
};
|
||||||
|
|
||||||
|
// keep track of vars in a function or global scope
|
||||||
|
var func = "__global__",
|
||||||
|
funcDoc = null;
|
||||||
|
if (node.enclosingFunction) {
|
||||||
|
func = 'astnode'+node.enclosingFunction.hashCode();
|
||||||
|
}
|
||||||
|
funcDoc = currentParser.refs[func];
|
||||||
|
if (funcDoc) {
|
||||||
|
funcDoc.meta.vars = funcDoc.meta.vars || {};
|
||||||
|
funcDoc.meta.vars[e.code.name] = false;
|
||||||
|
e.finishers.push(makeVarsFinisher(funcDoc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
|
||||||
|
e = {
|
||||||
|
id: 'astnode'+node.hashCode(), // the id of the COLON node
|
||||||
|
comment: String(node.getJsDoc()||'@undocumented'),
|
||||||
|
lineno: node.getLineno(),
|
||||||
|
filename: currentSourceName,
|
||||||
|
astnode: node,
|
||||||
|
code: aboutNode(node),
|
||||||
|
event: "symbolFound",
|
||||||
|
finishers: [currentParser.addDocletRef]
|
||||||
|
};
|
||||||
|
|
||||||
|
e.code.name = (node.type == tkn.NAMEDFUNCTIONSTATEMENT)? '' : String(node.name) || '';
|
||||||
|
//console.log(':: e.code.name is', e.code.name);
|
||||||
|
|
||||||
|
// keep track of vars in a function or global scope
|
||||||
|
var func = "__global__",
|
||||||
|
funcDoc = null;
|
||||||
|
if (node.enclosingFunction) {
|
||||||
|
func = 'astnode'+node.enclosingFunction.hashCode();
|
||||||
|
}
|
||||||
|
funcDoc = currentParser.refs[func];
|
||||||
|
if (funcDoc) {
|
||||||
|
funcDoc.meta.vars = funcDoc.meta.vars || {};
|
||||||
|
funcDoc.meta.vars[e.code.name] = false;
|
||||||
|
e.finishers.push(makeVarsFinisher(funcDoc));
|
||||||
|
}
|
||||||
|
|
||||||
|
var basename = getBasename(e.code.name)
|
||||||
|
e.code.funcscope = currentParser.resolveVar(node, basename);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e) { e = {finishers: []}; }
|
||||||
|
for(var i = 0, l = currentParser._visitors.length; i < l; i++) {
|
||||||
|
currentParser._visitors[i].visitNode(node, e, currentParser, currentSourceName);
|
||||||
|
if (e.stopPropagation) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!e.preventDefault && isValidJsdoc(e.comment)) {
|
||||||
|
currentParser.fire(e.event, e, currentParser);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0, l = e.finishers.length; i < l; i++) {
|
||||||
|
e.finishers[i].call(currentParser, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
exports.Parser.prototype._parseSourceCode = function(sourceCode, sourceName) {
|
exports.Parser.prototype._parseSourceCode = function(sourceCode, sourceName) {
|
||||||
var e = {filename: sourceName};
|
var e = {filename: sourceName};
|
||||||
@ -141,21 +472,6 @@ exports.Parser.prototype._parseSourceCode = function(sourceCode, sourceName) {
|
|||||||
currentSourceName = '';
|
currentSourceName = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function pretreat(code) {
|
|
||||||
return code
|
|
||||||
// make starbangstar comments look like real jsdoc comments
|
|
||||||
.replace(/\/\*\!\*/g, '/**')
|
|
||||||
|
|
||||||
// merge adjacent doclets
|
|
||||||
.replace(/\*\/\/\*\*+/g, '@also')
|
|
||||||
// make lent objectliterals documentable by giving them a dummy name
|
|
||||||
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/\s*)\{/g, '$1 ____ = {') // like return @lends {
|
|
||||||
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/)(\s*)return(\s*)\{/g, '$2$3 return $1 ____ = {'); // like @lends return {
|
|
||||||
}
|
|
||||||
|
|
||||||
var tkn = { NAMEDFUNCTIONSTATEMENT: -1001 };
|
|
||||||
exports.Parser.tkn = tkn;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a node, determine what the node is a member of.
|
* Given a node, determine what the node is a member of.
|
||||||
* @param {astnode} node
|
* @param {astnode} node
|
||||||
@ -331,322 +647,6 @@ exports.Parser.prototype.resolveEnum = function(e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
|
||||||
function visitNode(node) {
|
|
||||||
var e,
|
|
||||||
nodeComments,
|
|
||||||
comment,
|
|
||||||
commentSrc,
|
|
||||||
i,
|
|
||||||
l;
|
|
||||||
|
|
||||||
// look for stand-alone doc comments
|
|
||||||
if (node.type === Token.SCRIPT && node.comments) {
|
|
||||||
// note: ALL comments are seen in this block...
|
|
||||||
nodeComments = node.comments.toArray();
|
|
||||||
for (i = 0, l = nodeComments.length; i < l; i++) {
|
|
||||||
comment = nodeComments[i];
|
|
||||||
if (comment.commentType !== Token.CommentType.JSDOC) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (commentSrc = ''+comment.toSource()) {
|
|
||||||
|
|
||||||
e = {
|
|
||||||
comment: commentSrc,
|
|
||||||
lineno: comment.getLineno(),
|
|
||||||
filename: currentSourceName
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( isValidJsdoc(commentSrc) ) {
|
|
||||||
currentParser.fire('jsdocCommentFound', e, currentParser);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
e = null;
|
|
||||||
}
|
|
||||||
else if (node.type === Token.ASSIGN) {
|
|
||||||
e = {
|
|
||||||
id: 'astnode'+node.hashCode(), // the id of the ASSIGN node
|
|
||||||
comment: String(node.getJsDoc()||'@undocumented'),
|
|
||||||
lineno: node.left.getLineno(),
|
|
||||||
filename: currentSourceName,
|
|
||||||
astnode: node,
|
|
||||||
code: aboutNode(node),
|
|
||||||
event: "symbolFound",
|
|
||||||
finishers: [currentParser.addDocletRef]
|
|
||||||
};
|
|
||||||
|
|
||||||
var basename = getBasename(e.code.name);
|
|
||||||
|
|
||||||
if (basename !== 'this') {
|
|
||||||
e.code.funcscope = currentParser.resolveVar(node, basename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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.getJsDoc()||'@undocumented'),
|
|
||||||
lineno: node.left.getLineno(),
|
|
||||||
filename: currentSourceName,
|
|
||||||
astnode: node,
|
|
||||||
code: aboutNode(node),
|
|
||||||
event: "symbolFound",
|
|
||||||
finishers: [currentParser.addDocletRef, currentParser.resolveEnum]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
|
|
||||||
|
|
||||||
if (node.variables) {
|
|
||||||
return true; // we'll get each var separately on future visits
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.parent.variables.toArray()[0] === node) { // like /** blah */ var a=1, b=2, c=3;
|
|
||||||
// the first var assignment gets any jsDoc before the whole var series
|
|
||||||
if (typeof node.setJsDoc !== 'undefined') { node.setJsDoc( node.parent.getJsDoc() ); }
|
|
||||||
//node.jsDoc = node.parent.jsDoc;
|
|
||||||
}
|
|
||||||
|
|
||||||
e = {
|
|
||||||
id: 'astnode'+node.hashCode(), // the id of the VARIABLE node
|
|
||||||
comment: String(node.getJsDoc()||'@undocumented'),
|
|
||||||
lineno: node.getLineno(),
|
|
||||||
filename: currentSourceName,
|
|
||||||
astnode: node,
|
|
||||||
code: aboutNode(node),
|
|
||||||
event: "symbolFound",
|
|
||||||
finishers: [currentParser.addDocletRef]
|
|
||||||
};
|
|
||||||
|
|
||||||
// keep track of vars in a function or global scope
|
|
||||||
var func = "__global__",
|
|
||||||
funcDoc = null;
|
|
||||||
if (node.enclosingFunction) {
|
|
||||||
func = 'astnode'+node.enclosingFunction.hashCode();
|
|
||||||
}
|
|
||||||
funcDoc = currentParser.refs[func];
|
|
||||||
if (funcDoc) {
|
|
||||||
funcDoc.meta.vars = funcDoc.meta.vars || {};
|
|
||||||
funcDoc.meta.vars[e.code.name] = false;
|
|
||||||
e.finishers.push(makeVarsFinisher(funcDoc));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
|
|
||||||
e = {
|
|
||||||
id: 'astnode'+node.hashCode(), // the id of the COLON node
|
|
||||||
comment: String(node.getJsDoc()||'@undocumented'),
|
|
||||||
lineno: node.getLineno(),
|
|
||||||
filename: currentSourceName,
|
|
||||||
astnode: node,
|
|
||||||
code: aboutNode(node),
|
|
||||||
event: "symbolFound",
|
|
||||||
finishers: [currentParser.addDocletRef]
|
|
||||||
};
|
|
||||||
|
|
||||||
e.code.name = (node.type == tkn.NAMEDFUNCTIONSTATEMENT)? '' : String(node.name) || '';
|
|
||||||
//console.log(':: e.code.name is', e.code.name);
|
|
||||||
|
|
||||||
// keep track of vars in a function or global scope
|
|
||||||
var func = "__global__",
|
|
||||||
funcDoc = null;
|
|
||||||
if (node.enclosingFunction) {
|
|
||||||
func = 'astnode'+node.enclosingFunction.hashCode();
|
|
||||||
}
|
|
||||||
funcDoc = currentParser.refs[func];
|
|
||||||
if (funcDoc) {
|
|
||||||
funcDoc.meta.vars = funcDoc.meta.vars || {};
|
|
||||||
funcDoc.meta.vars[e.code.name] = false;
|
|
||||||
e.finishers.push(makeVarsFinisher(funcDoc));
|
|
||||||
}
|
|
||||||
|
|
||||||
var basename = getBasename(e.code.name)
|
|
||||||
e.code.funcscope = currentParser.resolveVar(node, basename);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e) { e = {finishers: []}; }
|
|
||||||
for(var i = 0, l = currentParser._visitors.length; i < l; i++) {
|
|
||||||
currentParser._visitors[i].visitNode(node, e, currentParser, currentSourceName);
|
|
||||||
if (e.stopPropagation) { break; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!e.preventDefault && isValidJsdoc(e.comment)) {
|
|
||||||
currentParser.fire(e.event, e, currentParser);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0, l = e.finishers.length; i < l; i++) {
|
|
||||||
e.finishers[i].call(currentParser, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
var about = {};
|
|
||||||
|
|
||||||
if (node.type == Token.FUNCTION || node.type == tkn.NAMEDFUNCTIONSTATEMENT) {
|
|
||||||
about.name = node.type == tkn.NAMEDFUNCTIONSTATEMENT? '' : '' + node.name;
|
|
||||||
about.type = 'function';
|
|
||||||
about.node = node;
|
|
||||||
}
|
|
||||||
else if (node.type == Token.VAR || node.type == Token.LET || node.type == Token.CONST) {
|
|
||||||
about.name = nodeToString(node.target);
|
|
||||||
if (node.initializer) { // like var i = 0;
|
|
||||||
about.node = node.initializer;
|
|
||||||
about.value = nodeToString(about.node);
|
|
||||||
about.type = getTypeName(node.initializer);
|
|
||||||
if (about.type === 'FUNCTION' && about.node.name) {
|
|
||||||
about.node.type = tkn.NAMEDFUNCTIONSTATEMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else { // like var i;
|
|
||||||
about.node = node.target;
|
|
||||||
about.value = nodeToString(about.node);
|
|
||||||
about.type = 'undefined';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node.type === Token.ASSIGN || node.type === Token.COLON) {
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (about.type === 'FUNCTION' && about.node.name) {
|
|
||||||
about.node.type = tkn.NAMEDFUNCTIONSTATEMENT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// type 39 (NAME)
|
|
||||||
var string = nodeToString(node);
|
|
||||||
if (string) {
|
|
||||||
about.name = string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// get names of the formal parameters declared for this function
|
|
||||||
if (about.node && about.node.getParamCount) {
|
|
||||||
var paramCount = about.node.getParamCount();
|
|
||||||
if (typeof paramCount === 'number') {
|
|
||||||
about.node.flattenSymbolTable(true);
|
|
||||||
var paramNames = [];
|
|
||||||
for (var i = 0, len = paramCount; i < len; i++) {
|
|
||||||
paramNames.push(''+about.node.getParamOrVarName(i));
|
|
||||||
}
|
|
||||||
about.paramnames = paramNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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 if (node.type === Token.NEG || node.type === Token.TRUE || node.type === Token.FALSE) {
|
|
||||||
str = node.toSource(); // like -1
|
|
||||||
}
|
|
||||||
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 && commentSrc.indexOf('/***') !== 0; /*** ignore comments that start with many stars ***/
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @private
|
|
||||||
* @memberof module:src/parser.Parser
|
|
||||||
*/
|
|
||||||
function makeVarsFinisher(funcDoc) {
|
|
||||||
var func = function(e) {
|
|
||||||
//no need to evaluate all things related to funcDoc again, just use it
|
|
||||||
if (funcDoc && e.doclet && e.doclet.alias) {
|
|
||||||
funcDoc.meta.vars[e.code.name] = e.doclet.longname;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return func;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @private
|
|
||||||
* @memberof module:src/parser.Parser
|
|
||||||
* @param {string} name Full symbol name.
|
|
||||||
* @return {string} Basename.
|
|
||||||
*/
|
|
||||||
function getBasename(name) {
|
|
||||||
if (name !== undefined) {
|
|
||||||
return name.replace(/^([$a-z_][$a-z_0-9]*).*?$/i, '$1');
|
|
||||||
}
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
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.
|
||||||
@event jsdocCommentFound
|
@event jsdocCommentFound
|
||||||
|
|||||||
@ -22,6 +22,45 @@ var jsdoc = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function trim(text, newlines) {
|
||||||
|
if (!text) { return ''; }
|
||||||
|
|
||||||
|
if (newlines) {
|
||||||
|
return text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return text.replace(/^\s+|\s+$/g, '');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse the parameter name and parameter desc from the tag text.
|
||||||
|
@inner
|
||||||
|
@method parseParamText
|
||||||
|
@memberof module:jsdoc/tag
|
||||||
|
@param {string} tagText
|
||||||
|
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
||||||
|
*/
|
||||||
|
function parseParamText(tagText) {
|
||||||
|
var pname, pdesc, poptional, pdefault;
|
||||||
|
|
||||||
|
// like: pname, pname pdesc, or name - pdesc
|
||||||
|
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
||||||
|
pname = RegExp.$1;
|
||||||
|
pdesc = RegExp.$3;
|
||||||
|
|
||||||
|
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
||||||
|
pname = RegExp.$1;
|
||||||
|
poptional = true;
|
||||||
|
|
||||||
|
if ( /^(.+?)\s*=\s*(.+)$/.test(pname) ) {
|
||||||
|
pname = RegExp.$1;
|
||||||
|
pdefault = RegExp.$2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return { name: pname, desc: pdesc, optional: poptional, default: pdefault };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Constructs a new tag object. Calls the tag validator.
|
Constructs a new tag object. Calls the tag validator.
|
||||||
@class
|
@class
|
||||||
@ -99,42 +138,3 @@ exports.Tag = function(tagTitle, tagBody, meta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function trim(text, newlines) {
|
|
||||||
if (!text) { return ''; }
|
|
||||||
|
|
||||||
if (newlines) {
|
|
||||||
return text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return text.replace(/^\s+|\s+$/g, '');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Parse the parameter name and parameter desc from the tag text.
|
|
||||||
@inner
|
|
||||||
@method parseParamText
|
|
||||||
@memberof module:jsdoc/tag
|
|
||||||
@param {string} tagText
|
|
||||||
@returns {Array.<string, string, boolean, boolean>} [pname, pdesc, poptional, pdefault].
|
|
||||||
*/
|
|
||||||
function parseParamText(tagText) {
|
|
||||||
var pname, pdesc, poptional, pdefault;
|
|
||||||
|
|
||||||
// like: pname, pname pdesc, or name - pdesc
|
|
||||||
tagText.match(/^(\[[^\]]+\]|\S+)((?:\s*\-\s*|\s+)(\S[\s\S]*))?$/);
|
|
||||||
pname = RegExp.$1;
|
|
||||||
pdesc = RegExp.$3;
|
|
||||||
|
|
||||||
if ( /^\[\s*(.+?)\s*\]$/.test(pname) ) {
|
|
||||||
pname = RegExp.$1;
|
|
||||||
poptional = true;
|
|
||||||
|
|
||||||
if ( /^(.+?)\s*=\s*(.+)$/.test(pname) ) {
|
|
||||||
pname = RegExp.$1;
|
|
||||||
pdefault = RegExp.$2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { name: pname, desc: pdesc, optional: poptional, default: pdefault };
|
|
||||||
}
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
var _synonyms = {},
|
var _synonyms = {},
|
||||||
_definitions = {},
|
_definitions = {},
|
||||||
_namespaces = [],
|
_namespaces = [],
|
||||||
|
dictionary,
|
||||||
hasOwnProp = Object.prototype.hasOwnProperty;
|
hasOwnProp = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
/** @private */
|
/** @private */
|
||||||
@ -29,7 +30,7 @@ TagDefinition.prototype.synonym = function(synonymName) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** @exports jsdoc/tag/dictionary */
|
/** @exports jsdoc/tag/dictionary */
|
||||||
var dictionary = {
|
dictionary = {
|
||||||
/** @function */
|
/** @function */
|
||||||
defineTag: function(title, opts) {
|
defineTag: function(title, opts) {
|
||||||
_definitions[title] = new TagDefinition(title, opts);
|
_definitions[title] = new TagDefinition(title, opts);
|
||||||
|
|||||||
@ -7,6 +7,91 @@
|
|||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
function setDocletKindToTitle(doclet, tag) {
|
||||||
|
doclet.addTag( 'kind', tag.title );
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocletScopeToTitle(doclet, tag) {
|
||||||
|
doclet.addTag( 'scope', tag.title );
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocletNameToValue(doclet, tag) {
|
||||||
|
if (tag.value && tag.value.description) { // as in a long tag
|
||||||
|
doclet.addTag( 'name', tag.value.description);
|
||||||
|
}
|
||||||
|
else if (tag.text) { // or a short tag
|
||||||
|
doclet.addTag('name', tag.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocletDescriptionToValue(doclet, tag) {
|
||||||
|
if (tag.value) {
|
||||||
|
doclet.addTag( 'description', tag.value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNameToFile(doclet, tag) {
|
||||||
|
if (doclet.meta.filename) {
|
||||||
|
var name = 'file:';
|
||||||
|
if (doclet.meta.path) { name += doclet.meta.path + java.lang.System.getProperty("file.separator"); }
|
||||||
|
doclet.addTag( 'name', name + doclet.meta.filename );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocletMemberof(doclet, tag) {
|
||||||
|
if (tag.value && tag.value !== '<global>') {
|
||||||
|
doclet.setMemberof(tag.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyNamespace(docletOrNs, tag) {
|
||||||
|
if (typeof docletOrNs === 'string') { // ns
|
||||||
|
tag.value = app.jsdoc.name.applyNamespace(tag.value, docletOrNs);
|
||||||
|
}
|
||||||
|
else { // doclet
|
||||||
|
if (!docletOrNs.name) {
|
||||||
|
return; // error?
|
||||||
|
}
|
||||||
|
|
||||||
|
//doclet.displayname = doclet.name;
|
||||||
|
docletOrNs.longname = app.jsdoc.name.applyNamespace(docletOrNs.name, tag.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDocletNameToFilename(doclet, tag) {
|
||||||
|
var name = (doclet.meta.path ? (doclet.meta.path + java.lang.System.getProperty("file.separator")) : "") + doclet.meta.filename;
|
||||||
|
name = name.replace(/\.js$/i, '');
|
||||||
|
|
||||||
|
for (var i = 0, len = env.opts._.length; i < len; i++) {
|
||||||
|
if (name.indexOf(env.opts._[i]) === 0) {
|
||||||
|
name = name.replace(env.opts._[0], '');
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
doclet.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseBorrows(doclet, tag) {
|
||||||
|
var m = /^(\S+)(?:\s+as\s+(\S+))?$/.exec(tag.text);
|
||||||
|
if (m) {
|
||||||
|
if (m[1] && m[2]) {
|
||||||
|
return { target: m[1], source: m[2] };
|
||||||
|
}
|
||||||
|
else if (m[1]) {
|
||||||
|
return { target: m[1] };
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function firstWordOf(string) {
|
||||||
|
var m = /^(\S+)/.exec(string);
|
||||||
|
if (m) { return m[1]; }
|
||||||
|
else { return ''; }
|
||||||
|
}
|
||||||
|
|
||||||
/** Populate the given dictionary with all known JSDoc tag definitions.
|
/** Populate the given dictionary with all known JSDoc tag definitions.
|
||||||
@param {module:jsdoc/tag/dictionary} dictionary
|
@param {module:jsdoc/tag/dictionary} dictionary
|
||||||
*/
|
*/
|
||||||
@ -561,88 +646,3 @@ exports.defineTags = function(dictionary) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @private */
|
|
||||||
function setDocletKindToTitle(doclet, tag) {
|
|
||||||
doclet.addTag( 'kind', tag.title );
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDocletScopeToTitle(doclet, tag) {
|
|
||||||
doclet.addTag( 'scope', tag.title );
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDocletNameToValue(doclet, tag) {
|
|
||||||
if (tag.value && tag.value.description) { // as in a long tag
|
|
||||||
doclet.addTag( 'name', tag.value.description);
|
|
||||||
}
|
|
||||||
else if (tag.text) { // or a short tag
|
|
||||||
doclet.addTag('name', tag.text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDocletDescriptionToValue(doclet, tag) {
|
|
||||||
if (tag.value) {
|
|
||||||
doclet.addTag( 'description', tag.value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setNameToFile(doclet, tag) {
|
|
||||||
if (doclet.meta.filename) {
|
|
||||||
var name = 'file:';
|
|
||||||
if (doclet.meta.path) { name += doclet.meta.path + java.lang.System.getProperty("file.separator"); }
|
|
||||||
doclet.addTag( 'name', name + doclet.meta.filename );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDocletMemberof(doclet, tag) {
|
|
||||||
if (tag.value && tag.value !== '<global>') {
|
|
||||||
doclet.setMemberof(tag.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function applyNamespace(docletOrNs, tag) {
|
|
||||||
if (typeof docletOrNs === 'string') { // ns
|
|
||||||
tag.value = app.jsdoc.name.applyNamespace(tag.value, docletOrNs);
|
|
||||||
}
|
|
||||||
else { // doclet
|
|
||||||
if (!docletOrNs.name) {
|
|
||||||
return; // error?
|
|
||||||
}
|
|
||||||
|
|
||||||
//doclet.displayname = doclet.name;
|
|
||||||
docletOrNs.longname = app.jsdoc.name.applyNamespace(docletOrNs.name, tag.title);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setDocletNameToFilename(doclet, tag) {
|
|
||||||
var name = (doclet.meta.path ? (doclet.meta.path + java.lang.System.getProperty("file.separator")) : "") + doclet.meta.filename;
|
|
||||||
name = name.replace(/\.js$/i, '');
|
|
||||||
|
|
||||||
for (var i = 0, len = env.opts._.length; i < len; i++) {
|
|
||||||
if (name.indexOf(env.opts._[i]) === 0) {
|
|
||||||
name = name.replace(env.opts._[0], '');
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
doclet.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseBorrows(doclet, tag) {
|
|
||||||
var m = /^(\S+)(?:\s+as\s+(\S+))?$/.exec(tag.text);
|
|
||||||
if (m) {
|
|
||||||
if (m[1] && m[2]) {
|
|
||||||
return { target: m[1], source: m[2] };
|
|
||||||
}
|
|
||||||
else if (m[1]) {
|
|
||||||
return { target: m[1] };
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function firstWordOf(string) {
|
|
||||||
var m = /^(\S+)/.exec(string);
|
|
||||||
if (m) { return m[1]; }
|
|
||||||
else { return ''; }
|
|
||||||
}
|
|
||||||
|
|||||||
@ -6,43 +6,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
@param {string} tagValue
|
|
||||||
@returns {object} Hash with type, text, optional, nullable, and variable properties
|
|
||||||
*/
|
|
||||||
exports.parse = function(tagValue) {
|
|
||||||
if (typeof tagValue !== 'string') { tagValue = ''; }
|
|
||||||
var type = '',
|
|
||||||
text = '',
|
|
||||||
tagType,
|
|
||||||
optional,
|
|
||||||
nullable,
|
|
||||||
variable;
|
|
||||||
|
|
||||||
tagType = getTagType(tagValue);
|
|
||||||
type = tagType.type;
|
|
||||||
if (tagType.type === '') {
|
|
||||||
text = tagValue;
|
|
||||||
} else {
|
|
||||||
text = tagType.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional = parseOptional(type);
|
|
||||||
nullable = parseNullable(type);
|
|
||||||
variable = parseVariable(type);
|
|
||||||
type = variable.type || nullable.type || optional.type;
|
|
||||||
|
|
||||||
type = parseTypes(type); // make it into an array
|
|
||||||
|
|
||||||
return {
|
|
||||||
type: type,
|
|
||||||
text: text,
|
|
||||||
optional: optional.optional,
|
|
||||||
nullable: nullable.nullable,
|
|
||||||
variable: variable.variable
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseOptional(type) {
|
function parseOptional(type) {
|
||||||
var optional = null;
|
var optional = null;
|
||||||
|
|
||||||
@ -97,6 +60,11 @@ function parseTypes(type) {
|
|||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @private */
|
||||||
|
function trim(text) {
|
||||||
|
return text.trim();
|
||||||
|
}
|
||||||
|
|
||||||
function getTagType(tagValue) {
|
function getTagType(tagValue) {
|
||||||
var type = '',
|
var type = '',
|
||||||
text = '',
|
text = '',
|
||||||
@ -126,7 +94,40 @@ function getTagType(tagValue) {
|
|||||||
}
|
}
|
||||||
exports.getTagType = getTagType;
|
exports.getTagType = getTagType;
|
||||||
|
|
||||||
/** @private */
|
|
||||||
function trim(text) {
|
/**
|
||||||
return text.trim();
|
@param {string} tagValue
|
||||||
|
@returns {object} Hash with type, text, optional, nullable, and variable properties
|
||||||
|
*/
|
||||||
|
exports.parse = function(tagValue) {
|
||||||
|
if (typeof tagValue !== 'string') { tagValue = ''; }
|
||||||
|
var type = '',
|
||||||
|
text = '',
|
||||||
|
tagType,
|
||||||
|
optional,
|
||||||
|
nullable,
|
||||||
|
variable;
|
||||||
|
|
||||||
|
tagType = getTagType(tagValue);
|
||||||
|
type = tagType.type;
|
||||||
|
if (tagType.type === '') {
|
||||||
|
text = tagValue;
|
||||||
|
} else {
|
||||||
|
text = tagType.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional = parseOptional(type);
|
||||||
|
nullable = parseNullable(type);
|
||||||
|
variable = parseVariable(type);
|
||||||
|
type = variable.type || nullable.type || optional.type;
|
||||||
|
|
||||||
|
type = parseTypes(type); // make it into an array
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: type,
|
||||||
|
text: text,
|
||||||
|
optional: optional.optional,
|
||||||
|
nullable: nullable.nullable,
|
||||||
|
variable: variable.variable
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,6 +10,24 @@
|
|||||||
|
|
||||||
var dictionary = require('jsdoc/tag/dictionary');
|
var dictionary = require('jsdoc/tag/dictionary');
|
||||||
|
|
||||||
|
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, meta) {
|
||||||
|
this.name = 'TagValueNotPermittedError';
|
||||||
|
this.message = 'The @' + tagName + ' tag does not permit a value. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
||||||
|
}
|
||||||
|
TagValueNotPermittedError.prototype = Error.prototype;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Validate the given tag.
|
Validate the given tag.
|
||||||
*/
|
*/
|
||||||
@ -31,22 +49,3 @@ exports.validate = function(tag, 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) {
|
|
||||||
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, meta) {
|
|
||||||
this.name = 'TagValueNotPermittedError';
|
|
||||||
this.message = 'The @' + tagName + ' tag does not permit a value. File: ' + meta.filename + ', Line: ' + meta.lineno + '\n' + meta.comment;
|
|
||||||
}
|
|
||||||
TagValueNotPermittedError.prototype = Error.prototype;
|
|
||||||
|
|
||||||
|
|||||||
@ -5,18 +5,6 @@
|
|||||||
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
@license Apache License 2.0 - See file 'LICENSE.md' in this project.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
@param {any} object
|
|
||||||
*/
|
|
||||||
exports.dump = function(object) {
|
|
||||||
indentBy = 0;
|
|
||||||
output = '';
|
|
||||||
|
|
||||||
walk(object);
|
|
||||||
outdent(false);
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
const INDENTATION = ' '; // 4 spaces
|
const INDENTATION = ' '; // 4 spaces
|
||||||
var indentBy,
|
var indentBy,
|
||||||
output;
|
output;
|
||||||
@ -62,6 +50,45 @@ seen.has = function(object) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function stringify(o) {
|
||||||
|
return JSON.stringify(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getValue(o) { // see: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof
|
||||||
|
if (o === null) { return 'null'; }
|
||||||
|
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
|
||||||
|
return ''+stringify(o);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
|
||||||
|
return (typeof o === 'object' && typeof o.constructor === 'undefined');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isArray(o) {
|
||||||
|
return o && (o instanceof Array) || o.constructor === Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isRegExp(o) {
|
||||||
|
return (o instanceof RegExp) ||
|
||||||
|
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDate(o) {
|
||||||
|
return o && (o instanceof Date) ||
|
||||||
|
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isFunction(o) {
|
||||||
|
return o && (typeof o === 'function' || o instanceof Function);// ||
|
||||||
|
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
|
||||||
|
}
|
||||||
|
|
||||||
|
function isObject(o) {
|
||||||
|
return o && o instanceof Object ||
|
||||||
|
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
|
||||||
|
}
|
||||||
|
|
||||||
function walk(object) {
|
function walk(object) {
|
||||||
var value;
|
var value;
|
||||||
|
|
||||||
@ -116,42 +143,14 @@ function walk(object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function getValue(o) { // see: https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special/typeof
|
/**
|
||||||
if (o === null) { return 'null'; }
|
@param {any} object
|
||||||
if ( /^(string|boolean|number|undefined)$/.test(typeof o) ) {
|
*/
|
||||||
return ''+stringify(o);
|
exports.dump = function(object) {
|
||||||
}
|
indentBy = 0;
|
||||||
}
|
output = '';
|
||||||
|
|
||||||
function stringify(o) {
|
walk(object);
|
||||||
return JSON.stringify(o);
|
outdent(false);
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isUnwalkable(o) { // some objects are unwalkable, like Java native objects
|
|
||||||
return (typeof o === 'object' && typeof o.constructor === 'undefined');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isArray(o) {
|
|
||||||
return o && (o instanceof Array) || o.constructor === Array;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isRegExp(o) {
|
|
||||||
return (o instanceof RegExp) ||
|
|
||||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'RegExp');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDate(o) {
|
|
||||||
return o && (o instanceof Date) ||
|
|
||||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Date');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isFunction(o) {
|
|
||||||
return o && (typeof o === 'function' || o instanceof Function);// ||
|
|
||||||
//(typeof o.constructor !== 'undefined' && (o.constructor||{}).name === 'Function');
|
|
||||||
}
|
|
||||||
|
|
||||||
function isObject(o) {
|
|
||||||
return o && o instanceof Object ||
|
|
||||||
(typeof o.constructor !== 'undefined' && o.constructor.name === 'Object');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@ -5,59 +5,23 @@
|
|||||||
var hash = require('pajhome/hash');
|
var hash = require('pajhome/hash');
|
||||||
var dictionary = require('jsdoc/tag/dictionary');
|
var dictionary = require('jsdoc/tag/dictionary');
|
||||||
|
|
||||||
exports.globalName = 'global';
|
var files = {};
|
||||||
exports.fileExtension = '.html';
|
|
||||||
|
|
||||||
/** Find symbol {@link ...} and {@tutorial ...} strings in text and turn into html links */
|
|
||||||
exports.resolveLinks = function(str) {
|
|
||||||
str = str.replace(/(?:\[(.+?)\])?\{@link +(.+?)\}/gi,
|
|
||||||
function(match, content, longname) {
|
|
||||||
return toLink(longname, content);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
str = str.replace(/(?:\[(.+?)\])?\{@tutorial +(.+?)\}/gi,
|
|
||||||
function(match, content, tutorial) {
|
|
||||||
return toTutorial(tutorial, content);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
|
|
||||||
// two-way lookup
|
|
||||||
var linkMap = {
|
|
||||||
longnameToUrl: {},
|
|
||||||
urlToLongname: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.registerLink = function(longname, url) {
|
|
||||||
linkMap.longnameToUrl[longname] = url;
|
|
||||||
linkMap.urlToLongname[url] = longname;
|
|
||||||
}
|
|
||||||
|
|
||||||
// each container gets its own html file
|
// each container gets its own html file
|
||||||
var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
|
var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
|
||||||
|
|
||||||
/** Turn a doclet into a URL. */
|
/** @external {jsdoc.tutorial.Tutorial} */
|
||||||
exports.createLink = function(doclet) {
|
var tutorials;
|
||||||
var url = '';
|
|
||||||
|
|
||||||
if (containers.indexOf(doclet.kind) < 0) {
|
/** Sets tutorials map.
|
||||||
var longname = doclet.longname,
|
@param {jsdoc.tutorial.Tutorial} root - Root tutorial node.
|
||||||
filename = strToFilename(doclet.memberof || exports.globalName);
|
*/
|
||||||
|
exports.setTutorials = function(root) {
|
||||||
|
tutorials = root;
|
||||||
|
};
|
||||||
|
|
||||||
url = filename + exports.fileExtension + '#' + getNamespace(doclet.kind) + doclet.name;
|
exports.globalName = 'global';
|
||||||
}
|
exports.fileExtension = '.html';
|
||||||
else {
|
|
||||||
var longname = doclet.longname,
|
|
||||||
filename = strToFilename(longname);
|
|
||||||
|
|
||||||
url = filename + exports.fileExtension;
|
|
||||||
}
|
|
||||||
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNamespace(kind) {
|
function getNamespace(kind) {
|
||||||
if (dictionary.isNamespace(kind)) {
|
if (dictionary.isNamespace(kind)) {
|
||||||
@ -66,6 +30,15 @@ function getNamespace(kind) {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function makeFilenameUnique(filename, str) {
|
||||||
|
//add suffix underscore until filename gets unique
|
||||||
|
while (filename in files && files[filename] !== str) {
|
||||||
|
filename += '_';
|
||||||
|
}
|
||||||
|
files[filename] = str;
|
||||||
|
return filename;
|
||||||
|
}
|
||||||
|
|
||||||
// compute it here just once
|
// compute it here just once
|
||||||
var nsprefix = /^(event|module|external):/;
|
var nsprefix = /^(event|module|external):/;
|
||||||
|
|
||||||
@ -79,15 +52,15 @@ function strToFilename(str) {
|
|||||||
return makeFilenameUnique(basename, str);
|
return makeFilenameUnique(basename, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
var files = {};
|
// two-way lookup
|
||||||
|
var linkMap = {
|
||||||
|
longnameToUrl: {},
|
||||||
|
urlToLongname: {}
|
||||||
|
};
|
||||||
|
|
||||||
function makeFilenameUnique(filename, str) {
|
exports.registerLink = function(longname, url) {
|
||||||
//add suffix underscore until filename gets unique
|
linkMap.longnameToUrl[longname] = url;
|
||||||
while (filename in files && files[filename] !== str) {
|
linkMap.urlToLongname[url] = longname;
|
||||||
filename += '_';
|
|
||||||
}
|
|
||||||
files[filename] = str;
|
|
||||||
return filename;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function toLink(longname, content) {
|
function toLink(longname, content) {
|
||||||
@ -121,16 +94,6 @@ function toLink(longname, content) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @external {jsdoc.tutorial.Tutorial} */
|
|
||||||
var tutorials;
|
|
||||||
|
|
||||||
/** Sets tutorials map.
|
|
||||||
@param {jsdoc.tutorial.Tutorial} root - Root tutorial node.
|
|
||||||
*/
|
|
||||||
exports.setTutorials = function(root) {
|
|
||||||
tutorials = root;
|
|
||||||
};
|
|
||||||
|
|
||||||
var toTutorial = exports.toTutorial = function(tutorial, content) {
|
var toTutorial = exports.toTutorial = function(tutorial, content) {
|
||||||
if (!tutorial) {
|
if (!tutorial) {
|
||||||
throw new Error('Missing required parameter: tutorial');
|
throw new Error('Missing required parameter: tutorial');
|
||||||
@ -147,6 +110,43 @@ var toTutorial = exports.toTutorial = function(tutorial, content) {
|
|||||||
return '<a href="'+exports.tutorialToUrl(tutorial)+'">'+content+'</a>';
|
return '<a href="'+exports.tutorialToUrl(tutorial)+'">'+content+'</a>';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Find symbol {@link ...} and {@tutorial ...} strings in text and turn into html links */
|
||||||
|
exports.resolveLinks = function(str) {
|
||||||
|
str = str.replace(/(?:\[(.+?)\])?\{@link +(.+?)\}/gi,
|
||||||
|
function(match, content, longname) {
|
||||||
|
return toLink(longname, content);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
str = str.replace(/(?:\[(.+?)\])?\{@tutorial +(.+?)\}/gi,
|
||||||
|
function(match, content, tutorial) {
|
||||||
|
return toTutorial(tutorial, content);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Turn a doclet into a URL. */
|
||||||
|
exports.createLink = function(doclet) {
|
||||||
|
var url = '';
|
||||||
|
|
||||||
|
if (containers.indexOf(doclet.kind) < 0) {
|
||||||
|
var longname = doclet.longname,
|
||||||
|
filename = strToFilename(doclet.memberof || exports.globalName);
|
||||||
|
|
||||||
|
url = filename + exports.fileExtension + '#' + getNamespace(doclet.kind) + doclet.name;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var longname = doclet.longname,
|
||||||
|
filename = strToFilename(longname);
|
||||||
|
|
||||||
|
url = filename + exports.fileExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
exports.longnameToUrl = linkMap.longnameToUrl;
|
exports.longnameToUrl = linkMap.longnameToUrl;
|
||||||
|
|
||||||
exports.tutorialToUrl = function(tutorial) {
|
exports.tutorialToUrl = function(tutorial) {
|
||||||
|
|||||||
@ -381,6 +381,20 @@
|
|||||||
// once for all
|
// once for all
|
||||||
view.nav = nav;
|
view.nav = nav;
|
||||||
|
|
||||||
|
function generate(title, docs, filename) {
|
||||||
|
var data = {
|
||||||
|
title: title,
|
||||||
|
docs: docs
|
||||||
|
};
|
||||||
|
|
||||||
|
var path = outdir + '/' + filename,
|
||||||
|
html = view.render('container.tmpl', data);
|
||||||
|
|
||||||
|
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
|
||||||
|
|
||||||
|
fs.writeFileSync(path, html)
|
||||||
|
}
|
||||||
|
|
||||||
for (var longname in helper.longnameToUrl) {
|
for (var longname in helper.longnameToUrl) {
|
||||||
if ( hasOwnProp.call(helper.longnameToUrl, longname) ) {
|
if ( hasOwnProp.call(helper.longnameToUrl, longname) ) {
|
||||||
var classes = find({kind: 'class', longname: longname});
|
var classes = find({kind: 'class', longname: longname});
|
||||||
@ -416,20 +430,6 @@
|
|||||||
, 'index.html');
|
, 'index.html');
|
||||||
|
|
||||||
|
|
||||||
function generate(title, docs, filename) {
|
|
||||||
var data = {
|
|
||||||
title: title,
|
|
||||||
docs: docs
|
|
||||||
};
|
|
||||||
|
|
||||||
var path = outdir + '/' + filename,
|
|
||||||
html = view.render('container.tmpl', data);
|
|
||||||
|
|
||||||
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
|
|
||||||
|
|
||||||
fs.writeFileSync(path, html)
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateTutorial(title, tutorial, filename) {
|
function generateTutorial(title, tutorial, filename) {
|
||||||
var data = {
|
var data = {
|
||||||
title: title,
|
title: title,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user