# idomizer

> An HTML template compiler providing an incremental-dom render factory.

Latest version **1.0.2** (published 2019-10-17) · MIT license · 0 weekly downloads

## Install

```sh
npm install idomizer
pnpm add idomizer
yarn add idomizer
bun add idomizer
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; no vulnerabilities; high quality score.

Warnings: low downloads; no esm support.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.0.2 |
| Published | 2019-10-17 |
| First published | 2015-09-30 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | CommonJS |
| Dependencies | 3 |
| Unpacked size | 734 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Thibault Morin |
| Maintainers | thibaultmorin |
| Keywords | template, incremental, dom, incremental-dom, virtual, virtual-dom, browserify, webpack, systemjs, jspm, loader, webpack-loader, module, plugin, babel-plugin, systemjs-plugin, transform, browserify-transform |

## Links

- npm: https://www.npmjs.com/package/idomizer
- Repository: https://github.com/tmorin/idomizer
- Homepage: https://tmorin.github.io/idomizer
- Issues: https://github.com/tmorin/idomizer/issues
- npm.io page: https://npm.io/package/idomizer

## Dependencies (3)

- [htmlparser2](https://npm.io/package/htmlparser2.md) ^4.0.0
- [loader-utils](https://npm.io/package/loader-utils.md) ^1.2.3
- [browserify-transform-tools](https://npm.io/package/browserify-transform-tools.md) ^1.5.0

## Alternatives

- [babylon](https://npm.io/package/babylon.md) — 5.1M weekly downloads
- [csscolorparser](https://npm.io/package/csscolorparser.md) — 3.7M weekly downloads
- [expr-eval-fork](https://npm.io/package/expr-eval-fork.md) — 1.5M weekly downloads
- [@leeoniya/ufuzzy](https://npm.io/package/@leeoniya/ufuzzy.md) — 247.7K weekly downloads
- [xml-parser](https://npm.io/package/xml-parser.md) — 78.4K weekly downloads

## Recent versions

- 1.0.2 (latest) — 2019-10-17
- 1.0.1 — 2018-11-22
- 1.0.0 — 2018-11-22
- 0.10.1 — 2017-10-15
- 0.9.3 — 2017-10-15
- 0.9.2 — 2017-03-18
- 0.9.1 — 2017-03-03
- 0.9.0 — 2017-03-03
- 0.8.0 — 2017-03-03
- 0.7.0 — 2017-02-22
- 0.6.3 — 2016-12-07
- 0.6.2 — 2016-10-10
- 0.6.1 — 2016-10-04
- 0.6.0 — 2016-09-29
- 0.5.3 — 2016-09-14
- … 10 more at https://npm.io/package/idomizer/versions

## README

# idomizer

[![pipeline status](https://gitlab.com/tmorin/idomizer/badges/master/pipeline.svg)](https://gitlab.com/tmorin/idomizer/commits/master)
[![Dependency Status](https://david-dm.org/tmorin/idomizer.svg)](https://david-dm.org/tmorin/idomizer)
[![devDependency Status](https://david-dm.org/tmorin/idomizer/dev-status.svg)](https://david-dm.org/tmorin/idomizer?type=dev)

`idomizer` is an HTML template compiler providing an [incremental-dom] render factory.
`idomizer` can be used at compile time (front end projects) or runtime time(back end projects).

Versions and compatibilities:

- idomizer <= 0.5 -> _incremental-dom_ 0.4 and below.
- idomizer >= 0.6 -> _incremental-dom_ 0.5 and above.
- idomizer >= 1.0.0 -> _incremental-dom_ 0.6 and above.

## Installation

```bash
$ npm install idomizer
```

```html
<script src="https://ajax.googleapis.com/ajax/libs/incrementaldom/0.6.0/incremental-dom-min.js"></script>
<script src="https://unpkg.com/idomizer/dist/idomizer.min.js"></script>
<script>
    var factory = idomizer.compile('<h1>Hello!</h1>');
    var render = factory(IncrementalDOM);
    IncrementalDOM.patch(document.body, render);
</script>
```

### Babel

A babel's plugin is available to compile an idomizer template into an [incremental-dom] render factory.

See the [babel's plugins](https://babeljs.io/docs/en/plugins#syntax-plugins) page to get more information about plugins in babel.

```javascript
{
    plugins: ['idomizer/lib/plugins/babel-idomizer.js']
}
```

Presently the plugin only support [ES6 Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) tagged with _idomizer_.

For instance,
```javascript
const template = idomizer`<h1 class="{{data.h1Class}}">Hello</h1>`;
```
will be compiled into:
```javascript
var template = function (_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('h1', null, null, 'class', data.h1Class);
    _text('Hello');
    _elementClose('h1');
  };
};
```

Be aware the template can not contain expressions like ``${anExpression}``.

### Webpack

A webpack's loader is available to compile an idomizer file into an [incremental-dom] render factory.

See [module.rules](https://webpack.js.org/configuration/module/#module-rules) to get more information about loaders in webpack.

```
module.loaders: [
    {test: /\.idomizer$/, loader: 'idomizer/lib/plugins/idomizer-loader'}
];
```

### Browserify

A browserify's transform module is available to compile an idomizer file into an [incremental-dom] render factory.

See [transforms](https://github.com/substack/browserify-handbook#transforms) to get more information about the transform system in browserify.

```shell
browserify -t idomizer/lib/plugins/idomizerify main.js > bundle.js
```

```javascript
const browserify = require('browserify');
const idomizerify = require('idomizer/lib/plugins/idomizerify');
const bundle = browserify();
bundle.transform({ extension: 'html' }, idomizerify);
```

## API

``idomizer.compile`` transforms an HTML template into a factory method.

```javascript
// idomizer.compile('<h1 class="main">Hello</h1>') will return:
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('h1', null, ['class', 'main'], null);
    _text('Hello');
    _elementClose('h1');
  };
}
```

The factory method requires the _incremental-dom_ library and an optional map of helpers.
The factory returns the _incremental-dom_'s render method.

## Syntax

### Static attributes

From
```javascript
idomizer.compile(`<h1 class="main">Hello</h1>`)(IncrementalDOM);
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('h1', null, ['class', 'main'], null);
    _text('Hello');
    _elementClose('h1');
  };
}
```

### Dynamic attributes

From
```javascript
idomizer.compile(`<h1 class="{{data.h1Class}}">Hello</h1>`)(IncrementalDOM)
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('h1', null, null, 'class', (data.h1Class));
    _text('Hello');
    _elementClose('h1');
  };
}
```

### Self closing elements

From
```javascript
idomizer.compile(`<input type="text" value="{{data.value}}">`)(IncrementalDOM)
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementVoid('input', null, ['type', 'text'], 'value', (data.value));
  };
}
```

### Dynamic text nodes

From
```javascript
idomizer.compile(`<strong><tpl-text value="data.value"/></strong>`)(IncrementalDOM)
// or
idomizer.compile(`<strong>{{ data.value }}</strong>`)(IncrementalDOM)
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('strong', null, null, null);
    _text(data.value);
    _elementClose('strong');
  };
}
```

### Condition with the tags _if_, _else-if_ and _else_

From
```javascript
idomizer.compile(`
    <tpl-if expression="data.yes">
        YES!
    <tpl-else-if expression="data.yes !== false" />
        MAY BE!
    <tpl-else/>
        NO!
    </tpl-if>
`)(IncrementalDOM);
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    if (data.yes) {
        _text('YES!');
    } else if (data.yes !== false) {
        _text('MAY BE!');
    } else {
        _text('NO!');
    }
  };
}
```

### Iteration with the tag _each_

From
```javascript
idomizer.compile(`
    <tpl-each items="data.items">
        <strong tpl-key="{{index}}">
            <tpl-text value="index"/>-<tpl-text value="item"/>
        </strong>
    </tpl-each>
`)(IncrementalDOM);
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    (data.items || []).forEach(function (item, index) {
        _elementOpen('strong', (index), null, null);
            _text(index);
            _text('-');
            _text(item);
        _elementClose('strong');
    });
  };
}
```

### Iteration with inline javascript

From
```javascript
idomizer.compile(`
    [[ data.items.forEach(function (item, i) { ]]
        <strong tpl-key="{{i}}">
            <tpl-text value="i"/>-<tpl-text value="item"/>
        </strong>
    [[ }); ]]
`)(IncrementalDOM);
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    data.items.forEach(function (item, i) {
        _elementOpen('strong', (i), null, null);
            _text(i);
            _text('-');
            _text(item);
        _elementClose('strong');
    });
  };
}
```

### Custom tags

From
```javascript
idomizer.compile(`<strong>strong text</strong><x-test></x-test><strong>strong text</strong>`, {
     tags: {
        'x-test': {
            onopentag(name, attrs, key, statics, varArgs, options) {
                return `t('${name} element');`;
            }
        }
    }
})(IncrementalDOM);
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('strong', null, null, null);
      _text('strong text');
    _elementClose('strong');
    _text('x-test element');
    _elementOpen('strong', null, null, null);
      _text('strong text');
    _elementClose('strong');
  };
}
```

### Custom helpers

From
```javascript
const subRender = compile(`helper content`)(IncrementalDOM);
idomizer.compile(`
    <strong>strong text</strong>
    <tpl-call name="subRender" />
    <strong>strong text</strong>
`)(IncrementalDOM, {subRender});
```
To
```javascript
function template(_i, _h) {
  var _elementOpen = _i.elementOpen,
      _elementClose = _i.elementClose,
      _elementVoid = _i.elementVoid,
      _text = _i.text,
      _skip = _i.skip;
  return function (_data_) {
    var helpers = _h || {},
        data = _data_ || {};
    _elementOpen('strong', null, null, null);
        _text('strong text');
    _elementClose('strong');
    helpers.subRender(data);
    _elementOpen('strong', null, null, null);
        _text('strong text');
    _elementClose('strong');
  };
}
```

### Custom elements

For [incremental-dom], custom elements are regular HTML elements.
So, if a custom element generates a sub-tree (i.e. a light DOM) outside of a ShadowDOM node,
it will be overridden during the execution of the function `patch()`.
To control this default behavior, [incremental-dom] provides the function `skip()` saying:
_don't touch the inner light DOM of the just opened node!_

By default idomizier detects the custom elements and force the call of the function `skip()` to protect their light DOM nodes.
Custom elements are detected according to the following rules:

- from the name, because of the `-` character
- from the attribute `ìs`

Obviously, this behavior can be deactivated:

- globally (for a whole HTML template)
    ```javascript
    const render = compile(`<x-element><p>will part of the light DOM</p></x-element>`, {skipCustomElements : false})
    ```
- locally (an HTML element), ``
    ```javascript
    const render = compile(`<x-element tpl-skip="deactivated"><p>will part of the light DOM</p></x-element>`)
    ```

[incremental-dom]: https://google.github.io/incremental-dom

---
_Source: https://npm.io/package/idomizer · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
