Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/marcodpt/h

Yet another hyperscript function
https://github.com/marcodpt/h

dom dom-manipulation es6-modules frontend html-tags hyperapp hyperscript microfrontends mithril server-side server-side-rendering tags

Last synced: 23 days ago
JSON representation

Yet another hyperscript function

Awesome Lists containing this project

README

        

# h
Yet another hyperscript function

## Examples
- [alert](https://marcodpt.github.io/h/)
- [chart](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fchart%2Fsamples.js)
- [graph](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fgraph%2Fsamples.js)
- [navbar](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fnavbar%2Fsamples.js)
- [SPA](https://marcodpt.github.io/h/?url=https%3A%2F%2Fcdn.jsdelivr.net%2Fgh%2Fmarcodpt%2Fspa%2Fsamples.js)

## Motivation
- Present hyperscript as an es6 module
- Allow to be used in server side in text mode
- Allow to be used in frontend in DOM mode
- Wrap any h function (
[react](https://github.com/facebook/react),
[hyperapp](https://github.com/jorgebucaran/hyperapp),
[mithril](https://github.com/MithrilJS/mithril.js/)...)
in the same consistent API
- Generate all HTML tags as functions
- Generate your own custom elements with great experience

## Definition
An `element` is a function with the following signature

### element(params, children) -> node
- object `params`: is the params that element recieve as attributes
- array `children`: is the children nodes of element
- return DOM `node`: the DOM node representing the element

## Usage
### DOM mode
```js
import {hDom as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'

const e = h('button', {
click: () => console.log('Hi!')
}, 'Click me!')

console.log(e.outerHTML)
//Click me!

e.click()
//Hi!
```

### DOM mode with HTML tags
```js
import {hDom as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'

const e = h(({button}) => {
button({
click: () => console.log('Hi!')
}, 'Click me!')
})

console.log(e.outerHTML)
//Click me!

e.click()
//Hi!
```

### Text mode
```js
import {hText as h} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'

console.log(h('button', {
type: 'button'
disabled: true
}, [
h('i', {
class: 'icon-check'
}),
h('span', 'Submit!')
]))
//
//
// Submit!
// button({
type: 'button'
disabled: true
}, [
i({
class: 'icon-check'
}),
span('Submit!')
])))
//
//
// Submit!
// html(({
button, i
}, resolvedAttrs, resolvedChildren) => {
//NO MATTER WHAT USER PUTS IN ATTRIBUTES OR CHILDREN

//resolvedAttrs is always an object
//with kebab case keys
//with string or functions values

//resolvedChildren is always a DOM array

return button({
class: "btn btn-"+resolvedAttrs.btn
}, [
resolvedAttrs.icon ? i({class: resolvedAttrs.icon}) : null
].concat(children))
}, attributes, children)

console.log(myButton({
btn: 'primary',
icon: 'fas fa-play'
}, ' Run!').outerHTML)
// Run!
```

### Syntax sugar
```js
import {hText as html} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'

//attributes are optional, text nodes are handled automatic
console.log(html(({div}) => div("Hello!")))
//

Hello!

//class might be an array
console.log(html(({div}) => div({
class: 'container mx-auto'
}, "Hello!")))
//

Hello!

console.log(html(({div}) => div({
class: [
'container',
'mx-auto'
]
}, "Hello!")))
//
Hello!

//style might be an object with case conversion
console.log(html(({div}) => div({
style: 'white-space: pre-wrap'
}, "Hello!")))
//

Hello!

console.log(html(({div}) => div({
style: {
'white-space': 'pre-wrap'
}
}, "Hello!")))
//
Hello!

console.log(html(({div}) => div({
style: {
whiteSpace: 'pre-wrap'
}
}, "Hello!")))
//
Hello!

//attributes have case conversion too
console.log(html(({div}) => div({
'data-bind': 'some data...'
}, "Hello!")))
//

Hello!

console.log(html(({div}) => div({
dataBind: 'some data...'
}, "Hello!")))
//
Hello!

```

### Wrapping hyperapp with this API
```js
import {h, text, app} from "https://unpkg.com/hyperapp"
import {wrapper} from 'https://cdn.jsdelivr.net/gh/marcodpt/h/index.js'

const html = wrapper(h, text)

const AddTodo = (state) => ({
...state,
value: "",
todos: state.todos.concat(state.value),
})

const NewValue = (state, event) => ({
...state,
value: event.target.value,
})

app({
init: { todos: [], value: "" },
view: ({ todos, value }) => html(({
main, h1, input, ul, li, button
}) => main([
h1("To do list"),
input({ type: "text", oninput: NewValue, value }),
ul(todos.map((todo) => li(todo))),
button({ onclick: AddTodo }, "New!"),
])),
node: document.getElementById("app"),
})
```

## Tests
- [wrapper](https://marcodpt.github.io/h/tests.html?url=.%2Ftests%2Fwrapper.js)
- [hDom](https://marcodpt.github.io/h/tests.html?url=.%2Ftests%2Fdom.js)
- [hText](https://marcodpt.github.io/h/tests.html?url=.%2Ftests%2Ftext.js)

## Contributing
Yes please! It is a very simple project, no guidelines, any contribution is
greatly appreciated!