1 if (typeof JSDOC
== "undefined") JSDOC
= {};
6 JSDOC
.DocTag
= function(src
) {
8 if (typeof src
!= "undefined") {
14 Create and initialize the properties of this.
16 JSDOC
.DocTag
.prototype.init
= function() {
20 this.isOptional
= false;
21 this.defaultValue
= "";
28 Populate the properties of this from the given tag src.
31 JSDOC
.DocTag
.prototype.parse
= function(src
) {
32 if (typeof src
!= "string") throw "src must be a string not "+(typeof src
);
35 src
= this.nibbleTitle(src
);
36 if (JSDOC
.PluginManager
) {
37 JSDOC
.PluginManager
.run("onDocTagSynonym", this);
40 src
= this.nibbleType(src
);
42 // only some tags are allowed to have names.
43 if (this.title
== "param" || this.title
== "property" || this.title
== "config") { // @config is deprecated
44 src
= this.nibbleName(src
);
51 this.desc
= src
; // whatever is left
53 // example tags need to have whitespace preserved
54 if (this.title
!= "example") this.desc
= this.desc
.trim();
56 if (JSDOC
.PluginManager
) {
57 JSDOC
.PluginManager
.run("onDocTag", this);
62 Automatically called when this is stringified.
64 JSDOC
.DocTag
.prototype.toString
= function() {
69 plan(1, "testing JSDOC.DocTag#toString");
71 var tag = new JSDOC.DocTag("param {object} date A valid date.");
72 is(""+tag, "A valid date.", "stringifying a tag returns the desc.");
76 Find and shift off the title of a tag.
80 JSDOC
.DocTag
.prototype.nibbleTitle
= function(src
) {
81 if (typeof src
!= "string") throw "src must be a string not "+(typeof src
);
83 var parts
= src
.match(/^\s*(\S+)(?:\s([\s\S]*))?$/);
85 if (parts
&& parts
[1]) this.title
= parts
[1];
86 if (parts
&& parts
[2]) src
= parts
[2];
93 plan(8, "testing JSDOC.DocTag#nibbleTitle");
95 var tag = new JSDOC.DocTag();
97 tag.init().nibbleTitle("aTitleGoesHere");
98 is(tag.title, "aTitleGoesHere", "a title can be found in a single-word string.");
100 var src = tag.init().nibbleTitle("aTitleGoesHere and the rest");
101 is(tag.title, "aTitleGoesHere", "a title can be found in a multi-word string.");
102 is(src, "and the rest", "the rest is returned when the title is nibbled off.");
104 src = tag.init().nibbleTitle("");
105 is(tag.title, "", "given an empty string the title is empty.");
106 is(src, "", "the rest is empty when the tag is empty.");
108 var src = tag.init().nibbleTitle(" aTitleGoesHere\n a description");
109 is(tag.title, "aTitleGoesHere", "leading and trailing spaces are not part of the title.");
110 is(src, " a description", "leading spaces (less one) are part of the description.");
112 tag.init().nibbleTitle("a.Title::Goes_Here foo");
113 is(tag.title, "a.Title::Goes_Here", "titles with punctuation are allowed.");
117 Find and shift off the type of a tag.
118 @requires frame/String.js
122 JSDOC
.DocTag
.prototype.nibbleType
= function(src
) {
123 if (typeof src
!= "string") throw "src must be a string not "+(typeof src
);
125 if (src
.match(/^\s*\{/)) {
126 var typeRange
= src
.balance("{", "}");
127 if (typeRange
[1] == -1) {
128 throw "Malformed comment tag ignored. Tag type requires an opening { and a closing }: "+src
;
130 this.type
= src
.substring(typeRange
[0]+1, typeRange
[1]).trim();
131 this.type
= this.type
.replace(/\s*,\s*/g, "|"); // multiples can be separated by , or |
132 src
= src
.substring(typeRange
[1]+1);
139 plan(5, "testing JSDOC.DocTag.parser.nibbleType");
140 requires("../frame/String.js");
142 var tag = new JSDOC.DocTag();
144 tag.init().nibbleType("{String[]} aliases");
145 is(tag.type, "String[]", "type can have non-alpha characters.");
147 tag.init().nibbleType("{ aTypeGoesHere } etc etc");
148 is(tag.type, "aTypeGoesHere", "type is trimmed.");
150 tag.init().nibbleType("{ oneType, twoType ,\n threeType } etc etc");
151 is(tag.type, "oneType|twoType|threeType", "multiple types can be separated by commas.");
154 try { tag.init().nibbleType("{widget foo"); }
155 catch(e) { error = e; }
156 is(typeof error, "string", "malformed tag type throws error.");
157 isnt(error.indexOf("Malformed"), -1, "error message tells tag is malformed.");
161 Find and shift off the name of a tag.
162 @requires frame/String.js
166 JSDOC
.DocTag
.prototype.nibbleName
= function(src
) {
167 if (typeof src
!= "string") throw "src must be a string not "+(typeof src
);
172 if (src
.charAt(0) == "[") {
173 var nameRange
= src
.balance("[", "]");
174 if (nameRange
[1] == -1) {
175 throw "Malformed comment tag ignored. Tag optional name requires an opening [ and a closing ]: "+src
;
177 this.name
= src
.substring(nameRange
[0]+1, nameRange
[1]).trim();
178 this.isOptional
= true;
180 src
= src
.substring(nameRange
[1]+1);
182 // has default value?
183 var nameAndValue
= this.name
.split("=");
184 if (nameAndValue
.length
) {
185 this.name
= nameAndValue
.shift().trim();
186 this.defaultValue
= nameAndValue
.join("=");
190 var parts
= src
.match(/^(\S+)(?:\s([\s\S]*))?$/);
192 if (parts
[1]) this.name
= parts
[1];
193 if (parts
[2]) src
= parts
[2].trim();
202 requires("../frame/String.js");
203 plan(9, "testing JSDOC.DocTag.parser.nibbleName");
205 var tag = new JSDOC.DocTag();
207 tag.init().nibbleName("[foo] This is a description.");
208 is(tag.isOptional, true, "isOptional syntax is detected.");
209 is(tag.name, "foo", "optional param name is found.");
211 tag.init().nibbleName("[foo] This is a description.");
212 is(tag.isOptional, true, "isOptional syntax is detected when no type.");
213 is(tag.name, "foo", "optional param name is found when no type.");
215 tag.init().nibbleName("[foo=7] This is a description.");
216 is(tag.name, "foo", "optional param name is found when default value.");
217 is(tag.defaultValue, 7, "optional param default value is found when default value.");
219 //tag.init().nibbleName("[foo= a value] This is a description.");
220 //is(tag.defaultValue, " a value", "optional param default value is found when default value has spaces (issue #112).");
222 tag.init().nibbleName("[foo=[]] This is a description.");
223 is(tag.defaultValue, "[]", "optional param default value is found when default value is [] (issue #95).");
225 tag.init().nibbleName("[foo=a=b] This is a description.");
226 is(tag.name, "foo", "optional param name is found when default value is a=b.");
227 is(tag.defaultValue, "a=b", "optional param default value is found when default value is a=b.")
231 plan(32, "Testing JSDOC.DocTag.parser.");
232 requires("../frame/String.js");
234 var tag = new JSDOC.DocTag();
236 is(typeof tag, "object", "JSDOC.DocTag.parser with an empty string returns an object.");
237 is(typeof tag.title, "string", "returned object has a string property 'title'.");
238 is(typeof tag.type, "string", "returned object has a string property 'type'.");
239 is(typeof tag.name, "string", "returned object has a string property 'name'.");
240 is(typeof tag.defaultValue, "string", "returned object has a string property 'defaultValue'.");
241 is(typeof tag.isOptional, "boolean", "returned object has a boolean property 'isOptional'.");
242 is(typeof tag.desc, "string", "returned object has a string property 'desc'.");
244 tag = new JSDOC.DocTag("param {widget} foo");
245 is(tag.title, "param", "param title is found.");
246 is(tag.name, "foo", "param name is found when desc is missing.");
247 is(tag.desc, "", "param desc is empty when missing.");
249 tag = new JSDOC.DocTag("param {object} date A valid date.");
250 is(tag.name, "date", "param name is found with a type.");
251 is(tag.type, "object", "param type is found.");
252 is(tag.desc, "A valid date.", "param desc is found with a type.");
254 tag = new JSDOC.DocTag("param aName a description goes\n here.");
255 is(tag.name, "aName", "param name is found without a type.");
256 is(tag.desc, "a description goes\n here.", "param desc is found without a type.");
258 tag = new JSDOC.DocTag("param {widget}");
259 is(tag.name, "", "param name is empty when it is not given.");
261 tag = new JSDOC.DocTag("param {widget} [foo] This is a description.");
262 is(tag.name, "foo", "optional param name is found.");
264 tag = new JSDOC.DocTag("return {aType} This is a description.");
265 is(tag.type, "aType", "when return tag has no name, type is found.");
266 is(tag.desc, "This is a description.", "when return tag has no name, desc is found.");
268 tag = new JSDOC.DocTag("author Joe Coder <jcoder@example.com>");
269 is(tag.title, "author", "author tag has a title.");
270 is(tag.type, "", "the author tag has no type.");
271 is(tag.name, "", "the author tag has no name.");
272 is(tag.desc, "Joe Coder <jcoder@example.com>", "author tag has desc.");
274 tag = new JSDOC.DocTag("private \t\n ");
275 is(tag.title, "private", "private tag has a title.");
276 is(tag.type, "", "the private tag has no type.");
277 is(tag.name, "", "the private tag has no name.");
278 is(tag.desc, "", "private tag has no desc.");
280 tag = new JSDOC.DocTag("example\n example(code);\n more();");
281 is(tag.desc, " example(code);\n more();", "leading whitespace (less one) in examples code is preserved.");
283 tag = new JSDOC.DocTag("param theName \n");
284 is(tag.name, "theName", "name only is found.");
286 tag = new JSDOC.DocTag("type theDesc \n");
287 is(tag.desc, "theDesc", "desc only is found.");
289 tag = new JSDOC.DocTag("type {theType} \n");
290 is(tag.type, "theType", "type only is found.");
292 tag = new JSDOC.DocTag("");
293 is(tag.title, "", "title is empty when tag is empty.");