I'm Morgan McGuire (@CasualEffects). I've been working on computer graphics and games for 20 years at great places including NVIDIA, Williams College, Brown University, and Activision.

See my home page for a full index of my blog posts, books, research, and projects.

Monday, March 11, 2013

JavaScript Doc Strings



codeheart.js is an open source 2D web and mobile game Javascript framework designed to be extremely easy to learn and use, even for non-programmers. In fact, it intentionally avoids providing many support routines in order to encourage learning to program (this also allows advanced programmers to include or write their own rather than having a structure imposed).  I'm writing a book to help new programmers learn codeheart.js, but also needed an online reference for the 112 API entry points. 

Many libraries and frameworks use generated API documentation. Javadoc and Doxygen are tools that I use regularly to produce documentation, for example, in the C++ G3D Innovation Engine documentation. These take source code as input and produce HTML output describing the API. The programmer can control the form of the output for individual entry points by writing specially formatted comments called doc strings. These include both regular text and (typically, Latex-style) markup.

The codeheart.js documentation:

      http://codeheartjs.com/doc.xml

is generated by a tool that I wrote in Python, called jsdoxml. It reads source files, extracts Doxygen-style "two-star" comments of the form /** ... */, and then outputs an XML file. Combining this with a hand-written XSL style file (e.g. http://codeheartjs.com/doc.xsl) yields the full online documentation.

The doc strings in the JavaScript source look like:

/**                                                                                                        
   <function category="interaction" name="onTouchMove">                                                    
     <description>                                                                                         
       Invoked by moving with the mouse button down or                                                     
       dragging fingers on a touch canvas.                                                                 
     </description>                                                                                        
     <param name="x" type="number" />                                                                
     <param name="y" type="number" />                                                                
     <param name="id" type="integer" />Identifier distinguishing 
            this touch from all others that are currently 
            active</param>
     <see><api>onTouchStart</api>, <api>onTouchEnd</api></see>                                             
   </function>                                                                                             
*/

The Python script itself is below.
#!/usr/bin/env python                                                                                      
# -*- python -*-                                                                                           
#                                                                                                          
# jsdoxml                                                                                                  
#                                                                                                          
# Extracts XML tags from /** */ comments in .js files to                                                   
# the file doc.xml                                                                                         
#                                                                                                          
# Morgan McGuire                                                                                           
#                                                                                                          

import sys, re

outFilename = 'doc.xml'
outStylesheet = 'doc.xsl'

outfile = open(outFilename, 'wt')

outfile.write('<?xml version="1.0" encoding="utf-8" ?>\n')
outfile.write('<?xml-stylesheet type="text/xsl" href="' + outStylesheet + '" ?>\n')
outfile.write('<doc>\n')

# Remove everything except /** */ comments                                                                 
# (using the pattern by Stephen Ostermiller from http://ostermiller.org/findcomment.html)                  
pattern = re.compile('/\*\*(?:.|[\r\n])*?\*/')

total = 0
for filename in sys.argv[1:]:
    print('Processing ' + filename)

    # Read the file                                                                                        
    f = open(filename)
    contents = f.read()
    f.close()

    allComments = re.findall(pattern, contents)

    for comment in allComments:
        # Strip the comment characters and leading and trailing space                                      
        docString = comment[3:-2].strip()

        # See if this begins with an XML tag                                                               
        if (len(docString) > 0) and (docString[0] == '<'):
            total += 1

            # Write the docstring to the file                                                              
            outfile.write(docString)
            outfile.write('\n\n')


outfile.write('</doc>\n')
outfile.close()
print('Wrote ' + str(total) + ' API doc strings to ' + outFilename)




Morgan McGuire is a professor of Computer Science at Williams College and a professional game developer. He is the author of The Graphics Codex, an essential reference for computer graphics that runs on iPhone, iPad, and iPod Touch.