aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorMisko Hevery2010-10-27 15:31:10 -0700
committerIgor Minar2010-11-03 09:47:22 -0700
commit659af29adbd041fbbbaf041ead53266210a61f4e (patch)
tree32a9ecff4482ae883321e2975fe74057795b21d1 /docs
parent1fe7e3a1302e948a31ab80d02ede6975c3bddd58 (diff)
downloadangular.js-659af29adbd041fbbbaf041ead53266210a61f4e.tar.bz2
jsdoc parser + generator + viewer + scenario runner
- parse jsdocs from source code - generate prerendered (markdown + mustache) partials - generate json - generate scenario runner for examples in docs - basic angular doc viewer
Diffstat (limited to 'docs')
-rw-r--r--docs/callback.js66
-rw-r--r--docs/collect.js206
-rw-r--r--docs/docs-data.js1
-rw-r--r--docs/docs-scenario.html9
-rw-r--r--docs/docs-scenario.js9
-rw-r--r--docs/docs.js7
-rw-r--r--docs/filter.template33
-rw-r--r--docs/filter:currency.html21
-rw-r--r--docs/filter:currency.md20
-rw-r--r--docs/index.html25
-rw-r--r--docs/overview.template1
-rw-r--r--docs/wiki_widgets.css58
-rw-r--r--docs/wiki_widgets.js51
13 files changed, 466 insertions, 41 deletions
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 @@
+<!DOCTYPE HTML>
+<html xmlns:ng="http://angularjs.org" wiki:ng="http://angularjs.org">
+<head>
+ <script type="text/javascript" src="../angular-scenario.js" ng:autobind></script>
+ <script type="text/javascript" src="docs-scenario.js"></script>
+</head>
+<body>
+</body>
+</html> \ 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 @@
+<h1><tt>{{name}}</tt></h1>
+<h2>Usage</h2>
+<h3>In HTML Template Binding</h3>
+<tt>
+ <span>{{</span>
+ {{paramFirst.name}}_expression
+ | {{shortName}}{{#paramRest}}{{^default}}:{{name}}{{/default}}{{#default}}<i>[:{{name}}={{default}}]</i>{{/default}}{{/paramRest}}
+ <span> }}</span>
+</tt>
+<h3>In JavaScript</h3>
+<tt ng:non-bindable>
+angular.filter.{{shortName}}({{paramFirst.name}}{{#paramRest}}, {{name}}{{/paramRest}} );
+</tt>
+
+<h3>Parameters</h3>
+<ul>
+ {{#param}}
+ <li><tt>{{name}}{{#type}}({{type}}){{/type}}</tt>: {{description}}</li>
+ {{/param}}
+</ul>
+
+<h3>Returns</h3>
+{{{returns}}}
+
+<h3>CSS</h3>
+{{{css}}}
+
+<h2>Description</h2>
+{{{description}}}
+
+<WIKI:SOURCE style="display:block;">
+{{example}}
+</WIKI:SOURCE> \ 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 @@
-<h1>filter:currency</h1>
-
-<p>formats a number as a currency (ie $1,234.56)</p>
-
-<p>@format <em>expression</em> | currency</p>
-
-<p><example>
-<input type="text" name="amount" value="1234.56"/> <br/>
-{{amount | currency}}
-</example></p>
-
-<p><test>
- 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');
- });
-</test></p>
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
-
-<example>
-<input type="text" name="amount" value="1234.56"/> <br/>
-{{amount | currency}}
-</example>
-
-<test>
- 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');
- });
-</test> \ 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 @@
+<!DOCTYPE HTML>
+<html xmlns:ng="http://angularjs.org" wiki:ng="http://angularjs.org">
+<head>
+ <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
+ <script type="text/javascript" src="docs-data.js"></script>
+ <script type="text/javascript" src="../angular.min.js" ng:autobind></script>
+ <script type="text/javascript" src="http://angularjs.org/extensions/wiki_widgets.js"></script>
+ <link rel="stylesheet" href="http://angularjs.org/extensions/wiki_widgets.css" type="text/css" media="screen" />
+</head>
+<body ng:init="docs=$window.NG_DOC; $window.$root = $root">
+ <table>
+ <tr>
+ <td valign="top">
+ <div ng:repeat="(name, type) in docs.section">
+ <b>{{name}}</b>
+ <div ng:repeat="page in type">
+ <a href="#{{page.name}}"><tt>{{page.shortName}}</tt></a>
+ </div>
+ </div>
+ </td>
+ <td valign="top"><ng:include src="$location.hashPath + '.html' "></ng:include></td>
+ </tr>
+ </table>
+</body>
+</html> \ 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 =
+ '<!DOCTYPE HTML>\n' +
+ '<html xmlns:ng="http://angularjs.org">\n' +
+ ' <head>\n' +
+ ' <script type="text/javascript"\n' +
+ ' src="http://angularjs.org/ng/js/angular-debug.js" ng:autobind></script>\n' +
+ ' </head>\n' +
+ ' <body>\n' +
+ '_HTML_SOURCE_\n' +
+ ' </body>\n' +
+ '</html>';
+
+ angular.widget('WIKI:SOURCE', function(element){
+ this.descend(true);
+ var html = element.text();
+ element.show();
+ var tabs = angular.element(
+ '<ul class="tabs">' +
+ '<li class="tab selected" to="angular">&lt;angular/&gt;</li>' +
+ '<li class="tab" to="plain">plain</li>' +
+ '<li class="tab" to="source">source</li>' +
+ '<li class="pane selected angular">' + html + '</li>' +
+ '<li class="pane plain" ng:non-bindable>' + html + '</li>' +
+ '<li class="pane source" ng:non-bindable><pre class="brush: js; html-script: true"></pre></li>' +
+ '</ul>');
+ 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(/<script[^\>]*>([\s\S]*)<\/script>/) || [])[1] || '';
+ try {
+ eval(script);
+ } catch (e) {
+ alert(e);
+ }
+ return function(element){
+ element.find('>ul.tabs>li.tab').click(function(){
+ if ($(this).is(".selected")) return;
+ element.
+ find('>ul.tabs>li.selected').
+ add(this).
+ add(element.find('>ul>li.pane.' + angular.element(this).attr('to'))).
+ toggleClass('selected');
+ });
+ };
+ });
+})(); \ No newline at end of file