npm package: @pjack/el
Description: Quickly create DOM trees from scripts.
Author: Paul Jack
Latest version: 2.0.5

# el

`el` is a tiny library to **programmatically create DOM trees** from scripts:

```TypeScript
import { "el" } from "@pjack/el"
    
document.body.add(
  el("h1", "el"),
  el("p").add(
    el("code", "el"),
    el("span", "is a tiny library to"),
    el("b", "programmatically create DOM trees"),
    el("span", "from scripts.")
  )
)
```

## The `el` Function

The `el` function takes a tag name and produces an `HTMLElement`
instance:

```TypeScript
const div = el("div")
```

The `el` function uses the 
[`xss-whitelist`](https://github.com/p-jack/xss-whitelist) library
to check tags for potential XSS vulnerabilities. An 
`XSSWhitelistError` will be thrown if the `tag` parameter is not
on the whitelist. (An error is thrown in this case because it's
caused by developer error, not user action; and presumably the
document wouldn't render properly if a particular tag were 
silently omitted.)

### Inner Text

You can pass an additional string to `el`. If you do, the element's `innerText` will be set to the string:

```TypeScript
const button = el("button", "Click Me")
```

### Attributes

You can also pass attributes to `el`, and they will be added to
the result:

```TypeScript
const emailInput = el("input", {type:"email"})
```

Any attributes are also checked by
[`xss-whitelist`](https://github.com/p-jack/xss-whitelist). If
an attribute is invalid, it is not added to the element, but
no error is thrown, but an error message will be printed to the
console. If you forget to sanitize some user input (and you
inevitably will), the tag can still be added to the document,
without ill effect:

```TypeScript
const unsanitizedInput = "javascript:alert(1)"
const safeLink = el("a", {href:unsanitizedInput})
// the safeLink can be safely added to the document, because
// the unsafe href attribute was never added to the tag
```

No error is thrown in this case because that would typically
break the app, enabling a denial of service attack.

Note that event handler attributes, such as `onclick`, are
_not_ in the whitelist. You can use the `on` method described
below to quickly add event handlers to an element. Attempting
to add an event handler as a text attribute _does_ raise an
error (because it's caused developer error, not by user action.)

Finally, you can pass both inner text and attributes. The
attributes must come last:

```TypeScript
const a = el("a", "Wikipedia", {href:"https://wikipedia.org"})
```

Again, all attributes are checked with `xss-whitelist` and unsafe
tags are omitted from the result.

## Fluent API

This library also monkey patches `HTMLElement` with fluent methods:

### `.add`

The `add` function appends child elements to a parent element, and
returns the parent:

```TypeScript
const ul = el("ul").add(
  el("li", "One"),
  el("li", "Two"),
  el("li", "Three"),
)
```

### `.attrs`

The `attrs` function sets or removes attributes from an element and
returns the element:

```TypeScript
const textInput = el("input").attrs({
  type:"text",
  id:"myId",
  disabled:"true"})
```

Again, the attributes are checked via
[`xss-whitelist`](https://github.com/p-jack/xss-whitelist).
And again, no error is thrown for unsafe attributes, but an
error message is printed to the console.

You can specify `undefined` for an attribute, in which case
it will be removed from the tag:

```TypeScript
textInput.attrs({disabled:undefined})
```

### `.css`

The `css` method sets style properties on the element and returns
the element:

```TypeScript
const blueCircle = el("div").css({
  background: "blue",
  borderRadius: "100px",
  width: "100px",
  height: "100px",
})
```

### `.inner`

The `inner` method sets the innerText of the element and returns
the element:

```TypeScript
const p = el("p").inner("Hello, world!")
```

### `.on`

The `on` function adds an event listener to an element and returns
the element:

```TypeScript
const submit = el("input", {type:"submit"}).on("click", (event) => {
  console.log("Clicked!", event)
})
```