StackGenVis: Alignment of Data, Algorithms, and Models for Stacking Ensemble Learning Using Performance Metrics https://doi.org/10.1109/TVCG.2020.3030352
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
StackGenVis/frontend/node_modules/templates/lib/plugins/render.js

354 lines
9.9 KiB

4 years ago
'use strict';
var debug = require('debug')('base:templates:render');
var utils = require('../utils');
module.exports = function(proto) {
debug('loading render methods onto %s, <%s>', proto.constructor.name);
/**
* Set view types for a collection.
*
* @param {String} `plural` e.g. `pages`
* @param {Object} `options`
*/
if (typeof proto.viewType !== 'function') {
proto.viewType = viewType;
}
function viewType(plural, types) {
var len = types.length, i = 0;
while (len--) {
var type = types[i++];
this.viewTypes[type] = this.viewTypes[type] || [];
if (this.viewTypes[type].indexOf(plural) === -1) {
this.viewTypes[type].push(plural);
}
}
return types;
}
/**
* Iterates over `renderable` view collections
* and returns the first view that matches the
* given `view` name
*/
function findView(app, name) {
var keys = app.viewTypes.renderable;
var len = keys.length;
var i = -1;
var res = null;
while (++i < len) {
res = app.find(name, keys[i]);
if (res) {
break;
}
}
return res;
}
/**
* Get a view from the specified collection, or list,
* or iterate over view collections until the view
* is found.
*/
function getView(app, view) {
if (typeof view !== 'string') {
return view;
}
if (app.isCollection) {
view = app.getView(view);
} else if (app.isList) {
view = app.getItem(view);
} else {
view = findView(app, view);
}
return view;
}
/**
* Compile `content` with the given `locals`.
*
* ```js
* var indexPage = app.page('some-index-page.hbs');
* var view = app.compile(indexPage);
* // view.fn => [function]
*
* // you can call the compiled function more than once
* // to render the view with different data
* view.fn({title: 'Foo'});
* view.fn({title: 'Bar'});
* view.fn({title: 'Baz'});
* ```
*
* @name .compile
* @param {Object|String} `view` View object.
* @param {Object} `locals`
* @param {Boolean} `isAsync` Load async helpers
* @return {Object} View object with compiled `view.fn` property.
* @api public
*/
proto.compile = function(view, locals, isAsync) {
if (typeof locals === 'boolean') {
isAsync = locals;
locals = {};
}
if (typeof locals === 'function' || typeof isAsync === 'function') {
throw this.formatError('compile', 'callback');
}
locals = utils.extend({settings: {}}, locals);
// if `view` is a string, see if it's a cached view
if (typeof view === 'string') {
view = getView(this, view);
}
// handle `preCompile` middleware
this.handleOnce('preCompile', view);
// determine the name of the engine to use
var ext = utils.resolveEngineExt(view, locals, this.options);
// get the actual engine (object)
var engine = this.getEngine(ext);
// throw if an engine is not defined
if (typeof engine === 'undefined') {
throw this.formatError('compile', 'engine', formatExtError(view, ext));
}
// clean up engine name, for consistency
ext = engine.options.ext;
engine.options.engineName = engine.options.name;
delete engine.options.name;
// get engine options (settings)
var engineOpts = utils.merge({}, locals.settings, engine.options);
var ctx = cacheContext(this, view, locals);
// apply layout
view = this.applyLayout(view);
// Bind context to helpers before passing to the engine.
this.bindHelpers(view, ctx, (ctx.async = !!isAsync));
// shallow clone the context and locals
engineOpts = utils.merge({}, ctx, engineOpts, this.mergePartials(engineOpts));
// compile the string
view.fn = engine.compile(view.content, engineOpts);
// handle `postCompile` middleware
this.handleOnce('postCompile', view);
return view;
};
/**
* Asynchronously compile `content` with the given `locals` and callback. _(fwiw, this
* method name uses the unconventional "*Async" nomenclature to allow us to preserve the
* synchronous behavior of the `view.compile` method as well as the name)_.
*
* ```js
* var indexPage = app.page('some-index-page.hbs');
* app.compileAsync(indexPage, function(err, view) {
* // view.fn => compiled function
* });
* ```
* @name .compileAsync
* @param {Object|String} `view` View object.
* @param {Object} `locals`
* @param {Boolean} `isAsync` Pass true to load helpers as async (mostly used internally)
* @param {Function} `callback` function that exposes `err` and the `view` object with compiled `view.fn` property
* @api public
*/
proto.compileAsync = function(view, locals, isAsync, cb) {
if (typeof locals === 'function') {
return this.compileAsync(view, {}, false, locals);
}
if (typeof isAsync === 'function') {
return this.compileAsync(view, locals, false, isAsync);
}
if (typeof locals === 'boolean') {
return this.compileAsync(view, {}, locals, isAsync);
}
// if `view` is a string, see if it's a cached view
if (typeof view === 'string') {
view = getView(this, view);
}
if (typeof view.engineStack === 'undefined') {
utils.define(view, 'engineStack', {});
}
locals = utils.extend({settings: {}}, locals);
var ctx = this.context(view, locals);
var app = this;
// handle `preCompile` middleware
this.handleOnce('preCompile', view, function(err, file) {
if (err) return cb(err);
// determine the name of the engine to use
var ext = utils.resolveEngineExt(file, ctx, app.options);
// get the actual engine (object)
var engine = app.getEngine(ext);
if (typeof engine === 'undefined') {
cb(app.formatError('compile', 'engine', formatExtError(file, ext)));
return;
}
ext = engine.options.ext;
engine.options.engineName = engine.options.name;
delete engine.options.name;
// get engine options (settings)
var engineOpts = utils.merge({}, locals.settings, engine.options);
// apply layout
app.applyLayoutAsync(file, function(err, view) {
if (err) return cb(err);
// Bind context to helpers before passing to the engine.
app.bindHelpers(view, ctx, (ctx.async = !!isAsync));
app.mergePartialsAsync(engineOpts, function(err, partials) {
if (err) return cb(err);
// shallow clone the context and engineOpts
var mergedSettings = utils.merge({}, engineOpts, ctx, partials);
var content = view.content;
if (view.engineStack.hasOwnProperty(ext)) {
content = view.engineStack[ext].content;
}
// compile the string
view.fn = engine.compile(content, mergedSettings);
utils.engineStack(view, ext, view.fn, content);
// handle `postCompile` middleware
app.handleOnce('postCompile', view, cb);
});
});
});
};
/**
* Render a view with the given `locals` and `callback`.
*
* ```js
* var blogPost = app.post.getView('2015-09-01-foo-bar');
* app.render(blogPost, {title: 'Foo'}, function(err, view) {
* // `view` is an object with a rendered `content` property
* });
* ```
* @name .render
* @param {Object|String} `view` Instance of `View`
* @param {Object} `locals` Locals to pass to template engine.
* @param {Function} `callback`
* @api public
*/
proto.render = function(view, locals, cb) {
if (typeof locals === 'function') {
cb = locals;
locals = {};
}
if (typeof cb !== 'function') {
throw this.formatError('render', 'callback');
}
// if `view` is a string, see if it's a cached view
if (typeof view === 'string') {
view = getView(this, view);
}
if (typeof view.localsStack === 'undefined') {
utils.define(view, 'localsStack', []);
}
var ctx = cacheContext(this, view, locals);
var app = this;
// handle `preRender` middleware
this.handleOnce('preRender', view, function(err, file) {
if (err) return cb(err);
// get the engine
var ext = utils.resolveEngineExt(file, ctx, app.options);
var engine = app.getEngine(ext);
if (!engine) {
cb(app.formatError('render', 'engine', formatExtError(file, ext)));
return;
}
// since we already merged context, add it to a property
// so it can be used by `compile`
if (app.options.cacheContext === true) {
file._context = ctx;
}
// compile the view
app.compileAsync(file, ctx, true, function(err, view) {
if (err) return cb(err);
// build the context one more time in case it has changed
var context = cacheContext(app, file, ctx);
// render the view
engine.render(view.fn, context, function(err, res) {
if (err) {
// rethrow is a noop if `options.rethrow` is not true
var renderErr = app.rethrow('render', err, view, context);
if (app.hasListeners('error')) {
app.emit('error', renderErr || err);
}
cb(renderErr || err);
return;
}
view.localsStack.push(locals);
view.content = res;
delete view._context;
// handle `postRender` middleware
app.handleOnce('postRender', view, cb);
});
});
});
};
};
function formatExtError(view, ext) {
if (ext && typeof ext === 'string' && ext.trim()) {
return ext;
}
return view.basename;
}
function cacheContext(app, file, context) {
if (typeof app.options.cacheContext === 'function') {
file._context = app.options.cacheContext(file, context, app);
} else if (app.options.cacheContext === true && typeof file.context === 'function') {
return (file._context || file.context(context));
} else if (typeof file.context === 'function') {
return file.context(app.cache.data, context);
} else {
return context;
}
}