• Stars
    star
    628
  • Rank 71,541 (Top 2 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 9 years ago
  • Updated over 4 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Terse syntax for hyperscript.

hyperscript-helpers

Terse syntax for hyperscript.

Less than 50 lines of code, taking your hyperscripting to the next level.

What is it

hyperscript-helpers elm-html inspired helpers for writing hyperscript or virtual-hyperscript.

They work with React.createElement, but there is also a feature-rich hyperscript library for React: react-hyperscript.

// instead of writing
h('div')

// write
div()

// instead of writing
h('section#main', mainContents)

// write
section('#main', mainContents)

hyperscript-helpers vs templates (including JSX)

With hyperscript-helpers:

  • It's nice to use functional utilities like lodash, because it's just functions
  • You get errors if you misspell a tag name, because they are function names
  • You have a consistent syntax at all times, because markup is just functions
  • Also, it's just functions

This is super helpful, especially when using hyperscript-helpers with Cycle.js!

See the supported TAG_NAMES here: src/index.js.

Example

Suppose we have a list of menu items of:

{ title: String, id: Number }

and a function that returns attributes given an id:

function attrs(id) {
  return { draggable: "true", "data-id": id };
}

How would we render these in plain hyperscript, JSX or with the helpers?

// plain hyperscript
h('ul#bestest-menu', items.map( item =>
  h('li#item-'+item.id, attrs(item.id), item.title))
);

// JSX
<ul id="bestest-menu">
  {items.map( item =>
    <li id={"item-"+item.id} {...attrs(item.id)}>{item.title}</li>
  )}
</ul>

// hyperscript-helpers
ul('#bestest-menu', items.map( item =>
  li('#item-'+item.id, attrs(item.id), item.title))
);

How to use

npm install hyperscript-helpers

The hyperscript-helpers are hyperscript-agnostic, which means there are no dependencies. Instead, you need to pass the implementation when you import the helpers.

Using ES6 πŸ’–

const h = require('hyperscript'); // or 'virtual-hyperscript'
const { div, span, h1 } =
  require('hyperscript-helpers')(h); // ← Notice the (h)

With React

// βœ… Preferred
const h = require('react-hyperscript');
const React = require('react');
const { div, span, h1 } =
  require('hyperscript-helpers')(h); // ← Notice the (h)


// Also works, but beware of the createElement API
const React = require('react');
const { div, span, h1 } =
  require('hyperscript-helpers')(React.createElement); // ← Notice the (React.createElement)

Using ES5

var h = require('hyperscript'); // or 'virtual-hyperscript'
var hh = require('hyperscript-helpers')(h);  // ← Notice the (h)
// to use the short syntax, you need to introduce them to the current scope
var div  = hh.div,
    span = hh.span,
    h1   = hh.h1;

Once that's done, you can go and use the terse syntax:

$ node
β–Έ const hh = require('hyperscript-helpers')(require('hyperscript'));
β—‚ undefined

β–Έ const { div, span, h1 } = hh;
β—‚ undefined

β–Έ span('😍').outerHTML
β—‚ '<span>😍</span>'

β–Έ h1({ 'data-id': 'headline-6.1.2' }, 'Structural Weaknesses').outerHTML
β—‚ '<h1 data-id="headline-6.1.2">Structural Weaknesses</h1>'

β–Έ div('#with-proper-id.wrapper', [ h1('Heading'), span('Spanner') ]).outerHTML
β—‚ '<div class="wrapper" id="with-proper-id"><h1>Heading</h1><span>Spanner</span></div>'

It's also natively supported to spell the helper function names with an uppercase first letter, for example to avoid conflicts with existing variables or reserved JavaScript keywords:

β–Έ const { Span, Var } = hh;
β—‚ undefined

β–Έ Span('😍').outerHTML
β—‚ '<span>😍</span>'

β–Έ Var('x').outerHTML
β—‚ '<var>x</var>'

Creating custom HTML tag names can be done with the createTag function:

β–Έ const someFn = hh.createTag('otherTag');
β—‚ undefined

β–Έ someFn('bla').outerHTML
β—‚ '<otherTag>bla</otherTag>'

API

Because hyperscript-helpers are hyperscript-agnostic there is no "exact" API. But, just to give you a direction of what should be possible:

tagName(selector)
tagName(attrs)
tagName(children)
tagName(attrs, children)
tagName(selector, children)
tagName(selector, attrs, children)

Where

  • tagName is a helper function named like the HTML element that it creates; hyperscript-helpers natively supports spelling the tag name with the first letter lowercase or uppercase.
  • selector is string, starting with "." or "#".
  • attrs is an object of attributes.
  • children is a hyperscript node, an array of hyperscript nodes, a string or an array of strings.

hyperscript-helpers is a collection of wrapper functions, so the syntax of your exact hyperscript library (like virtual-hyperscript) still applies.

For example, for multiple classes:

// ... with Matt-Esch/virtual-dom/.../virtual-hyperscript
button({className: "btn btn-default"}); // ← separated by space!
button(".btn.btn-default");             // ← separated by dot!

Other hyperscript libraries may have other syntax conventions.

Potential issues

Selector shortcut

The selector shortcut (div('.my-class')) may cause unexpected results in some cases. Our suggestion is:

Whenever you use tagName(<children>) syntax and <children> may be a string, starting with . (period) or # (number sign), wrap the argument in [].

// βœ… GOOD
filenames.map(filename => span([filename])); // <span>README.md</span><span>.gitignore</span>

// ❌ BAD
filenames.map(span); // <span>README.md</span><span class="gitignore"></span>

As most hyperscript is written by hand, we decided keep this convenient shortcut despite the issue.

Logic in class names

If you need to apply logic rules for class generation, we recommend using libraries like classnames for making proper {className: ...} argument.

Not recommended:

span(error ? ".error" : null);         // ← may be a trap, because:
span(error ? ".error" : null, {}, []); // ← this one is wrong

Tools

html-to-hyperscript.paqmind.com – webservice to convert HTML to hyperscript

Contributing

To get set up, simply clone the repository, navigate to the directory on your terminal and do the following:

# install dependencies
npm install

# build the project
npm start

# run tests
npm test

# commit your changes with commitizen
npm run commit
# or "git cz", if you have commitizen in your PATH

The source code can be found under the src directory, and the built file is under dist.

Tests are written with Mocha, using the awesome JSVerify library.


hyperscript-helpers is brought to you by @ohanhi.

License: MIT

More Repositories

1

elm-native-ui

[CLOSED] Experiment: mobile apps in Elm using React Native.
Elm
1,540
star
2

elm-shared-state

Example app on managing shared state in large Elm SPAs. (ex elm-taco)
Elm
302
star
3

elm-style-guide

Opinionated best practices for Elm code style, comments and contributions welcome!
75
star
4

elm-ement

The "Hello world" of Elm + Web Components.
JavaScript
50
star
5

keyboard-extra

Nice handling for keyboard inputs in Elm
Elm
49
star
6

elm-quicks

Tiny lessons gradually teaching Elm
Elm
44
star
7

elm-game-base

Example base for a game in Elm 0.19
Elm
31
star
8

elm-chronographify

Elm
25
star
9

trains

Elm SPA for live station schedules for Helsinki region commuter trains
Elm
25
star
10

keyboard

Nice handling for keyboard inputs in Elm
Elm
23
star
11

remotedata-http

A collection of helper functions for server communication using RemoteData
Elm
23
star
12

svg-css-backgrounds

Multicolor SVGs as CSS backgrounds
CSS
22
star
13

fish-elm-completions

Elm related completions for the friendly interactive shell
Shell
21
star
14

polymer-in-elm

Experimenting with using Polymer elements in Elm applications
JavaScript
16
star
15

autoexpand

Autoexpanding textarea in Elm
Elm
15
star
16

elm-web-data

Elm
11
star
17

bike-wars

Two-player local multiplayer game with light bikes
Elm
9
star
18

lorem

Placeholder text for your Elm apps
Elm
9
star
19

minimoka-gnome-shell

Minimalistic Gnome Shell Theme
CSS
7
star
20

decoder-examples

Some examples of decoding JSON in Elm
Elm
5
star
21

declarative-polymer

Experiments on making purely declarative Polymer apps
HTML
5
star
22

elm-native-ui-stopwatch

Elm
4
star
23

brunch-with-cycle

JavaScript
3
star
24

elmvaders

Simple Space Invaders clone in Elm
Elm
3
star
25

showroom-3d

Polymer element for easy display of your 3D models. Uses Three.js WebGL rendering.
JavaScript
3
star
26

chartist-elements

Polymer elements for Chartist
HTML
3
star
27

ohanhi.com

My website's source code
JavaScript
2
star
28

elm-html-drag-and-drop

Elm
2
star
29

chilicorn-friendly-time

JavaScript
2
star
30

elm-tasks-example

Simple example app utilizing Tasks
HTML
2
star
31

elm-child-parent

Super simple StartApp demo of child component using parent's action
HTML
2
star
32

remotedata-talk-examples

Elm
2
star
33

secret-message

Elm
2
star
34

find-princess

Elm
1
star
35

fp-in-haskell-course

Code related to the Functional Programming in Haskell MOOC
Haskell
1
star
36

advent-of-code-2017

Elm solutions for adventofcode.com/2017/
Elm
1
star
37

ohanhi.github.io

DEPRECATED, see `ohanhi/ohanhi.com` instead!
JavaScript
1
star