diff options
| author | Igor Minar | 2013-02-06 15:25:28 -0800 |
|---|---|---|
| committer | Igor Minar | 2013-02-11 14:08:16 -0800 |
| commit | 42a5033c563fcb3a3f0ddd89ab62ec36d0e73996 (patch) | |
| tree | b9fca17d2b025e18087e9db1906be502e6311a21 | |
| parent | 6b19e7d527dc67113e39bff0060238d78bed9447 (diff) | |
| download | angular.js-42a5033c563fcb3a3f0ddd89ab62ec36d0e73996.tar.bz2 | |
chore(docs): improve docs parser type
previously we barfed on function type definition with optional arguments
like {function(number=)}
this fixes it
I also added a bunch of code that helps to debug incorrectly parsed docs.
| -rw-r--r-- | docs/spec/ngdocSpec.js | 28 | ||||
| -rw-r--r-- | docs/src/ngdoc.js | 97 |
2 files changed, 79 insertions, 46 deletions
diff --git a/docs/spec/ngdocSpec.js b/docs/spec/ngdocSpec.js index 0a7979f2..48db580b 100644 --- a/docs/spec/ngdocSpec.js +++ b/docs/spec/ngdocSpec.js @@ -55,12 +55,15 @@ describe('ngdoc', function() { '@name a\n' + '@param {*} a short\n' + '@param {Type} b med\n' + - '@param {Class=} [c=2] long\nline'); + '@param {Class=} [c=2] long\nline\n' + + '@param {function(number, string=)} d fn with optional arguments'); doc.parse(); expect(doc.param).toEqual([ {name:'a', description:'<p>short</p>', type:'*', optional:false, 'default':undefined}, {name:'b', description:'<p>med</p>', type:'Type', optional:false, 'default':undefined}, - {name:'c', description:'<p>long\nline</p>', type:'Class', optional:true, 'default':'2'} + {name:'c', description:'<p>long\nline</p>', type:'Class', optional:true, 'default':'2'}, + {name:'d', description:'<p>fn with optional arguments</p>', + type: 'function(number, string=)', optional: false, 'default':undefined} ]); }); @@ -318,9 +321,9 @@ describe('ngdoc', function() { }); it('should not parse @property without a type', function() { - var doc = new Doc("@property fake"); + var doc = new Doc("@property fake", 'test.js', '44'); expect(function() { doc.parse(); }). - toThrow(new Error("Not a valid 'property' format: fake")); + toThrow(new Error("Not a valid 'property' format: fake (found in: test.js:44)")); }); it('should parse @property with type', function() { @@ -350,15 +353,30 @@ describe('ngdoc', function() { describe('@returns', function() { it('should not parse @returns without type', function() { var doc = new Doc("@returns lala"); - expect(doc.parse).toThrow(); + expect(function() { doc.parse(); }). + toThrow(); + }); + + + it('should not parse @returns with invalid type', function() { + var doc = new Doc("@returns {xx}x} lala", 'test.js', 34); + expect(function() { doc.parse(); }). + toThrow(new Error("Not a valid 'returns' format: {xx}x} lala (found in: test.js:34)")); }); + it('should parse @returns with type and description', function() { var doc = new Doc("@name a\n@returns {string} descrip tion"); doc.parse(); expect(doc.returns).toEqual({type: 'string', description: '<p>descrip tion</p>'}); }); + it('should parse @returns with complex type and description', function() { + var doc = new Doc("@name a\n@returns {function(string, number=)} description"); + doc.parse(); + expect(doc.returns).toEqual({type: 'function(string, number=)', description: '<p>description</p>'}); + }); + it('should transform description of @returns with markdown', function() { var doc = new Doc("@name a\n@returns {string} descrip *tion*"); doc.parse(); diff --git a/docs/src/ngdoc.js b/docs/src/ngdoc.js index ae612a55..253f5411 100644 --- a/docs/src/ngdoc.js +++ b/docs/src/ngdoc.js @@ -214,23 +214,25 @@ Doc.prototype = { if (atName) { var text = trim(atText.join('\n')), match; if (atName == 'param') { - match = text.match(/^\{([^}=]+)(=)?\}\s+(([^\s=]+)|\[(\S+)=([^\]]+)\])\s+(.*)/); - // 1 12 2 34 4 5 5 6 6 3 7 7 + match = text.match(/^\{([^}]+)\}\s+(([^\s=]+)|\[(\S+)=([^\]]+)\])\s+(.*)/); + // 1 1 23 3 4 4 5 5 2 6 6 if (!match) { - throw new Error("Not a valid 'param' format: " + text); + throw new Error("Not a valid 'param' format: " + text + ' (found in: ' + self.file + ':' + self.line + ')'); } + + var optional = (match[1].slice(-1) === '='); var param = { - name: match[5] || match[4], - description:self.markdown(text.replace(match[0], match[7])), - type: match[1], - optional: !!match[2], - 'default':match[6] + name: match[4] || match[3], + description:self.markdown(text.replace(match[0], match[6])), + type: optional ? match[1].substring(0, match[1].length-1) : match[1], + optional: optional, + 'default':match[5] }; self.param.push(param); } else if (atName == 'returns' || atName == 'return') { - match = text.match(/^\{([^}=]+)\}\s+(.*)/); + match = text.match(/^\{([^}]+)\}\s+(.*)/); if (!match) { - throw new Error("Not a valid 'returns' format: " + text + ' in ' + self.file + ':' + self.line); + throw new Error("Not a valid 'returns' format: " + text + ' (found in: ' + self.file + ':' + self.line + ')'); } self.returns = { type: match[1], @@ -245,7 +247,7 @@ Doc.prototype = { } else if(atName == 'property') { match = text.match(/^\{(\S+)\}\s+(\S+)(\s+(.*))?/); if (!match) { - throw new Error("Not a valid 'property' format: " + text); + throw new Error("Not a valid 'property' format: " + text + ' (found in: ' + self.file + ':' + self.line + ')'); } var property = new Doc({ type: match[1], @@ -383,40 +385,53 @@ Doc.prototype = { var self = this; dom.h('Usage', function() { var restrict = self.restrict || 'AC'; + if (restrict.match(/E/)) { - dom.text('as element (see '); + dom.text('This directive can be used as custom element, but we aware of '); dom.tag('a', {href:'guide/ie'}, 'IE restrictions'); - dom.text(')'); - dom.code(function() { - dom.text('<'); - dom.text(dashCase(self.shortName)); - renderParams('\n ', '="', '"'); - dom.text('>\n</'); - dom.text(dashCase(self.shortName)); - dom.text('>'); - }); + dom.text('.'); } - if (restrict.match(/A/)) { - var element = self.element || 'ANY'; - dom.text('as attribute'); - dom.code(function() { - dom.text('<' + element + ' '); - dom.text(dashCase(self.shortName)); - renderParams('\n ', '="', '"', true); - dom.text('>\n ...\n'); - dom.text('</' + element + '>'); - }); - } - if (restrict.match(/C/)) { - dom.text('as class'); - var element = self.element || 'ANY'; - dom.code(function() { - dom.text('<' + element + ' class="'); - dom.text(dashCase(self.shortName)); - renderParams(' ', ': ', ';', true); - dom.text('">\n ...\n'); - dom.text('</' + element + '>'); + + if (self.usage) { + dom.tag('pre', function() { + dom.tag('code', function() { + dom.text(self.usage); + }); }); + } else { + if (restrict.match(/E/)) { + dom.text('as element:'); + dom.code(function() { + dom.text('<'); + dom.text(dashCase(self.shortName)); + renderParams('\n ', '="', '"'); + dom.text('>\n</'); + dom.text(dashCase(self.shortName)); + dom.text('>'); + }); + } + if (restrict.match(/A/)) { + var element = self.element || 'ANY'; + dom.text('as attribute'); + dom.code(function() { + dom.text('<' + element + ' '); + dom.text(dashCase(self.shortName)); + renderParams('\n ', '="', '"', true); + dom.text('>\n ...\n'); + dom.text('</' + element + '>'); + }); + } + if (restrict.match(/C/)) { + dom.text('as class'); + var element = self.element || 'ANY'; + dom.code(function() { + dom.text('<' + element + ' class="'); + dom.text(dashCase(self.shortName)); + renderParams(' ', ': ', ';', true); + dom.text('">\n ...\n'); + dom.text('</' + element + '>'); + }); + } } self.html_usage_directiveInfo(dom); self.html_usage_parameters(dom); |
