Documentation

To keep the codebase and documentation in sync, we keep the documentation in 2 places:

  1. Inside the docs folder.
  2. Inside the code.

Documentation System

We use Sphinx to generate the project’s documentation. Documentation building and hosting is provided by Read the Docs.

Generating Documentations Locally

Install Sphinx using:

pip install sphinx

Inside the docs folder, type in:

make html

This will generate the HTML documentations in _build/html.

Writing Documentation Pages

To create a new documentation page, create an .rst file in the appropriate place, and then reference the .rst file inside README.rst‘s toctree.

Writing Documentation In Code

This project is written in ES6, and we don’t have an adequate documentation tool yet. Some tools don’t work with ES6 syntax, or some tools requires us to be too verbose and repetitive (making documentation a boring and error-prone process).

Therefore, this project invents its own code documentation tool which integrates nicely with Sphinx.

Source code files that matches the pattern src/**/.js or docs/**/*.py will be processed to find documentation comments.

To write a block of documentation inside code (called codedoc), start a block of inline comment with >> name:

// >> game/input
// Documentation text goes here.

To include that codedoc, use the codedoc directive:

.. codedoc:: game/input

The previous codedoc can be added later by starting a block of inline comment with >>:

// >> game/input
// Some documentation...

... /* code */ ...

// >>
// Some more documentation...

Automatically-Generated Module Documentation

To facilitate documenting the game internals, documentation for each ES6 module is generated.

If a block of inline comment starts with :doc:, then the comment will be added into the module’s documentation.

If a method definition syntax is found directly after a block of comment, then it will be used for documenting that method:

// Reports the progress.
report(current, total, extra) {

If a getter definition syntax or an assignment to this is found after a comment block, then the comment block documents that attribute:

constructor() {
  // ``true`` if the game is started, ``false`` otherwise.
  this.started = false
}

// The song duration in seconds.
get duration() {

If export let is found after a comment block, then the comment block documents that module export:

// The global SceneManager instance.
export let instance = new SceneManager()

If export function is found after a comment block, then the comment block documents that module export:

// The global SceneManager instance.
export function download() {

How It Works

I think from the outside, this system looks pretty cool, but from the inside, this is a dirty hack.

The code documentation and module documentations are generated by a Python script, generate.py, which scans the source files for comment blocks followed by the code that matches the regular expression.

This is simple and works very well, but the code must be written according to the coding convention.