starplate
Version:
View engine built on incremental-dom
261 lines (217 loc) • 6.12 kB
JavaScript
;
/**
* Module dependencies.
*/
Object.defineProperty(exports, '__esModule', {
value: true
});
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
var _view = require('./view');
/**
* Ensures an object.
*
* @private
* @function
* @name ensureObject
* @param {Mixed} o
* @return {Object}
*/
var ensureObject = function ensureObject(o) {
return null != o && 'object' == typeof o ? o : {};
};
/**
* Recursively makes an object safe for partial
* usage.
*
* @private
* @function
* @name makeSafeObject
* @param {Mixed} o
* @return {Mixed}
*/
function makeSafeObject(o) {
var out = String();
if ('function' == typeof o) {
return o;
}
if (null == o || 'object' != typeof o) {
if ('string' == typeof o) {
try {
return JSON.stringify(JSON.parse(o));
} catch (e) {}
}
return JSON.stringify(o);
}
if ('object' == typeof o) {
for (var k in o) {
o[k] = makeSafeObject(o[k]);
}if (Array.isArray(o)) {
out += '[';
for (var k in o) {
out += o[k] + ', ';
}out += ']';
} else {
out += '{';
for (var k in o) {
out += k + ': ' + o[k] + ', ';
}out += '}';
}
}
return out;
}
/**
* Template class.
*
* @public
* @class Template
*/
var Template = (function () {
_createClass(Template, null, [{
key: 'createPartial',
/**
* Creates a function that accepts an optional
* object creating a variable scope for the
* template string. You may pass a string or
* function. If a function is passed it is
* called when the partial is created. All
* data is propagated to functions passed to
* this function.
*
* @public
* @static
* @method
* @name createPartial
* @param {String|Function}
* @return {Function} (data) => {String}
*/
value: function createPartial(string) {
var _this = this;
if ('string' == typeof string) string = string.replace(RegExp('`', 'g', '\\`'));
/**
* Partial template function that accepts
* an optional variable scope object.
*
* @public
* @function
* @param {Object} [data = {}]
* @return {String}
*/
return function (data, scope) {
data = ensureObject(data);
scope = scope || _this;
var wrap = string;
var header = Object.keys(data).filter(function (key) {
return false == _view.helpers.has(key);
}).map(function (key) {
var value = makeSafeObject(data[key]);
return key + ' = ' + value;
});
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = _view.helpers.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var kv = _step.value;
header.push(kv[0] + ' = ' + makeSafeObject(kv[1]));
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator['return']) {
_iterator['return']();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
header = header.length ? 'var ' + header.join(', ') + ';' : '';
// allow use of #{} inside of ES6 template strings
if ('string' == typeof string) string = string.replace(/\#\{/g, '${');
if ('function' != typeof wrap) wrap = new Function('data', '\'use strict\'; ' + header + ' return `' + string + '`');
var src = '\'use strict\'; return wrap.call(this, data);';
var fn = new Function('data', 'wrap', src);
return String(fn.call(scope, data, wrap) || '');
};
}
/**
* Template class constructor.
*
* @public
* @constructor
* @param {String|Function} source
*/
}]);
function Template(source) {
_classCallCheck(this, Template);
/**
* The template source.
*
* @public
* @type {Function|String}
* @name source
*/
this.source = null;
/**
* A partial function used to
* render a template.
*
* @public
* @method
* @name render
* @param {Object} [data = {}]
*/
this.render = null;
// intial definition
this.define(source);
}
/**
* Defines the template source.
*
* @public
* @method
* @name define
* @param {String|Function} source
*/
_createClass(Template, [{
key: 'define',
value: function define(source) {
this.source = source;
this.render = Template.createPartial(source);
return this;
}
/**
* Implements toString.
*
* @public
* @method
* @name toString
* @return {String}
*/
}, {
key: 'toString',
value: function toString() {
return String(this.source || '');
}
/**
* Implements valueOf.
*
* @public
* @method
* @name valueOf
* @return {Element}
*/
}, {
key: 'valueOf',
value: function valueOf() {
return this.source;
}
}]);
return Template;
})();
exports['default'] = Template;
module.exports = exports['default'];