aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authorVojta Jina2010-11-15 01:10:16 +0000
committerMisko Hevery2010-11-15 21:55:37 -0800
commitcc749760fd59418433de5a055d1ca401f7500444 (patch)
treea6bc273b68b10515b9e00bc0b166c46d88748033 /docs
parentb467a50bc75b7f4c0d9bcee521387eda460337bf (diff)
downloadangular.js-cc749760fd59418433de5a055d1ca401f7500444.tar.bz2
Added basic Services, which support @memberOf and @methodOf
Diffstat (limited to 'docs')
-rw-r--r--docs/collect.js105
-rw-r--r--docs/docs.css5
-rw-r--r--docs/service.template37
-rw-r--r--docs/spec/collectSpec.js141
-rw-r--r--docs/specs.js2
5 files changed, 270 insertions, 20 deletions
diff --git a/docs/collect.js b/docs/collect.js
index 4e845f5b..7ad1630b 100644
--- a/docs/collect.js
+++ b/docs/collect.js
@@ -7,7 +7,8 @@ var fs = require('fs'),
Showdown = require('showdown').Showdown;
var documentation = {
- pages:[]
+ pages:[],
+ byName: {}
};
var keywordPages = [];
@@ -23,18 +24,7 @@ var work = callback.chain(function () {
//console.log('reading', file, '...');
findNgDoc(file, work.waitMany(function(doc) {
parseNgDoc(doc);
- if (doc.ngdoc) {
- keywordPages.push({
- name:doc.name,
- keywords:keywords(doc.raw.text)
- }
- );
- documentation.pages.push(doc);
- console.log('Found:', doc.ngdoc + ':' + doc.shortName);
- mergeTemplate(
- doc.ngdoc + '.template',
- doc.name + '.html', doc, work.waitFor());
- }
+ processNgDoc(documentation, doc);
}));
}));
}));
@@ -42,6 +32,7 @@ var work = callback.chain(function () {
console.log('ERROR:', err.stack || err);
}).onDone(function(){
keywordPages.sort(function(a,b){ return a.name == b.name ? 0:(a.name < b.name ? -1 : 1);});
+ writeDoc(documentation.pages);
mergeTemplate('docs-data.js', 'docs-data.js', {JSON:JSON.stringify(keywordPages)}, callback.chain());
mergeTemplate('docs-scenario.js', 'docs-scenario.js', documentation, callback.chain());
copy('docs-scenario.html', callback.chain());
@@ -156,11 +147,17 @@ function markdownTag(doc, name, value) {
}
function markdown(text) {
- text = text.replace(/<angular\/>/gm, '<tt>&lt;angular/&gt;</tt>');
- text = text.replace(/(angular\.[\w\._\-:]+)/gm, '<a href="#$1">$1</a>');
- text = text.replace(/(`(ng:[\w\._\-]+)`)/gm, '<a href="#angular.directive.$2">$1</a>');
- text = new Showdown.converter().makeHtml(text);
- return text;
+ var parts = text.split(/(<pre>[\s\S]*<\/pre>)/);
+ parts.forEach(function(text, i){
+ if (!text.match(/^<pre>/)) {
+ text = text.replace(/<angular\/>/gm, '<tt>&lt;angular/&gt;</tt>');
+ text = new Showdown.converter().makeHtml(text);
+ text = text.replace(/(angular\.[\$\w\._\-:]+)/gm, '<a href="#!$1">$1</a>');
+ text = text.replace(/(`(ng:[\w\._\-]+)`)/gm, '<a href="#!angular.directive.$2">$1</a>');
+ parts[i] = text;
+ }
+ });
+ return parts.join('');
}
function markdownNoP(text) {
@@ -171,6 +168,43 @@ function markdownNoP(text) {
return lines.join('\n');
}
+function requiresTag(doc, name, value) {
+ doc.requires = doc.requires || [];
+ doc.requires.push({name: value});
+}
+
+function propertyTag(doc, name, value) {
+ doc[name] = doc[name] || [];
+ var match = value.match(/^({(\S+)}\s*)?(\S+)(\s+(.*))?/);
+
+ if (match) {
+ var tag = {
+ type: match[2],
+ name: match[3],
+ description: match[5] || false
+ };
+ } else {
+ throw "[" + doc.raw.file + ":" + doc.raw.line +
+ "]: @" + name + " must be in format '{type} name description' got: " + value;
+ }
+ return doc[name].push(tag);
+}
+
+function returnsTag(doc, name, value) {
+ var match = value.match(/^({(\S+)}\s*)?(.*)?/);
+
+ if (match) {
+ var tag = {
+ type: match[2],
+ description: match[3] || false
+ };
+ } else {
+ throw "[" + doc.raw.file + ":" + doc.raw.line +
+ "]: @" + name + " must be in format '{type} description' got: " + value;
+ }
+ return doc[name] = tag;
+}
+
var TAG = {
ngdoc: valueTag,
example: escapedHtmlTag,
@@ -186,6 +220,7 @@ var TAG = {
paramDescription: markdownTag,
exampleDescription: markdownTag,
element: valueTag,
+ methodOf: valueTag,
name: function(doc, name, value) {
doc.name = value;
doc.shortName = value.split(/\./).pop();
@@ -212,7 +247,10 @@ var TAG = {
throw "[" + doc.raw.file + ":" + doc.raw.line +
"]: @param must be in format '{type} name=value description' got: " + value;
}
- }
+ },
+ property: propertyTag,
+ requires: requiresTag,
+ returns: returnsTag
};
function parseNgDoc(doc){
@@ -291,3 +329,32 @@ function findJsFiles(dir, callback){
callback.done();
}));
}
+
+function processNgDoc(documentation, doc) {
+ if (!doc.ngdoc) return;
+ console.log('Found:', doc.ngdoc + ':' + doc.name);
+
+ documentation.byName[doc.name] = doc;
+
+ if (doc.methodOf) {
+ if (parent = documentation.byName[doc.methodOf]) {
+ (parent.method = parent.method || []).push(doc);
+ } else {
+ throw 'Owner "' + doc.methodOf + '" is not defined.';
+ }
+ } else {
+ documentation.pages.push(doc);
+ keywordPages.push({
+ name:doc.name,
+ keywords:keywords(doc.raw.text)
+ });
+ }
+}
+
+function writeDoc(pages) {
+ pages.forEach(function(doc) {
+ mergeTemplate(
+ doc.ngdoc + '.template',
+ doc.name + '.html', doc, callback.chain());
+ });
+}
diff --git a/docs/docs.css b/docs/docs.css
index 25a8ffea..664328d0 100644
--- a/docs/docs.css
+++ b/docs/docs.css
@@ -125,3 +125,8 @@ a {
margin-left: 2em;
font-family: monospace;
}
+
+#sidebar ul li.level-3 {
+ margin-left: 3em;
+ font-family: monospace;
+}
diff --git a/docs/service.template b/docs/service.template
new file mode 100644
index 00000000..2774cad2
--- /dev/null
+++ b/docs/service.template
@@ -0,0 +1,37 @@
+<h1><tt>{{name}}</tt></h1>
+<h2>Description</h2>
+{{{description}}}
+
+<h2>Dependencies</h2>
+<ul>
+ {{#requires}}
+ <li><tt>{{name}}</tt></li>
+ {{/requires}}
+</ul>
+
+<h2>Methods</h2>
+<ul>
+ {{#method}}
+ <li><tt>{{shortName}}</tt>: {{{description}}}</li>
+ {{/method}}
+</ul>
+
+<h2>Properties</h2>
+<ul>
+ {{#property}}
+ <li><tt>{{name}}:{{#type}}{{type}}{{/type}}</tt>{{#description}}: {{{description}}}{{/description}}</li>
+ {{/property}}
+</ul>
+
+{{#example}}
+<h2>Example</h2>
+{{{exampleDescription}}}
+<doc:example>
+ <doc:source>
+{{/example}}
+ {{{example}}}
+{{#example}}
+ </doc:source>
+ {{#scenario}}<doc:scenario>{{{scenario}}}</doc:scenario>{{/scenario}}
+</doc:example>
+{{/example}} \ No newline at end of file
diff --git a/docs/spec/collectSpec.js b/docs/spec/collectSpec.js
index f20342b1..9de08dc8 100644
--- a/docs/spec/collectSpec.js
+++ b/docs/spec/collectSpec.js
@@ -11,6 +11,63 @@ describe('collect', function(){
expect(collect.markdown('<angular/>')).
toEqual('<p><tt>&lt;angular/&gt;</tt></p>');
});
+
+ it('should not replace anything in <pre>', function(){
+ expect(collect.markdown('angular.x\n<pre>\nangular.k\n</pre>\nangular.x')).
+ toEqual(
+ '<p><a href="#!angular.x">angular.x</a></p>' +
+ '<pre>\nangular.k\n</pre>' +
+ '<p><a href="#!angular.x">angular.x</a></p>');
+ });
+ });
+
+ describe('processNgDoc', function() {
+ var processNgDoc = collect.processNgDoc,
+ documentation;
+
+ beforeEach(function() {
+ documentation = {
+ pages: [],
+ byName: {}
+ };
+ });
+
+ it('should store references to docs by name', function() {
+ var doc = {ngdoc: 'section', name: 'fake', raw: {text:''}};
+ processNgDoc(documentation, doc);
+ expect(documentation.byName.fake).toBe(doc);
+ });
+
+ it('should connect doc to owner (specified by @methodOf)', function() {
+ var parentDoc = {ngdoc: 'section', name: 'parent', raw: {text:''}};
+ var doc = {ngdoc: 'section', name: 'child', methodOf: 'parent', raw: {text:''}};
+ processNgDoc(documentation, parentDoc);
+ processNgDoc(documentation, doc);
+ expect(documentation.byName.parent.method).toBeDefined();
+ expect(documentation.byName.parent.method[0]).toBe(doc);
+ });
+
+ it('should not add doc to sections if @memberOf specified', function() {
+ var parentDoc = {ngdoc: 'parent', name: 'parent', raw: {text:''}};
+ var doc = {ngdoc: 'child', name: 'child', methodOf: 'parent', raw: {text:''}};
+ processNgDoc(documentation, parentDoc);
+ processNgDoc(documentation, doc);
+ expect(documentation.pages.child).not.toBeDefined();
+ });
+
+ it('should throw exception if owner does not exist', function() {
+ expect(function() {
+ processNgDoc(documentation, {ngdoc: 'section', methodOf: 'not.exist', raw: {text:''}});
+ }).toThrow('Owner "not.exist" is not defined.');
+ });
+
+ it('should ignore non-ng docs', function() {
+ var doc = {name: 'anything'};
+ expect(function() {
+ processNgDoc(documentation, doc);
+ }).not.toThrow();
+ expect(documentation.pages).not.toContain(doc);
+ });
});
describe('TAG', function(){
@@ -41,6 +98,90 @@ describe('collect', function(){
});
});
+ describe('@requires', function() {
+ it('should parse more @requires tag into array', function() {
+ TAG.requires(doc, 'requires', '$service');
+ TAG.requires(doc, 'requires', '$another');
+
+ expect(doc.requires).toEqual([
+ {name: '$service'},
+ {name: '$another'}
+ ]);
+ });
+ });
+
+ describe('@property', function() {
+ it('should parse @property tags into array', function() {
+ TAG.property(doc, 'property', '{type} name1 desc');
+ TAG.property(doc, 'property', '{type} name2 desc');
+ expect(doc.property.length).toEqual(2);
+ });
+
+ it('should parse @property with only name', function() {
+ TAG.property(doc, 'property', 'fake');
+ expect(doc.property[0].name).toEqual('fake');
+ });
+
+ it('should parse @property with optional type', function() {
+ TAG.property(doc, 'property', '{string} name');
+ expect(doc.property[0].name).toEqual('name');
+ expect(doc.property[0].type).toEqual('string');
+ });
+
+ it('should parse @property with optional description', function() {
+ TAG.property(doc, 'property', 'name desc rip tion');
+ expect(doc.property[0].name).toEqual('name');
+ expect(doc.property[0].description).toEqual('desc rip tion');
+ });
+
+ it('should parse @property with type and description both', function() {
+ TAG.property(doc, 'property', '{bool} name desc rip tion');
+ expect(doc.property[0].name).toEqual('name');
+ expect(doc.property[0].type).toEqual('bool');
+ expect(doc.property[0].description).toEqual('desc rip tion');
+ });
+
+ /**
+ * If property description is undefined, this variable is not set in the template,
+ * so the whole @description tag is used instead
+ */
+ it('should set undefined description to "false"', function() {
+ TAG.property(doc, 'property', 'name');
+ expect(doc.property[0].description).toBe(false);
+ });
+ });
+
+ describe('@methodOf', function() {
+ it('should parse @methodOf tag', function() {
+ expect(function() {
+ TAG.methodOf(doc, 'methodOf', 'parentName');
+ }).not.toThrow();
+ expect(doc.methodOf).toEqual('parentName');
+ });
+ });
+
+ describe('@returns', function() {
+ it('should parse @returns', function() {
+ expect(function() {TAG.returns(doc, 'returns', '');})
+ .not.toThrow();
+ });
+
+ it('should parse @returns with type', function() {
+ TAG.returns(doc, 'returns', '{string}');
+ expect(doc.returns.type).toEqual('string');
+ });
+
+ it('should parse @returns with description', function() {
+ TAG.returns(doc, 'returns', 'descrip tion');
+ expect(doc.returns.description).toEqual('descrip tion');
+ });
+
+ it('should parse @returns with type and description', function() {
+ TAG.returns(doc, 'returns', '{string} description');
+ expect(doc.returns).toEqual({type: 'string', description: 'description'});
+ });
+ });
+
describe('@describe', function(){
it('should support pre blocks', function(){
TAG.description(doc, 'description', '<pre>abc</pre>');
diff --git a/docs/specs.js b/docs/specs.js
index 5f1cd153..d564b045 100644
--- a/docs/specs.js
+++ b/docs/specs.js
@@ -1,6 +1,6 @@
require.paths.push("./lib");
var jasmine = require('jasmine-1.0.1');
-var sys = require('sys');
+var sys = require('util');
for(var key in jasmine) {
global[key] = jasmine[key];