38 | 'use strict';
Dokker.js 0.0.1
31 | http://dokker.oceanhouse21.com
32 | (c) 2014-2015 Georg Schlenkhoff and Oceanhouse21
33 | Dokker.js may be freely distributed under the MIT license.
34 |
35 |
38 | 'use strict';
Define required dependencies
50 | 51 |var Promise = require('promise');
54 | var fs = require('fs');
55 | var path = require('path');
56 | var read = Promise.denodeify(fs.readFile);
57 | var write = Promise.denodeify(fs.writeFile);
58 | var docco = require('docco');
59 | var docdown = require('docdown');
60 | var marked = require('marked');
61 | var ejs = require('ejs');
62 | var cheerio = require('cheerio');
63 | var exec = require('child_process').exec;
64 | var Dokker = {};
65 | Dokker.VERSION = '0.1.2';
Transclude in a ejs template file the HTML snippet that was ultimately 77 | created with docdown. Also tweak the HTML page a bit and finally 78 | inject the README.md.
79 | 80 |Dokker.injectTemplate = function(options) {
83 | return new Promise(function(resolve, reject) {
84 | var template, body, html, readme, $;
85 | return read(options.template, 'utf8')
86 | .then(function(data) {
87 | template = data;
88 | return read(options.readme, 'utf8');
89 | }).then(function(data) {
90 | readme = marked(data);
91 | $ = cheerio.load(readme);
92 | $('h1').remove();
93 | readme = $.html();
94 | return read(options.html, 'utf8');
95 | }).then(function(data) {
96 | $ = cheerio.load(data);
97 | return ejs.render(template, {
98 | apiToc: $('.toc-container').html(),
99 | readme: readme,
100 | apiDoc: $('.doc-container').html(),
correctly setting links to your github/pages
112 | 113 | page_url: options.site,
116 | title: options.title,
117 | github_url: options.github,
fixed reference to generated annotation 129 | the ‘literate’ in .dokker.json shall not require a source since it’s never used.
130 | 131 | annotated_path: 'annotated/'+options.source
134 | });
135 | }).then(function(data) {
136 | return write(options.html, data, 'utf8');
137 | }).then(function() {
138 | resolve();
139 | }).then(null, function(err) {
140 | reject(err);
141 | });
142 | });
143 | };
Create a HTML site from any mocha tests find when executing mocha 155 | —reporter doc terminal command.
156 | 157 |Dokker.createTests = function(options) {
160 | return new Promise(function(resolve, reject) {
161 | var template, tests;
allows specification of mocha.command in .dokker.json, e.g. ‘mocha -u tdd —reporter doc’
173 | 174 | var cmd = options.command || 'mocha --reporter doc';
177 | exec(cmd, {cwd: process.cwd()}, function(error, stdout) {
178 | if(error) return reject(error);
179 | tests = stdout;
180 | return read(options.template, 'utf8')
181 | .then(function(data) {
182 | template = data;
183 | return ejs.render(template, {tests: tests});
184 | }).then(function(data) {
185 | return write(options.path, data, 'utf8');
186 | }).then(function() {
187 | resolve();
188 | }).then(null, function(err) {
189 | reject(err);
190 | });
191 | });
192 | });
193 | };
Extract docs folder to separate git branch and finally push branch to 205 | Github repository
206 | 207 |Dokker.ghPages = function(){
210 | return new Promise(function(resolve, reject) {
211 | exec('git subtree split -P docs -b gh-pages', function(error, stdout, stderr) {
212 | if(error) return reject(stderr);
213 | exec('git push origin gh-pages', function(error, stdout, stderr) {
214 | if(error) return reject(stderr);
215 | resolve();
216 | });
217 | });
218 | });
219 | };
Create an HTML file from any source code comments in the style of 231 | literate programming
232 | 233 |Dokker.literate = function (options) {
236 | return new Promise(function(resolve, reject) {
237 | var tmpDir = path.join(process.cwd(), '/.tmp');
238 | var tmpFile = path.join(tmpDir, options.source);
239 | var sourceFile = (options.cwd) ?
240 | path.join(process.cwd(), options.cwd, options.source) :
241 | path.join(process.cwd(), options.source);
242 | return read(sourceFile, 'utf8')
243 | .then(function(data) {
244 | var source = data.replace(/^\s*(\*|\/\*).*[\r\n]/gm, '');
245 | return Dokker.mkdir(tmpDir)
246 | .then(function() {
247 | return write(tmpFile, source, 'utf8');
248 | }).then(function(){
249 | docco.run(['', '', tmpFile, '-o', options.dir]);
250 | resolve();
251 | });
252 | }).then(null, function(err) {
253 | if (err) return reject(err);
254 | });
255 | });
256 | };
Convert markdown from any source code comments with docdown module.
268 | 269 |Dokker.jsdocMarkdown = function (options) {
272 | return new Promise(function(resolve, reject) {
273 | var source, tmpFile, tmpDir;
274 | var sourceFile = (options.cwd) ?
275 | path.join(process.cwd(), options.cwd, options.source) :
276 | path.join(process.cwd(), options.source);
277 | return read(sourceFile, 'utf8')
278 | .then(function(data){
279 | source = data.replace(/^\s*(\/\/).*[\r\n]/gm, '');
280 | tmpDir = path.join(process.cwd(), '/.tmp');
281 | return Dokker.mkdir(tmpDir);
282 | }).then(function(){
283 | tmpFile = path.join(tmpDir, options.source);
284 | return write(tmpFile, source, 'utf8');
285 | }).then(function(){
286 | var markdown = docdown({
287 | 'path': tmpFile,
288 | 'url': options.github,
289 | 'toc': 'categories'
290 | });
291 | return write(options.markdown, markdown, 'utf8');
292 | }).then(function() {
293 | resolve();
294 | }).then(null, function(err) {
295 | reject(err);
296 | });
297 | });
298 | };
Create an HTML file from any source code comments in the style of 310 | literate programming
311 | 312 |Dokker.jsdocHtml = function (options) {
315 | return new Promise(function(resolve, reject) {
316 | return read(options.markdown, 'utf8')
317 | .then(function(data) {
318 | var html = marked(data).replace(/<!-- /g,'<').replace(/ -->/g,'>');
319 | return write(options.html, html, 'utf8');
320 | }).then(function() {
321 | resolve();
322 | }).then(null, function(err) {
323 | reject(err);
324 | });
325 | });
326 | };
Internal helper function that creates any directory if not existing.
338 | 339 |Dokker.mkdir = function(dir) {
342 | return new Promise(function(resolve, reject) {
343 | fs.exists(dir, function(exists) {
344 | if (exists) {
345 | resolve();
346 | } else {
347 | fs.mkdir(dir, function(err) {
348 | if (err) return reject(err);
349 | resolve();
350 | });
351 | }
352 | });
353 | });
354 | };
Parses the options file, .Dokker.json, and sets the default parameters.
366 | 367 |Dokker.configure = function(options) {
370 | return new Promise(function(resolve, reject){
371 | var file = path.join(process.cwd(), '.dokker.json');
372 | return read(file, 'utf8')
373 | .then(function(data) {
374 | data = JSON.parse(data);
375 | data.jsdoc.template = (data.jsdoc.template) ? path.join(process.cwd(), data.jsdoc.template) : path.join(__dirname, 'templates/index.ejs.html');
376 | data.mocha.template = (data.mocha.template) ? path.join(process.cwd(), data.mocha.template) : path.join(__dirname, 'templates/tests.ejs.html');
377 | data.mocha.path = path.join(process.cwd(), data.dir, data.mocha.path);
mocha.command commented out to fix build-breaking bug 389 | specifies mocha command in .dokker.json; e.g. mocha -u tdd -R spec 390 | data.mocha.command = path.join(process.cwd(), data.dir, data.mocha.command);
391 | 392 | data.literate.dir = path.join(process.cwd(), data.dir, data.literate.dir);
395 | data.jsdoc.markdown = path.join(process.cwd(), data.dir, data.jsdoc.markdown);
396 | data.jsdoc.html = path.join(process.cwd(), data.dir, data.jsdoc.html);
397 | data.jsdoc.readme = path.join(process.cwd(), data.jsdoc.readme);
398 | resolve(data);
399 | }).then(null, function(err) {
400 | reject(err);
401 | });
402 | });
403 | };
Copy starter template to bootstrap any Dokker project.
415 | 416 |Dokker.copyTemplate = function(options) {
419 | return new Promise(function(resolve, reject) {
420 | var templatesDir = path.join(process.cwd(), 'templates');
421 | return Dokker.mkdir(templatesDir)
422 | .then(function() {
423 | var oldStyle = path.join(__dirname, 'templates', 'styles.css');
424 | var newStyle = path.join(process.cwd(), options.dir, 'styles.css');
425 | fs.createReadStream(oldStyle).pipe(fs.createWriteStream(newStyle));
426 | var oldLogo = path.join(__dirname, 'templates', 'logo.png');
427 | var newLogo = path.join(process.cwd(), options.dir, 'logo.png');
428 | fs.createReadStream(oldLogo).pipe(fs.createWriteStream(newLogo));
429 | var oldApp = path.join(__dirname, 'templates', 'app.js');
430 | var newApp = path.join(process.cwd(), options.dir, 'app.js');
431 | fs.createReadStream(oldApp).pipe(fs.createWriteStream(newApp));
432 | resolve();
433 | });
434 | });
435 | };
Copies the .Dokker.json file to bootstrap any Dokker project.
447 | 448 |Dokker.init = function(){
451 | return new Promise(function(resolve, reject) {
452 | var oldDok = path.join(__dirname, '.dokker.json');
453 | var newDok = path.join(process.cwd(), '.dokker.json');
454 | fs.createReadStream(oldDok).pipe(fs.createWriteStream(newDok));
455 | resolve();
456 | });
457 | };
Starts the Node.js/Express server to watch Dokker.js project 469 | documentation.
470 | 471 |Dokker.watch = function(options) {
474 | var gulpex = require(__dirname + '/gulpfile.js').gulpex;
475 | return gulpex();
return new Promise(function(resolve, reject){ 487 | exec(‘DIR=’+ options.dir + ‘ node ‘ + options.dir + ‘/app.js’, function(error, stdout, stderr){ 488 | if(error) return reject(stderr); 489 | }); 490 | });
491 | 492 |};
495 |
496 | module.exports = Dokker;
Dokker.js
Github Pages
Dokker.ghPages
JSDoc
Dokker.injectTemplate
Dokker.jsdocHtml
Dokker.jsdocMarkdown
Literate programming
Dokker.literate
Mocha
Dokker.createTests
Utility
Dokker.configure
Dokker.copyTemplate
Dokker.init
Dokker.watch
Methods
Properties
Dokker.VERSION
Dokker.js creates professional Javascript code documentations.
73 |See Dokker.js documentation as example.
74 | 75 |Dokker is available as npm package. So the easiest way is to install dokker as global module into your project:
91 |npm install -g dokker
92 |
After installation you can execute Dokker with the help of several terminal commands.
94 |Bootstrap Dokker project
95 |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.
97 |Create documentation
98 |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
100 |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
105 |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!
108 | 112 |“Github Pages” Methods
Dokker.ghPages()
Runs a terminal shell with the git command to extract the docs branch 134 | into a seperate gh-pages branch and finally pushes that branch to Github, 135 | so that the Github page is updated.
136 |(Promise): Returns a resolved promise if file was created.
138 |Dokker.ghPages()
140 | .then(function(){
141 | // => resolved promise
142 | });
143 |
144 | “JSDoc” Methods
Dokker.injectTemplate([options])
Creates a HTML file that transcludes the HTML snippet that was created 153 | by the docdown module into an ejs template which is defined by the 154 | .dokker.json configuration file.
155 |[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.
165 |var options = {
167 | template: 'template/index.ejs.html',
168 | html: 'docs/index.html',
169 | readme: 'docs/README.md',
170 | title: 'Dokker.js API Documentation'
171 | };
172 | Dokker.injectTemplate(options)
173 | .then(function(){
174 | // => resolved promise
175 | });
176 |
177 | Dokker.jsdocHtml([options])
Create an HTML file from the Markdown file that was create with 183 | Dokker.jsdocMarkdown()
184 |[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.
191 |var options = {
193 | markdown: 'docs/README.md'
194 | };
195 | Dokker.jsdocHtml()
196 | .then(function(){
197 | // => resolved promise
198 | });
199 |
200 | Dokker.jsdocMarkdown([options])
Create a Markdown file from JSDoc tags.
206 |[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.
215 |var options = {
217 | source: 'app.js',
218 | markdown: 'docs/README.md'
219 | };
220 | Dokker.jsdocMarkdown()
221 | .then(function(){
222 | // => resolved promise
223 | });
224 |
225 | “Literate programming” Methods
Dokker.literate([options])
Create a styled HTML file from your source code with the help of docco 234 | module.
235 |[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.
243 |var options = {
245 | dir: 'docs',
246 | source: 'app.js'
247 | };
248 | Dokker.literate()
249 | .then(function(){
250 | // => resolved promise
251 | });
252 |
253 | “Mocha” Methods
Dokker.createTests([options])
Creates an HTML file to describe the features of your module from your 262 | Mocha tests. The module is using the mocha doc reporter to 263 | generate the HTML contents.
264 |[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.
271 |var options = {
273 | path: 'docs/tests.html',
274 | };
275 | Dokker.createTests(options)
276 | .then(function(){
277 | // => resolved promise
278 | });
279 |
280 | “Utility” Methods
Dokker.configure([options])
Helper function that takes a couple of options arguments and 289 | normalises them and subsequently returns them.
290 |[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
303 |var options = {
305 | dir: 'docs',
306 | literate: {
307 | source: 'dokker.js',
308 | dir: 'annotated'
309 | },
310 | jsdoc: {
311 | title: 'Dokker.js',
312 | source: 'dokker.js',
313 | markdown: 'README.md',
314 | html: 'index.html',
315 | readme: 'README.md',
316 | }
317 | };
318 | Dokker.jsdocHtml()
319 | .then(function(){
320 | // => object with absolute pathes to the directory from
321 | // which the command was executed
322 | });
323 |
324 | Dokker.copyTemplate([options])
Copy the template to local directory so that one can make changes to ejs 330 | files.
331 |[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.
338 |var options = {
340 | dir: 'template'
341 | };
342 | Dokker.copyTemplate()
343 | .then(function(){
344 | // => resolved promise
345 | });
346 |
347 | Dokker.init()
Create a .dokker.json file to bootstrap any Dokker project
353 |(Promise): Returns a resolved promise if files were created.
355 |Dokker.init()
357 | .then(function(){
358 | // => resolved promise
359 | });
360 |
361 | Dokker.watch()
Starts a Node.js/Express webserver in docs directory to watch 367 | the build Dokker project
368 |(Promise): Returns a resolved promise if files were created.
370 |Dokker.init()
372 | .then(function(){
373 | // => resolved promise
374 | });
375 |
376 | Methods
return Dokker.literate(options.literate)
48 | .then(function(){
49 | done();
50 | }).done();
return Dokker.jsdocMarkdown(options.jsdoc)
59 | .then(function(){
60 | return read(options.jsdoc.markdown);
61 | }).then(function(){
62 | done();
63 | }).done();
return Dokker.jsdocHtml(options.jsdoc)
71 | .then(function(){
72 | return read(options.jsdoc.html);
73 | }).then(function(){
74 | done();
75 | }).done();
return Dokker.injectTemplate(options.jsdoc)
83 | .then(function() {
84 | return read(options.jsdoc.html, 'utf8');
85 | }).then(function(data){
86 | assert(/<!DOCTYPE html>/.test(data));
87 | done();
88 | }).done();
return Dokker.copyTemplate(options)
96 | .then(function(){
97 | return read(path.join(__dirname, '..', options.dir, 'styles.css'));
98 | }).then(function(data){
99 | assert(data);
100 | done();
101 | }).done();
><%= title %>