The concept of combining code with explanations is also known as Literate Programming. The idea here is that you write your program for human consumption first and for a computer second and generate both variants from a single source file. Writing down a good explanation makes your program better internally and it gives others a way to understand the thought process behind your code when they want to reuse it.

I have used a combination of CoffeeScript and Docco for a detailed explanation of stable zooming and panning in Paper.js. That blog post, including live code to illustrate the algorithms, was created almost 100% from the CoffeeScript source file.

Some advantages of the approach I used there are:

  • The CoffeeScript file is well documented
  • The blog post is generated directly from the CoffeeScript source so code and explanations are always in sync.
  • The blog post contains live code examples so you see commented code and the resulting behavior in the same document
  • Mathematical notation can be used in the blog post and it is still readable in the source (if you understand LaTeX syntax, that is)

To show you how it all works I have created a minimal example that is described here.

A minimal example

The minimal example produces a simple animation with Paper.js. The CoffeeScript input is here. You can see the animation and explanations in the generated HTML file.

CoffeeScript for the program

CoffeeScript is a pretty nice programming language that gets translated into clean and correct JavaScript. Here is an example function position(alpha, radius) that describes motion on a circle: it takes the angle alpha and the radius and produces the coordinates x and y from it:

position = (alpha, radius) ->
  [radius * Math.cos(alpha), radius * Math.sin(alpha)]

CoffeeScript uses indentation to define blocks, the last statement’s value is returned from a function.

Docco for generating HTML from source

Docco generates documentation from CoffeeScript source, Literate Programming style. That means every line of your source code is shown in the resulting HTML document along with code comments that are typeset nicely (including itemized lists, headings etc.). Code comments use Markdown syntax, a simple text markup whose source format is very readable.

Here is our function with comments added:

# Motion on a circle
# ------------------

# We want to rotate graphical objects at varying speeds to produce
# interesting visual effects.

# Compute a point's position from its angle alpha and radius.
position = (alpha, radius) ->
  [radius * Math.cos(alpha), radius * Math.sin(alpha)]

Running Docco on the CoffeeScript source file demo_01.coffee produces a HTML file.

$ docco --layout linear demo_01.coffee
docco: demo_01.coffee -> docs/demo_01.html

The result is a nice document with headings, explanatory text and the source.

Docco generated HTML screenshot

The --layout linear switch places the comments and source below each other, as opposed to Docco’s default side-by-side layout.

MathJax for displaying formulae

MathJax detects formulae written in LaTeX and lays them out in a HTML page. We add two script tags at the beginning of the source file. The first line loads MathJax, the second line configures MathJax to recognize text between dollar signs as formulae. Docco will pass these lines through to the final HTML document.

Now we can use mathematical notation in the comments. The double dollar sign produces a “display formula” that is placed on a separate line.

#<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
#<script type="text/x-mathjax-config">MathJax.Hub.Config({ tex2jax: {inlineMath: [['$','$'], ['\\(','\\)']]}});</script>


# Motion on a circle
# ------------------

# We want to rotate graphical objects at varying speeds to produce
# interesting visual effects.

# Compute a point's position from its angle $\alpha$ and radius $r$ according to
# $$(x,y) = r \, (\sin \alpha, \cos \alpha)$$
position = (alpha, radius) ->
  [radius * Math.cos(alpha), radius * Math.sin(alpha)]

Docco HTML screenshot with math

Paper.js for graphics

Now we want to show the animation in the browser side by side with the code. First we create a HTML canvas element right in the CoffeeScript source (demo_03.coffee).

# <canvas id="paper1" width="400" height="200" style="background: lightgray;"></canvas>

Again, Docco leaves HTML markup unchanged. The canvas element gets an ID so we can access it later.

Then add a script that executes the CoffeeScript source. Here we use RequireJS to load dependencies (so far only Paper.js) in a modular way.

# <script data-main="../scripts/demo_main" src="../../bower_components/requirejs/require.js"></script>

The main script in demo_main.coffee configures the dependencies and then loads demo_03.coffee as a RequireJS module:

require.config({
  paths: {
    'paper': '../../bower_components/paper/dist/paper'
  }
})

require ['demo_03'], (example) ->
  example('paper1')

Behind the scenes, demo_03.coffee is translated to a JavaScript file that is placed in a directory where it is accessible to RequireJS. All this is handled by Grunt, see the github repository.

Bonus: live reload

Instead of running Docco on the demo_03.coffee file after every edit, we can use Grunt and LiveReload. That combination executes essentially the command

docco --layout linear --output app/docs app/scripts/demo_03.coffee

after every change to the file. With LiveReload, the changed HTML file will be automatically reloaded in the browser. The whole process is kicked off by running

grunt serve

The generated document is served at 127.0.0.1:9000/docs/demo_03.html.

The essential sections in the Gruntfile.js are:

// Watches files for changes and runs tasks based on the changed files
watch: {
    coffee: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.{coffee,litcoffee,coffee.md}'],
        tasks: ['coffee:dist']
    }
    // ...
    livereload: {
        options: {
            livereload: '<%= connect.options.livereload %>'
        },
        files: [
            '<%= yeoman.app %>/{,*/}*.html',
            '.tmp/styles/{,*/}*.css',
            '.tmp/scripts/{,*/}*.js',
            '<%= yeoman.app %>/images/{,*/}*.{gif,jpeg,jpg,png,svg,webp}'
        ]
    },
    docco: {
        files: ['<%= yeoman.app %>/scripts/{,*/}*.{coffee,litcoffee,coffee.md}'],
        tasks: ['docco']
    }
}

And another section to configure docco to use linear layout.

docco: {
            debug: {
                src: ['<%= yeoman.app %>/scripts/{,*/}*.{coffee,litcoffee,coffee.md}'],
                options: {
                    output: '<%= yeoman.app %>/docs',
                    layout: 'linear'
                }
            }
        }

Summary

There you have it: one CoffeeScript file to produce documentation with embedded code and live running examples. To minimize friction it is all reloaded automatically whenever you change the CoffeeScript file.