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
---
.gitignore | 1 +
Rakefile | 2 +-
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 ++++++++++++++++++++++-------------------
8 files changed, 305 insertions(+), 344 deletions(-)
delete mode 100644 docs/src/callback.js
diff --git a/.gitignore b/.gitignore
index 38524cfa..487c14ac 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ performance/temp*.html
.idea/workspace.xml
*~
angular.js.tmproj
+node_modules
diff --git a/Rakefile b/Rakefile
index 83f69cfd..6d0ca960 100644
--- a/Rakefile
+++ b/Rakefile
@@ -246,7 +246,7 @@ task :package => [:clean, :compile, :docs] do
f.write text.sub('angular-scenario.js', "angular-scenario-#{version}.js")
end
- File.open("#{pkg_dir}/docs-#{version}/app-cache.manifest", File::RDWR) do |f|
+ File.open("#{pkg_dir}/docs-#{version}/appcache.manifest", File::RDWR) do |f|
text = f.read
f.rewind
f.write text.sub('angular.min.js', "angular-#{version}.min.js")
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