Skip to content

Instantly share code, notes, and snippets.

@tornqvist
Last active August 1, 2018 13:51
Show Gist options
  • Save tornqvist/ff7e408ed2e13f1aad22f7ad05ac0972 to your computer and use it in GitHub Desktop.
Save tornqvist/ff7e408ed2e13f1aad22f7ad05ac0972 to your computer and use it in GitHub Desktop.
Hypercomponent – experimental module for writing JSX-like markup with Nanocomponent
var html = require('nanohtml')
var Hypercomponent = require('hypercomponent')
class Greeting extends Hypercomponent {
update (strings, ...args) {
return true
}
Foo (attrs, children) {
if (attrs.bold) children = html`<strong>${children}</strong>`
return html`<div>${children}</div>`
}
Bar (attrs, children) {
if (attrs.italic) return html`<em>${children}</em>`
return children
}
createElement (attrs, children) {
return html`<h1 ${attrs}>${children}</h1>`
}
}
var hello = new Greeting()
document.body.appendChild(hello.html`
<Foo bold=${true}>
Hello <Bar>World</Bar>!
</Foo>
`)
/* renders to DOM:
<h1>
<div>
<strong>Hello World!</strong>
</div>
</h1>
*/
hello.html({class: 'foo'})`
<Foo>
Hello <Bar italic=${true}>World</Bar>!
</Foo>
`
/* re-renders as:
<h1 class="hello">
<div>
Hello <em>World</em>!
</div>
</h1>
*/
var assert = require('assert')
var hyperx = require('hyperx')
var nanohtml = require('nanohtml')
var Component = require('nanocomponent')
module.exports = Hypercomponent
function Hypercomponent (name) {
Component.call(this, name)
var self = this
var createElement = this.createElement
var hx = hyperx(function createElement (tag, attrs, children) {
var keys = Object.keys(attrs)
for (var i = 0, len = keys.length; i < len; i++) {
if (!isNaN(+attrs[keys[i]])) attrs[keys[i]] = parseInt(attrs[keys[i]], 10)
if (attrs[keys[i]] === 'false') attrs[keys[i]] = false
if (attrs[keys[i]] === 'true') attrs[keys[i]] = true
}
if (tag in self) return self[tag](attrs, children)
if (self._hasWindow) return nanohtml.createElement(tag, attrs, children)
return nanohtml(['<' + tag + ' ', '>', '</' + tag + '>'], attrs, children)
})
this._rootNodeAlias = 'Root' + (new Date() % 9e6).toString(36)
this[this._rootNodeAlias] = function (attrs, children) {
attrs = this._rootNodeAttrs || attrs
return createElement.call(this, attrs, children)
}
this.createElement = function (strings) {
var args = []
for (var i = 1; i <= arguments.length; i++) args.push(arguments[i])
strings = strings.slice()
var length = strings.length - 1
strings[0] = '<' + this._rootNodeAlias + '>' + strings[0]
strings[length] = strings[length] + '</' + this._rootNodeAlias + '>'
return hx.apply(undefined, [strings].concat(args))
}
}
Hypercomponent.prototype = Object.create(Component.prototype)
Hypercomponent.prototype.constructor = Hypercomponent
Hypercomponent.prototype.html = function () {
var args = []
for (var i = 0; i < arguments.length; i++) args.push(arguments[i])
assert(typeof args[0] === 'object', 'HyperComponent.html: attrs should be type object')
if (!Array.isArray(args[0])) {
this._rootNodeAttrs = args[0]
return this.html.bind(this)
}
var value = this.render.apply(this, args)
delete this._rootNodeAttrs
return value
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment