MediaWiki and related codebases use JSDoc annotations to document JavaScript code. This page contains information about setting up JSDoc, documenting code, and publishing a docs site.

Documenting your code edit

For more information about writing code comments in JavaScript, see Manual:Coding conventions/JavaScript.

JSDoc reads descriptions and annotations from code comments in JavaScript files. In general, annotations begin with @ and must be separated by new lines. Annotation blocks that precede a function or symbol assume that the annotation belongs to the following code and use the name of that function or symbol.

For a complete list of tags supported by JSDoc, see the JSDoc documentation.

ES6 example edit

/**
 * Description for MyClass.
 *
 * @extends MyParentClass
 */
class MyClass extends MyParentClass {
	/**
     * @param {Object} [config] Configuration options
     * @param {string} [config.optionA] Description for optionA
     * @param {string} [config.optionB] Description for optionB
     */
    constructor( config ) {
    	// …
    }
    
    // …
}

export default MyClass;

When using ES6 classes, you do not need to use tags such as @class, @member, @constructor, and @module since the structure of your code already expresses this to JSDoc. Adding these tags might cause duplicate definitions.

If you use ECMAScript Modules and want to export the class, this must be a separate statement due to a bug in JSDoc.[1] In the above example, using export default MyClass { … } will break the documentation. Instead, move the export default MyClass; to a separate statement.

ES5 example edit

To document a class that uses ES5 syntax, with the class and constructor defined together as function MyClass(…) {…}, use:

  • a @classdesc tag to document the class
  • a @description tag to document the constructor
/**
 * @classdesc Class description.
 *
 * @description Constructor description.
 *
 * @param {string} myParam
 * @return {string} Description
 */

Resourceloader module example edit

/**
 * Fetch and display a preview of the current editing area.
 *
 * @memberof module:mediawiki.page.preview
 * @param {Object} config Configuration options
 * @param {string} [config.summary=null] The edit summary
 * @return {jQuery.Promise}
 * @fires Hooks~'wikipage.content'
 * @stable
 */
function doPreview( config ) {
    // ...
}

/**
 * Fetch and display a preview of the current editing area.
 *
 * @example
 * var preview = require( 'mediawiki.page.preview' );
 * preview.doPreview();
 *
 * @exports mediawiki.page.preview
 */
module.exports = {
	doPreview: doPreview,
};

Links edit

Learn how to refer to other elements in your code by reading up on namepaths and the @link tag.

You can also use Markdown link syntax or a link enclosed in angle brackets. To link to a Phabricator task, use the task number (for example: T55555).

Reusable links edit

To create a reusable alias for a link or to set up a link for a type, add the link to the linkMap in the JSDoc configuration file:

{
...
  "templates": {
  ...
    "wmf": {
      "linkMap": {
        "mw": "https://doc.wikimedia.org/mediawiki-core/master/js/mw.html",
        "jQuery": "https://api.jquery.com/jQuery",
        "Array": "https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array"
      }
    }
  }
}

Previewing your changes edit

For MediaWiki core, you can generate a preview of the JSDoc site for a given patch using the patch demo tool. To view the JSDoc preview, select the JSDoc documentation link on the main page of the demo wiki.

To test the docs locally, run npm install and npm run doc.

To run the JSDoc WMF theme locally, see the local development instructions in the theme's code repository.

Setting up JSDoc edit

Once you've documented your code using JSDoc tags, follow these steps to build and publish the docs.

1. Configure JSDoc edit

Create a jsdoc.json file in your project's repository to configure JSDoc. If you want to include comments, you can create your JSDoc config as a JavaScript file; see MediaWiki core for an example.

Configuration example edit

{
	"opts": {
		"destination": "docs",
		"pedantic": true,
		"readme": "README.md",
		"recurse": true,
		"template": "node_modules/jsdoc-wmf-theme"
	},
	"plugins": [
		"plugins/markdown",
		"node_modules/jsdoc-wmf-theme/plugins/summarize",
		"node_modules/jsdoc-wmf-theme/plugins/betterlinks"
	],
	"source": {
		"include": [ "resources", "src" ],
		"exclude": [ "resources/libs", "resources/oldfile.js" ]
	},
	"templates": {
		"cleverLinks": true,
		"default": {
			"useLongnameInNav": true
		},
		"wmf": {
			"maintitle": "My Project",
			"repository": "https://gerrit.wikimedia.org/g/MyProject",
			"siteMap": {
				"sections": true
			}
		}
	}
}

Configuration options edit

Option Description
opts.destination Location of the autogenerated JavaScript documentation output. This should be ignored in a .gitignore. If you're using the regular CI jobs for generating and publishing the documentation, this must be docs.
opts.pedantic Treat errors as fatal errors, and treat warnings as errors
opts.readme Homepage content for the JSDoc site
opts.recurse Recurse into subdirectories when scanning for source files and tutorials
opts.template JSDoc theme. For Wikimedia codebases, use node_modules/jsdoc-wmf-theme
plugins Array of plugin names to execute after building the docs, executed in the order they are specified. Theme plugins should be prefixed with node_modules/jsdoc-wmf-theme/plugins/; JSDoc plugins should be prefixed with plugins/. At a minimum, we recommend adding the plugins shown in the example above. For more options, see #Plugins.
source.include Array of paths that JSDoc should parse. You can also use includePattern and a regular expression.
source.exclude Array of paths that JSDoc should ignore. You can also use excludePattern and a regular expression.
templates.cleverLinks Sets link text formatting based on the type of link. Set to true.
templates.default.useLongnameInNav If set to true, the navigation sidebar displays the full name of each item, including ancestors (for example: mw.user.clientPrefs).

If set to false, the navigation displays only the last segment of an item's name (for example: clientPrefs).

templates.wmf.maintitle Title of the site, overrides name from package.json
templates.wmf.repository Link to the project's code repository, overrides repo from package.json
templates.wmf.linkMap Map of #Reusable links
templates.wmf.hideSections Array of sections that will not appear in the sidebar, can include Modules, Externals, Namespaces, Classes, Interfaces, Events, Mixins, and Tutorials
templates.wmf.siteMap Object that adds a sitemap page to the sidebar
templates.wmf.siteMap.sections Set to true to split the sitemap into sections by category (modules, classes, namespaces, etc.), defaults to false
templates.wmf.siteMap.include Array of categories to include in the sitemap, can include modules, externals, namespaces, classes, interfaces, events, mixins, and tutorials. Must be lowercase. Defaults to all categories

Plugins edit

You can enable plugins in the JSDoc configuration file. Here are some useful plugins from JSDoc and from the JSDoc WMF theme:

Plugin Source Description
markdown JSDoc Supports Markdown formatting in descriptions
summarize theme Creates a summary field for each element based on its description
betterlinks theme Supports external links without a @link tag and Phabricator short links
allow-dots-in-modules theme Supports module names that include periods

Plugins are a great way to extend the functionality of JSDoc. You can contribute your own plugins to the theme by adding a file to the plugins directory. For more information about writing plugins, see the JSDoc documentation.

Custom navigation edit

The JSDoc WMF theme allows you to customize the navigation sidebar. This feature can help provide additional context for the docs and help larger projects reduce information overload.

In this example, this project has over 70 classes, so the Classes section in the sidebar is too long to navigate easily. Instead, the project uses the custom navigation feature to:

  • Hide the Classes section from the sidebar, and rely on the list of classes on each namespace page to guide users.
  • Rename the Namespaces section.
  • Add a landing page to the Namespaces section to provide context about each namespace.
  • Limit the Namespaces section to only the top-level namespaces.
{
	"opts": {
		"pages": {
			"namespaces": {
				"longname": "Frontend API",
				"readme": "resources/src/frontend-api.md",
				"depth": 1
			}
		}
	},
	"templates": {
		"wmf": {
			"hideSections": [ "Classes" ]
		}
	}
}
Option Description
opts.pages Object that configures custom navigation. Can include configuration objects for modules, externals, namespaces, classes, interfaces, events, mixins, and tutorials
opts.pages.CATEGORY_NAME.longname Name to use in the sidebar in place of the default name
opts.pages.CATEGORY_NAME.readme Markdown file to use as a category's landing page
opts.pages.CATEGORY_NAME.depth Limits the navigation items shown under a category by the number of elements in each item. For example, mw has a depth of 1; mw.Api has a depth of 2

2. Configure NPM edit

  1. Create a script named doc in your package.json file that runs jsdoc -c jsdoc.json. If you want to include private symbols in the docs, use jsdoc -c jsdoc.json -p. The script should also be invoked as part of test, such as ... && npm -s run doc && ....
  2. Add the latest JSDoc release and jsdoc-wmf-theme release to devDependencies.
  3. Run npm install.

Configuration example edit

{
	...,
	"scripts": {
		...,
		"test": "grunt lint && npm run doc",
		"doc": "jsdoc -c jsdoc.json",
		...,
	},
	"devDependencies": {
		...,
		"jsdoc": "^x.x.x",
		"jsdoc-wmf-theme": "^x.x.x",
		...,
	}
}

3. Preview your changes edit

See #Previewing your changes.

4. Publish on doc.wikimedia.org edit

To add the documentation to https://doc.wikimedia.org:

  1. Create a patch for the repo integration/docroot that adds a section to wikimedia/doc/opensource.yaml (example)
  2. Create a patch for the repo integration/config that enables doc generation and upload for your repository in zuul/layout.yaml. (example)

More details can be found in Continuous integration/Documentation generation.

Troubleshooting edit

Globals edit

Error: Unexpected global detected

The JSDoc WMF theme does not allow global methods, events, or properties outside of the window namespace. For recommended alternatives, see Manual:Coding conventions/JavaScript#Exporting. If the theme detects a global, JSDoc will fail with the error "Unexpected global detected" and list the relevant name and path.

To fix this issue, make sure the global is part of a module, namespace, or class.

Common causes:

  • In an ES5-style class, you may need to add a @memberof tag with the class, namespace, or module name. Modules names should be formatted as module:name.
  • In an ES6-style class, an unnecessary @class annotation can cause this error.
  • If the error relates to a method in an ECMAScript module, see the note under #ES6 example.

References edit

See also edit