iceddoc
Version:
An API documentation generator for IcedCoffeeScript
176 lines (140 loc) • 5.64 kB
text/coffeescript
###
Renderers
=========
These classes generate output from documentation objects as returned by the
`documentModule` function from the `iceddoc` module.
###
fs = require('fs')
path = require('path')
eco = require('eco')
traverse = require('traverse')
highlight = require('highlight').Highlight
marked = require('marked')
class Renderer
###
Base class for renderers. To create a new renderer, subclass this and
override the necessary properties and methods.
###
indexTemplate: null
moduleTemplate: null
indexFile: 'index'
extension: ''
renderIndex: (modules) =>
eco.render(this.indexTemplate, modules: modules)
renderModule: (module) =>
eco.render(this.moduleTemplate, module)
_createOutputDir: (outputdir) ->
###
Create output directory, recursively deleting it if it already exists.
###
if path.existsSync(outputdir)
rm = (target) ->
if fs.statSync(target).isDirectory()
rm(path.join(target, p)) for p in fs.readdirSync(target)
fs.rmdirSync(target)
else
fs.unlinkSync(target)
rm(outputdir)
fs.mkdirSync(outputdir, '755')
preprocess: (module) ->
###
Apply any preprocessing to module documentation before it is handed off
to the template for rendering.
###
return module
write: (modules, outputdir) =>
###
Render the documentation and generate output for the user. This method
writes the generated index page to `outputdir`, overwriting the
directory if it exists. If `outputdir` is not given, prints the index
page to stdout and exits.
This method does not write the documentation for individual modules.
Subclasses should override `write` and implement this themselves.
###
index = this.renderIndex(modules)
if not outputdir
process.stdout.write(index)
process.exit()
this._createOutputDir(outputdir)
fs.writeFile(path.join(outputdir, this.indexFile + this.extension), index)
render: (modules, outputdir) =>
this.write((this.preprocess(m) for m in modules), outputdir)
class HtmlRenderer extends Renderer
indexTemplate: fs.readFileSync(__dirname + '/../resources/html/index.eco', 'utf-8')
moduleTemplate: fs.readFileSync(__dirname + '/../resources/html/module.eco', 'utf-8')
baseCss: fs.readFileSync(__dirname + '/../resources/html/base.css', 'utf-8')
extension: '.html'
preprocess: (module) =>
###
Convert markdown to html, adding syntax highlighting markup to any code
blocks.
Add the relative path to the resources directory to the documentation
object so that generated pages know where to find css.
###
marked.setOptions(highlight: (code, lang) -> highlight(code))
module = traverse(module).map (value) ->
if value and this.key == 'docstring'
this.update(marked(value))
basepath = path.relative(path.dirname(module.path), process.cwd())
module.resourcepath = path.join(basepath, 'resources/')
return module
write: (modules, outputdir) =>
super(modules, outputdir)
# Recreate source directory structure and write module documentation.
for module in modules
docpath = outputdir
dirs = path.dirname(path.normalize(module.path)).split('/')
for dir in dirs
docpath = path.join(docpath, dir)
if not path.existsSync(docpath)
fs.mkdirSync(docpath, '755')
outfile = path.join(outputdir, module.path + this.extension)
fs.writeFile(outfile, this.renderModule(module))
# Write css resources.
resourcesdir = path.join(outputdir, 'resources')
fs.mkdir resourcesdir, '755', =>
fs.writeFile(path.join(resourcesdir, 'base.css'), this.baseCss)
class GithubWikiRenderer extends Renderer
indexTemplate: fs.readFileSync(__dirname + '/../resources/github-wiki/index.eco', 'utf-8')
moduleTemplate: fs.readFileSync(__dirname + '/../resources/github-wiki/module.eco', 'utf-8')
indexFile: 'ModuleIndex'
extension: '.md'
_wikiize: (path) ->
bits = path.split('/')
bucket = []
for b in bits
if b
bucket.push(b[0].toUpperCase() + b.substring(1))
return bucket.join(':')
_quoteMarkdown: (t) ->
###
It's more than possible that a function name will have underscores...
quote them.
###
return t.replace(/([^\\])?_/g, "$1\\_")
_params: (t) ->
a = []
for x in t
if x?
a.push(x)
else
a.push('{splat}')
return a.join(', ')
preprocess: (module) =>
module.wikiname = this._wikiize(module.path.replace(/\.iced$/, ''))
module.quoteMarkdown = this._quoteMarkdown
module.params = this._params
return module
write: (modules, outputdir) =>
super(modules, outputdir)
for module in modules
outfile = path.join(outputdir, module.wikiname + this.extension)
fs.writeFile(outfile, this.renderModule(module))
class JSONRenderer extends Renderer
extension: '.doc.json'
indexFile: 'index'
renderIndex: JSON.stringify
renderModule: JSON.stringify
exports.html = HtmlRenderer
exports.gfm = GithubWikiRenderer
exports.json = JSONRenderer