org.eclipse.wst.jsdt.core.jsNature
diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope
index 7beec24e..a8f1ce8f 100644
--- a/.settings/.jsdtscope
+++ b/.settings/.jsdtscope
@@ -1,9 +1,11 @@
+
+
diff --git a/Rakefile b/Rakefile
index a83b53ad..9a9835ba 100644
--- a/Rakefile
+++ b/Rakefile
@@ -156,8 +156,14 @@ task :compile => [:init, :compile_scenario, :generate_ie_compat] do
end
+desc 'Generate docs'
+task :docs do
+ `node docs/collect.js`
+end
+
+
desc 'Create angular distribution'
-task :package => [:clean, :compile] do
+task :package => [:clean, :compile, :docs] do
v = YAML::load( File.open( 'version.yaml' ) )['version']
match = v.match(/^([^-]*)(-snapshot)?$/)
version = match[1] + (match[2] ? ('-' + %x(git rev-parse HEAD)[0..7]) : '')
@@ -178,6 +184,20 @@ task :package => [:clean, :compile] do
FileUtils.cp(src, pkg_dir + '/' + dest)
end
+ FileUtils.cp_r path_to('docs'), "#{pkg_dir}/docs-#{version}"
+
+ File.open("#{pkg_dir}/docs-#{version}/index.html", File::RDWR) do |f|
+ text = f.read
+ f.rewind
+ f.write text.sub('angular.min.js', "angular-#{version}.min.js")
+ end
+
+ File.open("#{pkg_dir}/docs-#{version}/docs-scenario.html", File::RDWR) do |f|
+ text = f.read
+ f.rewind
+ f.write text.sub('angular-scenario.js', "angular-scenario-#{version}.js")
+ end
+
%x(tar -czf #{path_to(tarball)} -C #{path_to('pkg')} .)
puts "Package created: #{path_to(tarball)}"
@@ -256,5 +276,5 @@ end
# returns path to the file in the build directory
#
def path_to(filename)
- return File.join(BUILD_DIR, filename)
+ return File.join(BUILD_DIR, *filename)
end
diff --git a/docs/callback.js b/docs/callback.js
new file mode 100644
index 00000000..0d0669d1
--- /dev/null
+++ b/docs/callback.js
@@ -0,0 +1,66 @@
+function noop(){}
+
+function chain(delegateFn, explicitDone){
+ var onDoneFn = noop;
+ var onErrorFn = noop;
+ 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/collect.js b/docs/collect.js
new file mode 100644
index 00000000..a3c2a25c
--- /dev/null
+++ b/docs/collect.js
@@ -0,0 +1,206 @@
+var fs = require('fs'),
+ spawn = require('child_process').spawn,
+ mustache = require('../lib/mustache'),
+ callback = require('./callback'),
+ markdown = require('../lib/markdown');
+
+var documentation = {
+ section:{},
+ all:[]
+};
+
+var SRC_DIR = "docs/";
+var OUTPUT_DIR = "build/docs/";
+
+var work = callback.chain(function () {
+ console.log('Parsing Angular Reference Documentation');
+ mkdirPath(OUTPUT_DIR, work.waitFor(function(){
+ findJsFiles('src', work.waitMany(function(file) {
+ //console.log('reading', file, '...');
+ findNgDoc(file, work.waitMany(function(doc) {
+ parseNgDoc(doc);
+ if (doc.ngdoc) {
+ delete doc.raw.text;
+ var section = documentation.section;
+ (section[doc.ngdoc] = section[doc.ngdoc] || []).push(doc);
+ documentation.all.push(doc);
+ console.log('Found:', doc.ngdoc + ':' + doc.shortName);
+ mergeTemplate(
+ doc.ngdoc + '.template',
+ doc.name + '.html', doc, work.waitFor());
+ }
+ }));
+ }));
+ }));
+}).onError(function(err){
+ console.log('ERROR:', err.stack || err);
+}).onDone(function(){
+ mergeTemplate('docs-data.js', 'docs-data.js', {JSON:JSON.stringify(documentation)}, callback.chain());
+ mergeTemplate('docs-scenario.js', 'docs-scenario.js', documentation, callback.chain());
+ copy('docs-scenario.html', callback.chain());
+ copy('index.html', callback.chain());
+ mergeTemplate('docs.js', 'docs.js', documentation, callback.chain());
+ mergeTemplate('wiki_widgets.css', 'wiki_widgets.css', documentation, callback.chain());
+ mergeTemplate('wiki_widgets.js', 'wiki_widgets.js', documentation, callback.chain());
+ console.log('DONE');
+});
+work();
+////////////////////
+
+function noop(){}
+function mkdirPath(path, callback) {
+ var parts = path.split(/\//);
+ path = '.';
+ (function next(){
+ if (parts.length) {
+ path += '/' + parts.shift();
+ fs.mkdir(path, 0777, next);
+ } else {
+ callback();
+ }
+ })();
+}
+
+function copy(name, callback){
+ fs.readFile(SRC_DIR + name, callback.waitFor(function(err, content){
+ if (err) return this.error(err);
+ fs.writeFile(OUTPUT_DIR + name, content, callback);
+ }));
+}
+
+function mergeTemplate(template, output, doc, callback){
+ fs.readFile(SRC_DIR + template,
+ callback.waitFor(function(err, template){
+ if (err) return this.error(err);
+ var content = mustache.to_html(template.toString(), doc);
+ fs.writeFile(OUTPUT_DIR + output, content, callback);
+ }));
+}
+
+
+function unknownTag(doc, name) {
+ var error = "[" + doc.raw.file + ":" + doc.raw.line + "]: unknown tag: " + name;
+ console.log(error);
+ throw new Error(error);
+}
+
+function valueTag(doc, name, value) {
+ doc[name] = value;
+}
+
+function markdownTag(doc, name, value) {
+ doc[name] = markdown.toHTML(value);
+}
+
+var TAG = {
+ ngdoc: valueTag,
+ example: valueTag,
+ scenario: valueTag,
+ namespace: valueTag,
+ css: valueTag,
+ see: valueTag,
+ 'function': valueTag,
+ description: markdownTag,
+ returns: markdownTag,
+ name: function(doc, name, value) {
+ doc.name = value;
+ doc.shortName = value.split(/\./).pop();
+ },
+ param: function(doc, name, value){
+ doc.param = doc.param || [];
+ doc.paramRest = doc.paramRest || [];
+ var match = value.match(/^({([^\s=]+)(=([^\s]+))?}\s*)?([^\s]+)\s*(.*)/);
+ if (match) {
+ var param = {
+ type: match[2],
+ 'default':match[4],
+ name: match[5],
+ description:match[6]};
+ doc.param.push(param);
+ if (!doc.paramFirst) {
+ doc.paramFirst = param;
+ } else {
+ doc.paramRest.push(param);
+ }
+ } else {
+ throw "[" + doc.raw.file + ":" + doc.raw.line +
+ "]: @param must be in format '{type} name=value description' got: " + value;
+ }
+ }
+};
+
+function parseNgDoc(doc){
+ var atName;
+ var atText;
+ var match;
+ doc.raw.text.split(/\n/).forEach(function(line, lineNumber){
+ if (match = line.match(/^@(\w+)(\s+(.*))?/)) {
+ // we found @name ...
+ // if we have existing name
+ if (atName) {
+ (TAG[atName] || unknownTag)(doc, atName, atText.join('\n'));
+ }
+ atName = match[1];
+ atText = [];
+ if(match[3]) atText.push(match[3]);
+ } else {
+ if (atName) {
+ atText.push(line);
+ } else {
+ // ignore
+ }
+ }
+ });
+ if (atName) {
+ (TAG[atName] || unknownTag)(doc, atName, atText.join('\n'));
+ }
+}
+
+function findNgDoc(file, callback) {
+ fs.readFile(file, callback.waitFor(function(err, content){
+ var lines = content.toString().split(/\n\r?/);
+ var doc;
+ 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;
+ doc = {raw:{file:file, line:lineNumber, text:[]}};
+ }
+ // are we done?
+ if (inDoc && line.match(/\*\//)) {
+ doc.raw.text = doc.raw.text.join('\n');
+ doc.raw.text = doc.raw.text.replace(/^\n/, '');
+ if (doc.raw.text.match(/@ngdoc/))
+ callback(doc);
+ doc = null;
+ inDoc = false;
+ }
+ // is the comment add text
+ if (inDoc){
+ doc.raw.text.push(line.replace(/^\s*\*\s?/, ''));
+ }
+ });
+ callback.done();
+ }));
+}
+
+function findJsFiles(dir, callback){
+ fs.readdir(dir, callback.waitFor(function(err, files){
+ if (err) return this.error(err);
+ files.forEach(function(file){
+ var path = dir + '/' + file;
+ fs.lstat(path, callback.waitFor(function(err, stat){
+ if (err) return this.error(err);
+ if (stat.isDirectory())
+ findJsFiles(path, callback.waitMany(callback));
+ else if (/\.js$/.test(path))
+ callback(path);
+ }));
+ });
+ callback.done();
+ }));
+}
diff --git a/docs/docs-data.js b/docs/docs-data.js
new file mode 100644
index 00000000..27b3fab5
--- /dev/null
+++ b/docs/docs-data.js
@@ -0,0 +1 @@
+NG_DOC={{{JSON}}};
\ No newline at end of file
diff --git a/docs/docs-scenario.html b/docs/docs-scenario.html
new file mode 100644
index 00000000..83ca6fdf
--- /dev/null
+++ b/docs/docs-scenario.html
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/docs-scenario.js b/docs/docs-scenario.js
new file mode 100644
index 00000000..f0c6edb9
--- /dev/null
+++ b/docs/docs-scenario.js
@@ -0,0 +1,9 @@
+{{#all}}
+describe('{{name}}', function(){
+ beforeEach(function(){
+ navigateTo('index.html#{{name}}');
+ });
+ // {{raw.file}}:{{raw.line}}
+{{{scenario}}}
+});
+{{/all}}
\ No newline at end of file
diff --git a/docs/docs.js b/docs/docs.js
new file mode 100644
index 00000000..6f5c5034
--- /dev/null
+++ b/docs/docs.js
@@ -0,0 +1,7 @@
+function DocController($resource, $location){
+ this.docs = $resource('documentation.json').get();
+ this.getPartialDoc = function(){
+ return encodeURIComponent($location.hashPath) + '.html';
+ };
+}
+DocController.$inject=['$resource', '$location'];
\ No newline at end of file
diff --git a/docs/filter.template b/docs/filter.template
new file mode 100644
index 00000000..677a8785
--- /dev/null
+++ b/docs/filter.template
@@ -0,0 +1,33 @@
+{{name}}
+Usage
+In HTML Template Binding
+
+ {{
+ {{paramFirst.name}}_expression
+ | {{shortName}}{{#paramRest}}{{^default}}:{{name}}{{/default}}{{#default}}[:{{name}}={{default}}]{{/default}}{{/paramRest}}
+ }}
+
+In JavaScript
+
+angular.filter.{{shortName}}({{paramFirst.name}}{{#paramRest}}, {{name}}{{/paramRest}} );
+
+
+Parameters
+
+ {{#param}}
+ - {{name}}{{#type}}({{type}}){{/type}}: {{description}}
+ {{/param}}
+
+
+Returns
+{{{returns}}}
+
+CSS
+{{{css}}}
+
+Description
+{{{description}}}
+
+
+{{example}}
+
\ No newline at end of file
diff --git a/docs/filter:currency.html b/docs/filter:currency.html
deleted file mode 100644
index bd277bb8..00000000
--- a/docs/filter:currency.html
+++ /dev/null
@@ -1,21 +0,0 @@
-filter:currency
-
-formats a number as a currency (ie $1,234.56)
-
-@format expression | currency
-
-
-
-{{amount | currency}}
-
-
-
- it('should init with 1234.56', function(){
- expect(bind('amount')).toEqual('$1,234.56');
- });
- it('should update', function(){
- element(':input[name=amount]').value('-1234');
- expect(bind('amount')).toEqual('-$1,234.00');
- expect(bind('amount')).toHaveColor('red');
- });
-
diff --git a/docs/filter:currency.md b/docs/filter:currency.md
deleted file mode 100644
index 44687a91..00000000
--- a/docs/filter:currency.md
+++ /dev/null
@@ -1,20 +0,0 @@
-# filter:currency
-formats a number as a currency (ie $1,234.56)
-
-@format _expression_ | currency
-
-
-
-{{amount | currency}}
-
-
-
- it('should init with 1234.56', function(){
- expect(bind('amount')).toEqual('$1,234.56');
- });
- it('should update', function(){
- element(':input[name=amount]').value('-1234');
- expect(bind('amount')).toEqual('-$1,234.00');
- expect(bind('amount')).toHaveColor('red');
- });
-
\ No newline at end of file
diff --git a/docs/index.html b/docs/index.html
new file mode 100644
index 00000000..f61893a4
--- /dev/null
+++ b/docs/index.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/overview.template b/docs/overview.template
new file mode 100644
index 00000000..dbb91e2a
--- /dev/null
+++ b/docs/overview.template
@@ -0,0 +1 @@
+{{{description}}}
\ No newline at end of file
diff --git a/docs/wiki_widgets.css b/docs/wiki_widgets.css
new file mode 100644
index 00000000..a1f6e939
--- /dev/null
+++ b/docs/wiki_widgets.css
@@ -0,0 +1,58 @@
+WIKI\:SOURCE,
+WIKI\:SOURCE>ul.tabs,
+WIKI\:SOURCE>ul.tabs>li {
+ display: block;
+ margin: 0;
+ padding: 0;
+}
+WIKI\:SOURCE>ul.tabs {
+ margin: 0 !important;
+ padding: 0 !important;
+}
+
+WIKI\:SOURCE > ul.tabs > li.tab {
+ margin: 0 0 0 .8em !important;
+ display: inline-block;
+ border: 1px solid gray;
+ padding: .1em .8em .4em .8em !important;
+ -moz-border-radius-topleft: 5px;
+ -moz-border-radius-topright: 5px;
+ -webkit-border-top-left-radius: 5px;
+ -webkit-border-top-right-radius: 5px;
+ border-bottom: none;
+ cursor: pointer;
+ background-color: lightgray;
+ margin-bottom: -2px;
+ position: relative;
+ z-index: 0;
+}
+
+WIKI\:SOURCE > ul.tabs > li.tab.selected {
+ z-index: 2;
+ background-color: white;
+ font-weight: bold;
+ border-width: 2px;
+}
+
+WIKI\:SOURCE > ul.tabs > li.pane {
+ border: 2px solid gray;
+ border-radius: 5px;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+ background-color: white;
+ padding: 5px !important;
+}
+
+WIKI\:SOURCE > ul.tabs > li.pane {
+ display:none;
+}
+
+WIKI\:SOURCE > ul.tabs > li.pane.selected {
+ position: relative;
+ z-index: 1;
+ display:block;
+}
+WIKI\:SOURCE > ul.tabs > li.pane.source {
+ font-size: .8em !important;
+}
+//////////////////
\ No newline at end of file
diff --git a/docs/wiki_widgets.js b/docs/wiki_widgets.js
new file mode 100644
index 00000000..0147536b
--- /dev/null
+++ b/docs/wiki_widgets.js
@@ -0,0 +1,51 @@
+(function(){
+ var HTML_TEMPLATE =
+ '\n' +
+ '\n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ ' \n' +
+ '_HTML_SOURCE_\n' +
+ ' \n' +
+ '';
+
+ angular.widget('WIKI:SOURCE', function(element){
+ this.descend(true);
+ var html = element.text();
+ element.show();
+ var tabs = angular.element(
+ '' +
+ '- <angular/>
' +
+ '- plain
' +
+ '- source
' +
+ '- ' + html + '
' +
+ '- ' + html + '
' +
+ ' ' +
+ '
');
+ var pre = tabs.
+ find('>li.source>pre').
+ text(HTML_TEMPLATE.replace('_HTML_SOURCE_', html));
+ var color = element.attr('color') || 'white';
+ element.html('');
+ element.append(tabs);
+ element.find('>ul.tabs>li.pane').css('background-color', color);
+ var script = (html.match(/