Skip to content

Commit

Permalink
Merge pull request #12024 from hasezoey/updateDox
Browse files Browse the repository at this point in the history
Update `dox` to latest version and fix some documentation issues
  • Loading branch information
vkarpov15 committed Jul 8, 2022
2 parents 51ea808 + 1cc2293 commit d80a2ee
Show file tree
Hide file tree
Showing 43 changed files with 338 additions and 248 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Expand Up @@ -49,4 +49,8 @@ docs/tutorials/*.html
docs/typescript/*.html
docs/api/*.html
index.html

# yarn package-lock
yarn.lock

examples/ecommerce-netlify-functions/.netlify/state.json
114 changes: 92 additions & 22 deletions docs/source/api.js
Expand Up @@ -50,13 +50,35 @@ const out = module.exports.docs;

const combinedFiles = [];
for (const file of files) {
const comments = dox.parseComments(fs.readFileSync(`./${file}`, 'utf8'), { raw: true });
comments.file = file;
combinedFiles.push(comments);
try {
const comments = dox.parseComments(fs.readFileSync(`./${file}`, 'utf8'), { raw: true });
comments.file = file;
combinedFiles.push(comments);
} catch (err) {
// show log of which file has thrown a error for easier debugging
console.error("Error while trying to parseComments for ", file);
throw err;
}
}

parse();

/**
* @typedef {Object} PropContext
* @property {boolean} [isStatic] Defines wheter the current property is a static property (not mutually exlusive with "isInstance")
* @property {boolean} [isInstance] Defines wheter the current property is a instance property (not mutually exlusive with "isStatic")
* @property {boolean} [isFunction] Defines wheter the current property is meant to be a function
* @property {string} [constructor] Defines the Constructor (or rather path) the current property is on
* @property {boolean} [constructorWasUndefined] Defined wheter the "constructor" property was defined by "dox", but was set to "undefined"
* @property {string} [type] Defines the type the property is meant to be
* @property {string} [name] Defines the current Properties name
* @property {Object} [return] The full object for a "@return" jsdoc tag
* @property {string} [string] Defines the full string the property will be listed as
* @property {string} [anchorId] Defines the Anchor ID to be used for linking
* @property {string} [description] Defines the Description the property will be listed with
* @property {string} [deprecated] Defines wheter the current Property is signaled as deprecated
*/

function parse() {
for (const props of combinedFiles) {
let name = props.file.
Expand Down Expand Up @@ -88,43 +110,67 @@ function parse() {
if (prop.ignore || prop.isPrivate) {
continue;
}


/** @type {PropContext} */
const ctx = prop.ctx || {};

// somehow in "dox", it is named "receiver" sometimes, not "constructor"
// this is used as a fall-back if the handling below does not overwrite it
if ("receiver" in ctx) {
ctx.constructor = ctx.receiver;
delete ctx.receiver;
}

// in some cases "dox" has "ctx.constructor" defined but set to "undefined", which will later be used for setting "ctx.string"
if ("constructor" in ctx && ctx.constructor === undefined) {
ctx.constructorWasUndefined = true;
}

for (const tag of prop.tags) {
switch (tag.type) {
case 'receiver':
ctx.constructor = tag.string;
break;
case 'property':
ctx.type = 'property';

// somewhere since 6.0 the "string" property came back, which was gone with 4.5
let str = tag.string;

const match = str.match(/^{\w+}/);
if (match != null) {
ctx.type = match[0].substring(1, match[0].length - 1);
str = str.replace(/^{\w+}\s*/, '');
}
ctx.name = str;
ctx.string = `${ctx.constructor}.prototype.${ctx.name}`;
break;
case 'type':
ctx.type = Array.isArray(tag.types) ? tag.types.join('|') : tag.types;
break;
case 'static':
ctx.type = 'property';
ctx.static = true;
ctx.name = tag.string;
ctx.string = `${data.name}.${ctx.name}`;
ctx.isStatic = true;
// dont take "string" as "name" from here, because jsdoc definitions of "static" do not have parameters, also its defined elsewhere anyway
// ctx.name = tag.string;
break;
case 'function':
ctx.type = 'function';
ctx.static = true;
ctx.isStatic = true;
ctx.name = tag.string;
ctx.string = `${data.name}.${ctx.name}()`;
// extra parameter to make function definitions independant of where "@function" is defined
// like "@static" could have overwritten "ctx.string" again if defined after "@function"
ctx.isFunction = true;
break;
case 'return':
tag.return = tag.description ?
md.parse(tag.description).replace(/^<p>/, '').replace(/<\/p>$/, '') :
tag.description = tag.description ?
md.parse(tag.description).replace(/^<p>/, '').replace(/<\/p>\n?$/, '') :
'';

// dox does not add "void" / "undefined" to types, so in the documentation it would result in a empty "«»"
if (tag.string.includes('void') || tag.string.includes('undefined')) {
tag.types.push("void");
}

ctx.return = tag;
break;
case 'inherits':
Expand All @@ -133,6 +179,10 @@ function parse() {
case 'event':
case 'param':
ctx[tag.type] = (ctx[tag.type] || []);
// the following is required, because in newer "dox" version "null" is not included in "types" anymore, but a seperate property
if (tag.nullable) {
tag.types.push('null');
}
if (tag.types) {
tag.types = tag.types.join('|');
}
Expand All @@ -147,26 +197,49 @@ function parse() {
case 'method':
ctx.type = 'method';
ctx.name = tag.string;
ctx.string = `${ctx.constructor}.prototype.${ctx.name}()`;
ctx.isFunction = true;
break;
case 'memberOf':
ctx.constructor = tag.parent;
ctx.string = `${ctx.constructor}.prototype.${ctx.name}`;
if (ctx.type === 'method') {
ctx.string += '()';
}
break;
case 'constructor':
ctx.string = tag.string + '()';
ctx.string = tag.string;
ctx.name = tag.string;
ctx.isFunction = true;
break;
case 'instance':
ctx.isInstance = true;
break;
case 'deprecated':
ctx.deprecated = true;
break;
}
}

if (ctx.isInstance && ctx.isStatic) {
console.warn(`Property "${ctx.name}" in "${ctx.constructor}" has both instance and static JSDOC markings (most likely both @instance and @static)! (File: "${props.file}")`);
}

// the following if-else-if statement is in this order, because there are more "instance" methods thans static
// the following condition will be true if "isInstance = true" or if "isInstance = false && isStatic = false" AND "ctx.string" are empty or not defined
// if "isStatic" and "isInstance" are falsy and "ctx.string" is not falsy, then rely on the "ctx.string" set by "dox"
if (ctx.isInstance || (!ctx.isStatic && !ctx.isInstance && (!ctx.string || ctx.constructorWasUndefined))) {
ctx.string = `${ctx.constructor}.prototype.${ctx.name}`;
} else if (ctx.isStatic) {
ctx.string = `${ctx.constructor}.${ctx.name}`;
}

// add "()" to the end of the string if function
if ((ctx.isFunction || ctx.type === "method") && !ctx.string.endsWith("()")) {
ctx.string = ctx.string + "()";
}

// fixing up "something.prototypemissingdot" to "something.prototype.missingdot"
if (/\.prototype[^.]/.test(ctx.string)) {
ctx.string = `${ctx.constructor}.prototype.${ctx.name}`;
}

// Backwards compat
// Backwards compat anchors
if (typeof ctx.constructor === 'string') {
ctx.anchorId = `${ctx.constructor.toLowerCase()}_${ctx.constructor}-${ctx.name}`;
} else if (typeof ctx.receiver === 'string') {
Expand All @@ -178,9 +251,6 @@ function parse() {
ctx.description = prop.description.full.
replace(/<br \/>/ig, ' ').
replace(/&gt;/ig, '>');
if (ctx.description.includes('function capitalize')) {
console.log('\n\n-------\n\n', ctx);
}
ctx.description = md.parse(ctx.description);

data.props.push(ctx);
Expand Down
5 changes: 3 additions & 2 deletions lib/aggregate.js
Expand Up @@ -481,7 +481,8 @@ Aggregate.prototype.sortByCount = function(arg) {
*
* @see $lookup https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/#pipe._S_lookup
* @param {Object} options to $lookup as described in the above link
* @return {Aggregate}* @api public
* @return {Aggregate}
* @api public
*/

Aggregate.prototype.lookup = function(options) {
Expand Down Expand Up @@ -1051,7 +1052,7 @@ Aggregate.prototype.catch = function(reject) {
* You do not need to call this function explicitly, the JavaScript runtime
* will call it for you.
*
* #### Example
* #### Example:
*
* const agg = Model.aggregate([{ $match: { age: { $gte: 25 } } }]);
* for await (const doc of agg) {
Expand Down
18 changes: 9 additions & 9 deletions lib/connection.js
Expand Up @@ -93,7 +93,7 @@ Connection.prototype.__proto__ = EventEmitter.prototype;
*
* Each state change emits its associated event name.
*
* #### Example
* #### Example:
*
* conn.on('connected', callback);
* conn.on('disconnected', callback);
Expand Down Expand Up @@ -193,7 +193,7 @@ Connection.prototype.collections;
/**
* The name of the database this connection points to.
*
* #### Example
* #### Example:
*
* mongoose.createConnection('mongodb://localhost:27017/mydb').name; // "mydb"
*
Expand All @@ -210,7 +210,7 @@ Connection.prototype.name;
* a map from model names to models. Contains all models that have been
* added to this connection using [`Connection#model()`](/docs/api/connection.html#connection_Connection-model).
*
* #### Example
* #### Example:
*
* const conn = mongoose.createConnection();
* const Test = conn.model('Test', mongoose.Schema({ name: String }));
Expand All @@ -230,7 +230,7 @@ Connection.prototype.models;
* A number identifier for this connection. Used for debugging when
* you have [multiple connections](/docs/connections.html#multiple_connections).
*
* #### Example
* #### Example:
*
* // The default connection has `id = 0`
* mongoose.connection.id; // 0
Expand Down Expand Up @@ -274,7 +274,7 @@ Object.defineProperty(Connection.prototype, 'plugins', {
* The host name portion of the URI. If multiple hosts, such as a replica set,
* this will contain the first host name in the URI
*
* #### Example
* #### Example:
*
* mongoose.createConnection('mongodb://localhost:27017/mydb').host; // "localhost"
*
Expand All @@ -294,7 +294,7 @@ Object.defineProperty(Connection.prototype, 'host', {
* The port portion of the URI. If multiple hosts, such as a replica set,
* this will contain the port from the first host name in the URI.
*
* #### Example
* #### Example:
*
* mongoose.createConnection('mongodb://localhost:27017/mydb').port; // 27017
*
Expand All @@ -313,7 +313,7 @@ Object.defineProperty(Connection.prototype, 'port', {
/**
* The username specified in the URI
*
* #### Example
* #### Example:
*
* mongoose.createConnection('mongodb://val:psw@localhost:27017/mydb').user; // "val"
*
Expand All @@ -332,7 +332,7 @@ Object.defineProperty(Connection.prototype, 'user', {
/**
* The password specified in the URI
*
* #### Example
* #### Example:
*
* mongoose.createConnection('mongodb://val:psw@localhost:27017/mydb').pass; // "psw"
*
Expand Down Expand Up @@ -1452,7 +1452,7 @@ Connection.prototype.setClient = function setClient(client) {
*
* @param {Object} options
* @param {Boolean} options.continueOnError `false` by default. If set to `true`, mongoose will not throw an error if one model syncing failed, and will return an object where the keys are the names of the models, and the values are the results/errors for each model.
* @returns
* @return {Promise} Returns a Promise, when the Promise resolves the value is a list of the dropped indexes.
*/
Connection.prototype.syncIndexes = async function syncIndexes(options = {}) {
const result = {};
Expand Down
5 changes: 3 additions & 2 deletions lib/cursor/AggregationCursor.js
Expand Up @@ -107,7 +107,7 @@ if (Symbol.asyncIterator != null) {
* Registers a transform function which subsequently maps documents retrieved
* via the streams interface or `.next()`
*
* #### Example
* #### Example:
*
* // Map documents returned by `data` events
* Thing.
Expand All @@ -132,6 +132,7 @@ if (Symbol.asyncIterator != null) {
*
* @param {Function} fn
* @return {AggregationCursor}
* @memberOf AggregationCursor
* @api public
* @method map
*/
Expand Down Expand Up @@ -226,7 +227,7 @@ AggregationCursor.prototype.eachAsync = function(fn, opts, callback) {
* You do not need to call this function explicitly, the JavaScript runtime
* will call it for you.
*
* #### Example
* #### Example:
*
* // Async iterator without explicitly calling `cursor()`. Mongoose still
* // creates an AggregationCursor instance internally.
Expand Down
9 changes: 5 additions & 4 deletions lib/cursor/QueryCursor.js
Expand Up @@ -112,7 +112,7 @@ QueryCursor.prototype._read = function() {
* Registers a transform function which subsequently maps documents retrieved
* via the streams interface or `.next()`
*
* #### Example
* #### Example:
*
* // Map documents returned by `data` events
* Thing.
Expand All @@ -137,6 +137,7 @@ QueryCursor.prototype._read = function() {
*
* @param {Function} fn
* @return {QueryCursor}
* @memberOf QueryCursor
* @api public
* @method map
*/
Expand Down Expand Up @@ -211,7 +212,7 @@ QueryCursor.prototype.next = function(callback) {
* will wait for the promise to resolve before iterating on to the next one.
* Returns a promise that resolves when done.
*
* #### Example
* #### Example:
*
* // Iterate over documents asynchronously
* Thing.
Expand Down Expand Up @@ -300,7 +301,7 @@ QueryCursor.prototype._transformForAsyncIterator = function() {
* You do not need to call this function explicitly, the JavaScript runtime
* will call it for you.
*
* #### Example
* #### Example:
*
* // Works without using `cursor()`
* for await (const doc of Model.find([{ $sort: { name: 1 } }])) {
Expand All @@ -320,7 +321,7 @@ QueryCursor.prototype._transformForAsyncIterator = function() {
* support async iterators.
*
* @method Symbol.asyncIterator
* @memberOf Query
* @memberOf QueryCursor
* @instance
* @api public
*/
Expand Down

0 comments on commit d80a2ee

Please sign in to comment.