1
0
mirror of /repos/Prototyper.git synced 2025-12-30 06:31:32 +01:00
Prototyper/lib/preview.js
2015-07-03 18:10:15 +02:00

262 lines
8.3 KiB
JavaScript

'use strict';
var Handlebars = require('handlebars');
var markdown = require('markdown').markdown;
var _ = require('underscore');
var less = require('less');
var when = require('when');
module.exports = function (config, dataInstance, helpers, markers) {
var getPreviewHTML;
var script_tag = markers.script_tag;
var script_regexp = markers.script_regexp;
var style_tag = markers.style_tag;
var style_regexp = markers.style_regexp;
var less_tag = markers.less_tag;
var less_regexp = markers.less_regexp;
var template_tag = markers.template_tag;
var template_regexp = markers.template_regexp;
var markdown_tag = markers.markdown_tag;
var markdown_regexp = markers.markdown_regexp;
var remove_tag = markers.remove_tag;
//var remove_regexp = markers.remove_regexp;
var replaceMarkers = function (html, options) {
var promises = [];
// Script tag handling
promises.push(
helpers.replace(html, script_tag, function handleScriptMarker(result, callback) {
var parts = script_regexp.exec(result);
var context = {
collection: parts[1],
name: parts[2],
attribute: parts[3]
};
return callback && callback(null, {
regExp: new RegExp(result, 'gmi'),
value: '<script src="' + config.api.content + '/' + context.collection + '/' + context.name + '/' + context.attribute + '.js" type="text/javascript" charset="utf-8"></script>'
});
}));
// Style tag handling
promises.push(
helpers.replace(html, style_tag, function handleStyleMarker(result, callback) {
var parts = style_regexp.exec(result);
var context = {
collection: parts[1],
name: parts[2],
attribute: parts[3]
};
return callback && callback(null, {
regExp: new RegExp(result, 'gmi'),
value: '<link href="' + config.api.content + '/' + context.collection + '/' + context.name + '/' + context.attribute + '.css" media="all" rel="stylesheet" type="text/css">'
});
}));
// Less tag handling
promises.push(
helpers.replace(html, less_tag, function handleStyleMarker(result, callback) {
var parts = less_regexp.exec(result);
var context = {
collection: parts[1],
name: parts[2],
attribute: parts[3]
};
return callback && callback(null, {
regExp: new RegExp(result, 'gmi'),
value: '<link href="' + config.api.content + '/' + context.collection + '/' + context.name + '/' + context.attribute + '.less" media="all" rel="stylesheet/less" type="text/css">'
});
}));
// Template tag handling
promises.push(
helpers.replace(html, template_tag, function handleTemplateMarker(result, callback) {
var parts = template_regexp.exec(result);
var template = {
collection: parts[1],
name: parts[2],
attribute: parts[3],
query: {name: parts[2]}
};
var context = {
collection: parts[4],
name: parts[5],
query: {name: parts[5]},
req: options.req
};
return dataInstance.getContent(context, function handleContext(err, context_result) {
if (err) {
config.error && config.error('ERR template_tag getContent', context);
return callback && callback(err);
}
return dataInstance.getAttribute(template, function handleTemplate(err, template_result) {
if (err) {
config.error && config.error('ERR template_tag getAttribute', template, err);
return callback && callback(err);
}
var compiled_template = null;
var keys_to_collect = {};
function collectKey(key) {
return function () {
if (keys_to_collect.hasOwnProperty(key)) {
return keys_to_collect[key];
}
keys_to_collect[key] = null;
return 'waiting for content';
};
}
// Handlebars is synchronous ouch !!
var handlebars = Handlebars.create();
_.forEach(_.keys(context_result), function (key) {
handlebars.registerHelper(key, function () {
if (context_result[key].guid) {
return collectKey(key)();
}
return context_result[key];
});
});
try {
compiled_template = handlebars.compile(template_result[template.attribute]);
} catch (error1) {
config.error && config.error('ERR template_tag Handlebars.compile', template, error1);
return callback && callback(error1);
}
var extendHandlebars_context = function (result) {
var handlebars = {};
_.forEach(_.keys(result), function (key) {
if (result[key].guid) {
handlebars[key] = collectKey(key);
} else {
handlebars[key] = result[key];
}
});
return handlebars;
};
var handlebars_context = extendHandlebars_context(context_result);
try {
compiled_template(handlebars_context);
} catch (error2) {
config.error && config.error('ERR template_tag Handlebars.render', template, context, error2);
return callback && callback(error2);
}
var promises = [];
_.forEach(_.keys(keys_to_collect), function gatherKeyValues(key) {
//noinspection JSUnresolvedFunction
var deferred = when.defer();
var promise = deferred.promise;
promises.push(promise);
var attribute_context = {
collection: context.collection,
attribute: key,
query: {}
};
attribute_context.query[config.database.pk] = context_result[config.database.pk];
return dataInstance.getAttribute(attribute_context, function cacheTemplateKey(err, template_key_result) {
if (err) {
config.error && config.error('ERR handlebar.registerHelper getAttribute', err);
deferred.reject(err);
}
var value = template_key_result[key];
keys_to_collect[key] = value;
deferred.resolve(value);
});
});
//noinspection JSUnresolvedFunction
return when.all(promises).then(
function onSuccess() {
var rendered = null;
try {
rendered = compiled_template(handlebars_context);
} catch (err) {
config.error && config.error('ERR template_tag Handlebars.render', template, context, err);
return callback && callback(err);
}
config.debug && config.debug('// handle markers on rendered template');
context.query = {};
context.query[config.database.pk] = context_result[config.database.pk];
return getPreviewHTML(rendered, context, function handlePreviewResult(err, preview_html) {
if (err) {
config.error && config.error('ERR template_tag getPreviewHTML', err);
return callback(err);
}
return callback(null, {
regExp: new RegExp(result, 'gmi'),
value: preview_html
});
});
},
function onFailure(err) {
config.error && config.error('ERR template_tag resolving promises', err);
return callback && callback(err);
}
);
});
});
}));
// Markdown tag handling
promises.push(
helpers.replace(html, markdown_tag, function handleMarkDownMarker(result, callback) {
var parts = markdown_regexp.exec(result);
var attribute = {
collection: parts[1],
name: parts[2],
attribute: parts[3],
query: {name: parts[2]}
};
return dataInstance.getAttribute(attribute, function handleMarkdownContent(err, markdown_result) {
if (err) {
return callback && callback(err);
}
var html = markdown.toHTML(markdown_result[attribute.attribute]);
return callback && callback(null, {
regExp: new RegExp(result, 'gmi'),
value: html
});
});
}));
// Remove tag handling
promises.push(
helpers.replace(html, remove_tag, function handleRemoveMarker(result, callback) {
return callback && callback(null, {
regExp: null,
value: ''
});
}, true));
return promises;
};
getPreviewHTML = function (content, options, callback) {
config.debug && config.debug('getPreviewHTML', content);
var promises = replaceMarkers(content, options);
function handler(text, result) {
return text.replace(result.regExp, result.replacement);
}
return helpers.handTextManipulation(content,
promises,
handler,
callback
);
};
return {
getPreviewHTML: getPreviewHTML,
_replaceMarkers: replaceMarkers
};
};