From 6180a42bcc371549208233496bae5d4c1aa6b64d Mon Sep 17 00:00:00 2001 From: Peter Rottmann <rottmann@inveris.de> Date: Thu, 30 May 2013 23:26:51 +0200 Subject: [PATCH] 0.2.0 Extend apiParam, apiSuccess, apiError with a grouping ability. Add new Functions: apiParamTitle, apiSuccessTitle, apiErrorTitle --- CHANGELOG.md | 11 +- lib/apidoc.js | 13 +- lib/parser.js | 27 +- lib/plugins/filter_api_error.js | 2 +- lib/plugins/filter_api_info.js | 2 +- lib/plugins/filter_api_param.js | 50 ++- lib/plugins/filter_api_success.js | 2 +- lib/plugins/parser_api_error.js | 9 +- lib/plugins/parser_api_error_title.js | 21 ++ lib/plugins/parser_api_info.js | 9 +- lib/plugins/parser_api_info_title.js | 21 ++ lib/plugins/parser_api_param.js | 39 ++- lib/plugins/parser_api_param_title.js | 41 +++ lib/plugins/parser_api_success.js | 9 +- lib/plugins/parser_api_success_title.js | 21 ++ lib/plugins/worker_error_structure.js | 4 +- lib/plugins/worker_error_title.js | 33 ++ lib/plugins/worker_info_title.js | 33 ++ lib/plugins/worker_param_title.js | 89 ++++++ lib/plugins/worker_permission.js | 74 ++--- lib/plugins/worker_structure.js | 55 ++-- lib/plugins/worker_success_structure.js | 4 +- lib/plugins/worker_success_title.js | 33 ++ package.json | 2 +- template/css/style.css | 11 + template/handlebars_helper.js | 158 ++++++---- template/index.html | 158 ++++++---- template/locales/de.js | 3 +- template/main.js | 65 ++-- template/vendor/handlebars.min.js | 120 ++------ template_basic/handlebars_helper.js | 2 +- template_basic/index.html | 30 +- template_basic/locales/de.js | 3 +- template_basic/main.js | 34 ++- test/fixtures/api_data.js | 390 ++++++++++++++++++++++-- test/fixtures/api_data.json | 390 ++++++++++++++++++++++-- test/fixtures/api_project.js | 6 +- test/fixtures/api_project.json | 6 +- test/fixtures/example/example.js | 103 +++++-- 39 files changed, 1564 insertions(+), 519 deletions(-) create mode 100644 lib/plugins/parser_api_error_title.js create mode 100644 lib/plugins/parser_api_info_title.js create mode 100644 lib/plugins/parser_api_param_title.js create mode 100644 lib/plugins/parser_api_success_title.js create mode 100644 lib/plugins/worker_error_title.js create mode 100644 lib/plugins/worker_info_title.js create mode 100644 lib/plugins/worker_param_title.js create mode 100644 lib/plugins/worker_success_title.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b67fcd1..cc659ad0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # apiDoc Changelog +#### 0.2.0 +Extend `@apiParam`, `@apiSuccess`, `@apiError` with a grouping ability. Example `@apiParam (group) varname`. +view [@apiParam](http://apidocjs.com/#param-api-param) +Add new Functions: +* [@apiParamTitle](http://apidocjs.com/#param-api-param-title) +* [@apiSuccessTitle](http://apidocjs.com/#param-api-success-title) +* [@apiErrorTitle](http://apidocjs.com/#param-api-error-title) +Minor Template-Bugfixes. + #### 0.1.11 Allow whitespace in apiName and apiGroup. Bugfix filter for directories. @@ -18,7 +27,7 @@ Fix for whitespace before comment block (Brandon Hamilton https://github.com/api Change templates, enable navigation scroll. #### 0.1.7 -Add [@apiIgnore`](http://apidocjs.com/#param-api-ignore). +Add [@apiIgnore](http://apidocjs.com/#param-api-ignore). Update grunt Modules. #### 0.1.6 diff --git a/lib/apidoc.js b/lib/apidoc.js index 12a32151..3234971e 100644 --- a/lib/apidoc.js +++ b/lib/apidoc.js @@ -90,24 +90,32 @@ var app = { apierror : "./plugins/parser_api_error.js", apierrorexample : "./plugins/parser_api_error_example.js", apierrorstructure : "./plugins/parser_api_error_structure.js", + apierrortitle : "./plugins/parser_api_error_title.js", apiexample : "./plugins/parser_api_example.js", apigroup : "./plugins/parser_api_group.js", apiinfo : "./plugins/parser_api_info.js", apiinfoexample : "./plugins/parser_api_info_example.js", + apiinfotitle : "./plugins/parser_api_info_title.js", apiname : "./plugins/parser_api_name.js", apiparam : "./plugins/parser_api_param.js", + apiparamtitle : "./plugins/parser_api_param_title.js", apipermission : "./plugins/parser_api_permission.js", apistructure : "./plugins/parser_api_structure.js", apisuccess : "./plugins/parser_api_success.js", apisuccessexample : "./plugins/parser_api_success_example.js", apisuccessstructure : "./plugins/parser_api_success_structure.js", + apisuccesstitle : "./plugins/parser_api_success_title.js", apiversion : "./plugins/parser_api_version.js" }, workers: { workererrorstructure : "./plugins/worker_error_structure.js", + workererrortitle : "./plugins/worker_error_title.js", + workerinfotitle : "./plugins/worker_info_title.js", workerpermission : "./plugins/worker_permission.js", workerstructure : "./plugins/worker_structure.js", - workersuccessstructure : "./plugins/worker_success_structure.js" + workerparamtitle : "./plugins/worker_param_title.js", + workersuccessstructure : "./plugins/worker_success_structure.js", + workersuccesstitle : "./plugins/worker_success_title.js" } }; // app @@ -183,7 +191,8 @@ function createOutputFiles(parsedFiles, parsedFilenames, packageInfos) for(var blockIndex = 0; blockIndex < parsedFile.length; blockIndex += 1) { var block = parsedFile[blockIndex]; - if(Object.keys(block.global).length === 0 && Object.keys(block.local).length > 0) + // "<= 1" if successTitle gets removed, empty Object remain. + if(Object.keys(block.global).length <= 1 && Object.keys(block.local).length > 0) { // Add needed Elements for sorting if( ! block.local.group) block.local.group = path.basename( parsedFilenames[fileIndex] ); diff --git a/lib/parser.js b/lib/parser.js index 446580d1..0ab91481 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -135,7 +135,7 @@ Parser.prototype._parseBlockElements = function(indexApiBlocks, detectedElements if(Object.keys(blockData.global).length > 0) { throw new Error("Can't set \"@" + element.sourceName + "\" in file \"" + self.filename + - "\" block number " + (blockIndex + 1) + ", only one define or use is allowed in the same block." + "\" block number " + (blockIndex + 1) + ", only one definition or use is allowed in the same block." ); } } @@ -147,18 +147,23 @@ Parser.prototype._parseBlockElements = function(indexApiBlocks, detectedElements // Only one global allowed per block if(pushTo === "global" || pushTo.substr(0, 7) === "global.") { - if(Object.keys(blockData.global).length > 0) - { - throw new Error("Can't set \"@" + element.sourceName + "\" in file \"" + self.filename + - "\" block number " + (blockIndex + 1) + ", only one define per block allowed." - ); - } + var allowMultiple = self.parsers[element.name].allowMultiple || false; - if(preventGlobal === true) + if( ! allowMultiple) { - throw new Error("Can't set \"@" + element.sourceName + "\" in file \"" + self.filename + - "\" block number " + (blockIndex + 1) + ", only one define or use is allowed in the same block." - ); + if(Object.keys(blockData.global).length > 0) + { + throw new Error("Can't set \"@" + element.sourceName + "\" in file \"" + self.filename + + "\" block number " + (blockIndex + 1) + ", only one definition per block allowed." + ); + } + + if(preventGlobal === true) + { + throw new Error("Can't set \"@" + element.sourceName + "\" in file \"" + self.filename + + "\" block number " + (blockIndex + 1) + ", only one definition or use is allowed in the same block." + ); + } } } diff --git a/lib/plugins/filter_api_error.js b/lib/plugins/filter_api_error.js index eecda0f2..130f70f8 100644 --- a/lib/plugins/filter_api_error.js +++ b/lib/plugins/filter_api_error.js @@ -10,7 +10,7 @@ var filterApiParam = require("./filter_api_param.js"); */ function postFilter(parsedFiles, filenames) { - filterApiParam._postFilter(parsedFiles, filenames, "error"); + filterApiParam.postFilter(parsedFiles, filenames, "error"); } // postFilter /** diff --git a/lib/plugins/filter_api_info.js b/lib/plugins/filter_api_info.js index 2ea84d7c..d32d7f4e 100644 --- a/lib/plugins/filter_api_info.js +++ b/lib/plugins/filter_api_info.js @@ -10,7 +10,7 @@ var filterApiParam = require("./filter_api_param.js"); */ function postFilter(parsedFiles, filenames) { - filterApiParam._postFilter(parsedFiles, filenames, "info"); + filterApiParam.postFilter(parsedFiles, filenames, "info"); } // postFilter /** diff --git a/lib/plugins/filter_api_param.js b/lib/plugins/filter_api_param.js index af0007db..d5915ee7 100644 --- a/lib/plugins/filter_api_param.js +++ b/lib/plugins/filter_api_param.js @@ -1,15 +1,3 @@ -/** - * Post Filter parsed results. - * - * @param {Object[]} parsedFiles - * @param {String[]} filenames - * @returns {Object} - */ -function postFilter(parsedFiles, filenames) -{ - _postFilter(parsedFiles, filenames, "parameter"); -} // postFilter - /** * Post Filter parsed results. * @@ -19,8 +7,9 @@ function postFilter(parsedFiles, filenames) * @returns {Object} * @todo Use elegant Map and Reduce Funktions. */ -function _postFilter(parsedFiles, filenames, tagName) +function postFilter(parsedFiles, filenames, tagName) { + tagName = tagName || "parameter"; for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) { var parsedFile = parsedFiles[fileIndex]; @@ -29,29 +18,34 @@ function _postFilter(parsedFiles, filenames, tagName) var block = parsedFile[blockIndex]; if(block["local"][tagName] && block["local"][tagName]["fields"]) { - // Remove double field params, 1st is newest and is ok - var fields = block["local"][tagName]["fields"]; - var newFields = []; - var keys = {}; - for(var fieldIndex = 0; fieldIndex < fields.length; fieldIndex += 1) + var blockFields = block["local"][tagName]["fields"]; + var blockFieldKeys = Object.keys(blockFields); + for(var blockFieldKeysIndex = 0; blockFieldKeysIndex < blockFieldKeys.length; blockFieldKeysIndex += 1) { - var key = fields[fieldIndex].field; - if( ! keys[key]) + var blockFieldKey = blockFieldKeys[blockFieldKeysIndex]; + // Remove double field params, 1st is newest and is ok + var fields = block["local"][tagName]["fields"][blockFieldKey]; + var newFields = []; + var keys = {}; + for(var fieldIndex = 0; fieldIndex < fields.length; fieldIndex += 1) { - keys[key] = 1; - newFields.push(fields[fieldIndex]); - } - } // for fieldIndex - block["local"][tagName]["fields"] = newFields; + var key = fields[fieldIndex].field; + if( ! keys[key]) + { + keys[key] = 1; + newFields.push(fields[fieldIndex]); + } + } // for fieldIndex + block["local"][tagName]["fields"][blockFieldKey] = newFields; + } // for blockFieldKeysIndex } } // for blockIndex } // for fileIndex -} // _postFilter +} // postFilter /** * Exports. */ module.exports = { - postFilter: postFilter, - _postFilter: _postFilter + postFilter: postFilter }; \ No newline at end of file diff --git a/lib/plugins/filter_api_success.js b/lib/plugins/filter_api_success.js index 1e103011..2047fff4 100644 --- a/lib/plugins/filter_api_success.js +++ b/lib/plugins/filter_api_success.js @@ -10,7 +10,7 @@ var filterApiParam = require("./filter_api_param.js"); */ function postFilter(parsedFiles, filenames) { - filterApiParam._postFilter(parsedFiles, filenames, "success"); + filterApiParam.postFilter(parsedFiles, filenames, "success"); } // postFilter /** diff --git a/lib/plugins/parser_api_error.js b/lib/plugins/parser_api_error.js index 299bef2d..43cefd8d 100644 --- a/lib/plugins/parser_api_error.js +++ b/lib/plugins/parser_api_error.js @@ -1,15 +1,20 @@ // Same as @apiparam var apiParam = require("./parser_api_param.js"); +function parse(content, source) +{ + return apiParam.parse(content, source, "Error 4xx"); +} + function pushTo() { - return "local.error.fields"; + return "local.error.fields." + apiParam.getGroup(); } /** * Exports. */ module.exports = { - parse: apiParam.parse, + parse: parse, pushTo: pushTo }; \ No newline at end of file diff --git a/lib/plugins/parser_api_error_title.js b/lib/plugins/parser_api_error_title.js new file mode 100644 index 00000000..944effa7 --- /dev/null +++ b/lib/plugins/parser_api_error_title.js @@ -0,0 +1,21 @@ +var apiParser = require("./parser_api_param_title.js"); + +function parse(content, source) +{ + return apiParser.parse(content, source); +} // parse + +function pushTo() +{ + return "global.errorTitle"; +} + +/** + * Exports. + */ +module.exports = { + parse: parse, + pushTo: pushTo, + getGroup: apiParser.getGroup, + allowMultiple: true +}; \ No newline at end of file diff --git a/lib/plugins/parser_api_info.js b/lib/plugins/parser_api_info.js index f55e45be..fa6f5f6d 100644 --- a/lib/plugins/parser_api_info.js +++ b/lib/plugins/parser_api_info.js @@ -1,15 +1,20 @@ // Same as @apiparam var apiParam = require("./parser_api_param.js"); +function parse(content, source) +{ + return apiParam.parse(content, source, "Info"); +} + function pushTo() { - return "local.info.fields"; + return "local.info.fields." + apiParam.getGroup(); } /** * Exports. */ module.exports = { - parse: apiParam.parse, + parse: parse, pushTo: pushTo }; \ No newline at end of file diff --git a/lib/plugins/parser_api_info_title.js b/lib/plugins/parser_api_info_title.js new file mode 100644 index 00000000..f440900c --- /dev/null +++ b/lib/plugins/parser_api_info_title.js @@ -0,0 +1,21 @@ +var apiParser = require("./parser_api_param_title.js"); + +function parse(content, source) +{ + return apiParser.parse(content, source); +} // parse + +function pushTo() +{ + return "global.infoTitle"; +} + +/** + * Exports. + */ +module.exports = { + parse: parse, + pushTo: pushTo, + getGroup: apiParser.getGroup, + allowMultiple: true +}; \ No newline at end of file diff --git a/lib/plugins/parser_api_param.js b/lib/plugins/parser_api_param.js index 2515edf5..3df178e1 100644 --- a/lib/plugins/parser_api_param.js +++ b/lib/plugins/parser_api_param.js @@ -1,4 +1,6 @@ -function parse(content) +var group = ""; + +function parse(content, source, defaultGroup) { // Trim content = content.replace(/^\s+|\s+$/g, ""); @@ -6,11 +8,16 @@ function parse(content) // Replace Linebreak with Unicode content = content.replace(/\n/g, "\uffff"); - // Search: type, field, defaultValue, optional, description + // Search: group, type, field, defaultValue, optional, description // Example: {Boolean} [user.name="Default Value"] Users lastname. // RegExp: // ^ // (?: + // (?:\( + // (.+?) ; group + // \)) + // \s*)? + // (?: // (?:\{ // (.+?) ; type // \}) @@ -24,8 +31,7 @@ function parse(content) // \s* // (.*)? ; description // (^@|$) ; Multiline - //var parseRegExp = /^(?:(?:\{(.+?)\})\s*)?(\[?(\S[a-zA-Z0-9._\-]*)(?:=['|"]?([\s.a-zA-Z0-9_\-]*)['|"]?)?\]?)\s*(.*)?$/g; - var parseRegExp = /^(?:(?:\{(.+?)\})\s*)?(\[?(\S[a-zA-Z0-9._\-]*)(?:=['|"]?([\s.a-zA-Z0-9_\-]*)['|"]?)?\]?)\s*(.*)?(^@|$)/g; + var parseRegExp = /^(?:(?:\((.+?)\))\s*)?(?:(?:\{(.+?)\})\s*)?(\[?(\S[a-zA-Z0-9._\-]*)(?:=['|"]?([\s.a-zA-Z0-9_\-]*)['|"]?)?\]?)\s*(.*)?(^@|$)/g; var matches = parseRegExp.exec(content); // function objectValuesToString(obj) // { @@ -67,20 +73,28 @@ function parse(content) if( ! matches) return null; // Reverse Unicode Linebreaks - if(matches[5]) matches[5] = matches[5].replace(/\uffff/g, "\n"); + if(matches[6]) matches[6] = matches[6].replace(/\uffff/g, "\n"); + + group = matches[1] || defaultGroup || "Parameter"; return { - type: matches[1], - field: matches[3], - defaultValue: matches[4], - optional: (matches[2] !== matches[3]) ? true : false, - description: matches[5] + group: group, + type: matches[2], + field: matches[4], + defaultValue: matches[5], + optional: (matches[3] !== matches[4]) ? true : false, + description: matches[6] || "" }; } // parse function pushTo() { - return "local.parameter.fields"; + return "local.parameter.fields." + getGroup(); +} + +function getGroup() +{ + return group; } /** @@ -88,5 +102,6 @@ function pushTo() */ module.exports = { parse: parse, - pushTo: pushTo + pushTo: pushTo, + getGroup: getGroup }; \ No newline at end of file diff --git a/lib/plugins/parser_api_param_title.js b/lib/plugins/parser_api_param_title.js new file mode 100644 index 00000000..64a27ab4 --- /dev/null +++ b/lib/plugins/parser_api_param_title.js @@ -0,0 +1,41 @@ +var group = ""; + +function parse(content, source) +{ + // Trim + content = content.replace(/^\s+|\s+$/g, ""); + + // Replace Linebreak with Unicode + content = content.replace(/\n/g, "\uffff"); + + // Search: group, title + var parseRegExp = /^(?:\((.+?)\))\s*(.*)(^@|$)/g; + var matches = parseRegExp.exec(content); + + if( ! matches) return null; + + return { + group: matches[1], + title: matches[2] + }; +} // parse + +function pushTo() +{ + return "global.paramTitle"; +} + +function getGroup() +{ + return group; +} + +/** + * Exports. + */ +module.exports = { + parse: parse, + pushTo: pushTo, + getGroup: getGroup, + allowMultiple: true +}; \ No newline at end of file diff --git a/lib/plugins/parser_api_success.js b/lib/plugins/parser_api_success.js index 900f33e0..403bc645 100644 --- a/lib/plugins/parser_api_success.js +++ b/lib/plugins/parser_api_success.js @@ -1,15 +1,20 @@ // Same as @apiparam var apiParam = require("./parser_api_param.js"); +function parse(content, source) +{ + return apiParam.parse(content, source, "Success 200"); +} + function pushTo() { - return "local.success.fields"; + return "local.success.fields." + apiParam.getGroup(); } /** * Exports. */ module.exports = { - parse: apiParam.parse, + parse: parse, pushTo: pushTo }; \ No newline at end of file diff --git a/lib/plugins/parser_api_success_title.js b/lib/plugins/parser_api_success_title.js new file mode 100644 index 00000000..df0363f2 --- /dev/null +++ b/lib/plugins/parser_api_success_title.js @@ -0,0 +1,21 @@ +var apiParser = require("./parser_api_param_title.js"); + +function parse(content, source) +{ + return apiParser.parse(content, source); +} // parse + +function pushTo() +{ + return "global.successTitle"; +} + +/** + * Exports. + */ +module.exports = { + parse: parse, + pushTo: pushTo, + getGroup: apiParser.getGroup, + allowMultiple: true +}; \ No newline at end of file diff --git a/lib/plugins/worker_error_structure.js b/lib/plugins/worker_error_structure.js index f0b370b7..e3f23724 100644 --- a/lib/plugins/worker_error_structure.js +++ b/lib/plugins/worker_error_structure.js @@ -9,7 +9,7 @@ var apiWorker = require("./worker_structure.js"); */ function preProcess(parsedFiles, filenames) { - return apiWorker._preProcess(parsedFiles, filenames, "errorStructure", "defineErrorStructure"); + return apiWorker.preProcess(parsedFiles, filenames, "errorStructure", "defineErrorStructure"); } // preProcess /** @@ -21,7 +21,7 @@ function preProcess(parsedFiles, filenames) */ function postProcess(parsedFiles, filenames, preProcessResults) { - apiWorker._postProcess(parsedFiles, filenames, preProcessResults, "errorStructure", "defineErrorStructure"); + apiWorker.postProcess(parsedFiles, filenames, preProcessResults, "errorStructure", "defineErrorStructure"); } // postProcess /** diff --git a/lib/plugins/worker_error_title.js b/lib/plugins/worker_error_title.js new file mode 100644 index 00000000..e889abbf --- /dev/null +++ b/lib/plugins/worker_error_title.js @@ -0,0 +1,33 @@ +var apiWorker = require("./worker_param_title.js"); + +/** + * PreProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @returns {Object} + */ +function preProcess(parsedFiles, filenames) +{ + return apiWorker.preProcess(parsedFiles, filenames, "errorTitle"); +} // preProcess + +/** + * PostProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @param {Object[]} preProcessResults + */ +function postProcess(parsedFiles, filenames, preProcessResults) +{ + apiWorker.postProcess(parsedFiles, filenames, preProcessResults, "error", "errorTitle"); +} // postProcess + +/** + * Exports. + */ +module.exports = { + preProcess: preProcess, + postProcess: postProcess, +}; \ No newline at end of file diff --git a/lib/plugins/worker_info_title.js b/lib/plugins/worker_info_title.js new file mode 100644 index 00000000..c1d89fc3 --- /dev/null +++ b/lib/plugins/worker_info_title.js @@ -0,0 +1,33 @@ +var apiWorker = require("./worker_param_title.js"); + +/** + * PreProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @returns {Object} + */ +function preProcess(parsedFiles, filenames) +{ + return apiWorker.preProcess(parsedFiles, filenames, "infoTitle"); +} // preProcess + +/** + * PostProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @param {Object[]} preProcessResults + */ +function postProcess(parsedFiles, filenames, preProcessResults) +{ + apiWorker.postProcess(parsedFiles, filenames, preProcessResults, "info", "infoTitle"); +} // postProcess + +/** + * Exports. + */ +module.exports = { + preProcess: preProcess, + postProcess: postProcess, +}; \ No newline at end of file diff --git a/lib/plugins/worker_param_title.js b/lib/plugins/worker_param_title.js new file mode 100644 index 00000000..b0d39edc --- /dev/null +++ b/lib/plugins/worker_param_title.js @@ -0,0 +1,89 @@ +/** + * PreProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @returns {Object} + */ +function preProcess(parsedFiles, filenames, defineStructureName) +{ + var result = {}; + defineStructureName = defineStructureName || "paramTitle"; + result[defineStructureName] = []; + for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) + { + var parsedFile = parsedFiles[fileIndex]; + for(var blockIndex = 0; blockIndex < parsedFile.length; blockIndex += 1) + { + var block = parsedFile[blockIndex]; + if(block["global"][defineStructureName]) + { + var entries = block["global"][defineStructureName]; + // Simple append, same Codes too. + for(var entryIndex = 0; entryIndex < entries.length; entryIndex += 1) + { + result[defineStructureName].push(entries[entryIndex]); + } // for entryIndex + + // Unset + delete(block["global"][defineStructureName]); + } + } // for blockIndex + } // for fileIndex + return result; +} // preProcess + +/** + * PostProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @param {Object[]} preProcessResults + */ +function postProcess(parsedFiles, filenames, preProcessResults, structureName, defineStructureName) +{ + structureName = structureName || "parameter"; + defineStructureName = defineStructureName || "paramTitle"; + for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) + { + var parsedFile = parsedFiles[fileIndex]; + for(var blockIndex = 0; blockIndex < parsedFile.length; blockIndex += 1) + { + var block = parsedFile[blockIndex]; + if(block["local"][structureName] && block["local"][structureName]["fields"]) + { + var fields = block["local"][structureName]["fields"]; + var newBlock = {}; // preserve sorting + var blockKeys = Object.keys(fields); + for(var blockKeyIndex = 0; blockKeyIndex < blockKeys.length; blockKeyIndex += 1) + { + var blockKey = blockKeys[blockKeyIndex]; + var blockEntries = block["local"][structureName]["fields"][blockKey]; + var found = false; + for(var preIndex = 0; preIndex < preProcessResults[defineStructureName].length; preIndex += 1) + { + var preEntry = preProcessResults[defineStructureName][preIndex]; + if(preEntry.group === blockKey) + { + found = true; + newBlock[preEntry.title] = blockEntries; + } + } // for preIndex + if( ! found) + { + newBlock[blockKey] = blockEntries; + } + } // for blockKey + block["local"][structureName]["fields"] = newBlock; + } + } // for blockIndex + } // for fileIndex +} // postProcess + +/** + * Exports. + */ +module.exports = { + preProcess: preProcess, + postProcess: postProcess, +}; \ No newline at end of file diff --git a/lib/plugins/worker_permission.js b/lib/plugins/worker_permission.js index b1726325..96e3f787 100644 --- a/lib/plugins/worker_permission.js +++ b/lib/plugins/worker_permission.js @@ -1,30 +1,6 @@ var _ = require("lodash"); // Because of _.merge var semver = require("semver"); -/** - * PreProcess. - * - * @param {Object[]} parsedFiles - * @param {String[]} filenames - * @returns {Object} - */ -function preProcess(parsedFiles, filenames) -{ - return _preProcess(parsedFiles, filenames, "permission", "definePermission"); -} // preProcess - -/** - * PostProcess. - * - * @param {Object[]} parsedFiles - * @param {String[]} filenames - * @param {Object[]} preProcessResults - */ -function postProcess(parsedFiles, filenames, preProcessResults) -{ - _postProcess(parsedFiles, filenames, preProcessResults, "permission", "definePermission"); -} // postProcess - /** * PreProcess. * @@ -34,8 +10,10 @@ function postProcess(parsedFiles, filenames, preProcessResults) * @param {String} defineName * @returns {Object} */ -function _preProcess(parsedFiles, filenames, useName, defineName) +function preProcess(parsedFiles, filenames, useName, defineName) { + useName = useName || "permission"; + defineName = defineName || "definePermission"; var result = {}; for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) { @@ -53,13 +31,14 @@ function _preProcess(parsedFiles, filenames, useName, defineName) version = block.version; } - if( ! result[name]) result[name] = {}; - result[name][version] = block["global"][defineName]; + if( ! result[defineName]) result[defineName] = {}; + if( ! result[defineName][name]) result[defineName][name] = {}; + result[defineName][name][version] = block["global"][defineName]; } } // for blockIndex } // for fileIndex return result; -} // _preProcess +} // preProcess /** * PostProcess. @@ -70,8 +49,10 @@ function _preProcess(parsedFiles, filenames, useName, defineName) * @param {String} findName * @param {String} defineName */ -function _postProcess(parsedFiles, filenames, preProcessResults, findName, defineName) +function postProcess(parsedFiles, filenames, preProcessResults, findName, defineName) { + findName = findName || "permission"; + defineName = defineName || "definePermission"; for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) { var parsedFile = parsedFiles[fileIndex]; @@ -88,14 +69,14 @@ function _postProcess(parsedFiles, filenames, preProcessResults, findName, defin version = block.version; } - if(preProcessResults[name]) + if(preProcessResults[defineName][name]) { var matchedData = {}; var matchedVersion = version; - if(preProcessResults[name][version]) + if(preProcessResults[defineName][name][version]) { // Exact Version - matchedData = preProcessResults[name][version]; + matchedData = preProcessResults[defineName][name][version]; } else { @@ -103,7 +84,7 @@ function _postProcess(parsedFiles, filenames, preProcessResults, findName, defin var foundIndex = -1; var lastVersion = "0.0.0"; - var versionKeys = Object.keys(preProcessResults[name]); + var versionKeys = Object.keys(preProcessResults[defineName][name]); for(var versionIndex = 0; versionIndex < versionKeys.length; versionIndex += 1) { var currentVersion = versionKeys[versionIndex]; @@ -122,7 +103,7 @@ function _postProcess(parsedFiles, filenames, preProcessResults, findName, defin ); } var versionName = versionKeys[foundIndex]; - matchedData = preProcessResults[name][versionName]; + matchedData = preProcessResults[defineName][name][versionName]; } // Copy matched elements into parsed block @@ -138,33 +119,12 @@ function _postProcess(parsedFiles, filenames, preProcessResults, findName, defin } } // for blockIndex } // for fileIndex -} // _postProcess - -/** - * Recursive Merge of Objects with Arrays. - * - * @param block - * @param matchedData - * @todo Bad Hack - watch for something better - */ -function _recursiveMerge(block, matchedData) -{ - _.merge(block, matchedData, function(a, b) { - if(a instanceof Array) return a.concat(b); - if(_.isObject(a)) - { - return _recursiveMerge(a, b); - } - return a; - }); -} // _recursiveMerge +} // postProcess /** * Exports. */ module.exports = { preProcess: preProcess, - postProcess: postProcess, - _preProcess: _preProcess, - _postProcess: _postProcess + postProcess: postProcess }; \ No newline at end of file diff --git a/lib/plugins/worker_structure.js b/lib/plugins/worker_structure.js index 5bcd6c19..39d999ec 100644 --- a/lib/plugins/worker_structure.js +++ b/lib/plugins/worker_structure.js @@ -1,30 +1,6 @@ var _ = require("lodash"); // Because of _.merge var semver = require("semver"); -/** - * PreProcess. - * - * @param {Object[]} parsedFiles - * @param {String[]} filenames - * @returns {Object} - */ -function preProcess(parsedFiles, filenames) -{ - return _preProcess(parsedFiles, filenames, "structure", "defineStructure"); -} // preProcess - -/** - * PostProcess. - * - * @param {Object[]} parsedFiles - * @param {String[]} filenames - * @param {Object[]} preProcessResults - */ -function postProcess(parsedFiles, filenames, preProcessResults) -{ - _postProcess(parsedFiles, filenames, preProcessResults, "structure", "defineStructure"); -} // postProcess - /** * PreProcess. * @@ -34,8 +10,10 @@ function postProcess(parsedFiles, filenames, preProcessResults) * @param {String} defineStructureName * @returns {Object} */ -function _preProcess(parsedFiles, filenames, structureName, defineStructureName) +function preProcess(parsedFiles, filenames, structureName, defineStructureName) { + structureName = structureName || "structure"; + defineStructureName = defineStructureName || "defineStructure"; var result = {}; for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) { @@ -53,13 +31,14 @@ function _preProcess(parsedFiles, filenames, structureName, defineStructureName) version = block.version; } - if( ! result[name]) result[name] = {}; - result[name][version] = block.local; + if( ! result[defineStructureName]) result[defineStructureName] = {}; + if( ! result[defineStructureName][name]) result[defineStructureName][name] = {}; + result[defineStructureName][name][version] = block.local; } } // for blockIndex } // for fileIndex return result; -} // _preProcess +} // preProcess /** * PostProcess. @@ -70,8 +49,10 @@ function _preProcess(parsedFiles, filenames, structureName, defineStructureName) * @param {String} structureName * @param {String} defineStructureName */ -function _postProcess(parsedFiles, filenames, preProcessResults, structureName, defineStructureName) +function postProcess(parsedFiles, filenames, preProcessResults, structureName, defineStructureName) { + structureName = structureName || "structure"; + defineStructureName = defineStructureName || "defineStructure"; for(var fileIndex = 0; fileIndex < parsedFiles.length; fileIndex += 1) { var parsedFile = parsedFiles[fileIndex]; @@ -88,14 +69,14 @@ function _postProcess(parsedFiles, filenames, preProcessResults, structureName, version = block.version; } - if(preProcessResults[name]) + if(preProcessResults[defineStructureName][name]) { var matchedData = {}; var matchedVersion = version; - if(preProcessResults[name][version]) + if(preProcessResults[defineStructureName][name][version]) { // Exact Version - matchedData = preProcessResults[name][version]; + matchedData = preProcessResults[defineStructureName][name][version]; } else { @@ -103,7 +84,7 @@ function _postProcess(parsedFiles, filenames, preProcessResults, structureName, var foundIndex = -1; var lastVersion = "0.0.0"; - var versionKeys = Object.keys(preProcessResults[name]); + var versionKeys = Object.keys(preProcessResults[defineStructureName][name]); for(var versionIndex = 0; versionIndex < versionKeys.length; versionIndex += 1) { var currentVersion = versionKeys[versionIndex]; @@ -122,7 +103,7 @@ function _postProcess(parsedFiles, filenames, preProcessResults, structureName, ); } var versionName = versionKeys[foundIndex]; - matchedData = preProcessResults[name][versionName]; + matchedData = preProcessResults[defineStructureName][name][versionName]; } // Copy matched elements into parsed block @@ -140,7 +121,7 @@ function _postProcess(parsedFiles, filenames, preProcessResults, structureName, } } // for blockIndex } // for fileIndex -} // _postProcess +} // postProcess /** * Recursive Merge of Objects with Arrays. @@ -166,7 +147,5 @@ function _recursiveMerge(block, matchedData) */ module.exports = { preProcess: preProcess, - postProcess: postProcess, - _preProcess: _preProcess, - _postProcess: _postProcess + postProcess: postProcess }; \ No newline at end of file diff --git a/lib/plugins/worker_success_structure.js b/lib/plugins/worker_success_structure.js index afaffae4..b8db13b9 100644 --- a/lib/plugins/worker_success_structure.js +++ b/lib/plugins/worker_success_structure.js @@ -9,7 +9,7 @@ var apiWorker = require("./worker_structure.js"); */ function preProcess(parsedFiles, filenames) { - return apiWorker._preProcess(parsedFiles, filenames, "successStructure", "defineSuccessStructure"); + return apiWorker.preProcess(parsedFiles, filenames, "successStructure", "defineSuccessStructure"); } // preProcess /** @@ -21,7 +21,7 @@ function preProcess(parsedFiles, filenames) */ function postProcess(parsedFiles, filenames, preProcessResults) { - apiWorker._postProcess(parsedFiles, filenames, preProcessResults, "successStructure", "defineSuccessStructure"); + apiWorker.postProcess(parsedFiles, filenames, preProcessResults, "successStructure", "defineSuccessStructure"); } // postProcess /** diff --git a/lib/plugins/worker_success_title.js b/lib/plugins/worker_success_title.js new file mode 100644 index 00000000..cc70f473 --- /dev/null +++ b/lib/plugins/worker_success_title.js @@ -0,0 +1,33 @@ +var apiWorker = require("./worker_param_title.js"); + +/** + * PreProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @returns {Object} + */ +function preProcess(parsedFiles, filenames) +{ + return apiWorker.preProcess(parsedFiles, filenames, "successTitle"); +} // preProcess + +/** + * PostProcess. + * + * @param {Object[]} parsedFiles + * @param {String[]} filenames + * @param {Object[]} preProcessResults + */ +function postProcess(parsedFiles, filenames, preProcessResults) +{ + apiWorker.postProcess(parsedFiles, filenames, preProcessResults, "success", "successTitle"); +} // postProcess + +/** + * Exports. + */ +module.exports = { + preProcess: preProcess, + postProcess: postProcess, +}; \ No newline at end of file diff --git a/package.json b/package.json index 61e3b282..8c48621a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "apidoc", - "version": "0.1.11", + "version": "0.2.0", "description": "RESTful web API Documentation Generator", "author": "Peter Rottmann <rottmann@inveris.de>", "license": "MIT", diff --git a/template/css/style.css b/template/css/style.css index 92acfb57..9b6d266a 100644 --- a/template/css/style.css +++ b/template/css/style.css @@ -315,6 +315,17 @@ pre.del { text-decoration: line-through; } +table.ins th, +table.ins td { + background-color: #60d060; +} + +table.del th, +table.del td { + background-color: #f05050; + text-decoration: line-through; +} + tr.ins td { background-color: #60d060; } diff --git a/template/handlebars_helper.js b/template/handlebars_helper.js index 16484a59..0d950966 100644 --- a/template/handlebars_helper.js +++ b/template/handlebars_helper.js @@ -3,37 +3,6 @@ define([ "handlebars", "diffMatchPatch" ], function(locale, Handlebars, DiffMatchPatch) { - var diffMatchPatch = new DiffMatchPatch(); - - /** - * Overwrite Colors - */ - DiffMatchPatch.prototype.diff_prettyHtml = function(diffs) { - var html = []; - var pattern_amp = /&/g; - var pattern_lt = /</g; - var pattern_gt = />/g; - var pattern_para = /\n/g; - for (var x = 0; x < diffs.length; x++) { - var op = diffs[x][0]; // Operation (insert, delete, equal) - var data = diffs[x][1]; // Text of change. - var text = data.replace(pattern_amp, '&').replace(pattern_lt, '<') - .replace(pattern_gt, '>').replace(pattern_para, '¶<br>'); - switch (op) { - case DIFF_INSERT: - html[x] = '<ins>' + text + '</ins>'; - break; - case DIFF_DELETE: - html[x] = '<del>' + text + '</del>'; - break; - case DIFF_EQUAL: - html[x] = '<span>' + text + '</span>'; - break; - } - } - return html.join(''); - }; - /** * Return localized Text. * @param string text @@ -64,20 +33,6 @@ define([ return ""; }); - /** - * - */ - Handlebars.registerHelper("each_compare_field", function(source, compare, options) { - return _handlebarsEachCompared("field", source, compare, options); - }); - - /** - * - */ - Handlebars.registerHelper("each_compare_title", function(source, compare, options) { - return _handlebarsEachCompared("title", source, compare, options); - }); - /** * */ @@ -93,25 +48,6 @@ define([ return options.inverse(this); }); - /** - * - */ - Handlebars.registerHelper("showDiff", function(source, compare, options) { - var ds = ""; - if(source === compare) ds = source; - else - { - if( ! source) return compare; - if( ! compare) return source; - var d = diffMatchPatch.diff_main(compare, source); - diffMatchPatch.diff_cleanupSemantic(d); - ds = diffMatchPatch.diff_prettyHtml(d); - ds = ds.replace(/¶/gm, ""); - } - if(options === "nl2br") ds = _handlebarsNewlineToBreak(ds); - return ds; - }); - /** * */ @@ -148,6 +84,69 @@ define([ return (text + "").replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, "$1" + "<br>" + "$2"); } // _handlebarsNewlineToBreak + /** + * + */ + Handlebars.registerHelper("each_compare_keys", function(source, compare, options) { + var newSource = []; + if(source) + { + var sourceFields = Object.keys(source); + sourceFields.forEach(function(name) { + var values = {}; + values["value"] = source[name]; + values["key"] = name; + newSource.push(values); + }); + } + + var newCompare = []; + if(compare) + { + var compareFields = Object.keys(compare); + compareFields.forEach(function(name) { + var values = {}; + values["value"] = compare[name]; + values["key"] = name; + newCompare.push(values); + }); + } + return _handlebarsEachCompared("key", newSource, newCompare, options); + }); + + /** + * + */ + Handlebars.registerHelper("each_compare_field", function(source, compare, options) { + return _handlebarsEachCompared("field", source, compare, options); + }); + + /** + * + */ + Handlebars.registerHelper("each_compare_title", function(source, compare, options) { + return _handlebarsEachCompared("title", source, compare, options); + }); + + /** + * + */ + Handlebars.registerHelper("showDiff", function(source, compare, options) { + var ds = ""; + if(source === compare) ds = source; + else + { + if( ! source) return compare; + if( ! compare) return source; + var d = diffMatchPatch.diff_main(compare, source); + diffMatchPatch.diff_cleanupSemantic(d); + ds = diffMatchPatch.diff_prettyHtml(d); + ds = ds.replace(/¶/gm, ""); + } + if(options === "nl2br") ds = _handlebarsNewlineToBreak(ds); + return ds; + }); + /** * */ @@ -216,5 +215,36 @@ define([ return ret; } // _handlebarsEachCompared + var diffMatchPatch = new DiffMatchPatch(); + + /** + * Overwrite Colors + */ + DiffMatchPatch.prototype.diff_prettyHtml = function(diffs) { + var html = []; + var pattern_amp = /&/g; + var pattern_lt = /</g; + var pattern_gt = />/g; + var pattern_para = /\n/g; + for (var x = 0; x < diffs.length; x++) { + var op = diffs[x][0]; // Operation (insert, delete, equal) + var data = diffs[x][1]; // Text of change. + var text = data.replace(pattern_amp, '&').replace(pattern_lt, '<') + .replace(pattern_gt, '>').replace(pattern_para, '¶<br>'); + switch (op) { + case DIFF_INSERT: + html[x] = '<ins>' + text + '</ins>'; + break; + case DIFF_DELETE: + html[x] = '<del>' + text + '</del>'; + break; + case DIFF_EQUAL: + html[x] = '<span>' + text + '</span>'; + break; + } + } + return html.join(''); + }; + return Handlebars; }); \ No newline at end of file diff --git a/template/index.html b/template/index.html index 74784ecd..54a5329f 100644 --- a/template/index.html +++ b/template/index.html @@ -120,42 +120,43 @@ <h1>{{underscoreToSpace article.group}} - {{article.title}}</h1> <pre class="prettyprint language-json" data-type="json"><code>{{{content}}}</code></pre> {{/each}} - {{subTemplate "article-param-block" params=article.parameter _title="Parameter" _hasType=_hasTypeInParameterFields}} - {{subTemplate "article-param-block" params=article.success _title="Success (200)" _hasType=_hasTypeInSuccessFields}} - {{subTemplate "article-param-block" params=article.info _title="Info" _hasType=_hasTypeInInfoFields}} - {{subTemplate "article-param-block" params=article.error _title="Error (4xx)" _col1="Name" _hasType=_hasTypeInErrorFields}} + {{subTemplate "article-param-block" params=article.parameter _hasType=_hasTypeInParameterFields}} + {{subTemplate "article-param-block" params=article.success _hasType=_hasTypeInSuccessFields}} + {{subTemplate "article-param-block" params=article.info _hasType=_hasTypeInInfoFields}} + {{subTemplate "article-param-block" params=article.error _col1="Name" _hasType=_hasTypeInErrorFields}} </article> </script> <script id="template-article-param-block" type="text/x-handlebars-template"> {{#if params}} - <h2>{{__ _title}}</h2> - {{#if params.fields}} + {{#each params.fields}} + <h2>{{__ @key}}</h2> <table> <thead> <tr> <th style="width: 30%">{{#if _col1}}{{__ _col1}}{{else}}{{__ "Field"}}{{/if}}</th> - {{#if _hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} + {{#if ../../_hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} <th style="width: {{#if _hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th> </tr> </thead> <tbody> - {{#each params.fields}} + {{#each this}} <tr> <td class="code">{{{splitFill field "." " "}}}{{#if optional}} <span class="label label-optional">{{__ "optional"}}</span>{{/if}}</td> {{#if ../../_hasType}}<td>{{{type}}}</td>{{/if}} - <td>{{{nl2br description}}}</td> + <td> + {{{nl2br description}}} + {{#if defaultValue}}<p class="default-value">{{__ "Default value:"}} <code>{{{defaultValue}}}</code></p>{{/if}} + </td> </tr> {{/each}} </tbody> </table> - {{else}} - <p>{{__ "No response values."}}</p> - {{/if}} - {{#each params.examples}} - <strong>{{title}}</strong> - <pre class="prettyprint language-json" data-type="json"><code>{{{content}}}</code></pre> + {{#each params.examples}} + <strong>{{title}}</strong> + <pre class="prettyprint language-json" data-type="json"><code>{{{content}}}</code></pre> + {{/each}} {{/each}} {{/if}} </script> @@ -216,10 +217,10 @@ <h1>{{underscoreToSpace article.group}} - {{{showDiff article.title compare.titl {{/each_compare_title}} - {{subTemplate "article-compare-param-block" source=article.parameter compare=compare.parameter _title="Parameter" _hasType=_hasTypeInParameterFields}} - {{subTemplate "article-compare-param-block" source=article.success compare=compare.success _title="Success (200)" _hasType=_hasTypeInSuccessFields}} - {{subTemplate "article-compare-param-block" source=article.info compare=compare.info _title="Info" _hasType=_hasTypeInInfoFields}} - {{subTemplate "article-compare-param-block" source=article.error compare=compare.error _title="Error (4xx)" _col1="Name" _hasType=_hasTypeInErrorFields}} + {{subTemplate "article-compare-param-block" source=article.parameter compare=compare.parameter _hasType=_hasTypeInParameterFields}} + {{subTemplate "article-compare-param-block" source=article.success compare=compare.success _hasType=_hasTypeInSuccessFields}} + {{subTemplate "article-compare-param-block" source=article.info compare=compare.info _hasType=_hasTypeInInfoFields}} + {{subTemplate "article-compare-param-block" source=article.error compare=compare.error _col1="Name" _hasType=_hasTypeInErrorFields}} </article> </script> @@ -304,20 +305,74 @@ <h1>{{underscoreToSpace article.group}} - {{{showDiff article.title compare.titl <script id="template-article-compare-param-block" type="text/x-handlebars-template"> {{#if source}} - <h2>{{__ _title}}</h2> + {{#each_compare_keys source.fields compare.fields}} + {{#if typeSame}} + <h2>{{__ source.key}}</h2> + <table> + <thead> + <tr> + <th style="width: 30%">{{#if _col1}}{{__ _col1}}{{else}}{{__ "Field"}}{{/if}}</th> + {{#if ../../_hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} + <th style="width: {{#if _hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th> + </tr> + </thead> + {{subTemplate "article-compare-param-block-body" source=source.value compare=compare.value _hasType=../../_hasType}} + </table> + {{/if}} - <table> - <thead> - <tr> - <th style="width: 30%">{{#if _col1}}{{__ _col1}}{{else}}{{__ "Field"}}{{/if}}</th> - {{#if _hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} - <th style="width: {{#if _hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th> - </tr> - </thead> + {{#if typeIns}} + <h2><ins>{{__ source.key}}</ins></h2> + <table class="ins"> + <thead> + <tr> + <th style="width: 30%">{{#if _col1}}{{__ _col1}}{{else}}{{__ "Field"}}{{/if}}</th> + {{#if ../../_hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} + <th style="width: {{#if _hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th> + </tr> + </thead> + {{subTemplate "article-compare-param-block-body" source=source.value compare=source.value _hasType=../../_hasType}} + </table> + {{/if}} - <tbody> - {{#each_compare_field source.fields compare.fields}} + {{#if typeDel}} + <h2><del>{{__ compare.key}}</del></h2> + <table class="del"> + <thead> + <tr> + <th style="width: 30%">{{#if _col1}}{{__ _col1}}{{else}}{{__ "Field"}}{{/if}}</th> + {{#if ../../_hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} + <th style="width: {{#if _hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th> + </tr> + </thead> + {{subTemplate "article-compare-param-block-body" source=compare.value compare=compare.value _hasType=../../_hasType}} + </table> + {{/if}} + {{#each_compare_title source.examples compare.examples}} + + {{#if typeSame}} + <strong>{{{showDiff source.title compare.title}}}</strong> + <pre class="prettyprint language-json" data-type="json"><code>{{{showDiff source.content compare.content}}}</code></pre> + {{/if}} + + {{#if typeIns}} + <strong><ins>{{{source.title}}}</ins></strong> + <pre class="ins prettyprint language-json" data-type="json"><code>{{{source.content}}}</code></pre> + {{/if}} + + {{#if typeDel}} + <strong><del>{{{compare.title}}}</del></strong> + <pre class="del prettyprint language-json" data-type="json"><code>{{{compare.content}}}</code></pre> + {{/if}} + + {{/each_compare_title}} + {{/each_compare_keys}} + {{/if}} +</script> + +<script id="template-article-compare-param-block-body" type="text/x-handlebars-template"> + <tbody> + {{#each_compare_field source compare}} {{#if typeSame}} <tr> <td class="code"> @@ -341,12 +396,13 @@ <h2>{{__ _title}}</h2> {{#if compare.type}} <td>{{{compare.type}}}</td> {{else}} - {{#if ../../_hasType}}<td></td>{{/if}} + {{#if ../../../../_hasType}}<td></td>{{/if}} {{/if}} - {{/if}} - - <td>{{{showDiff source.description compare.description "nl2br"}}}</td> + <td> + {{{showDiff source.description compare.description "nl2br"}}} + {{#if source.defaultValue}}<p class="default-value">{{__ "Default value:"}} <code>{{{showDiff source.defaultValue compare.defaultValue}}}</code><p>{{/if}} + </td> </tr> {{/if}} @@ -363,7 +419,10 @@ <h2>{{__ _title}}</h2> {{{typRowTd}}} {{/if}} - <td>{{{nl2br source.description}}}</td> + <td> + {{{nl2br source.description}}} + {{#if source.defaultValue}}<p class="default-value">{{__ "Default value:"}} <code>{{{source.defaultValue}}}</code><p>{{/if}} + </td> </tr> {{/if}} @@ -380,34 +439,15 @@ <h2>{{__ _title}}</h2> {{{typRowTd}}} {{/if}} - <td>{{{nl2br compare.description}}}</td> + <td> + {{{nl2br compare.description}}} + {{#if compare.defaultValue}}<p class="default-value">{{__ "Default value:"}} <code>{{{compare.defaultValue}}}</code><p>{{/if}} + </td> </tr> {{/if}} {{/each_compare_field}} - </tbody> - </table> - - {{#each_compare_title source.examples compare.examples}} - - - {{#if typeSame}} - <strong>{{{showDiff source.title compare.title}}}</strong> - <pre class="prettyprint language-json" data-type="json"><code>{{{showDiff source.content compare.content}}}</code></pre> - {{/if}} - - {{#if typeIns}} - <strong><ins>{{{source.title}}}</ins></strong> - <pre class="ins prettyprint language-json" data-type="json"><code>{{{source.content}}}</code></pre> - {{/if}} - - {{#if typeDel}} - <strong><del>{{{compare.title}}}</del></strong> - <pre class="del prettyprint language-json" data-type="json"><code>{{{compare.content}}}</code></pre> - {{/if}} - - {{/each_compare_title}} - {{/if}} + </tbody> </script> <div class="container-fluid"> diff --git a/template/locales/de.js b/template/locales/de.js index fc941e18..b97f6ccb 100644 --- a/template/locales/de.js +++ b/template/locales/de.js @@ -3,8 +3,8 @@ define({ "Compare all with predecessor": "Vergleiche alle mit ihren Vorgängern", "compare changes to:" : "vergleiche Änderungen mit:", "compared to" : "verglichen mit", + "Default value:" : "Standardwert:", "Description" : "Beschreibung", - "Error (4xx)" : "Error (4xx)", "Field" : "Feld", "General" : "Allgemein", "Generated with" : "Erstellt mit", @@ -14,7 +14,6 @@ define({ "Parameter" : "Parameter", "Permission:" : "Berechtigung:", "show up to version:" : "zeige bis zur Version:", - "Success (200)" : "Success (200)", "Type" : "Typ" } }); \ No newline at end of file diff --git a/template/main.js b/template/main.js index 653a189c..bcb54105 100644 --- a/template/main.js +++ b/template/main.js @@ -78,11 +78,12 @@ require([ // Titel der ersten Einträge von group[].name[] ermitteln (name hat Versionsliste) var titles = {}; $.each(groupEntries, function(index, entries) { - var title = entries[0].title; - if (title) { - title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; }); - titles[title + " #~#" + index] = 1; - } + var title = entries[0].title; + if(title) + { + title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; }); + titles[title + " #~#" + index] = 1; + } }); // each // Sortieren var values = Object.keys(titles); @@ -239,12 +240,12 @@ require([ versions: articleVersions[entry.group][entry.name] }; } - - if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _.any(entry.parameter.fields, function(item) { return item.type; }); - if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _.any(entry.error.fields, function(item) { return item.type; }); - if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _.any(entry.success.fields, function(item) { return item.type; }); - if(entry.info && entry.info.fields) fields._hasTypeInInfoFields = _.any(entry.info.fields, function(item) { return item.type; }); - + + if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + if(entry.info && entry.info.fields) fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); + articles.push({ article: templateArticle(fields), group: entry.group, @@ -283,6 +284,25 @@ require([ $('html,body').animate({ scrollTop: parseInt($(id).offset().top) - 18 }, 0); } + /** + * Check if Parameter (sub) List has a type Field. + * Example: @apaSuccess varname1 No type. + * @apaSuccess {String} varname2 With type. + * + * @param {Object} fields + */ + function _hasTypeInFields(fields) + { + hasField = false; + $.each(fields, function(name) { + if(_.any(fields[name], function(item) { return item.type; }) ) + { + hasField = true; + } + }); + return hasField; + } // _hasTypeInFields + /** * On Template changes, recall plugins. */ @@ -358,7 +378,7 @@ require([ // On change the Version of an article. $("article .versions li.version a").on("click", changeVersionCompareTo); - + /** * */ @@ -406,14 +426,16 @@ require([ }; var entry = sourceEntry; - if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _.any(entry.parameter.fields, function(item) { return item.type; }); - if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _.any(entry.error.fields, function(item) { return item.type; }); - if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _.any(entry.success.fields, function(item) { return item.type; }); + if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + if(entry.info && entry.info.fields) fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); var entry = compareEntry; - if(fields._hasTypeInParameterFields !== true && entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _.any(entry.parameter.fields, function(item) { return item.type; }); - if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _.any(entry.error.fields, function(item) { return item.type; }); - if(fields._hasTypeInParameterFields !== true && entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _.any(entry.success.fields, function(item) { return item.type; }); + if(fields._hasTypeInParameterFields !== true && entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + if(fields._hasTypeInErrorFields !== true && entry.error && entry.error.fields) fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + if(fields._hasTypeInSuccessFields !== true && entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + if(fields._hasTypeInInfoFields !== true && entry.info && entry.info.fields) fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); var content = templateCompareArticle(fields); $root.after(content); @@ -475,9 +497,10 @@ require([ versions: articleVersions[group][name] }; - if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _.any(entry.parameter.fields, function(item) { return item.type; }); - if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _.any(entry.error.fields, function(item) { return item.type; }); - if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _.any(entry.success.fields, function(item) { return item.type; }); + if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + if(entry.info && entry.info.fields) fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); return templateArticle(fields); } // renderArticle diff --git a/template/vendor/handlebars.min.js b/template/vendor/handlebars.min.js index afd91781..1915ee69 100644 --- a/template/vendor/handlebars.min.js +++ b/template/vendor/handlebars.min.js @@ -1,96 +1,24 @@ -this.Handlebars={}; -(function(Handlebars){Handlebars.VERSION="1.0.0-rc.3";Handlebars.COMPILER_REVISION=2;Handlebars.REVISION_CHANGES={1:"<= 1.0.rc.2",2:">= 1.0.0-rc.3"};Handlebars.helpers={};Handlebars.partials={};Handlebars.registerHelper=function(name,fn,inverse){if(inverse)fn.not=inverse;this.helpers[name]=fn};Handlebars.registerPartial=function(name,str){this.partials[name]=str};Handlebars.registerHelper("helperMissing",function(arg){if(arguments.length===2)return undefined;else throw new Error("Could not find property '"+arg+ -"'");});var toString=Object.prototype.toString,functionType="[object Function]";Handlebars.registerHelper("blockHelperMissing",function(context,options){var inverse=options.inverse||function(){},fn=options.fn;var ret="";var type=toString.call(context);if(type===functionType)context=context.call(this);if(context===true)return fn(this);else if(context===false||context==null)return inverse(this);else if(type==="[object Array]")if(context.length>0)return Handlebars.helpers.each(context,options);else return inverse(this); -else return fn(context)});Handlebars.K=function(){};Handlebars.createFrame=Object.create||function(object){Handlebars.K.prototype=object;var obj=new Handlebars.K;Handlebars.K.prototype=null;return obj};Handlebars.logger={DEBUG:0,INFO:1,WARN:2,ERROR:3,level:3,methodMap:{"0":"debug",1:"info",2:"warn",3:"error"},log:function(level,obj){if(Handlebars.logger.level<=level){var method=Handlebars.logger.methodMap[level];if(typeof console!=="undefined"&&console[method])console[method].call(console,obj)}}}; -Handlebars.log=function(level,obj){Handlebars.logger.log(level,obj)};Handlebars.registerHelper("each",function(context,options){var fn=options.fn,inverse=options.inverse;var i=0,ret="",data;if(options.data)data=Handlebars.createFrame(options.data);if(context&&typeof context==="object")if(context instanceof Array)for(var j=context.length;i<j;i++){if(data)data.index=i;ret=ret+fn(context[i],{data:data})}else for(var key in context)if(context.hasOwnProperty(key)){if(data)data.key=key;ret=ret+fn(context[key], -{data:data});i++}if(i===0)ret=inverse(this);return ret});Handlebars.registerHelper("if",function(context,options){var type=toString.call(context);if(type===functionType)context=context.call(this);if(!context||Handlebars.Utils.isEmpty(context))return options.inverse(this);else return options.fn(this)});Handlebars.registerHelper("unless",function(context,options){var fn=options.fn,inverse=options.inverse;options.fn=inverse;options.inverse=fn;return Handlebars.helpers["if"].call(this,context,options)}); -Handlebars.registerHelper("with",function(context,options){return options.fn(context)});Handlebars.registerHelper("log",function(context,options){var level=options.data&&options.data.level!=null?parseInt(options.data.level,10):1;Handlebars.log(level,context)})})(this.Handlebars); -var handlebars=function(){var parser={trace:function trace(){},yy:{},symbols_:{"error":2,"root":3,"program":4,"EOF":5,"simpleInverse":6,"statements":7,"statement":8,"openInverse":9,"closeBlock":10,"openBlock":11,"mustache":12,"partial":13,"CONTENT":14,"COMMENT":15,"OPEN_BLOCK":16,"inMustache":17,"CLOSE":18,"OPEN_INVERSE":19,"OPEN_ENDBLOCK":20,"path":21,"OPEN":22,"OPEN_UNESCAPED":23,"OPEN_PARTIAL":24,"partialName":25,"params":26,"hash":27,"DATA":28,"param":29,"STRING":30,"INTEGER":31,"BOOLEAN":32, -"hashSegments":33,"hashSegment":34,"ID":35,"EQUALS":36,"PARTIAL_NAME":37,"pathSegments":38,"SEP":39,"$accept":0,"$end":1},terminals_:{2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"DATA",30:"STRING",31:"INTEGER",32:"BOOLEAN",35:"ID",36:"EQUALS",37:"PARTIAL_NAME",39:"SEP"},productions_:[0,[3,2],[4,2],[4,3],[4,2],[4,1],[4,1],[4,0],[7,1],[7,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9, -3],[10,3],[12,3],[12,3],[13,3],[13,4],[6,2],[17,3],[17,2],[17,2],[17,1],[17,1],[26,2],[26,1],[29,1],[29,1],[29,1],[29,1],[29,1],[27,1],[33,2],[33,1],[34,3],[34,3],[34,3],[34,3],[34,3],[25,1],[21,1],[38,3],[38,1]],performAction:function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$){var $0=$$.length-1;switch(yystate){case 1:return $$[$0-1];break;case 2:this.$=new yy.ProgramNode([],$$[$0]);break;case 3:this.$=new yy.ProgramNode($$[$0-2],$$[$0]);break;case 4:this.$=new yy.ProgramNode($$[$0-1],[]); -break;case 5:this.$=new yy.ProgramNode($$[$0]);break;case 6:this.$=new yy.ProgramNode([],[]);break;case 7:this.$=new yy.ProgramNode([]);break;case 8:this.$=[$$[$0]];break;case 9:$$[$0-1].push($$[$0]);this.$=$$[$0-1];break;case 10:this.$=new yy.BlockNode($$[$0-2],$$[$0-1].inverse,$$[$0-1],$$[$0]);break;case 11:this.$=new yy.BlockNode($$[$0-2],$$[$0-1],$$[$0-1].inverse,$$[$0]);break;case 12:this.$=$$[$0];break;case 13:this.$=$$[$0];break;case 14:this.$=new yy.ContentNode($$[$0]);break;case 15:this.$= -new yy.CommentNode($$[$0]);break;case 16:this.$=new yy.MustacheNode($$[$0-1][0],$$[$0-1][1]);break;case 17:this.$=new yy.MustacheNode($$[$0-1][0],$$[$0-1][1]);break;case 18:this.$=$$[$0-1];break;case 19:this.$=new yy.MustacheNode($$[$0-1][0],$$[$0-1][1]);break;case 20:this.$=new yy.MustacheNode($$[$0-1][0],$$[$0-1][1],true);break;case 21:this.$=new yy.PartialNode($$[$0-1]);break;case 22:this.$=new yy.PartialNode($$[$0-2],$$[$0-1]);break;case 23:break;case 24:this.$=[[$$[$0-2]].concat($$[$0-1]),$$[$0]]; -break;case 25:this.$=[[$$[$0-1]].concat($$[$0]),null];break;case 26:this.$=[[$$[$0-1]],$$[$0]];break;case 27:this.$=[[$$[$0]],null];break;case 28:this.$=[[new yy.DataNode($$[$0])],null];break;case 29:$$[$0-1].push($$[$0]);this.$=$$[$0-1];break;case 30:this.$=[$$[$0]];break;case 31:this.$=$$[$0];break;case 32:this.$=new yy.StringNode($$[$0]);break;case 33:this.$=new yy.IntegerNode($$[$0]);break;case 34:this.$=new yy.BooleanNode($$[$0]);break;case 35:this.$=new yy.DataNode($$[$0]);break;case 36:this.$= -new yy.HashNode($$[$0]);break;case 37:$$[$0-1].push($$[$0]);this.$=$$[$0-1];break;case 38:this.$=[$$[$0]];break;case 39:this.$=[$$[$0-2],$$[$0]];break;case 40:this.$=[$$[$0-2],new yy.StringNode($$[$0])];break;case 41:this.$=[$$[$0-2],new yy.IntegerNode($$[$0])];break;case 42:this.$=[$$[$0-2],new yy.BooleanNode($$[$0])];break;case 43:this.$=[$$[$0-2],new yy.DataNode($$[$0])];break;case 44:this.$=new yy.PartialNameNode($$[$0]);break;case 45:this.$=new yy.IdNode($$[$0]);break;case 46:$$[$0-2].push($$[$0]); -this.$=$$[$0-2];break;case 47:this.$=[$$[$0]];break}},table:[{3:1,4:2,5:[2,7],6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],22:[1,14],23:[1,15],24:[1,16]},{1:[3]},{5:[1,17]},{5:[2,6],7:18,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,6],22:[1,14],23:[1,15],24:[1,16]},{5:[2,5],6:20,8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,5],22:[1,14],23:[1,15],24:[1,16]},{17:23,18:[1,22],21:24,28:[1,25],35:[1,27],38:26},{5:[2,8],14:[2,8], -15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{4:28,6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,7],22:[1,14],23:[1,15],24:[1,16]},{4:29,6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,7],22:[1,14],23:[1,15],24:[1,16]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,14],14:[2,14],15:[2, -14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{17:30,21:24,28:[1,25],35:[1,27],38:26},{17:31,21:24,28:[1,25],35:[1,27],38:26},{17:32,21:24,28:[1,25],35:[1,27],38:26},{25:33,37:[1,34]},{1:[2,1]},{5:[2,2],8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,2],22:[1,14],23:[1,15],24:[1,16]},{17:23,21:24,28:[1,25],35:[1,27],38:26},{5:[2,4],7:35,8:6,9:7,11:8,12:9,13:10,14:[1, -11],15:[1,12],16:[1,13],19:[1,19],20:[2,4],22:[1,14],23:[1,15],24:[1,16]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,23],14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],24:[2,23]},{18:[1,36]},{18:[2,27],21:41,26:37,27:38,28:[1,45],29:39,30:[1,42],31:[1,43],32:[1,44],33:40,34:46,35:[1,47],38:26},{18:[2,28]},{18:[2,45],28:[2,45],30:[2,45],31:[2,45],32:[2,45],35:[2,45],39:[1,48]},{18:[2,47],28:[2,47],30:[2,47],31:[2,47],32:[2,47],35:[2, -47],39:[2,47]},{10:49,20:[1,50]},{10:51,20:[1,50]},{18:[1,52]},{18:[1,53]},{18:[1,54]},{18:[1,55],21:56,35:[1,27],38:26},{18:[2,44],35:[2,44]},{5:[2,3],8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,3],22:[1,14],23:[1,15],24:[1,16]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{18:[2,25],21:41,27:57,28:[1,45],29:58,30:[1,42],31:[1,43],32:[1,44],33:40,34:46,35:[1,47],38:26},{18:[2,26]},{18:[2,30],28:[2,30],30:[2,30],31:[2,30],32:[2,30],35:[2, -30]},{18:[2,36],34:59,35:[1,60]},{18:[2,31],28:[2,31],30:[2,31],31:[2,31],32:[2,31],35:[2,31]},{18:[2,32],28:[2,32],30:[2,32],31:[2,32],32:[2,32],35:[2,32]},{18:[2,33],28:[2,33],30:[2,33],31:[2,33],32:[2,33],35:[2,33]},{18:[2,34],28:[2,34],30:[2,34],31:[2,34],32:[2,34],35:[2,34]},{18:[2,35],28:[2,35],30:[2,35],31:[2,35],32:[2,35],35:[2,35]},{18:[2,38],35:[2,38]},{18:[2,47],28:[2,47],30:[2,47],31:[2,47],32:[2,47],35:[2,47],36:[1,61],39:[2,47]},{35:[1,62]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2, -10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{21:63,35:[1,27],38:26},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21], -24:[2,21]},{18:[1,64]},{18:[2,24]},{18:[2,29],28:[2,29],30:[2,29],31:[2,29],32:[2,29],35:[2,29]},{18:[2,37],35:[2,37]},{36:[1,61]},{21:65,28:[1,69],30:[1,66],31:[1,67],32:[1,68],35:[1,27],38:26},{18:[2,46],28:[2,46],30:[2,46],31:[2,46],32:[2,46],35:[2,46],39:[2,46]},{18:[1,70]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],24:[2,22]},{18:[2,39],35:[2,39]},{18:[2,40],35:[2,40]},{18:[2,41],35:[2,41]},{18:[2,42],35:[2,42]},{18:[2,43],35:[2,43]},{5:[2,18],14:[2,18],15:[2, -18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]}],defaultActions:{17:[2,1],25:[2,28],38:[2,26],57:[2,24]},parseError:function parseError(str,hash){throw new Error(str);},parse:function parse(input){var self=this,stack=[0],vstack=[null],lstack=[],table=this.table,yytext="",yylineno=0,yyleng=0,recovering=0,TERROR=2,EOF=1;this.lexer.setInput(input);this.lexer.yy=this.yy;this.yy.lexer=this.lexer;this.yy.parser=this;if(typeof this.lexer.yylloc=="undefined")this.lexer.yylloc={};var yyloc= -this.lexer.yylloc;lstack.push(yyloc);var ranges=this.lexer.options&&this.lexer.options.ranges;if(typeof this.yy.parseError==="function")this.parseError=this.yy.parseError;function popStack(n){stack.length=stack.length-2*n;vstack.length=vstack.length-n;lstack.length=lstack.length-n}function lex(){var token;token=self.lexer.lex()||1;if(typeof token!=="number")token=self.symbols_[token]||token;return token}var symbol,preErrorSymbol,state,action,a,r,yyval={},p,len,newState,expected;while(true){state= -stack[stack.length-1];if(this.defaultActions[state])action=this.defaultActions[state];else{if(symbol===null||typeof symbol=="undefined")symbol=lex();action=table[state]&&table[state][symbol]}if(typeof action==="undefined"||!action.length||!action[0]){var errStr="";if(!recovering){expected=[];for(p in table[state])if(this.terminals_[p]&&p>2)expected.push("'"+this.terminals_[p]+"'");if(this.lexer.showPosition)errStr="Parse error on line "+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+ -expected.join(", ")+", got '"+(this.terminals_[symbol]||symbol)+"'";else errStr="Parse error on line "+(yylineno+1)+": Unexpected "+(symbol==1?"end of input":"'"+(this.terminals_[symbol]||symbol)+"'");this.parseError(errStr,{text:this.lexer.match,token:this.terminals_[symbol]||symbol,line:this.lexer.yylineno,loc:yyloc,expected:expected})}}if(action[0]instanceof Array&&action.length>1)throw new Error("Parse Error: multiple actions possible at state: "+state+", token: "+symbol);switch(action[0]){case 1:stack.push(symbol); -vstack.push(this.lexer.yytext);lstack.push(this.lexer.yylloc);stack.push(action[1]);symbol=null;if(!preErrorSymbol){yyleng=this.lexer.yyleng;yytext=this.lexer.yytext;yylineno=this.lexer.yylineno;yyloc=this.lexer.yylloc;if(recovering>0)recovering--}else{symbol=preErrorSymbol;preErrorSymbol=null}break;case 2:len=this.productions_[action[1]][1];yyval.$=vstack[vstack.length-len];yyval._$={first_line:lstack[lstack.length-(len||1)].first_line,last_line:lstack[lstack.length-1].last_line,first_column:lstack[lstack.length- -(len||1)].first_column,last_column:lstack[lstack.length-1].last_column};if(ranges)yyval._$.range=[lstack[lstack.length-(len||1)].range[0],lstack[lstack.length-1].range[1]];r=this.performAction.call(yyval,yytext,yyleng,yylineno,this.yy,action[1],vstack,lstack);if(typeof r!=="undefined")return r;if(len){stack=stack.slice(0,-1*len*2);vstack=vstack.slice(0,-1*len);lstack=lstack.slice(0,-1*len)}stack.push(this.productions_[action[1]][0]);vstack.push(yyval.$);lstack.push(yyval._$);newState=table[stack[stack.length- -2]][stack[stack.length-1]];stack.push(newState);break;case 3:return true}}return true}};var lexer=function(){var lexer={EOF:1,parseError:function parseError(str,hash){if(this.yy.parser)this.yy.parser.parseError(str,hash);else throw new Error(str);},setInput:function(input){this._input=input;this._more=this._less=this.done=false;this.yylineno=this.yyleng=0;this.yytext=this.matched=this.match="";this.conditionStack=["INITIAL"];this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0};if(this.options.ranges)this.yylloc.range= -[0,0];this.offset=0;return this},input:function(){var ch=this._input[0];this.yytext+=ch;this.yyleng++;this.offset++;this.match+=ch;this.matched+=ch;var lines=ch.match(/(?:\r\n?|\n).*/g);if(lines){this.yylineno++;this.yylloc.last_line++}else this.yylloc.last_column++;if(this.options.ranges)this.yylloc.range[1]++;this._input=this._input.slice(1);return ch},unput:function(ch){var len=ch.length;var lines=ch.split(/(?:\r\n?|\n)/g);this._input=ch+this._input;this.yytext=this.yytext.substr(0,this.yytext.length- -len-1);this.offset-=len;var oldLines=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1);this.matched=this.matched.substr(0,this.matched.length-1);if(lines.length-1)this.yylineno-=lines.length-1;var r=this.yylloc.range;this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:lines?(lines.length===oldLines.length?this.yylloc.first_column:0)+oldLines[oldLines.length-lines.length].length-lines[0].length: -this.yylloc.first_column-len};if(this.options.ranges)this.yylloc.range=[r[0],r[0]+this.yyleng-len];return this},more:function(){this._more=true;return this},less:function(n){this.unput(this.match.slice(n))},pastInput:function(){var past=this.matched.substr(0,this.matched.length-this.match.length);return(past.length>20?"...":"")+past.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var next=this.match;if(next.length<20)next+=this._input.substr(0,20-next.length);return(next.substr(0,20)+(next.length> -20?"...":"")).replace(/\n/g,"")},showPosition:function(){var pre=this.pastInput();var c=(new Array(pre.length+1)).join("-");return pre+this.upcomingInput()+"\n"+c+"^"},next:function(){if(this.done)return this.EOF;if(!this._input)this.done=true;var token,match,tempMatch,index,col,lines;if(!this._more){this.yytext="";this.match=""}var rules=this._currentRules();for(var i=0;i<rules.length;i++){tempMatch=this._input.match(this.rules[rules[i]]);if(tempMatch&&(!match||tempMatch[0].length>match[0].length)){match= -tempMatch;index=i;if(!this.options.flex)break}}if(match){lines=match[0].match(/(?:\r\n?|\n).*/g);if(lines)this.yylineno+=lines.length;this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:lines?lines[lines.length-1].length-lines[lines.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+match[0].length};this.yytext+=match[0];this.match+=match[0];this.matches=match;this.yyleng=this.yytext.length;if(this.options.ranges)this.yylloc.range= -[this.offset,this.offset+=this.yyleng];this._more=false;this._input=this._input.slice(match[0].length);this.matched+=match[0];token=this.performAction.call(this,this.yy,this,rules[index],this.conditionStack[this.conditionStack.length-1]);if(this.done&&this._input)this.done=false;if(token)return token;else return}if(this._input==="")return this.EOF;else return this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})}, -lex:function lex(){var r=this.next();if(typeof r!=="undefined")return r;else return this.lex()},begin:function begin(condition){this.conditionStack.push(condition)},popState:function popState(){return this.conditionStack.pop()},_currentRules:function _currentRules(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function begin(condition){this.begin(condition)}};lexer.options={}; -lexer.performAction=function anonymous(yy,yy_,$avoiding_name_collisions,YY_START){var YYSTATE=YY_START;switch($avoiding_name_collisions){case 0:if(yy_.yytext.slice(-1)!=="\\")this.begin("mu");if(yy_.yytext.slice(-1)==="\\")yy_.yytext=yy_.yytext.substr(0,yy_.yyleng-1),this.begin("emu");if(yy_.yytext)return 14;break;case 1:return 14;break;case 2:if(yy_.yytext.slice(-1)!=="\\")this.popState();if(yy_.yytext.slice(-1)==="\\")yy_.yytext=yy_.yytext.substr(0,yy_.yyleng-1);return 14;break;case 3:yy_.yytext= -yy_.yytext.substr(0,yy_.yyleng-4);this.popState();return 15;break;case 4:this.begin("par");return 24;break;case 5:return 16;break;case 6:return 20;break;case 7:return 19;break;case 8:return 19;break;case 9:return 23;break;case 10:return 23;break;case 11:this.popState();this.begin("com");break;case 12:yy_.yytext=yy_.yytext.substr(3,yy_.yyleng-5);this.popState();return 15;break;case 13:return 22;break;case 14:return 36;break;case 15:return 35;break;case 16:return 35;break;case 17:return 39;break;case 18:break; -case 19:this.popState();return 18;break;case 20:this.popState();return 18;break;case 21:yy_.yytext=yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\"/g,'"');return 30;break;case 22:yy_.yytext=yy_.yytext.substr(1,yy_.yyleng-2).replace(/\\'/g,"'");return 30;break;case 23:yy_.yytext=yy_.yytext.substr(1);return 28;break;case 24:return 32;break;case 25:return 32;break;case 26:return 31;break;case 27:return 35;break;case 28:yy_.yytext=yy_.yytext.substr(1,yy_.yyleng-2);return 35;break;case 29:return"INVALID"; -break;case 30:break;case 31:this.popState();return 37;break;case 32:return 5;break}};lexer.rules=[/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[} ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/, -/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:\s+)/,/^(?:[a-zA-Z0-9_$-/]+)/,/^(?:$)/];lexer.conditions={"mu":{"rules":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,32],"inclusive":false},"emu":{"rules":[2],"inclusive":false},"com":{"rules":[3],"inclusive":false},"par":{"rules":[30,31],"inclusive":false},"INITIAL":{"rules":[0,1,32],"inclusive":true}};return lexer}();parser.lexer=lexer; -function Parser(){this.yy={}}Parser.prototype=parser;parser.Parser=Parser;return new Parser}();Handlebars.Parser=handlebars;Handlebars.parse=function(input){if(input.constructor===Handlebars.AST.ProgramNode)return input;Handlebars.Parser.yy=Handlebars.AST;return Handlebars.Parser.parse(input)};Handlebars.print=function(ast){return(new Handlebars.PrintVisitor).accept(ast)}; -(function(){Handlebars.AST={};Handlebars.AST.ProgramNode=function(statements,inverse){this.type="program";this.statements=statements;if(inverse)this.inverse=new Handlebars.AST.ProgramNode(inverse)};Handlebars.AST.MustacheNode=function(rawParams,hash,unescaped){this.type="mustache";this.escaped=!unescaped;this.hash=hash;var id=this.id=rawParams[0];var params=this.params=rawParams.slice(1);var eligibleHelper=this.eligibleHelper=id.isSimple;this.isHelper=eligibleHelper&&(params.length||hash)};Handlebars.AST.PartialNode= -function(partialName,context){this.type="partial";this.partialName=partialName;this.context=context};var verifyMatch=function(open,close){if(open.original!==close.original)throw new Handlebars.Exception(open.original+" doesn't match "+close.original);};Handlebars.AST.BlockNode=function(mustache,program,inverse,close){verifyMatch(mustache.id,close);this.type="block";this.mustache=mustache;this.program=program;this.inverse=inverse;if(this.inverse&&!this.program)this.isInverse=true};Handlebars.AST.ContentNode= -function(string){this.type="content";this.string=string};Handlebars.AST.HashNode=function(pairs){this.type="hash";this.pairs=pairs};Handlebars.AST.IdNode=function(parts){this.type="ID";this.original=parts.join(".");var dig=[],depth=0;for(var i=0,l=parts.length;i<l;i++){var part=parts[i];if(part===".."||part==="."||part==="this")if(dig.length>0)throw new Handlebars.Exception("Invalid path: "+this.original);else if(part==="..")depth++;else this.isScoped=true;else dig.push(part)}this.parts=dig;this.string= -dig.join(".");this.depth=depth;this.isSimple=parts.length===1&&!this.isScoped&&depth===0;this.stringModeValue=this.string};Handlebars.AST.PartialNameNode=function(name){this.type="PARTIAL_NAME";this.name=name};Handlebars.AST.DataNode=function(id){this.type="DATA";this.id=id};Handlebars.AST.StringNode=function(string){this.type="STRING";this.string=string;this.stringModeValue=string};Handlebars.AST.IntegerNode=function(integer){this.type="INTEGER";this.integer=integer;this.stringModeValue=Number(integer)}; -Handlebars.AST.BooleanNode=function(bool){this.type="BOOLEAN";this.bool=bool;this.stringModeValue=bool==="true"};Handlebars.AST.CommentNode=function(comment){this.type="comment";this.comment=comment}})();var errorProps=["description","fileName","lineNumber","message","name","number","stack"];Handlebars.Exception=function(message){var tmp=Error.prototype.constructor.apply(this,arguments);for(var idx=0;idx<errorProps.length;idx++)this[errorProps[idx]]=tmp[errorProps[idx]]}; -Handlebars.Exception.prototype=new Error;Handlebars.SafeString=function(string){this.string=string};Handlebars.SafeString.prototype.toString=function(){return this.string.toString()}; -(function(){var escape={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};var badChars=/[&<>"'`]/g;var possible=/[&<>"'`]/;var escapeChar=function(chr){return escape[chr]||"&"};Handlebars.Utils={escapeExpression:function(string){if(string instanceof Handlebars.SafeString)return string.toString();else if(string==null||string===false)return"";if(!possible.test(string))return string;return string.replace(badChars,escapeChar)},isEmpty:function(value){if(!value&&value!==0)return true; -else if(Object.prototype.toString.call(value)==="[object Array]"&&value.length===0)return true;else return false}}})();Handlebars.Compiler=function(){};Handlebars.JavaScriptCompiler=function(){}; -(function(Compiler,JavaScriptCompiler){Compiler.prototype={compiler:Compiler,disassemble:function(){var opcodes=this.opcodes,opcode,out=[],params,param;for(var i=0,l=opcodes.length;i<l;i++){opcode=opcodes[i];if(opcode.opcode==="DECLARE")out.push("DECLARE "+opcode.name+"="+opcode.value);else{params=[];for(var j=0;j<opcode.args.length;j++){param=opcode.args[j];if(typeof param==="string")param='"'+param.replace("\n","\\n")+'"';params.push(param)}out.push(opcode.opcode+" "+params.join(" "))}}return out.join("\n")}, -equals:function(other){var len=this.opcodes.length;if(other.opcodes.length!==len)return false;for(var i=0;i<len;i++){var opcode=this.opcodes[i],otherOpcode=other.opcodes[i];if(opcode.opcode!==otherOpcode.opcode||opcode.args.length!==otherOpcode.args.length)return false;for(var j=0;j<opcode.args.length;j++)if(opcode.args[j]!==otherOpcode.args[j])return false}return true},guid:0,compile:function(program,options){this.children=[];this.depths={list:[]};this.options=options;var knownHelpers=this.options.knownHelpers; -this.options.knownHelpers={"helperMissing":true,"blockHelperMissing":true,"each":true,"if":true,"unless":true,"with":true,"log":true};if(knownHelpers)for(var name in knownHelpers)this.options.knownHelpers[name]=knownHelpers[name];return this.program(program)},accept:function(node){return this[node.type](node)},program:function(program){var statements=program.statements,statement;this.opcodes=[];for(var i=0,l=statements.length;i<l;i++){statement=statements[i];this[statement.type](statement)}this.isSimple= -l===1;this.depths.list=this.depths.list.sort(function(a,b){return a-b});return this},compileProgram:function(program){var result=(new this.compiler).compile(program,this.options);var guid=this.guid++,depth;this.usePartial=this.usePartial||result.usePartial;this.children[guid]=result;for(var i=0,l=result.depths.list.length;i<l;i++){depth=result.depths.list[i];if(depth<2)continue;else this.addDepth(depth-1)}return guid},block:function(block){var mustache=block.mustache,program=block.program,inverse= -block.inverse;if(program)program=this.compileProgram(program);if(inverse)inverse=this.compileProgram(inverse);var type=this.classifyMustache(mustache);if(type==="helper")this.helperMustache(mustache,program,inverse);else if(type==="simple"){this.simpleMustache(mustache);this.opcode("pushProgram",program);this.opcode("pushProgram",inverse);this.opcode("emptyHash");this.opcode("blockValue")}else{this.ambiguousMustache(mustache,program,inverse);this.opcode("pushProgram",program);this.opcode("pushProgram", -inverse);this.opcode("emptyHash");this.opcode("ambiguousBlockValue")}this.opcode("append")},hash:function(hash){var pairs=hash.pairs,pair,val;this.opcode("pushHash");for(var i=0,l=pairs.length;i<l;i++){pair=pairs[i];val=pair[1];if(this.options.stringParams)this.opcode("pushStringParam",val.stringModeValue,val.type);else this.accept(val);this.opcode("assignToHash",pair[0])}this.opcode("popHash")},partial:function(partial){var partialName=partial.partialName;this.usePartial=true;if(partial.context)this.ID(partial.context); -else this.opcode("push","depth0");this.opcode("invokePartial",partialName.name);this.opcode("append")},content:function(content){this.opcode("appendContent",content.string)},mustache:function(mustache){var options=this.options;var type=this.classifyMustache(mustache);if(type==="simple")this.simpleMustache(mustache);else if(type==="helper")this.helperMustache(mustache);else this.ambiguousMustache(mustache);if(mustache.escaped&&!options.noEscape)this.opcode("appendEscaped");else this.opcode("append")}, -ambiguousMustache:function(mustache,program,inverse){var id=mustache.id,name=id.parts[0],isBlock=program!=null||inverse!=null;this.opcode("getContext",id.depth);this.opcode("pushProgram",program);this.opcode("pushProgram",inverse);this.opcode("invokeAmbiguous",name,isBlock)},simpleMustache:function(mustache){var id=mustache.id;if(id.type==="DATA")this.DATA(id);else if(id.parts.length)this.ID(id);else{this.addDepth(id.depth);this.opcode("getContext",id.depth);this.opcode("pushContext")}this.opcode("resolvePossibleLambda")}, -helperMustache:function(mustache,program,inverse){var params=this.setupFullMustacheParams(mustache,program,inverse),name=mustache.id.parts[0];if(this.options.knownHelpers[name])this.opcode("invokeKnownHelper",params.length,name);else if(this.knownHelpersOnly)throw new Error("You specified knownHelpersOnly, but used the unknown helper "+name);else this.opcode("invokeHelper",params.length,name)},ID:function(id){this.addDepth(id.depth);this.opcode("getContext",id.depth);var name=id.parts[0];if(!name)this.opcode("pushContext"); -else this.opcode("lookupOnContext",id.parts[0]);for(var i=1,l=id.parts.length;i<l;i++)this.opcode("lookup",id.parts[i])},DATA:function(data){this.options.data=true;this.opcode("lookupData",data.id)},STRING:function(string){this.opcode("pushString",string.string)},INTEGER:function(integer){this.opcode("pushLiteral",integer.integer)},BOOLEAN:function(bool){this.opcode("pushLiteral",bool.bool)},comment:function(){},opcode:function(name){this.opcodes.push({opcode:name,args:[].slice.call(arguments,1)})}, -declare:function(name,value){this.opcodes.push({opcode:"DECLARE",name:name,value:value})},addDepth:function(depth){if(isNaN(depth))throw new Error("EWOT");if(depth===0)return;if(!this.depths[depth]){this.depths[depth]=true;this.depths.list.push(depth)}},classifyMustache:function(mustache){var isHelper=mustache.isHelper;var isEligible=mustache.eligibleHelper;var options=this.options;if(isEligible&&!isHelper){var name=mustache.id.parts[0];if(options.knownHelpers[name])isHelper=true;else if(options.knownHelpersOnly)isEligible= -false}if(isHelper)return"helper";else if(isEligible)return"ambiguous";else return"simple"},pushParams:function(params){var i=params.length,param;while(i--){param=params[i];if(this.options.stringParams){if(param.depth)this.addDepth(param.depth);this.opcode("getContext",param.depth||0);this.opcode("pushStringParam",param.stringModeValue,param.type)}else this[param.type](param)}},setupMustacheParams:function(mustache){var params=mustache.params;this.pushParams(params);if(mustache.hash)this.hash(mustache.hash); -else this.opcode("emptyHash");return params},setupFullMustacheParams:function(mustache,program,inverse){var params=mustache.params;this.pushParams(params);this.opcode("pushProgram",program);this.opcode("pushProgram",inverse);if(mustache.hash)this.hash(mustache.hash);else this.opcode("emptyHash");return params}};var Literal=function(value){this.value=value};JavaScriptCompiler.prototype={nameLookup:function(parent,name){if(/^[0-9]+$/.test(name))return parent+"["+name+"]";else if(JavaScriptCompiler.isValidJavaScriptVariableName(name))return parent+ -"."+name;else return parent+"['"+name+"']"},appendToBuffer:function(string){if(this.environment.isSimple)return"return "+string+";";else return{appendToBuffer:true,content:string,toString:function(){return"buffer += "+string+";"}}},initializeBuffer:function(){return this.quotedString("")},namespace:"Handlebars",compile:function(environment,options,context,asObject){this.environment=environment;this.options=options||{};Handlebars.log(Handlebars.logger.DEBUG,this.environment.disassemble()+"\n\n");this.name= -this.environment.name;this.isChild=!!context;this.context=context||{programs:[],environments:[],aliases:{}};this.preamble();this.stackSlot=0;this.stackVars=[];this.registers={list:[]};this.compileStack=[];this.inlineStack=[];this.compileChildren(environment,options);var opcodes=environment.opcodes,opcode;this.i=0;for(l=opcodes.length;this.i<l;this.i++){opcode=opcodes[this.i];if(opcode.opcode==="DECLARE")this[opcode.name]=opcode.value;else this[opcode.opcode].apply(this,opcode.args)}return this.createFunctionContext(asObject)}, -nextOpcode:function(){var opcodes=this.environment.opcodes;return opcodes[this.i+1]},eat:function(){this.i=this.i+1},preamble:function(){var out=[];if(!this.isChild){var namespace=this.namespace;var copies="helpers = helpers || "+namespace+".helpers;";if(this.environment.usePartial)copies=copies+" partials = partials || "+namespace+".partials;";if(this.options.data)copies=copies+" data = data || {};";out.push(copies)}else out.push("");if(!this.environment.isSimple)out.push(", buffer = "+this.initializeBuffer()); -else out.push("");this.lastContext=0;this.source=out},createFunctionContext:function(asObject){var locals=this.stackVars.concat(this.registers.list);if(locals.length>0)this.source[1]=this.source[1]+", "+locals.join(", ");if(!this.isChild)for(var alias in this.context.aliases)this.source[1]=this.source[1]+", "+alias+"="+this.context.aliases[alias];if(this.source[1])this.source[1]="var "+this.source[1].substring(2)+";";if(!this.isChild)this.source[1]+="\n"+this.context.programs.join("\n")+"\n";if(!this.environment.isSimple)this.source.push("return buffer;"); -var params=this.isChild?["depth0","data"]:["Handlebars","depth0","helpers","partials","data"];for(var i=0,l=this.environment.depths.list.length;i<l;i++)params.push("depth"+this.environment.depths.list[i]);var source=this.mergeSource();if(!this.isChild){var revision=Handlebars.COMPILER_REVISION,versions=Handlebars.REVISION_CHANGES[revision];source="this.compilerInfo = ["+revision+",'"+versions+"'];\n"+source}if(asObject){params.push(source);return Function.apply(this,params)}else{var functionSource= -"function "+(this.name||"")+"("+params.join(",")+") {\n "+source+"}";Handlebars.log(Handlebars.logger.DEBUG,functionSource+"\n\n");return functionSource}},mergeSource:function(){var source="",buffer;for(var i=0,len=this.source.length;i<len;i++){var line=this.source[i];if(line.appendToBuffer)if(buffer)buffer=buffer+"\n + "+line.content;else buffer=line.content;else{if(buffer){source+="buffer += "+buffer+";\n ";buffer=undefined}source+=line+"\n "}}return source},blockValue:function(){this.context.aliases.blockHelperMissing= -"helpers.blockHelperMissing";var params=["depth0"];this.setupParams(0,params);this.replaceStack(function(current){params.splice(1,0,current);return"blockHelperMissing.call("+params.join(", ")+")"})},ambiguousBlockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var params=["depth0"];this.setupParams(0,params);var current=this.topStack();params.splice(1,0,current);params[params.length-1]="options";this.source.push("if (!"+this.lastHelper+") { "+current+" = blockHelperMissing.call("+ -params.join(", ")+"); }")},appendContent:function(content){this.source.push(this.appendToBuffer(this.quotedString(content)))},append:function(){this.flushInline();var local=this.popStack();this.source.push("if("+local+" || "+local+" === 0) { "+this.appendToBuffer(local)+" }");if(this.environment.isSimple)this.source.push("else { "+this.appendToBuffer("''")+" }")},appendEscaped:function(){this.context.aliases.escapeExpression="this.escapeExpression";this.source.push(this.appendToBuffer("escapeExpression("+ -this.popStack()+")"))},getContext:function(depth){if(this.lastContext!==depth)this.lastContext=depth},lookupOnContext:function(name){this.push(this.nameLookup("depth"+this.lastContext,name,"context"))},pushContext:function(){this.pushStackLiteral("depth"+this.lastContext)},resolvePossibleLambda:function(){this.context.aliases.functionType='"function"';this.replaceStack(function(current){return"typeof "+current+" === functionType ? "+current+".apply(depth0) : "+current})},lookup:function(name){this.replaceStack(function(current){return current+ -" == null || "+current+" === false ? "+current+" : "+this.nameLookup(current,name,"context")})},lookupData:function(id){this.push(this.nameLookup("data",id,"data"))},pushStringParam:function(string,type){this.pushStackLiteral("depth"+this.lastContext);this.pushString(type);if(typeof string==="string")this.pushString(string);else this.pushStackLiteral(string)},emptyHash:function(){this.pushStackLiteral("{}");if(this.options.stringParams)this.register("hashTypes","{}")},pushHash:function(){this.hash= -{values:[],types:[]}},popHash:function(){var hash=this.hash;this.hash=undefined;if(this.options.stringParams)this.register("hashTypes","{"+hash.types.join(",")+"}");this.push("{\n "+hash.values.join(",\n ")+"\n }")},pushString:function(string){this.pushStackLiteral(this.quotedString(string))},push:function(expr){this.inlineStack.push(expr);return expr},pushLiteral:function(value){this.pushStackLiteral(value)},pushProgram:function(guid){if(guid!=null)this.pushStackLiteral(this.programExpression(guid)); -else this.pushStackLiteral(null)},invokeHelper:function(paramSize,name){this.context.aliases.helperMissing="helpers.helperMissing";var helper=this.lastHelper=this.setupHelper(paramSize,name,true);this.push(helper.name);this.replaceStack(function(name){return name+" ? "+name+".call("+helper.callParams+") "+": helperMissing.call("+helper.helperMissingParams+")"})},invokeKnownHelper:function(paramSize,name){var helper=this.setupHelper(paramSize,name);this.push(helper.name+".call("+helper.callParams+ -")")},invokeAmbiguous:function(name,helperCall){this.context.aliases.functionType='"function"';this.pushStackLiteral("{}");var helper=this.setupHelper(0,name,helperCall);var helperName=this.lastHelper=this.nameLookup("helpers",name,"helper");var nonHelper=this.nameLookup("depth"+this.lastContext,name,"context");var nextStack=this.nextStack();this.source.push("if ("+nextStack+" = "+helperName+") { "+nextStack+" = "+nextStack+".call("+helper.callParams+"); }");this.source.push("else { "+nextStack+" = "+ -nonHelper+"; "+nextStack+" = typeof "+nextStack+" === functionType ? "+nextStack+".apply(depth0) : "+nextStack+"; }")},invokePartial:function(name){var params=[this.nameLookup("partials",name,"partial"),"'"+name+"'",this.popStack(),"helpers","partials"];if(this.options.data)params.push("data");this.context.aliases.self="this";this.push("self.invokePartial("+params.join(", ")+")")},assignToHash:function(key){var value=this.popStack(),type;if(this.options.stringParams){type=this.popStack();this.popStack()}var hash= -this.hash;if(type)hash.types.push("'"+key+"': "+type);hash.values.push("'"+key+"': ("+value+")")},compiler:JavaScriptCompiler,compileChildren:function(environment,options){var children=environment.children,child,compiler;for(var i=0,l=children.length;i<l;i++){child=children[i];compiler=new this.compiler;var index=this.matchExistingProgram(child);if(index==null){this.context.programs.push("");index=this.context.programs.length;child.index=index;child.name="program"+index;this.context.programs[index]= -compiler.compile(child,options,this.context);this.context.environments[index]=child}else{child.index=index;child.name="program"+index}}},matchExistingProgram:function(child){for(var i=0,len=this.context.environments.length;i<len;i++){var environment=this.context.environments[i];if(environment&&environment.equals(child))return i}},programExpression:function(guid){this.context.aliases.self="this";if(guid==null)return"self.noop";var child=this.environment.children[guid],depths=child.depths.list,depth; -var programParams=[child.index,child.name,"data"];for(var i=0,l=depths.length;i<l;i++){depth=depths[i];if(depth===1)programParams.push("depth0");else programParams.push("depth"+(depth-1))}if(depths.length===0)return"self.program("+programParams.join(", ")+")";else{programParams.shift();return"self.programWithDepth("+programParams.join(", ")+")"}},register:function(name,val){this.useRegister(name);this.source.push(name+" = "+val+";")},useRegister:function(name){if(!this.registers[name]){this.registers[name]= -true;this.registers.list.push(name)}},pushStackLiteral:function(item){return this.push(new Literal(item))},pushStack:function(item){this.flushInline();var stack=this.incrStack();if(item)this.source.push(stack+" = "+item+";");this.compileStack.push(stack);return stack},replaceStack:function(callback){var prefix="",inline=this.isInline(),stack;if(inline){var top=this.popStack(true);if(top instanceof Literal)stack=top.value;else{var name=this.stackSlot?this.topStackName():this.incrStack();prefix="("+ -this.push(name)+" = "+top+"),";stack=this.topStack()}}else stack=this.topStack();var item=callback.call(this,stack);if(inline){if(this.inlineStack.length||this.compileStack.length)this.popStack();this.push("("+prefix+item+")")}else{if(!/^stack/.test(stack))stack=this.nextStack();this.source.push(stack+" = ("+prefix+item+");")}return stack},nextStack:function(){return this.pushStack()},incrStack:function(){this.stackSlot++;if(this.stackSlot>this.stackVars.length)this.stackVars.push("stack"+this.stackSlot); -return this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var inlineStack=this.inlineStack;if(inlineStack.length){this.inlineStack=[];for(var i=0,len=inlineStack.length;i<len;i++){var entry=inlineStack[i];if(entry instanceof Literal)this.compileStack.push(entry);else this.pushStack(entry)}}},isInline:function(){return this.inlineStack.length},popStack:function(wrapped){var inline=this.isInline(),item=(inline?this.inlineStack:this.compileStack).pop(); -if(!wrapped&&item instanceof Literal)return item.value;else{if(!inline)this.stackSlot--;return item}},topStack:function(wrapped){var stack=this.isInline()?this.inlineStack:this.compileStack,item=stack[stack.length-1];if(!wrapped&&item instanceof Literal)return item.value;else return item},quotedString:function(str){return'"'+str.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")+'"'},setupHelper:function(paramSize,name,missingParams){var params=[];this.setupParams(paramSize, -params,missingParams);var foundHelper=this.nameLookup("helpers",name,"helper");return{params:params,name:foundHelper,callParams:["depth0"].concat(params).join(", "),helperMissingParams:missingParams&&["depth0",this.quotedString(name)].concat(params).join(", ")}},setupParams:function(paramSize,params,useRegister){var options=[],contexts=[],types=[],param,inverse,program;options.push("hash:"+this.popStack());inverse=this.popStack();program=this.popStack();if(program||inverse){if(!program){this.context.aliases.self= -"this";program="self.noop"}if(!inverse){this.context.aliases.self="this";inverse="self.noop"}options.push("inverse:"+inverse);options.push("fn:"+program)}for(var i=0;i<paramSize;i++){param=this.popStack();params.push(param);if(this.options.stringParams){types.push(this.popStack());contexts.push(this.popStack())}}if(this.options.stringParams){options.push("contexts:["+contexts.join(",")+"]");options.push("types:["+types.join(",")+"]");options.push("hashTypes:hashTypes")}if(this.options.data)options.push("data:data"); -options="{"+options.join(",")+"}";if(useRegister){this.register("options",options);params.push("options")}else params.push(options);return params.join(", ")}};var reservedWords=("break else new var"+" case finally return void"+" catch for switch while"+" continue function this with"+" default if throw"+" delete in try"+" do instanceof typeof"+" abstract enum int short"+" boolean export interface static"+" byte extends long super"+" char final native synchronized"+" class float package throws"+" const goto private transient"+ -" debugger implements protected volatile"+" double import public let yield").split(" ");var compilerWords=JavaScriptCompiler.RESERVED_WORDS={};for(var i=0,l=reservedWords.length;i<l;i++)compilerWords[reservedWords[i]]=true;JavaScriptCompiler.isValidJavaScriptVariableName=function(name){if(!JavaScriptCompiler.RESERVED_WORDS[name]&&/^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(name))return true;return false}})(Handlebars.Compiler,Handlebars.JavaScriptCompiler); -Handlebars.precompile=function(input,options){if(!input||typeof input!=="string"&&input.constructor!==Handlebars.AST.ProgramNode)throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+input);options=options||{};if(!("data"in options))options.data=true;var ast=Handlebars.parse(input);var environment=(new Handlebars.Compiler).compile(ast,options);return(new Handlebars.JavaScriptCompiler).compile(environment,options)}; -Handlebars.compile=function(input,options){if(!input||typeof input!=="string"&&input.constructor!==Handlebars.AST.ProgramNode)throw new Handlebars.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+input);options=options||{};if(!("data"in options))options.data=true;var compiled;function compile(){var ast=Handlebars.parse(input);var environment=(new Handlebars.Compiler).compile(ast,options);var templateSpec=(new Handlebars.JavaScriptCompiler).compile(environment, -options,undefined,true);return Handlebars.template(templateSpec)}return function(context,options){if(!compiled)compiled=compile();return compiled.call(this,context,options)}}; -Handlebars.VM={template:function(templateSpec){var container={escapeExpression:Handlebars.Utils.escapeExpression,invokePartial:Handlebars.VM.invokePartial,programs:[],program:function(i,fn,data){var programWrapper=this.programs[i];if(data)return Handlebars.VM.program(fn,data);else if(programWrapper)return programWrapper;else{programWrapper=this.programs[i]=Handlebars.VM.program(fn);return programWrapper}},programWithDepth:Handlebars.VM.programWithDepth,noop:Handlebars.VM.noop,compilerInfo:null};return function(context, -options){options=options||{};var result=templateSpec.call(container,Handlebars,context,options.helpers,options.partials,options.data);var compilerInfo=container.compilerInfo||[],compilerRevision=compilerInfo[0]||1,currentRevision=Handlebars.COMPILER_REVISION;if(compilerRevision!==currentRevision)if(compilerRevision<currentRevision){var runtimeVersions=Handlebars.REVISION_CHANGES[currentRevision],compilerVersions=Handlebars.REVISION_CHANGES[compilerRevision];throw"Template was precompiled with an older version of Handlebars than the current runtime. "+ -"Please update your precompiler to a newer version ("+runtimeVersions+") or downgrade your runtime to an older version ("+compilerVersions+").";}else throw"Template was precompiled with a newer version of Handlebars than the current runtime. "+"Please update your runtime to a newer version ("+compilerInfo[1]+").";return result}},programWithDepth:function(fn,data,$depth){var args=Array.prototype.slice.call(arguments,2);return function(context,options){options=options||{};return fn.apply(this,[context, -options.data||data].concat(args))}},program:function(fn,data){return function(context,options){options=options||{};return fn(context,options.data||data)}},noop:function(){return""},invokePartial:function(partial,name,context,helpers,partials,data){var options={helpers:helpers,partials:partials,data:data};if(partial===undefined)throw new Handlebars.Exception("The partial "+name+" could not be found");else if(partial instanceof Function)return partial(context,options);else if(!Handlebars.compile)throw new Handlebars.Exception("The partial "+ -name+" could not be compiled when running in runtime-only mode");else{partials[name]=Handlebars.compile(partial,{data:data!==undefined});return partials[name](context,options)}}};Handlebars.template=Handlebars.VM.template; +/* + +Copyright (C) 2011 by Yehuda Katz + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +*/ +var Handlebars={};(function(d,c){d.VERSION="1.0.0-rc.4";d.COMPILER_REVISION=3;d.REVISION_CHANGES={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:">= 1.0.0-rc.4"};d.helpers={};d.partials={};var n=Object.prototype.toString,b="[object Function]",h="[object Object]";d.registerHelper=function(l,u,i){if(n.call(l)===h){if(i||u){throw new d.Exception("Arg not supported with multiple helpers")}d.Utils.extend(this.helpers,l)}else{if(i){u.not=i}this.helpers[l]=u}};d.registerPartial=function(i,l){if(n.call(i)===h){d.Utils.extend(this.partials,i)}else{this.partials[i]=l}};d.registerHelper("helperMissing",function(i){if(arguments.length===2){return c}else{throw new Error("Could not find property '"+i+"'")}});d.registerHelper("blockHelperMissing",function(u,l){var i=l.inverse||function(){},w=l.fn;var v=n.call(u);if(v===b){u=u.call(this)}if(u===true){return w(this)}else{if(u===false||u==null){return i(this)}else{if(v==="[object Array]"){if(u.length>0){return d.helpers.each(u,l)}else{return i(this)}}else{return w(u)}}}});d.K=function(){};d.createFrame=Object.create||function(i){d.K.prototype=i;var l=new d.K();d.K.prototype=null;return l};d.logger={DEBUG:0,INFO:1,WARN:2,ERROR:3,level:3,methodMap:{0:"debug",1:"info",2:"warn",3:"error"},log:function(u,i){if(d.logger.level<=u){var l=d.logger.methodMap[u];if(typeof console!=="undefined"&&console[l]){console[l].call(console,i)}}}};d.log=function(l,i){d.logger.log(l,i)};d.registerHelper("each",function(l,B){var z=B.fn,v=B.inverse;var x=0,y="",w;if(B.data){w=d.createFrame(B.data)}if(l&&typeof l==="object"){if(l instanceof Array){for(var u=l.length;x<u;x++){if(w){w.index=x}y=y+z(l[x],{data:w})}}else{for(var A in l){if(l.hasOwnProperty(A)){if(w){w.key=A}y=y+z(l[A],{data:w});x++}}}}if(x===0){y=v(this)}return y});d.registerHelper("if",function(l,i){var u=n.call(l);if(u===b){l=l.call(this)}if(!l||d.Utils.isEmpty(l)){return i.inverse(this)}else{return i.fn(this)}});d.registerHelper("unless",function(l,i){return d.helpers["if"].call(this,l,{fn:i.inverse,inverse:i.fn})});d.registerHelper("with",function(l,i){if(!d.Utils.isEmpty(l)){return i.fn(l)}});d.registerHelper("log",function(l,i){var u=i.data&&i.data.level!=null?parseInt(i.data.level,10):1;d.log(u,l)});var r=(function(){var y={trace:function u(){},yy:{},symbols_:{error:2,root:3,program:4,EOF:5,simpleInverse:6,statements:7,statement:8,openInverse:9,closeBlock:10,openBlock:11,mustache:12,partial:13,CONTENT:14,COMMENT:15,OPEN_BLOCK:16,inMustache:17,CLOSE:18,OPEN_INVERSE:19,OPEN_ENDBLOCK:20,path:21,OPEN:22,OPEN_UNESCAPED:23,OPEN_PARTIAL:24,partialName:25,params:26,hash:27,DATA:28,param:29,STRING:30,INTEGER:31,BOOLEAN:32,hashSegments:33,hashSegment:34,ID:35,EQUALS:36,PARTIAL_NAME:37,pathSegments:38,SEP:39,"$accept":0,"$end":1},terminals_:{2:"error",5:"EOF",14:"CONTENT",15:"COMMENT",16:"OPEN_BLOCK",18:"CLOSE",19:"OPEN_INVERSE",20:"OPEN_ENDBLOCK",22:"OPEN",23:"OPEN_UNESCAPED",24:"OPEN_PARTIAL",28:"DATA",30:"STRING",31:"INTEGER",32:"BOOLEAN",35:"ID",36:"EQUALS",37:"PARTIAL_NAME",39:"SEP"},productions_:[0,[3,2],[4,2],[4,3],[4,2],[4,1],[4,1],[4,0],[7,1],[7,2],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[11,3],[9,3],[10,3],[12,3],[12,3],[13,3],[13,4],[6,2],[17,3],[17,2],[17,2],[17,1],[17,1],[26,2],[26,1],[29,1],[29,1],[29,1],[29,1],[29,1],[27,1],[33,2],[33,1],[34,3],[34,3],[34,3],[34,3],[34,3],[25,1],[21,1],[38,3],[38,1]],performAction:function l(z,C,D,G,F,B,E){var A=B.length-1;switch(F){case 1:return B[A-1];break;case 2:this.$=new G.ProgramNode([],B[A]);break;case 3:this.$=new G.ProgramNode(B[A-2],B[A]);break;case 4:this.$=new G.ProgramNode(B[A-1],[]);break;case 5:this.$=new G.ProgramNode(B[A]);break;case 6:this.$=new G.ProgramNode([],[]);break;case 7:this.$=new G.ProgramNode([]);break;case 8:this.$=[B[A]];break;case 9:B[A-1].push(B[A]);this.$=B[A-1];break;case 10:this.$=new G.BlockNode(B[A-2],B[A-1].inverse,B[A-1],B[A]);break;case 11:this.$=new G.BlockNode(B[A-2],B[A-1],B[A-1].inverse,B[A]);break;case 12:this.$=B[A];break;case 13:this.$=B[A];break;case 14:this.$=new G.ContentNode(B[A]);break;case 15:this.$=new G.CommentNode(B[A]);break;case 16:this.$=new G.MustacheNode(B[A-1][0],B[A-1][1]);break;case 17:this.$=new G.MustacheNode(B[A-1][0],B[A-1][1]);break;case 18:this.$=B[A-1];break;case 19:this.$=new G.MustacheNode(B[A-1][0],B[A-1][1]);break;case 20:this.$=new G.MustacheNode(B[A-1][0],B[A-1][1],true);break;case 21:this.$=new G.PartialNode(B[A-1]);break;case 22:this.$=new G.PartialNode(B[A-2],B[A-1]);break;case 23:break;case 24:this.$=[[B[A-2]].concat(B[A-1]),B[A]];break;case 25:this.$=[[B[A-1]].concat(B[A]),null];break;case 26:this.$=[[B[A-1]],B[A]];break;case 27:this.$=[[B[A]],null];break;case 28:this.$=[[new G.DataNode(B[A])],null];break;case 29:B[A-1].push(B[A]);this.$=B[A-1];break;case 30:this.$=[B[A]];break;case 31:this.$=B[A];break;case 32:this.$=new G.StringNode(B[A]);break;case 33:this.$=new G.IntegerNode(B[A]);break;case 34:this.$=new G.BooleanNode(B[A]);break;case 35:this.$=new G.DataNode(B[A]);break;case 36:this.$=new G.HashNode(B[A]);break;case 37:B[A-1].push(B[A]);this.$=B[A-1];break;case 38:this.$=[B[A]];break;case 39:this.$=[B[A-2],B[A]];break;case 40:this.$=[B[A-2],new G.StringNode(B[A])];break;case 41:this.$=[B[A-2],new G.IntegerNode(B[A])];break;case 42:this.$=[B[A-2],new G.BooleanNode(B[A])];break;case 43:this.$=[B[A-2],new G.DataNode(B[A])];break;case 44:this.$=new G.PartialNameNode(B[A]);break;case 45:this.$=new G.IdNode(B[A]);break;case 46:B[A-2].push(B[A]);this.$=B[A-2];break;case 47:this.$=[B[A]];break}},table:[{3:1,4:2,5:[2,7],6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],22:[1,14],23:[1,15],24:[1,16]},{1:[3]},{5:[1,17]},{5:[2,6],7:18,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,6],22:[1,14],23:[1,15],24:[1,16]},{5:[2,5],6:20,8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,5],22:[1,14],23:[1,15],24:[1,16]},{17:23,18:[1,22],21:24,28:[1,25],35:[1,27],38:26},{5:[2,8],14:[2,8],15:[2,8],16:[2,8],19:[2,8],20:[2,8],22:[2,8],23:[2,8],24:[2,8]},{4:28,6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,7],22:[1,14],23:[1,15],24:[1,16]},{4:29,6:3,7:4,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,5],20:[2,7],22:[1,14],23:[1,15],24:[1,16]},{5:[2,12],14:[2,12],15:[2,12],16:[2,12],19:[2,12],20:[2,12],22:[2,12],23:[2,12],24:[2,12]},{5:[2,13],14:[2,13],15:[2,13],16:[2,13],19:[2,13],20:[2,13],22:[2,13],23:[2,13],24:[2,13]},{5:[2,14],14:[2,14],15:[2,14],16:[2,14],19:[2,14],20:[2,14],22:[2,14],23:[2,14],24:[2,14]},{5:[2,15],14:[2,15],15:[2,15],16:[2,15],19:[2,15],20:[2,15],22:[2,15],23:[2,15],24:[2,15]},{17:30,21:24,28:[1,25],35:[1,27],38:26},{17:31,21:24,28:[1,25],35:[1,27],38:26},{17:32,21:24,28:[1,25],35:[1,27],38:26},{25:33,37:[1,34]},{1:[2,1]},{5:[2,2],8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,2],22:[1,14],23:[1,15],24:[1,16]},{17:23,21:24,28:[1,25],35:[1,27],38:26},{5:[2,4],7:35,8:6,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,4],22:[1,14],23:[1,15],24:[1,16]},{5:[2,9],14:[2,9],15:[2,9],16:[2,9],19:[2,9],20:[2,9],22:[2,9],23:[2,9],24:[2,9]},{5:[2,23],14:[2,23],15:[2,23],16:[2,23],19:[2,23],20:[2,23],22:[2,23],23:[2,23],24:[2,23]},{18:[1,36]},{18:[2,27],21:41,26:37,27:38,28:[1,45],29:39,30:[1,42],31:[1,43],32:[1,44],33:40,34:46,35:[1,47],38:26},{18:[2,28]},{18:[2,45],28:[2,45],30:[2,45],31:[2,45],32:[2,45],35:[2,45],39:[1,48]},{18:[2,47],28:[2,47],30:[2,47],31:[2,47],32:[2,47],35:[2,47],39:[2,47]},{10:49,20:[1,50]},{10:51,20:[1,50]},{18:[1,52]},{18:[1,53]},{18:[1,54]},{18:[1,55],21:56,35:[1,27],38:26},{18:[2,44],35:[2,44]},{5:[2,3],8:21,9:7,11:8,12:9,13:10,14:[1,11],15:[1,12],16:[1,13],19:[1,19],20:[2,3],22:[1,14],23:[1,15],24:[1,16]},{14:[2,17],15:[2,17],16:[2,17],19:[2,17],20:[2,17],22:[2,17],23:[2,17],24:[2,17]},{18:[2,25],21:41,27:57,28:[1,45],29:58,30:[1,42],31:[1,43],32:[1,44],33:40,34:46,35:[1,47],38:26},{18:[2,26]},{18:[2,30],28:[2,30],30:[2,30],31:[2,30],32:[2,30],35:[2,30]},{18:[2,36],34:59,35:[1,60]},{18:[2,31],28:[2,31],30:[2,31],31:[2,31],32:[2,31],35:[2,31]},{18:[2,32],28:[2,32],30:[2,32],31:[2,32],32:[2,32],35:[2,32]},{18:[2,33],28:[2,33],30:[2,33],31:[2,33],32:[2,33],35:[2,33]},{18:[2,34],28:[2,34],30:[2,34],31:[2,34],32:[2,34],35:[2,34]},{18:[2,35],28:[2,35],30:[2,35],31:[2,35],32:[2,35],35:[2,35]},{18:[2,38],35:[2,38]},{18:[2,47],28:[2,47],30:[2,47],31:[2,47],32:[2,47],35:[2,47],36:[1,61],39:[2,47]},{35:[1,62]},{5:[2,10],14:[2,10],15:[2,10],16:[2,10],19:[2,10],20:[2,10],22:[2,10],23:[2,10],24:[2,10]},{21:63,35:[1,27],38:26},{5:[2,11],14:[2,11],15:[2,11],16:[2,11],19:[2,11],20:[2,11],22:[2,11],23:[2,11],24:[2,11]},{14:[2,16],15:[2,16],16:[2,16],19:[2,16],20:[2,16],22:[2,16],23:[2,16],24:[2,16]},{5:[2,19],14:[2,19],15:[2,19],16:[2,19],19:[2,19],20:[2,19],22:[2,19],23:[2,19],24:[2,19]},{5:[2,20],14:[2,20],15:[2,20],16:[2,20],19:[2,20],20:[2,20],22:[2,20],23:[2,20],24:[2,20]},{5:[2,21],14:[2,21],15:[2,21],16:[2,21],19:[2,21],20:[2,21],22:[2,21],23:[2,21],24:[2,21]},{18:[1,64]},{18:[2,24]},{18:[2,29],28:[2,29],30:[2,29],31:[2,29],32:[2,29],35:[2,29]},{18:[2,37],35:[2,37]},{36:[1,61]},{21:65,28:[1,69],30:[1,66],31:[1,67],32:[1,68],35:[1,27],38:26},{18:[2,46],28:[2,46],30:[2,46],31:[2,46],32:[2,46],35:[2,46],39:[2,46]},{18:[1,70]},{5:[2,22],14:[2,22],15:[2,22],16:[2,22],19:[2,22],20:[2,22],22:[2,22],23:[2,22],24:[2,22]},{18:[2,39],35:[2,39]},{18:[2,40],35:[2,40]},{18:[2,41],35:[2,41]},{18:[2,42],35:[2,42]},{18:[2,43],35:[2,43]},{5:[2,18],14:[2,18],15:[2,18],16:[2,18],19:[2,18],20:[2,18],22:[2,18],23:[2,18],24:[2,18]}],defaultActions:{17:[2,1],25:[2,28],38:[2,26],57:[2,24]},parseError:function v(A,z){throw new Error(A)},parse:function x(I){var P=this,F=[0],Y=[null],K=[],Z=this.table,A="",J=0,W=0,C=0,H=2,M=1;this.lexer.setInput(I);this.lexer.yy=this.yy;this.yy.lexer=this.lexer;this.yy.parser=this;if(typeof this.lexer.yylloc=="undefined"){this.lexer.yylloc={}}var B=this.lexer.yylloc;K.push(B);var D=this.lexer.options&&this.lexer.options.ranges;if(typeof this.yy.parseError==="function"){this.parseError=this.yy.parseError}function O(ab){F.length=F.length-2*ab;Y.length=Y.length-ab;K.length=K.length-ab}function N(){var ab;ab=P.lexer.lex()||1;if(typeof ab!=="number"){ab=P.symbols_[ab]||ab}return ab}var V,R,E,U,aa,L,T={},Q,X,z,G;while(true){E=F[F.length-1];if(this.defaultActions[E]){U=this.defaultActions[E]}else{if(V===null||typeof V=="undefined"){V=N()}U=Z[E]&&Z[E][V]}if(typeof U==="undefined"||!U.length||!U[0]){var S="";if(!C){G=[];for(Q in Z[E]){if(this.terminals_[Q]&&Q>2){G.push("'"+this.terminals_[Q]+"'")}}if(this.lexer.showPosition){S="Parse error on line "+(J+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+G.join(", ")+", got '"+(this.terminals_[V]||V)+"'"}else{S="Parse error on line "+(J+1)+": Unexpected "+(V==1?"end of input":"'"+(this.terminals_[V]||V)+"'")}this.parseError(S,{text:this.lexer.match,token:this.terminals_[V]||V,line:this.lexer.yylineno,loc:B,expected:G})}}if(U[0] instanceof Array&&U.length>1){throw new Error("Parse Error: multiple actions possible at state: "+E+", token: "+V)}switch(U[0]){case 1:F.push(V);Y.push(this.lexer.yytext);K.push(this.lexer.yylloc);F.push(U[1]);V=null;if(!R){W=this.lexer.yyleng;A=this.lexer.yytext;J=this.lexer.yylineno;B=this.lexer.yylloc;if(C>0){C--}}else{V=R;R=null}break;case 2:X=this.productions_[U[1]][1];T.$=Y[Y.length-X];T._$={first_line:K[K.length-(X||1)].first_line,last_line:K[K.length-1].last_line,first_column:K[K.length-(X||1)].first_column,last_column:K[K.length-1].last_column};if(D){T._$.range=[K[K.length-(X||1)].range[0],K[K.length-1].range[1]]}L=this.performAction.call(T,A,W,J,this.yy,U[1],Y,K);if(typeof L!=="undefined"){return L}if(X){F=F.slice(0,-1*X*2);Y=Y.slice(0,-1*X);K=K.slice(0,-1*X)}F.push(this.productions_[U[1]][0]);Y.push(T.$);K.push(T._$);z=Z[F[F.length-2]][F[F.length-1]];F.push(z);break;case 3:return true}}return true}};var i=(function(){var C=({EOF:1,parseError:function E(H,G){if(this.yy.parser){this.yy.parser.parseError(H,G)}else{throw new Error(H)}},setInput:function(G){this._input=G;this._more=this._less=this.done=false;this.yylineno=this.yyleng=0;this.yytext=this.matched=this.match="";this.conditionStack=["INITIAL"];this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0};if(this.options.ranges){this.yylloc.range=[0,0]}this.offset=0;return this},input:function(){var H=this._input[0];this.yytext+=H;this.yyleng++;this.offset++;this.match+=H;this.matched+=H;var G=H.match(/(?:\r\n?|\n).*/g);if(G){this.yylineno++;this.yylloc.last_line++}else{this.yylloc.last_column++}if(this.options.ranges){this.yylloc.range[1]++}this._input=this._input.slice(1);return H},unput:function(I){var G=I.length;var H=I.split(/(?:\r\n?|\n)/g);this._input=I+this._input;this.yytext=this.yytext.substr(0,this.yytext.length-G-1);this.offset-=G;var K=this.match.split(/(?:\r\n?|\n)/g);this.match=this.match.substr(0,this.match.length-1);this.matched=this.matched.substr(0,this.matched.length-1);if(H.length-1){this.yylineno-=H.length-1}var J=this.yylloc.range;this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:H?(H.length===K.length?this.yylloc.first_column:0)+K[K.length-H.length].length-H[0].length:this.yylloc.first_column-G};if(this.options.ranges){this.yylloc.range=[J[0],J[0]+this.yyleng-G]}return this},more:function(){this._more=true;return this},less:function(G){this.unput(this.match.slice(G))},pastInput:function(){var G=this.matched.substr(0,this.matched.length-this.match.length);return(G.length>20?"...":"")+G.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var G=this.match;if(G.length<20){G+=this._input.substr(0,20-G.length)}return(G.substr(0,20)+(G.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var G=this.pastInput();var H=new Array(G.length+1).join("-");return G+this.upcomingInput()+"\n"+H+"^"},next:function(){if(this.done){return this.EOF}if(!this._input){this.done=true}var M,K,H,J,I,G;if(!this._more){this.yytext="";this.match=""}var N=this._currentRules();for(var L=0;L<N.length;L++){H=this._input.match(this.rules[N[L]]);if(H&&(!K||H[0].length>K[0].length)){K=H;J=L;if(!this.options.flex){break}}}if(K){G=K[0].match(/(?:\r\n?|\n).*/g);if(G){this.yylineno+=G.length}this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:G?G[G.length-1].length-G[G.length-1].match(/\r?\n?/)[0].length:this.yylloc.last_column+K[0].length};this.yytext+=K[0];this.match+=K[0];this.matches=K;this.yyleng=this.yytext.length;if(this.options.ranges){this.yylloc.range=[this.offset,this.offset+=this.yyleng]}this._more=false;this._input=this._input.slice(K[0].length);this.matched+=K[0];M=this.performAction.call(this,this.yy,this,N[J],this.conditionStack[this.conditionStack.length-1]);if(this.done&&this._input){this.done=false}if(M){return M}else{return}}if(this._input===""){return this.EOF}else{return this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})}},lex:function z(){var G=this.next();if(typeof G!=="undefined"){return G}else{return this.lex()}},begin:function A(G){this.conditionStack.push(G)},popState:function F(){return this.conditionStack.pop()},_currentRules:function D(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function A(G){this.begin(G)}});C.options={};C.performAction=function B(K,H,J,G){var I=G;switch(J){case 0:H.yytext="\\";return 14;break;case 1:if(H.yytext.slice(-1)!=="\\"){this.begin("mu")}if(H.yytext.slice(-1)==="\\"){H.yytext=H.yytext.substr(0,H.yyleng-1),this.begin("emu")}if(H.yytext){return 14}break;case 2:return 14;break;case 3:if(H.yytext.slice(-1)!=="\\"){this.popState()}if(H.yytext.slice(-1)==="\\"){H.yytext=H.yytext.substr(0,H.yyleng-1)}return 14;break;case 4:H.yytext=H.yytext.substr(0,H.yyleng-4);this.popState();return 15;break;case 5:this.begin("par");return 24;break;case 6:return 16;break;case 7:return 20;break;case 8:return 19;break;case 9:return 19;break;case 10:return 23;break;case 11:return 23;break;case 12:this.popState();this.begin("com");break;case 13:H.yytext=H.yytext.substr(3,H.yyleng-5);this.popState();return 15;break;case 14:return 22;break;case 15:return 36;break;case 16:return 35;break;case 17:return 35;break;case 18:return 39;break;case 19:break;case 20:this.popState();return 18;break;case 21:this.popState();return 18;break;case 22:H.yytext=H.yytext.substr(1,H.yyleng-2).replace(/\\"/g,'"');return 30;break;case 23:H.yytext=H.yytext.substr(1,H.yyleng-2).replace(/\\'/g,"'");return 30;break;case 24:H.yytext=H.yytext.substr(1);return 28;break;case 25:return 32;break;case 26:return 32;break;case 27:return 31;break;case 28:return 35;break;case 29:H.yytext=H.yytext.substr(1,H.yyleng-2);return 35;break;case 30:return"INVALID";break;case 31:break;case 32:this.popState();return 37;break;case 33:return 5;break}};C.rules=[/^(?:\\\\(?=(\{\{)))/,/^(?:[^\x00]*?(?=(\{\{)))/,/^(?:[^\x00]+)/,/^(?:[^\x00]{2,}?(?=(\{\{|$)))/,/^(?:[\s\S]*?--\}\})/,/^(?:\{\{>)/,/^(?:\{\{#)/,/^(?:\{\{\/)/,/^(?:\{\{\^)/,/^(?:\{\{\s*else\b)/,/^(?:\{\{\{)/,/^(?:\{\{&)/,/^(?:\{\{!--)/,/^(?:\{\{![\s\S]*?\}\})/,/^(?:\{\{)/,/^(?:=)/,/^(?:\.(?=[}/ ]))/,/^(?:\.\.)/,/^(?:[\/.])/,/^(?:\s+)/,/^(?:\}\}\})/,/^(?:\}\})/,/^(?:"(\\["]|[^"])*")/,/^(?:'(\\[']|[^'])*')/,/^(?:@[a-zA-Z]+)/,/^(?:true(?=[}\s]))/,/^(?:false(?=[}\s]))/,/^(?:-?[0-9]+(?=[}\s]))/,/^(?:[a-zA-Z0-9_$:\-]+(?=[=}\s\/.]))/,/^(?:\[[^\]]*\])/,/^(?:.)/,/^(?:\s+)/,/^(?:[a-zA-Z0-9_$\-\/]+)/,/^(?:$)/];C.conditions={mu:{rules:[5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,33],inclusive:false},emu:{rules:[3],inclusive:false},com:{rules:[4],inclusive:false},par:{rules:[31,32],inclusive:false},INITIAL:{rules:[0,1,2,33],inclusive:true}};return C})();y.lexer=i;function w(){this.yy={}}w.prototype=y;y.Parser=w;return new w})();d.Parser=r;d.parse=function(i){if(i.constructor===d.AST.ProgramNode){return i}d.Parser.yy=d.AST;return d.Parser.parse(i)};d.AST={};d.AST.ProgramNode=function(l,i){this.type="program";this.statements=l;if(i){this.inverse=new d.AST.ProgramNode(i)}};d.AST.MustacheNode=function(x,u,l){this.type="mustache";this.escaped=!l;this.hash=u;var w=this.id=x[0];var v=this.params=x.slice(1);var i=this.eligibleHelper=w.isSimple;this.isHelper=i&&(v.length||u)};d.AST.PartialNode=function(i,l){this.type="partial";this.partialName=i;this.context=l};d.AST.BlockNode=function(u,l,i,w){var v=function(x,y){if(x.original!==y.original){throw new d.Exception(x.original+" doesn't match "+y.original)}};v(u.id,w);this.type="block";this.mustache=u;this.program=l;this.inverse=i;if(this.inverse&&!this.program){this.isInverse=true}};d.AST.ContentNode=function(i){this.type="content";this.string=i};d.AST.HashNode=function(i){this.type="hash";this.pairs=i};d.AST.IdNode=function(y){this.type="ID";this.original=y.join(".");var w=[],z=0;for(var x=0,u=y.length;x<u;x++){var v=y[x];if(v===".."||v==="."||v==="this"){if(w.length>0){throw new d.Exception("Invalid path: "+this.original)}else{if(v===".."){z++}else{this.isScoped=true}}}else{w.push(v)}}this.parts=w;this.string=w.join(".");this.depth=z;this.isSimple=y.length===1&&!this.isScoped&&z===0;this.stringModeValue=this.string};d.AST.PartialNameNode=function(i){this.type="PARTIAL_NAME";this.name=i};d.AST.DataNode=function(i){this.type="DATA";this.id=i};d.AST.StringNode=function(i){this.type="STRING";this.string=i;this.stringModeValue=i};d.AST.IntegerNode=function(i){this.type="INTEGER";this.integer=i;this.stringModeValue=Number(i)};d.AST.BooleanNode=function(i){this.type="BOOLEAN";this.bool=i;this.stringModeValue=i==="true"};d.AST.CommentNode=function(i){this.type="comment";this.comment=i};var q=["description","fileName","lineNumber","message","name","number","stack"];d.Exception=function(u){var l=Error.prototype.constructor.apply(this,arguments);for(var i=0;i<q.length;i++){this[q[i]]=l[q[i]]}};d.Exception.prototype=new Error();d.SafeString=function(i){this.string=i};d.SafeString.prototype.toString=function(){return this.string.toString()};var k={"&":"&","<":"<",">":">",'"':""","'":"'","`":"`"};var e=/[&<>"'`]/g;var p=/[&<>"'`]/;var t=function(i){return k[i]||"&"};d.Utils={extend:function(u,l){for(var i in l){if(l.hasOwnProperty(i)){u[i]=l[i]}}},escapeExpression:function(i){if(i instanceof d.SafeString){return i.toString()}else{if(i==null||i===false){return""}}i=i.toString();if(!p.test(i)){return i}return i.replace(e,t)},isEmpty:function(i){if(!i&&i!==0){return true}else{if(n.call(i)==="[object Array]"&&i.length===0){return true}else{return false}}}};var j=d.Compiler=function(){};var g=d.JavaScriptCompiler=function(){};j.prototype={compiler:j,disassemble:function(){var z=this.opcodes,y,w=[],B,A;for(var x=0,u=z.length;x<u;x++){y=z[x];if(y.opcode==="DECLARE"){w.push("DECLARE "+y.name+"="+y.value)}else{B=[];for(var v=0;v<y.args.length;v++){A=y.args[v];if(typeof A==="string"){A='"'+A.replace("\n","\\n")+'"'}B.push(A)}w.push(y.opcode+" "+B.join(" "))}}return w.join("\n")},equals:function(u){var l=this.opcodes.length;if(u.opcodes.length!==l){return false}for(var x=0;x<l;x++){var y=this.opcodes[x],v=u.opcodes[x];if(y.opcode!==v.opcode||y.args.length!==v.args.length){return false}for(var w=0;w<y.args.length;w++){if(y.args[w]!==v.args[w]){return false}}}l=this.children.length;if(u.children.length!==l){return false}for(x=0;x<l;x++){if(!this.children[x].equals(u.children[x])){return false}}return true},guid:0,compile:function(i,u){this.children=[];this.depths={list:[]};this.options=u;var v=this.options.knownHelpers;this.options.knownHelpers={helperMissing:true,blockHelperMissing:true,each:true,"if":true,unless:true,"with":true,log:true};if(v){for(var l in v){this.options.knownHelpers[l]=v[l]}}return this.program(i)},accept:function(i){return this[i.type](i)},program:function(w){var v=w.statements,y;this.opcodes=[];for(var x=0,u=v.length;x<u;x++){y=v[x];this[y.type](y)}this.isSimple=u===1;this.depths.list=this.depths.list.sort(function(l,i){return l-i});return this},compileProgram:function(w){var u=new this.compiler().compile(w,this.options);var x=this.guid++,z;this.usePartial=this.usePartial||u.usePartial;this.children[x]=u;for(var y=0,v=u.depths.list.length;y<v;y++){z=u.depths.list[y];if(z<2){continue}else{this.addDepth(z-1)}}return x},block:function(w){var v=w.mustache,l=w.program,i=w.inverse;if(l){l=this.compileProgram(l)}if(i){i=this.compileProgram(i)}var u=this.classifyMustache(v);if(u==="helper"){this.helperMustache(v,l,i)}else{if(u==="simple"){this.simpleMustache(v);this.opcode("pushProgram",l);this.opcode("pushProgram",i);this.opcode("emptyHash");this.opcode("blockValue")}else{this.ambiguousMustache(v,l,i);this.opcode("pushProgram",l);this.opcode("pushProgram",i);this.opcode("emptyHash");this.opcode("ambiguousBlockValue")}}this.opcode("append")},hash:function(x){var w=x.pairs,z,y;this.opcode("pushHash");for(var v=0,u=w.length;v<u;v++){z=w[v];y=z[1];if(this.options.stringParams){if(y.depth){this.addDepth(y.depth)}this.opcode("getContext",y.depth||0);this.opcode("pushStringParam",y.stringModeValue,y.type)}else{this.accept(y)}this.opcode("assignToHash",z[0])}this.opcode("popHash")},partial:function(i){var l=i.partialName;this.usePartial=true;if(i.context){this.ID(i.context)}else{this.opcode("push","depth0")}this.opcode("invokePartial",l.name);this.opcode("append")},content:function(i){this.opcode("appendContent",i.string)},mustache:function(u){var i=this.options;var l=this.classifyMustache(u);if(l==="simple"){this.simpleMustache(u)}else{if(l==="helper"){this.helperMustache(u)}else{this.ambiguousMustache(u)}}if(u.escaped&&!i.noEscape){this.opcode("appendEscaped")}else{this.opcode("append")}},ambiguousMustache:function(w,u,l){var x=w.id,v=x.parts[0],i=u!=null||l!=null;this.opcode("getContext",x.depth);this.opcode("pushProgram",u);this.opcode("pushProgram",l);this.opcode("invokeAmbiguous",v,i)},simpleMustache:function(i){var l=i.id;if(l.type==="DATA"){this.DATA(l)}else{if(l.parts.length){this.ID(l)}else{this.addDepth(l.depth);this.opcode("getContext",l.depth);this.opcode("pushContext")}}this.opcode("resolvePossibleLambda")},helperMustache:function(v,l,i){var w=this.setupFullMustacheParams(v,l,i),u=v.id.parts[0];if(this.options.knownHelpers[u]){this.opcode("invokeKnownHelper",w.length,u)}else{if(this.options.knownHelpersOnly){throw new Error("You specified knownHelpersOnly, but used the unknown helper "+u)}else{this.opcode("invokeHelper",w.length,u)}}},ID:function(x){this.addDepth(x.depth);this.opcode("getContext",x.depth);var v=x.parts[0];if(!v){this.opcode("pushContext")}else{this.opcode("lookupOnContext",x.parts[0])}for(var w=1,u=x.parts.length;w<u;w++){this.opcode("lookup",x.parts[w])}},DATA:function(i){this.options.data=true;this.opcode("lookupData",i.id)},STRING:function(i){this.opcode("pushString",i.string)},INTEGER:function(i){this.opcode("pushLiteral",i.integer)},BOOLEAN:function(i){this.opcode("pushLiteral",i.bool)},comment:function(){},opcode:function(i){this.opcodes.push({opcode:i,args:[].slice.call(arguments,1)})},declare:function(i,l){this.opcodes.push({opcode:"DECLARE",name:i,value:l})},addDepth:function(i){if(isNaN(i)){throw new Error("EWOT")}if(i===0){return}if(!this.depths[i]){this.depths[i]=true;this.depths.list.push(i)}},classifyMustache:function(v){var u=v.isHelper;var w=v.eligibleHelper;var l=this.options;if(w&&!u){var i=v.id.parts[0];if(l.knownHelpers[i]){u=true}else{if(l.knownHelpersOnly){w=false}}}if(u){return"helper"}else{if(w){return"ambiguous"}else{return"simple"}}},pushParams:function(v){var l=v.length,u;while(l--){u=v[l];if(this.options.stringParams){if(u.depth){this.addDepth(u.depth)}this.opcode("getContext",u.depth||0);this.opcode("pushStringParam",u.stringModeValue,u.type)}else{this[u.type](u)}}},setupMustacheParams:function(i){var l=i.params;this.pushParams(l);if(i.hash){this.hash(i.hash)}else{this.opcode("emptyHash")}return l},setupFullMustacheParams:function(u,l,i){var v=u.params;this.pushParams(v);this.opcode("pushProgram",l);this.opcode("pushProgram",i);if(u.hash){this.hash(u.hash)}else{this.opcode("emptyHash")}return v}};var s=function(i){this.value=i};g.prototype={nameLookup:function(l,i){if(/^[0-9]+$/.test(i)){return l+"["+i+"]"}else{if(g.isValidJavaScriptVariableName(i)){return l+"."+i}else{return l+"['"+i+"']"}}},appendToBuffer:function(i){if(this.environment.isSimple){return"return "+i+";"}else{return{appendToBuffer:true,content:i,toString:function(){return"buffer += "+i+";"}}}},initializeBuffer:function(){return this.quotedString("")},namespace:"Handlebars",compile:function(i,l,v,u){this.environment=i;this.options=l||{};d.log(d.logger.DEBUG,this.environment.disassemble()+"\n\n");this.name=this.environment.name;this.isChild=!!v;this.context=v||{programs:[],environments:[],aliases:{}};this.preamble();this.stackSlot=0;this.stackVars=[];this.registers={list:[]};this.compileStack=[];this.inlineStack=[];this.compileChildren(i,l);var x=i.opcodes,w;this.i=0;for(m=x.length;this.i<m;this.i++){w=x[this.i];if(w.opcode==="DECLARE"){this[w.name]=w.value}else{this[w.opcode].apply(this,w.args)}}return this.createFunctionContext(u)},nextOpcode:function(){var i=this.environment.opcodes;return i[this.i+1]},eat:function(){this.i=this.i+1},preamble:function(){var i=[];if(!this.isChild){var l=this.namespace;var u="helpers = helpers || "+l+".helpers;";if(this.environment.usePartial){u=u+" partials = partials || "+l+".partials;"}if(this.options.data){u=u+" data = data || {};"}i.push(u)}else{i.push("")}if(!this.environment.isSimple){i.push(", buffer = "+this.initializeBuffer())}else{i.push("")}this.lastContext=0;this.source=i},createFunctionContext:function(B){var w=this.stackVars.concat(this.registers.list);if(w.length>0){this.source[1]=this.source[1]+", "+w.join(", ")}if(!this.isChild){for(var A in this.context.aliases){this.source[1]=this.source[1]+", "+A+"="+this.context.aliases[A]}}if(this.source[1]){this.source[1]="var "+this.source[1].substring(2)+";"}if(!this.isChild){this.source[1]+="\n"+this.context.programs.join("\n")+"\n"}if(!this.environment.isSimple){this.source.push("return buffer;")}var y=this.isChild?["depth0","data"]:["Handlebars","depth0","helpers","partials","data"];for(var z=0,x=this.environment.depths.list.length;z<x;z++){y.push("depth"+this.environment.depths.list[z])}var u=this.mergeSource();if(!this.isChild){var C=d.COMPILER_REVISION,v=d.REVISION_CHANGES[C];u="this.compilerInfo = ["+C+",'"+v+"'];\n"+u}if(B){y.push(u);return Function.apply(this,y)}else{var D="function "+(this.name||"")+"("+y.join(",")+") {\n "+u+"}";d.log(d.logger.DEBUG,D+"\n\n");return D}},mergeSource:function(){var x="",v;for(var w=0,l=this.source.length;w<l;w++){var u=this.source[w];if(u.appendToBuffer){if(v){v=v+"\n + "+u.content}else{v=u.content}}else{if(v){x+="buffer += "+v+";\n ";v=c}x+=u+"\n "}}return x},blockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var i=["depth0"];this.setupParams(0,i);this.replaceStack(function(l){i.splice(1,0,l);return"blockHelperMissing.call("+i.join(", ")+")"})},ambiguousBlockValue:function(){this.context.aliases.blockHelperMissing="helpers.blockHelperMissing";var l=["depth0"];this.setupParams(0,l);var i=this.topStack();l.splice(1,0,i);l[l.length-1]="options";this.source.push("if (!"+this.lastHelper+") { "+i+" = blockHelperMissing.call("+l.join(", ")+"); }")},appendContent:function(i){this.source.push(this.appendToBuffer(this.quotedString(i)))},append:function(){this.flushInline();var i=this.popStack();this.source.push("if("+i+" || "+i+" === 0) { "+this.appendToBuffer(i)+" }");if(this.environment.isSimple){this.source.push("else { "+this.appendToBuffer("''")+" }")}},appendEscaped:function(){this.context.aliases.escapeExpression="this.escapeExpression";this.source.push(this.appendToBuffer("escapeExpression("+this.popStack()+")"))},getContext:function(i){if(this.lastContext!==i){this.lastContext=i}},lookupOnContext:function(i){this.push(this.nameLookup("depth"+this.lastContext,i,"context"))},pushContext:function(){this.pushStackLiteral("depth"+this.lastContext)},resolvePossibleLambda:function(){this.context.aliases.functionType='"function"';this.replaceStack(function(i){return"typeof "+i+" === functionType ? "+i+".apply(depth0) : "+i})},lookup:function(i){this.replaceStack(function(l){return l+" == null || "+l+" === false ? "+l+" : "+this.nameLookup(l,i,"context")})},lookupData:function(i){this.push(this.nameLookup("data",i,"data"))},pushStringParam:function(i,l){this.pushStackLiteral("depth"+this.lastContext);this.pushString(l);if(typeof i==="string"){this.pushString(i)}else{this.pushStackLiteral(i)}},emptyHash:function(){this.pushStackLiteral("{}");if(this.options.stringParams){this.register("hashTypes","{}");this.register("hashContexts","{}")}},pushHash:function(){this.hash={values:[],types:[],contexts:[]}},popHash:function(){var i=this.hash;this.hash=c;if(this.options.stringParams){this.register("hashContexts","{"+i.contexts.join(",")+"}");this.register("hashTypes","{"+i.types.join(",")+"}")}this.push("{\n "+i.values.join(",\n ")+"\n }")},pushString:function(i){this.pushStackLiteral(this.quotedString(i))},push:function(i){this.inlineStack.push(i);return i},pushLiteral:function(i){this.pushStackLiteral(i)},pushProgram:function(i){if(i!=null){this.pushStackLiteral(this.programExpression(i))}else{this.pushStackLiteral(null)}},invokeHelper:function(u,i){this.context.aliases.helperMissing="helpers.helperMissing";var l=this.lastHelper=this.setupHelper(u,i,true);this.push(l.name);this.replaceStack(function(v){return v+" ? "+v+".call("+l.callParams+") : helperMissing.call("+l.helperMissingParams+")"})},invokeKnownHelper:function(u,i){var l=this.setupHelper(u,i);this.push(l.name+".call("+l.callParams+")")},invokeAmbiguous:function(i,w){this.context.aliases.functionType='"function"';this.pushStackLiteral("{}");var l=this.setupHelper(0,i,w);var u=this.lastHelper=this.nameLookup("helpers",i,"helper");var x=this.nameLookup("depth"+this.lastContext,i,"context");var v=this.nextStack();this.source.push("if ("+v+" = "+u+") { "+v+" = "+v+".call("+l.callParams+"); }");this.source.push("else { "+v+" = "+x+"; "+v+" = typeof "+v+" === functionType ? "+v+".apply(depth0) : "+v+"; }")},invokePartial:function(i){var l=[this.nameLookup("partials",i,"partial"),"'"+i+"'",this.popStack(),"helpers","partials"];if(this.options.data){l.push("data")}this.context.aliases.self="this";this.push("self.invokePartial("+l.join(", ")+")")},assignToHash:function(l){var v=this.popStack(),i,u;if(this.options.stringParams){u=this.popStack();i=this.popStack()}var w=this.hash;if(i){w.contexts.push("'"+l+"': "+i)}if(u){w.types.push("'"+l+"': "+u)}w.values.push("'"+l+"': ("+v+")")},compiler:g,compileChildren:function(u,x){var z=u.children,B,A;for(var y=0,v=z.length;y<v;y++){B=z[y];A=new this.compiler();var w=this.matchExistingProgram(B);if(w==null){this.context.programs.push("");w=this.context.programs.length;B.index=w;B.name="program"+w;this.context.programs[w]=A.compile(B,x,this.context);this.context.environments[w]=B}else{B.index=w;B.name="program"+w}}},matchExistingProgram:function(w){for(var v=0,u=this.context.environments.length;v<u;v++){var l=this.context.environments[v];if(l&&l.equals(w)){return v}}},programExpression:function(v){this.context.aliases.self="this";if(v==null){return"self.noop"}var A=this.environment.children[v],z=A.depths.list,y;var x=[A.index,A.name,"data"];for(var w=0,u=z.length;w<u;w++){y=z[w];if(y===1){x.push("depth0")}else{x.push("depth"+(y-1))}}return(z.length===0?"self.program(":"self.programWithDepth(")+x.join(", ")+")"},register:function(i,l){this.useRegister(i);this.source.push(i+" = "+l+";")},useRegister:function(i){if(!this.registers[i]){this.registers[i]=true;this.registers.list.push(i)}},pushStackLiteral:function(i){return this.push(new s(i))},pushStack:function(l){this.flushInline();var i=this.incrStack();if(l){this.source.push(i+" = "+l+";")}this.compileStack.push(i);return i},replaceStack:function(y){var v="",x=this.isInline(),i;if(x){var w=this.popStack(true);if(w instanceof s){i=w.value}else{var l=this.stackSlot?this.topStackName():this.incrStack();v="("+this.push(l)+" = "+w+"),";i=this.topStack()}}else{i=this.topStack()}var u=y.call(this,i);if(x){if(this.inlineStack.length||this.compileStack.length){this.popStack()}this.push("("+v+u+")")}else{if(!/^stack/.test(i)){i=this.nextStack()}this.source.push(i+" = ("+v+u+");")}return i},nextStack:function(){return this.pushStack()},incrStack:function(){this.stackSlot++;if(this.stackSlot>this.stackVars.length){this.stackVars.push("stack"+this.stackSlot)}return this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var v=this.inlineStack;if(v.length){this.inlineStack=[];for(var u=0,l=v.length;u<l;u++){var w=v[u];if(w instanceof s){this.compileStack.push(w)}else{this.pushStack(w)}}}},isInline:function(){return this.inlineStack.length},popStack:function(i){var u=this.isInline(),l=(u?this.inlineStack:this.compileStack).pop();if(!i&&(l instanceof s)){return l.value}else{if(!u){this.stackSlot--}return l}},topStack:function(l){var i=(this.isInline()?this.inlineStack:this.compileStack),u=i[i.length-1];if(!l&&(u instanceof s)){return u.value}else{return u}},quotedString:function(i){return'"'+i.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\u2028/g,"\\u2028").replace(/\u2029/g,"\\u2029")+'"'},setupHelper:function(w,u,l){var v=[];this.setupParams(w,v,l);var i=this.nameLookup("helpers",u,"helper");return{params:v,name:i,callParams:["depth0"].concat(v).join(", "),helperMissingParams:l&&["depth0",this.quotedString(u)].concat(v).join(", ")}},setupParams:function(w,v,l){var C=[],A=[],B=[],u,x,z;C.push("hash:"+this.popStack());x=this.popStack();z=this.popStack();if(z||x){if(!z){this.context.aliases.self="this";z="self.noop"}if(!x){this.context.aliases.self="this";x="self.noop"}C.push("inverse:"+x);C.push("fn:"+z)}for(var y=0;y<w;y++){u=this.popStack();v.push(u);if(this.options.stringParams){B.push(this.popStack());A.push(this.popStack())}}if(this.options.stringParams){C.push("contexts:["+A.join(",")+"]");C.push("types:["+B.join(",")+"]");C.push("hashContexts:hashContexts");C.push("hashTypes:hashTypes")}if(this.options.data){C.push("data:data")}C="{"+C.join(",")+"}";if(l){this.register("options",C);v.push("options")}else{v.push(C)}return v.join(", ")}};var f=("break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public let yield").split(" ");var a=g.RESERVED_WORDS={};for(var o=0,m=f.length;o<m;o++){a[f[o]]=true}g.isValidJavaScriptVariableName=function(i){if(!g.RESERVED_WORDS[i]&&/^[a-zA-Z_$][0-9a-zA-Z_$]+$/.test(i)){return true}return false};d.precompile=function(u,v){if(u==null||(typeof u!=="string"&&u.constructor!==d.AST.ProgramNode)){throw new d.Exception("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+u)}v=v||{};if(!("data" in v)){v.data=true}var l=d.parse(u);var i=new j().compile(l,v);return new g().compile(i,v)};d.compile=function(i,l){if(i==null||(typeof i!=="string"&&i.constructor!==d.AST.ProgramNode)){throw new d.Exception("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+i)}l=l||{};if(!("data" in l)){l.data=true}var v;function u(){var y=d.parse(i);var x=new j().compile(y,l);var w=new g().compile(x,l,c,true);return d.template(w)}return function(x,w){if(!v){v=u()}return v.call(this,x,w)}};d.VM={template:function(i){var l={escapeExpression:d.Utils.escapeExpression,invokePartial:d.VM.invokePartial,programs:[],program:function(v,w,x){var u=this.programs[v];if(x){u=d.VM.program(v,w,x)}else{if(!u){u=this.programs[v]=d.VM.program(v,w)}}return u},programWithDepth:d.VM.programWithDepth,noop:d.VM.noop,compilerInfo:null};return function(y,x){x=x||{};var v=i.call(l,d,y,x.helpers,x.partials,x.data);var z=l.compilerInfo||[],w=z[0]||1,B=d.COMPILER_REVISION;if(w!==B){if(w<B){var u=d.REVISION_CHANGES[B],A=d.REVISION_CHANGES[w];throw"Template was precompiled with an older version of Handlebars than the current runtime. Please update your precompiler to a newer version ("+u+") or downgrade your runtime to an older version ("+A+")."}else{throw"Template was precompiled with a newer version of Handlebars than the current runtime. Please update your runtime to a newer version ("+z[1]+")."}}return v}},programWithDepth:function(v,w,x){var u=Array.prototype.slice.call(arguments,3);var l=function(y,i){i=i||{};return w.apply(this,[y,i.data||x].concat(u))};l.program=v;l.depth=u.length;return l},program:function(u,v,w){var l=function(x,i){i=i||{};return v(x,i.data||w)};l.program=u;l.depth=0;return l},noop:function(){return""},invokePartial:function(i,u,w,x,v,y){var l={helpers:x,partials:v,data:y};if(i===c){throw new d.Exception("The partial "+u+" could not be found")}else{if(i instanceof Function){return i(w,l)}else{if(!d.compile){throw new d.Exception("The partial "+u+" could not be compiled when running in runtime-only mode")}else{v[u]=d.compile(i,{data:y!==c});return v[u](w,l)}}}}};d.template=d.VM.template})(Handlebars); \ No newline at end of file diff --git a/template_basic/handlebars_helper.js b/template_basic/handlebars_helper.js index 681902b1..58a7cd40 100644 --- a/template_basic/handlebars_helper.js +++ b/template_basic/handlebars_helper.js @@ -18,7 +18,7 @@ define([ Handlebars.registerHelper("underscoreToSpace", function(text){ return text.replace(/(_+)/g, " "); }); - + /** * */ diff --git a/template_basic/index.html b/template_basic/index.html index 15f96c8e..5b41cc79 100644 --- a/template_basic/index.html +++ b/template_basic/index.html @@ -106,41 +106,43 @@ <h1>{{underscoreToSpace article.group}} - {{article.title}}</h1> <pre class="prettyprint language-json" data-type="json"><code>{{{content}}}</code></pre> {{/each}} - {{subTemplate "article-param-block" params=article.parameter _title="Parameter" _hasType=_hasTypeInParameterFields}} - {{subTemplate "article-param-block" params=article.success _title="Success (200)" _hasType=_hasTypeInSuccessFields}} - {{subTemplate "article-param-block" params=article.error _title="Error (4xx)" _col1="Name" _hasType=_hasTypeInErrorFields}} + {{subTemplate "article-param-block" params=article.parameter _hasType=_hasTypeInParameterFields}} + {{subTemplate "article-param-block" params=article.success _hasType=_hasTypeInSuccessFields}} + {{subTemplate "article-param-block" params=article.info _hasType=_hasTypeInInfoFields}} + {{subTemplate "article-param-block" params=article.error _col1="Name" _hasType=_hasTypeInErrorFields}} </article> </script> <script id="template-article-param-block" type="text/x-handlebars-template"> {{#if params}} - <h2>{{__ _title}}</h2> - {{#if params.fields}} + {{#each params.fields}} + <h2>{{__ @key}}</h2> <table> <thead> <tr> <th style="width: 30%">{{#if _col1}}{{__ _col1}}{{else}}{{__ "Field"}}{{/if}}</th> - {{#if _hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} + {{#if ../_hasType}}<th style="width: 10%">{{__ "Type"}}</th>{{/if}} <th style="width: {{#if _hasType}}60%{{else}}70%{{/if}}">{{__ "Description"}}</th> </tr> </thead> <tbody> - {{#each params.fields}} + {{#each this}} <tr> <td class="code">{{{splitFill field "." " "}}}{{#if optional}} <span class="label label-optional">{{__ "optional"}}</span>{{/if}}</td> {{#if ../../_hasType}}<td>{{{type}}}</td>{{/if}} - <td>{{{nl2br description}}}</td> + <td> + {{{nl2br description}}} + {{#if defaultValue}}<p class="default-value">{{__ "Default value:"}} <code>{{{defaultValue}}}</code></p>{{/if}} + </td> </tr> {{/each}} </tbody> </table> - {{else}} - <p>{{__ "No response values."}}</p> - {{/if}} - {{#each params.examples}} - <strong>{{title}}</strong> - <pre class="prettyprint language-json" data-type="json"><code>{{{content}}}</code></pre> + {{#each params.examples}} + <strong>{{title}}</strong> + <pre class="prettyprint language-json" data-type="json"><code>{{{content}}}</code></pre> + {{/each}} {{/each}} {{/if}} </script> diff --git a/template_basic/locales/de.js b/template_basic/locales/de.js index fc941e18..b97f6ccb 100644 --- a/template_basic/locales/de.js +++ b/template_basic/locales/de.js @@ -3,8 +3,8 @@ define({ "Compare all with predecessor": "Vergleiche alle mit ihren Vorgängern", "compare changes to:" : "vergleiche Änderungen mit:", "compared to" : "verglichen mit", + "Default value:" : "Standardwert:", "Description" : "Beschreibung", - "Error (4xx)" : "Error (4xx)", "Field" : "Feld", "General" : "Allgemein", "Generated with" : "Erstellt mit", @@ -14,7 +14,6 @@ define({ "Parameter" : "Parameter", "Permission:" : "Berechtigung:", "show up to version:" : "zeige bis zur Version:", - "Success (200)" : "Success (200)", "Type" : "Typ" } }); \ No newline at end of file diff --git a/template_basic/main.js b/template_basic/main.js index ecc5a72c..3972cfc4 100644 --- a/template_basic/main.js +++ b/template_basic/main.js @@ -73,8 +73,12 @@ require([ // Titel der ersten Einträge von group[].name[] ermitteln (name hat Versionsliste) var titles = {}; $.each(groupEntries, function(index, entries) { - var title = entries[0].title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; }); - titles[title + " #~#" + index] = 1; + var title = entries[0].title; + if(title) + { + title.toLowerCase().replace(/[äöüß]/g, function($0) { return umlauts[$0]; }); + titles[title + " #~#" + index] = 1; + } }); // each // Sortieren var values = Object.keys(titles); @@ -232,9 +236,10 @@ require([ }; } - if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _.any(entry.parameter.fields, function(item) { return item.type; }); - if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _.any(entry.error.fields, function(item) { return item.type; }); - if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _.any(entry.success.fields, function(item) { return item.type; }); + if(entry.parameter && entry.parameter.fields) fields._hasTypeInParameterFields = _hasTypeInFields(entry.parameter.fields); + if(entry.error && entry.error.fields) fields._hasTypeInErrorFields = _hasTypeInFields(entry.error.fields); + if(entry.success && entry.success.fields) fields._hasTypeInSuccessFields = _hasTypeInFields(entry.success.fields); + if(entry.info && entry.info.fields) fields._hasTypeInInfoFields = _hasTypeInFields(entry.info.fields); articles.push({ article: templateArticle(fields), @@ -274,6 +279,25 @@ require([ $('html,body').animate({ scrollTop: parseInt($(id).offset().top) - 18 }, 0); } + /** + * Check if Parameter (sub) List has a type Field. + * Example: @apaSuccess varname1 No type. + * @apaSuccess {String} varname2 With type. + * + * @param {Object} fields + */ + function _hasTypeInFields(fields) + { + hasField = false; + $.each(fields, function(name) { + if(_.any(fields[name], function(item) { return item.type; }) ) + { + hasField = true; + } + }); + return hasField; + } // _hasTypeInFields + /** * On Template changes, recall plugins. */ diff --git a/test/fixtures/api_data.js b/test/fixtures/api_data.js index 2c3bae49..86ef8401 100644 --- a/test/fixtures/api_data.js +++ b/test/fixtures/api_data.js @@ -1,40 +1,366 @@ define({ api: [ { "type": "get", - "url": "/log/:id", - "title": "Get", - "description": "Daten eines Logs laden.", + "url": "/test1/:id", + "title": "Get Test 1", + "name": "GetTest1", + "group": "Test", + "version": "0.1.1", + "description": "Test Version 0.1.x\nTest some basic functions.", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "String", + "field": "param1", + "optional": false, + "description": "Parameter with type and description." + }, + { + "group": "Parameter", + "type": "String", + "field": "param2", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param3", + "defaultValue": "Default Value", + "optional": true, + "description": "Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param4", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param5", + "optional": false, + "description": "Basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param6", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "field": "param7", + "defaultValue": "Default Value", + "optional": true, + "description": "Basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param8", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param9", + "optional": true, + "description": "Optional basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param10", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param11", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param12", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param13", + "optional": true, + "description": "Optional Parameter with type and description." + }, + { + "group": "Parameter", + "type": "String", + "field": "param14", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param15", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param16", + "defaultValue": "Default Value", + "optional": true, + "description": "" + } + ] + } + }, + "filename": "test\\fixtures\\example\\example.js" + }, + { + "type": "get", + "url": "/test1/:id", + "title": "Get Test 1", + "name": "GetTest1", + "group": "Test", + "version": "0.1.0", + "description": "Test Version 0.1.x\nTest some basic functions.", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "String", + "field": "param0", + "optional": false, + "description": "This param is removed in 0.1.1." + }, + { + "group": "Parameter", + "type": "String", + "field": "param1", + "optional": false, + "description": "This is an old text." + }, + { + "group": "Parameter", + "type": "String", + "field": "param2", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param3", + "defaultValue": "Default Value", + "optional": true, + "description": "Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param4", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param5", + "optional": false, + "description": "Basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param6", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "field": "param7", + "defaultValue": "Default Value", + "optional": true, + "description": "Basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param8", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param9", + "optional": true, + "description": "Optional basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param10", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param11", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param12", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param13", + "optional": true, + "description": "Optional Parameter with type and description." + }, + { + "group": "Parameter", + "type": "String", + "field": "param14", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param15", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param16", + "defaultValue": "Default Value", + "optional": true, + "description": "" + } + ] + } + }, + "filename": "test\\fixtures\\example\\example.js" + }, + { + "type": "get", + "url": "/test2/:id", + "title": "Get Test 2", + "name": "GetTest2", + "group": "Test", "version": "0.2.0", - "permission": "none", + "description": "Test Version 0.2.x\nTest Title and Grouping of param, success, error", "parameter": { - "fields": [ - { - "type": "String", - "field": "param1", - "optional": false, - "description": "Beschreibung Param1" - }, - { - "type": "String", - "field": "param2", - "optional": false - }, - { - "type": "String", - "field": "param3", - "defaultValue": "Default Value", - "optional": true, - "description": "Beschreibung Param3" - }, - { - "type": "String", - "field": "param4", - "defaultValue": "Default Value", - "optional": true - } - ] + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "String", + "field": "param1", + "optional": false, + "description": "No Group, automatically set Group to \"Parameter\"" + } + ], + "Replace \"login\" with this text": [ + { + "group": "login", + "type": "String", + "field": "param2", + "optional": false, + "description": "Group \"login\"" + }, + { + "group": "login", + "type": "String", + "field": "param3", + "defaultValue": "Default Value", + "optional": true, + "description": "Group \"login\" with default Value" + } + ] + } + }, + "success": { + "fields": { + "201 - Everything ok, replace \"201\" with this text.": [ + { + "group": "201", + "type": "String", + "field": "success2", + "optional": false, + "description": "Group \"201\"" + }, + { + "group": "201", + "type": "String", + "field": "success3", + "defaultValue": "Default Value", + "optional": true, + "description": "Group \"201\" with default Value" + } + ], + "Success 200": [ + { + "group": "Success 200", + "type": "String", + "field": "success1", + "optional": false, + "description": "No Group, automatically set \"Success 200\"" + } + ] + } + }, + "error": { + "fields": { + "400": [ + { + "group": "400", + "type": "String", + "field": "error2", + "optional": false, + "description": "Group \"400\"" + } + ], + "401 - Oh oh, replace \"401\" with this text": [ + { + "group": "401", + "type": "String", + "field": "error3", + "optional": false, + "description": "Group \"401\"" + } + ], + "Error 4xx": [ + { + "group": "Error 4xx", + "type": "String", + "field": "error1", + "optional": false, + "description": "No Group automatically set \"Error 4xx\"" + } + ] + } }, - "group": "example.js", - "filename": "test/fixtures/example/example.js" + "filename": "test\\fixtures\\example\\example.js" } ] }); \ No newline at end of file diff --git a/test/fixtures/api_data.json b/test/fixtures/api_data.json index 04fb5a2f..26491f33 100644 --- a/test/fixtures/api_data.json +++ b/test/fixtures/api_data.json @@ -1,40 +1,366 @@ [ { "type": "get", - "url": "/log/:id", - "title": "Get", - "description": "Daten eines Logs laden.", + "url": "/test1/:id", + "title": "Get Test 1", + "name": "GetTest1", + "group": "Test", + "version": "0.1.1", + "description": "Test Version 0.1.x\nTest some basic functions.", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "String", + "field": "param1", + "optional": false, + "description": "Parameter with type and description." + }, + { + "group": "Parameter", + "type": "String", + "field": "param2", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param3", + "defaultValue": "Default Value", + "optional": true, + "description": "Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param4", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param5", + "optional": false, + "description": "Basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param6", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "field": "param7", + "defaultValue": "Default Value", + "optional": true, + "description": "Basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param8", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param9", + "optional": true, + "description": "Optional basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param10", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param11", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param12", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param13", + "optional": true, + "description": "Optional Parameter with type and description." + }, + { + "group": "Parameter", + "type": "String", + "field": "param14", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param15", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param16", + "defaultValue": "Default Value", + "optional": true, + "description": "" + } + ] + } + }, + "filename": "test\\fixtures\\example\\example.js" + }, + { + "type": "get", + "url": "/test1/:id", + "title": "Get Test 1", + "name": "GetTest1", + "group": "Test", + "version": "0.1.0", + "description": "Test Version 0.1.x\nTest some basic functions.", + "parameter": { + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "String", + "field": "param0", + "optional": false, + "description": "This param is removed in 0.1.1." + }, + { + "group": "Parameter", + "type": "String", + "field": "param1", + "optional": false, + "description": "This is an old text." + }, + { + "group": "Parameter", + "type": "String", + "field": "param2", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param3", + "defaultValue": "Default Value", + "optional": true, + "description": "Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param4", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param5", + "optional": false, + "description": "Basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param6", + "optional": false, + "description": "" + }, + { + "group": "Parameter", + "field": "param7", + "defaultValue": "Default Value", + "optional": true, + "description": "Basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param8", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param9", + "optional": true, + "description": "Optional basic Parameter with description." + }, + { + "group": "Parameter", + "field": "param10", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "field": "param11", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional basic Parameter with description and default value." + }, + { + "group": "Parameter", + "field": "param12", + "defaultValue": "Default Value", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param13", + "optional": true, + "description": "Optional Parameter with type and description." + }, + { + "group": "Parameter", + "type": "String", + "field": "param14", + "optional": true, + "description": "" + }, + { + "group": "Parameter", + "type": "String", + "field": "param15", + "defaultValue": "Default Value", + "optional": true, + "description": "Optional Parameter with type, description and default value." + }, + { + "group": "Parameter", + "type": "String", + "field": "param16", + "defaultValue": "Default Value", + "optional": true, + "description": "" + } + ] + } + }, + "filename": "test\\fixtures\\example\\example.js" + }, + { + "type": "get", + "url": "/test2/:id", + "title": "Get Test 2", + "name": "GetTest2", + "group": "Test", "version": "0.2.0", - "permission": "none", + "description": "Test Version 0.2.x\nTest Title and Grouping of param, success, error", "parameter": { - "fields": [ - { - "type": "String", - "field": "param1", - "optional": false, - "description": "Beschreibung Param1" - }, - { - "type": "String", - "field": "param2", - "optional": false - }, - { - "type": "String", - "field": "param3", - "defaultValue": "Default Value", - "optional": true, - "description": "Beschreibung Param3" - }, - { - "type": "String", - "field": "param4", - "defaultValue": "Default Value", - "optional": true - } - ] + "fields": { + "Parameter": [ + { + "group": "Parameter", + "type": "String", + "field": "param1", + "optional": false, + "description": "No Group, automatically set Group to \"Parameter\"" + } + ], + "Replace \"login\" with this text": [ + { + "group": "login", + "type": "String", + "field": "param2", + "optional": false, + "description": "Group \"login\"" + }, + { + "group": "login", + "type": "String", + "field": "param3", + "defaultValue": "Default Value", + "optional": true, + "description": "Group \"login\" with default Value" + } + ] + } + }, + "success": { + "fields": { + "201 - Everything ok, replace \"201\" with this text.": [ + { + "group": "201", + "type": "String", + "field": "success2", + "optional": false, + "description": "Group \"201\"" + }, + { + "group": "201", + "type": "String", + "field": "success3", + "defaultValue": "Default Value", + "optional": true, + "description": "Group \"201\" with default Value" + } + ], + "Success 200": [ + { + "group": "Success 200", + "type": "String", + "field": "success1", + "optional": false, + "description": "No Group, automatically set \"Success 200\"" + } + ] + } + }, + "error": { + "fields": { + "400": [ + { + "group": "400", + "type": "String", + "field": "error2", + "optional": false, + "description": "Group \"400\"" + } + ], + "401 - Oh oh, replace \"401\" with this text": [ + { + "group": "401", + "type": "String", + "field": "error3", + "optional": false, + "description": "Group \"401\"" + } + ], + "Error 4xx": [ + { + "group": "Error 4xx", + "type": "String", + "field": "error1", + "optional": false, + "description": "No Group automatically set \"Error 4xx\"" + } + ] + } }, - "group": "example.js", - "filename": "test/fixtures/example/example.js" + "filename": "test\\fixtures\\example\\example.js" } ] \ No newline at end of file diff --git a/test/fixtures/api_project.js b/test/fixtures/api_project.js index 7ce3c673..5bc72255 100644 --- a/test/fixtures/api_project.js +++ b/test/fixtures/api_project.js @@ -1,10 +1,10 @@ define({ "name": "apidoc", - "version": "0.1.10", + "version": "0.2.0", "description": "RESTful web API Documentation Generator", "apidoc": "", "generator": { - "version": "0.1.10", - "time": "2013-04-12T16:50:18.630Z" + "version": "0.2.0", + "time": "2013-05-30T18:44:56.859Z" } }); \ No newline at end of file diff --git a/test/fixtures/api_project.json b/test/fixtures/api_project.json index 1f80f92e..b8826e58 100644 --- a/test/fixtures/api_project.json +++ b/test/fixtures/api_project.json @@ -1,10 +1,10 @@ { "name": "apidoc", - "version": "0.1.10", + "version": "0.2.0", "description": "RESTful web API Documentation Generator", "apidoc": "", "generator": { - "version": "0.1.10", - "time": "2013-04-12T16:50:18.630Z" + "version": "0.2.0", + "time": "2013-05-30T18:44:56.859Z" } } \ No newline at end of file diff --git a/test/fixtures/example/example.js b/test/fixtures/example/example.js index d7c7e9df..090fd4f5 100644 --- a/test/fixtures/example/example.js +++ b/test/fixtures/example/example.js @@ -5,36 +5,95 @@ /** * @apiIgnore Ignore this block, apiIgnore is set. * @api {get} /ignore/me + * Test whitespaces befor block. */ /** - * @api {get} /log/:id Get - * @apiDescription Daten eines Logs laden. - * test + * @api {get} /test1/:id Get Test 1 + * @apiName GetTest1 + * @apiGroup Test + * @apiVersion 0.1.1 + * @apiDescription Test Version 0.1.x + * Test some basic functions. * - * @apiVersion 0.2.0 - * @apiPermission none - * @apiDescription Daten eines Logs laden. + * @apiParam {String} param1 Parameter with type and description. + * @apiParam {String} param2 + * @apiParam {String} param3="Default Value" Parameter with type, description and default value. + * @apiParam {String} param4="Default Value" + * + * @apiParam param5 Basic Parameter with description. + * @apiParam param6 + * @apiParam param7="Default Value" Basic Parameter with description and default value. + * @apiParam param8="Default Value" + * + * @apiParam [param9] Optional basic Parameter with description. + * @apiParam [param10] + * @apiParam [param11="Default Value"] Optional basic Parameter with description and default value. + * @apiParam [param12="Default Value"] + * + * @apiParam {String} [param13] Optional Parameter with type and description. + * @apiParam {String} [param14] + * @apiParam {String} [param15="Default Value"] Optional Parameter with type, description and default value. + * @apiParam {String} [param16="Default Value"] + */ + +/** + * @api {get} /test1/:id Get Test 1 + * @apiName GetTest1 + * @apiGroup Test + * @apiVersion 0.1.0 + * @apiDescription Test Version 0.1.x + * Test some basic functions. * - * @apiParam {String} param1 Beschreibung Param1 + * @apiParam {String} param0 This param is removed in 0.1.1. + * @apiParam {String} param1 This is an old text. * @apiParam {String} param2 - * @apiParam {String} param3="Default Value" Beschreibung Param3 + * @apiParam {String} param3="Default Value" Parameter with type, description and default value. * @apiParam {String} param4="Default Value" * - * @apiParam param1 Beschreibung Param1 - * @apiParam param2 - * @apiParam param3="Default Value" Beschreibung Param3 - * @apiParam param4="Default Value" + * @apiParam param5 Basic Parameter with description. + * @apiParam param6 + * @apiParam param7="Default Value" Basic Parameter with description and default value. + * @apiParam param8="Default Value" * - * @apiParam [param1] Beschreibung Param1 - * @apiParam [param2] - * @apiParam [param3="Default Value"] Beschreibung Param3 - * @apiParam [param4="Default Value"] + * @apiParam [param9] Optional basic Parameter with description. + * @apiParam [param10] + * @apiParam [param11="Default Value"] Optional basic Parameter with description and default value. + * @apiParam [param12="Default Value"] + * + * @apiParam {String} [param13] Optional Parameter with type and description. + * @apiParam {String} [param14] + * @apiParam {String} [param15="Default Value"] Optional Parameter with type, description and default value. + * @apiParam {String} [param16="Default Value"] + */ + +/** + * @api {get} /test2/:id Get Test 2 + * @apiName GetTest2 + * @apiGroup Test + * @apiVersion 0.2.0 + * @apiDescription Test Version 0.2.x + * Test Title and Grouping of param, success, error * - * @apiParam {String} [param1] Beschreibung Param1 - * @apiParam {String} [param2] - * @apiParam {String} [param3="Default Value"] Beschreibung Param3 - * @apiParam {String} [param4="Default Value"] * - * @api {get} /log/:id Get - */ \ No newline at end of file + * @apiParam {String} param1 No Group, automatically set Group to "Parameter" + * + * @apiParamTitle (login) Replace "login" with this text + * @apiParam (login) {String} param2 Group "login" + * @apiParam (login) {String} param3="Default Value" Group "login" with default Value + * + * + * @apiSuccess {String} success1 No Group, automatically set "Success 200" + * + * @apiSuccessTitle (201) 201 - Everything ok, replace "201" with this text. + * @apiSuccess (201) {String} success2 Group "201" + * @apiSuccess (201) {String} success3="Default Value" Group "201" with default Value + * + * + * @apiError {String} error1 No Group automatically set "Error 4xx" + * + * @apiError (400) {String} error2 Group "400" + * + * @apiErrorTitle (401) 401 - Oh oh, replace "401" with this text + * @apiError (401) {String} error3 Group "401" + */