decca
Version:
Render interfaces using pure functions and virtual DOM, kinda
59 lines (58 loc) • 1.96 kB
JavaScript
/**
* @module decca/string
*/
;
var id_1 = require('./id');
var assign = require('object-assign');
/**
* Renders an element into a string without using the DOM.
*
* @param {Element} el The Element to render
* @param {*=} context The context to be passed onto components
* @returns {string} the rendered HTML string
*/
function render(el, context) {
if (typeof el === 'string')
return el;
if (typeof el === 'number')
return '' + el;
if (Array.isArray(el))
return el.map(function (_el) { return render(_el, context); });
if (typeof el === 'undefined' || el === null)
return '';
var tag = el.tag, props = el.props, children = el.children;
if (typeof tag === 'string') {
var open_1 = '<' + tag + toProps(props) + '>';
var close_1 = '</' + tag + '>';
return open_1 +
(children || []).map(function (_el) { return render(_el, context); }).join('') +
close_1;
}
if (typeof tag === 'object') {
if (!tag.render)
throw new Error('component has no render()');
return render(tag.render({ props: assign({}, props, { children: children }), path: id_1["default"](), context: context }), context);
}
if (typeof tag === 'function') {
// Pure components
return render(tag({ props: assign({}, props, { children: children }), path: id_1["default"](), context: context }), context);
}
}
exports.render = render;
/*
* { class: 'foo', id: 'box' } => ' class="foo" id="box"'
*/
function toProps(props) {
if (!props)
return '';
var result = [];
Object.keys(props).forEach(function (attr) {
if (/^on[A-Za-z]/.test(attr))
return;
var val = props[attr];
if (typeof val === 'undefined' || val === null)
return;
result.push(attr + "=" + JSON.stringify(val));
});
return result.length ? ' ' + result.join(' ') : '';
}