add longnamesToTree method

This commit is contained in:
Jeff Williams 2014-07-03 13:53:46 -07:00
parent dcca9a4714
commit cae3cce8c1
3 changed files with 109 additions and 42 deletions

View File

@ -65,9 +65,10 @@ var scopeToPunc = exports.scopeToPunc = {
var puncToScope = exports.puncToScope = _.invert(scopeToPunc); var puncToScope = exports.puncToScope = _.invert(scopeToPunc);
var DEFAULT_SCOPE = SCOPE.NAMES.STATIC; var DEFAULT_SCOPE = SCOPE.NAMES.STATIC;
var REGEXP_SCOPE_PUNC = '([' + _.values(SCOPE.PUNC) + '])'; var SCOPE_PUNC = _.values(SCOPE.PUNC);
var REGEXP_LEADING_SCOPE = new RegExp('^' + REGEXP_SCOPE_PUNC); var REGEXP_SCOPE_PUNC = '[' + SCOPE_PUNC.join() + ']';
var REGEXP_TRAILING_SCOPE = new RegExp(REGEXP_SCOPE_PUNC + '$'); var REGEXP_LEADING_SCOPE = new RegExp('^(' + REGEXP_SCOPE_PUNC + ')');
var REGEXP_TRAILING_SCOPE = new RegExp('(' + REGEXP_SCOPE_PUNC + ')$');
function nameIsLongname(name, memberof) { function nameIsLongname(name, memberof) {
var regexp = new RegExp('^' + memberof + REGEXP_SCOPE_PUNC); var regexp = new RegExp('^' + memberof + REGEXP_SCOPE_PUNC);
@ -206,18 +207,19 @@ exports.applyNamespace = function(longname, ns) {
return longname; return longname;
}; };
/** // TODO: docs
Given a longname like "a.b#c(2)", slice it up into an object function shorten(longname, sliceChars, forcedMemberof) {
containing the memberof, the scope, the name, and variation. var i;
@param {string} longname var memberof = '';
@param {string} forcedMemberof var name = '';
@returns {object} Representing the properties of the given name. var parts;
*/ var partsRegExp;
exports.shorten = function(longname, forcedMemberof) { var scope = '';
// quoted strings in a longname are atomic, convert to tokens var token;
var atoms = [], token; var tokens = [];
var variation;
// handle quoted names like foo["bar"] or foo['bar'] // quoted strings in a longname are atomic, so we convert them to tokens
longname = longname.replace(/(\[?["'].+?["']\]?)/g, function($) { longname = longname.replace(/(\[?["'].+?["']\]?)/g, function($) {
var dot = ''; var dot = '';
if ( /^\[/.test($) ) { if ( /^\[/.test($) ) {
@ -225,34 +227,31 @@ exports.shorten = function(longname, forcedMemberof) {
$ = $.replace( /^\[/g, '' ).replace( /\]$/g, '' ); $ = $.replace( /^\[/g, '' ).replace( /\]$/g, '' );
} }
token = '@{' + atoms.length + '}@'; token = '@{' + tokens.length + '}@';
atoms.push($); tokens.push($);
return dot + token; // foo["bar"] => foo.@{1}@ return dot + token; // foo["bar"] => foo.@{1}@
}); });
var name = '',
scope = '', // ., ~, or #
memberof = '',
parts,
variation;
longname = prototypeToPunc(longname); longname = prototypeToPunc(longname);
if (typeof forcedMemberof !== 'undefined') { if (forcedMemberof !== undefined) {
partsRegExp = new RegExp('^(.*?)([' + sliceChars.join() + ']?)$');
name = longname.substr(forcedMemberof.length); name = longname.substr(forcedMemberof.length);
parts = forcedMemberof.match(/^(.*?)([#.~]?)$/); parts = forcedMemberof.match(partsRegExp);
if (parts[1]) { memberof = parts[1] || forcedMemberof; } if (parts[1]) {
if (parts[2]) { scope = parts[2]; } memberof = parts[1] || forcedMemberof;
} }
else { if (parts[2]) {
parts = longname ? scope = parts[2];
(longname.match( /^(:?(.+)([#.~]))?(.+?)$/ ) || []).reverse() : }
['']; }
else if (longname) {
name = parts[0] || ''; // ensure name is always initialised to avoid error being thrown when calling replace on undefined [gh-24] parts = (longname.match(new RegExp('^(:?(.+)([' + sliceChars.join() + ']))?(.+?)$')) || [])
scope = parts[1] || ''; // ., ~, or # .reverse();
name = parts[0] || '';
scope = parts[1] || '';
memberof = parts[2] || ''; memberof = parts[2] || '';
} }
@ -262,17 +261,71 @@ exports.shorten = function(longname, forcedMemberof) {
variation = RegExp.$2; variation = RegExp.$2;
} }
//// restore quoted strings back again // restore quoted strings
var i = atoms.length; i = tokens.length;
while (i--) { while (i--) {
longname = longname.replace('@{' + i + '}@', atoms[i]); longname = longname.replace('@{' + i + '}@', tokens[i]);
memberof = memberof.replace('@{' + i + '}@', atoms[i]); memberof = memberof.replace('@{' + i + '}@', tokens[i]);
scope = scope.replace('@{' + i + '}@', atoms[i]); scope = scope.replace('@{' + i + '}@', tokens[i]);
name = name.replace('@{' + i + '}@', atoms[i]); name = name.replace('@{' + i + '}@', tokens[i]);
} }
////
return {longname: longname, memberof: memberof, scope: scope, name: name, variation: variation}; return {longname: longname, memberof: memberof, scope: scope, name: name, variation: variation};
}
/**
Given a longname like "a.b#c(2)", slice it up into an object
containing the memberof, the scope, the name, and variation.
@param {string} longname
@param {string} forcedMemberof
@returns {object} Representing the properties of the given name.
*/
exports.shorten = function(longname, forcedMemberof) {
return shorten(longname, SCOPE_PUNC, forcedMemberof);
};
function splitLongname(longname) {
var chunks = [];
var currentNameInfo;
var nameInfo = {};
var previousName = longname;
var splitters = SCOPE_PUNC.concat('/');
do {
currentNameInfo = nameInfo[previousName] = shorten(previousName, splitters);
previousName = currentNameInfo.memberof;
chunks.push(currentNameInfo.scope + currentNameInfo.name);
} while (previousName);
return {
chunks: chunks.reverse(),
nameInfo: nameInfo
};
}
// TODO: docs
exports.longnamesToTree = function longnamesToTree(longnames, doclets) {
var tree = {};
longnames.forEach(function(longname) {
var processed = splitLongname(longname);
var nameInfo = processed.nameInfo;
var chunk;
var currentLongname = '';
var currentNavItem = tree;
processed.chunks.forEach(function(chunk) {
currentLongname += chunk;
currentNavItem[chunk] = currentNavItem[chunk] || nameInfo[currentLongname];
currentNavItem[chunk].doclet = doclets ? doclets[currentLongname] : null;
currentNavItem[chunk].children = currentNavItem[chunk].children || {};
currentNavItem = currentNavItem[chunk].children;
});
});
return tree;
}; };
/** /**

View File

@ -6,12 +6,14 @@
var catharsis = require('catharsis'); var catharsis = require('catharsis');
var dictionary = require('jsdoc/tag/dictionary'); var dictionary = require('jsdoc/tag/dictionary');
var name = require('jsdoc/name');
var util = require('util'); var util = require('util');
var hasOwnProp = Object.prototype.hasOwnProperty; var hasOwnProp = Object.prototype.hasOwnProperty;
var NAMESPACES = require('jsdoc/name').NAMESPACES; var NAMESPACES = require('jsdoc/name').NAMESPACES;
var files = {}; var files = {};
var ids = {};
// each container gets its own html file // each container gets its own html file
var containers = ['class', 'module', 'external', 'namespace', 'mixin']; var containers = ['class', 'module', 'external', 'namespace', 'mixin'];
@ -760,3 +762,6 @@ exports.createLink = function(doclet) {
return url; return url;
}; };
// TODO: docs
exports.longnamesToTree = name.longnamesToTree;

View File

@ -1,4 +1,4 @@
/*global afterEach, beforeEach, describe, expect, env, it, jasmine, spyOn */ /*global afterEach, beforeEach, describe, expect, env, it, jasmine, spyOn, xdescribe */
/*eslint quotes:0 */ /*eslint quotes:0 */
'use strict'; 'use strict';
@ -133,6 +133,11 @@ describe("jsdoc/util/templateHelper", function() {
expect(typeof helper.createLink).toBe("function"); expect(typeof helper.createLink).toBe("function");
}); });
it('should export a "longnamesToTree" function', function() {
expect(helper.longnamesToTree).toBeDefined();
expect(typeof helper.longnamesToTree).toBe('function');
});
describe("setTutorials", function() { describe("setTutorials", function() {
// used in tutorialToUrl, toTutorial. // used in tutorialToUrl, toTutorial.
it("setting tutorials to null causes all tutorial lookups to fail", function() { it("setting tutorials to null causes all tutorial lookups to fail", function() {
@ -412,7 +417,7 @@ describe("jsdoc/util/templateHelper", function() {
{kind: 'class', memberof: 'SomeNamespace'} // not global {kind: 'class', memberof: 'SomeNamespace'} // not global
]; ];
var externals = [ var externals = [
{kind: 'external'} {kind: 'external', name: 'foo'}
]; ];
var events = [ var events = [
{kind: 'event'} {kind: 'event'}
@ -1425,4 +1430,8 @@ describe("jsdoc/util/templateHelper", function() {
expect(out).toBe(helper.htmlsafe(str)); expect(out).toBe(helper.htmlsafe(str));
}); });
}); });
xdescribe('longnamesToTree', function() {
// TODO
});
}); });