Merge branch 'master' into parsimony

Conflicts:
	lib/jsdoc/src/parser.js
	test/specs/tags/defaulttag.js
This commit is contained in:
Jeff Williams 2013-06-23 21:40:21 -07:00
commit da22d723b7
17 changed files with 105 additions and 17 deletions

View File

@ -11,7 +11,7 @@ This file describes notable changes in each version of JSDoc 3. To download a sp
### Enhancements
+ The parser now fires a `parseBegin` event before it starts parsing files, as well as a `parseComplete` event after all files have been parsed. Plugins can define event handlers for these events, and `parseBegin` handlers can modify the list of files to parse. (#299)
+ Event handlers for `jsdocCommentFount` events can now modify the JSDoc comment. (#228)
+ Event handlers for `jsdocCommentFound` events can now modify the JSDoc comment. (#228)
+ You can now exclude tags from Markdown processing using the new option `markdown.excludeTags` in the configuration file. (#337)
+ You can now use the [marked](https://github.com/chjj/marked) Markdown parser by setting the configuration property `markdown.parser` to `marked`. In addition, if `markdown.parser` is set to `gfm`, JSDoc will now use the "marked" parser instead. (#385)
+ The `@typedef` tag no longer requires a name when used with a Closure Compiler-style type definition. For example, the following type definition will automatically get the name `Foo.Bar`:

View File

@ -170,7 +170,7 @@ function main() {
env.opts = jsdoc.opts.args.parse(env.args);
confPath = env.opts.configure || path.join(__dirname, 'conf.json');
if ( !fs.statSync(confPath).isFile() ) {
if ( !fs.statSync(confPath).isFile() && !env.opts.configure ) {
confPath = path.join(__dirname, 'conf.json.EXAMPLE');
}
@ -237,6 +237,8 @@ function main() {
jsdoc.augment.addInherited(docs);
jsdoc.borrow.resolveBorrows(docs);
app.jsdoc.parser.fireProcessingComplete(docs);
if (env.opts.explain) {
dump(docs);
process.exit(0);

View File

@ -90,7 +90,10 @@ function getAdditions(doclets, docs, longnames) {
for (var k = 0, kk = members.length; k < kk; k++) {
member = doop(members[k]);
member.inherits = member.longname;
if(!member.inherited)
{
member.inherits = member.longname;
}
member.inherited = true;
member.memberof = doc.longname;

View File

@ -128,7 +128,12 @@ Parser.prototype.parse = function(sourceFiles, encoding) {
return this._resultBuffer;
};
// TODO: update docs
// TODO: docs
Parser.prototype.fireProcessingComplete = function(doclets) {
this.emit('processingComplete', { doclets: doclets });
};
// TODO: docs
/**
* @returns {Array<Doclet>} The accumulated results of any calls to parse.
*/

View File

@ -246,6 +246,10 @@ exports.defineTags = function(dictionary) {
if (type === Syntax.Literal) {
doclet.defaultvalue = String(value);
}
else if (doclet.meta.code.type === 'OBJECTLIT') {
doclet.defaultvalue = String(doclet.meta.code.node.toSource());
doclet.defaultvaluetype = 'object';
}
}
}
})

View File

@ -61,7 +61,7 @@ exports.replaceInlineTags = function(string, replacers) {
string = string || '';
Object.keys(replacers).forEach(function(replacer) {
var tagRegExp = new RegExp('\\{@' + replacer + '\\s+(.+?)\\}', 'gi');
var tagRegExp = new RegExp('\\{@' + replacer + '\\s+((?:.|\n)+?)\\}', 'gi');
var matches;
// call the replacer once for each match
while ( (matches = tagRegExp.exec(string)) !== null ) {

View File

@ -256,11 +256,13 @@ function splitLinkText(text) {
// if a pipe is not present, we split on the first space
splitIndex = text.indexOf('|');
if (splitIndex === -1) {
splitIndex = text.indexOf(' ');
splitIndex = text.search(/\s/);
}
if (splitIndex !== -1) {
linkText = text.substr(splitIndex + 1);
// Normalize subsequent newlines to a single space.
linkText = linkText.replace(/\n+/, ' ');
target = text.substr(0, splitIndex);
}

View File

@ -19,7 +19,8 @@ var events = conf.include || [
'symbolFound',
'newDoclet',
'fileComplete',
'parseComplete'
'parseComplete',
'processingComplete'
];
// Don't dump the excluded parser events
if (conf.exclude) {

View File

@ -195,12 +195,14 @@ h6
font-family: Consolas, "Lucida Console", Monaco, monospace;
}
.details { margin-top: 14px; }
.details dt { width:100px; float:left; border-left: 2px solid #DDD; padding-left: 10px; padding-top: 6px; }
.details { margin-top: 14px; border-left: 2px solid #DDD; }
.details dt { width:100px; float:left; padding-left: 10px; padding-top: 6px; }
.details dd { margin-left: 50px; }
.details ul { margin: 0; }
.details ul { list-style-type: none; }
.details li { margin-left: 30px; padding-top: 6px; }
.details pre.prettyprint { margin: 0 }
.details .object-value { padding-top: 0; }
.description {
margin-bottom: 1em;

View File

@ -1,6 +1,13 @@
<?js
var data = obj;
var self = this;
var defaultObjectClass = '';
// Check if the default value is an object, if so, apply code highlighting
if (data.defaultvalue && data.defaultvaluetype === 'object') {
data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
defaultObjectClass = ' class="object-value"';
}
?>
<dl class="details">
<?js
@ -59,7 +66,9 @@ var self = this;
<?js if (data.defaultvalue) {?>
<dt class="tag-default">Default Value:</dt>
<dd class="tag-default"><ul class="dummy"><li><?js= data.defaultvalue ?></li></ul></dd>
<dd class="tag-default"><ul class="dummy">
<li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li>
</ul></dd>
<?js } ?>
<?js if (data.meta) {?>

View File

@ -31,4 +31,17 @@ var win = getParentWindow();
/**
@default
*/
var header = getHeaders(request);
var header = getHeaders(request);
/**
@default
*/
var obj = { value_a : 'a', value_b : 'b' };
/**
* @default
*/
var multilineObject = {
value_a : 'a',
value_b : 'b'
};

View File

@ -2,7 +2,7 @@
describe("jsdoc/src/filter", function() {
var filter = new (require('jsdoc/src/filter').Filter)({
includePattern: new RegExp(".+\\.js(doc)?$"),
excludePattern: new RegExp("(^|\\/)_"),
excludePattern: new RegExp("(^|\\/|\\\\)_"),
exclude: ['.ignore', 'scratch/conf.js']
});

View File

@ -77,6 +77,16 @@ describe("jsdoc/src/parser", function() {
expect(spy).toHaveBeenCalled();
expect(spy.mostRecentCall.args[0].sourcefiles).toEqual(["[[string0]]"]);
});
it("should fire processingComplete when fireProcessingComplete is called", function() {
var spy = jasmine.createSpy(),
doclets = ['a','b'];
parser.on('processingComplete', spy).fireProcessingComplete(doclets);
expect(spy).toHaveBeenCalled();
expect(typeof spy.mostRecentCall.args[0]).toBe('object');
expect(spy.mostRecentCall.args[0].doclets).toBeDefined();
expect(spy.mostRecentCall.args[0].doclets).toBe(doclets);
});
it("should be able to parse its own source file", function() {
var fs = require('jsdoc/fs'),

View File

@ -1168,6 +1168,22 @@ describe("jsdoc/util/templateHelper", function() {
expect(output).toBe('This is a <a href="path/to/test.html">test</a>.');
});
it('should allow linebreaks to separate url from link text', function() {
var input = 'This is a {@link\ntest\ntest}.',
output = helper.resolveLinks(input);
expect(output).toBe('This is a <a href="path/to/test.html">test</a>.');
});
it('should normalize additional newlines to spaces', function() {
var input = 'This is a {@link\ntest\ntest\n\ntest}.',
output = helper.resolveLinks(input);
expect(output).toBe('This is a <a href="path/to/test.html">test test</a>.');
});
it('should allow tabs between link tag and content', function() {
var input = 'This is a {@link\ttest}.',
output = helper.resolveLinks(input);

View File

@ -80,6 +80,15 @@
expect(bazMethod3.memberof).toBe("Baz");
});
it('(Grand)children correctly identify the original source of inherited members', function(){
expect(fooProp1.inherits).not.toBeDefined();
expect(barProp3.inherits).not.toBeDefined();
expect(barProp1.inherits).toBe("Foo#prop1");
expect(bazProp2.inherits).toBe("Foo#prop2");
expect(bazProp3.inherits).toBe("Bar#prop3");
expect(bazMethod1.inherits).toBe("Foo#method1");
});
it('When an object is extended, and it overrides an ancestor property, the child does not include docs for the ancestor property.', function() {
expect(bazProp1All.length).toBe(1);
});

View File

@ -8,6 +8,8 @@ describe("@default tag", function() {
var rerrored = (docSet.getByLongname('rerrored') || [])[0];
var win = (docSet.getByLongname('win') || [])[0];
var header = (docSet.getByLongname('header') || [])[0];
var obj = docSet.getByLongname('obj')[0];
var multilineObject = docSet.getByLongname('multilineObject')[0];
it('When symbol set to null has a @default tag with no text, the doclet\'s defaultValue property should be: null', function() {
expect(request.defaultvalue).toBe('null');
@ -37,4 +39,14 @@ describe("@default tag", function() {
expect(header.defaultvalue).toBeUndefined();
});
it('When symbol has a @default tag with an object, the doclet\'s defaultValue property should contain the stringified object', function() {
var expected_value = "{value_a: 'a', value_b: 'b'}";
expect(obj.defaultvalue).toEqual(expected_value);
});
it('When symbol has a @default tag with a multiline object, the doclet\'s defaultValue property should contain the properly stringified object', function() {
var expected_value = "{value_a: 'a', value_b: 'b'}";
expect(obj.defaultvalue).toEqual(expected_value);
});
});

View File

@ -2,21 +2,21 @@ describe("@example tag", function() {
var docSet = jasmine.getDocSetFromFile('test/fixtures/exampletag.js'),
doc = docSet.getByLongname('x')[0],
doc2 = docSet.getByLongname('y')[0],
txt = 'console.log("foo");\nconsole.log("bar");',
txt2 = '<caption>Example 2</caption>\n1 + 2;';
txtRegExp = new RegExp('console\\.log\\("foo"\\);[\\r\\n]{1,2}console\\.log\\("bar"\\);'),
txt2RegExp = new RegExp('<caption>Example 2</caption>[\\r\\n]{1,2}1 \\+ 2;');
it("creates an 'examples' property on the doclet with the example", function() {
expect(doc.examples).toBeDefined();
expect(Array.isArray(doc.examples)).toBe(true);
expect(doc.examples.length).toBe(1);
expect(doc.examples).toContain(txt);
expect(doc.examples).toMatch(txtRegExp);
});
it("can be specified multiple times on one doclet", function() {
expect(doc2.examples).toBeDefined();
expect(Array.isArray(doc2.examples)).toBe(true);
expect(doc2.examples.length).toBe(2);
expect(doc2.examples).toContain(txt);
expect(doc2.examples).toContain(txt2);
expect(doc2.examples).toMatch(txtRegExp);
expect(doc2.examples).toMatch(txt2RegExp);
});
});