Module index
March 16, 2025 · View on GitHub
Defines a JSDoc plugin that adds custom properties to doclets and provides a new category tag.
Functions
defineTags()
Defines a new JSDoc tag 'category' that accepts a text value. This adds a corresponding 'category' property on the corresponding doclet.
Examples
@category Model
extractTypeExpression(string) ► string
Extracts the type expression from a comment string
| Parameters | Type | Description |
|---|---|---|
| string | string | the comment string |
| return | string | the type expression |
extractParametersInfo(line) ► Doclet
Extracts the type, name and description of the 'param' tag.
| Parameters | Type | Description |
|---|---|---|
| line | string | the comment line |
| return | Doclet | list of parameters |
extractTagInfo(line, tag) ► Doclet
Extracts the type and description of the specified tag.
| Parameters | Type | Description |
|---|---|---|
| line | string | the comment line |
| tag | 'return' | the specified tag |
| return | Doclet | list of parameters |
populateFunctionInfo(doclet)
Tries to populate 'params' and 'return' type and description on the specified doclet if not provided but found through comment
| Parameters | Type | Description |
|---|---|---|
| doclet | Doclet | the doclet to process |
populateMemberInfo(doclet)
Tries to populate type and description on the specified doclet if not provided but found through comment
| Parameters | Type | Description |
|---|---|---|
| doclet | Doclet | the doclet to process |
getFilePath(d) ► string
Gets the absolute file path corresponding to the specified doclet.
| Parameters | Type | Description |
|---|---|---|
| d | Doclet | the specified doclet |
| return | string | the absolute file path |
getModuleName(filename, folderPath) ► string
Get the module name corresponding to the given filename and path. In case of index.js the folder name is used.
| Parameters | Type | Description |
|---|---|---|
| filename | string | the given filename |
| folderPath | string | the given folder path containing the file |
| return | string | the module name |
defaultProcess(cf, k) ► function
Defines the default process on doclet: applying the 'value' function defined on the configuration object to the specified key/property of the doclet instance.
| Parameters | Type | Description |
|---|---|---|
| cf | object | the configuration object |
| k | string | the key/property of the object |
| return | function | a function that takes a doclet as input and sets the corresponding key/property with the 'value' function |
processDoclet(doclet) ► Doclet
Processes the specified doclet to add or modify properties based on the processConfig object.
| Parameters | Type | Description |
|---|---|---|
| doclet | Doclet | the specified doclet to modify |
| return | Doclet | the modified doclet |
processDoclets(doclets)
Processes the parsed doclets to provide a better hierarchy.
| Parameters | Type | Description |
|---|---|---|
| doclets | Array.<Doclet> | the array of parsed doclets |
Members
handlers
Defines the event handlers of the JSDoc plugin.
Constants
config
The configuration of the JSDoc plugin.
Value
{
rootFolder: env.pwd,
docFolder: env.opts.destination,
includes: (env.opts.includes || 'public,protected,private').toLowerCase().replace(' ', '').split(','),
badgecolors:
(env.conf &&
env.conf.templates &&
env.conf.templates.markdown &&
env.conf.templates.markdown.badgecolors) ||
{}
}
processConfig
The configuration of the doclet processing. Each key of the configuration object defines a process:
- either explicitly if the 'process' function is defined,
- either implictly if the 'value' function is defined : in such case the process consists of applying a value to the corresponding key property of the doclet instance.
- In both cases, the process is executed if there is no 'condition' function, or if the 'condition' function evaluates to true.
Value
d.kind === 'class' &&
d.meta.code &&
d.meta.code.name &&
(d.meta.code.name.startsWith('export') || (d.tags && d.tags.some(t => t.title === 'export'))),
process: d => {
exportedClasses.push(d.name);
return d;
}
},
tocDescription: {
// add 'tocDescription' property that represents the description of a module that appears in the toc
condition: d => d.kind === 'module' && !d.tocDescription,
value: d => d.description
},
valuecode: {
// add 'valuecode' property that represents the source code of a constant
condition: d => d.kind === 'constant',
value: d => {
const sourcefile = getFilePath(d);
const source = fs.readFileSync(sourcefile, 'utf8');
const indexedSource = lineColumn(source);
const { loc } = d.meta.code.node;
const code = source.slice(
indexedSource.toIndex(loc.start.line, loc.start.column + 1),
indexedSource.toIndex(loc.end.line, loc.end.column + 1)
);
return code.includes(' =') ? code.slice(code.indexOf(' =') + 3, -1) : code;
}
},
screenshot: {
// add 'screenshot' property that indicates if the documented has a related snapshot image?
condition: d => {
if (!['module', 'class'].includes(d.kind)) return false;
// the relative path of the screenshot file
const filename = `${d.kind}_${path.basename(d.meta.filename, path.extname(d.meta.filename))}.png`;
const filepath = path.join(config.docFolder, 'images/screenshots', filename);
return fs.existsSync(filepath);
},
value: d => `${d.kind}_${path.basename(d.meta.filename, path.extname(d.meta.filename))}.png`
},
category: {
// modify the 'category' property: add a default value ('other') if none found
condition: d => !d.category && ['module', 'class'].includes(d.kind),
value: () => 'other'
},
categorycolor: {
// add 'categorycolor' property
value: d => config.badgecolors[d.category] || 'blue'
},
static: {
// add 'relativepath' property that indicates if the documented object is static?
value: d => d.scope === 'static'
},
hasParameters: {
// add 'hasParameters' property that indicates if the documented object has @param or @returns tags?
value: d => (d.params && d.params.length > 0) || (d.returns && d.returns.length > 0)
},
relativepath: {
// add 'relativepath' property that indicates the relative path from the documentation to the source code
value: d => {
const filepath = getFilePath(d); // the absolute path of the source file
return path.relative(config.docFolder, filepath).replaceAll(path.sep, path.posix.sep); // the relative path of the source file from the documentation folder
}
},
fixDotPathForModule: {
// fix a jsdoc issue: 'longname' and 'memberof' are corrupted when file path contains a dot: 'module' string appears in the middle of 'longname'
condition: d => d.longname?.indexOf(tagModule) > 0 && d.kind === 'module',
process: d => {
d.name = d.longname.replace(tagModule, '');
d.longname = tagModule + d.name;
if (d.memberof) delete d.memberof;
return d;
}
},
fixDotPathForNonModule: {
// fix a jsdoc issue: 'longname' and 'memberof' are corrupted when file path contains a dot: 'module' string appears in the middle of 'longname'
condition: d => d.longname?.indexOf(tagModule) > 0 && d.kind !== 'module',
process: d => {
d.longname = tagModule + d.longname.replace(tagModule, '');
d.memberof = tagModule + d.memberof.replace(tagModule, '');
return d;
}
},
memberof: {
// modify the 'memberof' property: fix 'export default var'
condition: d => d.kind !== 'module' && !d.memberof && d.longname && d.longname.startsWith(tagModule),
value: d => d.longname
},
access: {
// modify the 'access' property: add a default value ('private') if none found
condition: d => !d.access,
value: d => {
if (d.memberof && exportedClasses.includes(d.memberof) && d.name.charAt(0) !== '_') return 'public';
if (
(d.kind === 'constant' || d.kind === 'function' || d.kind === 'member') &&
d.meta.code &&
d.meta.code.name &&
d.meta.code.name.length > 0 &&
(d.meta.code.name.startsWith('exports.') || d.meta.code.name === 'module.exports')
) {
return 'public';
}
return 'private';
}
},
included: {
// add 'included' property that indicates if the comment is to be included in the doc
value: d => ['module', 'class'].includes(d.kind) || config.includes.includes(d.access)
},
isDefault: {
// add 'isDefault' property that indicates if the documented object is the default export of the module
condition: d => d.kind !== 'module' && d.name && d.name.startsWith(tagModule),
process: d => {
d.isDefault = true;
d.name = 'default';
return d;
}
},
fixUndocumented: {
// fix a jsdoc regression: constructors are forced to undocumented on some conditions
// so the publish handler has been modified to include also undocumented
// and truly undocumented doclets are marked as 'included': false so that they can be removed
condition: d => d.undocumented === true,
process: d => {
d.included = false;
return d;
}
},
acceptTypeScriptType: {
// add 'type' property when type tag is expressed as some funky typescript expression
// causing JSDoc to throw an error preventing type to be defined
// but still can be retrieved from the comment property
condition: d => d.comment?.length > 0,
process: d => {
if (d.kind === 'member' && !d.type) {
populateMemberInfo(d);
}
if (d.kind === 'function' || d.kind === 'constant') {
populateFunctionInfo(d);
}
return d;
}
}