From 8fa066190af2b2267a5e8111a41beb6e8af5c340 Mon Sep 17 00:00:00 2001 From: Di Peng Date: Sat, 9 Jul 2011 18:15:40 -0700 Subject: refactor(gen-docs): use q, qq, q-fs (node modules) to write gen-docs - re-write gendocs.js, reader.js and writer.js - all calls are asynchronous --- docs/src/appCache.js | 99 +++++++++++++++---------- docs/src/callback.js | 69 ----------------- docs/src/gen-docs.js | 139 ++++++++++++++++------------------ docs/src/reader.js | 168 +++++++++++++++++++++--------------------- docs/src/templates/index.html | 4 +- docs/src/writer.js | 167 ++++++++++++++++++++++------------------- 6 files changed, 303 insertions(+), 343 deletions(-) delete mode 100644 docs/src/callback.js (limited to 'docs') diff --git a/docs/src/appCache.js b/docs/src/appCache.js index 994054c2..cf7827bf 100644 --- a/docs/src/appCache.js +++ b/docs/src/appCache.js @@ -3,48 +3,73 @@ */ exports.appCache = appCache; -var fs = require('fs'); +var fs = require('q-fs'); +var Q = require('qq'); +function identity($) {return $;} function appCache(path) { - var blackList = [ "offline.html", - "sitemap.xml", - "robots.txt", - "docs-scenario.html", - "docs-scenario.js", - "app-cache.manifest" + if(!path) { + return appCacheTemplate(); + } + var blackList = ["offline.html", + "sitemap.xml", + "robots.txt", + "docs-scenario.html", + "docs-scenario.js", + "appcache.manifest" ]; var result = ["CACHE MANIFEST", - "# %TIMESTAMP%", - "", - "# cache all of these", - "CACHE:", - "../angular.min.js"]; + "# " + new Date().toISOString(), + "", + "# cache all of these", + "CACHE:", + "../angular.min.js"]; + + var resultPostfix = ["", + "FALLBACK:", + "/offline.html", + "", + "# allow access to google analytics and twitter when we are online", + "NETWORK:", + "*"]; + + var promise = fs.listTree(path).then(function(files){ + var fileFutures = []; + files.forEach(function(file){ + fileFutures.push(fs.isFile(file).then(function(isFile){ + if (isFile && blackList.indexOf(file) == -1) { + return file.replace('build/docs/',''); + } + })); + }); + return Q.deep(fileFutures); + }).then(function(files){ + return result.concat(files.filter(identity)).concat(resultPostfix).join('\n'); + }); - var resultPostfix = [ "", - "FALLBACK:", - "/offline.html", - "", - "# allow access to google analytics and twitter when we are online", - "NETWORK:", - "*"]; - walk(path,result,blackList); - return result.join('\n').replace(/%TIMESTAMP%/, (new Date()).toISOString()) + '\n' + resultPostfix.join('\n'); + return promise; } -function walk(path, array, blackList) { - var temp = fs.readdirSync(path); - for (var i=0; i< temp.length; i++) { - if(blackList.indexOf(temp[i]) < 0) { - var currentPath = path + '/' + temp[i]; - var stat = fs.statSync(currentPath); - - if (stat.isDirectory()) { - walk(currentPath, array, blackList); - } - else { - array.push(currentPath.replace('build/docs/','')); - } - } - } -} \ No newline at end of file +function appCacheTemplate() { + return ["CACHE MANIFEST", + "# " + new Date().toISOString(), + "", + "# cache all of these", + "CACHE:", + "syntaxhighlighter/syntaxhighlighter-combined.js", + "../angular.min.js", + "docs-combined.js", + "docs-keywords.js", + "docs-combined.css", + "syntaxhighlighter/syntaxhighlighter-combined.css", + "img/texture_1.png", + "img/yellow_bkgnd.jpg", + "", + "FALLBACK:", + "/ offline.html", + "", + "# allow access to google analytics and twitter when we are online", + "NETWORK:", + "*"].join('\n'); +} diff --git a/docs/src/callback.js b/docs/src/callback.js deleted file mode 100644 index aaf69cde..00000000 --- a/docs/src/callback.js +++ /dev/null @@ -1,69 +0,0 @@ -function noop(){} - -function chain(delegateFn, explicitDone){ - var onDoneFn = noop; - var onErrorFn = function(e){ - console.error(e.stack || e); - process.exit(-1); - }; - var waitForCount = 1; - delegateFn = delegateFn || noop; - var stackError = new Error('capture stack'); - - function decrementWaitFor() { - waitForCount--; - if (waitForCount == 0) - onDoneFn(); - } - - function self(){ - try { - return delegateFn.apply(self, arguments); - } catch (error) { - self.error(error); - } finally { - if (!explicitDone) - decrementWaitFor(); - } - }; - self.onDone = function(callback){ - onDoneFn = callback; - return self; - }; - self.onError = function(callback){ - onErrorFn = callback; - return self; - }; - self.waitFor = function(callback){ - if (waitForCount == 0) - throw new Error("Can not wait on already called callback."); - waitForCount++; - return chain(callback).onDone(decrementWaitFor).onError(self.error); - }; - - self.waitMany = function(callback){ - if (waitForCount == 0) - throw new Error("Can not wait on already called callback."); - waitForCount++; - return chain(callback, true).onDone(decrementWaitFor).onError(self.error); - }; - - self.done = function(callback){ - decrementWaitFor(); - }; - - self.error = function(error) { - var stack = stackError.stack.split(/\n\r?/).splice(2); - var nakedStack = []; - stack.forEach(function(frame){ - if (!frame.match(/callback\.js:\d+:\d+\)$/)) - nakedStack.push(frame); - }); - error.stack = error.stack + '\nCalled from:\n' + nakedStack.join('\n'); - onErrorFn(error); - }; - - return self; -} - -exports.chain = chain; diff --git a/docs/src/gen-docs.js b/docs/src/gen-docs.js index 8ed0c563..2cbc9267 100755 --- a/docs/src/gen-docs.js +++ b/docs/src/gen-docs.js @@ -3,90 +3,77 @@ require.paths.push('lib'); var reader = require('reader.js'), ngdoc = require('ngdoc.js'), writer = require('writer.js'), - callback = require('callback.js'), SiteMap = require('SiteMap.js').SiteMap, - appCache = require('appCache.js'); + appCache = require('appCache.js').appCache, + Q = require('qq'); -var docs = []; -var start; -var work = callback.chain(function(){ - start = now(); - console.log('Generating Angular Reference Documentation...'); - reader.collect(work.waitMany(function(text, file, line){ - var doc = new ngdoc.Doc(text, file, line); - docs.push(doc); - doc.parse(); - })); +process.on('uncaughtException', function (err) { + console.error(err.stack || err); }); -var writes = callback.chain(function(){ + +var start = now(); +var docs; + +writer.makeDir('build/docs/syntaxhighlighter').then(function() { + console.log('Generating Angular Reference Documentation...'); + return reader.collect(); +}).then(function generateHtmlDocPartials(docs_) { + docs = docs_; ngdoc.merge(docs); + var fileFutures = []; docs.forEach(function(doc){ - writer.output(doc.section + '/' + doc.id + '.html', doc.html(), writes.waitFor()); + fileFutures.push(writer.output(doc.section + '/' + doc.id + '.html', doc.html())); }); + + writeTheRest(fileFutures); + + return Q.deep(fileFutures); +}).then(function generateManifestFile() { + return appCache('build/docs/').then(function(list) { + writer.output('appcache-offline.manifest',list) + }); +}).then(function printStats() { + console.log('DONE. Generated ' + docs.length + ' pages in ' + (now()-start) + 'ms.' ); +}).end(); + + +function writeTheRest(writesFuture) { var metadata = ngdoc.metadata(docs); - writer.output('docs-keywords.js', ['NG_PAGES=', JSON.stringify(metadata).replace(/{/g, '\n{'), ';'], writes.waitFor()); - writer.copyDir('img', writes.waitFor()); - writer.copyDir('examples', writes.waitFor()); - writer.copyTpl('index.html', writes.waitFor()); - writer.copyTpl('.htaccess', writes.waitFor()); - writer.copy('docs/src/templates/index.html', 'build/docs/index-jq.html', writes.waitFor(), - '<-- jquery place holder -->', ' - <-- jquery place holder --> + diff --git a/docs/src/writer.js b/docs/src/writer.js index 0655572d..1acf9df7 100644 --- a/docs/src/writer.js +++ b/docs/src/writer.js @@ -3,37 +3,113 @@ * for testability */ require.paths.push(__dirname); -var fs = require('fs'); +var qfs = require('q-fs'); +var Q = require('qq'); var OUTPUT_DIR = "build/docs/"; +var fs = require('fs'); -function output(docs, content, callback){ - callback(); +exports.output = function(file, content){ + console.log('writing ', file); + var fullPath = OUTPUT_DIR + file; + var dir = parent(fullPath); + return Q.when(exports.makeDir(dir), function(error) { + qfs.write(fullPath,exports.toString(content)); + }); +} + +//recursively create directory +exports.makeDir = function (path) { + var parts = path.split(/\//); + var path = "."; + //Sequentially create directories + var done = Q.defer(); + (function createPart() { + + if(!parts.length) { + done.resolve(); + } else { + path += "/" + parts.shift(); + qfs.isDirectory(path).then(function(isDir) { + if(!isDir) { + qfs.makeDirectory(path); + } + createPart(); + }); + } + })(); + return done.promise; +}; + +exports.copyTpl = function(filename) { + return exports.copy('docs/src/templates/' + filename, OUTPUT_DIR + filename); +}; + +exports.copy = function (from, to, replacementKey, replacement) { + // Have to use rb (read binary), char 'r' is infered by library. + return qfs.read(from,'b').then(function(content) { + if(replacementKey && replacement) { + content = content.toString().replace(replacementKey, replacement); + } + qfs.write(to, content); + }); +} + +exports.copyDir = function copyDir(dir) { + return qfs.listDirectoryTree('docs/' + dir).then(function(dirs) { + var done; + dirs.forEach(function(dirToMake) { + done = Q.when(done, function() { + return exports.makeDir("./build/" + dirToMake); + }); + }); + return done; + }).then(function() { + return qfs.listTree('docs/' + dir); + }).then(function(files) { + files.forEach( function(file) { + exports.copy(file,'./build/' + file); + }); + }); +}; + +exports.merge = function(srcs, to) { + return merge(srcs.map(function(src) { return 'docs/src/templates/' + src; }), OUTPUT_DIR + to); +}; + +function merge(srcs, to) { + var contents = []; + //Sequentially read file + var done; + srcs.forEach(function (src) { + done = Q.when(done, function(content) { + if(content) contents.push(content); + return qfs.read(src); + }); + }); + + // write to file + return Q.when(done, function(content) { + contents.push(content); + qfs.write(to, contents.join('\n')); + }); } +//----------------------- Synchronous Methods ---------------------------------- + function parent(file) { var parts = file.split('/'); parts.pop(); return parts.join('/'); } -exports.output = function(file, content, callback){ - console.log('write', file); - exports.makeDir(parent(OUTPUT_DIR + file), callback.waitFor(function(){ - fs.writeFile( - OUTPUT_DIR + file, - exports.toString(content), - callback); - })); -}; - -exports.toString = function toString(obj){ +exports.toString = function toString(obj) { switch (typeof obj) { case 'string': return obj; case 'object': if (obj instanceof Array) { - obj.forEach(function (value, key){ + obj.forEach(function (value, key) { obj[key] = toString(value); }); return obj.join(''); @@ -44,64 +120,5 @@ exports.toString = function toString(obj){ return obj; }; -exports.makeDir = function (path, callback) { - var parts = path.split(/\//); - path = '.'; - (function next(error){ - if (error && error.code != 'EEXIST') return callback.error(error); - if (parts.length) { - path += '/' + parts.shift(); - fs.mkdir(path, 0777, next); - } else { - callback(); - } - })(); -}; - -exports.copyTpl = function(filename, callback) { - exports.copy('docs/src/templates/' + filename, OUTPUT_DIR + filename, callback); -}; -exports.copy = function(from, to, callback, replacementKey, replacement) { - //console.log('writing', to, '...'); - fs.readFile(from, function(err, content){ - if (err) return callback.error(err); - if(replacementKey && replacement) { - content = content.toString().replace(replacementKey, replacement); - } - fs.writeFile(to, content, callback); - }); -}; - -exports.copyDir = function copyDir(dir, callback) { - exports.makeDir(OUTPUT_DIR + '/' + dir, callback.waitFor(function(){ - fs.readdir('docs/' + dir, callback.waitFor(function(err, files){ - if (err) return this.error(err); - files.forEach(function(file){ - var path = 'docs/' + dir + '/' + file; - fs.stat(path, callback.waitFor(function(err, stat) { - if (err) return this.error(err); - if (stat.isDirectory()) { - copyDir(dir + '/' + file, callback.waitFor()); - } else { - exports.copy(path, OUTPUT_DIR + '/' + dir + '/' + file, callback.waitFor()); - } - })); - }); - callback(); - })); - })); -}; - - -exports.merge = function(srcs, to, callback){ - merge(srcs.map(function(src) { return 'docs/src/templates/' + src; }), OUTPUT_DIR + to, callback); -}; - -function merge(srcs, to, callback) { - var content = []; - srcs.forEach(function (src) { - content.push(fs.readFileSync(src)); - }); - fs.writeFile(to, content.join('\n'), callback.waitFor()); -} +function noop(){}; -- cgit v1.2.3