Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jsdoc

Package Overview
Dependencies
Maintainers
2
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsdoc - npm Package Compare versions

Comparing version 3.3.0-alpha5 to 3.3.0-alpha7

97

cli.js

@@ -0,1 +1,3 @@

/*global java */
/*eslint no-process-exit:0 */
/**

@@ -18,2 +20,3 @@ * Helper methods for running JSDoc on the command line.

var logger = require('jsdoc/util/logger');
var stripJsonComments = require('strip-json-comments');

@@ -88,3 +91,3 @@ var hasOwnProp = Object.prototype.hasOwnProperty;

try {
env.conf = new Config( fs.readFileSync(confPath, 'utf8') )
env.conf = new Config( stripJsonComments(fs.readFileSync(confPath, 'utf8')) )
.get();

@@ -234,2 +237,6 @@ }

}
else {
console.log('There are no input files to process.\n');
cli.printHelp(cb);
}

@@ -248,74 +255,2 @@ env.run.finish = new Date();

// TODO: docs
function createTempDir() {
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var wrench = require('wrench');
var isRhino;
var tempDirname;
var tempPath;
// We only need one temp directory
if (props.tmpdir) {
return props.tmpdir;
}
isRhino = require('jsdoc/util/runtime').isRhino();
tempDirname = 'tmp-' + Date.now() + '-' + getRandomId();
tempPath = path.join(env.dirname, tempDirname);
try {
fs.mkdirSync(tempPath);
props.tmpdir = tempPath;
}
catch (e) {
logger.fatal('Unable to create the temp directory %s: %s', tempPath, e.message);
return null;
}
try {
// Delete the temp directory on exit
if (isRhino) {
( new java.io.File(tempPath) ).deleteOnExit();
}
else {
process.on('exit', function() {
wrench.rmdirSyncRecursive(tempPath);
});
}
return tempPath;
}
catch (e) {
logger.error('Cannot automatically delete the temp directory %s on exit: %s', tempPath,
e.message);
return null;
}
}
// TODO: docs
function copyResourceDir(filepath) {
var fs = require('jsdoc/fs');
var path = require('jsdoc/path');
var wrench = require('wrench');
var resourceDir;
var tmpDir;
try {
tmpDir = createTempDir();
resourceDir = path.join( tmpDir, path.basename(filepath) + '-' + getRandomId() );
fs.mkdirSync(resourceDir);
wrench.copyDirSyncRecursive(filepath, resourceDir);
return resourceDir;
}
catch (e) {
logger.fatal('Unable to copy %s to the temp directory %s: %s', filepath, resourceDir,
e.message);
return null;
}
}
// TODO: docs
cli.scanFiles = function() {

@@ -352,3 +287,3 @@ var Filter = require('jsdoc/src/filter').Filter;

env.sourceFiles = app.jsdoc.scanner.scan(env.opts._, (env.opts.recurse? 10 : undefined),
env.sourceFiles = app.jsdoc.scanner.scan(env.opts._, (env.opts.recurse ? 10 : undefined),
filter);

@@ -375,6 +310,2 @@ }

}
// On Node.js, the plugin needs to be inside the JSDoc directory
else if ( isNode && (pluginPath.indexOf(global.env.dirname) !== 0) ) {
pluginPath = copyResourceDir(pluginPath);
}

@@ -408,3 +339,4 @@ pluginPaths.push( path.join(pluginPath, basename) );

var borrow = require('jsdoc/borrow');
var Package = require('jsdoc/package').Package;
// Prevent Requizzle from picking up package.json. See #662.
var Package = require('./lib/jsdoc/package').Package;

@@ -472,9 +404,2 @@ var docs;

if (templatePath && isNode) {
// On Node.js, the template needs to be inside the JSDoc folder
if (templatePath.indexOf(env.dirname) !== 0) {
templatePath = copyResourceDir(templatePath);
}
}
// if we didn't find the template, keep the user-specified value so the error message is

@@ -481,0 +406,0 @@ // useful

42

jsdoc.js
#!/usr/bin/env node
/*global arguments, require: true */
/**

@@ -86,8 +87,21 @@ * @project jsdoc

(function(args) {
'use strict';
var path;
if (args[0] && typeof args[0] === 'object') {
// we should be on Node.js
args = [__dirname, process.cwd()];
path = require('path');
// Create a custom require method that adds `lib/jsdoc` to the module lookup path.
// This makes it possible to `require('jsdoc/foo')` from external templates and plugins,
// and within JSDoc itself.
require = require('requizzle')({
requirePaths: [path.join(__dirname, 'lib')],
infect: true
});
}
require('jsdoc/util/runtime').initialize(args);
require('./lib/jsdoc/util/runtime').initialize(args);
})( Array.prototype.slice.call(arguments, 0) );

@@ -103,5 +117,5 @@

jsdoc: {
scanner: new (require('jsdoc/src/scanner').Scanner)(),
name: require('./lib/jsdoc/name'),
parser: null,
name: require('jsdoc/name')
scanner: new (require('./lib/jsdoc/src/scanner').Scanner)()
}

@@ -121,4 +135,6 @@ };

global.dump = function() {
var doop = require('jsdoc/util/doop').doop;
var _dump = require('jsdoc/util/dumper').dump;
'use strict';
var doop = require('./lib/jsdoc/util/doop').doop;
var _dump = require('./lib/jsdoc/util/dumper').dump;
for (var i = 0, l = arguments.length; i < l; i++) {

@@ -132,7 +148,10 @@ console.log( _dump(doop(arguments[i])) );

var logger = require('jsdoc/util/logger');
var path = require('jsdoc/path');
var runtime = require('jsdoc/util/runtime');
var logger = require('./lib/jsdoc/util/logger');
var runtime = require('./lib/jsdoc/util/runtime');
var cli = require('./cli');
var cli = require( path.join(global.env.dirname, 'cli') );
function cb(errorCode) {
cli.logFinish();
cli.exit(errorCode || 0);
}

@@ -148,7 +167,2 @@ cli.setVersionInfo()

function cb(errorCode) {
cli.logFinish();
cli.exit(errorCode || 0);
}
// On Rhino, we use a try/catch block so we can log the Java exception (if available)

@@ -155,0 +169,0 @@ if ( runtime.isRhino() ) {

@@ -12,3 +12,3 @@ 'use strict';

doc = doclets[i];
if (doc.kind === "class" || doc.kind === "external") {
if (doc.kind === 'class' || doc.kind === 'external') {
dependencies[name] = {};

@@ -67,3 +67,3 @@ len = doc.augments && doc.augments.length || 0;

candidate = docs[i];
if (candidate.memberof === longname && candidate.scope === "instance") {
if (candidate.memberof === longname && candidate.scope === 'instance') {
members.push(candidate);

@@ -76,3 +76,3 @@ }

function getAdditions(doclets, docs, longnames) {
var doop = require("jsdoc/util/doop").doop;
var doop = require('jsdoc/util/doop');

@@ -92,3 +92,3 @@ var additions = [];

parents = doc.augments;
if (parents && doc.kind === "class") {
if (parents && doc.kind === 'class') {
for (var j = 0, jj = parents.length; j < jj; j++) {

@@ -106,5 +106,5 @@ members = getMembers(parents[j], docs);

member.memberof = doc.longname;
parts = member.longname.split("#");
parts = member.longname.split('#');
parts[0] = doc.longname;
member.longname = parts.join("#");
member.longname = parts.join('#');

@@ -111,0 +111,0 @@ // if the child doesn't override the parent member, add the parent member

@@ -34,2 +34,3 @@ /**

exports.resolveBorrows = function(docs) {
/*eslint max-nested-callbacks:[2, 3] */
if (!docs.index) {

@@ -59,3 +60,4 @@ logger.error('Unable to resolve borrowed symbols, because the docs have not been indexed.');

clone.memberof = doc.longname;
clone.longname = clone.memberof + (clone.scope === 'instance'? '#': '.') + clone.name;
clone.longname = clone.memberof + (clone.scope === 'instance' ? '#' : '.') +
clone.name;
docs.push(clone);

@@ -62,0 +64,0 @@ });

@@ -28,14 +28,14 @@ /**

var defaults = {
"tags": {
"allowUnknownTags": true
tags: {
allowUnknownTags: true
},
"templates": {
"monospaceLinks": false,
"cleverLinks": false
templates: {
monospaceLinks: false,
cleverLinks: false
},
"source": {
"includePattern": ".+\\.js(doc)?$",
"excludePattern": ""
source: {
includePattern: '.+\\.js(doc)?$',
excludePattern: ''
},
"plugins": []
plugins: []
};

@@ -49,3 +49,3 @@

function Config(json) {
json = JSON.parse( (json || "{}") );
json = JSON.parse( (json || '{}') );
this._config = mergeRecurse(defaults, json);

@@ -52,0 +52,0 @@ }

@@ -16,2 +16,3 @@ /**

src: {
astnode: require('jsdoc/src/astnode'),
Syntax: require('jsdoc/src/syntax').Syntax

@@ -28,11 +29,5 @@ },

var path = require('jsdoc/path');
var Syntax = jsdoc.src.Syntax;
var util = require('util');
// Longname used for doclets whose actual longname cannot be identified.
exports.ANONYMOUS_LONGNAME = '<anonymous>';
// Longname used for doclets in global scope.
exports.GLOBAL_LONGNAME = '<global>';
// Special tag identifying undocumented symbols; not to be used in actual JSDoc comments.
exports.UNDOCUMENTED_TAG = '@undocumented';
function applyTag(doclet, tag) {

@@ -53,9 +48,21 @@ if (tag.title === 'name') {

// use the meta info about the source code to guess what the doclet kind should be
function codetypeToKind(type) {
var Syntax = jsdoc.src.Syntax;
if (type === Syntax.FunctionDeclaration || type === Syntax.FunctionExpression) {
return 'function';
function codeToKind(code) {
var parent;
var isFunction = jsdoc.src.astnode.isFunction;
// default
var kind = 'member';
if (code.type === Syntax.FunctionDeclaration || code.type === Syntax.FunctionExpression) {
kind = 'function';
}
else if (code.node && code.node.parent) {
parent = code.node.parent;
if ( isFunction(parent) ) {
kind = 'param';
}
}
return 'member';
return kind;
}

@@ -72,3 +79,3 @@

docletSrc.replace(/^\/\*\*+/, '') // remove opening slash+stars
.replace(/\**\*\/$/, "\\Z") // replace closing star slash with end-marker
.replace(/\**\*\/$/, '\\Z') // replace closing star slash with end-marker
.replace(/^\s*(\* ?|\\Z)/gm, '') // remove left margin like: spaces+star or spaces+end-marker

@@ -173,7 +180,7 @@ .replace(/\s*\\Z$/g, ''); // remove end-marker

if (this.memberof === '') {
delete(this.memberof);
delete this.memberof;
}
if (!this.kind && this.meta && this.meta.code) {
this.addTag( 'kind', codetypeToKind(this.meta.code.type) );
this.addTag( 'kind', codeToKind(this.meta.code) );
}

@@ -218,3 +225,3 @@

function removeGlobal(longname) {
var globalRegexp = new RegExp('^' + exports.GLOBAL_LONGNAME + '\\.?');
var globalRegexp = new RegExp('^' + jsdoc.name.GLOBAL_LONGNAME + '\\.?');

@@ -221,0 +228,0 @@ return longname.replace(globalRegexp, '');

@@ -11,7 +11,10 @@ /**

var _ = require('underscore');
var jsdoc = {
doclet: require('jsdoc/doclet'),
tagDictionary: require('jsdoc/tag/dictionary')
};
// Longname used for doclets whose actual longname cannot be identified.
var ANONYMOUS_LONGNAME = exports.ANONYMOUS_LONGNAME = '<anonymous>';
// Longname used for doclets in global scope.
var GLOBAL_LONGNAME = exports.GLOBAL_LONGNAME = '<global>';
var INNER = exports.INNER = '~';
var INSTANCE = exports.INSTANCE = '#';
var MODULE_PREFIX = exports.MODULE_PREFIX = 'module:';
// Scope identifiers.

@@ -24,4 +27,2 @@ var SCOPE_NAMES = exports.SCOPE_NAMES = {

};
var INNER = exports.INNER = '~';
var INSTANCE = exports.INSTANCE = '#';
var STATIC = exports.STATIC = '.';

@@ -35,6 +36,15 @@ var scopeToPunc = exports.scopeToPunc = {

var MODULE_PREFIX = exports.MODULE_PREFIX = 'module:';
var DEFAULT_SCOPE = SCOPE_NAMES.static;
var REGEXP_SCOPE_PUNC = '([' + INNER + INSTANCE + STATIC + '])';
function nameIsLongname(name, memberof) {
var regexp = new RegExp('^' + memberof + REGEXP_SCOPE_PUNC);
return regexp.test(name);
}
function prototypeToPunc(name) {
return name.replace(/(?:^|\.)prototype\.?/g, INSTANCE);
}
/**

@@ -45,10 +55,10 @@ Resolves the longname, memberof, variation and name values of the given doclet.

exports.resolve = function(doclet) {
var name = doclet.name ? String(doclet.name) : '',
memberof = doclet.memberof || '',
about = {},
scopePunc = '([' + INNER + INSTANCE + STATIC + '])',
leadingScope = new RegExp('^' + scopePunc),
trailingScope = new RegExp(scopePunc + '$'),
parentDoc;
var about = {};
var leadingScope = new RegExp('^' + REGEXP_SCOPE_PUNC);
var memberof = doclet.memberof || '';
var name = doclet.name ? String(doclet.name) : '';
var trailingScope = new RegExp(REGEXP_SCOPE_PUNC + '$');
var parentDoc;
// change MyClass.prototype.instanceMethod to MyClass#instanceMethod

@@ -58,3 +68,3 @@ // (but not in function params, which lack doclet.kind)

if (name && doclet.kind) {
name = name.replace(/(?:^|\.)prototype\.?/g, INSTANCE);
name = prototypeToPunc(name);
}

@@ -69,6 +79,6 @@ doclet.name = name;

if (memberof || doclet.forceMemberof) { // @memberof tag given
memberof = ('' || memberof).replace(/\.prototype\.?/g, INSTANCE);
memberof = prototypeToPunc(memberof);
// the name is a fullname, like @name foo.bar, @memberof foo
if (name && name.indexOf(memberof) === 0 && name !== memberof) {
// the name is a complete longname, like @name foo.bar, @memberof foo
if (name && nameIsLongname(name, memberof) && name !== memberof) {
about = exports.shorten(name, (doclet.forceMemberof ? memberof : undefined));

@@ -108,3 +118,3 @@ }

if (about.longname && !doclet.longname) {
if (about.longname && (!doclet.longname || doclet.longname === doclet.name)) {
doclet.setLongname(about.longname);

@@ -118,3 +128,3 @@ }

else if (about.scope) {
if (about.memberof === jsdoc.doclet.GLOBAL_LONGNAME) { // via @memberof <global> ?
if (about.memberof === GLOBAL_LONGNAME) { // via @memberof <global> ?
doclet.scope = 'global';

@@ -143,25 +153,13 @@ }

}
};
/**
@inner
@memberof module:jsdoc/name
@param {string} name
@param {string} kind
@returns {string} The name with unsafe names enclosed in quotes.
*/
function quoteUnsafe(name, kind) { // docspaced names may have unsafe characters which need to be quoted by us
if ( (jsdoc.tagDictionary.lookUp(kind).setsDocletDocspace) && /[^$_a-zA-Z0-9\/]/.test(name) ) {
if (!/^[a-z_$-\/]+:\"/i.test(name)) {
return '"' + name.replace(/\"/g, '"') + '"';
}
// if we never found a longname, just use an empty string
if (!doclet.longname) {
doclet.longname = '';
}
};
return name;
}
// TODO: make this a private method, or remove it if possible
RegExp.escape = RegExp.escape || function(str) {
var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
return str.replace(specials, "\\$&");
var specials = new RegExp('[.*+?|()\\[\\]{}\\\\]', 'g'); // .*+?|()[]{}\
return str.replace(specials, '\\$&');
};

@@ -181,3 +179,3 @@

if ( !/^[a-zA-Z]+?:.+$/i.test(name) ) {
longname = longname.replace( new RegExp(RegExp.escape(name)+'$'), ns + ':' + name );
longname = longname.replace( new RegExp(RegExp.escape(name) + '$'), ns + ':' + name );
}

@@ -219,3 +217,3 @@

longname = longname.replace(/\.prototype\.?/g, INSTANCE);
longname = prototypeToPunc(longname);

@@ -230,5 +228,5 @@ if (typeof forcedMemberof !== 'undefined') {

else {
parts = longname?
(longname.match( /^(:?(.+)([#.~]))?(.+?)$/ ) || []).reverse()
: [''];
parts = longname ?
(longname.match( /^(:?(.+)([#.~]))?(.+?)$/ ) || []).reverse() :
[''];

@@ -249,6 +247,6 @@ name = parts[0] || ''; // ensure name is always initialised to avoid error being thrown when calling replace on undefined [gh-24]

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]);
longname = longname.replace('@{' + i + '}@', atoms[i]);
memberof = memberof.replace('@{' + i + '}@', atoms[i]);
scope = scope.replace('@{' + i + '}@', atoms[i]);
name = name.replace('@{' + i + '}@', atoms[i]);
}

@@ -255,0 +253,0 @@

@@ -53,2 +53,4 @@ /**

}
return this;
};

@@ -64,2 +66,3 @@

* @param {function} [coercer] A function to coerce the given value to a specific type.
* @return {this}
* @example

@@ -79,3 +82,3 @@ * myParser.addOption('t', 'template', true, 'The path to the template.');

this._addOption(option);
return this._addOption(option);
};

@@ -101,3 +104,3 @@

this._addOption(option);
return this._addOption(option);
};

@@ -231,3 +234,3 @@

var arg = '' + args[i],
next = (i < leni-1)? '' + args[i+1] : null,
next = (i < leni - 1) ? '' + args[i + 1] : null,
option,

@@ -234,0 +237,0 @@ shortName = null,

@@ -108,3 +108,3 @@ /**

if (typeof args === 'string' || args.constructor === String) {
args = (''+args).split(/\s+/g);
args = String(args).split(/\s+/g);
}

@@ -111,0 +111,0 @@

@@ -19,3 +19,3 @@ /**

exports.Package = function(json) {
json = json || "{}";
json = json || '{}';

@@ -22,0 +22,0 @@ /** The source files associated with this package.

@@ -11,2 +11,8 @@ /*global app: true */

function addHandlers(handlers, parser) {
Object.keys(handlers).forEach(function(eventName) {
parser.on(eventName, handlers[eventName]);
});
}
exports.installPlugins = function(plugins, parser) {

@@ -24,5 +30,3 @@ var dictionary = require('jsdoc/tag/dictionary');

if (plugin.handlers) {
Object.keys(plugin.handlers).forEach(function(eventName) {
parser.on(eventName, plugin.handlers[eventName]);
});
addHandlers(plugin.handlers, parser);
}

@@ -29,0 +33,0 @@

@@ -21,2 +21,5 @@ /**

var BOOLEAN_OPTIONAL = [BOOLEAN, NULL, UNDEFINED];
var STRING_OPTIONAL = [STRING, NULL, UNDEFINED];
var EVENT_REGEXP = /event\:[\S]+/;

@@ -124,9 +127,7 @@ var PACKAGE_REGEXP = /package\:[\S]+/;

defaultvalue: {
// TODO: stop adding property if it's empty
type: [STRING, NULL, UNDEFINED],
type: STRING_OPTIONAL,
optional: true
},
description: {
// TODO: stop adding property if it's empty
type: [STRING, NULL, UNDEFINED],
type: STRING_OPTIONAL,
optional: true

@@ -150,2 +151,10 @@ },

},
// is this member nullable? (derived from the type expression)
nullable: {
type: BOOLEAN_OPTIONAL
},
// is this member optional? (derived from the type expression)
optional: {
type: BOOLEAN_OPTIONAL
},
scope: {

@@ -156,3 +165,7 @@ type: STRING,

},
type: TYPE_PROPERTY_SCHEMA
type: TYPE_PROPERTY_SCHEMA,
// can this member be provided more than once? (derived from the type expression)
variable: {
type: BOOLEAN_OPTIONAL
}
}

@@ -168,4 +181,3 @@ };

defaultvalue: {
// TODO: stop adding property if it's empty
type: [STRING, NULL, UNDEFINED],
type: STRING_OPTIONAL,
optional: true

@@ -175,4 +187,3 @@ },

description: {
// TODO: stop adding property if it's empty
type: [STRING, NULL, UNDEFINED],
type: STRING_OPTIONAL,
optional: true

@@ -186,4 +197,3 @@ },

nullable: {
// TODO: stop adding property if it's empty
type: [BOOLEAN, NULL, UNDEFINED],
type: BOOLEAN_OPTIONAL,
optional: true

@@ -193,4 +203,3 @@ },

optional: {
// TODO: stop adding property if it's empty
type: [BOOLEAN, NULL, UNDEFINED],
type: BOOLEAN_OPTIONAL,
optional: true

@@ -202,4 +211,3 @@ },

variable: {
// TODO: stop adding property if it's empty
type: [BOOLEAN, NULL, UNDEFINED],
type: BOOLEAN_OPTIONAL,
optional: true

@@ -281,3 +289,3 @@ }

optional: true,
enum: [OBJECT]
enum: [OBJECT, ARRAY]
},

@@ -291,4 +299,3 @@ // is usage of this symbol deprecated?

description: {
// TODO: stop adding property if it's empty
type: [STRING, NULL, UNDEFINED],
type: STRING_OPTIONAL,
optional: true

@@ -329,4 +336,3 @@ },

forceMemberof: {
// TODO: stop adding property if it's empty
type: [BOOLEAN, NULL, UNDEFINED],
type: BOOLEAN_OPTIONAL,
optional: true

@@ -377,2 +383,3 @@ },

'package',
'param',
'typedef'

@@ -416,2 +423,10 @@ ]

},
// is this member nullable? (derived from the type expression)
nullable: {
type: BOOLEAN_OPTIONAL
},
// is this member optional? (derived from the type expression)
optional: {
type: BOOLEAN_OPTIONAL
},
// are there function parameters associated with this doc?

@@ -540,2 +555,6 @@ params: {

},
// can this member be provided more than once? (derived from the type expression)
variable: {
type: BOOLEAN_OPTIONAL
},
variation: {

@@ -542,0 +561,0 @@ type: STRING,

@@ -9,5 +9,7 @@ 'use strict';

// TODO: docs
var acceptsLeadingComments = exports.acceptsLeadingComments = (function() {
// TODO: docs; empty array means any node type, otherwise only the node types in the array
var acceptsLeadingComments = (function() {
var accepts = {};
// these nodes always accept leading comments
var commentable = [

@@ -25,7 +27,20 @@ Syntax.AssignmentExpression,

];
for (var i = 0, l = commentable.length; i < l; i++) {
accepts[commentable[i]] = true;
accepts[commentable[i]] = [];
}
// these nodes accept leading comments if they have specific types of parent nodes
// like: function foo(/** @type {string} */ bar) {}
accepts[Syntax.Identifier] = [
Syntax.CatchClause,
Syntax.FunctionDeclaration,
Syntax.FunctionExpression
];
// like: var Foo = Class.create(/** @lends Foo */{ // ... })
accepts[Syntax.ObjectExpression] = [
Syntax.CallExpression,
Syntax.Property,
Syntax.ReturnStatement
];
return accepts;

@@ -35,14 +50,19 @@ })();

// TODO: docs
var searchDescendants = (function() {
var search = {};
var shouldSearch = [
Syntax.CallExpression
];
function canAcceptComment(node) {
var canAccept = false;
var spec = acceptsLeadingComments[node.type];
for (var i = 0, l = shouldSearch.length; i < l; i++) {
search[shouldSearch[i]] = true;
if (spec) {
// empty array means we don't care about the parent type
if (spec.length === 0) {
canAccept = true;
}
// we can accept the comment if the spec contains the type of the node's parent
else if (node.parent) {
canAccept = spec.indexOf(node.parent.type) !== -1;
}
}
return search;
})();
return canAccept;
}

@@ -56,8 +76,2 @@ // TODO: docs

// TODO: docs
function isBetween(middleRange, beforeRange, afterRange) {
return isBefore(middleRange, afterRange) && (beforeRange ?
isBefore(beforeRange, middleRange) : true);
}
// TODO: docs
function isWithin(innerRange, outerRange) {

@@ -68,8 +82,2 @@ return innerRange[0] >= outerRange[0] && innerRange[1] <= outerRange[1];

// TODO: docs
function isLeadingComment(comment, before, after) {
return !!before && !!after && !!acceptsLeadingComments[after.type] &&
isBefore(before.range, after.range) && isBetween(comment.range, before.range, after.range);
}
// TODO: docs
function isJsdocComment(comment) {

@@ -109,2 +117,18 @@ return comment && (comment.type === 'Block') && (comment.value[0] === '*');

function parse(source, filename, esprimaOpts) {
var esprima = require('esprima');
var logger = require('jsdoc/util/logger');
var ast;
try {
ast = esprima.parse(source, esprimaOpts);
}
catch (e) {
logger.error('Unable to parse %s: %s', filename, e.message);
}
return ast;
}
// TODO: docs

@@ -118,10 +142,11 @@ AstBuilder.prototype.build = function(source, filename) {

range: true,
// can probably remove when 1.1.0 is released
raw: true,
tokens: true
};
ast = require('esprima').parse(source, esprimaOpts);
this._postProcess(filename, ast);
ast = parse(source, filename, esprimaOpts);
if (ast) {
this._postProcess(filename, ast);
}
return ast;

@@ -157,2 +182,3 @@ };

// TODO: docs
// TODO: export?
function CommentAttacher(comments, tokens) {

@@ -167,4 +193,2 @@ this._comments = comments || [];

this._parentRange = [];
this._resetPendingComment()

@@ -200,7 +224,2 @@ ._resetCandidates();

// TODO: docs
CommentAttacher.prototype._extractComments = function(index, count) {
return this._comments.splice(index, count);
};
// TODO: docs
// find the index of the atom whose end position is closest to (but not after) the specified

@@ -238,13 +257,5 @@ // position

CommentAttacher.prototype._fastForwardComments = function(node) {
var commentIndex;
var position;
var position = node.range[0];
var commentIndex = this._nextIndexBefore(0, this._comments, position);
// don't fast-forward if there might be a sibling that can receive the comment
if ( this._parentRange.length && isWithin(node.range, this._parentRange) ) {
return;
}
position = node.range[0];
commentIndex = this._nextIndexBefore(0, this._comments, position);
// all comments before the node (except the last one) are considered stray comments

@@ -261,13 +272,15 @@ if (commentIndex > 0) {

if (this._pendingComment) {
if (this._candidates.length > 0) {
target = this._candidates[this._candidates.length - 1];
target.leadingComments = target.leadingComments || [];
target.leadingComments.push(this._pendingComment);
}
else {
this._strayComments.push(this._pendingComment);
}
if (!this._pendingComment) {
return this;
}
if (this._candidates.length > 0) {
target = this._candidates[this._candidates.length - 1];
target.leadingComments = target.leadingComments || [];
target.leadingComments.push(this._pendingComment);
}
else {
this._strayComments.push(this._pendingComment);
}
this._resetPendingComment()

@@ -306,7 +319,2 @@ ._resetCandidates();

// TODO: docs
CommentAttacher.prototype._shouldSkipNode = function(node) {
return !isWithin(node.range, this._pendingCommentRange) && !this._parentRange.length;
};
// TODO: docs
// TODO: do we ever get multiple candidate nodes?

@@ -324,12 +332,2 @@ CommentAttacher.prototype.visit = function(node) {

// clear the parent range if we've moved past it
if ( this._parentRange.length && !isWithin(node.range, this._parentRange) ) {
this._parentRange = [];
}
// if we need to search this node's descendants, set the range in which to search
if (searchDescendants[node.type] && !this._parentRange.length) {
this._parentRange = node.range.slice(0);
}
// move to the next token, and fast-forward past comments that can no longer be attached

@@ -341,12 +339,8 @@ this._advanceTokenIndex(node);

// if we already had a pending comment, and the current node is in the wrong place to be a
// comment target, try attaching the comment
if ( (this._pendingComment && !isWithin(node.range, this._pendingCommentRange)) ||
!searchDescendants[node.type] ) {
this._attachPendingComment();
}
// attach the pending comment, if there is one
this._attachPendingComment();
// okay, now that we've done all that bookkeeping, we can check whether the current node accepts
// leading comments and add it to the candidate list if needed
if (isEligible && acceptsLeadingComments[node.type]) {
if ( isEligible && canAcceptComment(node) ) {
// make sure we don't go past the end of the outermost target node

@@ -353,0 +347,0 @@ if (!this._pendingCommentRange) {

// TODO: docs
'use strict';
var doop = require('jsdoc/util/doop');
var Syntax = require('jsdoc/src/syntax').Syntax;

@@ -12,5 +13,15 @@ var util = require('util');

// TODO: currently unused
var GLOBAL_NODE_ID = exports.GLOBAL_NODE_ID = require('jsdoc/doclet').GLOBAL_LONGNAME;
var GLOBAL_NODE_ID = exports.GLOBAL_NODE_ID = require('jsdoc/name').GLOBAL_LONGNAME;
/**
* Check whether an AST node represents a function.
*
* @param {Object} node - The AST node to check.
* @return {boolean} Set to `true` if the node is a function or `false` in all other cases.
*/
var isFunction = exports.isFunction = function(node) {
return node.type === Syntax.FunctionDeclaration || node.type === Syntax.FunctionExpression;
};
/**
* Check whether an AST node creates a new scope.

@@ -23,4 +34,4 @@ *

// TODO: handle blocks with "let" declarations
return !!node && typeof node === 'object' && (node.type === Syntax.CatchClause ||
node.type === Syntax.FunctionDeclaration || node.type === Syntax.FunctionExpression);
return !!node && typeof node === 'object' && ( node.type === Syntax.CatchClause ||
isFunction(node) );
};

@@ -30,5 +41,4 @@

var addNodeProperties = exports.addNodeProperties = function(node) {
var doop = require('jsdoc/util/doop');
var debugEnabled = !!global.env.opts.debug;
var newProperties = {};

@@ -40,50 +50,50 @@ if (!node || typeof node !== 'object') {

if (!node.nodeId) {
Object.defineProperty(node, 'nodeId', {
newProperties.nodeId = {
value: 'astnode' + uid++,
enumerable: debugEnabled
});
};
}
if (!node.parent && node.parent !== null) {
Object.defineProperty(node, 'parent', {
newProperties.parent = {
// `null` means 'no parent', so use `undefined` for now
value: undefined,
writable: true
});
};
}
if (!node.enclosingScope && node.enclosingScope !== null) {
Object.defineProperty(node, 'enclosingScope', {
newProperties.enclosingScope = {
// `null` means 'no enclosing scope', so use `undefined` for now
value: undefined,
writable: true
});
};
}
if (!node.knownVariables) {
Object.defineProperty(node, 'knownVariables', {
newProperties.knownVariables = {
value: node.enclosingScope ? doop(node.enclosingScope.knownVariables) : {}
});
};
}
if (!node.ownedVariables) {
Object.defineProperty(node, 'ownedVariables', {
newProperties.ownedVariables = {
value: {}
});
};
}
if (!node.knownAliases) {
Object.defineProperty(node, 'knownAliases', {
newProperties.knownAliases = {
value: node.enclosingScope ? doop(node.enclosingScope.knownAliases) : {}
});
};
}
if (!node.ownedAliases) {
Object.defineProperty(node, 'ownedAliases', {
newProperties.ownedAliases = {
value: {}
});
};
}
if (debugEnabled && !node.parentId) {
Object.defineProperty(node, 'parentId', {
newProperties.parentId = {
enumerable: true,

@@ -93,7 +103,7 @@ get: function() {

}
});
};
}
if (debugEnabled && !node.enclosingScopeId) {
Object.defineProperty(node, 'enclosingScopeId', {
newProperties.enclosingScopeId = {
enumerable: true,

@@ -103,5 +113,7 @@ get: function() {

}
});
};
}
Object.defineProperties(node, newProperties);
return node;

@@ -127,5 +139,22 @@ };

var nodeToString = exports.nodeToString = function(node) {
var tempObject;
var str = '';
switch (node.type) {
case Syntax.ArrayExpression:
tempObject = [];
node.elements.forEach(function(el, i) {
// preserve literal values so that the JSON form shows the correct type
if (el.type === Syntax.Literal) {
tempObject[i] = el.value;
}
else {
tempObject[i] = nodeToString(el);
}
});
str = JSON.stringify(tempObject);
break;
case Syntax.AssignmentExpression:

@@ -161,2 +190,18 @@ str = nodeToString(node.left);

case Syntax.ObjectExpression:
tempObject = {};
node.properties.forEach(function(prop) {
var key = prop.key.name;
// preserve literal values so that the JSON form shows the correct type
if (prop.value.type === Syntax.Literal) {
tempObject[key] = prop.value.value;
}
else {
tempObject[key] = nodeToString(prop);
}
});
str = JSON.stringify(tempObject);
break;
case Syntax.ThisExpression:

@@ -171,3 +216,4 @@ str = 'this';

if (node.prefix) {
// workaround for https://code.google.com/p/esprima/issues/detail?id=526
if (node.prefix === true || node.prefix === undefined) {
str = node.operator + str;

@@ -177,3 +223,4 @@ }

// this shouldn't happen
throw new Error('Found a UnaryExpression with a postfix operator: %j', node);
throw new Error( util.format('Found a UnaryExpression with a postfix operator: %j',
node) );
}

@@ -249,2 +296,9 @@ break;

// like the param "bar" in: "function foo(bar) {}"
case Syntax.Identifier:
info.node = node;
info.name = nodeToString(info.node);
info.type = info.node.type;
break;
// like "a.b.c"

@@ -251,0 +305,0 @@ case Syntax.MemberExpression:

@@ -60,3 +60,3 @@ /*global env: true */

this.exclude.forEach(function(exclude) {
if ( exclude === filepath || exclude === path.dirname(filepath) ) {
if ( filepath.indexOf(exclude) === 0 ) {
included = false;

@@ -63,0 +63,0 @@ }

@@ -6,2 +6,11 @@ /**

var jsdoc = {
doclet: require('jsdoc/doclet'),
name: require('jsdoc/name'),
util: {
logger: require('jsdoc/util/logger')
}
};
var util = require('util');
var currentModule = null;

@@ -12,7 +21,5 @@

function getNewDoclet(comment, e) {
var Doclet = require('jsdoc/doclet').Doclet;
var util = require('util');
var Doclet = jsdoc.doclet.Doclet;
var doclet;
var err;
var doclet;

@@ -25,3 +32,3 @@ try {

comment.replace(/[\r\n]/g, ''), error.message) );
require('jsdoc/util/logger').error(err);
jsdoc.util.logger.error(err);
doclet = new Doclet('', e);

@@ -39,2 +46,16 @@ }

function setDefaultScopeMemberOf(doclet) {
// add @inner and @memberof tags unless the current module exports only this symbol
if (currentModule && currentModule !== doclet.name) {
// add @inner unless the current module exports only this symbol
if (!doclet.scope) {
doclet.addTag('inner');
}
if (!doclet.memberof && doclet.scope !== 'global') {
doclet.addTag('memberof', currentModule);
}
}
}
/**

@@ -45,25 +66,23 @@ * Attach these event handlers to a particular instance of a parser.

exports.attachTo = function(parser) {
var jsdoc = {doclet: require('jsdoc/doclet'), name: require('jsdoc/name')};
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
parser.on('jsdocCommentFound', function(e) {
var newDoclet = getNewDoclet(e.comment, e);
if (!newDoclet.name) {
return false; // only interested in virtual comments (with a @name) here
function filter(doclet) {
// you can't document prototypes
if ( /#$/.test(doclet.longname) ) {
return true;
}
addDoclet.call(parser, newDoclet);
return false;
}
e.doclet = newDoclet;
});
function addDoclet(newDoclet) {
var e;
if (newDoclet) {
setCurrentModule(newDoclet);
e = { doclet: newDoclet };
parser.emit('newDoclet', e);
// handles named symbols in the code, may or may not have a JSDoc comment attached
parser.on('symbolFound', function(e) {
var subDoclets = e.comment.split(/@also\b/g);
for (var i = 0, l = subDoclets.length; i < l; i++) {
newSymbolDoclet.call(parser, subDoclets[i], e);
if ( !e.defaultPrevented && !filter(e.doclet) ) {
parser.addResult(e.doclet);
}
}
});
}

@@ -125,3 +144,3 @@ // TODO: for clarity, decompose into smaller functions

memberofName = parser.resolveThis(e.astnode);
scope = nameStartsWith === 'exports'? 'static' : 'instance';
scope = nameStartsWith === 'exports' ? 'static' : 'instance';

@@ -137,3 +156,4 @@ // like /** @module foo */ this.bar = 1;

if (newDoclet.name) {
newDoclet.name = memberofName + (scope === 'instance'? '#' : '.') + newDoclet.name;
newDoclet.name = memberofName + (scope === 'instance' ? '#' : '.') +
newDoclet.name;
}

@@ -159,13 +179,3 @@ else { newDoclet.name = memberofName; }

else {
// add @inner and @memberof tags unless the current module exports only this symbol
if (currentModule && currentModule !== newDoclet.name) {
// add @inner unless the current module exports only this symbol
if (!newDoclet.scope) {
newDoclet.addTag('inner');
}
if (!newDoclet.memberof && newDoclet.scope !== 'global') {
newDoclet.addTag('memberof', currentModule);
}
}
setDefaultScopeMemberOf(newDoclet);
}

@@ -190,31 +200,29 @@ }

parser.on('fileComplete', function(e) {
currentModule = null;
// handles JSDoc comments that include a @name tag -- the code is ignored in such a case
parser.on('jsdocCommentFound', function(e) {
var newDoclet = getNewDoclet(e.comment, e);
if (!newDoclet.name) {
return false; // only interested in virtual comments (with a @name) here
}
setDefaultScopeMemberOf(newDoclet);
newDoclet.postProcess();
addDoclet.call(parser, newDoclet);
e.doclet = newDoclet;
});
function addDoclet(newDoclet) {
var e;
if (newDoclet) {
setCurrentModule(newDoclet);
e = { doclet: newDoclet };
parser.emit('newDoclet', e);
// handles named symbols in the code, may or may not have a JSDoc comment attached
parser.on('symbolFound', function(e) {
var subDoclets = e.comment.split(/@also\b/g);
if ( !e.defaultPrevented && !filter(e.doclet) ) {
parser.addResult(e.doclet);
}
for (var i = 0, l = subDoclets.length; i < l; i++) {
newSymbolDoclet.call(parser, subDoclets[i], e);
}
}
});
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;
}
parser.on('fileComplete', function(e) {
currentModule = null;
});
};

@@ -1,2 +0,3 @@

/*global env: true, Packages: true */
/*global env, Packages */
/*eslint no-script-url:0 */
/**

@@ -218,9 +219,3 @@ * @module jsdoc/src/parser

// merge adjacent doclets
.replace(/\*\/\/\*\*+/g, '@also')
// add a dummy name to object literals that are lent to a function prototype
// like: return @lends {
.replace(/(\/\*\*[^\*\/]*?[\*\s]*@lends\s(?:[^\*]|\*(?!\/))*\*\/\s*)\{/g, '$1 ____ = {')
// like: @lends return {
.replace(/(\/\*\*[^\*\/]*?@lends\b[^\*\/]*?\*\/)(\s*)return(\s*)\{/g,
'$2$3 return $1 ____ = {');
.replace(/\*\/\/\*\*+/g, '@also');
}

@@ -252,3 +247,6 @@

ast = this._astBuilder.build(sourceCode, sourceName);
this._walker.recurse(sourceName, ast, this._visitor);
if (ast) {
this._walker.recurse(sourceName, ast, this._visitor);
}
}

@@ -275,3 +273,3 @@

this.refs[node.nodeId] = {
longname: jsdoc.doclet.ANONYMOUS_LONGNAME,
longname: jsdoc.name.ANONYMOUS_LONGNAME,
meta: {

@@ -330,3 +328,3 @@ code: e.code

if (!doclet) {
result = jsdoc.doclet.ANONYMOUS_LONGNAME + jsdoc.name.INNER;
result = jsdoc.name.ANONYMOUS_LONGNAME + jsdoc.name.INNER;
}

@@ -365,6 +363,5 @@ else {

if (!doclet) {
// global?
}
else {
// set the result if we found a doclet. (if we didn't, the AST node may describe a
// global symbol.)
if (doclet) {
result = doclet.longname || doclet.name;

@@ -395,3 +392,3 @@ }

if (!doclet) {
result = jsdoc.doclet.ANONYMOUS_LONGNAME; // TODO handle global this?
result = jsdoc.name.ANONYMOUS_LONGNAME; // TODO handle global this?
}

@@ -398,0 +395,0 @@ else if (doclet['this']) {

@@ -7,2 +7,3 @@ 'use strict';

ArrayPattern: 'ArrayPattern',
ArrowFunctionExpression: 'ArrowFunctionExpression',
AssignmentExpression: 'AssignmentExpression',

@@ -14,2 +15,5 @@ BinaryExpression: 'BinaryExpression',

CatchClause: 'CatchClause',
ClassBody: 'ClassBody',
ClassDeclaration: 'ClassDeclaration',
ClassExpression: 'ClassExpression',
ComprehensionBlock: 'ComprehensionBlock',

@@ -22,2 +26,5 @@ ComprehensionExpression: 'ComprehensionExpression',

EmptyStatement: 'EmptyStatement',
ExportBatchSpecifier: 'ExportBatchSpecifier',
ExportDeclaration: 'ExportDeclaration',
ExportSpecifier: 'ExportSpecifier',
ExpressionStatement: 'ExpressionStatement',

@@ -31,7 +38,11 @@ ForInStatement: 'ForInStatement',

IfStatement: 'IfStatement',
ImportDeclaration: 'ImportDeclaration',
ImportSpecifier: 'ImportSpecifier',
LabeledStatement: 'LabeledStatement',
LetStatement: 'LetStatement',
LetStatement: 'LetStatement', // TODO: update Rhino to use VariableDeclaration
Literal: 'Literal',
LogicalExpression: 'LogicalExpression',
MemberExpression: 'MemberExpression',
MethodDefinition: 'MethodDefinition',
ModuleDeclaration: 'ModuleDeclaration',
NewExpression: 'NewExpression',

@@ -44,4 +55,8 @@ ObjectExpression: 'ObjectExpression',

SequenceExpression: 'SequenceExpression',
SpreadElement: 'SpreadElement',
SwitchCase: 'SwitchCase',
SwitchStatement: 'SwitchStatement',
TaggedTemplateExpression: 'TaggedTemplateExpression',
TemplateElement: 'TemplateElement',
TemplateLiteral: 'TemplateLiteral',
ThisExpression: 'ThisExpression',

@@ -48,0 +63,0 @@ ThrowStatement: 'ThrowStatement',

@@ -13,2 +13,5 @@ /**

syntax: require('jsdoc/src/syntax')
},
util: {
logger: require('jsdoc/util/logger')
}

@@ -43,2 +46,63 @@ };

/**
* For function parameters that have inline documentation, create a function that will merge the
* inline documentation into the function's doclet. If the parameter is already documented in the
* function's doclet, the inline documentation will be ignored.
*
* @private
* @param {module:jsdoc/src/parser.Parser} parser - The JSDoc parser.
* @return {function} A function that merges a parameter's inline documentation into the function's
* doclet.
*/
function makeInlineParamsFinisher(parser) {
return function(e) {
var documentedParams;
var knownParams;
var param;
var parentDoclet;
var i = 0;
if (e.doclet && e.doclet.meta && e.doclet.meta.code && e.doclet.meta.code.node &&
e.doclet.meta.code.node.parent) {
parentDoclet = parser._getDoclet(e.doclet.meta.code.node.parent.nodeId);
}
if (!parentDoclet) {
return;
}
parentDoclet.params = parentDoclet.params || [];
documentedParams = parentDoclet.params;
knownParams = parentDoclet.meta.code.paramnames;
while (true) {
param = documentedParams[i];
// is the param already documented? if so, we're done
if (param && param.name === e.doclet.name) {
// the doclet is no longer needed
e.doclet.undocumented = true;
break;
}
// if we ran out of documented params, or we're at the parameter's actual position,
// splice in the param at the current index
if ( !param || i === knownParams.indexOf(e.doclet.name) ) {
documentedParams.splice(i, 0, {
type: e.doclet.type,
description: '',
name: e.doclet.name
});
// the doclet is no longer needed
e.doclet.undocumented = true;
break;
}
i++;
}
};
}
// TODO: docs

@@ -50,3 +114,3 @@ function SymbolFound(node, filename, extras) {

this.id = extras.id || node.nodeId;
this.comment = extras.comment || getLeadingComment(node) || jsdoc.doclet.UNDOCUMENTED_TAG;
this.comment = extras.comment || getLeadingComment(node) || '@undocumented';
this.lineno = extras.lineno || node.loc.start.line;

@@ -251,2 +315,4 @@ this.range = extras.range || node.range;

Visitor.prototype.makeSymbolFoundEvent = function(node, parser, filename) {
var logger = jsdoc.util.logger;
var e;

@@ -256,2 +322,3 @@ var basename;

var l;
var parent;

@@ -270,5 +337,3 @@ var extras = {

basename = parser.getBasename(e.code.name);
// in addition to `this`, we need to special-case the string `____`, or else our
// `@lends` tag hackery causes things to appear in the wrong scope
if (basename !== 'this' && basename !== '____') {
if (basename !== 'this') {
e.code.funcscope = parser.resolveVar(node, basename);

@@ -294,2 +359,14 @@ }

// like "bar" in: function foo(/** @type {string} */ bar) {}
// This is an extremely common type of node; we only care about function parameters with
// inline type annotations. No need to fire events unless they're already commented.
case Syntax.Identifier:
parent = node.parent;
if ( node.leadingComments && parent && jsdoc.src.astnode.isFunction(parent) ) {
extras.finishers = [makeInlineParamsFinisher(parser)];
e = new SymbolFound(node, filename, extras);
}
break;
// like "obj.prop" in: /** @typedef {string} */ obj.prop;

@@ -305,2 +382,8 @@ // Closure Compiler uses this pattern extensively for enums.

// like the object literal in: function Foo = Class.create(/** @lends Foo */ {});
case Syntax.ObjectExpression:
e = new SymbolFound(node, filename, extras);
break;
// like "bar: true" in: var foo = { bar: true };

@@ -327,2 +410,23 @@ // like "get bar() {}" in: var foo = { get bar() {} };

// for now, log a warning for all ES6 nodes, since we don't do anything useful with them
case Syntax.ArrowFunctionExpression:
case Syntax.ClassBody:
case Syntax.ClassDeclaration:
case Syntax.ClassExpression:
case Syntax.ExportBatchSpecifier:
case Syntax.ExportDeclaration:
case Syntax.ExportSpecifier:
case Syntax.ImportDeclaration:
case Syntax.ImportSpecifier:
case Syntax.MethodDefinition:
case Syntax.ModuleDeclaration:
case Syntax.SpreadElement:
case Syntax.TaggedTemplateExpression:
case Syntax.TemplateElement:
case Syntax.TemplateLiteral:
logger.warn('JSDoc does not currently handle %s nodes. Source file: %s, line %s',
node.type, filename, (node.loc && node.loc.start) ? node.loc.start.line : '??');
break;
default:

@@ -329,0 +433,0 @@ // ignore

@@ -65,2 +65,27 @@ /**

walkers[Syntax.ArrowFunctionExpression] =
function arrowFunctionExpression(node, parent, state, cb) {
var i;
var l;
// used for function declarations, so we include it here
if (node.id) {
cb(node.id, node, state);
}
for (i = 0, l = node.params.length; i < l; i++) {
cb(node.params[i], node, state);
}
for (i = 0, l = node.defaults.length; i < l; i++) {
cb(node.defaults[i], node, state);
}
cb(node.body, node, state);
if (node.rest) {
cb(node.rest, node, state);
}
};
walkers[Syntax.AssignmentExpression] = function assignmentExpression(node, parent, state, cb) {

@@ -98,2 +123,20 @@ cb(node.left, node, state);

walkers[Syntax.ClassBody] = walkers[Syntax.BlockStatement];
walkers[Syntax.ClassDeclaration] = function classDeclaration(node, parent, state, cb) {
if (node.id) {
cb(node.id, node, state);
}
if (node.superClass) {
cb(node.superClass, node, state);
}
if (node.body) {
cb(node.body, node, state);
}
};
walkers[Syntax.ClassExpression] = walkers[Syntax.ClassDeclaration];
// TODO: verify correctness

@@ -133,2 +176,35 @@ walkers[Syntax.ComprehensionBlock] = walkers[Syntax.AssignmentExpression];

walkers[Syntax.ExportBatchSpecifier] = leafNode;
walkers[Syntax.ExportDeclaration] = function exportDeclaration(node, parent, state, cb) {
var i;
var l;
if (node.declaration) {
for (i = 0, l = node.declaration.length; i < l; i++) {
cb(node.declaration[i], node, state);
}
}
if (node.specifiers) {
for (i = 0, l = node.specifiers.length; i < l; i++) {
cb(node.specifiers[i], node, state);
}
}
if (node.source) {
cb(node.source, node, state);
}
};
walkers[Syntax.ExportSpecifier] = function exportSpecifier(node, parent, state, cb) {
if (node.id) {
cb(node.id, node, state);
}
if (node.name) {
cb(node.name, node, state);
}
};
walkers[Syntax.ExpressionStatement] = function expressionStatement(node, parent, state, cb) {

@@ -162,24 +238,6 @@ cb(node.expression, node, state);

walkers[Syntax.FunctionDeclaration] = function functionDeclaration(node, parent, state, cb) {
var i;
var l;
walkers[Syntax.FunctionDeclaration] = walkers[Syntax.ArrowFunctionExpression];
// can be null for function expressions
if (node.id) {
cb(node.id, node, state);
}
walkers[Syntax.FunctionExpression] = walkers[Syntax.ArrowFunctionExpression];
if (node.params && node.params.length) {
for (i = 0, l = node.params.length; i < l; i++) {
cb(node.params[i], node, state);
}
}
// ignore node.defaults and node.rest for now; always empty
cb(node.body, node, state);
};
walkers[Syntax.FunctionExpression] = walkers[Syntax.FunctionDeclaration];
walkers[Syntax.Identifier] = leafNode;

@@ -195,2 +253,19 @@

walkers[Syntax.ImportDeclaration] = function importDeclaration(node, parent, state, cb) {
var i;
var l;
if (node.specifiers) {
for (i = 0, l = node.specifiers.length; i < l; i++) {
cb(node.specifiers[i], node, state);
}
}
if (node.source) {
cb(node.source, node, state);
}
};
walkers[Syntax.ImportSpecifier] = walkers[Syntax.ExportSpecifier];
walkers[Syntax.LabeledStatement] = function labeledStatement(node, parent, state, cb) {

@@ -218,8 +293,32 @@ cb(node.body, node, state);

walkers[Syntax.MemberExpression] = function memberExpression(node, parent, state, cb) {
cb(node.object, node, state);
if (node.property) {
cb(node.property, node, state);
}
cb(node.object, node, state);
};
walkers[Syntax.MethodDefinition] = function methodDefinition(node, parent, state, cb) {
if (node.key) {
cb(node.key, node, state);
}
if (node.value) {
cb(node.value, node, state);
}
};
walkers[Syntax.ModuleDeclaration] = function moduleDeclaration(node, parent, state, cb) {
if (node.id) {
cb(node.id, node, state);
}
if (node.source) {
cb(node.source, node, state);
}
if (node.body) {
cb(node.body, node, state);
}
};
walkers[Syntax.NewExpression] = walkers[Syntax.CallExpression];

@@ -256,2 +355,8 @@

walkers[Syntax.SpreadElement] = function spreadElement(node, parent, state, cb) {
if (node.argument) {
cb(node.argument, node, state);
}
};
walkers[Syntax.SwitchCase] = function switchCase(node, parent, state, cb) {

@@ -275,2 +380,31 @@ if (node.test) {

walkers[Syntax.TaggedTemplateExpression] =
function taggedTemplateExpression(node, parent, state, cb) {
if (node.tag) {
cb(node.tag, node, state);
}
if (node.quasi) {
cb(node.quasi, node, state);
}
};
walkers[Syntax.TemplateElement] = leafNode;
walkers[Syntax.TemplateLiteral] = function templateLiteral(node, parent, state, cb) {
var i;
var l;
if (node.quasis && node.quasis.length) {
for (i = 0, l = node.quasis.length; i < l; i++) {
cb(node.quasis[i], node, state);
}
}
if (node.expressions && node.expressions.length) {
for (i = 0, l = node.expressions.length; i < l; i++) {
cb(node.expressions[i], node, state);
}
}
};
walkers[Syntax.ThisExpression] = leafNode;

@@ -354,5 +488,6 @@

// TODO: docs
Walker.prototype._recurse = function(ast) {
Walker.prototype._recurse = function(filename, ast) {
// TODO: track variables/aliases during the walk
var state = {
filename: filename,
nodes: [],

@@ -402,3 +537,3 @@ scopes: []

Walker.prototype.recurse = function(filename, ast, visitor) {
var state = this._recurse(ast);
var state = this._recurse(filename, ast);

@@ -405,0 +540,0 @@ if (visitor) {

@@ -34,5 +34,4 @@ /*global env: true */

opts = opts || {};
text = text || '';
if (!text) { return ''; }
if (opts.keepsWhitespace) {

@@ -47,7 +46,8 @@ text = text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');

}
return text;
}
else {
return text.replace(/^\s+|\s+$/g, '');
text = text.replace(/^\s+|\s+$/g, '');
}
return text;
}

@@ -54,0 +54,0 @@

@@ -41,3 +41,3 @@ /**

if (opts.isNamespace) {
if (opts && opts.isNamespace) {
_namespaces.push(def.title);

@@ -44,0 +44,0 @@ }

@@ -1,2 +0,2 @@

/*global app: true, env: true */
/*global app, env */
/**

@@ -11,6 +11,20 @@ Define tags that are known in JSDoc.

var logger = require('jsdoc/util/logger');
var jsdoc = {
name: require('jsdoc/name'),
src: {
astnode: require('jsdoc/src/astnode')
},
tag: {
type: require('jsdoc/tag/type')
},
util: {
logger: require('jsdoc/util/logger')
}
};
var path = require('jsdoc/path');
var Syntax = require('jsdoc/src/syntax').Syntax;
var GLOBAL_LONGNAME = jsdoc.name.GLOBAL_LONGNAME;
var MODULE_PREFIX = jsdoc.name.MODULE_PREFIX;
function getSourcePaths() {

@@ -59,3 +73,3 @@ var sourcePaths = env.sourceFiles.slice(0) || [];

catch(e) {
logger.error(e.message);
jsdoc.util.logger.error(e.message);
}

@@ -87,3 +101,6 @@ }

if (tag.value && tag.value.type) {
doclet.type = tag.value.type;
// add the type names and other type properties (such as `optional`)
Object.keys(tag.value).forEach(function(prop) {
doclet[prop] = tag.value[prop];
});
}

@@ -209,4 +226,4 @@ }

onTagText: function(text) {
var type = require('jsdoc/tag/type'),
tagType = type.parse(text, false, true);
var tagType = jsdoc.tag.type.parse(text, false, true);
return tagType.typeExpression || text;

@@ -298,2 +315,4 @@ },

var nodeToString = jsdoc.src.astnode.nodeToString;
if (tag.value) {

@@ -306,12 +325,21 @@ doclet.defaultvalue = tag.value;

if (type === Syntax.Literal) {
doclet.defaultvalue = String(value);
switch(type) {
case Syntax.ArrayExpression:
doclet.defaultvalue = nodeToString(doclet.meta.code.node);
doclet.defaultvaluetype = 'array';
break;
case Syntax.Literal:
doclet.defaultvalue = String(value);
break;
case Syntax.ObjectExpression:
doclet.defaultvalue = nodeToString(doclet.meta.code.node);
doclet.defaultvaluetype = 'object';
break;
default:
// do nothing
break;
}
// TODO: reenable the changes for https://github.com/jsdoc3/jsdoc/pull/419
/*
else if (doclet.meta.code.type === 'OBJECTLIT') {
doclet.defaultvalue = String(doclet.meta.code.node.toSource());
doclet.defaultvaluetype = 'object';
}
*/
}

@@ -391,2 +419,5 @@ }

}
else {
setDocletNameToValue(doclet, tag);
}
}

@@ -460,4 +491,2 @@ })

onTagged: function(doclet, tag) {
var GLOBAL_LONGNAME = require('jsdoc/doclet').GLOBAL_LONGNAME;
doclet.alias = tag.value || GLOBAL_LONGNAME;

@@ -499,4 +528,2 @@ doclet.addTag('undocumented');

onTagged: function(doclet, tag) {
var GLOBAL_LONGNAME = require('jsdoc/doclet').GLOBAL_LONGNAME;
if (tag.originalTitle === 'memberof!') {

@@ -562,3 +589,3 @@ doclet.forceMemberof = true;

if (!doclet.params) { doclet.params = []; }
doclet.params.push(tag.value||{});
doclet.params.push(tag.value || {});
}

@@ -614,4 +641,2 @@ })

var MODULE_PREFIX = require('jsdoc/name').MODULE_PREFIX;
// inline link tags are passed through as-is so that `@requires {@link foo}` works

@@ -697,10 +722,24 @@ if ( require('jsdoc/tag/inline').isInlineTag(tag.value, 'link\\S*') ) {

mustHaveValue: true,
mustNotHaveDescription: true,
canHaveType: true,
onTagText: function(text) {
// remove line breaks so we can parse the type expression correctly
text = text.replace(/[\n\r]/g, '');
// any text must be formatted as a type, but for back compat braces are optional
if ( !/^\{[\s\S]+\}$/.test(text) ) {
text = '{' + text + '}';
var closeIdx;
var openIdx;
var OPEN_BRACE = '{';
var CLOSE_BRACE = '}';
// remove line breaks
text = text.replace(/[\f\n\r]/g, '');
// Text must be a type expression; for backwards compatibility, we add braces if they're
// missing. But do NOT add braces to things like `@type {string} some pointless text`.
openIdx = text.indexOf(OPEN_BRACE);
closeIdx = text.indexOf(CLOSE_BRACE);
// a type expression is at least one character long
if ( openIdx !== 0 || closeIdx <= openIdx + 1) {
text = OPEN_BRACE + text + CLOSE_BRACE;
}
return text;

@@ -707,0 +746,0 @@ },

@@ -69,8 +69,3 @@ /**

exports.isInlineTag = function(string, tagName) {
try {
return regExpFactory(tagName, '^', '$').test(string);
}
catch(e) {
return false;
}
return regExpFactory(tagName, '^', '$').test(string);
};

@@ -77,0 +72,0 @@

@@ -10,2 +10,3 @@ /**

var catharsis = require('catharsis');
var jsdoc = {

@@ -17,2 +18,3 @@ name: require('jsdoc/name'),

};
var util = require('util');

@@ -42,4 +44,2 @@ /**

function extractTypeExpression(string) {
string = string || '';
var completeExpression;

@@ -116,3 +116,3 @@ var count = 0;

if (typeOverride.tags && typeOverride.tags[0]) {
typeExpression = typeOverride.tags[0].text || typeExpression;
typeExpression = typeOverride.tags[0].text;
}

@@ -175,8 +175,9 @@ text = typeOverride.newString;

/** @private */
function getTypeStrings(parsedType) {
function getTypeStrings(parsedType, isOutermostType) {
var applications;
var typeString;
var types = [];
var catharsis = require('catharsis');
var TYPES = catharsis.Types;
var util = require('util');

@@ -200,3 +201,15 @@ switch(parsedType.type) {

case TYPES.TypeApplication:
types.push( catharsis.stringify(parsedType) );
// if this is the outermost type, we strip the modifiers; otherwise, we keep them
if (isOutermostType) {
applications = parsedType.applications.map(function(application) {
return getTypeStrings(application);
}).join(', ');
typeString = util.format( '%s.<%s>', getTypeStrings(parsedType.expression),
applications );
types.push(typeString);
}
else {
types.push( catharsis.stringify(parsedType) );
}
break;

@@ -232,5 +245,2 @@ case TYPES.TypeUnion:

function parseTypeExpression(tagInfo) {
var catharsis = require('catharsis');
var util = require('util');
var errorMessage;

@@ -253,16 +263,14 @@ var parsedType;

if (parsedType) {
tagInfo.type = tagInfo.type.concat( getTypeStrings(parsedType) );
tagInfo.type = tagInfo.type.concat( getTypeStrings(parsedType, true) );
// Catharsis and JSDoc use the same names for 'optional' and 'nullable'...
['optional', 'nullable'].forEach(function(key) {
if (parsedType[key] !== null && parsedType[key] !== undefined) {
tagInfo[key] = parsedType[key];
}
});
// Catharsis and JSDoc use the same names for 'optional' and 'nullable'...
['optional', 'nullable'].forEach(function(key) {
if (parsedType[key] !== null && parsedType[key] !== undefined) {
tagInfo[key] = parsedType[key];
}
});
// ...but not 'variable'.
if (parsedType.repeatable !== null && parsedType.repeatable !== undefined) {
tagInfo.variable = parsedType.repeatable;
}
// ...but not 'variable'.
if (parsedType.repeatable !== null && parsedType.repeatable !== undefined) {
tagInfo.variable = parsedType.repeatable;
}

@@ -269,0 +277,0 @@

@@ -28,15 +28,19 @@ /*global env: true */

exports.validate = function(tag, tagDef, meta) {
// check for errors that make the tag useless
if (!tagDef && !env.conf.tags.allowUnknownTags) {
logger.error( buildMessage(tag.title, meta, 'is not a known tag') );
}
else if (!tag.text) {
if (tagDef.mustHaveValue) {
logger.error( buildMessage(tag.title, meta, 'requires a value') );
}
else if (!tag.text && tagDef.mustHaveValue) {
logger.error( buildMessage(tag.title, meta, 'requires a value') );
}
else {
if (tagDef.mustNotHaveValue) {
logger.error( buildMessage(tag.title, meta, 'does not permit a value') );
}
// check for minor issues that are usually harmless
else if (tag.text && tagDef.mustNotHaveValue) {
logger.warn( buildMessage(tag.title, meta,
'does not permit a value; the value will be ignored') );
}
else if (tag.value && tag.value.description && tagDef.mustNotHaveDescription) {
logger.warn( buildMessage(tag.title, meta,
'does not permit a description; the description will be ignored') );
}
};

@@ -17,3 +17,3 @@ /**

var index = parent.children.indexOf(child);
if (index != -1) {
if (index !== -1) {
parent.children.splice(index, 1);

@@ -20,0 +20,0 @@ }

@@ -13,11 +13,13 @@ /*global env: true */

var tutorial = require('jsdoc/tutorial'),
fs = require('jsdoc/fs'),
logger = require('jsdoc/util/logger'),
path = require('path'),
hasOwnProp = Object.prototype.hasOwnProperty,
conf = {},
tutorials = {},
finder = /^(.*)\.(x(?:ht)?ml|html?|md|markdown|json)$/i;
var logger = require('jsdoc/util/logger');
var fs = require('jsdoc/fs');
var path = require('path');
var tutorial = require('jsdoc/tutorial');
var hasOwnProp = Object.prototype.hasOwnProperty;
var conf = {};
var finder = /^(.*)\.(x(?:ht)?ml|html?|md|markdown|json)$/i;
var tutorials = {};
/** checks if `conf` is the metadata for a single tutorial.

@@ -24,0 +26,0 @@ * A tutorial's metadata has a property 'title' and/or a property 'children'.

@@ -13,3 +13,3 @@ /**

if (o instanceof Object && o.constructor != Function) {
if (o instanceof Object && o.constructor !== Function) {
if ( Array.isArray(o) ) {

@@ -16,0 +16,0 @@ clone = [];

@@ -0,1 +1,2 @@

/*global Set */
/**

@@ -10,15 +11,41 @@ * Recursively print out all names and values in a data structure.

var util = require('util');
var setDefined = typeof Set !== 'undefined';
function ObjectWalker() {
this.seenItems = [];
if (setDefined) {
this.seenItems = new Set();
} else {
this.seenItems = [];
}
}
ObjectWalker.prototype.seen = function(object) {
if (this.seenItems.indexOf(object) !== -1) {
return true;
var result;
if (setDefined) {
result = this.seenItems.has(object);
} else {
result = object.hasBeenSeenByWalkerDumper;
}
return result;
};
return false;
ObjectWalker.prototype.markAsSeen = function(object) {
if (setDefined) {
this.seenItems.add(object);
} else {
object.hasBeenSeenByWalkerDumper = true;
this.seenItems.push(object);
}
};
ObjectWalker.prototype.cleanSeenFlag = function() {
if (setDefined) {
this.seenItems = new Set();
} else {
this.seenItems.forEach(function(object) {
delete object.hasBeenSeenByWalkerDumper;
});
}
};
// some objects are unwalkable, like Java native objects

@@ -43,3 +70,3 @@ ObjectWalker.prototype.isUnwalkable = function(o) {

else {
this.seenItems.push(o);
this.markAsSeen(o);
return func(o);

@@ -86,2 +113,3 @@ }

Object.keys(obj).forEach(function(key) {
if (!setDefined && key === 'hasBeenSeenByWalkerDumper') { return; }
newObj[key] = self.walk(obj[key]);

@@ -105,3 +133,7 @@ });

exports.dump = function(object) {
return JSON.stringify(new ObjectWalker().walk(object), null, 4);
var walker = new ObjectWalker();
var result = JSON.stringify(walker.walk(object), null, 4);
walker.cleanSeenFlag();
return result;
};

@@ -88,3 +88,3 @@ /**

var DEFAULT_LEVEL = LEVELS.ERROR;
var DEFAULT_LEVEL = LEVELS.WARN;
var logLevel = DEFAULT_LEVEL;

@@ -91,0 +91,0 @@

@@ -21,3 +21,3 @@ /*global env: true */

*/
evilstreak: "marked",
evilstreak: 'marked',
/**

@@ -27,7 +27,7 @@ * The "GitHub-flavored Markdown" parser.

*/
gfm: "marked",
gfm: 'marked',
/**
* The "[Marked](https://github.com/chjj/marked)" parser.
*/
marked: "marked"
marked: 'marked'
};

@@ -96,2 +96,6 @@

};
// Allow prettyprint to work on inline code samples
markedRenderer.code = function(code, language) {
return '<pre class="prettyprint source"><code>' + code + '</code></pre>';
};

@@ -98,0 +102,0 @@ parserFunction = function(source) {

@@ -1,2 +0,2 @@

/*global env: true */
/*global env, java */
/**

@@ -3,0 +3,0 @@ * Helper functions to enable JSDoc to run on multiple JavaScript runtimes.

@@ -289,3 +289,3 @@ /*global env: true */

require('jsdoc/util/logger').error( new Error('No such tutorial: ' + tutorial) );
return;
return null;
}

@@ -322,3 +322,3 @@

require('jsdoc/util/logger').error( new Error('Missing required parameter: tutorial') );
return;
return null;
}

@@ -501,3 +501,3 @@

if (d.virtual) {
attribs.push('virtual');
attribs.push('abstract');
}

@@ -510,3 +510,3 @@

if (d.scope && d.scope !== 'instance' && d.scope !== 'global') {
if (d.kind == 'function' || d.kind == 'member' || d.kind == 'constant') {
if (d.kind === 'function' || d.kind === 'member' || d.kind === 'constant') {
attribs.push(d.scope);

@@ -517,3 +517,3 @@ }

if (d.readonly === true) {
if (d.kind == 'member') {
if (d.kind === 'member') {
attribs.push('readonly');

@@ -527,2 +527,9 @@ }

if (d.nullable === true) {
attribs.push('nullable');
}
else if (d.nullable === false) {
attribs.push('non-null');
}
return attribs;

@@ -529,0 +536,0 @@ };

@@ -7,3 +7,4 @@ # License #

Copyright (c) 2011-2012 Michael Mathews <micmath@gmail.com>
Copyright (c) 2011-2014 Michael Mathews <micmath@gmail.com> and the
[contributors to JSDoc](https://github.com/jsdoc3/jsdoc/graphs/contributors).
All rights reserved.

@@ -277,2 +278,12 @@

## Requizzle ##
Requizzle is distributed under the MIT license, which is reproduced above.
Copyright (c) 2014 Google Inc. All rights reserved.
Copyright (c) 2012-2013 Johannes Ewald.
The source code for Requizzle is available at:
https://github.com/hegemonic/requizzle
## Rhino ##

@@ -369,6 +380,7 @@

Copyright (c) 2009-2012 Jeremy Ashkenas, DocumentCloud.
Copyright (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative
Reporters & Editors.
The source code for Underscore.js is available at:
https://github.com/documentcloud/underscore
https://github.com/jashkenas/underscore

@@ -375,0 +387,0 @@ ## wrench-js ##

{
"name": "jsdoc",
"version": "3.3.0-alpha5",
"revision": "1395025186103",
"version": "3.3.0-alpha7",
"revision": "1402418188968",
"description": "An API documentation generator for JavaScript.",

@@ -22,17 +22,17 @@ "keywords": [

"async": "~0.1.22",
"catharsis": "~0.7.0",
"esprima": "~1.0.4",
"catharsis": "~0.7.1",
"esprima": "https://github.com/ariya/esprima/tarball/49a2eccb243f29bd653b11e9419241a9d726af7c",
"js2xmlparser": "~0.1.0",
"marked": "~0.3.1",
"requizzle": "~0.1.0",
"strip-json-comments": "~0.1.3",
"taffydb": "https://github.com/hegemonic/taffydb/tarball/master",
"underscore": "~1.4.2",
"underscore": "~1.6.0",
"wrench": "~1.3.9"
},
"devDependencies": {
"grunt": "~0.4.2",
"grunt-bumpup": "~0.4.2",
"grunt-contrib-jshint": "~0.8.0",
"grunt-shell": "~0.6.1",
"gulp": "~3.6.2",
"gulp-eslint": "~0.1.6",
"gulp-json-editor": "~2.0.2",
"istanbul": "~0.2.1",
"load-grunt-tasks": "~0.2.1",
"tv4": "https://github.com/hegemonic/tv4/tarball/own-properties"

@@ -44,4 +44,3 @@ },

"scripts": {
"postinstall": "node ./node/postinstall.js",
"test": "grunt test"
"test": "gulp test"
},

@@ -65,2 +64,2 @@ "bin": {

}
}
}

@@ -92,7 +92,4 @@ /*global env: true */

// never include functions that belong to the object
else if (typeof e[prop] === 'function') {
// do nothing
}
// don't call JSON.stringify() on Java native objects--Rhino will throw an exception
else {
else if (typeof e[prop] !== 'function') {
// don't call JSON.stringify() on Java native objects--Rhino will throw an exception
result[prop] = isJavaNativeObject(e[prop]) ? String(e[prop]) : e[prop];

@@ -99,0 +96,0 @@ }

@@ -11,3 +11,3 @@ /*global env: true */

var conf = env.conf.markdown;
var defaultTags = [ "classdesc", "description", "params", "properties", "returns", "see"];
var defaultTags = [ 'classdesc', 'description', 'params', 'properties', 'returns', 'see'];
var hasOwnProp = Object.prototype.hasOwnProperty;

@@ -44,3 +44,3 @@ var parse = require('jsdoc/util/markdown').getParser();

if (typeof doclet[tag] === "string" && shouldProcessString(tag, doclet[tag]) ) {
if (typeof doclet[tag] === 'string' && shouldProcessString(tag, doclet[tag]) ) {
doclet[tag] = parse(doclet[tag]);

@@ -47,0 +47,0 @@ }

@@ -17,5 +17,5 @@ /**

if (e.filename.match(/\.erb$/)) {
e.source = e.source.replace(/<%.*%>/g, "");
e.source = e.source.replace(/<%.*%>/g, '');
}
}
};
JSDoc 3
=======
[![Build Status](https://secure.travis-ci.org/jsdoc3/jsdoc.png?branch=master)](http://travis-ci.org/jsdoc3/jsdoc)
[![Build Status](https://img.shields.io/travis/jsdoc3/jsdoc.svg)](http://travis-ci.org/jsdoc3/jsdoc)

@@ -5,0 +5,0 @@ An API documentation generator for JavaScript.

/*global env: true */
'use strict';
var template = require('jsdoc/template'),
fs = require('jsdoc/fs'),
path = require('jsdoc/path'),
taffy = require('taffydb').taffy,
logger = require('jsdoc/util/logger'),
helper = require('jsdoc/util/templateHelper'),
htmlsafe = helper.htmlsafe,
linkto = helper.linkto,
resolveAuthorLinks = helper.resolveAuthorLinks,
scopeToPunc = helper.scopeToPunc,
hasOwnProp = Object.prototype.hasOwnProperty,
data,
view,
outdir = env.opts.destination;
var fs = require('jsdoc/fs');
var helper = require('jsdoc/util/templateHelper');
var logger = require('jsdoc/util/logger');
var path = require('jsdoc/path');
var taffy = require('taffydb').taffy;
var template = require('jsdoc/template');
var util = require('util');
var htmlsafe = helper.htmlsafe;
var linkto = helper.linkto;
var resolveAuthorLinks = helper.resolveAuthorLinks;
var scopeToPunc = helper.scopeToPunc;
var hasOwnProp = Object.prototype.hasOwnProperty;
var data;
var view;
var outdir = env.opts.destination;
function find(spec) {

@@ -61,21 +65,114 @@ return helper.find(data, spec);

function getSignatureAttributes(item) {
var attributes = [];
if (item.optional) {
attributes.push('opt');
}
if (item.nullable === true) {
attributes.push('nullable');
}
else if (item.nullable === false) {
attributes.push('non-null');
}
return attributes;
}
function updateItemName(item) {
var attributes = getSignatureAttributes(item);
var itemName = item.name || '';
if (item.variable) {
itemName = '&hellip;' + itemName;
}
if (attributes && attributes.length) {
itemName = util.format( '%s<span class="signature-attributes">%s</span>', itemName,
attributes.join(', ') );
}
return itemName;
}
function addParamAttributes(params) {
return params.map(updateItemName);
}
function buildItemTypeStrings(item) {
var types = [];
if (item.type && item.type.names) {
item.type.names.forEach(function(name) {
types.push( linkto(name, htmlsafe(name)) );
});
}
return types;
}
function buildAttribsString(attribs) {
var attribsString = '';
if (attribs && attribs.length) {
attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) );
}
return attribsString;
}
function addNonParamAttributes(items) {
var types = [];
items.forEach(function(item) {
types = types.concat( buildItemTypeStrings(item) );
});
return types;
}
function addSignatureParams(f) {
var params = helper.getSignatureParams(f, 'optional');
var params = f.params ? addParamAttributes(f.params) : [];
f.signature = (f.signature || '') + '('+params.join(', ')+')';
f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') );
}
function addSignatureReturns(f) {
var returnTypes = helper.getSignatureReturns(f);
var attribs = [];
var attribsString = '';
var returnTypes = [];
var returnTypesString = '';
// jam all the return-type attributes into an array. this could create odd results (for example,
// if there are both nullable and non-nullable return types), but let's assume that most people
// who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa.
if (f.returns) {
f.returns.forEach(function(item) {
helper.getAttribs(item).forEach(function(attrib) {
if (attribs.indexOf(attrib) === -1) {
attribs.push(attrib);
}
});
});
attribsString = buildAttribsString(attribs);
}
if (f.returns) {
returnTypes = addNonParamAttributes(f.returns);
}
if (returnTypes.length) {
returnTypesString = util.format( ' &rarr; %s{%s}', attribsString, returnTypes.join('|') );
}
f.signature = '<span class="signature">' + (f.signature || '') + '</span>' +
'<span class="type-signature">' +
(returnTypes && returnTypes.length ? ' &rarr; {' + returnTypes.join('|') + '}' : '') +
'</span>';
'<span class="type-signature">' + returnTypesString + '</span>';
}
function addSignatureTypes(f) {
var types = helper.getSignatureTypes(f);
var types = f.type ? buildItemTypeStrings(f) : [];
f.signature = (f.signature || '') + '<span class="type-signature">'+(types.length? ' :'+types.join('|') : '')+'</span>';
f.signature = (f.signature || '') + '<span class="type-signature">' +
(types.length ? ' :' + types.join('|') : '') + '</span>';
}

@@ -85,6 +182,5 @@

var attribs = helper.getAttribs(f);
var attribsString = buildAttribsString(attribs);
f.attribs = '<span class="type-signature">' + htmlsafe(attribs.length ?
// we want the template output to say 'abstract', not 'virtual'
'<' + attribs.join(', ').replace('virtual', 'abstract') + '> ' : '') + '</span>';
f.attribs = util.format('<span class="type-signature">%s</span>', attribsString);
}

@@ -104,3 +200,3 @@

if (!doclet.meta) {
return;
return null;
}

@@ -176,3 +272,3 @@

module.module = symbols[module.longname];
module.module.name = module.module.name.replace('module:', 'require("') + '")';
module.module.name = module.module.name.replace('module:', '(require("') + '"))';
}

@@ -206,3 +302,3 @@ });

if ( !hasOwnProp.call(seen, m.longname) ) {
nav += '<li>'+linkto(m.longname, m.name)+'</li>';
nav += '<li>' + linkto(m.longname, m.name) + '</li>';
}

@@ -219,3 +315,3 @@ seen[m.longname] = true;

if ( !hasOwnProp.call(seen, e.longname) ) {
nav += '<li>'+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'</li>';
nav += '<li>' + linkto( e.longname, e.name.replace(/(^"|"$)/g, '') ) + '</li>';
}

@@ -231,3 +327,3 @@ seen[e.longname] = true;

if ( !hasOwnProp.call(seen, c.longname) ) {
classNav += '<li>'+linkto(c.longname, c.name)+'</li>';
classNav += '<li>' + linkto(c.longname, c.name) + '</li>';
}

@@ -248,3 +344,3 @@ seen[c.longname] = true;

if ( !hasOwnProp.call(seen, e.longname) ) {
nav += '<li>'+linkto(e.longname, e.name)+'</li>';
nav += '<li>' + linkto(e.longname, e.name) + '</li>';
}

@@ -261,3 +357,3 @@ seen[e.longname] = true;

if ( !hasOwnProp.call(seen, n.longname) ) {
nav += '<li>'+linkto(n.longname, n.name)+'</li>';
nav += '<li>' + linkto(n.longname, n.name) + '</li>';
}

@@ -274,3 +370,3 @@ seen[n.longname] = true;

if ( !hasOwnProp.call(seen, m.longname) ) {
nav += '<li>'+linkto(m.longname, m.name)+'</li>';
nav += '<li>' + linkto(m.longname, m.name) + '</li>';
}

@@ -286,3 +382,3 @@ seen[m.longname] = true;

members.tutorials.forEach(function(t) {
nav += '<li>'+tutoriallink(t.name)+'</li>';
nav += '<li>' + tutoriallink(t.name) + '</li>';
});

@@ -289,0 +385,0 @@

@@ -0,1 +1,2 @@

/*eslint no-nested-ternary:0, space-infix-ops: 0 */
/**

@@ -2,0 +3,0 @@ @overview Builds a tree-like JSON string from the doclet data.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc