handle symbol names with leading/trailing whitespace (#549)

This commit is contained in:
Jeff Williams 2014-10-23 09:38:30 -07:00
parent 58839223a9
commit 996c283733
2 changed files with 52 additions and 5 deletions

View File

@ -25,15 +25,25 @@ var jsdoc = {
} }
}; };
var path = require('jsdoc/path'); var path = require('jsdoc/path');
var util = require('util');
function trim(text, opts) { // Check whether the text is the same as a symbol name with leading or trailing whitespace. If so,
// the text cannot be trimmed.
function textIsUntrimmable(text, meta) {
return meta && meta.code && meta.code.name === text && text.match(/(?:^\s+)|(?:\s+$)/);
}
function trim(text, opts, meta) {
var indentMatcher; var indentMatcher;
var match; var match;
opts = opts || {}; opts = opts || {};
text = text || ''; text = text || '';
if (opts.keepsWhitespace) { if ( textIsUntrimmable(text, meta) ) {
text = util.format('"%s"', text);
}
else if (opts.keepsWhitespace) {
text = text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, ''); text = text.replace(/^[\n\r\f]+|[\n\r\f]+$/g, '');
if (opts.removesIndent) { if (opts.removesIndent) {
match = text.match(/^([ \t]+)/); match = text.match(/^([ \t]+)/);
@ -131,7 +141,7 @@ var Tag = exports.Tag = function(tagTitle, tagBody, meta) {
this.originalTitle = trim(tagTitle); this.originalTitle = trim(tagTitle);
/** The title part of the tag: @title text */ /** The title of the tag (for example, `title` in `@title text`). */
this.title = jsdoc.tag.dictionary.normalise(this.originalTitle); this.title = jsdoc.tag.dictionary.normalise(this.originalTitle);
tagDef = jsdoc.tag.dictionary.lookUp(this.title); tagDef = jsdoc.tag.dictionary.lookUp(this.title);
@ -140,8 +150,25 @@ var Tag = exports.Tag = function(tagTitle, tagBody, meta) {
removesIndent: tagDef.removesIndent removesIndent: tagDef.removesIndent
}; };
/** The text part of the tag: @title text */ /**
this.text = trim(tagBody, trimOpts); * The text following the tag (for example, `text` in `@title text`).
*
* Whitespace is trimmed from the tag text as follows:
*
* + If the tag's `keepsWhitespace` option is falsy, all leading and trailing whitespace are
* removed.
* + If the tag's `keepsWhitespace` option is set to `true`, leading and trailing whitespace are
* not trimmed, unless the `removesIndent` option is also enabled.
* + If the tag's `removesIndent` option is set to `true`, any indentation that is shared by
* every line in the string is removed. This option is ignored unless `keepsWhitespace` is set
* to `true`.
*
* **Note**: If the tag text is the name of a symbol, and the symbol's name includes leading or
* trailing whitespace (for example, the property names in `{ ' ': true, ' foo ': false }`),
* the tag text is not trimmed. Instead, the tag text is wrapped in double quotes to prevent the
* whitespace from being trimmed.
*/
this.text = trim(tagBody, trimOpts, meta);
if (this.text) { if (this.text) {
try { try {

View File

@ -112,6 +112,26 @@ describe('jsdoc/tag', function() {
expect(tagType.text).toBeDefined(); expect(tagType.text).toBeDefined();
expect(tagType.text).toBe(def.onTagText('MyType')); expect(tagType.text).toBe(def.onTagText('MyType'));
}); });
it('should be enclosed in quotes, with no whitespace trimming, if it is a symbol name with leading or trailing whitespace', function() {
var wsBoth;
var wsLeading;
var wsOnly;
var wsTrailing;
spyOn(logger, 'error');
wsOnly = new jsdoc.tag.Tag('name', ' ', { code: { name: ' ' } });
wsLeading = new jsdoc.tag.Tag('name', ' foo', { code: { name: ' foo' } });
wsTrailing = new jsdoc.tag.Tag('name', 'foo ', { code: { name: 'foo ' } });
wsBoth = new jsdoc.tag.Tag('name', ' foo ', { code: { name: ' foo ' } });
expect(logger.error).not.toHaveBeenCalled();
expect(wsOnly.text).toBe('" "');
expect(wsLeading.text).toBe('" foo"');
expect(wsTrailing.text).toBe('"foo "');
expect(wsBoth.text).toBe('" foo "');
});
}); });
describe("'value' property", function() { describe("'value' property", function() {