mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-05-10 15:54:42 +00:00
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.
This commit is contained in:
parent
43fccf5617
commit
87f6b36bab
2 changed files with 79 additions and 46 deletions
|
|
@ -55,12 +55,15 @@ describe('ngdoc', function() {
|
||||||
'@name a\n' +
|
'@name a\n' +
|
||||||
'@param {*} a short\n' +
|
'@param {*} a short\n' +
|
||||||
'@param {Type} b med\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();
|
doc.parse();
|
||||||
expect(doc.param).toEqual([
|
expect(doc.param).toEqual([
|
||||||
{name:'a', description:'<p>short</p>', type:'*', optional:false, 'default':undefined},
|
{name:'a', description:'<p>short</p>', type:'*', optional:false, 'default':undefined},
|
||||||
{name:'b', description:'<p>med</p>', type:'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() {
|
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(); }).
|
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() {
|
it('should parse @property with type', function() {
|
||||||
|
|
@ -350,15 +353,30 @@ describe('ngdoc', function() {
|
||||||
describe('@returns', function() {
|
describe('@returns', function() {
|
||||||
it('should not parse @returns without type', function() {
|
it('should not parse @returns without type', function() {
|
||||||
var doc = new Doc("@returns lala");
|
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() {
|
it('should parse @returns with type and description', function() {
|
||||||
var doc = new Doc("@name a\n@returns {string} descrip tion");
|
var doc = new Doc("@name a\n@returns {string} descrip tion");
|
||||||
doc.parse();
|
doc.parse();
|
||||||
expect(doc.returns).toEqual({type: 'string', description: '<p>descrip tion</p>'});
|
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() {
|
it('should transform description of @returns with markdown', function() {
|
||||||
var doc = new Doc("@name a\n@returns {string} descrip *tion*");
|
var doc = new Doc("@name a\n@returns {string} descrip *tion*");
|
||||||
doc.parse();
|
doc.parse();
|
||||||
|
|
|
||||||
|
|
@ -214,23 +214,25 @@ Doc.prototype = {
|
||||||
if (atName) {
|
if (atName) {
|
||||||
var text = trim(atText.join('\n')), match;
|
var text = trim(atText.join('\n')), match;
|
||||||
if (atName == 'param') {
|
if (atName == 'param') {
|
||||||
match = text.match(/^\{([^}=]+)(=)?\}\s+(([^\s=]+)|\[(\S+)=([^\]]+)\])\s+(.*)/);
|
match = text.match(/^\{([^}]+)\}\s+(([^\s=]+)|\[(\S+)=([^\]]+)\])\s+(.*)/);
|
||||||
// 1 12 2 34 4 5 5 6 6 3 7 7
|
// 1 1 23 3 4 4 5 5 2 6 6
|
||||||
if (!match) {
|
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 = {
|
var param = {
|
||||||
name: match[5] || match[4],
|
name: match[4] || match[3],
|
||||||
description:self.markdown(text.replace(match[0], match[7])),
|
description:self.markdown(text.replace(match[0], match[6])),
|
||||||
type: match[1],
|
type: optional ? match[1].substring(0, match[1].length-1) : match[1],
|
||||||
optional: !!match[2],
|
optional: optional,
|
||||||
'default':match[6]
|
'default':match[5]
|
||||||
};
|
};
|
||||||
self.param.push(param);
|
self.param.push(param);
|
||||||
} else if (atName == 'returns' || atName == 'return') {
|
} else if (atName == 'returns' || atName == 'return') {
|
||||||
match = text.match(/^\{([^}=]+)\}\s+(.*)/);
|
match = text.match(/^\{([^}]+)\}\s+(.*)/);
|
||||||
if (!match) {
|
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 = {
|
self.returns = {
|
||||||
type: match[1],
|
type: match[1],
|
||||||
|
|
@ -245,7 +247,7 @@ Doc.prototype = {
|
||||||
} else if(atName == 'property') {
|
} else if(atName == 'property') {
|
||||||
match = text.match(/^\{(\S+)\}\s+(\S+)(\s+(.*))?/);
|
match = text.match(/^\{(\S+)\}\s+(\S+)(\s+(.*))?/);
|
||||||
if (!match) {
|
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({
|
var property = new Doc({
|
||||||
type: match[1],
|
type: match[1],
|
||||||
|
|
@ -383,40 +385,53 @@ Doc.prototype = {
|
||||||
var self = this;
|
var self = this;
|
||||||
dom.h('Usage', function() {
|
dom.h('Usage', function() {
|
||||||
var restrict = self.restrict || 'AC';
|
var restrict = self.restrict || 'AC';
|
||||||
|
|
||||||
if (restrict.match(/E/)) {
|
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.tag('a', {href:'guide/ie'}, 'IE restrictions');
|
||||||
dom.text(')');
|
dom.text('.');
|
||||||
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';
|
if (self.usage) {
|
||||||
dom.text('as attribute');
|
dom.tag('pre', function() {
|
||||||
dom.code(function() {
|
dom.tag('code', function() {
|
||||||
dom.text('<' + element + ' ');
|
dom.text(self.usage);
|
||||||
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 + '>');
|
|
||||||
});
|
});
|
||||||
|
} 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_directiveInfo(dom);
|
||||||
self.html_usage_parameters(dom);
|
self.html_usage_parameters(dom);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue