diff --git a/modules/jsdoc/doclet.js b/modules/jsdoc/doclet.js index b4ec491a..4229ab0e 100644 --- a/modules/jsdoc/doclet.js +++ b/modules/jsdoc/doclet.js @@ -95,7 +95,7 @@ */ exports.Doclet.prototype.setLongname = function(name) { if (/^\.?/.test(name)) { name = name.replace(/^\.?/, ''); } - + /** The fully resolved symbol name. @type string diff --git a/modules/jsdoc/name.js b/modules/jsdoc/name.js index 789ce122..f2f41b05 100644 --- a/modules/jsdoc/name.js +++ b/modules/jsdoc/name.js @@ -24,7 +24,7 @@ memberof = doclet.memberof || '', about = {}, parentDoc; - + name = name? (''+name).replace(/\.prototype\.?/g, '#') : ''; // member of a var in an outer scope? @@ -172,6 +172,7 @@ scope = scope.replace('@{'+i+'}@', atoms[i]); name = name.replace('@{'+i+'}@', atoms[i]); } + //// return {longname: longname, memberof: memberof, scope: scope, name: name, variation: variation}; } diff --git a/modules/jsdoc/src/parser.js b/modules/jsdoc/src/parser.js index d0dafb38..6f83a44f 100644 --- a/modules/jsdoc/src/parser.js +++ b/modules/jsdoc/src/parser.js @@ -268,7 +268,7 @@ currentParser.refs['astnode'+e.code.node.hashCode()] = e.doclet; // allow lookup from value => doclet } } - else if (node.type === Token.COLON) { + else if (node.type === Token.COLON) { // assignment within an object literal e = { id: 'astnode'+node.hashCode(), // the id of the COLON node comment: String(node.left.jsDoc||'@undocumented'), @@ -376,8 +376,9 @@ function aboutNode(node) { about = {}; - if (node.type == Token.FUNCTION /*&& String(node.name) !== ''*/) { + if (node.type == Token.FUNCTION) { about.name = '' + node.name; + about.type = 'function'; about.node = node; @@ -402,6 +403,13 @@ if (node.type === Token.ASSIGN || node.type === Token.COLON) { about.name = nodeToString(node.left); + if (node.type === Token.COLON) { + + // objlit keys with unsafe variable-name characters must be quoted + if (!/^[$_a-z][$_a-z0-9]*$/i.test(about.name) ) { + about.name = '"'+about.name.replace(/"/g, '\\"')+'"'; + } + } about.node = node.right; about.value = nodeToString(about.node); about.type = getTypeName(node.right); diff --git a/modules/jsdoc/tag/dictionary/definitions.js b/modules/jsdoc/tag/dictionary/definitions.js index c3995aa6..95815693 100644 --- a/modules/jsdoc/tag/dictionary/definitions.js +++ b/modules/jsdoc/tag/dictionary/definitions.js @@ -123,12 +123,16 @@ doclet.defaultvalue = tag.value; } else if (doclet.meta && doclet.meta.code && typeof doclet.meta.code.value !== 'undefined') { - if (doclet.meta.code.type && /STRING|NUMBER|NAME/.test(doclet.meta.code.type)) { + if (doclet.meta.code.type && /STRING|NUMBER|NAME|TRUE|FALSE/.test(doclet.meta.code.type)) { doclet.defaultvalue = doclet.meta.code.value; if (doclet.meta.code.type === 'STRING') { // TODO: handle escaped quotes in values doclet.defaultvalue = '"'+doclet.defaultvalue.replace(/"/g, '\\"')+'"' } + + if (doclet.defaultvalue === 'TRUE' || doclet.defaultvalue == 'FALSE') { + doclet.defaultvalue = doclet.defaultvalue.toLowerCase(); + } } else if (doclet.meta.code.type === 'NULL') { // TODO: handle escaped quotes in values diff --git a/test/cases/quotename.js b/test/cases/quotename.js index 945357dd..e484db5e 100644 --- a/test/cases/quotename.js +++ b/test/cases/quotename.js @@ -1,6 +1,8 @@ +/** @namespace */ +var chat = {}; + /** @namespace - @name chat."#channel" */ chat["#channel"] = {}; @@ -8,7 +10,7 @@ chat["#channel"] = {}; /** @property @type {boolean} - @name chat."#channel".open + @defaultvalue */ chat["#channel"].open = true; diff --git a/test/cases/quotename2.js b/test/cases/quotename2.js new file mode 100644 index 00000000..b05c8136 --- /dev/null +++ b/test/cases/quotename2.js @@ -0,0 +1,10 @@ +/** @namespace */ +var contacts = { + + /** @namespace */ + 'say-"hello"@example.com': { + + /** document me */ + "username": 'Sue Smart' + } +} \ No newline at end of file diff --git a/test/runner.js b/test/runner.js index 1d93ea87..3bdd56d9 100644 --- a/test/runner.js +++ b/test/runner.js @@ -130,6 +130,8 @@ testFile('test/t/cases/moduletag.js'); testFile('test/t/cases/moduletag2.js'); testFile('test/t/cases/paramtag.js'); testFile('test/t/cases/privatetag.js'); +testFile('test/t/cases/quotename.js'); +testFile('test/t/cases/quotename2.js'); testFile('test/t/cases/readonlytag.js'); testFile('test/t/cases/requirestag.js'); testFile('test/t/cases/returnstag.js'); diff --git a/test/t/cases/quotename.js b/test/t/cases/quotename.js new file mode 100644 index 00000000..489080df --- /dev/null +++ b/test/t/cases/quotename.js @@ -0,0 +1,11 @@ +(function() { + var docSet = testhelpers.getDocSetFromFile('test/cases/quotename.js'), + found1 = docSet.getByLongname('chat.\"#channel\".open')[0]; + + // dump(docSet); + + test('When a member is quoted in square brackets.', function() { + assert.equal(found1.name, 'open', 'The short name should be correct.'); + assert.equal(found1.memberof, 'chat.\"#channel\"', 'The memberof should be correct.'); + }); +})(); \ No newline at end of file diff --git a/test/t/cases/quotename2.js b/test/t/cases/quotename2.js new file mode 100644 index 00000000..e33799a2 --- /dev/null +++ b/test/t/cases/quotename2.js @@ -0,0 +1,11 @@ +(function() { + var docSet = testhelpers.getDocSetFromFile('test/cases/quotename2.js'), + found1 = docSet.getByLongname("contacts.\"say-\\\"hello\\\"@example.com\".username")[0]; + + // dump(docSet); + + test('When a key name of a member of an objlit is quoted.', function() { + assert.equal(found1.name, 'username', 'The short name should be correct.'); + assert.equal(found1.memberof, "contacts.\"say-\\\"hello\\\"@example.com\"", 'The memberof should be correct.'); + }); +})(); \ No newline at end of file