[!NOTE]
This is one of 188 standalone projects, maintained as part
of the @thi.ng/umbrella monorepo
and anti-framework.
🚀 Please help me to work full-time on these projects by sponsoring me on
GitHub. Thank you! ❤️
About
100+ type-checked HTML5 element functions for @thi.ng/hiccup related infrastructure.
The following type-checked factory functions are provided so far and in most
cases include specialized type definitions for element-specific attributes,
incl. enumerated attrib values (where applicable/useful) and 420+ CSS property
names (for use with the style
attrib). See type definitions in
api.ts
and defElement()
below for more details.
Supported elements
Block content
Source
blockquote
details
dialog
div
figcaption
figure
hr
iframe
para
pre
slot
summary
template
Forms / inputs
Source
button
checkbox
fieldset
form
inputColor
inputFile
inputNumber
inputPass
inputRange
inputReset
inputSearch
inputSubmit
inputText
label
legend
meter
optGroup
option
output
progress
radio
select
textArea
Head / metadata
Source
base
head
link
linkCSS
meta
metaReferrer
metaRefresh
metaRobots
metaUTF8
metaViewport
metaXUA
script
style
title
Inline
Source
abbr
anchor
br
cite
code
data
del
dfn
em
i
ins
kbd
mark
quote
small
span
strikethrough
strong
sub
sup
time
variable
wbr
Lists
Source
Media
Source
audio
canvas
img
object
picture
source
track
video
Sections
Source
address
article
aside
body
comment
footer
h1
h2
h3
h4
h5
h6
header
hgroup
html
main
nav
noscript
search
section
Tables
Source
caption
col
colgroup
table
tbody
td
tfoot
th
thead
tr
Compatibility
The hiccup syntax is (by design) merely a convention and specific
feature support and interpretation is down to the actual tooling used.
Whilst not a direct aspect or feature of this package, the type
definitions for element attributes defined here allow certain constructs
which are only supported by some hiccup consumers. OTOH not all of
the constructs are meaningful in the different usage contexts and for
most there're compatible alternative ways of expressing the same data.
The table below provides an overview of the current syntax feature
support by the relevant packages consuming hiccup:
Feature | Example and HTML equivalent/result | hiccup | hdom | rdom |
---|
Emmet style tags | ["div#id.foo", {}] | ✅ | ✅ | ✅ |
| <div id="id" class="foo"> | | | |
class attrib as object | ["a.bar.baz", { class: { foo: true, bar: false }}] | ✅ | ✅ | ✅ |
| <a class="baz foo"> | | | |
style attrib as object | ["div", { style: { color: "red" }}] | ✅ | ✅ | ✅ |
| <div style="color:red;"> | | | |
Attrib array values | ["img", { srcset: ["1.jpg", "2.jpg"] }] | ✅ | ❌ | ✅ |
| <img srcset="1.jpg, 2.jpg"> | | | |
Data attribs as object | ["a", { data: { foo: 42 }}] | ✅ | ❌ | ✅ |
| <a data-foo="42"> | | | |
Function attrib values (1) | ["a", { id: () => "epoch-" + Date.now() }] | ✅ | ✅ | ✅ |
| <a id="epoch-1593024083666"> | | | |
IDeref attrib values (2) | ["div", { id: { deref() { return "foo"; }}}] | ✅ | ❌ | ✅ |
| <div id="foo"> | | | |
All other features not explicitly mentioned are supported by all three
packages.
(1) Excluding event listener attribs, these are always function values
of course, but will NOT be evaluated to obtain final attrib value
(2) The
IDeref
interface is implemented by various data structures in the
thi.ng/umbrella eco system (most relevant:
@thi.ng/rstream,
@thi.ng/atom).
Status
STABLE - used in production
Search or submit any issues for this package
The current aim is not necessarily to have wrappers for each possible
HTML5 element, but certainly to support the most commonly used ones. PRs
welcome!
Support packages
Related packages
Installation
yarn add @thi.ng/hiccup-html
ESM import:
import * as html from "@thi.ng/hiccup-html";
Browser ESM import:
<script type="module" src="https://esm.run/@thi.ng/hiccup-html"></script>
JSDelivr documentation
Package sizes (brotli'd, pre-treeshake): ESM: 1.63 KB
Dependencies
Usage examples
Several projects in this repo's
/examples
directory are using this package:
Screenshot | Description | Live demo | Source |
---|
| Large ASCII font text generator using @thi.ng/rdom | Demo | Source |
| Interactive & reactive image blurhash generator | Demo | Source |
| Self-modifying, animated typographic grid with emergent complex patterns | Demo | Source |
| Probabilistic color theme generator | Demo | Source |
| CSP channel-based event handling, async transducers & reactive UI components | Demo | Source |
| Color palette generation via dominant color extraction from uploaded images | Demo | Source |
| Randomized space-filling, nested grid layout generator | Demo | Source |
| Browser REPL for a Lispy S-expression based mini language | Demo | Source |
| Mastodon API feed reader with support for different media types, fullscreen media modal, HTML rewriting | Demo | Source |
| Basic thi.ng/meta-css usage & testbed | Demo | Source |
| Parser grammar livecoding editor/playground & codegen | Demo | Source |
| Randomized 4-point 2D color gradient image generator | Demo | Source |
| Interactive pixel sorting tool using thi.ng/color & thi.ng/pixel | Demo | Source |
| RGB waveform image analysis | Demo | Source |
| Procedural stochastic text generation via custom DSL, parse grammar & AST transformation | Demo | Source |
| rdom drag & drop example | Demo | Source |
| Basic usage of the declarative rdom-forms generator | Demo | Source |
| rstream & transducer-based FSM for converting key event sequences into high-level commands | Demo | Source |
| rdom & hiccup-canvas interop test | Demo | Source |
| Basic thi.ng/router usage with thi.ng/rdom components | Demo | Source |
| Full umbrella repo doc string search w/ paginated results | Demo | Source |
| Defining & using basic Web Components (with shadow DOM) via @thi.ng/rdom & @thi.ng/meta-css | Demo | Source |
| Responsive image gallery with tag-based Jaccard similarity ranking | Demo | Source |
| Generative audio synth offline renderer and WAV file export | Demo | Source |
| Declarative component-based system with central rstream-based pubsub event bus | Demo | Source |
| Responsive & reactively computed stacked column layout | Demo | Source |
| SVG path parsing & dynamic resampling | Demo | Source |
| Multi-layer vectorization & dithering of bitmap images | Demo | Source |
| rdom & WebGL-based image channel editor | Demo | Source |
API
Generated API docs
import { div, label, option, select } from "@thi.ng/hiccup-html";
import { $compile } from "@thi.ng/rdom";
const choices = [
["#f00", "Red"],
["#ff0", "Yellow"],
["#0f0", "Green"],
["#0ff", "Cyan"],
["#00f", "Blue"],
["#f0f", "Magenta"],
];
$compile(
div(
null,
label({ for: "colors" }, "Fave color: "),
select(
{
id: "colors",
onchange: (e) => alert((<HTMLSelectElement>e.target).value),
},
option(null, "Please choose..."),
...choices.map((x) => option({ value: x[0] }, x[1]))
)
)
).mount(document.body);
defElement
All element functions are created via the higher-order function defElement
which produces the typed, variadic factories. defElement
takes an element name
and optional set of default attributes. It also uses generics to enforce types
for the element's attributes (default:
Attribs
and/or children/body (default: any
).
Define element with defaults:
import { defElement } from "@thi.ng/hiccup-html";
const el = defElement("tag")
Define with custom attribs & no children allowed:
import { Attribs, AttribVal, defElement } from "@thi.ng/hiccup-html";
interface MyAttribs extends Attribs {
class: AttribVal<string>;
width: AttribVal<number>;
height: AttribVal<number>;
}
const el = defElement<Partial<MyAttribs>, never>(
"tag",
{ width: 100, height: 100 }
);
const div = defElement<Partial<Pick<Attribs, "class" | "style">>>("div");
The Attribs
interface provides a common, fully typed base definition
of HTML attributes (incl. event listeners and enumerated attrib options)
and can be found in
api.ts.
The AttribVal
type wrapper is used to allow for reactive attribute
values (in
@thi.ng/rdom)
and IDeref
instances
when later providing attribute values to an element.
Element creation
The function returned by defElement
has the following
signatures:
(attribs?: Nullable<T>, ...body: B[]) => [string, Nullable<T>, ...B[]];
(emmet: string, attribs?: Nullable<T>, ...body: B[]) => [string, Nullable<T>, ...B[]];
The result of either form is a simple tuple, defining an HTML element in
@thi.ng/hiccup
syntax.
If the second call signature is used, the initial emmet
-style string
will be appended to the tag name and merely acts as syntax sugar for
providing an element ID and/or CSS classes.
import { defElement } from "@thi.ng/hiccup-html";
const el = defElement<any>("a");
Call | Result |
---|
el() | ["a", null] |
el(null) | ["a", null] |
el(null, "body") | ["a", null, "body"] |
el({ c: 2 }) | ["a", { c: 2 }] |
el({ c: 2 }, "body") | ["a", { c: 2 }, "body"] |
el("#id.foo") | ["a#id.foo", null] |
el("#id.foo", { c: 2 }) | ["a#id.foo", { c: 2 }] |
el("#id.foo", { c: 2 }, "body") | ["a#id.foo", { c: 2 }, "body"] |
el("#id.foo", null, "body") | ["a#id.foo", null, "body"] |
import { defElement } from "@thi.ng/hiccup-html";
const el = defElement<any>("a", { b: 1 });
Call | Result |
---|
el() | ["a", { b: 1 }] |
el(null) | ["a", { b: 1 }] |
el(null, "body") | ["a", { b: 1 }, "body"] |
el({ c: 2 }) | ["a", { b: 1, c: 2 }] |
el({ c: 2 }, "body") | ["a", { b: 1, c: 2 }, "body"] |
el("#id.foo") | ["a#id.foo", { b: 1 }] |
el("#id.foo", { c: 2 }) | ["a#id.foo", { b: 1, c: 2 }] |
el("#id.foo", { c: 2 }, "body") | ["a#id.foo", { b: 1, c: 2 }, "body"] |
el("#id.foo", null, "body") | ["a#id.foo", { b: 1 }, "body"] |
Authors
If this project contributes to an academic publication, please cite it as:
@misc{thing-hiccup-html,
title = "@thi.ng/hiccup-html",
author = "Karsten Schmidt",
note = "https://thi.ng/hiccup-html",
year = 2020
}
License
© 2020 - 2024 Karsten Schmidt // Apache License 2.0