mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-25 06:13:44 +00:00
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
This commit is contained in:
parent
e90b741c94
commit
8fa066190a
8 changed files with 308 additions and 347 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -9,3 +9,4 @@ performance/temp*.html
|
||||||
.idea/workspace.xml
|
.idea/workspace.xml
|
||||||
*~
|
*~
|
||||||
angular.js.tmproj
|
angular.js.tmproj
|
||||||
|
node_modules
|
||||||
|
|
|
||||||
2
Rakefile
2
Rakefile
|
|
@ -246,7 +246,7 @@ task :package => [:clean, :compile, :docs] do
|
||||||
f.write text.sub('angular-scenario.js', "angular-scenario-#{version}.js")
|
f.write text.sub('angular-scenario.js', "angular-scenario-#{version}.js")
|
||||||
end
|
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
|
text = f.read
|
||||||
f.rewind
|
f.rewind
|
||||||
f.write text.sub('angular.min.js', "angular-#{version}.min.js")
|
f.write text.sub('angular.min.js', "angular-#{version}.min.js")
|
||||||
|
|
|
||||||
|
|
@ -3,48 +3,73 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exports.appCache = appCache;
|
exports.appCache = appCache;
|
||||||
var fs = require('fs');
|
var fs = require('q-fs');
|
||||||
|
var Q = require('qq');
|
||||||
|
function identity($) {return $;}
|
||||||
|
|
||||||
function appCache(path) {
|
function appCache(path) {
|
||||||
var blackList = [ "offline.html",
|
if(!path) {
|
||||||
"sitemap.xml",
|
return appCacheTemplate();
|
||||||
"robots.txt",
|
}
|
||||||
"docs-scenario.html",
|
var blackList = ["offline.html",
|
||||||
"docs-scenario.js",
|
"sitemap.xml",
|
||||||
"app-cache.manifest"
|
"robots.txt",
|
||||||
|
"docs-scenario.html",
|
||||||
|
"docs-scenario.js",
|
||||||
|
"appcache.manifest"
|
||||||
];
|
];
|
||||||
|
|
||||||
var result = ["CACHE MANIFEST",
|
var result = ["CACHE MANIFEST",
|
||||||
"# %TIMESTAMP%",
|
"# " + new Date().toISOString(),
|
||||||
"",
|
"",
|
||||||
"# cache all of these",
|
"# cache all of these",
|
||||||
"CACHE:",
|
"CACHE:",
|
||||||
"../angular.min.js"];
|
"../angular.min.js"];
|
||||||
|
|
||||||
var resultPostfix = [ "",
|
var resultPostfix = ["",
|
||||||
"FALLBACK:",
|
"FALLBACK:",
|
||||||
"/offline.html",
|
"/offline.html",
|
||||||
"",
|
"",
|
||||||
"# allow access to google analytics and twitter when we are online",
|
"# allow access to google analytics and twitter when we are online",
|
||||||
"NETWORK:",
|
"NETWORK:",
|
||||||
"*"];
|
"*"];
|
||||||
walk(path,result,blackList);
|
|
||||||
return result.join('\n').replace(/%TIMESTAMP%/, (new Date()).toISOString()) + '\n' + resultPostfix.join('\n');
|
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');
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
function walk(path, array, blackList) {
|
function appCacheTemplate() {
|
||||||
var temp = fs.readdirSync(path);
|
return ["CACHE MANIFEST",
|
||||||
for (var i=0; i< temp.length; i++) {
|
"# " + new Date().toISOString(),
|
||||||
if(blackList.indexOf(temp[i]) < 0) {
|
"",
|
||||||
var currentPath = path + '/' + temp[i];
|
"# cache all of these",
|
||||||
var stat = fs.statSync(currentPath);
|
"CACHE:",
|
||||||
|
"syntaxhighlighter/syntaxhighlighter-combined.js",
|
||||||
if (stat.isDirectory()) {
|
"../angular.min.js",
|
||||||
walk(currentPath, array, blackList);
|
"docs-combined.js",
|
||||||
}
|
"docs-keywords.js",
|
||||||
else {
|
"docs-combined.css",
|
||||||
array.push(currentPath.replace('build/docs/',''));
|
"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');
|
||||||
}
|
}
|
||||||
|
|
@ -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;
|
|
||||||
|
|
@ -3,90 +3,77 @@ require.paths.push('lib');
|
||||||
var reader = require('reader.js'),
|
var reader = require('reader.js'),
|
||||||
ngdoc = require('ngdoc.js'),
|
ngdoc = require('ngdoc.js'),
|
||||||
writer = require('writer.js'),
|
writer = require('writer.js'),
|
||||||
callback = require('callback.js'),
|
|
||||||
SiteMap = require('SiteMap.js').SiteMap,
|
SiteMap = require('SiteMap.js').SiteMap,
|
||||||
appCache = require('appCache.js');
|
appCache = require('appCache.js').appCache,
|
||||||
|
Q = require('qq');
|
||||||
|
|
||||||
var docs = [];
|
process.on('uncaughtException', function (err) {
|
||||||
var start;
|
console.error(err.stack || err);
|
||||||
var work = callback.chain(function(){
|
});
|
||||||
start = now();
|
|
||||||
|
var start = now();
|
||||||
|
var docs;
|
||||||
|
|
||||||
|
writer.makeDir('build/docs/syntaxhighlighter').then(function() {
|
||||||
console.log('Generating Angular Reference Documentation...');
|
console.log('Generating Angular Reference Documentation...');
|
||||||
reader.collect(work.waitMany(function(text, file, line){
|
return reader.collect();
|
||||||
var doc = new ngdoc.Doc(text, file, line);
|
}).then(function generateHtmlDocPartials(docs_) {
|
||||||
docs.push(doc);
|
docs = docs_;
|
||||||
doc.parse();
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
var writes = callback.chain(function(){
|
|
||||||
ngdoc.merge(docs);
|
ngdoc.merge(docs);
|
||||||
|
var fileFutures = [];
|
||||||
docs.forEach(function(doc){
|
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()));
|
||||||
});
|
});
|
||||||
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 -->', '<script src=\"jquery.min.js\"><\/script>');
|
|
||||||
writer.copyTpl('offline.html', writes.waitFor());
|
|
||||||
//writer.output('app-cache.manifest',
|
|
||||||
// appCacheTemplate().replace(/%TIMESTAMP%/, (new Date()).toISOString()),
|
|
||||||
// writes.waitFor());
|
|
||||||
writer.merge(['docs.js',
|
|
||||||
'doc_widgets.js'],
|
|
||||||
'docs-combined.js',
|
|
||||||
writes.waitFor());
|
|
||||||
writer.merge(['docs.css',
|
|
||||||
'doc_widgets.css'],
|
|
||||||
'docs-combined.css',
|
|
||||||
writes.waitFor());
|
|
||||||
writer.copyTpl('docs-scenario.html', writes.waitFor());
|
|
||||||
writer.output('docs-scenario.js', ngdoc.scenarios(docs), writes.waitFor());
|
|
||||||
writer.output('sitemap.xml', new SiteMap(docs).render(), writes.waitFor());
|
|
||||||
writer.output('robots.txt', 'Sitemap: http://docs.angularjs.org/sitemap.xml\n', writes.waitFor());
|
|
||||||
writer.merge(['syntaxhighlighter/shCore.js',
|
|
||||||
'syntaxhighlighter/shBrushJScript.js',
|
|
||||||
'syntaxhighlighter/shBrushXml.js'],
|
|
||||||
'syntaxhighlighter/syntaxhighlighter-combined.js',
|
|
||||||
writes.waitFor());
|
|
||||||
writer.merge(['syntaxhighlighter/shCore.css',
|
|
||||||
'syntaxhighlighter/shThemeDefault.css'],
|
|
||||||
'syntaxhighlighter/syntaxhighlighter-combined.css',
|
|
||||||
writes.waitFor());
|
|
||||||
writer.copyTpl('jquery.min.js', writes.waitFor());
|
|
||||||
writer.output('app-cache.manifest', appCache('build/docs/'), writes.waitFor());
|
|
||||||
});
|
|
||||||
writes.onDone(function(){
|
|
||||||
console.log('DONE. Generated ' + docs.length + ' pages in ' +
|
|
||||||
(now()-start) + 'ms.' );
|
|
||||||
});
|
|
||||||
work.onDone(writes);
|
|
||||||
writer.makeDir('build/docs/syntaxhighlighter', work);
|
|
||||||
|
|
||||||
///////////////////////////////////
|
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);
|
||||||
|
|
||||||
|
writesFuture.push(writer.copyDir('img'));
|
||||||
|
writesFuture.push(writer.copyDir('examples'));
|
||||||
|
writesFuture.push(writer.copyTpl('index.html'));
|
||||||
|
writesFuture.push(writer.copy('docs/src/templates/index.html',
|
||||||
|
'build/docs/index-jq.html',
|
||||||
|
'<!-- jquery place holder -->',
|
||||||
|
'<script src=\"jquery.min.js\"><\/script>'));
|
||||||
|
writesFuture.push(writer.copyTpl('offline.html'));
|
||||||
|
writesFuture.push(writer.copyTpl('docs-scenario.html'));
|
||||||
|
writesFuture.push(writer.copyTpl('jquery.min.js'));
|
||||||
|
|
||||||
|
writesFuture.push(writer.output('docs-keywords.js',
|
||||||
|
['NG_PAGES=', JSON.stringify(metadata).replace(/{/g, '\n{'), ';']));
|
||||||
|
writesFuture.push(writer.output('sitemap.xml', new SiteMap(docs).render()));
|
||||||
|
writesFuture.push(writer.output('docs-scenario.js', ngdoc.scenarios(docs)));
|
||||||
|
writesFuture.push(writer.output('robots.txt', 'Sitemap: http://docs.angularjs.org/sitemap.xml\n'));
|
||||||
|
writesFuture.push(writer.output('appcache.manifest',appCache()));
|
||||||
|
|
||||||
|
writesFuture.push(writer.merge(['docs.js',
|
||||||
|
'doc_widgets.js'],
|
||||||
|
'docs-combined.js'));
|
||||||
|
writesFuture.push(writer.merge(['docs.css',
|
||||||
|
'doc_widgets.css'],
|
||||||
|
'docs-combined.css'));
|
||||||
|
writesFuture.push(writer.merge(['syntaxhighlighter/shCore.js',
|
||||||
|
'syntaxhighlighter/shBrushJScript.js',
|
||||||
|
'syntaxhighlighter/shBrushXml.js'],
|
||||||
|
'syntaxhighlighter/syntaxhighlighter-combined.js'));
|
||||||
|
writesFuture.push(writer.merge(['syntaxhighlighter/shCore.css',
|
||||||
|
'syntaxhighlighter/shThemeDefault.css'],
|
||||||
|
'syntaxhighlighter/syntaxhighlighter-combined.css'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function now(){ return new Date().getTime(); }
|
function now(){ return new Date().getTime(); }
|
||||||
|
|
||||||
|
function noop(){};
|
||||||
function appCacheTemplate() {
|
|
||||||
return ["CACHE MANIFEST",
|
|
||||||
"# %TIMESTAMP%",
|
|
||||||
"",
|
|
||||||
"# 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",
|
|
||||||
"",
|
|
||||||
"FALLBACK:",
|
|
||||||
"/ offline.html",
|
|
||||||
"",
|
|
||||||
"# allow access to google analytics and twitter when we are online",
|
|
||||||
"NETWORK:",
|
|
||||||
"*"].join('\n');
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,98 +2,98 @@
|
||||||
* All reading related code here. This is so that we can separate the async code from sync code
|
* All reading related code here. This is so that we can separate the async code from sync code
|
||||||
* for testability
|
* for testability
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
exports.collect = collect;
|
||||||
|
|
||||||
require.paths.push(__dirname);
|
require.paths.push(__dirname);
|
||||||
var fs = require('fs'),
|
var ngdoc = require('ngdoc.js'),
|
||||||
callback = require('callback');
|
Q = require('qq'),
|
||||||
|
qfs = require('q-fs');
|
||||||
|
|
||||||
var NEW_LINE = /\n\r?/;
|
var NEW_LINE = /\n\r?/;
|
||||||
|
|
||||||
function collect(callback){
|
function collect() {
|
||||||
findJsFiles('src', callback.waitMany(function(file) {
|
var allDocs = [];
|
||||||
console.log('reading', file, '...');
|
|
||||||
findNgDocInJsFile(file, callback.waitMany(function(doc, line) {
|
|
||||||
callback('@section api\n' + doc, file, line);
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
findNgDocInDir('docs/content', callback.waitMany(callback));
|
|
||||||
callback.done();
|
|
||||||
}
|
|
||||||
|
|
||||||
function findJsFiles(dir, callback){
|
//collect docs in JS Files
|
||||||
fs.readdir(dir, callback.waitFor(function(err, files){
|
var path = 'src';
|
||||||
if (err) return this.error(err);
|
var promiseA = Q.when(qfs.listTree(path), function(files) {
|
||||||
files.forEach(function(file){
|
var done;
|
||||||
var path = dir + '/' + file;
|
//read all files in parallel.
|
||||||
fs.lstat(path, callback.waitFor(function(err, stat){
|
files.forEach(function(file) {
|
||||||
if (err) return this.error(err);
|
var work;
|
||||||
if (stat.isDirectory())
|
if(/\.js$/.test(file)) {
|
||||||
findJsFiles(path, callback.waitMany(callback));
|
console.log("reading " + file + ".......");
|
||||||
else if (/\.js$/.test(path))
|
work = Q.when(qfs.read(file), function(content) {
|
||||||
callback(path);
|
processJsFile(content, file).forEach (function(doc) {
|
||||||
}));
|
allDocs.push(doc);
|
||||||
});
|
});
|
||||||
callback.done();
|
});
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNgDocInDir(directory, docNotify) {
|
|
||||||
fs.readdir(directory, docNotify.waitFor(function(err, files){
|
|
||||||
if (err) return this.error(err);
|
|
||||||
files.forEach(function(file){
|
|
||||||
fs.stat(directory + '/' + file, docNotify.waitFor(function(err, stats){
|
|
||||||
if (err) return this.error(err);
|
|
||||||
if (stats.isFile()) {
|
|
||||||
if (!file.match(/\.ngdoc$/)) return;
|
|
||||||
console.log('reading', directory + '/' + file, '...');
|
|
||||||
fs.readFile(directory + '/' + file, docNotify.waitFor(function(err, content){
|
|
||||||
if (err) return this.error(err);
|
|
||||||
var section = '@section ' + directory.split('/').pop() + '\n';
|
|
||||||
docNotify(section + content.toString(), directory + '/' +file, 1);
|
|
||||||
}));
|
|
||||||
} else if(stats.isDirectory()) {
|
|
||||||
findNgDocInDir(directory + '/' + file, docNotify.waitFor(docNotify));
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
docNotify.done();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function findNgDocInJsFile(file, callback) {
|
|
||||||
fs.readFile(file, callback.waitFor(function(err, content){
|
|
||||||
var lines = content.toString().split(NEW_LINE);
|
|
||||||
var text;
|
|
||||||
var startingLine ;
|
|
||||||
var match;
|
|
||||||
var inDoc = false;
|
|
||||||
lines.forEach(function(line, lineNumber){
|
|
||||||
lineNumber++;
|
|
||||||
// is the comment starting?
|
|
||||||
if (!inDoc && (match = line.match(/^\s*\/\*\*\s*(.*)$/))) {
|
|
||||||
line = match[1];
|
|
||||||
inDoc = true;
|
|
||||||
text = [];
|
|
||||||
startingLine = lineNumber;
|
|
||||||
}
|
|
||||||
// are we done?
|
|
||||||
if (inDoc && line.match(/\*\//)) {
|
|
||||||
text = text.join('\n');
|
|
||||||
text = text.replace(/^\n/, '');
|
|
||||||
if (text.match(/@ngdoc/)){
|
|
||||||
callback(text, startingLine);
|
|
||||||
}
|
|
||||||
doc = null;
|
|
||||||
inDoc = false;
|
|
||||||
}
|
|
||||||
// is the comment add text
|
|
||||||
if (inDoc){
|
|
||||||
text.push(line.replace(/^\s*\*\s?/, ''));
|
|
||||||
}
|
}
|
||||||
|
done = Q.when(done, function() {
|
||||||
|
return work;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
callback.done();
|
return done;
|
||||||
}));
|
});
|
||||||
|
|
||||||
|
//collect all NG Docs in Content Folder
|
||||||
|
var path2 = 'docs/content';
|
||||||
|
var promiseB = Q.when(qfs.listTree(path2), function(files){
|
||||||
|
var done2;
|
||||||
|
files.forEach(function(file) {
|
||||||
|
var work2;
|
||||||
|
if (file.match(/\.ngdoc$/)) {
|
||||||
|
console.log("reading " + file + ".......");
|
||||||
|
work2 = Q.when(qfs.read(file), function(content){
|
||||||
|
var section = '@section ' + file.split('/')[2] + '\n';
|
||||||
|
allDocs.push(new ngdoc.Doc(section + content.toString(),file, 1).parse());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
done2 = Q.when(done2, function() {
|
||||||
|
return work2;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return done2;
|
||||||
|
});
|
||||||
|
|
||||||
|
return Q.join(promiseA, promiseB, function() {
|
||||||
|
return allDocs;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function processJsFile(content, file) {
|
||||||
|
var docs = [];
|
||||||
|
var lines = content.toString().split(NEW_LINE);
|
||||||
|
var text;
|
||||||
|
var startingLine ;
|
||||||
|
var match;
|
||||||
|
var inDoc = false;
|
||||||
|
|
||||||
|
lines.forEach(function(line, lineNumber){
|
||||||
exports.collect = collect;
|
lineNumber++;
|
||||||
|
// is the comment starting?
|
||||||
|
if (!inDoc && (match = line.match(/^\s*\/\*\*\s*(.*)$/))) {
|
||||||
|
line = match[1];
|
||||||
|
inDoc = true;
|
||||||
|
text = [];
|
||||||
|
startingLine = lineNumber;
|
||||||
|
}
|
||||||
|
// are we done?
|
||||||
|
if (inDoc && line.match(/\*\//)) {
|
||||||
|
text = text.join('\n');
|
||||||
|
text = text.replace(/^\n/, '');
|
||||||
|
if (text.match(/@ngdoc/)){
|
||||||
|
//console.log(file, startingLine)
|
||||||
|
docs.push(new ngdoc.Doc('@section api\n' + text, file, startingLine).parse());
|
||||||
|
}
|
||||||
|
doc = null;
|
||||||
|
inDoc = false;
|
||||||
|
}
|
||||||
|
// is the comment add text
|
||||||
|
if (inDoc){
|
||||||
|
text.push(line.replace(/^\s*\*\s?/, ''));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<html xmlns:ng="http://angularjs.org/"
|
<html xmlns:ng="http://angularjs.org/"
|
||||||
xmlns:doc="http://docs.angularjs.org/"
|
xmlns:doc="http://docs.angularjs.org/"
|
||||||
ng:controller="DocsController"
|
ng:controller="DocsController"
|
||||||
manifest="app-cache.manifest">
|
manifest="appcache.manifest">
|
||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||||
<title ng:bind-template="AngularJS: {{partialTitle}}">AngularJS</title>
|
<title ng:bind-template="AngularJS: {{partialTitle}}">AngularJS</title>
|
||||||
|
|
@ -76,7 +76,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="syntaxhighlighter/syntaxhighlighter-combined.js"></script>
|
<script src="syntaxhighlighter/syntaxhighlighter-combined.js"></script>
|
||||||
<-- jquery place holder -->
|
<!-- jquery place holder -->
|
||||||
<script src="../angular.min.js" ng:autobind></script>
|
<script src="../angular.min.js" ng:autobind></script>
|
||||||
<script src="docs-combined.js"></script>
|
<script src="docs-combined.js"></script>
|
||||||
<script src="docs-keywords.js"></script>
|
<script src="docs-keywords.js"></script>
|
||||||
|
|
|
||||||
|
|
@ -3,37 +3,113 @@
|
||||||
* for testability
|
* for testability
|
||||||
*/
|
*/
|
||||||
require.paths.push(__dirname);
|
require.paths.push(__dirname);
|
||||||
var fs = require('fs');
|
var qfs = require('q-fs');
|
||||||
|
var Q = require('qq');
|
||||||
var OUTPUT_DIR = "build/docs/";
|
var OUTPUT_DIR = "build/docs/";
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
function output(docs, content, callback){
|
exports.output = function(file, content){
|
||||||
callback();
|
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) {
|
function parent(file) {
|
||||||
var parts = file.split('/');
|
var parts = file.split('/');
|
||||||
parts.pop();
|
parts.pop();
|
||||||
return parts.join('/');
|
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) {
|
switch (typeof obj) {
|
||||||
case 'string':
|
case 'string':
|
||||||
return obj;
|
return obj;
|
||||||
case 'object':
|
case 'object':
|
||||||
if (obj instanceof Array) {
|
if (obj instanceof Array) {
|
||||||
obj.forEach(function (value, key){
|
obj.forEach(function (value, key) {
|
||||||
obj[key] = toString(value);
|
obj[key] = toString(value);
|
||||||
});
|
});
|
||||||
return obj.join('');
|
return obj.join('');
|
||||||
|
|
@ -44,64 +120,5 @@ exports.toString = function toString(obj){
|
||||||
return 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) {
|
function noop(){};
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue