'use strict';Dokker.js 0.0.1
http://dokker.oceanhouse21.com
(c) 2014-2015 Georg Schlenkhoff and Oceanhouse21
Dokker.js may be freely distributed under the MIT license.
'use strict';Define required dependencies
var Promise = require('promise');
var fs = require('fs');
var path = require('path');
var read = Promise.denodeify(fs.readFile);
var write = Promise.denodeify(fs.writeFile);
var docco = require('docco');
var docdown = require('docdown');
var marked = require('marked');
var ejs = require('ejs');
var cheerio = require('cheerio');
var exec = require('child_process').exec;
var Dokker = {};
Dokker.VERSION = '0.1.2';Transclude in a ejs template file the HTML snippet that was ultimately created with docdown. Also tweak the HTML page a bit and finally inject the README.md.
Dokker.injectTemplate = function(options) {
return new Promise(function(resolve, reject) {
var template, body, html, readme, $;
return read(options.template, 'utf8')
.then(function(data) {
template = data;
return read(options.readme, 'utf8');
}).then(function(data) {
readme = marked(data);
$ = cheerio.load(readme);
$('h1').remove();
readme = $.html();
return read(options.html, 'utf8');
}).then(function(data) {
$ = cheerio.load(data);
return ejs.render(template, {
apiToc: $('.toc-container').html(),
readme: readme,
apiDoc: $('.doc-container').html(),correctly setting links to your github/pages
page_url: options.site,
title: options.title,
github_url: options.github,fixed reference to generated annotation the ‘literate’ in .dokker.json shall not require a source since it’s never used.
annotated_path: 'annotated/'+options.source
});
}).then(function(data) {
return write(options.html, data, 'utf8');
}).then(function() {
resolve();
}).then(null, function(err) {
reject(err);
});
});
};Create a HTML site from any mocha tests find when executing mocha —reporter doc terminal command.
Dokker.createTests = function(options) {
return new Promise(function(resolve, reject) {
var template, tests;allows specification of mocha.command in .dokker.json, e.g. ‘mocha -u tdd —reporter doc’
var cmd = options.command || 'mocha --reporter doc';
exec(cmd, {cwd: process.cwd()}, function(error, stdout) {
if(error) return reject(error);
tests = stdout;
return read(options.template, 'utf8')
.then(function(data) {
template = data;
return ejs.render(template, {tests: tests});
}).then(function(data) {
return write(options.path, data, 'utf8');
}).then(function() {
resolve();
}).then(null, function(err) {
reject(err);
});
});
});
};Extract docs folder to separate git branch and finally push branch to Github repository
Dokker.ghPages = function(){
return new Promise(function(resolve, reject) {
exec('git subtree split -P docs -b gh-pages', function(error, stdout, stderr) {
if(error) return reject(stderr);
exec('git push origin gh-pages', function(error, stdout, stderr) {
if(error) return reject(stderr);
resolve();
});
});
});
};Create an HTML file from any source code comments in the style of literate programming
Dokker.literate = function (options) {
return new Promise(function(resolve, reject) {
var tmpDir = path.join(process.cwd(), '/.tmp');
var tmpFile = path.join(tmpDir, options.source);
var sourceFile = (options.cwd) ?
path.join(process.cwd(), options.cwd, options.source) :
path.join(process.cwd(), options.source);
return read(sourceFile, 'utf8')
.then(function(data) {
var source = data.replace(/^\s*(\*|\/\*).*[\r\n]/gm, '');
return Dokker.mkdir(tmpDir)
.then(function() {
return write(tmpFile, source, 'utf8');
}).then(function(){
docco.run(['', '', tmpFile, '-o', options.dir]);
resolve();
});
}).then(null, function(err) {
if (err) return reject(err);
});
});
};Convert markdown from any source code comments with docdown module.
Dokker.jsdocMarkdown = function (options) {
return new Promise(function(resolve, reject) {
var source, tmpFile, tmpDir;
var sourceFile = (options.cwd) ?
path.join(process.cwd(), options.cwd, options.source) :
path.join(process.cwd(), options.source);
return read(sourceFile, 'utf8')
.then(function(data){
source = data.replace(/^\s*(\/\/).*[\r\n]/gm, '');
tmpDir = path.join(process.cwd(), '/.tmp');
return Dokker.mkdir(tmpDir);
}).then(function(){
tmpFile = path.join(tmpDir, options.source);
return write(tmpFile, source, 'utf8');
}).then(function(){
var markdown = docdown({
'path': tmpFile,
'url': options.github,
'toc': 'categories'
});
return write(options.markdown, markdown, 'utf8');
}).then(function() {
resolve();
}).then(null, function(err) {
reject(err);
});
});
};Create an HTML file from any source code comments in the style of literate programming
Dokker.jsdocHtml = function (options) {
return new Promise(function(resolve, reject) {
return read(options.markdown, 'utf8')
.then(function(data) {
var html = marked(data).replace(/<!-- /g,'<').replace(/ -->/g,'>');
return write(options.html, html, 'utf8');
}).then(function() {
resolve();
}).then(null, function(err) {
reject(err);
});
});
};Internal helper function that creates any directory if not existing.
Dokker.mkdir = function(dir) {
return new Promise(function(resolve, reject) {
fs.exists(dir, function(exists) {
if (exists) {
resolve();
} else {
fs.mkdir(dir, function(err) {
if (err) return reject(err);
resolve();
});
}
});
});
};Parses the options file, .Dokker.json, and sets the default parameters.
Dokker.configure = function(options) {
return new Promise(function(resolve, reject){
var file = path.join(process.cwd(), '.dokker.json');
return read(file, 'utf8')
.then(function(data) {
data = JSON.parse(data);
data.jsdoc.template = (data.jsdoc.template) ? path.join(process.cwd(), data.jsdoc.template) : path.join(__dirname, 'templates/index.ejs.html');
data.mocha.template = (data.mocha.template) ? path.join(process.cwd(), data.mocha.template) : path.join(__dirname, 'templates/tests.ejs.html');
data.mocha.path = path.join(process.cwd(), data.dir, data.mocha.path);mocha.command commented out to fix build-breaking bug specifies mocha command in .dokker.json; e.g. mocha -u tdd -R spec data.mocha.command = path.join(process.cwd(), data.dir, data.mocha.command);
data.literate.dir = path.join(process.cwd(), data.dir, data.literate.dir);
data.jsdoc.markdown = path.join(process.cwd(), data.dir, data.jsdoc.markdown);
data.jsdoc.html = path.join(process.cwd(), data.dir, data.jsdoc.html);
data.jsdoc.readme = path.join(process.cwd(), data.jsdoc.readme);
resolve(data);
}).then(null, function(err) {
reject(err);
});
});
};Copy starter template to bootstrap any Dokker project.
Dokker.copyTemplate = function(options) {
return new Promise(function(resolve, reject) {
var templatesDir = path.join(process.cwd(), 'templates');
return Dokker.mkdir(templatesDir)
.then(function() {
var oldStyle = path.join(__dirname, 'templates', 'styles.css');
var newStyle = path.join(process.cwd(), options.dir, 'styles.css');
fs.createReadStream(oldStyle).pipe(fs.createWriteStream(newStyle));
var oldLogo = path.join(__dirname, 'templates', 'logo.png');
var newLogo = path.join(process.cwd(), options.dir, 'logo.png');
fs.createReadStream(oldLogo).pipe(fs.createWriteStream(newLogo));
var oldApp = path.join(__dirname, 'templates', 'app.js');
var newApp = path.join(process.cwd(), options.dir, 'app.js');
fs.createReadStream(oldApp).pipe(fs.createWriteStream(newApp));
resolve();
});
});
};Copies the .Dokker.json file to bootstrap any Dokker project.
Dokker.init = function(){
return new Promise(function(resolve, reject) {
var oldDok = path.join(__dirname, '.dokker.json');
var newDok = path.join(process.cwd(), '.dokker.json');
fs.createReadStream(oldDok).pipe(fs.createWriteStream(newDok));
resolve();
});
};Starts the Node.js/Express server to watch Dokker.js project documentation.
Dokker.watch = function(options) {
var gulpex = require(__dirname + '/gulpfile.js').gulpex;
return gulpex();return new Promise(function(resolve, reject){ exec(‘DIR=’+ options.dir + ‘ node ‘ + options.dir + ‘/app.js’, function(error, stdout, stderr){ if(error) return reject(stderr); }); });
};
module.exports = Dokker;
Dokker.js creates professional Javascript code documentations.
See Dokker.js documentation as example.
Dokker is available as npm package. So the easiest way is to install dokker as global module into your project:
npm install -g dokker
After installation you can execute Dokker with the help of several terminal commands.
Bootstrap Dokker project
Dokker needs a configuration file to execute, such as a .travis or .jshintrc. You can easily create .dokker.json file with the dokker-init command from the root directory of your project or copy an example file.
Dokker provides a default template for your project. The template is based on an ejs file. Either you use the default template or modify it. If you choose for the latter you can copy the templates directory and tweak the ejs files how you like.
Create documentation
Creating a documentation is really simple with the help of Dokker. You just configure the .dokker.json file and execute dokker. Then you’re done.
Live edit your documentation
If you want to work on your source file and see how the documentation evolves, you can do dokker-watch and it will open a browser with live preview.
Deploy to Github Pages
If you want to deploy your documentation to Github Pages, run gh-pages. Finally a separate branch, named gh-pages is created from the docs folder. That is enough for Github to serve your documentation. Please do not forget to git commit your changes before your run gh-pages command.
Some examples by our users. Let us know what you did with Dokker too!
“Github Pages” MethodsDokker.ghPages()Runs a terminal shell with the git command to extract the docs branch into a seperate gh-pages branch and finally pushes that branch to Github, so that the Github page is updated.
(Promise): Returns a resolved promise if file was created.
Dokker.ghPages()
.then(function(){
// => resolved promise
});
“JSDoc” MethodsDokker.injectTemplate([options])Creates a HTML file that transcludes the HTML snippet that was created by the docdown module into an ejs template which is defined by the .dokker.json configuration file.
[options] (Object): The options object.[options.template='template/index.ejs.html'] (String): The path to the ejs template file.[options.html='docs/index.html'] (string): The path to the docdown generated JSDoc documentation.[options.readme='README.md'] (string): The path to the README.md file.[options.title=''] (string): The title for the documentation.(Promise): Returns a resolved promise if file was created.
var options = {
template: 'template/index.ejs.html',
html: 'docs/index.html',
readme: 'docs/README.md',
title: 'Dokker.js API Documentation'
};
Dokker.injectTemplate(options)
.then(function(){
// => resolved promise
});
Dokker.jsdocHtml([options])Create an HTML file from the Markdown file that was create with Dokker.jsdocMarkdown()
[options] (Object): The options object.[options.markdown='docs/READMDE.md'] (string): The path where to save the Markdown file.(Promise): Returns a resolved promise if file was created.
var options = {
markdown: 'docs/README.md'
};
Dokker.jsdocHtml()
.then(function(){
// => resolved promise
});
Dokker.jsdocMarkdown([options])Create a Markdown file from JSDoc tags.
[options] (Object): The options object.[options.source='app.js'] (String): The path the source code with JSDoc tags.[options.github =''] (String): The path the Github repository.[options.markdown='docs/READMDE.md'] (string): The path where to save the Markdown file.(Promise): Returns a resolved promise if file was created.
var options = {
source: 'app.js',
markdown: 'docs/README.md'
};
Dokker.jsdocMarkdown()
.then(function(){
// => resolved promise
});
“Literate programming” MethodsDokker.literate([options])Create a styled HTML file from your source code with the help of docco module.
[options] (Object): The options object.[options.source='app.js'] (String): The path the source code with comments[options.dir='docs/annotated'] (string): The directory where to save the generated HTML file.(Promise): Returns a resolved promise if file was created.
var options = {
dir: 'docs',
source: 'app.js'
};
Dokker.literate()
.then(function(){
// => resolved promise
});
“Mocha” MethodsDokker.createTests([options])Creates an HTML file to describe the features of your module from your Mocha tests. The module is using the mocha doc reporter to generate the HTML contents.
[options] (Object): The options object.[options.path='docs.html'] (String): The path where to save the HTML file(Promise): Returns a resolved promise if file was created.
var options = {
path: 'docs/tests.html',
};
Dokker.createTests(options)
.then(function(){
// => resolved promise
});
“Utility” MethodsDokker.configure([options])Helper function that takes a couple of options arguments and normalises them and subsequently returns them.
[options] (Object): The options object.[options.li.markdown='docs/READMDE.md'] (string): The path where to[options.source='app.js'] (String): The path the source code with JSDoc tags.[options.jsdoc.markdown='docs/READMDE.md'] (string): The path where to save the Markdown file.[options.jsdoc.README ='READMDE.md'] (string): The path to the project’s README.md file[options.jsodc.template ='templates/index.ejs.html'] (String): The path to the ejs template.[options.mocha.template='templates/tests.ejs.html'] (String): The path to the mocha template.[options.dir='docs'] (String): The path where to store the generated files(Promise): Returns a resolved promise with edited options object
var options = {
dir: 'docs',
literate: {
source: 'dokker.js',
dir: 'annotated'
},
jsdoc: {
title: 'Dokker.js',
source: 'dokker.js',
markdown: 'README.md',
html: 'index.html',
readme: 'README.md',
}
};
Dokker.jsdocHtml()
.then(function(){
// => object with absolute pathes to the directory from
// which the command was executed
});
Dokker.copyTemplate([options])Copy the template to local directory so that one can make changes to ejs files.
[options] (Object): The options object.[options.dir='templates'] (string): The path where to save the template files(Promise): Returns a resolved promise if files were created.
var options = {
dir: 'template'
};
Dokker.copyTemplate()
.then(function(){
// => resolved promise
});
Methodsreturn Dokker.literate(options.literate)
.then(function(){
done();
}).done();return Dokker.jsdocMarkdown(options.jsdoc)
.then(function(){
return read(options.jsdoc.markdown);
}).then(function(){
done();
}).done();return Dokker.jsdocHtml(options.jsdoc)
.then(function(){
return read(options.jsdoc.html);
}).then(function(){
done();
}).done();return Dokker.injectTemplate(options.jsdoc)
.then(function() {
return read(options.jsdoc.html, 'utf8');
}).then(function(data){
assert(/<!DOCTYPE html>/.test(data));
done();
}).done();return Dokker.copyTemplate(options)
.then(function(){
return read(path.join(__dirname, '..', options.dir, 'styles.css'));
}).then(function(data){
assert(data);
done();
}).done();><%= title %>