UNPKG

sinuous

Version:

🧬 Small, fast, reactive render engine

119 lines (101 loc) • 2.35 kB
const EMPTY_ARR = []; let actions; /** * Template tag. * @param {string} key * @return {Function} */ function t(key) { const tag = () => key; tag.$t = (type, fn, el, str) => { const create = type === 1 ? createInsert : createProperty; const action = create(fn, str); action._tag = tag; action._el = el; actions.push(action); }; return tag; } /** * Observable template tag. * @param {string} key * @return {Function} */ function o(key) { const observedTag = t(key); observedTag._observable = 1; return observedTag; } function createInsert(insert, current) { return (element, value) => { insert(element, value, null, current); }; } function createProperty(property, name) { return (element, value) => { property(name, value, element); }; } /** * Creates a template. * @param {Function} fn * @return {Function} */ function template(fn) { actions = []; const fragment = document.createDocumentFragment(); fragment.appendChild(fn()); actions.forEach(action => { action._paths = []; let el = action._el; let parent; while ((parent = el.parentNode)) { action._paths.unshift(EMPTY_ARR.indexOf.call(parent.childNodes, el)); el = parent; } }); const cloneActions = actions; actions = null; return function clone(props) { const el = fragment.cloneNode(true); el.firstChild.props = props; for (let i = 0; i < cloneActions.length; i++) { const action = cloneActions[i]; const paths = action._paths; let target = el; let j = 0; while (j < paths.length) { target = target.firstChild; const path = paths[j]; let k = 0; while (k < path) { target = target.nextSibling; k += 1; } j += 1; } const tag = action._tag; const key = tag(); const value = props[key]; if (value != null) { action(target, value); } if (tag._observable) { observeProperty(props, key, value, action, target); } } return el; }; } function observeProperty(props, key, value, action, target) { Object.defineProperty(props, key, { get() { return value; }, set(newValue) { value = newValue; action(target, newValue); } }); } export { o, t, template };