add getAncestors and getUniqueId helpers

This commit is contained in:
Jeff Williams 2014-08-06 15:32:06 -07:00
parent d220954d97
commit c2d3d0041b
2 changed files with 100 additions and 17 deletions

View File

@ -38,13 +38,13 @@ function getNamespace(kind) {
return '';
}
function makeFilenameUnique(filename, str) {
function makeUniqueFilename(filename, str) {
var key = filename.toLowerCase();
var nonUnique = true;
// append enough underscores to make the filename unique
while (nonUnique) {
if ( files[key] && hasOwnProp.call(files, key) ) {
if ( hasOwnProp.call(files, key) ) {
filename += '_';
key = filename.toLowerCase();
} else {
@ -56,6 +56,27 @@ function makeFilenameUnique(filename, str) {
return filename;
}
function makeUniqueId(filename, id) {
var key = id.toLowerCase();
var nonUnique = true;
// append enough underscores to make the identifier unique
while (nonUnique) {
if ( hasOwnProp.call(ids, filename) && ids[filename].indexOf(key) !== -1 ) {
id += '_';
key = id.toLowerCase();
}
else {
nonUnique = false;
}
}
ids[filename] = ids[filename] || [];
ids[filename].push(id);
return id;
}
var htmlsafe = exports.htmlsafe = function(str) {
return str.replace(/&/g, '&')
.replace(/</g, '&lt;');
@ -93,9 +114,22 @@ var getUniqueFilename = exports.getUniqueFilename = function(str) {
// in case we've now stripped the entire basename (uncommon, but possible):
basename = basename.length ? basename : '_';
return makeFilenameUnique(basename, str) + exports.fileExtension;
return makeUniqueFilename(basename, str) + exports.fileExtension;
};
/**
* Convert a string to an identifier that is unique for a specified URL.
*
* Identifiers are not considered unique if they are capitalized differently but are otherwise
* identical.
*
* @method
* @param {string} url - The URL in which the identifier will be used.
* @param {string} str - The string to convert.
* @return {string} A unique identifier based on the original string.
*/
var getUniqueId = exports.getUniqueId = makeUniqueId;
// two-way lookup
var linkMap = {
longnameToUrl: {},
@ -481,7 +515,16 @@ exports.getMembers = function(data) {
namespaces: find( data, {kind: 'namespace'} )
};
// functions that are also modules (as in "module.exports = function() {};") are not globals
// strip quotes from externals, since we allow quoted names that would normally indicate a
// namespace hierarchy (as in `@external "jquery.fn"`)
// TODO: we should probably be doing this for other types of symbols, here or elsewhere; see
// jsdoc3/jsdoc#396
members.externals = members.externals.map(function(doclet) {
doclet.name = doclet.name.replace(/(^"|"$)/g, '');
return doclet;
});
// functions that are also modules (as in `module.exports = function() {};`) are not globals
members.globals = members.globals.filter(function(doclet) {
return !isModuleExports(doclet);
});
@ -613,6 +656,29 @@ exports.getSignatureReturns = function(d, cssClass) {
return returnTypes;
};
/**
* Retrieve an ordered list of doclets for a symbol's ancestors.
*
* @param {TAFFY} data - The TaffyDB database to search.
* @param {Object} doclet - The doclet whose ancestors will be retrieved.
* @return {Array.<module:jsdoc/doclet.Doclet>} A array of ancestor doclets, sorted from most to
* least distant.
*/
exports.getAncestors = function(data, doclet) {
var ancestors = [];
var doc = doclet;
while (doc) {
doc = find(data, {longname: doc.memberof})[0];
if (doc) {
ancestors.unshift(doc);
}
}
return ancestors;
};
/**
* Retrieve links to a member's ancestors.
*
@ -622,21 +688,20 @@ exports.getSignatureReturns = function(d, cssClass) {
* @return {Array.<string>} HTML links to a member's ancestors.
*/
exports.getAncestorLinks = function(data, doclet, cssClass) {
var ancestors = [],
doc = doclet.memberof;
var ancestors = exports.getAncestors(data, doclet);
var links = [];
while (doc) {
doc = find( data, {longname: doc}, false );
if (doc) { doc = doc[0]; }
if (!doc) { break; }
ancestors.unshift( linkto(doc.longname, (exports.scopeToPunc[doc.scope] || '') + doc.name,
cssClass) );
doc = doc.memberof;
ancestors.forEach(function(ancestor) {
var linkText = (exports.scopeToPunc[ancestor.scope] || '') + ancestor.name;
var link = linkto(ancestor.longname, linkText, cssClass);
links.push(link);
});
if (links.length) {
links[links.length - 1] += (exports.scopeToPunc[doclet.scope] || '');
}
if (ancestors.length) {
ancestors[ancestors.length - 1] += (exports.scopeToPunc[doclet.scope] || '');
}
return ancestors;
return links;
};
/**

View File

@ -43,6 +43,11 @@ describe("jsdoc/util/templateHelper", function() {
expect(typeof helper.getUniqueFilename).toBe("function");
});
it("should export a 'getUniqueId' function", function() {
expect(helper.getUniqueId).toBeDefined();
expect(typeof helper.getUniqueId).toBe('function');
});
it("should export a 'longnameToUrl' property", function() {
expect(helper.longnameToUrl).toBeDefined();
expect(typeof helper.longnameToUrl).toBe("object");
@ -88,6 +93,11 @@ describe("jsdoc/util/templateHelper", function() {
expect(typeof helper.getSignatureReturns).toBe("function");
});
it("should export a 'getAncestors' function", function() {
expect(helper.getAncestors).toBeDefined();
expect(typeof helper.getAncestors).toBe('function');
});
it("should export a 'getAncestorLinks' function", function() {
expect(helper.getAncestorLinks).toBeDefined();
expect(typeof helper.getAncestorLinks).toBe("function");
@ -215,6 +225,10 @@ describe("jsdoc/util/templateHelper", function() {
});
});
xdescribe('getUniqueId', function() {
// TODO
});
describe("longnameToUrl", function() {
it("is an object", function() {
expect(typeof helper.longnameToUrl).toBe('object');
@ -772,6 +786,10 @@ describe("jsdoc/util/templateHelper", function() {
});
});
xdescribe('getAncestors', function() {
// TODO
});
describe("getAncestorLinks", function() {
// make a hierarchy.
var lackeys = new doclet.Doclet('/** @member lackeys\n@memberof module:mafia/gangs.Sharks~Henchman\n@instance*/', {}),