From 4f22d6866c052fb5b770ce4f377cecacacd9e6d8 Mon Sep 17 00:00:00 2001
From: Misko Hevery
Date: Thu, 23 Dec 2010 00:44:27 +0100
Subject: complete rewrite of documentation generation
- romeved mustache.js
- unified templates
- improved testability of the code
---
docs/spec/collectSpec.js | 288 -----------------------------------------------
docs/spec/ngdocSpec.js | 257 ++++++++++++++++++++++++++++++++++++++++++
docs/spec/specs.js | 39 +++++++
docs/spec/writerSpec.js | 18 +++
4 files changed, 314 insertions(+), 288 deletions(-)
delete mode 100644 docs/spec/collectSpec.js
create mode 100644 docs/spec/ngdocSpec.js
create mode 100644 docs/spec/specs.js
create mode 100644 docs/spec/writerSpec.js
(limited to 'docs/spec')
diff --git a/docs/spec/collectSpec.js b/docs/spec/collectSpec.js
deleted file mode 100644
index f0783bdf..00000000
--- a/docs/spec/collectSpec.js
+++ /dev/null
@@ -1,288 +0,0 @@
-console.log(__dirname);
-require.paths.push(__dirname + "/../");
-require.paths.push(__dirname + "/../../");
-var fs = require('fs');
-var Script = process.binding('evals').Script;
-var collect = load('docs/collect.js');
-
-describe('collect', function(){
- describe('markdown', function(){
- it('should replace angular in markdown', function(){
- expect(collect.markdown('
<angular/>
'); - }); - - it('should not replace anything in', function(){
- expect(collect.markdown('bah x\n\nangular.k\n
\n asdf x')).
- toEqual(
- 'bah x
' +
- '\nangular.k\n
' +
- 'asdf x
');
- });
-
- it('should replace text between two tags', function() {
- expect(collect.markdown('x
# Oneb
')).
- toEqual('x
One
b
');
- });
- });
-
- 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(){
- var TAG = collect.TAG;
- var doc;
- beforeEach(function(){
- doc = {};
- });
-
- describe('@param', function(){
- it('should parse with no default', function(){
- TAG.param(doc, 'param',
- '{(number|string)} number Number \n to format.');
- expect(doc.param).toEqual([{
- type : '(number|string)',
- name : 'number',
- optional: false,
- 'default' : undefined,
- description : 'Number \n to format.' }]);
- });
- it('should parse with default and optional', function(){
- TAG.param(doc, 'param',
- '{(number|string)=} [fractionSize=2] desc');
- expect(doc.param).toEqual([{
- type : '(number|string)',
- name : 'fractionSize',
- optional: true,
- 'default' : '2',
- description : 'desc' }]);
- });
- });
-
- 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 not parse @returns without type', function() {
- expect(function() {TAG.returns(doc, 'returns', 'lala');})
- .toThrow();
- });
-
- it('should parse @returns with type and description', function() {
- TAG.returns(doc, 'returns', '{string} descrip tion');
- expect(doc.returns).toEqual({type: 'string', description: 'descrip tion'});
- });
-
- it('should transform description of @returns with markdown', function() {
- TAG.returns(doc, 'returns', '{string} descrip *tion*');
- expect(doc.returns).toEqual({type: 'string', description: 'descrip tion'});
- });
-
- it('should support multiline content', function() {
- TAG.returns(doc, 'returns', '{string} description\n new line\n another line');
- expect(doc.returns).
- toEqual({type: 'string', description: 'description\n new line\n another line'});
- });
- });
-
- describe('@description', function(){
- it('should support pre blocks', function(){
- TAG.description(doc, 'description', 'abc
');
- expect(doc.description).
- toBe('abc
');
- });
-
- it('should support multiple pre blocks', function() {
- TAG.description(doc, 'description', 'foo \nabc
\n#bah\nfoo \ncba
');
- expect(doc.description).
- toBe('foo
' +
- 'abc
' +
- 'bah
\n\n' +
- 'foo
' +
- 'cba
');
-
- });
-
- it('should support nested @link annotations with or without description', function() {
- TAG.description(doc, 'description',
- 'foo {@link angular.foo}\n\n da {@link angular.foo bar foo bar } \n\n' +
- 'dad{@link angular.foo}\n\n' +
- '{@link angular.directive.ng:foo ng:foo}');
- expect(doc.description).
- toBe('foo angular.foo
\n\n' +
- 'da bar foo bar
\n\n' +
- 'dadangular.foo
\n\n' +
- '');
- });
-
- it('should increment all headings by one', function() {
- TAG.description(doc, 'description', '# foo\nabc');
- expect(doc.description).
- toBe('foo
\n\nabc
');
- });
- });
-
- describe('@example', function(){
- it('should not remove {{}}', function(){
- TAG.example(doc, 'example', 'text {{ abc }}');
- expect(doc.example).toEqual('text {{ abc }}');
- });
- });
-
- describe('@deprecated', function() {
- it('should parse @deprecated', function() {
- TAG.deprecated(doc, 'deprecated', 'Replaced with foo.');
- expect(doc.deprecated).toBe('Replaced with foo.');
- })
- });
-
- describe('@workInProgress', function() {
- it('should parse @workInProgress without a description and default to true', function() {
- TAG.workInProgress(doc, 'workInProgress', '');
- expect(doc.workInProgress).toEqual({description: ''});
- });
-
- it('should parse @workInProgress with a description', function() {
- TAG.workInProgress(doc, 'workInProgress', 'my description');
- expect(doc.workInProgress).toEqual({description: 'my description
'});
- });
- });
-
- });
-
- describe('trim', function(){
- var trim = collect.trim;
- it('should remove leading/trailing space', function(){
- expect(trim(' \nabc\n ')).toEqual('abc');
- });
-
- it('should remove leading space on every line', function(){
- expect(trim('\n 1\n 2\n 3\n')).toEqual('1\n 2\n 3');
- });
- });
-
- describe('keywords', function(){
- var keywords = collect.keywords;
- it('should collect keywords', function(){
- expect(keywords('\nHello: World! @ignore.')).toEqual('hello world');
- expect(keywords('The `ng:class-odd` and ')).toEqual('and ng:class-odd the');
- });
- });
-
-});
-
-function load(path){
- var sandbox = {
- require: require,
- console: console,
- __dirname: __dirname,
- testmode: true
- };
- Script.runInNewContext(fs.readFileSync(path), sandbox, path);
- return sandbox;
-}
diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js
new file mode 100644
index 00000000..63be610b
--- /dev/null
+++ b/docs/spec/ngdocSpec.js
@@ -0,0 +1,257 @@
+var ngdoc = require('ngdoc.js');
+
+describe('ngdoc', function(){
+ var Doc = ngdoc.Doc;
+ describe('Doc', function(){
+ describe('metadata', function(){
+
+ it('should find keywords', function(){
+ expect(new Doc('\nHello: World! @ignore.').keywords()).toEqual('hello world');
+ expect(new Doc('The `ng:class-odd` and').keywords()).toEqual('and ng:class-odd the');
+ });
+ });
+
+ describe('parse', function(){
+ it('should convert @names into properties', function(){
+ var doc = new Doc('\n@name name\n@desc\ndesc\ndesc2\n@dep\n');
+ doc.parse();
+ expect(doc.name).toEqual('name');
+ expect(doc.desc).toEqual('desc\ndesc2');
+ expect(doc.dep).toEqual('');
+ });
+
+ it('should parse parameters', function(){
+ var doc = new Doc(
+ '@param {*} a short\n' +
+ '@param {Type} b med\n' +
+ '@param {Class=} [c=2] long\nline');
+ doc.parse();
+ expect(doc.param).toEqual([
+ {name:'a', description:'short', type:'*', optional:false, 'default':undefined},
+ {name:'b', description:'med', type:'Type', optional:false, 'default':undefined},
+ {name:'c', description:'long\nline', type:'Class', optional:true, 'default':'2'}
+ ]);
+ });
+
+ it('should parse return', function(){
+ var doc = new Doc('@returns {Type} text *bold*.');
+ doc.parse();
+ expect(doc.returns).toEqual({
+ type: 'Type',
+ description: 'text bold.'
+ });
+ });
+ });
+
+
+ });
+
+ describe('markdown', function(){
+ var markdown = ngdoc.markdown;
+
+ it('should replace angular in markdown', function(){
+ expect(markdown(' ')).
+ toEqual('<angular/>
');
+ });
+
+ it('should not replace anything in ', function(){
+ expect(markdown('bah x\n\nangular.k\n
\n asdf x')).
+ toEqual(
+ 'bah x
' +
+ '\n' +
+ 'angular.k\n' +
+ '
' +
+ 'asdf x
');
+ });
+
+ it('should replace text between two tags', function() {
+ expect(markdown('x
# Oneb
')).
+ toMatch('One
tion'});
+ });
+
+ it('should support multiline content', function() {
+ var doc = new Doc("@returns {string} description\n new line\n another line");
+ doc.parse();
+ expect(doc.returns).
+ toEqual({type: 'string', description: 'description\n new line\n another line'});
+ });
+ });
+
+ describe('@description', function(){
+ it('should support pre blocks', function(){
+ var doc = new Doc("@description abc
");
+ doc.parse();
+ expect(doc.description).
+ toBe('abc
');
+ });
+
+ it('should support multiple pre blocks', function() {
+ var doc = new Doc("@description foo \nabc
\n#bah\nfoo \ncba
");
+ doc.parse();
+ expect(doc.description).
+ toBe('foo
' +
+ 'abc
' +
+ 'bah
\n\n' +
+ 'foo
' +
+ 'cba
');
+
+ });
+
+ it('should support nested @link annotations with or without description', function() {
+ var doc = new Doc("@description " +
+ 'foo {@link angular.foo}\n\n da {@link angular.foo bar foo bar } \n\n' +
+ 'dad{@link angular.foo}\n\n' +
+ '{@link angular.directive.ng:foo ng:foo}');
+ doc.parse();
+ expect(doc.description).
+ toBe('foo angular.foo
\n\n' +
+ 'da bar foo bar
\n\n' +
+ 'dadangular.foo
\n\n' +
+ '');
+ });
+
+ it('should increment all headings by two', function() {
+ var doc = new Doc('@description # foo\nabc\n## bar \n xyz');
+ doc.parse();
+ expect(doc.description).
+ toBe('foo
\n\nabc
\n\nbar
\n\nxyz
');
+ });
+ });
+
+ describe('@example', function(){
+ it('should not remove {{}}', function(){
+ var doc = new Doc('@example text {{ abc }}');
+ doc.parse();
+ expect(doc.example).toEqual('text {{ abc }}');
+ });
+ });
+
+ describe('@deprecated', function() {
+ it('should parse @deprecated', function() {
+ var doc = new Doc('@deprecated Replaced with foo.');
+ doc.parse();
+ expect(doc.deprecated).toBe('Replaced with foo.');
+ });
+ });
+ });
+
+});
diff --git a/docs/spec/specs.js b/docs/spec/specs.js
new file mode 100644
index 00000000..a6ba17a9
--- /dev/null
+++ b/docs/spec/specs.js
@@ -0,0 +1,39 @@
+if (global.jasmine) return;
+
+require.paths.push(__dirname + "/../../lib");
+require.paths.push(__dirname + '/../src');
+var jasmine = require('jasmine-1.0.1');
+var sys = require('util');
+
+for(var key in jasmine) {
+ global[key] = jasmine[key];
+}
+
+//Patch Jasmine for proper stack traces
+jasmine.Spec.prototype.fail = function (e) {
+ var expectationResult = new jasmine.ExpectationResult({
+ passed: false,
+ message: e ? jasmine.util.formatException(e) : 'Exception'
+ });
+ // PATCH
+ if (e) {
+ expectationResult.trace = e;
+ }
+ this.results_.addResult(expectationResult);
+};
+
+
+
+var isVerbose = false;
+var showColors = true;
+process.argv.forEach(function(arg){
+ switch(arg) {
+ case '--color': showColors = true; break;
+ case '--noColor': showColors = false; break;
+ case '--verbose': isVerbose = true; break;
+ }
+});
+
+jasmine.executeSpecsInFolder(__dirname, function(runner, log){
+ process.exit(runner.results().failedCount);
+}, isVerbose, showColors);
diff --git a/docs/spec/writerSpec.js b/docs/spec/writerSpec.js
new file mode 100644
index 00000000..1a722ca6
--- /dev/null
+++ b/docs/spec/writerSpec.js
@@ -0,0 +1,18 @@
+var writer = require('writer.js');
+describe('writer', function(){
+ describe('toString', function(){
+ var toString = writer.toString;
+
+ it('should merge string', function(){
+ expect(toString('abc')).toEqual('abc');
+ });
+
+ it('should merge obj', function(){
+ expect(toString({a:1})).toEqual('{"a":1}');
+ });
+
+ it('should merge array', function(){
+ expect(toString(['abc',{}])).toEqual('abc{}');
+ });
+ });
+});
\ No newline at end of file
--
cgit v1.2.3