diff --git a/rhino_modules/jsdoc/util/templateHelper.js b/rhino_modules/jsdoc/util/templateHelper.js index 53201528..4f2beb2d 100644 --- a/rhino_modules/jsdoc/util/templateHelper.js +++ b/rhino_modules/jsdoc/util/templateHelper.js @@ -1,3 +1,4 @@ +/*global env: true */ /** * @module jsdoc/util/templateHelper */ @@ -22,10 +23,11 @@ exports.setTutorials = function(root) { exports.globalName = 'global'; exports.fileExtension = '.html'; +exports.scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' }; function getNamespace(kind) { if (dictionary.isNamespace(kind)) { - return kind+':'; + return kind + ':'; } return ''; } @@ -58,6 +60,222 @@ var linkMap = { urlToLongname: {} }; +var longnameToUrl = exports.longnameToUrl = linkMap.longnameToUrl; + +var linkto = exports.linkto = function(longname, linktext) { + var url = longnameToUrl[longname]; + return url ? '' + (linktext || longname) + '' : (linktext || longname); +}; + +var htmlsafe = exports.htmlsafe = function(str) { + return str.replace(/} The matching items. + */ +var find = exports.find = function(data, spec, sort) { + sort = sort === false ? sort : true; + + var items = data.get( data.find(spec) ); + if (sort) { + items.sort(function(a, b) { + return a.name > b.name; + }); + } + + return items; +}; + +/** + * Retrieve all of the following types of members from a set of doclets: + * + * + Classes + * + Externals + * + Globals + * + Mixins + * + Modules + * + Namespaces + * @param {TAFFY} data The TaffyDB database to search. + * @return {object} An object with `classes`, `externals`, `globals`, `mixins`, `modules`, and + * `namespaces` properties. Each property contains an array of objects. + */ +exports.getMembers = function(data) { + return { + classes: find( data, {kind: 'class'} ), + externals: find( data, {kind: 'external'} ), + globals: find(data, { + kind: ['member', 'function', 'constant', 'typedef'], + 'memberof': { + 'isUndefined': true + } + }), + mixins: find( data, {kind: 'mixin'} ), + modules: find( data, {kind: 'module'} ), + namespaces: find( data, {kind: 'namespace'} ) + }; +}; + +/** + * Retrieve the member attributes for a doclet (for example, `virtual`, `static`, and + * `readonly`). + * @param {object} d The doclet whose attributes will be retrieved. + * @return {array} The member attributes for the doclet. + */ +exports.getAttribs = function(d) { + var attribs = []; + + if (d.virtual) { + attribs.push('virtual'); + } + + if (d.access && d.access !== 'public') { + attribs.push(d.access); + } + + if (d.scope && d.scope !== 'instance' && d.scope !== 'global') { + if (d.kind == 'function' || d.kind == 'member' || d.kind == 'constant') { + attribs.push(d.scope); + } + } + + if (d.readonly === true) { + if (d.kind == 'member') { + attribs.push('readonly'); + } + } + + if (d.kind === 'constant') { + attribs.push('constant'); + } + + return attribs; +}; + +/** + * Retrieve links to allowed types for the member. + * @param {object} d The doclet whose types will be retrieved. + * @return {array} HTML links to allowed types for the member. + */ +exports.getSignatureTypes = function(d) { + var types = []; + + if (d.type && d.type.names) { + types = d.type.names; + } + + if (types && types.length) { + types = types.map(function(t) { + return linkto(t, htmlsafe(t)); + }); + } + + return types; +}; + +/** + * Retrieve names of the parameters that the member accepts. If a value is provided for `optClass`, + * the names of optional parameters will be wrapped in a `` tag with that class. + * @param {object} d The doclet whose parameter names will be retrieved. + * @param {string} [optClass] The class to assign to the `` tag that is wrapped around the + * names of optional parameters. If a value is not provided, optional parameter names will not be + * wrapped with a `` tag. Must be a legal value for a CSS class name. + * @return {array} An array of parameter names, with or without `` tags wrapping the + * names of optional parameters. + */ +exports.getSignatureParams = function(d, optClass) { + var pnames = []; + + if (d.params) { + d.params.forEach(function(p) { + if (p.name && p.name.indexOf('.') === -1) { + if (p.optional && optClass) { + pnames.push('' + p.name + ''); + } + else { + pnames.push(p.name); + } + } + }); + } + + return pnames; +}; + +/** + * Retrieve links to types that the member can return. + * @param {object} d The doclet whose types will be retrieved. + * @return {array} HTML links to types that the member can return. + */ +exports.getSignatureReturns = function(d) { + var returnTypes = []; + + if (d.returns) { + d.returns.forEach(function(r) { + if (r.type && r.type.names) { + if (!returnTypes.length) { + returnTypes = r.type.names; + } + } + }); + } + + if (returnTypes && returnTypes.length) { + returnTypes = returnTypes.map(function(r) { + return linkto(r); + }); + } + + return returnTypes; +}; + +/** + * Retrieve links to a member's ancestors. + * @param {TAFFY} data The TaffyDB database to search. + * @param {object} doclet The doclet whose ancestors will be retrieved. + * @return {array} HTML links to a member's ancestors. + */ +exports.getAncestorLinks = function(data, doclet) { + var ancestors = [], + doc = doclet.memberof; + + 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) ); + doc = doc.memberof; + } + if (ancestors.length) { + ancestors[ancestors.length - 1] += (exports.scopeToPunc[doclet.scope] || ''); + } + return ancestors; +}; + +/** + * Remove members that will not be included in the output, including: + * + * + Undocumented members. + * + Members tagged `@ignore`. + * + Members of anonymous classes. + * + Members tagged `@private`, unless the `private` option is enabled. + * @param {TAFFY} data The TaffyDB database to prune. + * @return {TAFFY} The pruned database. + */ +exports.prune = function(data) { + data.remove({undocumented: true}); + data.remove({ignore: true}); + if (!env.opts.private) { data.remove({access: 'private'}); } + data.remove({memberof: ''}); + + return data; +}; + exports.registerLink = function(longname, url) { linkMap.longnameToUrl[longname] = url; linkMap.urlToLongname[url] = longname; @@ -95,7 +313,31 @@ function toLink(longname, content) { } } -var toTutorial = exports.toTutorial = function(tutorial, content) { +var tutorialToUrl = exports.tutorialToUrl = function(tutorial) { + var node = tutorials.getByName(tutorial); + // no such tutorial + if (!node) { + require('jsdoc/util/error').handle( new Error('No such tutorial: '+tutorial) ); + return; + } + + return 'tutorial-' + strToFilename(node.name) + exports.fileExtension; +}; + +/** + * Retrieve a link to a tutorial, or the name of the tutorial if the tutorial is missing. If the + * `missingOpts` parameter is supplied, the names of missing tutorials will be prefixed by the + * specified text and wrapped in the specified HTML tag and CSS class. + * @param {string} tutorial The name of the tutorial. + * @param {string} content The link text to use. + * @param {object} [missingOpts] Options for displaying the name of a missing tutorial. + * @param {string} missingOpts.classname The CSS class to wrap around the tutorial name. + * @param {string} missingOpts.prefix The prefix to add to the tutorial name. + * @param {string} missingOpts.tag The tag to wrap around the tutorial name. + * @return {string} An HTML link to the tutorial, or the name of the tutorial with the specified + * options. + */ +var toTutorial = exports.toTutorial = function(tutorial, content, missingOpts) { if (!tutorial) { require('jsdoc/util/error').handle( new Error('Missing required parameter: tutorial') ); return; @@ -104,12 +346,24 @@ var toTutorial = exports.toTutorial = function(tutorial, content) { var node = tutorials.getByName(tutorial); // no such tutorial if (!node) { - return 'Tutorial: '+tutorial+''; + missingOpts = missingOpts || {}; + var tag = missingOpts.tag; + var classname = missingOpts.classname; + + var link = tutorial; + if (missingOpts.prefix) { + link = missingOpts.prefix + link; + } + if (tag) { + link = '<' + tag + (classname ? (' class="' + classname + '">') : '>') + link; + link += ''; + } + return link; } content = content || node.title; - return ''+content+''; + return '' + content + ''; }; /** Find symbol {@link ...} and {@tutorial ...} strings in text and turn into html links */ @@ -150,16 +404,3 @@ exports.createLink = function(doclet) { return url; }; - -exports.longnameToUrl = linkMap.longnameToUrl; - -exports.tutorialToUrl = function(tutorial) { - var node = tutorials.getByName(tutorial); - // no such tutorial - if (!node) { - require('jsdoc/util/error').handle( new Error('No such tutorial: '+tutorial) ); - return; - } - - return 'tutorial-'+strToFilename(node.name)+exports.fileExtension; -}; diff --git a/templates/default/publish.js b/templates/default/publish.js index 69d6ac66..312b2d9f 100644 --- a/templates/default/publish.js +++ b/templates/default/publish.js @@ -2,18 +2,198 @@ var template = require('jsdoc/template'), fs = require('fs'), helper = require('jsdoc/util/templateHelper'), - scopeToPunc = { 'static': '.', 'inner': '~', 'instance': '#' }, - hasOwnProp = Object.prototype.hasOwnProperty; + scopeToPunc = helper.scopeToPunc, + hasOwnProp = Object.prototype.hasOwnProperty, + data, + view, + outdir = env.opts.destination; + + +function find(spec, sort) { + return helper.find(data, spec, sort); +} + +function tutoriallink(tutorial) { + return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' }); +} + +function getAncestorLinks(doclet) { + return helper.getAncestorLinks(data, doclet); +} + +var linkto = helper.linkto; + +var htmlsafe = helper.htmlsafe; + +function hashToLink(doclet, hash) { + if ( !/^(#.+)/.test(hash) ) { return hash; } + + var url = helper.createLink(doclet); + + url = url.replace(/(#.+|$)/, hash); + return '' + hash + ''; +} + +function addSignatureParams(f) { + var params = helper.getSignatureParams(f, 'optional'); + + f.signature = (f.signature || '') + '('+params.join(', ')+')'; +} + +function addSignatureReturns(f) { + var returnTypes = helper.getSignatureReturns(f); + + f.signature = ''+(f.signature || '') + '' + ''+(returnTypes.length? ' → {'+returnTypes.join('|')+'}' : '')+''; +} + +function addSignatureTypes(f) { + var types = helper.getSignatureTypes(f); + + f.signature = (f.signature || '') + ''+(types.length? ' :'+types.join('|') : '')+''; +} + +function addAttribs(f) { + var attribs = helper.getAttribs(f); + + f.attribs = ''+htmlsafe(attribs.length? '<'+attribs.join(', ')+'> ' : '')+''; +} + +function generate(title, docs, filename) { + var docData = { + title: title, + docs: docs + }; + + var path = outdir + '/' + filename, + html = view.render('container.tmpl', docData); + + html = helper.resolveLinks(html); // turn {@link foo} into foo + + fs.writeFileSync(path, html); +} /** - @param {TAFFY} data See . + * Create the navigation sidebar. + * @param {object} members The members that will be used to create the sidebar. + * @param {array} members.classes + * @param {array} members.externals + * @param {array} members.globals + * @param {array} members.mixins + * @param {array} members.modules + * @param {array} members.namespaces + * @param {array} members.tutorials + * @return {string} The HTML for the navigation sidebar. + */ +function buildNav(members) { + var nav = '

Index

', + seen = {}; + + if (members.modules.length) { + nav += '

Modules

    '; + members.modules.forEach(function(m) { + if ( !hasOwnProp.call(seen, m.longname) ) { + nav += '
  • '+linkto(m.longname, m.name)+'
  • '; + } + seen[m.longname] = true; + }); + + nav += '
'; + } + + if (members.externals.length) { + nav += '

Externals

    '; + members.externals.forEach(function(e) { + if ( !hasOwnProp.call(seen, e.longname) ) { + nav += '
  • '+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'
  • '; + } + seen[e.longname] = true; + }); + + nav += '
'; + } + + if (members.classes.length) { + var moduleClasses = 0; + members.classes.forEach(function(c) { + var moduleSameName = find( {kind: 'module', longname: c.longname}, false ); + if (moduleSameName.length) { + c.name = c.name.replace('module:', 'require("')+'")'; + moduleClasses++; + moduleSameName[0].module = c; + } + if (moduleClasses !== -1 && moduleClasses < members.classes.length) { + nav += '

Classes

    '; + moduleClasses = -1; + } + if ( !hasOwnProp.call(seen, c.longname) ) { + nav += '
  • '+linkto(c.longname, c.name)+'
  • '; + } + seen[c.longname] = true; + }); + + nav += '
'; + } + + if (members.namespaces.length) { + nav += '

Namespaces

    '; + members.namespaces.forEach(function(n) { + if ( !hasOwnProp.call(seen, n.longname) ) { + nav += '
  • '+linkto(n.longname, n.name)+'
  • '; + } + seen[n.longname] = true; + }); + + nav += '
'; + } + + if (members.mixins.length) { + nav += '

Mixins

    '; + members.mixins.forEach(function(m) { + if ( !hasOwnProp.call(seen, m.longname) ) { + nav += '
  • '+linkto(m.longname, m.name)+'
  • '; + } + seen[m.longname] = true; + }); + + nav += '
'; + } + + if (members.tutorials.length) { + nav += '

Tutorials

    '; + members.tutorials.forEach(function(t) { + nav += '
  • '+tutoriallink(t.name)+'
  • '; + }); + + nav += '
'; + } + + if (members.globals.length) { + nav += '

Global

    '; + members.globals.forEach(function(g) { + if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) { + nav += '
  • '+linkto(g.longname, g.name)+'
  • '; + } + seen[g.longname] = true; + }); + + nav += '
'; + } + + return nav; +} + + +/** + @param {TAFFY} taffyData See . @param {object} opts @param {Tutorial} tutorials */ -exports.publish = function(data, opts, tutorials) { +exports.publish = function(taffyData, opts, tutorials) { + data = taffyData; + var defaultTemplatePath = 'templates/default', - templatePath = (opts.template) ? opts.template : defaultTemplatePath, - view = new template.Template(env.dirname + '/' + templatePath + '/tmpl'); + templatePath = (opts.template) ? opts.template : defaultTemplatePath; + view = new template.Template(env.dirname + '/' + templatePath + '/tmpl'); // set up templating view.layout = 'layout.tmpl'; @@ -21,134 +201,11 @@ exports.publish = function(data, opts, tutorials) { // set up tutorials for helper helper.setTutorials(tutorials); - function find(spec) { - return data.get( data.find(spec) ); - } - - function htmlsafe(str) { - return str.replace(/'+hash+''; - } - - function addSignatureParams(f) { - var pnames = []; - if (f.params) { - f.params.forEach(function(p) { - if (p.name && p.name.indexOf('.') === -1) { - if (p.optional) { pnames.push(''+p.name+''); } - else { pnames.push(p.name); } - } - }); - } - - f.signature = (f.signature || '') + '('+pnames.join(', ')+')'; - } - - function generateAncestry(thisdoc) { - var ancestors = [], - doc = thisdoc.memberof; - - while (doc) { - doc = find({longname: doc}); - if (doc) { doc = doc[0]; } - if (!doc) { break; } - ancestors.unshift( linkto(doc.longname, (scopeToPunc[doc.scope] || '') + doc.name) ); - doc = doc.memberof; - } - if (ancestors.length) { - ancestors[ancestors.length-1] += (scopeToPunc[thisdoc.scope] || ''); - } - return ancestors; - } - - function addSignatureReturns(f) { - var returnTypes = []; - - if (f.returns) { - f.returns.forEach(function(r) { - if (r.type && r.type.names) { - if (! returnTypes.length) { returnTypes = r.type.names; } - } - }); - } - - if (returnTypes && returnTypes.length) { - returnTypes = returnTypes.map(function(r) { - return linkto(r); - }); - } - f.signature = ''+(f.signature || '') + '' + ''+(returnTypes.length? ' → {'+returnTypes.join('|')+'}' : '')+''; - } - - function addSignatureType(f) { - var types = []; - - if (f.type && f.type.names) { - types = f.type.names; - } - - if (types && types.length) { - types = types.map(function(t) { - return linkto(t, htmlsafe(t)); - }); - } - - f.signature = (f.signature || '') + ''+(types.length? ' :'+types.join('|') : '')+''; - } - - function addAttribs(f) { - var attribs = []; - - if (f.virtual) { - attribs.push('virtual'); - } - - if (f.access && f.access !== 'public') { - attribs.push(f.access); - } - - if (f.scope && f.scope !== 'instance' && f.scope !== 'global') { - if (f.kind == 'function' || f.kind == 'member' || f.kind == 'constant') { - attribs.push(f.scope); - } - } - - if (f.readonly === true) { - if (f.kind == 'member') { - attribs.push('readonly'); - } - } - - if (f.kind === 'constant') { - attribs.push('constant'); - f.kind = 'member'; - } - - f.attribs = ''+htmlsafe(attribs.length? '<'+attribs.join(', ')+'> ' : '')+''; - } - - data.remove({undocumented: true}); - data.remove({ignore: true}); - if (!opts.private) { data.remove({access: 'private'}); } - data.remove({memberof: ''}); - - var packageInfo = (find({kind: 'package'}) || []) [0]; - - //function renderLinks(text) { - // return helper.resolveLinks(text); - //} - data.forEach(function(doclet) { doclet.attribs = ''; - if (doclet.examples) { doclet.examples = doclet.examples.map(function(example) { @@ -172,11 +229,8 @@ exports.publish = function(data, opts, tutorials) { } }); - data.orderBy(['longname', 'version', 'since']); - - var globals = find( {kind: ['member', 'function', 'constant', 'typedef'], memberof: {isUndefined: true}} ); - - var outdir = opts.destination; + // update outdir if necessary, then create outdir + var packageInfo = ( find({kind: 'package'}, false) || [] ) [0]; if (packageInfo && packageInfo.name) { outdir += '/' + packageInfo.name + '/' + packageInfo.version + '/'; } @@ -192,15 +246,6 @@ exports.publish = function(data, opts, tutorials) { fs.copyFileSync(fileName, toDir); }); - function linkto(longname, linktext) { - var url = helper.longnameToUrl[longname]; - return url? ''+(linktext || longname)+'' : (linktext || longname); - } - - function tutoriallink(tutorial) { - return helper.toTutorial(tutorial); - } - data.forEach(function(doclet) { var url = helper.createLink(doclet); helper.registerLink(doclet.longname, url); @@ -225,202 +270,74 @@ exports.publish = function(data, opts, tutorials) { // do this after the urls have all been generated data.forEach(function(doclet) { - doclet.ancestors = generateAncestry(doclet); - + doclet.ancestors = getAncestorLinks(doclet); + doclet.signature = ''; if (doclet.kind === 'member') { - addSignatureType(doclet); + addSignatureTypes(doclet); addAttribs(doclet); } if (doclet.kind === 'constant') { - addSignatureType(doclet); + addSignatureTypes(doclet); addAttribs(doclet); + doclet.kind = 'member'; } }); - var nav = '

Index

', - seen = {}; - - var moduleNames = find({kind: 'module'}); - moduleNames.sort(function(a, b) { - return a.name > b.name; - }); - if (moduleNames.length) { - nav += '

Modules

    '; - moduleNames.forEach(function(m) { - if ( !hasOwnProp.call(seen, m.longname) ) { - nav += '
  • '+linkto(m.longname, m.name)+'
  • '; - } - seen[m.longname] = true; - }); - - nav += '
'; - } - - var externalNames = find({kind: 'external'}); - externalNames.sort(function(a, b) { - return a.name > b.name; - }); - if (externalNames.length) { - nav += '

Externals

    '; - externalNames.forEach(function(e) { - if ( !hasOwnProp.call(seen, e.longname) ) { - nav += '
  • '+linkto( e.longname, e.name.replace(/(^"|"$)/g, '') )+'
  • '; - } - seen[e.longname] = true; - }); - - nav += '
'; - } + var members = helper.getMembers(data); + members.tutorials = tutorials.children; - var classNames = find({kind: 'class'}); - classNames.sort(function(a, b) { - return a.name > b.name; - }); - if (classNames.length) { - var moduleClasses = 0; - classNames.forEach(function(c) { - var moduleSameName = find({kind: 'module', longname: c.longname}); - if (moduleSameName.length) { - c.name = c.name.replace('module:', 'require("')+'")'; - moduleClasses++; - moduleSameName[0].module = c; - } - if (moduleClasses !== -1 && moduleClasses < classNames.length) { - nav += '

Classes

    '; - moduleClasses = -1; - } - if ( !hasOwnProp.call(seen, c.longname) ) { - nav += '
  • '+linkto(c.longname, c.name)+'
  • '; - } - seen[c.longname] = true; - }); - - nav += '
'; - } - - var namespaceNames = find({kind: 'namespace'}); - namespaceNames.sort(function(a, b) { - return a.name > b.name; - }); - if (namespaceNames.length) { - nav += '

Namespaces

    '; - namespaceNames.forEach(function(n) { - if ( !hasOwnProp.call(seen, n.longname) ) { - nav += '
  • '+linkto(n.longname, n.name)+'
  • '; - } - seen[n.longname] = true; - }); - - nav += '
'; - } - -// var constantNames = find({kind: 'constants'}); -// if (constantNames.length) { -// nav += '

Constants

    '; -// constantNames.forEach(function(c) { -// if ( !hasOwnProp.call(seen, c.longname) ) { -// nav += '
  • '+linkto(c.longname, c.name)+'
  • '; -// } -// seen[c.longname] = true; -// }); -// -// nav += '
'; -// } - - var mixinNames = find({kind: 'mixin'}); - mixinNames.sort(function(a, b) { - return a.name > b.name; - }); - if (mixinNames.length) { - nav += '

Mixins

    '; - mixinNames.forEach(function(m) { - if ( !hasOwnProp.call(seen, m.longname) ) { - nav += '
  • '+linkto(m.longname, m.name)+'
  • '; - } - seen[m.longname] = true; - }); - - nav += '
'; - } - - if (tutorials.children.length) { - nav += '

Tutorials

    '; - tutorials.children.forEach(function(t) { - nav += '
  • '+tutoriallink(t.name)+'
  • '; - }); - - nav += '
'; - } - - var globalNames = find({kind: ['member', 'function', 'constant', 'typedef'], 'memberof': {'isUndefined': true}}); - globalNames.sort(function(a, b) { - return a.name > b.name; - }); - if (globalNames.length) { - nav += '

Global

    '; - - globalNames.forEach(function(g) { - if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) { - nav += '
  • '+linkto(g.longname, g.name)+'
  • '; - } - seen[g.longname] = true; - }); - - nav += '
'; - } - // add template helpers view.find = find; view.linkto = linkto; view.tutoriallink = tutoriallink; view.htmlsafe = htmlsafe; - // once for all - view.nav = nav; - function generate(title, docs, filename) { - var data = { - title: title, - docs: docs - }; - - var path = outdir + '/' + filename, - html = view.render('container.tmpl', data); - - html = helper.resolveLinks(html); // turn {@link foo} into foo - - fs.writeFileSync(path, html); - } - + // once for all + view.nav = buildNav(members); + for (var longname in helper.longnameToUrl) { if ( hasOwnProp.call(helper.longnameToUrl, longname) ) { - var classes = find({kind: 'class', longname: longname}); - if (classes.length) { generate('Class: '+classes[0].name, classes, helper.longnameToUrl[longname]); } + // reuse 'members', which speeds things up a bit + var classes = new (require('typicaljoe/taffy'))(members.classes); + classes = helper.find( classes, {longname: longname}, false ); + if (classes.length) { + generate('Class: ' + classes[0].name, classes, helper.longnameToUrl[longname]); + } - var modules = find({kind: 'module', longname: longname}); - if (modules.length) { generate('Module: '+modules[0].name, modules, helper.longnameToUrl[longname]); } + var modules = new (require('typicaljoe/taffy'))(members.modules); + modules = helper.find( modules, {longname: longname}, false ); + if (modules.length) { + generate('Module: ' + modules[0].name, modules, helper.longnameToUrl[longname]); + } - var namespaces = find({kind: 'namespace', longname: longname}); - if (namespaces.length) { generate('Namespace: '+namespaces[0].name, namespaces, helper.longnameToUrl[longname]); } + var namespaces = new (require('typicaljoe/taffy'))(members.namespaces); + namespaces = helper.find( namespaces, {longname: longname}, false ); + if (namespaces.length) { + generate('Namespace: ' + namespaces[0].name, namespaces, helper.longnameToUrl[longname]); + } -// var constants = find({kind: 'constant', longname: longname}); -// if (constants.length) { generate('Constant: '+constants[0].name, constants, helper.longnameToUrl[longname]); } - - var mixins = find({kind: 'mixin', longname: longname}); - if (mixins.length) { generate('Mixin: '+mixins[0].name, mixins, helper.longnameToUrl[longname]); } + var mixins = new (require('typicaljoe/taffy'))(members.mixins); + mixins = helper.find( mixins, {longname: longname}, false ); + if (mixins.length) { + generate('Mixin: ' + mixins[0].name, mixins, helper.longnameToUrl[longname]); + } - var externals = find({kind: 'external', longname: longname}); - if (externals.length) { generate('External: '+externals[0].name, externals, helper.longnameToUrl[longname]); } + var externals = new (require('typicaljoe/taffy'))(members.externals); + externals = helper.find( externals, {longname: longname}, false ); + if (externals.length) { + generate('External: ' + externals[0].name, externals, helper.longnameToUrl[longname]); + } } } - if (globals.length) { generate('Global', [{kind: 'globalobj'}], 'global.html'); } + if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], 'global.html'); } // index page displays information from package.json and lists files - var files = find({kind: 'file'}), - packages = find({kind: 'package'}); + var files = find( {kind: 'file'}, false), + packages = find( {kind: 'package'}, false ); generate('Index', packages.concat( @@ -428,9 +345,9 @@ exports.publish = function(data, opts, tutorials) { ).concat(files), 'index.html'); - + // TODO: move the tutorial functions to templateHelper.js function generateTutorial(title, tutorial, filename) { - var data = { + var tutorialData = { title: title, header: tutorial.title, content: tutorial.parse(), @@ -438,7 +355,7 @@ exports.publish = function(data, opts, tutorials) { }; var path = outdir + '/' + filename, - html = view.render('tutorial.tmpl', data); + html = view.render('tutorial.tmpl', tutorialData); // yes, you can use {@link} in tutorials too! html = helper.resolveLinks(html); // turn {@link foo} into foo @@ -449,7 +366,7 @@ exports.publish = function(data, opts, tutorials) { // tutorials can have only one parent so there is no risk for loops function saveChildren(node) { node.children.forEach(function(child) { - generateTutorial('Tutorial: '+child.title, child, helper.tutorialToUrl(child.name)); + generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name)); saveChildren(child); }); } diff --git a/templates/default/tmpl/details.tmpl b/templates/default/tmpl/details.tmpl index ead4c4e3..18ef9d0d 100644 --- a/templates/default/tmpl/details.tmpl +++ b/templates/default/tmpl/details.tmpl @@ -68,7 +68,7 @@
Tutorials:
    -
  • +