API documentation generator for JavaScript that parses source code and JSDoc comments to produce HTML documentation
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
JSDoc's configuration system provides flexible control over documentation generation through JSON configuration files, command-line options, and environment settings.
Core configuration management class for loading and merging settings.
class Config {
/**
* Create configuration instance
* @param jsonOrObject - Configuration JSON string, object, or undefined
*/
constructor(jsonOrObject?: string | object);
/**
* Get merged configuration with defaults
* @returns Complete configuration object
*/
get(): ConfigObject;
}Complete configuration object interface with all available options.
interface ConfigObject {
/** Plugin module paths to load */
plugins: string[];
/** Maximum recursion depth for directory scanning */
recurseDepth: number;
/** Source file configuration */
source: {
/** Regex pattern for files to include */
includePattern: string;
/** Regex pattern for files to exclude */
excludePattern: string;
/** Array of specific paths to include */
include?: string[];
/** Array of specific paths to exclude */
exclude?: string[];
};
/** Source code type: 'module' or 'script' */
sourceType: string;
/** JSDoc tag configuration */
tags: {
/** Allow unknown tags without errors */
allowUnknownTags: boolean;
/** Tag dictionaries to use */
dictionaries: string[];
};
/** Template configuration */
templates: {
/** Use monospace font for links */
monospaceLinks: boolean;
/** Use intelligent link text */
cleverLinks: boolean;
/** Additional template-specific options */
[key: string]: any;
};
/** Command-line options */
opts?: {
/** Output destination directory */
destination?: string;
/** File encoding */
encoding?: string;
/** Configuration file path */
configure?: string;
/** Template directory path */
template?: string;
/** Include private members */
private?: boolean;
/** README file path */
readme?: string;
/** Package.json file path */
package?: string;
/** Enable debug logging */
debug?: boolean;
/** Enable verbose logging */
verbose?: boolean;
/** Recursive directory scanning */
recurse?: boolean;
/** Tutorial directory path */
tutorials?: string;
/** Access levels to include */
access?: string | string[];
/** Treat warnings as errors */
pedantic?: boolean;
/** Additional query parameters */
query?: object;
};
}{
"source": {
"include": ["./src/"],
"includePattern": "\\.(js|jsx)$",
"exclude": ["node_modules/"],
"excludePattern": "(node_modules/|docs/)"
},
"opts": {
"destination": "./docs/",
"recurse": true
},
"plugins": ["plugins/markdown"]
}{
"tags": {
"allowUnknownTags": true,
"dictionaries": ["jsdoc", "closure"]
},
"source": {
"include": ["./lib", "./src"],
"includePattern": "\\.(js|jsx|ts|tsx)$",
"exclude": ["node_modules/", "test/", "spec/"],
"excludePattern": "((node_modules/|docs/)|\\.(test|spec)\\.js$)"
},
"plugins": [
"plugins/markdown",
"plugins/overloadHelper",
"plugins/summarize",
"./custom-plugins/version-plugin"
],
"recurseDepth": 10,
"sourceType": "module",
"opts": {
"destination": "./public/docs/",
"encoding": "utf8",
"private": false,
"recurse": true,
"template": "./templates/custom",
"tutorials": "./tutorials",
"readme": "./README.md",
"package": "./package.json",
"access": ["public", "protected"],
"debug": false,
"verbose": false,
"pedantic": false
},
"templates": {
"cleverLinks": false,
"monospaceLinks": false,
"dateFormat": "MMMM Do YYYY",
"outputSourceFiles": true,
"systemName": "My API Documentation",
"footer": "Generated by JSDoc",
"copyright": "Copyright © 2023 My Company",
"includeDate": true,
"navType": "vertical",
"theme": "default",
"linenums": true,
"collapseSymbols": false
}
}{
"plugins": ["plugins/markdown"],
"markdown": {
"hardwrap": true,
"idInHeadings": true
},
"templates": {
"applicationName": "My API",
"disqus": "my-disqus-shortname",
"googleAnalytics": "UA-12345678-1",
"openGraph": {
"title": "My API Documentation",
"type": "website",
"image": "http://example.com/image.png",
"site_name": "My API Docs"
},
"meta": {
"title": "My API Documentation",
"description": "Complete API reference",
"keyword": "api, documentation, javascript"
},
"linenums": true
}
}// Environment object structure
const env = {
/** Runtime information */
run: {
start: Date;
finish: Date | null;
};
/** Command-line arguments */
args: string[];
/** Loaded configuration */
conf: ConfigObject;
/** JSDoc installation directory */
dirname: string;
/** Working directory when JSDoc started */
pwd: string;
/** Parsed command-line options */
opts: ConfigObject['opts'];
/** Source files to process */
sourceFiles: string[];
/** Version information */
version: {
number: string;
revision: string;
};
};const env = require('jsdoc/env');
// Check if debug mode is enabled
if (env.opts.debug) {
console.log('Debug mode enabled');
}
// Get output destination
const outputDir = env.opts.destination || './out/';
// Check configuration
if (env.conf.plugins.includes('plugins/markdown')) {
console.log('Markdown plugin enabled');
}JSDoc uses these defaults when no configuration is provided:
const defaults = {
plugins: [],
recurseDepth: 10,
source: {
includePattern: '.+\\.js(doc|x)?$',
excludePattern: ''
},
sourceType: 'module',
tags: {
allowUnknownTags: true,
dictionaries: ['jsdoc', 'closure']
},
templates: {
monospaceLinks: false,
cleverLinks: false
}
};Configuration is merged in this order (later values override earlier):
// Example of configuration merging
const baseConfig = {
source: { includePattern: '\\.js$' },
opts: { destination: './out/' }
};
const userConfig = {
source: { excludePattern: 'test/' },
opts: { destination: './docs/' }
};
// Result after merging:
const finalConfig = {
source: {
includePattern: '\\.js$', // from base
excludePattern: 'test/' // from user
},
opts: {
destination: './docs/' // user overrides base
}
};JSDoc looks for configuration files in this order:
-c or --configure optionconf.json in JSDoc installation directoryconf.json.EXAMPLE as fallback// Configuration loading process
const Config = require('jsdoc/config');
const path = require('jsdoc/path');
let configPath = env.opts.configure || path.join(env.dirname, 'conf.json');
try {
const configContent = fs.readFileSync(configPath, 'utf8');
const config = new Config(configContent);
env.conf = config.get();
} catch (error) {
// Fall back to default configuration
env.conf = new Config().get();
}{
"source": {
"include": ["./src", "./lib"],
"exclude": ["./src/legacy", "./lib/vendor"],
"includePattern": "\\.(js|jsx|ts|tsx)$",
"excludePattern": "((node_modules/|docs/)|\\.(test|spec|min)\\.js$)"
}
}// Common include patterns
{
"includePattern": "\\.js$", // JavaScript files only
"includePattern": "\\.(js|jsx)$", // JavaScript and JSX
"includePattern": "\\.(js|ts)$", // JavaScript and TypeScript
"includePattern": "\\.js(doc|x)?$" // JS, JSX, and JSDoc files
}
// Common exclude patterns
{
"excludePattern": "node_modules/", // Exclude dependencies
"excludePattern": "\\.(test|spec)\\.js$", // Exclude test files
"excludePattern": "\\.min\\.js$", // Exclude minified files
"excludePattern": "(test/|spec/|build/)" // Multiple directories
}{
"templates": {
"cleverLinks": false, // Automatic link text generation
"monospaceLinks": false, // Monospace font for links
"dateFormat": "ddd MMM Do YYYY",
"outputSourceFiles": true, // Include source file links
"outputSourcePath": true, // Show source paths
"systemName": "My API", // Site title
"footer": "Custom footer", // Footer text
"copyright": "© 2023", // Copyright notice
"includeDate": true, // Include generation date
"navType": "vertical", // Navigation style
"theme": "cerulean", // Color theme
"linenums": false, // Line numbers in code
"collapseSymbols": false, // Collapsible sections
"inverseNav": false, // Inverse navigation colors
"protocol": "html://", // Link protocol
"methodHeadingReturns": false // Show returns in headings
}
}{
"templates": {
"custom": {
"brandColor": "#2196F3",
"logoUrl": "./assets/logo.png",
"showInheritedInNav": true,
"showAccessFilter": true,
"analytics": {
"ua": "UA-12345678-1",
"domain": "mydocs.com"
},
"social": {
"github": "username/repo",
"twitter": "@username"
}
}
}
}const Config = require('jsdoc/config');
const fs = require('fs');
// Load from JSON file
const configContent = fs.readFileSync('jsdoc.conf.json', 'utf8');
const config = new Config(configContent);
const settings = config.get();
// Load from object
const configObject = {
source: { includePattern: '\\.js$' },
opts: { destination: './docs/' }
};
const config2 = new Config(configObject);
const settings2 = config2.get();
// Use defaults
const config3 = new Config();
const defaults = config3.get();// config-loader.js
const env = process.env.NODE_ENV || 'development';
const configs = {
development: {
opts: {
destination: './dev-docs/',
debug: true,
verbose: true
}
},
production: {
opts: {
destination: './public/docs/',
debug: false,
verbose: false
},
templates: {
includeDate: true,
copyright: `© ${new Date().getFullYear()} My Company`
}
}
};
module.exports = configs[env];// dynamic-config.js
const pkg = require('./package.json');
module.exports = {
source: {
include: ['./src'],
includePattern: '\\.js$'
},
opts: {
destination: './docs/',
readme: './README.md',
package: './package.json'
},
templates: {
systemName: pkg.name,
footer: `${pkg.name} v${pkg.version}`,
copyright: `© ${new Date().getFullYear()} ${pkg.author}`
}
};// conditional-plugins.js
const plugins = ['plugins/markdown'];
// Add development plugins
if (process.env.NODE_ENV === 'development') {
plugins.push('plugins/eventDumper');
}
// Add custom plugins if they exist
try {
require.resolve('./custom-plugin');
plugins.push('./custom-plugin');
} catch (e) {
// Plugin not available
}
module.exports = {
plugins: plugins,
// ... other configuration
};function validateConfig(config) {
const errors = [];
// Validate required fields
if (!config.source) {
errors.push('Missing source configuration');
}
// Validate patterns
if (config.source.includePattern) {
try {
new RegExp(config.source.includePattern);
} catch (e) {
errors.push(`Invalid includePattern: ${e.message}`);
}
}
// Validate plugins
if (config.plugins) {
config.plugins.forEach(plugin => {
try {
require.resolve(plugin);
} catch (e) {
errors.push(`Plugin not found: ${plugin}`);
}
});
}
return errors;
}
// Usage
const config = new Config(configContent);
const settings = config.get();
const errors = validateConfig(settings);
if (errors.length > 0) {
console.error('Configuration errors:', errors);
process.exit(1);
}