Skip to content

Instantly share code, notes, and snippets.

@bitinn
Last active August 29, 2015 14:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bitinn/ca83c32f041f89e4e5ad to your computer and use it in GitHub Desktop.
Save bitinn/ca83c32f041f89e4e5ad to your computer and use it in GitHub Desktop.
vdom-compat (make virtual-dom hyperscript template work with deku)
/**
* vdom.js
*
* A virtual-dom compatibility layer
*/
var element = require('deku').element;
var classIdMatch = /([\.#]?[a-zA-Z0-9_:-]+)/;
var nonEmpty = function(input) {
return input !== '';
};
module.exports = vdom;
/**
* A simple api that abstracts vdom api
*
* @param Mixed el Tagname with class or id
* @param Mixed props Element properties
* @param Mixed children List of child nodes
* @return VNode
*/
function vdom(el, props, children) {
// build attributes
var new_props, new_children;
// vdom('div', 'abc');
if (getType(props) === 'String' && children === undefined) {
new_props = {};
new_children = [ props ];
// vdom('div', vnode);
} else if (getType(props) === 'Object' && props.tagName) {
new_props = {};
new_children = [ props ];
// vdom('div', { abc: 'abc' });
} else if (getType(props) === 'Object' && children === undefined) {
new_props = props;
new_children = [];
// vdom('div', ['abc', $('span', 'abc')]);
} else if (getType(props) === 'Array' && children === undefined) {
new_props = {};
new_children = [];
props.forEach(function(child) {
var node = createNode(child);
if (node) {
new_children.push(node);
}
});
// vdom('div', { abc: 'abc' }, ['abc', $('span', 'abc')]);
// vdom('div', { abc: 'abc' }, 'abc');
} else if (getType(props) === 'Object') {
new_props = props;
new_children = [];
if (getType(children) !== 'Array') {
new_children.push(children);
} else {
children.forEach(function(child) {
var node = createNode(child);
if (node) {
new_children.push(node);
}
});
}
}
// split el into tagName and class/id
var new_el;
el.split(classIdMatch).filter(nonEmpty).forEach(function(prop) {
var hint = prop.substr(0, 1);
if (hint === '#') {
new_props.id = prop.substr(1);
} else if (hint === '.') {
if (!new_props.class) {
new_props.class = {};
}
new_props.class[prop.substr(1)] = true;
} else {
new_el = prop;
}
});
return element(new_el, new_props, new_children);
};
/**
* Helper function to convert child node recursively
*
* @param Mixed child Any valid node value
* @return VNode
*/
function createNode(child) {
var output;
// string content
if (getType(child) === 'String') {
output = child;
// vnode
} else if (getType(child) === 'Object' && child.tagName) {
output = child;
// function
} else if (getType(child) === 'Function') {
output = vdom(child());
}
return output;
};
/**
* Helper
*
* @param Mixed input Anything
* @return String
*/
function getType(input) {
return Object.prototype.toString.call(input).slice(8, -1);
};
/**
* vdom.js
*
* A virtual-dom compatibility layer
*/
var h = require('virtual-dom/h');
var svg = require('virtual-dom/virtual-hyperscript/svg');
var svg_tags = JSON.stringify(require('svg-tags'));
module.exports = vdom;
/**
* A simple api that abstracts vdom api
*
* @param String el Tagname with class or id
* @param Object props Element properties
* @param Array children List of child nodes
* @return VNode
*/
function vdom(el, props, children) {
var vnode;
var hint = el.split(/(\.|#)+/);
if (svg_tags.indexOf(hint[0]) !== -1) {
vnode = svg;
} else {
vnode = h;
}
return vnode(el, props, children);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment