Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

a docs task

plus the internal scripts/docs tool and genedocs grunt task to generate

the docs task (provided in the plugin, or via h5bp docs) will start a
server on top of docs/ directory and open a browser on generated
documentation
  • Loading branch information...
commit cece1da169abda34681a052ff2fe3b2cd6d85525 1 parent d911203
@mklabs authored
View
5 .gitignore
@@ -2,6 +2,7 @@ node_modules
test/fixtures/h5bp
.test
npm-debug.log
-test/custom
-docs/_site
tasks/init/h5bp/root
+docs/css
+docs/index.html
+docs/api
View
4 .gitmodules
@@ -1,6 +1,6 @@
[submodule "test/h5bp"]
path = test/h5bp
url = git://github.com/h5bp/html5-boilerplate.git
-[submodule "docs"]
- path = docs
+[submodule "docs/wiki"]
+ path = docs/wiki
url = git://github.com/h5bp/node-build-script.wiki.git
1  docs
@@ -1 +0,0 @@
-Subproject commit 58354b41556600e0d8ac451d9187c8bd21564be3
1  docs/wiki
@@ -0,0 +1 @@
+Subproject commit 84ff15d925c03b37a0491a81fda10d1fd5a121e0
View
19 grunt.js
@@ -1,4 +1,5 @@
-var util = require('util');
+var util = require('util'),
+ path = require('path');
/*global module:false*/
module.exports = function(grunt) {
@@ -48,4 +49,20 @@ module.exports = function(grunt) {
grunt.helper('inspect', grunt.task._tasks[t]);
});
+ // and the doc generation for the docs task
+ grunt.registerTask('gendocs', 'Generates docs/index.html from wiki pages', function() {
+ var cb = this.async();
+
+ var gendoc = grunt.utils.spawn({
+ cmd: 'grunt', opts: { cwd: path.join(__dirname, 'scripts/docs') }
+ }, function() {});
+
+ gendoc.stdout.pipe(process.stdout);
+ gendoc.stderr.pipe(process.stderr);
+ gendoc.on('exit', function(code) {
+ if(code) grunt.warn('Something bad happend', code);
+ cb();
+ });
+ });
+
};
View
196 scripts/docs/grunt.js
@@ -0,0 +1,196 @@
+var fs = require('fstream'),
+ path = require('path'),
+ fork = require('child_process').fork,
+ rimf = require('rimraf'),
+ Generator = require('h5bp-docs');
+
+module.exports = function(grunt) {
+
+ // Project configuration.
+ grunt.initConfig({
+ pkg: '<json:../../package.json>',
+ docs: {
+ wiki: {
+ filter : 'Home',
+ layout : 'index.html',
+ style : 'grey',
+ cwd : path.join(__dirname, '../../docs/wiki/'),
+ files : '**/*.md',
+ assets : '**/*.css',
+ prefix : './',
+ relative : false
+ },
+ api: {
+ tasks : '../../tasks/**/*.js',
+ lib : '../../lib/**/*.js',
+ root : '../../*.js'
+ }
+ }
+ });
+
+ // Default task.
+ grunt.registerTask('default', 'clean:../../docs/api docs clean:api/ assets clean:../../docs/wiki/_site');
+ grunt.registerTask('wiki', 'docs:wiki');
+ grunt.registerTask('api', 'docs:api');
+
+ grunt.registerTask('clean', 'Clean dir', function(dirpath) {
+ rimf.sync(path.join(__dirname, dirpath));
+ });
+
+ grunt.registerTask('assets', 'Copy css / js files', function(dirpath) {
+ grunt.helper('copy', '../../docs/wiki/css', '../../docs/css', this.async());
+ });
+
+
+ // **docs** task - uses h5bp-docs on top of wiki submodule (path:
+ // `docs/`) and docco on top of project's sources.
+ //
+ // This is a multi task with `wiki` and `api` as subtarget.
+ grunt.registerMultiTask('docs', 'Generates docs', function() {
+ var target = this.target,
+ data = this.data,
+ cb = this.async();
+
+ if(grunt.option('serve')) data.serve = true;
+ grunt.helper(target, data, function(err) {
+ if(err) return grunt.fail(err);
+ cb();
+ });
+ });
+
+
+ // **wiki** helper - creates a new site, with given `data`
+ // configuration. if `data.serve=true` then a http server is started
+ // with live rebuilding (eg. page is rebuild / served on requests)
+ grunt.registerHelper('wiki', function(data, cb) {
+ var site = new Generator(data);
+ site.on('error', function(er) {
+ grunt.log.error('✗ Got error' + er.message);
+ cb(err);
+ });
+
+ var now = +new Date;
+ site.on('end', function() {
+ grunt.log
+ .ok(' ✔ Site generated in ' + ((+new Date - now) / 1000) + 's')
+ .writeln(data.serve ? 'Try opening http://localhost:3000' : 'Try running: open docs/_site/index.html');
+
+ grunt.helper('copy', '../../docs/wiki/_site/index.html', '../../docs/index.html', function() {
+ if(data.serve) site.preview(cb);
+ else cb();
+ });
+ });
+
+
+ // reorder the page the way we want
+ var ordered = grunt.file.read('pages.txt').trim().split('\n');
+ var tmp = [];
+ ordered.forEach(function(name, i) {
+ var page = site.pages.filter(function(page) {
+ return page.name === name;
+ })[0];
+
+ tmp[i] = page;
+ });
+ site.pages = tmp;
+
+ // Now build our pageset, totally custom
+ site.data = site.data || {};
+ var ps = site.data.pageset = {};
+ function json(p) { return p.toJSON(true, ''); }
+ ps.intro = site.pages.slice(1, 4).map(json);
+ ps.tasks = site.pages.filter(function(page) {
+ return path.basename(page.dirname) === 'tasks';
+ }).map(json);
+ ps.dom = site.pages.filter(function(page) {
+ return path.basename(page.dirname) === 'plugins' || page.basename === 'dom.md';
+ }).map(json);
+
+ // add package info
+ site.data.pkg = grunt.config('pkg');
+
+
+ // add an anchor to the first heading, for each page
+ site.on('page', function(p) {
+ var tokens = p.tokens,
+ first = tokens[0],
+ h1 = first.type === 'heading' && first.depth === 1;
+
+ if(!h1) return;
+
+ var slug = json(p).slug;
+ first.escaped = true;
+ first.text = first.text
+ .link('#' + slug)
+ .replace(/href/, 'id="' + slug + '" href');
+
+ p.tokens.unshift({ type: 'hr' });
+ });
+
+ // generate
+ site.generate();
+ });
+
+
+ // **api**: Uses docco on top of gruntfile, tasks, and lib utils.
+ grunt.registerHelper('api', function(data, cb) {
+ var docco = require.resolve('docco'),
+ categs = Object.keys(data);
+
+ (function generate(categ) {
+ if(!categ) return grunt.helper('copy', 'api', '../../docs/api', cb);
+ grunt.log.writeln('Generating docco for ' + categ);
+ var files = grunt.file.expandFiles(data[categ]);
+ grunt.log.writeln('Files: ').writeln(grunt.log.wordlist(files, grunt.utils.linefeed));
+
+ // the docco binary
+ var doccobin = path.join(path.dirname(require.resolve('docco')), '../bin/docco');
+
+ // destination dir
+ var dest = path.join(__dirname, 'api', categ);
+
+ // adjust filepath to opts.cwd
+ files = files.map(function(file) {
+ return path.join('../..', file);
+ });
+
+ // temporary check on filtering minified files (jquery.min in
+ // tasks dir)
+ files = files.filter(function(file) {
+ return !/\.min\.js$/.test(file);
+ });
+
+ grunt.file.mkdir(dest);
+
+ var docco = grunt.utils.spawn({
+ cmd: 'node',
+ args: [doccobin].concat(files),
+ opts: {
+ cwd: dest
+ }
+ }, function() {});
+
+ docco.stdout.on('data', function() { grunt.log.write('.'); });
+ docco.stderr.pipe(process.stderr);
+ docco.on('error', cb).on('exit', function(code) {
+ if(code) return cb(new Error('Error exit code not 0: ' + code));
+ grunt.log.ok().ok("I'm done generating " + categ + ' - ' + dest).writeln();
+ generate(categs.shift());
+ });
+ })(categs.shift());
+
+ return;
+ });
+
+
+
+ // **copy** task - copy the files in docs/_site/* into ./
+ grunt.registerHelper('copy', function(src, dest, cb) {
+ src = path.join(__dirname, src);
+ dest = path.join(__dirname, dest);
+ console.log('Copy files %s -> %s', src, dest);
+ var type = path.extname(dest) ? 'File' : 'Directory';
+ fs.Reader(src).pipe(fs.Writer({ path: dest, type: type })).on('close', cb);
+ });
+
+};
View
16 scripts/docs/package.json
@@ -0,0 +1,16 @@
+{
+ "author": "mklabs",
+ "name": "grunt-doc-generator",
+ "description": "Internal tool for generating api docs",
+ "version": "0.0.0",
+ "engines": {
+ "node": "0.6.x"
+ },
+ "dependencies": {
+ "marked": "~0.2.4",
+ "h5bp-docs": "http://nodeload.github.com/mklabs/h5bp-docs/tarball/next",
+ "docco": "~0.3.0",
+ "fstream": "~0.1.18"
+ },
+ "bin": "./generate.js"
+}
View
19 scripts/docs/pages.txt
@@ -0,0 +1,19 @@
+Home
+install
+overview
+configuration
+tasks
+clean
+concat
+connect
+css
+min
+mkdirs
+rev
+serve
+usemin
+dom
+link-plugin
+rev-plugin
+script-plugin
+test
View
53 scripts/docs/readme.md
@@ -0,0 +1,53 @@
+
+node-build-script documentation site
+====================================
+
+Site is build with [h5bp-docs][] and generated from the project wiki.
+Each page may be rendered as individual page, but the docs are all compiled
+into one page (index.html).
+
+[Docco][] is also used and generates from files in `src/` into `api/`.
+
+The site can be built with:
+
+``` sh
+$ grunt docs
+# >> docs copy
+$ open index.html
+```
+
+```sh
+$ grunt wiki
+# >> docs:wiki copy
+open index.html
+```
+
+```sh
+$ grunt api
+# >> docs:api
+$ ls api/
+lib/ root/ tasks/
+```
+
+Faster building & rebuilding
+----------------------------
+
+For quicker rebuilding of the site, you can start up the preview server:
+
+``` sh
+$ grunt docs --serve # live rebuilding of the site!
+$ open http://localhost:3000
+```
+
+Update the docs
+---------------
+
+The docs are managed through git submodules in `docs/` path. To update
+(or clone the first time it's run):
+
+```sh
+$ git submodule update --init
+```
+
+[h5bp-docs]: https://github.com/mklabs/h5bp-docs
+[Docco]: http://jashkenas.github.com/docco/
View
34 tasks/docs.js
@@ -0,0 +1,34 @@
+
+var path = require('path'),
+ spawn = require('child_process').spawn;
+
+var env = process.platform;
+
+module.exports = function(grunt) {
+
+ grunt.registerTask('docs', 'grunt h5bp plugin documentation', function(target) {
+ // long running process
+ var cb = this.async();
+ var config = {
+ base: path.join(__dirname, '../docs'),
+ port: grunt.option('port') || 3000,
+ browser: grunt.config('browser') || grunt.option('browser') || ''
+ };
+
+ var browser = config.browser ? config.browser :
+ env === 'win32' ? 'explorer' :
+ env === 'darwin' ? 'open' :
+ 'google-chrome';
+
+ var app = grunt.helper('serve', config);
+
+ app.on('start', function() {
+ var open = spawn(browser, ['http://localhost:' + config.port]);
+ open.on('error', function(er) { console.error(er); });
+ open.on('exit', function(code) {
+ if(code) grunt.warn('Something bad happend', code);
+ });
+ });
+ });
+
+};
View
5 tasks/serve.js
@@ -43,10 +43,13 @@ module.exports = function(grunt) {
port = config.port || 8000,
app = connect();
- return app.listen(port, function(err) {
+ app.listen(port, function(err) {
if(err) grunt.log.error(err).warn(err.message, err.code);
grunt.log.ok('Started static web server in ' + base.underline.bold + ' on port ' + (port + '').green + '...');
+ app.emit('start');
});
+
+ return app;
});
// **serve.io** creates and returns a webserver and setup a socket.io instance and
Please sign in to comment.
Something went wrong with that request. Please try again.