somedom
Building blocks for the DOM.
Installation
Get it through npm
or yarn
, e.g.
$ npm install somedom --save-dev
Now you can import
the bits you need, see below.
E2E Tests
This guide has embbeded <script>
tags invoking test(...)
calls, no wonder yet.
Behind there's a function named appendChild
linked to document.currentScript
at execution time.
- Example
-
Those
output:appendChild
calls are removed from the code for readability. -
Also,
output:somedom
is bound to this function. -
Errors thrown are captured and shown as below:
output:
Reference API
Produce, patch and render vnodes, mount/unmount them from the DOM, mix and compose hooks, etc.
h()
h(name[, props], ...children)
-
This function will produce a
output:vnode
value.
pre()
pre(vnode[, svg[, cb]])
-
Use this function to debug vnodes and tag functions.
output:
bind()
bind(render[, ...extensions])
-
This function will help you to merge given middleware as a tag function.
It receives an initial render function and a list of extensions to be applied:
- Any factory
function
will be used as render callback, e.g.attributes(...)
,listeners(...)
, etc. - If you pass either an object or an array of objects, those will be registered as custom tags on the bound function.
- Any factory
-
Always return a valid HTMLElement or TextNode, otherwise return
output:cb(..., svg)
.
mount()
mount(target[, vnode[, cb]])
-
Use this function to attach elements on the DOM, it receives an string selector or HTMLElement as target, the given
vnode
will be the source.If no
target
is given it will usedocument.body
as fallback.Passing a custom tag (
output:cb
) function also works. -
Rendering from multiple nodes is possible through
output:DocumentFragment
, e.g.
patch()
patch(target, vnode, next[, svg[, cb]])
-
Update a previous
vnode
with anext
one, this function will fix the DOM for you. -
It will also sync hooks from any given tag function.
render()
render(vnode[, svg[, cb]])
-
This function accepts only scalars and
output:vnode
values. -
Given strings are rendered as
output:TextNode
elements. -
You can render single or nested vnodes, attributes are supported as well.
output: -
SVG support is handled for you. However, elements without an
output:svg
root requirestrue
as second argument. -
All functions are executed during
output:render
calls.
unmount()
unmount(target[, cb])
-
Removes the given node from the DOM. It also invoke registered hooks before complete removal.
If you give a function as second argument, the element is removed only when
done
is called.
Available Hooks
Listen for events on the DOM, setup element's lifecycle or enhance dynamic class
names, etc.
listeners()
listeners([globals])
-
This hook allows you to bind any event-handler from your elements' props.
Any given
output:globals
will be also used as default event handlers, if they returnfalse
the rest of handlers will be skipped. -
Event listeners also help you to manage the element's lifecycle:
output:oncreate
,onupdate
andondestroy
.
attributes()
attributes([helpers])
-
Through this hook
output:style
andclass
props can be fixed if they're objects. -
Also
output:update
,enter
andexit
props can be used for togglingclasses
during the elements' lifecycle. -
Otherwise, any given props matching
output:helpers
will be invoked as fallback for unhandled props. -
Non matched props that remain as objects will be converted to
output:data-*
attributes.
Server Side Rendering
To render entire vnode trees on the back-end use:
import { enable, disable, findOne, findAll, useWindow, parseMarkup, markupAdapter, renderToString, bindHelpers as $, } from 'somedom/ssr';
enable()
enable([env])
-
The `env` argument is used to retrieve the `jsdom` or `happy-dom` modules from the user, e.g.
// CommonJS const happydom = require('happy-dom'); const jsdom = require('jsdom'); enable({ jsdom, happydom }); // ESM import * as happydom from 'happy-dom'; import * as jsdom from 'jsdom'; enable({ jsdom, happydom });
You can set those conditionally: `happy-dom` will be tried first, then `jsdom`, otherwise the built-in environment will be used.
disable()
disable()
-
This will clear the globals set by the method above, use after your tests or SSR stuff.
useWindow()
useWindow(cb)
-
Use this hook to patch
document
andwindow
globally during the callback's lifecycle.useWindow(() => { var span = document.createElement('span'); var text = document.createTextNode('OSOM'); span.appendChild(text); console.log(span.outerHTML); // <span>OSOM</span> });
bindHelpers()
bindHelpers(node)
-
Use this to wrap an existing node, e.g.
document.body
— it'll return the given node withfindText()
andwithText()
methods attached.var $ = bindHelpers; // lets say you have an application var el = document.createElement('div'); var app = new Application(el, { value: 'Hello.', }); // wrap to enable lookup methods var $root = $(app.target); // returns the first node matching $root.withText('Click me.').dispatchEvent(new Event('click'));
-
The method above returns a single instance from calling
findText()
which just returns a list for matching nodes.var button = $root.findText(/Click me/)[0]; button.dispatchEvent(new Event('click'));
findOne()
findOne(css, nodes[, adapter])
-
Returns a node matching the css-selector, used by SSR's `querySelector` implementation.
findAll()
findAll(css, nodes[, adapter])
-
Returns all nodes matching the css-selector, used by SSR's `querySelectorAll` implementation.
markupAdapter
{ isTag, getAttributeValue, getName, getChildren, getParent, getText, removeSubsets, existsOne, getSiblings, hasAttrib, findOne, findAll }
-
Implements the required methods for `css-select` adapters, used by methods above. You can extend from here to make your own adapter.
parseMarkup()
parseMarkup(html[, options])
-
Returns an AST from parsed HTML, used by SSR's `innerHTML` implementation.
var test = '<b>OSOM</b>'; var ast = parseMarkup(test); console.log(ast); // [ { type: 'element', rawTagName: 'b', tagName: 'b', attributes: [], children: [ [Object] ] } ]
renderToString()
renderToString(vnode[, cb])
-
Returns a new function, when invoked it'll produce HTML as its output.
var test = ['h1', ['It works!']]; var dom = renderToString(test); var html = await dom(); console.log(html); // <h1>It works!</h1>
-
Any given callback will be used as tag function.
var $ = bind(render, attributes({ class: classes, })); var dom = renderToString(vnode, $); var html = await dom();