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 environment system provides access to runtime information, configuration data, command-line options, and execution state throughout the documentation generation process.
Global environment object containing all runtime state and configuration.
const env = {
/** Execution timing information */
run: {
/** When JSDoc execution started */
start: Date;
/** When JSDoc execution finished (null during execution) */
finish: Date | null;
};
/** Original command-line arguments array */
args: string[];
/** Loaded and merged configuration object */
conf: ConfigObject;
/** Absolute path to JSDoc installation directory */
dirname: string;
/** Working directory when JSDoc was started */
pwd: string;
/** Parsed command-line options */
opts: CommandLineOptions;
/** Array of source file paths to process */
sourceFiles: string[];
/** JSDoc version information */
version: {
/** Version number string */
number: string;
/** Revision date string */
revision: string;
};
};Structure of parsed command-line options available in env.opts.
interface CommandLineOptions {
/** Output destination directory */
destination?: string;
/** File encoding for reading source files */
encoding?: string;
/** Path to configuration file */
configure?: string;
/** Path to template directory */
template?: string;
/** Include private members in documentation */
private?: boolean;
/** Path to README file */
readme?: string;
/** Path to package.json file */
package?: string;
/** Enable debug logging */
debug?: boolean;
/** Enable verbose logging */
verbose?: boolean;
/** Recursively scan directories */
recurse?: boolean;
/** Path to tutorials directory */
tutorials?: string;
/** Access levels to include */
access?: string | string[];
/** Treat warnings as errors */
pedantic?: boolean;
/** Display help and exit */
help?: boolean;
/** Display version and exit */
version?: boolean;
/** Run test suite */
test?: boolean;
/** Dump doclet internals to console */
explain?: boolean;
/** Custom query parameters object */
query?: object;
/** Positional arguments (source files/directories) */
_?: string[];
}const env = require('jsdoc/env');
// Check execution state
console.log('JSDoc started at:', env.run.start);
console.log('Working directory:', env.pwd);
console.log('JSDoc version:', env.version.number);
// Access configuration
console.log('Output destination:', env.opts.destination);
console.log('Debug mode:', env.opts.debug);
console.log('Plugins loaded:', env.conf.plugins);
// Check source files
console.log('Processing files:', env.sourceFiles);// Check if in debug mode
if (env.opts.debug) {
console.log('Debug information enabled');
}
// Check if private members should be included
if (env.opts.private) {
console.log('Including private members');
}
// Check template configuration
if (env.conf.templates && env.conf.templates.cleverLinks) {
console.log('Clever links enabled');
}
// Validate required options
if (!env.opts.destination) {
console.warn('No destination specified, using default');
}// Access timing information
const startTime = env.run.start;
console.log('JSDoc started at:', startTime.toISOString());
// Calculate duration (if finished)
if (env.run.finish) {
const duration = env.run.finish.getTime() - env.run.start.getTime();
console.log(`Execution took ${duration}ms`);
}// Get version details
const versionInfo = env.version;
console.log(`JSDoc ${versionInfo.number}`);
console.log(`Revision: ${versionInfo.revision}`);
// Version string formatting
const versionString = `JSDoc ${versionInfo.number} (${versionInfo.revision})`;// Get path information
const jsdocDir = env.dirname;
const workingDir = env.pwd;
console.log('JSDoc installed at:', jsdocDir);
console.log('Working directory:', workingDir);
// Resolve relative paths
const path = require('path');
const configPath = path.resolve(workingDir, env.opts.configure || 'jsdoc.conf.json');// Access main configuration sections
const sourceConfig = env.conf.source;
const pluginList = env.conf.plugins;
const templateConfig = env.conf.templates;
// Check source patterns
console.log('Include pattern:', sourceConfig.includePattern);
console.log('Exclude pattern:', sourceConfig.excludePattern);
// Check loaded plugins
pluginList.forEach(plugin => {
console.log('Plugin loaded:', plugin);
});// Access all command-line options
const opts = env.opts;
// Check boolean flags
const flags = {
debug: opts.debug || false,
verbose: opts.verbose || false,
private: opts.private || false,
recurse: opts.recurse || false,
pedantic: opts.pedantic || false
};
// Get paths
const paths = {
destination: opts.destination || './out/',
template: opts.template || 'templates/default',
readme: opts.readme,
package: opts.package,
tutorials: opts.tutorials
};
// Get source files from positional arguments
const sourceFiles = opts._ || [];// Set configuration values (typically done during initialization)
env.opts.destination = './custom-docs/';
env.opts.debug = true;
// Add source files
env.sourceFiles = ['src/index.js', 'src/utils.js'];
// Set version information
env.version = {
number: '4.0.4',
revision: 'Wed Oct 19 2023 12:00:00 GMT+0000 (UTC)'
};function validateEnvironment() {
const issues = [];
// Check required paths exist
const fs = require('fs');
if (env.opts.readme && !fs.existsSync(env.opts.readme)) {
issues.push(`README file not found: ${env.opts.readme}`);
}
if (env.opts.package && !fs.existsSync(env.opts.package)) {
issues.push(`Package file not found: ${env.opts.package}`);
}
// Check source files
if (!env.sourceFiles || env.sourceFiles.length === 0) {
issues.push('No source files specified');
}
// Validate configuration
if (!env.conf) {
issues.push('No configuration loaded');
}
return issues;
}
// Usage
const issues = validateEnvironment();
if (issues.length > 0) {
console.error('Environment issues:', issues);
}JSDoc provides deprecated global access to environment (for backward compatibility):
// Deprecated: global.env (use require('jsdoc/env') instead)
global.env = (() => require('jsdoc/env'))();
// Deprecated: global.app (use require('jsdoc/app') instead)
global.app = (() => require('jsdoc/app'))();
// Access patterns (deprecated)
if (global.env.opts.debug) {
// Debug functionality
}// Preferred: require the env module
const env = require('jsdoc/env');
// Access environment information
const isDebug = env.opts.debug;
const outputDir = env.opts.destination;
// Use in plugin development
exports.handlers = {
parseBegin: function(e) {
if (env.opts.verbose) {
console.log('Starting parse of:', e.sourcefiles.length, 'files');
}
}
};// environment-plugin.js
const env = require('jsdoc/env');
exports.handlers = {
parseBegin: function(e) {
// Log based on environment settings
if (env.opts.verbose) {
console.log(`JSDoc ${env.version.number} starting parse`);
console.log(`Output destination: ${env.opts.destination}`);
console.log(`Processing ${e.sourcefiles.length} files`);
}
// Debug information
if (env.opts.debug) {
console.log('Environment state:', {
pwd: env.pwd,
dirname: env.dirname,
sourceFiles: env.sourceFiles,
plugins: env.conf.plugins
});
}
},
parseComplete: function(e) {
if (env.opts.verbose) {
const duration = Date.now() - env.run.start.getTime();
console.log(`Parse completed in ${duration}ms`);
console.log(`Generated ${e.doclets.length} doclets`);
}
}
};// config-processor.js
const env = require('jsdoc/env');
function processBasedOnConfig() {
const conf = env.conf;
// Markdown processing based on plugin
const hasMarkdown = conf.plugins.includes('plugins/markdown');
// Template-specific processing
const templateConfig = conf.templates || {};
const useCleverLinks = templateConfig.cleverLinks;
// Source filtering based on patterns
const includePattern = new RegExp(conf.source.includePattern);
const excludePattern = conf.source.excludePattern ?
new RegExp(conf.source.excludePattern) : null;
return {
hasMarkdown,
useCleverLinks,
includePattern,
excludePattern
};
}
// Usage in template
exports.publish = function(data, opts) {
const config = processBasedOnConfig();
if (config.hasMarkdown) {
// Process markdown in descriptions
}
if (config.useCleverLinks) {
// Generate intelligent link text
}
};// state-manager.js
const env = require('jsdoc/env');
class RuntimeState {
constructor() {
this.startTime = env.run.start;
this.isDebug = env.opts.debug;
this.isVerbose = env.opts.verbose;
}
logTiming(message) {
if (this.isVerbose) {
const elapsed = Date.now() - this.startTime.getTime();
console.log(`[${elapsed}ms] ${message}`);
}
}
debugLog(message, data) {
if (this.isDebug) {
console.log(`[DEBUG] ${message}`, data || '');
}
}
getConfig(key) {
return key ? env.conf[key] : env.conf;
}
getOption(key) {
return key ? env.opts[key] : env.opts;
}
}
module.exports = new RuntimeState();// env-info.js
const env = require('jsdoc/env');
function displayEnvironmentInfo() {
console.log('\n=== JSDoc Environment Information ===');
console.log(`Version: ${env.version.number}`);
console.log(`Revision: ${env.version.revision}`);
console.log(`Started: ${env.run.start.toISOString()}`);
console.log(`Working Directory: ${env.pwd}`);
console.log(`JSDoc Directory: ${env.dirname}`);
console.log('\n--- Configuration ---');
console.log(`Plugins: ${env.conf.plugins.join(', ') || 'none'}`);
console.log(`Include Pattern: ${env.conf.source.includePattern}`);
console.log(`Exclude Pattern: ${env.conf.source.excludePattern || 'none'}`);
console.log('\n--- Command Line Options ---');
console.log(`Destination: ${env.opts.destination || 'default'}`);
console.log(`Template: ${env.opts.template || 'default'}`);
console.log(`Debug: ${env.opts.debug || false}`);
console.log(`Verbose: ${env.opts.verbose || false}`);
console.log(`Private: ${env.opts.private || false}`);
console.log(`Recurse: ${env.opts.recurse || false}`);
console.log('\n--- Source Files ---');
console.log(`Count: ${env.sourceFiles.length}`);
if (env.opts.verbose && env.sourceFiles.length > 0) {
env.sourceFiles.forEach(file => console.log(` ${file}`));
}
console.log('=====================================\n');
}
// Usage
if (env.opts.debug || env.opts.verbose) {
displayEnvironmentInfo();
}// Plugin that adapts to environment
exports.handlers = {
parseBegin: function(e) {
// Adapt behavior based on environment
this.isProduction = !env.opts.debug && !env.opts.verbose;
this.outputDir = env.opts.destination;
this.templatePath = env.opts.template;
},
newDoclet: function(e) {
// Production vs development processing
if (this.isProduction) {
// Minimal processing for production
if (e.doclet.kind === 'function' && !e.doclet.description) {
e.doclet.undocumented = true;
}
} else {
// Enhanced processing for development
if (!e.doclet.description) {
console.warn(`Missing description: ${e.doclet.longname}`);
}
}
}
};// Template that uses environment information
exports.publish = function(data, opts) {
const env = require('jsdoc/env');
// Template configuration based on environment
const templateConfig = {
debug: env.opts.debug,
verbose: env.opts.verbose,
version: env.version.number,
generatedAt: new Date().toISOString(),
sourceCount: env.sourceFiles.length
};
// Pass environment info to templates
const commonData = {
env: templateConfig,
packageInfo: opts.package,
hasReadme: !!opts.readme
};
// Generate pages with environment context
generateIndexPage(data, commonData);
generateClassPages(data, commonData);
};