forked from jsdoc/jsdoc
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
clean up/rename summarize plugin, and add tests
- Loading branch information
Showing
3 changed files
with
163 additions
and
48 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/** | ||
* @overview This plugin creates a summary tag, if missing, from the first sentence in the | ||
* description. | ||
* @module plugins/summarize | ||
* @author Mads Bondo Dydensborg <[email protected]> | ||
*/ | ||
'use strict'; | ||
|
||
exports.handlers = { | ||
/** | ||
* Autogenerate summaries, if missing, from the description, if present. | ||
*/ | ||
newDoclet: function(e) { | ||
var endTag; | ||
var tags; | ||
var stack; | ||
|
||
// If the summary is missing, grab the first sentence from the description | ||
// and use that. | ||
if (e.doclet && !e.doclet.summary && e.doclet.description) { | ||
// The summary may end with `. ` or with `.<` (a period followed by an HTML tag). | ||
e.doclet.summary = e.doclet.description.split(/\.\s|\.</)[0]; | ||
// Append `.` as it was removed in both cases, or is possibly missing. | ||
e.doclet.summary += '.'; | ||
|
||
// This is an excerpt of something that is possibly HTML. | ||
// Balance it using a stack. Assume it was initially balanced. | ||
tags = e.doclet.summary.match(/<[^>]+>/g) || []; | ||
stack = []; | ||
|
||
tags.forEach(function(tag) { | ||
var idx = tag.indexOf('/'); | ||
|
||
if (idx === -1) { | ||
// start tag -- push onto the stack | ||
stack.push(tag); | ||
} else if (idx === 1) { | ||
// end tag -- pop off of the stack | ||
stack.pop(); | ||
} | ||
|
||
// otherwise, it's a self-closing tag; don't modify the stack | ||
}); | ||
|
||
// stack should now contain only the start tags that lack end tags, | ||
// with the most deeply nested start tag at the top | ||
while (stack.length > 0) { | ||
// pop the unmatched tag off the stack | ||
endTag = stack.pop(); | ||
// get just the tag name | ||
endTag = endTag.substring(1, endTag.search(/[ >]/)); | ||
// append the end tag | ||
e.doclet.summary += '</' + endTag + '>'; | ||
} | ||
|
||
// and, finally, if the summary starts and ends with a <p> tag, remove it; let the | ||
// template decide whether to wrap the summary in a <p> tag | ||
e.doclet.summary = e.doclet.summary.replace(/^<p>(.*)<\/p>$/i, '$1'); | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/*global describe, expect, it */ | ||
'use strict'; | ||
|
||
var summarize = require('../../summarize'); | ||
|
||
describe('summarize', function() { | ||
it('should export handlers', function() { | ||
expect(summarize.handlers).toBeDefined(); | ||
expect(typeof summarize.handlers).toBe('object'); | ||
}); | ||
|
||
it('should export a newDoclet handler', function() { | ||
expect(summarize.handlers.newDoclet).toBeDefined(); | ||
expect(typeof summarize.handlers.newDoclet).toBe('function'); | ||
}); | ||
|
||
describe('newDoclet handler', function() { | ||
var handler = summarize.handlers.newDoclet; | ||
|
||
it('should not blow up if the doclet is missing', function() { | ||
function noDoclet() { | ||
return handler({}); | ||
} | ||
|
||
expect(noDoclet).not.toThrow(); | ||
}); | ||
|
||
it('should not change the summary if it is already defined', function() { | ||
var doclet = { | ||
summary: 'This is a summary.', | ||
description: 'Descriptions are good.' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).not.toBe(doclet.description); | ||
}); | ||
|
||
it('should not do anything if the description is missing', function() { | ||
var doclet = {}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).not.toBeDefined(); | ||
}); | ||
|
||
it('should use the first sentence as the summary', function() { | ||
var doclet = { | ||
description: 'This sentence is the summary. This sentence is not.' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).toBe('This sentence is the summary.'); | ||
}); | ||
|
||
it('should use the entire description, plus a period, as the summary if the description ' + | ||
'does not contain a period', function() { | ||
var doclet = { | ||
description: 'This is a description' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).toBe('This is a description.'); | ||
}); | ||
|
||
it('should use the entire description as the summary if the description contains only ' + | ||
'one sentence', function() { | ||
var doclet = { | ||
description: 'This is a description.' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.description).toBe('This is a description.'); | ||
}); | ||
|
||
it('should work when an HTML tag immediately follows the first sentence', function() { | ||
var doclet = { | ||
description: 'This sentence is the summary.<small>This sentence is small.</small>' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).toBe('This sentence is the summary.'); | ||
}); | ||
|
||
it('should generate valid HTML if a tag is opened, but not closed, in the summary', | ||
function() { | ||
var doclet = { | ||
description: 'This description has <em>a tag. The tag straddles</em> sentences.' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).toBe('This description has <em>a tag.</em>'); | ||
}); | ||
|
||
it('should not include a <p> tag in the summary', function() { | ||
var doclet = { | ||
description: '<p>This description contains HTML.</p><p>And plenty of it!</p>' | ||
}; | ||
handler({ doclet: doclet }); | ||
|
||
expect(doclet.summary).toBe('This description contains HTML.'); | ||
}); | ||
}); | ||
}); |