require.config({ paths: { bootstrap: './vendor/bootstrap.min', diffMatchPatch: './vendor/diff_match_patch.min', handlebars: './vendor/handlebars.min', handlebarsExtended: './utils/handlebars_helper', jquery: './vendor/jquery.min', locales: './locales/locale', lodash: './vendor/lodash.v4.17.11.min', pathToRegexp: './vendor/path-to-regexp/index', prettify: './vendor/prettify/prettify', semver: './vendor/semver.min', utilsSampleRequest: './utils/send_sample_request', webfontloader: './vendor/webfontloader', list: './vendor/list.min', clipboardJS: './vendor/clipboard.min', copyToClipboard: './vendor/copyToClipboard' }, shim: { bootstrap: { deps: ['jquery'] }, diffMatchPatch: { exports: 'diff_match_patch' }, handlebars: { exports: 'Handlebars' }, handlebarsExtended: { deps: ['jquery', 'handlebars'], exports: 'Handlebars' }, prettify: { exports: 'prettyPrint' } }, urlArgs: 'v=' + (new Date()).getTime(), waitSeconds: 15 }); require([ // eslint-disable-line 'jquery', 'lodash', 'locales', 'handlebarsExtended', './api_project.js', './api_data.js', 'prettify', 'utilsSampleRequest', 'semver', 'webfontloader', 'clipboardJS', 'copyToClipboard', 'bootstrap', 'pathToRegexp', 'list' ], function ($, _, locale, Handlebars, apiProject, apiData, prettyPrint, sampleRequest, semver, WebFont, clipboardJS, copyToClipboard) { // load google web fonts loadGoogleFontCss(); var api = apiData.api; // // Templates // var templateHeader = Handlebars.compile($('#template-header').html()); var templateFooter = Handlebars.compile($('#template-footer').html()); var templateArticle = Handlebars.compile($('#template-article').html()); var templateCompareArticle = Handlebars.compile($('#template-compare-article').html()); var templateGenerator = Handlebars.compile($('#template-generator').html()); var templateProject = Handlebars.compile($('#template-project').html()); var templateSections = Handlebars.compile($('#template-sections').html()); var templateSidenav = Handlebars.compile($('#template-sidenav').html()); // // apiProject defaults // if (!apiProject.template) apiProject.template = {}; if (apiProject.template.withCompare == null) apiProject.template.withCompare = true; if (apiProject.template.withGenerator == null) apiProject.template.withGenerator = true; if (apiProject.template.forceLanguage) locale.setLanguage(apiProject.template.forceLanguage); // Setup jQuery Ajax $.ajaxSetup(apiProject.template.jQueryAjaxSetup); // // Data transform // // grouped by group var apiByGroup = _.groupBy(api, function (entry) { return entry.group; }); // grouped by group and name var apiByGroupAndName = {}; $.each(apiByGroup, function (index, entries) { apiByGroupAndName[index] = _.groupBy(entries, function (entry) { return entry.name; }); }); // // sort api within a group by title ASC and custom order // var newList = []; var umlauts = { 'ä': 'ae', 'ü': 'ue', 'ö': 'oe', 'ß': 'ss' }; $.each(apiByGroupAndName, function (index, groupEntries) { // get titles from the first entry of group[].name[] (name has versioning) var titles = []; $.each(groupEntries, function (titleName, entries) { var title = entries[0].title; if (title !== undefined) { title.toLowerCase().replace(/[äöüß]/g, function ($0) { return umlauts[$0]; }); titles.push(title + '#~#' + titleName); // '#~#' keep reference to titleName after sorting } }); // sort by name ASC titles.sort(); // custom order if (apiProject.order) titles = sortByOrder(titles, apiProject.order, '#~#'); // add single elements to the new list titles.forEach(function (name) { var values = name.split('#~#'); var key = values[1]; groupEntries[key].forEach(function (entry) { newList.push(entry); }); }); }); // api overwrite with ordered list api = newList; // // Group- and Versionlists // var apiGroups = {}; var apiGroupTitles = {}; var apiVersions = {}; apiVersions[apiProject.version] = 1; $.each(api, function (index, entry) { apiGroups[entry.group] = 1; apiGroupTitles[entry.group] = entry.groupTitle || entry.group; apiVersions[entry.version] = 1; }); // sort groups apiGroups = Object.keys(apiGroups); apiGroups.sort(); // custom order if (apiProject.order) apiGroups = sortByOrder(apiGroups, apiProject.order); // sort versions DESC apiVersions = Object.keys(apiVersions); apiVersions.sort(semver.compare); apiVersions.reverse(); // // create Navigationlist // var nav = []; apiGroups.forEach(function (group) { // Mainmenu entry nav.push({ group: group, isHeader: true, title: apiGroupTitles[group] }); // Submenu var oldName = ''; api.forEach(function (entry) { if (entry.group === group) { if (oldName !== entry.name) { nav.push({ title: entry.title, group: group, name: entry.name, type: entry.type, typeName: shortenType(entry.type), version: entry.version }); } else { nav.push({ title: entry.title, group: group, hidden: true, name: entry.name, type: entry.type, typeName: shortenType(entry.type), version: entry.version }); } oldName = entry.name; } }); }); // Mainmenu Header entry if (apiProject.header) { nav.unshift({ group: '_', isHeader: true, title: (apiProject.header.title == null) ? locale.__('General') : apiProject.header.title, isFixed: true }); } // Mainmenu Footer entry if (apiProject.footer && apiProject.footer.title != null) { nav.push({ group: '_footer', isHeader: true, title: apiProject.footer.title, isFixed: true }); } var filterName = apiProject.name .split('-') .map(function (s) { return s.charAt(0).toUpperCase() + s.substring(1); }) .join(' ') .split('_') .join(' '); apiProject.name = filterName; // render pagetitle var title = apiProject.title ? apiProject.title : 'Documentation: ' + apiProject.name + ' - ' + apiProject.version; $(document).attr('title', title); // remove loader $('#loader').remove(); // render sidenav var fields = { nav: nav, apiName: apiProject.name || null }; $('#sidenav').append(templateSidenav(fields)); // render Generator $('#generator').append(templateGenerator(apiProject)); // render Project _.extend(apiProject, { versions: apiVersions }); $('#project').append(templateProject(apiProject)); // render apiDoc, header/footer documentation if (apiProject.header) $('#header').append(templateHeader(apiProject.header)); if (apiProject.footer) $('#footer').append(templateFooter(apiProject.footer)); // // Render Sections and Articles // var articleVersions = {}; var content = ''; apiGroups.forEach(function (groupEntry) { var articles = []; var oldName = ''; var fields = {}; var title = groupEntry; var description = ''; articleVersions[groupEntry] = {}; // render all articles of a group api.forEach(function (entry) { if (groupEntry === entry.group) { if (oldName !== entry.name) { // determine versions api.forEach(function (versionEntry) { if (groupEntry === versionEntry.group && entry.name === versionEntry.name) { if (!articleVersions[entry.group].hasOwnProperty(entry.name)) { articleVersions[entry.group][entry.name] = []; } articleVersions[entry.group][entry.name].push(versionEntry.version); } }); fields = { article: entry, versions: articleVersions[entry.group][entry.name] }; } else { fields = { article: entry, hidden: true, versions: articleVersions[entry.group][entry.name] }; } // add prefix URL for endpoint if (apiProject.url) fields.article.url = apiProject.url + fields.article.url; addArticleSettings(fields, entry); if (entry.groupTitle) title = entry.groupTitle; if (entry.groupDescription) description = entry.groupDescription; articles.push({ article: templateArticle(fields), group: entry.group, name: entry.name }); oldName = entry.name; } }); // render Section with Articles var fields = { group: groupEntry, title: title, description: description, articles: articles }; content += templateSections(fields); }); $('#sections').append(content); // Bootstrap Scrollspy $(this).scrollspy({ target: '#scrollingNav', offset: 18 }); // Content-Scroll on Navigation click. $('.sidenav').find('a').on('click', function (e) { e.preventDefault(); var id = $(this).attr('href'); if ($(id).length > 0) $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 400); window.location.hash = $(this).attr('href'); }); // Quickjump on Pageload to hash position. if (window.location.hash) { var id = window.location.hash; if ($(id).length > 0) $('html,body').animate({ scrollTop: parseInt($(id).offset().top) }, 0); } /** * Check if Parameter (sub) List has a type Field. * Example: @apiSuccess varname1 No type. * @apiSuccess {String} varname2 With type. * * @param {Object} fields */ function _hasTypeInFields(fields) { var result = false; $.each(fields, function (name) { if (_.some(fields[name], function (item) { return item.type; })) result = true; }); return result; } /** * On Template changes, recall plugins. */ function initDynamic() { // bootstrap popover $('a[data-toggle=popover]') .popover() .click(function (e) { e.preventDefault(); }); var version = $('#version strong').html(); $('#sidenav li').removeClass('is-new'); if (apiProject.template.withCompare) { $('#sidenav li[data-version=\'' + version + '\']').each(function () { var group = $(this).data('group'); var name = $(this).data('name'); var length = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').length; var index = $('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\']').index($(this)); if (length === 1 || index === (length - 1)) $(this).addClass('is-new'); }); } // tabs $('.nav-tabs-examples a').click(function (e) { e.preventDefault(); $(this).tab('show'); }); $('.nav-tabs-examples').find('a:first').tab('show'); // sample request switch $('.sample-request-switch').click(function (e) { var name = '.' + $(this).attr('name') + '-fields'; $(name).addClass('hide'); $(this).parent().next(name).removeClass('hide'); }); // call scrollspy refresh method $(window).scrollspy('refresh'); // init modules sampleRequest.initDynamic(); /** * * * * * * * * * * * * * * * show json schema in modal dialog * * * * * * * * * * * * * * */ var jsonTypes = ['string', 'number', 'integer', 'float', 'double', 'object', 'array', 'boolean', 'null']; $('.json-schema').click(function (e) { e.preventDefault(); var group = this.getAttribute('data-group'); var param = this.getAttribute('data-param'); var articleName = this.closest('article').getAttribute('data-name'); var indx = api.findIndex(function (entry) { return entry.name === articleName}); if (!group || !param || indx === -1) { return; } var jsondata = api[indx][param].fields[group]; if (!jsondata) return; var jsonSchema = {}; jsondata.forEach(function (keys) { var type = keys.type.toLowerCase(); if (jsonTypes.includes(type) && type !== 'object') { var res = expandDot(keys.field.split('.'), jsonSchema, type); jsonSchema = res; } }); jsonSchema = { "type": "object", "properties": jsonSchema }; $('#preData').text(syntaxHighlight(jsonSchema, true)); jsonSchema = '
' + syntaxHighlight(jsonSchema, false) + '';
$('#jsonModal .modal-title').html(articleName.split('_').join(' ') + ' - ' + param + ' ' + group);
$('#json-pre').html(jsonSchema);
$('#jsonModal').modal('toggle');
prettyPrint();
});
/** * * * * * * * * * * * * * *
* click copy to clipboard
* * * * * * * * * * * * * * */
var permissionClipboard = new clipboardJS('.label-permission');
permissionClipboard.on('success', showTooltip);
$('.label-permission').on('shown.bs.tooltip', hideTooltip);
var uriClipboard = new clipboardJS('.full-pre', {
target: function (trigger) {
return $(trigger).children('.url')[0];
}
});
uriClipboard.on('success', showTooltip);
$('.full-pre').on('shown.bs.tooltip', hideTooltip);
$('.modal-clipboard').on('click', function () {
var code = $('#preData').text();
var copySuccess = copyToClipboard(code, document.getElementById('jsonModal'));
if (copySuccess) {
showTooltip({ action: 'copy', trigger: $('.modal-clipboard') });
}
});
$('.modal-clipboard').on('shown.bs.tooltip', hideTooltip);
function showTooltip(e) {
if (e.action === 'copy') {
$(e.trigger).tooltip({ trigger: 'manual', placement: 'bottom', title: 'Coped to clipboard!' });
$(e.trigger).tooltip('show');
}
}
function hideTooltip(e) {
e.preventDefault();
setTimeout(function (el) {
$(el).tooltip('hide');
}, 800, this);
}
}
initDynamic();
// Pre- / Code-Format
prettyPrint();
//
// HTML-Template specific jQuery-Functions
//
// Change Main Version
$('#versions li.version a').on('click', function (e) {
e.preventDefault();
var selectedVersion = $(this).html();
$('#version strong').html(selectedVersion);
// hide all
$('article').addClass('hide');
$('#sidenav li:not(.nav-fixed)').addClass('hide');
// show 1st equal or lower Version of each entry
$('article[data-version]').each(function (index) {
var group = $(this).data('group');
var name = $(this).data('name');
var version = $(this).data('version');
if (version <= selectedVersion) {
if ($('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible').length === 0) {
// enable Article
$('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide');
// enable Navigation
$('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('hide');
$('#sidenav li.nav-header[data-group=\'' + group + '\']').removeClass('hide');
}
}
});
// show 1st equal or lower Version of each entry
$('article[data-version]').each(function (index) {
var group = $(this).data('group');
$('section#api-' + group).removeClass('hide');
if ($('section#api-' + group + ' article:visible').length === 0) {
$('section#api-' + group).addClass('hide');
} else {
$('section#api-' + group).removeClass('hide');
}
});
initDynamic();
return;
});
// compare all article with their predecessor
$('#compareAllWithPredecessor').on('click', changeAllVersionCompareTo);
// change version of an article
$('article .versions li.version a').on('click', changeVersionCompareTo);
// compare url-parameter
$.urlParam = function (name) {
var results = new RegExp('[\\?&]' + name + '=([^&#]*)').exec(window.location.href);
return (results && results[1]) ? results[1] : null;
};
if ($.urlParam('compare')) {
// URL Paramter ?compare=1 is set
$('#compareAllWithPredecessor').trigger('click');
if (window.location.hash) {
var id = window.location.hash;
$('html,body').animate({
scrollTop: parseInt($(id).offset().top) - 18
}, 0);
}
}
/**
* Initialize search
*/
var options = {
valueNames: ['nav-list-item']
};
var endpointsList = new List('scrollingNav', options);
/**
* Set initial focus to search input
*/
$('#scrollingNav .sidenav-search input.search').focus();
/**
* Detect ESC key to reset search
*/
$(document).keyup(function (e) {
if (e.keyCode === 27) $('span.search-reset').click();
});
/**
* Search reset
*/
$('span.search-reset').on('click', function () {
$('#scrollingNav .sidenav-search input.search')
.val("")
.focus();
endpointsList.search();
});
/**
* Change version of an article to compare it to an other version.
*/
function changeVersionCompareTo(e) {
e.preventDefault();
var $root = $(this).parents('article');
var selectedVersion = $(this).html();
var $button = $root.find('.version');
var currentVersion = $button.find('strong').html();
$button.find('strong').html(selectedVersion);
var group = $root.data('group');
var name = $root.data('name');
var version = $root.data('version');
var compareVersion = $root.data('compare-version');
if (compareVersion === selectedVersion)
return;
if (!compareVersion && version == selectedVersion)
return;
if (compareVersion && articleVersions[group][name][0] === selectedVersion || version === selectedVersion) {
// the version of the entry is set to the highest version (reset)
resetArticle(group, name, version);
} else {
var $compareToArticle = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + selectedVersion + '\']');
var sourceEntry = {};
var compareEntry = {};
$.each(apiByGroupAndName[group][name], function (index, entry) {
if (entry.version === version)
sourceEntry = entry;
if (entry.version === selectedVersion)
compareEntry = entry;
});
var fields = {
article: sourceEntry,
compare: compareEntry,
versions: articleVersions[group][name]
};
// add unique id
fields.article.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version;
fields.article.id = fields.article.id.replace(/\./g, '_');
fields.compare.id = fields.compare.group + '-' + fields.compare.name + '-' + fields.compare.version;
fields.compare.id = fields.compare.id.replace(/\./g, '_');
var entry = sourceEntry;
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 = _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);
var $content = $root.next();
// Event on.click re-assign
$content.find('.versions li.version a').on('click', changeVersionCompareTo);
// select navigation
$('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + currentVersion + '\']').addClass('has-modifications');
$root.remove();
}
initDynamic();
}
/**
* Compare all currently selected Versions with their predecessor.
*/
function changeAllVersionCompareTo(e) {
e.preventDefault();
$('article:visible .versions').each(function () {
var $root = $(this).parents('article');
var currentVersion = $root.data('version');
var $foundElement = null;
$(this).find('li.version a').each(function () {
var selectVersion = $(this).html();
if (selectVersion < currentVersion && !$foundElement)
$foundElement = $(this);
});
if ($foundElement)
$foundElement.trigger('click');
});
initDynamic();
}
/**
* Add article settings.
*/
function addArticleSettings(fields, entry) {
// add unique id
fields.id = fields.article.group + '-' + fields.article.name + '-' + fields.article.version;
fields.id = fields.id.replace(/\./g, '_');
if (entry.header && entry.header.fields)
fields._hasTypeInHeaderFields = _hasTypeInFields(entry.header.fields);
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);
// add template settings
fields.template = apiProject.template;
}
/**
* Render Article.
*/
function renderArticle(group, name, version) {
var entry = {};
$.each(apiByGroupAndName[group][name], function (index, currentEntry) {
if (currentEntry.version === version)
entry = currentEntry;
});
var fields = {
article: entry,
versions: articleVersions[group][name]
};
addArticleSettings(fields, entry);
return templateArticle(fields);
}
/**
* Render original Article and remove the current visible Article.
*/
function resetArticle(group, name, version) {
var $root = $('article[data-group=\'' + group + '\'][data-name=\'' + name + '\']:visible');
var content = renderArticle(group, name, version);
$root.after(content);
var $content = $root.next();
// Event on.click muss neu zugewiesen werden (sollte eigentlich mit on automatisch funktionieren... sollte)
$content.find('.versions li.version a').on('click', changeVersionCompareTo);
$('#sidenav li[data-group=\'' + group + '\'][data-name=\'' + name + '\'][data-version=\'' + version + '\']').removeClass('has-modifications');
$root.remove();
return;
}
/**
* Load google fonts.
*/
function loadGoogleFontCss() {
WebFont.load({
active: function () {
// Update scrollspy
$(window).scrollspy('refresh');
},
google: {
families: ['Oxygen:400,700', 'Roboto:400,600,500,700', 'Source+Code+Pro:400,600,700']
}
});
}
/**
* Return ordered entries by custom order and append not defined entries to the end.
* @param {String[]} elements
* @param {String[]} order
* @param {String} splitBy
* @return {String[]} Custom ordered list.
*/
function sortByOrder(elements, order, splitBy) {
var results = [];
order.forEach(function (name) {
if (splitBy)
elements.forEach(function (element) {
var parts = element.split(splitBy);
var key = parts[1]; // reference keep for sorting
if (key == name)
results.push(element);
});
else
elements.forEach(function (key) {
if (key == name)
results.push(name);
});
});
// Append all other entries that ar not defined in order
elements.forEach(function (element) {
if (results.indexOf(element) === -1)
results.push(element);
});
return results;
}
function shortenType(methodType) {
switch(methodType.toUpperCase()) {
case 'DELETE':
return 'DEL';
case 'PATCH':
return 'PATC';
case 'OPTIONS':
return 'OPT';
case 'GET':
case 'POST':
case 'PUT':
default:
return methodType.toUpperCase();
}
}
function expandDot(dots, obj, type) {
if (!obj || dots.length === 0) {
return obj;
}
if (type === 'object') {
obj[dots[0]] = {
"type": "object",
"properties": {}
};
return obj;
}
if (type === 'array') {
obj[dots[0]] = {
"type": "array",
"items": {}
};
return obj;
}
var par = dots[0];
var rest = dots.slice(1);
if (obj[par]) {
if (obj[par].type && obj[par].type === 'array') {
obj[par]['items'] = expandDot(rest, obj[par]['items'] ? obj[par]['items'] : {}, type);
}
else {
obj[par]['properties'] = expandDot(rest, obj[par]['properties'] ? obj[par]['properties'] : {}, type);
}
}
else if (rest.length > 0) {
var properties = expandDot(rest, {}, type);
obj[par] = {
"type": "object",
"properties": properties
};
}
else {
obj[par] = {
"type": type
};
}
return obj;
}
/**
* https://stackoverflow.com/a/7220510/4839437
*/
function syntaxHighlight(json, raw) {
if (typeof json != 'string') {
json = JSON.stringify(json, undefined, 2);
}
json = json.replace(/&/g, '&').replace(//g, '>');
if (raw) {
return json;
}
return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
var cls = 'number';
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key';
} else {
cls = 'string';
}
} else if (/true|false/.test(match)) {
cls = 'boolean';
} else if (/null/.test(match)) {
cls = 'null';
}
return '' + match + '';
});
}
});