From edcd94eeba0bf6204976bdd6c85498c013edaf90 Mon Sep 17 00:00:00 2001 From: Jeff Williams Date: Tue, 19 Mar 2013 22:43:27 -0700 Subject: [PATCH] link to type applications correctly in template output (#152) --- lib/jsdoc/util/templateHelper.js | 31 +++++++++++++++++++++++++ test/specs/jsdoc/util/templateHelper.js | 26 ++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/lib/jsdoc/util/templateHelper.js b/lib/jsdoc/util/templateHelper.js index 50d4dc2b..92de911b 100644 --- a/lib/jsdoc/util/templateHelper.js +++ b/lib/jsdoc/util/templateHelper.js @@ -100,11 +100,42 @@ var tutorialLinkMap = { var longnameToUrl = exports.longnameToUrl = linkMap.longnameToUrl; +/** + * Retrieve an HTML link to the member with the specified longname. If the longname is not + * associated with a URL, this method returns the link text, if provided, or the longname. + * + * This method supports type applications that can contain one or more types, such as + * `Array.` or `Array.<(MyClass|YourClass)>`. In these examples, the method attempts to + * replace `Array`, `MyClass`, and `YourClass` with links to the appropriate types. The link text + * is ignored for type applications. + * + * @param {string} longname - The longname that is the target of the link. + * @param {string=} linktext - The text to display for the link, or `longname` if no text is + * provided. + * @param {string=} cssClass - The CSS class (or classes) to include in the link's `` tag. + * @return {string} The HTML link, or a plain-text string if the link is not available. + */ var linkto = exports.linkto = function(longname, linktext, cssClass) { + var catharsis = require('catharsis'); + var classString = cssClass ? util.format(' class="%s"', cssClass) : ''; var text = linktext || longname; var url = hasOwnProp.call(longnameToUrl, longname) && longnameToUrl[longname]; + var parsedType; + // type applications require special treatment + var typeAppInfo = /(\S+)<(\S+)>/.exec(longname); + if (typeAppInfo) { + typeAppInfo[1] = linkto(typeAppInfo[1], null, cssClass); + parsedType = catharsis.parse(typeAppInfo[2], {jsdoc: true}); + typeAppInfo[2] = catharsis.stringify(parsedType, { + cssClass: cssClass, + htmlSafe: true, + links: longnameToUrl + }); + return typeAppInfo[1] + '<' + typeAppInfo[2] + '>'; + } + if (!url) { return text; } diff --git a/test/specs/jsdoc/util/templateHelper.js b/test/specs/jsdoc/util/templateHelper.js index c434af4a..f4392fb5 100644 --- a/test/specs/jsdoc/util/templateHelper.js +++ b/test/specs/jsdoc/util/templateHelper.js @@ -223,10 +223,12 @@ describe("jsdoc/util/templateHelper", function() { describe("linkto", function() { beforeEach(function() { helper.longnameToUrl.linktoTest = 'test.html'; + helper.longnameToUrl.LinktoFakeClass = 'fakeclass.html'; }); afterEach(function() { delete helper.longnameToUrl.linktoTest; + delete helper.longnameToUrl.LinktoFakeClass; }); it('returns the longname if only the longname is specified and has no URL', function() { @@ -260,12 +262,34 @@ describe("jsdoc/util/templateHelper", function() { expect(link).toBe('link text'); }); - it("is careful with longnames that are reserved words in JS", function() { + it('is careful with longnames that are reserved words in JS', function() { // we don't have a registered link for 'constructor' so it should return the text 'link text'. var link = helper.linkto('constructor', 'link text'); expect(typeof link).toBe('string'); expect(link).toBe('link text'); }); + + it('works correctly with type applications if only the longname is specified', function() { + var link = helper.linkto('Array.'); + expect(link).toBe('Array.<LinktoFakeClass>'); + }); + + it('works correctly with type applications if a class is not specified', function() { + var link = helper.linkto('Array.', 'link text'); + expect(link).toBe('Array.<LinktoFakeClass>'); + }); + + it('works correctly with type applications if a class is specified', function() { + var link = helper.linkto('Array.', 'link text', 'myclass'); + expect(link).toBe('Array.<LinktoFakeClass' + + '>'); + }); + + it('works correctly with type applications that include a type union', function() { + var link = helper.linkto('Array.<(linktoTest|LinktoFakeClass)>', 'link text'); + expect(link).toBe('Array.<(linktoTest|' + + 'LinktoFakeClass)>'); + }); }); describe("htmlsafe", function() {