Skip to content

Commit

Permalink
Add support for running Docco via an exported public API:
Browse files Browse the repository at this point in the history
 - run(args=process.argv) : Run Docco from the command line
 - document(sources,options,callback) : Run Docco over a list of source wildcard matches, with the specified options, with an optional completion callback
 - resolve_source(source) : Useful utility for resolving a source input (supports wildcards) to a list of matched files.

 Add Docco configurable options:
 - use commander.js for command line option parsing, and usage output generation.  (Tried to borrow CoffeeScript optparser, but it's not exposed.)
 - add options for specifying what jst template to use, which css file to copy, and what output folder to use.

Misc
 - Update docco binary to invoke Docco.run() rather than just requiring the library.

Add command line coffee file (second file, drats!):
In order to be able to use docco outside of a direct command line invocation, the main Docco file cannot automatically process the argv and run.  It needed to export an API that can be used to run it from the command line, as well as directly from within another application.  The good news is that this second file is really just for convenience for developers running Docco directly.  e.g. "coffee src/cmd -t myproj/custom_template.jst src/*.coffee")
  • Loading branch information
justindujardin committed Mar 14, 2012
1 parent 9ea1a35 commit 608870d
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 64 deletions.
4 changes: 1 addition & 3 deletions bin/docco
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@
var path = require('path');
var fs = require('fs');
var lib = path.join(path.dirname(fs.realpathSync(__filename)), '../lib');

process.ARGV = process.argv = process.argv.slice(2, process.argv.length);
require(lib + '/docco.js');
require(lib + '/docco.js').run();
5 changes: 5 additions & 0 deletions lib/cmd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
(function() {

(new require('./docco')).run();

}).call(this);
97 changes: 72 additions & 25 deletions lib/docco.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/cmd.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# A simple coffee file to enable direct invocation of docco.coffee,
# now that the file is not runnable.
(new require './docco').run()
121 changes: 85 additions & 36 deletions src/docco.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@
# Generate the documentation for a source file by reading it in, splitting it
# up into comment/code sections, highlighting them for the appropriate language,
# and merging them into an HTML template.
generate_documentation = (source, callback) ->
generate_documentation = (source, config, callback) ->
fs.readFile source, "utf-8", (error, code) ->
throw error if error
sections = parse source, code
highlight source, sections, ->
generate_html source, sections
generate_html source, sections, config
callback()

# Given a string of source code, parse out each comment and the code that
Expand Down Expand Up @@ -132,11 +132,20 @@ highlight = (source, sections, callback) ->
# Once all of the code is finished highlighting, we can generate the HTML file
# and write out the documentation. Pass the completed sections into the template
# found in `resources/docco.jst`
generate_html = (source, sections) ->
generate_html = (source, sections, config) ->
# Compute the destination HTML path for an input source file path. If the source
# is `lib/example.coffee`, the HTML will be at `[config.output]/example.html`
destination = (filepath) ->
path.join(config.output, path.basename(filepath, path.extname(filepath)) + '.html')

title = path.basename source
dest = destination source
html = docco_template {
title: title, sections: sections, sources: options.args, path: path, destination: destination
html = config.docco_template {
title : title,
sections : sections,
sources : config.sources,
path : path,
destination: destination
}
console.log "docco: #{source} -> #{dest}"
fs.writeFile dest, html
Expand All @@ -149,7 +158,7 @@ fs = require 'fs'
path = require 'path'
showdown = require('showdown').Showdown
{spawn, exec} = require 'child_process'
options = require 'commander'
commander = require 'commander'

# A list of the languages that Docco supports, mapping the file extension to
# the name of the Pygments lexer and the symbol that indicates a comment. To
Expand Down Expand Up @@ -194,11 +203,6 @@ for ext, l of languages
# Get the current language we're documenting, based on the extension.
get_language = (source) -> languages[path.extname(source)]

# Compute the destination HTML path for an input source file path. If the source
# is `lib/example.coffee`, the HTML will be at `[output_path]/example.html`
destination = (filepath) ->
options.output + path.basename(filepath, path.extname(filepath)) + '.html'

# Ensure that the destination directory exists.
ensure_directory = (dir, callback) ->
exec "mkdir -p #{dir}", -> callback()
Expand All @@ -220,38 +224,83 @@ template = (str) ->

# Extract the docco version from `package.json`
version = JSON.parse(fs.readFileSync("#{__dirname}/../package.json")).version

# Configure [Commander JS](https://github.com/visionmedia/commander.js) options
# to parse out of the command line.
options.version(version)
.usage("[options] <file_pattern ...>")
.option("-t, --template [file]","use a custom .jst template","#{__dirname}/../resources/docco.jst")
.option("-c, --css [file]","use a custom css file","#{__dirname}/../resources/docco.css")
.option("-o, --output [path]","use a custom output path (defaults to 'docs/')","docs/")
.parse(process.argv)
.name = "docco"

# Create the template that we will use to generate the Docco HTML page.
docco_template = template fs.readFileSync(options.template).toString()

# The CSS styles we'd like to apply to the documentation.
docco_styles = fs.readFileSync(options.css).toString()
# Default configuration options.
DEFAULTS =
template: "#{__dirname}/../resources/docco.jst"
css : "#{__dirname}/../resources/docco.css"
output : "docs/"

# The start of each Pygments highlight block.
highlight_start = '<div class="highlight"><pre>'

# The end of each Pygments highlight block.
highlight_end = '</pre></div>'

# Run the script.
# For each source file passed in as an argument, generate the documentation.
# If no sources are specified, print the usage help and exit.
if options.args.length
ensure_directory options.output, ->
fs.writeFile "#{options.output}docco.css", docco_styles
files = options.args.slice(0)
next_file = -> generate_documentation files.shift(), next_file if files.length
#### Public API

# Resolve a wildcard source input to the files it matches.
# Return an array of matched files, or `source` if it does
# not contain any wildcards.
exports.resolve_source = (source) ->
# If it is not a wildcard, just return the input.
return source if not source.match(/([\*\?])/)

# Convert the wildcard match to a regular expression.
match_path = path.dirname(source)
match_string = path.basename(source)
.replace(/\./g, "\\$&")
.replace(/\*/,".*")
.replace(/\?/,".")
match_regex = new RegExp('(' + match_string + ')')

# Look for files in the match path, and return the ones
# that match the regex.
match_files = fs.readdirSync match_path
return (path.join(match_path,file) for file in match_files when file.match match_regex)

# Run Docco from a set of command line arguments, defaulting to `process.argv`.
exports.run = (args=process.argv) ->
# Parse command line options using [Commander JS](https://github.com/visionmedia/commander.js).
commander.version(version)
.usage("[options] <file_pattern ...>")
.option("-t, --template [file]","use a custom .jst template",DEFAULTS.template)
.option("-c, --css [file]","use a custom css file",DEFAULTS.css)
.option("-o, --output [path]","use a custom output path (defaults to 'docs/')",DEFAULTS.output)
.parse(args)
.name = "docco"

# Generate the documentation for provided source arguments.
# If no sources are specified, print the usage help and exit.
if commander.args.length
exports.document(commander.args.slice(),commander)
else
console.log commander.helpInformation()

# Run Docco with overs `sources` with the given `options`
exports.document = (sources,options,callback) ->
# Construct the Docco config to use with this documentation pass
# by taking the `DEFAULTS` first, then merging in specified options
# from the passed `config` object.
config = {}
config[key] = DEFAULTS[key] for key,value of DEFAULTS
config[key] = value for key,value of options if key of DEFAULTS
config.sources = []
config.sources = config.sources.concat(exports.resolve_source(src)) for src in sources

# Create the template that we will use to generate the Docco HTML page.
config.docco_template = template fs.readFileSync(config.template).toString()

# The CSS styles we'd like to apply to the documentation.
docco_styles = fs.readFileSync(config.css).toString()

# Run the script.
# For each source file passed in, generate the documentation.
ensure_directory config.output, ->
fs.writeFile path.join(config.output,path.basename(config.css)), docco_styles
files = config.sources.slice()
next_file = ->
callback() if callback? and not files.length
generate_documentation files.shift(), config, next_file if files.length
next_file()
else
console.log options.helpInformation()

0 comments on commit 608870d

Please sign in to comment.