text: // 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, renderAttributes, 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');
  
    renderAttributes = require('./attribute');
  
    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, dataStructure, dataStructures, err, example, i, item, j, k, knownParams, l, len, len1, len2, len3, meta, name, newParams, param, ref, ref1, ref2, ref3, resource, resourceGroup, results, reversed, schema, 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)));
      }
      if (api.description) {
        api.descriptionHtml = md.render(api.description);
        api.navItems = slugCache._nav;
        slugCache._nav = [];
      }
      ref2 = api.metadata || [];
      for (k = 0, len2 = ref2.length; k < len2; k++) {
        meta = ref2[k];
        if (meta.name === 'HOST') {
          api.host = meta.value;
        }
      }
      ref3 = api.resourceGroups || [];
      results = [];
      for (l = 0, len3 = ref3.length; l < len3; l++) {
        resourceGroup = ref3[l];
        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 len4, m, ref4, results1;
          ref4 = resourceGroup.resources || [];
          results1 = [];
          for (m = 0, len4 = ref4.length; m < len4; m++) {
            resource = ref4[m];
            resource.elementId = slugify(resourceGroup.name + "-" + resource.name, true);
            resource.elementLink = "#" + resource.elementId;
            results1.push((function() {
              var len5, len6, n, o, ref5, results2;
              ref5 = resource.actions || [];
              results2 = [];
              for (n = 0, len5 = ref5.length; n < len5; n++) {
                action = ref5[n];
                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 (o = 0, len6 = reversed.length; o < len6; o++) {
                  param = reversed[o];
                  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;
                action.requestAttributes = [];
                action.hasResponse = false;
                action.responseAttributes = [];
                results2.push((function() {
                  var len7, p, ref6, results3;
                  ref6 = action.examples || [];
                  results3 = [];
                  for (p = 0, len7 = ref6.length; p < len7; p++) {
                    example = ref6[p];
                    results3.push((function() {
                      var len8, q, ref7, results4;
                      ref7 = ['requests', 'responses'];
                      results4 = [];
                      for (q = 0, len8 = ref7.length; q < len8; q++) {
                        name = ref7[q];
                        results4.push((function() {
                          var error, error1, error2, error3, error4, len10, len11, len12, len13, len9, r, ref10, ref11, ref12, ref8, ref9, results5, s, t, u, w;
                          ref8 = example[name] || [];
                          results5 = [];
                          for (r = 0, len9 = ref8.length; r < len9; r++) {
                            item = ref8[r];
                            if (name === 'requests' && !action.hasRequest) {
                              if (item.content) {
                                ref9 = item.content;
                                for (s = 0, len10 = ref9.length; s < len10; s++) {
                                  dataStructure = ref9[s];
                                  if (dataStructure.element === 'dataStructure') {
                                    try {
                                      action.requestAttributes = renderAttributes(dataStructure.content[0], dataStructures).properties;
                                    } catch (error) {
                                      err = error;
                                      if (verbose) {
                                        console.log(dataStructure.content[0]);
                                        console.log(err);
                                      }
                                    }
                                  }
                                }
                              }
                              action.hasRequest = true;
                            }
                            if (name === 'responses' && !action.hasResponse) {
                              if (item.content) {
                                ref10 = item.content;
                                for (t = 0, len11 = ref10.length; t < len11; t++) {
                                  dataStructure = ref10[t];
                                  if (dataStructure.element === 'dataStructure') {
                                    try {
                                      action.responseAttributes = renderAttributes(dataStructure.content[0], dataStructures).properties;
                                    } catch (error1) {
                                      err = error1;
                                      if (verbose) {
                                        console.log(dataStructure.content[0]);
                                        console.log(err);
                                      }
                                    }
                                  }
                                }
                              }
                              action.hasResponse = true;
                            }
                            if (!item.schema && item.content) {
                              ref11 = item.content;
                              for (u = 0, len12 = ref11.length; u < len12; u++) {
                                dataStructure = ref11[u];
                                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 (error2) {
                                    err = error2;
                                    if (verbose) {
                                      console.log(JSON.stringify(dataStructure.content[0], null, 2));
                                      console.log(err);
                                    }
                                  }
                                }
                              }
                            }
                            if (item.content && !process.env.DRAFTER_EXAMPLES) {
                              ref12 = item.content;
                              for (w = 0, len13 = ref12.length; w < len13; w++) {
                                dataStructure = ref12[w];
                                if (dataStructure.element === 'dataStructure') {
                                  try {
                                    item.body = JSON.stringify(renderExample(dataStructure.content[0], dataStructures), null, 2);
                                  } catch (error3) {
                                    err = error3;
                                    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 (error4) {
                              err = error4;
                              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);
  