UNPKG

aglio-theme-tanda

Version:

Tanda theme for the Aglio API Blueprint renderer

742 lines (714 loc) 26.1 kB
// Generated by CoffeeScript 1.10.0 (function() { var ROOT, benchmark, cache, compileTemplate, crypto, decorate, errMsg, fs, getCached, getCss, getTemplate, highlight, hljs, jade, less, markdownIt, modifyUriTemplate, moment, path, querystring, renderExample, renderSchema, sha1, slug; crypto = require('crypto'); fs = require('fs'); hljs = require('highlight.js'); jade = require('jade'); less = require('less'); markdownIt = require('markdown-it'); moment = require('moment'); path = require('path'); querystring = require('querystring'); renderExample = require('./example'); renderSchema = require('./schema'); ROOT = path.dirname(__dirname); cache = {}; benchmark = { start: function(message) { if (process.env.BENCHMARK) { return console.time(message); } }, end: function(message) { if (process.env.BENCHMARK) { return console.timeEnd(message); } } }; errMsg = function(message, err) { err.message = message + ": " + err.message; return err; }; sha1 = function(value) { return crypto.createHash('sha1').update(value.toString()).digest('hex'); }; slug = function(cache, value, unique) { var sluggified; if (cache == null) { cache = {}; } if (value == null) { value = ''; } if (unique == null) { unique = false; } sluggified = value.toLowerCase().replace(/[ \t\n\\<>"'=:\/]/g, '-').replace(/-+/g, '-').replace(/^-/, ''); if (unique) { while (cache[sluggified]) { if (sluggified.match(/\d+$/)) { sluggified = sluggified.replace(/\d+$/, function(value) { return parseInt(value) + 1; }); } else { sluggified = sluggified + '-1'; } } } cache[sluggified] = true; return sluggified; }; highlight = function(code, lang, subset) { var response; benchmark.start("highlight " + lang); response = (function() { switch (lang) { case 'no-highlight': return code; case void 0: case null: case '': return hljs.highlightAuto(code, subset).value; default: return hljs.highlight(lang, code).value; } })(); benchmark.end("highlight " + lang); return response.trim(); }; getCached = function(key, compiledPath, sources, load, done) { var compiledStats, err, error, error1, i, len, loadErr, source, sourceStats; if (process.env.NOCACHE) { return done(null); } if (cache[key]) { return done(null, cache[key]); } try { if (fs.existsSync(compiledPath)) { compiledStats = fs.statSync(compiledPath); for (i = 0, len = sources.length; i < len; i++) { source = sources[i]; sourceStats = fs.statSync(source); if (sourceStats.mtime > compiledStats.mtime) { return done(null); } } try { return load(compiledPath, function(err, item) { if (err) { return done(errMsg('Error loading cached resource', err)); } cache[key] = item; return done(null, cache[key]); }); } catch (error) { loadErr = error; return done(errMsg('Error loading cached resource', loadErr)); } } else { return done(null); } } catch (error1) { err = error1; return done(err); } }; getCss = function(variables, styles, verbose, done) { var compiledPath, customPath, defaultVariablePath, i, item, j, key, len, len1, load, sources, stylePaths, variablePaths; key = "css-" + variables + "-" + styles; if (cache[key]) { return done(null, cache[key]); } compiledPath = path.join(ROOT, 'cache', (sha1(key)) + ".css"); defaultVariablePath = path.join(ROOT, 'styles', 'variables-default.less'); sources = [defaultVariablePath]; if (!Array.isArray(variables)) { variables = [variables]; } if (!Array.isArray(styles)) { styles = [styles]; } variablePaths = [defaultVariablePath]; for (i = 0, len = variables.length; i < len; i++) { item = variables[i]; if (item !== 'default') { customPath = path.join(ROOT, 'styles', "variables-" + item + ".less"); if (!fs.existsSync(customPath)) { customPath = item; if (!fs.existsSync(customPath)) { return done(new Error(customPath + " does not exist!")); } } variablePaths.push(customPath); sources.push(customPath); } } stylePaths = []; for (j = 0, len1 = styles.length; j < len1; j++) { item = styles[j]; customPath = path.join(ROOT, 'styles', "layout-" + item + ".less"); if (!fs.existsSync(customPath)) { customPath = item; if (!fs.existsSync(customPath)) { return done(new Error(customPath + " does not exist!")); } } stylePaths.push(customPath); sources.push(customPath); } load = function(filename, loadDone) { return fs.readFile(filename, 'utf-8', loadDone); }; if (verbose) { console.log("Using variables " + variablePaths); console.log("Using styles " + stylePaths); console.log("Checking cache " + compiledPath); } return getCached(key, compiledPath, sources, load, function(err, css) { var k, l, len2, len3, tmp; if (err) { return done(err); } if (css) { if (verbose) { console.log('Cached version loaded'); } return done(null, css); } if (verbose) { console.log('Not cached or out of date. Generating CSS...'); } tmp = ''; for (k = 0, len2 = variablePaths.length; k < len2; k++) { customPath = variablePaths[k]; tmp += "@import \"" + customPath + "\";\n"; } for (l = 0, len3 = stylePaths.length; l < len3; l++) { customPath = stylePaths[l]; tmp += "@import \"" + customPath + "\";\n"; } benchmark.start('less-compile'); return less.render(tmp, { compress: true }, function(err, result) { var error, writeErr; if (err) { return done(msgErr('Error processing LESS -> CSS', err)); } try { css = result.css; fs.writeFileSync(compiledPath, css, 'utf-8'); } catch (error) { writeErr = error; return done(errMsg('Error writing cached CSS to file', writeErr)); } benchmark.end('less-compile'); cache[key] = css; return done(null, cache[key]); }); }); }; compileTemplate = function(filename, options) { var compiled; return compiled = "var jade = require('jade/runtime');\n" + (jade.compileFileClient(filename, options)) + "\nmodule.exports = compiledFunc;"; }; getTemplate = function(name, verbose, done) { var builtin, compiledPath, key, load; builtin = path.join(ROOT, 'templates', name + ".jade"); if (!fs.existsSync(name) && fs.existsSync(builtin)) { name = builtin; } key = "template-" + name; if (cache[key]) { return done(null, cache[key]); } compiledPath = path.join(ROOT, 'cache', (sha1(key)) + ".js"); load = function(filename, loadDone) { var error, loadErr, loaded; try { loaded = require(filename); } catch (error) { loadErr = error; return loadDone(errMsg('Unable to load template', loadErr)); } return loadDone(null, require(filename)); }; if (verbose) { console.log("Using template " + name); console.log("Checking cache " + compiledPath); } return getCached(key, compiledPath, [name], load, function(err, template) { var compileErr, compileOptions, compiled, error, error1, error2, writeErr; if (err) { return done(err); } if (template) { if (verbose) { console.log('Cached version loaded'); } return done(null, template); } if (verbose) { console.log('Not cached or out of date. Generating template JS...'); } benchmark.start('jade-compile'); compileOptions = { filename: name, name: 'compiledFunc', self: true, compileDebug: false }; try { compiled = compileTemplate(name, compileOptions); } catch (error) { compileErr = error; return done(errMsg('Error compiling template', compileErr)); } if (compiled.indexOf('self.') === -1) { compileOptions.self = false; try { compiled = compileTemplate(name, compileOptions); } catch (error1) { compileErr = error1; return done(errMsg('Error compiling template', compileErr)); } } try { fs.writeFileSync(compiledPath, compiled, 'utf-8'); } catch (error2) { writeErr = error2; return done(errMsg('Error writing cached template file', writeErr)); } benchmark.end('jade-compile'); cache[key] = require(compiledPath); return done(null, cache[key]); }); }; modifyUriTemplate = function(templateUri, parameters, colorize) { var block, closeIndex, index, lastIndex, param, parameterBlocks, parameterNames, parameterSet, parameterValidator; parameterValidator = function(b) { return parameterNames.indexOf(querystring.unescape(b.replace(/^\*|\*$/, ''))) !== -1; }; parameterNames = (function() { var i, len, results; results = []; for (i = 0, len = parameters.length; i < len; i++) { param = parameters[i]; results.push(param.name); } return results; })(); parameterBlocks = []; lastIndex = index = 0; while ((index = templateUri.indexOf("{", index)) !== -1) { parameterBlocks.push(templateUri.substring(lastIndex, index)); block = {}; closeIndex = templateUri.indexOf("}", index); block.querySet = templateUri.indexOf("{?", index) === index; block.formSet = templateUri.indexOf("{&", index) === index; block.reservedSet = templateUri.indexOf("{+", index) === index; lastIndex = closeIndex + 1; index++; if (block.querySet || block.formSet || block.reservedSet) { index++; } parameterSet = templateUri.substring(index, closeIndex); block.parameters = parameterSet.split(",").filter(parameterValidator); if (block.parameters.length) { parameterBlocks.push(block); } } parameterBlocks.push(templateUri.substring(lastIndex, templateUri.length)); return parameterBlocks.reduce(function(uri, v) { var segment; if (typeof v === "string") { uri.push(v); } else { segment = !colorize ? ["{"] : []; if (v.querySet) { segment.push("?"); } if (v.formSet) { segment.push("&"); } if (v.reservedSet && !colorize) { segment.push("+"); } segment.push(v.parameters.map(function(name) { if (!colorize) { return name; } else { name = name.replace(/^\*|\*$/, ''); param = parameters[parameterNames.indexOf(querystring.unescape(name))]; if (v.querySet || v.formSet) { return ("<span class=\"hljs-attribute\">" + name + "=</span>") + ("<span class=\"hljs-literal\">" + (param.example || '') + "</span>"); } else { return "<span class=\"hljs-attribute\" title=\"" + name + "\">" + (param.example || name) + "</span>"; } } }).join(colorize ? '&' : ',')); if (!colorize) { segment.push("}"); } uri.push(segment.join("")); } return uri; }, []).join('').replace(/\/+/g, '/').replace(/\/$/, ''); }; decorate = function(api, md, slugCache, verbose) { var action, category, content_sections, dataStructure, dataStructures, err, example, findListsAndRender, fn, i, item, j, k, knownParams, l, len, len1, len2, len3, len4, m, meta, name, newParams, param, ref, ref1, ref2, ref3, ref4, resource, resourceGroup, results, reversed, schema, section, slugify; slugify = slug.bind(slug, slugCache); dataStructures = {}; ref = api.content || []; for (i = 0, len = ref.length; i < len; i++) { category = ref[i]; ref1 = category.content || []; for (j = 0, len1 = ref1.length; j < len1; j++) { item = ref1[j]; if (item.element === 'dataStructure') { dataStructure = item.content[0]; dataStructures[dataStructure.meta.id] = dataStructure; } } } if (verbose) { console.log("Known data structures: " + (Object.keys(dataStructures))); } findListsAndRender = function(content) { var finalHtml, k, l, len2, len3, ref2, ref3, section, section2; finalHtml = ''; ref2 = content.split('# STARTLIST'); for (k = 0, len2 = ref2.length; k < len2; k++) { section = ref2[k]; ref3 = section.split('# ENDLIST'); for (l = 0, len3 = ref3.length; l < len3; l++) { section2 = ref3[l]; finalHtml += md.render(section2); slugCache._nav.push(['ENDLIST']); } slugCache._nav.pop(); slugCache._nav.push(['STARTLIST']); } slugCache._nav.pop(); return finalHtml; }; if (api.description) { content_sections = api.description.split('# LHSCONTENT'); api.descriptionHtml = []; slugCache._nav = []; api.descriptionHtml.push([findListsAndRender(content_sections[0])]); ref2 = content_sections.slice(1); fn = function() { var ref3, rest, side, sides, sidesContent; sides = section.split('# RHSCONTENT'); ref3 = sides[1].split('# ENDCONTENT'), sides[1] = ref3[0], rest = ref3[1]; sidesContent = (function() { var l, len3, results; results = []; for (l = 0, len3 = sides.length; l < len3; l++) { side = sides[l]; results.push(findListsAndRender(side)); } return results; })(); api.descriptionHtml.push(sidesContent); return api.descriptionHtml.push([findListsAndRender(rest)]); }; for (k = 0, len2 = ref2.length; k < len2; k++) { section = ref2[k]; fn(); } api.navItems = slugCache._nav; slugCache._nav = []; } ref3 = api.metadata || []; for (l = 0, len3 = ref3.length; l < len3; l++) { meta = ref3[l]; if (meta.name === 'HOST') { api.host = meta.value; } } ref4 = api.resourceGroups || []; results = []; for (m = 0, len4 = ref4.length; m < len4; m++) { resourceGroup = ref4[m]; resourceGroup.elementId = slugify(resourceGroup.name, true); resourceGroup.elementLink = "#" + resourceGroup.elementId; if (resourceGroup.description) { resourceGroup.descriptionHtml = md.render(resourceGroup.description); resourceGroup.navItems = slugCache._nav; slugCache._nav = []; } results.push((function() { var len5, n, ref5, results1; ref5 = resourceGroup.resources || []; results1 = []; for (n = 0, len5 = ref5.length; n < len5; n++) { resource = ref5[n]; resource.elementId = slugify(resourceGroup.name + "-" + resource.name, true); resource.elementLink = "#" + resource.elementId; results1.push((function() { var len6, len7, o, p, ref6, results2; ref6 = resource.actions || []; results2 = []; for (o = 0, len6 = ref6.length; o < len6; o++) { action = ref6[o]; action.elementId = slugify(resourceGroup.name + "-" + resource.name + "-" + action.method, true); action.elementLink = "#" + action.elementId; action.methodLower = action.method.toLowerCase(); if (!(action.attributes || {}).uriTemplate) { if (!action.parameters || !action.parameters.length) { action.parameters = resource.parameters; } else if (resource.parameters) { action.parameters = resource.parameters.concat(action.parameters); } } knownParams = {}; newParams = []; reversed = (action.parameters || []).concat([]).reverse(); for (p = 0, len7 = reversed.length; p < len7; p++) { param = reversed[p]; if (knownParams[param.name]) { continue; } knownParams[param.name] = true; newParams.push(param); } action.parameters = newParams.reverse(); action.uriTemplate = modifyUriTemplate((action.attributes || {}).uriTemplate || resource.uriTemplate || '', action.parameters); action.colorizedUriTemplate = modifyUriTemplate((action.attributes || {}).uriTemplate || resource.uriTemplate || '', action.parameters, true); action.hasRequest = false; results2.push((function() { var len8, q, ref7, results3; ref7 = action.examples || []; results3 = []; for (q = 0, len8 = ref7.length; q < len8; q++) { example = ref7[q]; results3.push((function() { var len9, r, ref8, results4; ref8 = ['requests', 'responses']; results4 = []; for (r = 0, len9 = ref8.length; r < len9; r++) { name = ref8[r]; results4.push((function() { var error, error1, error2, len10, len11, len12, ref10, ref11, ref9, results5, s, t, u; ref9 = example[name] || []; results5 = []; for (s = 0, len10 = ref9.length; s < len10; s++) { item = ref9[s]; if (name === 'requests' && !action.hasRequest) { action.hasRequest = true; } if (!item.schema && item.content) { ref10 = item.content; for (t = 0, len11 = ref10.length; t < len11; t++) { dataStructure = ref10[t]; if (dataStructure.element === 'dataStructure') { try { schema = renderSchema(dataStructure.content[0], dataStructures); schema['$schema'] = 'http://json-schema.org/draft-04/schema#'; item.schema = JSON.stringify(schema, null, 2); } catch (error) { err = error; if (verbose) { console.log(JSON.stringify(dataStructure.content[0], null, 2)); console.log(err); } } } } } if (item.content && !process.env.DRAFTER_EXAMPLES) { ref11 = item.content; for (u = 0, len12 = ref11.length; u < len12; u++) { dataStructure = ref11[u]; if (dataStructure.element === 'dataStructure') { try { item.body = JSON.stringify(renderExample(dataStructure.content[0], dataStructures), null, 2); } catch (error1) { err = error1; if (verbose) { console.log(JSON.stringify(dataStructure.content[0], null, 2)); console.log(err); } } } } } item.hasContent = item.description || Object.keys(item.headers).length || item.body || item.schema; try { if (item.body) { item.body = JSON.stringify(JSON.parse(item.body), null, 2); } if (item.schema) { results5.push(item.schema = JSON.stringify(JSON.parse(item.schema), null, 2)); } else { results5.push(void 0); } } catch (error2) { err = error2; results5.push(false); } } return results5; })()); } return results4; })()); } return results3; })()); } return results2; })()); } return results1; })()); } return results; }; exports.getConfig = function() { return { formats: ['1A'], options: [ { name: 'variables', description: 'Color scheme name or path to custom variables', "default": 'default' }, { name: 'condense-nav', description: 'Condense navigation links', boolean: true, "default": true }, { name: 'full-width', description: 'Use full window width', boolean: true, "default": false }, { name: 'template', description: 'Template name or path to custom template', "default": 'default' }, { name: 'style', description: 'Layout style name or path to custom stylesheet' }, { name: 'emoji', description: 'Enable support for emoticons', boolean: true, "default": true } ] }; }; exports.render = function(input, options, done) { var md, slugCache, themeStyle, themeVariables, verbose; if (done == null) { done = options; options = {}; } if (process.env.NOCACHE) { cache = {}; } if (options.condenseNav) { options.themeCondenseNav = options.condenseNav; } if (options.fullWidth) { options.themeFullWidth = options.fullWidth; } if (options.themeVariables == null) { options.themeVariables = 'default'; } if (options.themeStyle == null) { options.themeStyle = 'default'; } if (options.themeTemplate == null) { options.themeTemplate = 'default'; } if (options.themeCondenseNav == null) { options.themeCondenseNav = true; } if (options.themeFullWidth == null) { options.themeFullWidth = false; } if (options.themeTemplate === 'default') { options.themeTemplate = path.join(ROOT, 'templates', 'index.jade'); } slugCache = { _nav: [] }; md = markdownIt({ html: true, linkify: true, typographer: true, highlight: highlight }).use(require('markdown-it-anchor'), { slugify: function(value) { var output; output = "header-" + (slug(slugCache, value, true)); slugCache._nav.push([value, "#" + output]); return output; }, permalink: true, permalinkClass: 'permalink' }).use(require('markdown-it-checkbox')).use(require('markdown-it-container'), 'note').use(require('markdown-it-container'), 'warning'); if (options.themeEmoji) { md.use(require('markdown-it-emoji')); } md.renderer.rules.code_block = md.renderer.rules.fence; benchmark.start('decorate'); decorate(input, md, slugCache, options.verbose); benchmark.end('decorate'); benchmark.start('css-total'); themeVariables = options.themeVariables, themeStyle = options.themeStyle, verbose = options.verbose; return getCss(themeVariables, themeStyle, verbose, function(err, css) { var key, locals, ref, value; if (err) { return done(errMsg('Could not get CSS', err)); } benchmark.end('css-total'); locals = { api: input, condenseNav: options.themeCondenseNav, css: css, fullWidth: options.themeFullWidth, date: moment, hash: function(value) { return crypto.createHash('md5').update(value.toString()).digest('hex'); }, highlight: highlight, markdown: function(content) { return md.render(content); }, slug: slug.bind(slug, slugCache), urldec: function(value) { return querystring.unescape(value); } }; ref = options.locals || {}; for (key in ref) { value = ref[key]; locals[key] = value; } benchmark.start('get-template'); return getTemplate(options.themeTemplate, verbose, function(getTemplateErr, renderer) { var error, html; if (getTemplateErr) { return done(errMsg('Could not get template', getTemplateErr)); } benchmark.end('get-template'); benchmark.start('call-template'); try { html = renderer(locals); } catch (error) { err = error; return done(errMsg('Error calling template during rendering', err)); } benchmark.end('call-template'); return done(null, html); }); }); }; }).call(this);