From be1c7e50e1e8809ea56f2c9d472eccd8ffd73a97 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 04:57:58 +0200 Subject: Adding upstream version 1.44.3. Signed-off-by: Daniel Baumann --- .../misc/oktavia/templates/jsdoc3/publish.js | 508 +++++++++++++++++++++ 1 file changed, 508 insertions(+) create mode 100644 web/server/h2o/libh2o/misc/oktavia/templates/jsdoc3/publish.js (limited to 'web/server/h2o/libh2o/misc/oktavia/templates/jsdoc3/publish.js') diff --git a/web/server/h2o/libh2o/misc/oktavia/templates/jsdoc3/publish.js b/web/server/h2o/libh2o/misc/oktavia/templates/jsdoc3/publish.js new file mode 100644 index 00000000..36211462 --- /dev/null +++ b/web/server/h2o/libh2o/misc/oktavia/templates/jsdoc3/publish.js @@ -0,0 +1,508 @@ +/*global env: true */ +var template = require('jsdoc/template'), + fs = require('jsdoc/fs'), + path = require('jsdoc/path'), + taffy = require('taffydb').taffy, + handle = require('jsdoc/util/error').handle, + helper = require('jsdoc/util/templateHelper'), + htmlsafe = helper.htmlsafe, + linkto = helper.linkto, + resolveAuthorLinks = helper.resolveAuthorLinks, + scopeToPunc = helper.scopeToPunc, + hasOwnProp = Object.prototype.hasOwnProperty, + data, + view, + outdir = env.opts.destination; + + +function find(spec) { + return helper.find(data, spec); +} + +function tutoriallink(tutorial) { + return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' }); +} + +function getAncestorLinks(doclet) { + return helper.getAncestorLinks(data, doclet); +} + +function hashToLink(doclet, hash) { + if ( !/^(#.+)/.test(hash) ) { return hash; } + + var url = helper.createLink(doclet); + + url = url.replace(/(#.+|$)/, hash); + return '' + hash + ''; +} + +function needsSignature(doclet) { + var needsSig = false; + + // function and class definitions always get a signature + if (doclet.kind === 'function' || doclet.kind === 'class') { + needsSig = true; + } + // typedefs that contain functions get a signature, too + else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names && + doclet.type.names.length) { + for (var i = 0, l = doclet.type.names.length; i < l; i++) { + if (doclet.type.names[i].toLowerCase() === 'function') { + needsSig = true; + break; + } + } + } + + return needsSig; +} + +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 shortenPaths(files, commonPrefix) { + // always use forward slashes + var regexp = new RegExp('\\\\', 'g'); + + Object.keys(files).forEach(function(file) { + files[file].shortened = files[file].resolved.replace(commonPrefix, '') + .replace(regexp, '/'); + }); + + return files; +} + +function resolveSourcePath(filepath) { + return path.resolve(process.cwd(), filepath); +} + +function getPathFromDoclet(doclet) { + if (!doclet.meta) { + return; + } + + var filepath = doclet.meta.path && doclet.meta.path !== 'null' ? + doclet.meta.path + '/' + doclet.meta.filename : + doclet.meta.filename; + + return filepath; +} + +function generate(title, docs, filename, resolveLinks) { + resolveLinks = resolveLinks === false ? false : true; + + var docData = { + title: title, + docs: docs + }; + + var outpath = path.join(outdir, filename), + html = view.render('container.tmpl', docData); + + if (resolveLinks) { + html = helper.resolveLinks(html); // turn {@link foo} into foo + } + + fs.writeFileSync(outpath, html, 'utf8'); +} + +function generateSourceFiles(sourceFiles) { + Object.keys(sourceFiles).forEach(function(file) { + var source; + // links are keyed to the shortened path in each doclet's `meta.filename` property + var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened); + helper.registerLink(sourceFiles[file].shortened, sourceOutfile); + + try { + source = { + kind: 'source', + code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, 'utf8') ) + }; + } + catch(e) { + handle(e); + } + + generate('Source: ' + sourceFiles[file].shortened, [source], sourceOutfile, + false); + }); +} + +/** + * 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 + * @param {array} members.events + * @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}); + 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.events.length) { + nav += '

Events

    '; + members.events.forEach(function(e) { + if ( !hasOwnProp.call(seen, e.longname) ) { + nav += '
  • '+linkto(e.longname, e.name)+'
  • '; + } + seen[e.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(taffyData, opts, tutorials) { + data = taffyData; + + var conf = env.conf.templates || {}; + conf['default'] = conf['default'] || {}; + + var templatePath = opts.template; + view = new template.Template(templatePath + '/tmpl'); + + // claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness + // doesn't try to hand them out later + var indexUrl = helper.getUniqueFilename('index'); + // don't call registerLink() on this one! 'index' is also a valid longname + + var globalUrl = helper.getUniqueFilename('global'); + helper.registerLink('global', globalUrl); + + // set up templating + view.layout = 'layout.tmpl'; + + // set up tutorials for helper + helper.setTutorials(tutorials); + + data = helper.prune(data); + data.sort('longname, version, since'); + + var sourceFiles = {}; + var sourceFilePaths = []; + data().each(function(doclet) { + doclet.attribs = ''; + + if (doclet.examples) { + doclet.examples = doclet.examples.map(function(example) { + var caption, code; + + if (example.match(/^\s*([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) { + caption = RegExp.$1; + code = RegExp.$3; + } + + return { + caption: caption || '', + code: code || example + }; + }); + } + if (doclet.see) { + doclet.see.forEach(function(seeItem, i) { + doclet.see[i] = hashToLink(doclet, seeItem); + }); + } + + // build a list of source files + var sourcePath; + var resolvedSourcePath; + if (doclet.meta) { + sourcePath = getPathFromDoclet(doclet); + resolvedSourcePath = resolveSourcePath(sourcePath); + sourceFiles[sourcePath] = { + resolved: resolvedSourcePath, + shortened: null + }; + sourceFilePaths.push(resolvedSourcePath); + } + }); + + // update outdir if necessary, then create outdir + var packageInfo = ( find({kind: 'package'}) || [] ) [0]; + if (packageInfo && packageInfo.name) { + outdir = path.join(outdir, packageInfo.name, packageInfo.version); + } + fs.mkPath(outdir); + + // copy static files to outdir + var fromDir = path.join(templatePath, 'static'), + staticFiles = fs.ls(fromDir, 3); + + staticFiles.forEach(function(fileName) { + var toDir = fs.toDir( fileName.replace(fromDir, outdir) ); + fs.mkPath(toDir); + fs.copyFileSync(fileName, toDir); + }); + + if (sourceFilePaths.length) { + sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) ); + } + data().each(function(doclet) { + var url = helper.createLink(doclet); + helper.registerLink(doclet.longname, url); + + // replace the filename with a shortened version of the full path + var docletPath; + if (doclet.meta) { + docletPath = getPathFromDoclet(doclet); + docletPath = sourceFiles[docletPath].shortened; + if (docletPath) { + doclet.meta.filename = docletPath; + } + } + }); + + data().each(function(doclet) { + var url = helper.longnameToUrl[doclet.longname]; + + if (url.indexOf('#') > -1) { + doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop(); + } + else { + doclet.id = doclet.name; + } + + if ( needsSignature(doclet) ) { + addSignatureParams(doclet); + addSignatureReturns(doclet); + addAttribs(doclet); + } + }); + + // do this after the urls have all been generated + data().each(function(doclet) { + doclet.ancestors = getAncestorLinks(doclet); + + if (doclet.kind === 'member') { + addSignatureTypes(doclet); + addAttribs(doclet); + } + + if (doclet.kind === 'constant') { + addSignatureTypes(doclet); + addAttribs(doclet); + doclet.kind = 'member'; + } + }); + + var members = helper.getMembers(data); + members.tutorials = tutorials.children; + + // add template helpers + view.find = find; + view.linkto = linkto; + view.resolveAuthorLinks = resolveAuthorLinks; + view.tutoriallink = tutoriallink; + view.htmlsafe = htmlsafe; + + // once for all + view.nav = buildNav(members); + + // only output pretty-printed source files if requested; do this before generating any other + // pages, so the other pages can link to the source files + if (conf['default'].outputSourceFiles) { + generateSourceFiles(sourceFiles); + } + + if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); } + + // index page displays information from package.json and lists files + var files = find({kind: 'file'}), + packages = find({kind: 'package'}); + + generate('Index', + packages.concat( + [{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}] + ).concat(files), + indexUrl); + + // set up the lists that we'll use to generate pages + var classes = taffy(members.classes); + var modules = taffy(members.modules); + var namespaces = taffy(members.namespaces); + var mixins = taffy(members.mixins); + var externals = taffy(members.externals); + + for (var longname in helper.longnameToUrl) { + if ( hasOwnProp.call(helper.longnameToUrl, longname) ) { + var myClasses = helper.find(classes, {longname: longname}); + if (myClasses.length) { + generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]); + } + + var myModules = helper.find(modules, {longname: longname}); + if (myModules.length) { + generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]); + } + + var myNamespaces = helper.find(namespaces, {longname: longname}); + if (myNamespaces.length) { + generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]); + } + + var myMixins = helper.find(mixins, {longname: longname}); + if (myMixins.length) { + generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]); + } + + var myExternals = helper.find(externals, {longname: longname}); + if (myExternals.length) { + generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]); + } + } + } + + // TODO: move the tutorial functions to templateHelper.js + function generateTutorial(title, tutorial, filename) { + var tutorialData = { + title: title, + header: tutorial.title, + content: tutorial.parse(), + children: tutorial.children + }; + + var tutorialPath = path.join(outdir, filename), + html = view.render('tutorial.tmpl', tutorialData); + + // yes, you can use {@link} in tutorials too! + html = helper.resolveLinks(html); // turn {@link foo} into foo + + fs.writeFileSync(tutorialPath, html, 'utf8'); + } + + // 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)); + saveChildren(child); + }); + } + saveChildren(tutorials); +}; -- cgit v1.2.3