emel
Version:
Create DOM elements with Emmet
280 lines (231 loc) • 5.94 kB
Markdown
[](https://github.com/UziTech/emel/actions)
# emel
**em(met) el(ement)**
Create DOM elements with Emmet
## Installation
```sh
npm install emel
```
## Usage
You can use any [emmet abbreviation](https://docs.emmet.io/abbreviations/syntax/).
Options:
- [`doc`](#doc): `Document`
- [`returnSingleChild`](#returnsinglechild): `boolean`
- [`multiline`](#multiline): `boolean`
- [`placeholders`](#placeholders): `mixed`
```js
import emel from "emel";
// or const emel = require("emel"); // for cjs
// or const emel = global.emel; // for umd
const emmetString = "table>thead>tr>th{col1}+th{col2}^^tbody>(tr>td[colspan=2]{2 col width})+tr>td.col${1 col width}*2";
const options = {};
const element = emel(emmetString, options);
/**
* TABLE DOM element:
* <table>
* <thead>
* <tr>
* <th>col1</th>
* <th>col2</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td colspan="2">2 col width</td>
* </tr>
* <tr>
* <td class="col1">1 col width</td>
* <td class="col2">1 col width</td>
* </tr>
* </tbody>
* </table>
*/
```
### Setting default options
You can set the default options by creating a new instance of emel and pass the default options.
```js
import Emel from "emel";
// or const Emel = require("emel"); // for cjs
// or const Emel = global.emel; // for umd
const { emel } = new Emel({placeholders: [1, 2]});
const element = emel("div{?}+div{?}");
/**
* <div>1</div>
* <div>2</div>
*/
```
### Doc
Default to browser `document`.
For [Angular SSR](https://angular.io/guide/universal), use `injector.get(DOCUMENT)`
```ts
import { DOCUMENT } from '@angular/common';
emel(`div>p*3`, {
doc: injector.get(DOCUMENT)
});
```
### ReturnSingleChild
By default emel will always return the elements as children of a document fragment.
If you set the `returnSingleChild` option to `true` it will only wrap the elements in a document fragment if there are multiple top level elements.
### Multiline
By default space characters are not allowed outside of text nodes.
If you want to write readable strings with multiple lines you can use the `multiline` option to remove newline characters and surrounding spaces.
```js
emel(`
table>
thead>
tr>
th{col1}+
th{col2}^^
tbody>
tr>
td[colspan=2]{2 col width}^
tr>
td.col\${1 col width}*2
`, {
multiline: true
});
/**
* <table>
* <thead>
* <tr>
* <th>col1</th>
* <th>col2</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td colspan="2">2 col width</td>
* </tr>
* <tr>
* <td class="col1">1 col width</td>
* <td class="col2">1 col width</td>
* </tr>
* </tbody>
* </table>
*/
```
***Note***: The `multiline` option will remove newline characters and surrounding spaces from text nodes as well (which might not be expected).
```js
emel(`
div{
line 1
line 2
}
`, {
multiline: true
})
// <div>line 1line 2</div>
```
### Placeholders
You can use placeholders to insert dynamic content into any string value.
Replacements can be a string to replace all placeholders with the same value:
```js
emel("?#?.?[?=?]{?}", {
placeholders: "test"
});
// <test id="test" class="test" test="test">test</test>
```
Or an array to replace each placeholder with different value:
```js
emel("?#?.?[?=?]{?}", {
placeholders: ["tag", "id", "class", "attrName", "attrValue", "text"]
});
// <tag id="id" class="class" attrname="attrValue">text</tag>
```
***Note***: Placeholders are replaced after parsing so values do not need to be escaped. This comes with a few unintuitive cases.
- Text placeholders (`{?}`) are replaced after attributes:
```js
// INCORRECT:
emel("?{?}#?", {
placeholders: ["tag", "text", "id"]
});
// <tag id="text">id</tag>
// CORRECT:
emel("?{?}#?", {
placeholders: ["tag", "id", "text"]
});
// <tag id="id">text</tag>
```
- Placeholders on multiplied elements are not copied to every element:
```js
// INCORRECT:
emel("div{?}*2+span{?}", {
placeholders: ["div", "span"]
});
// <div>div</div><div>span</div><span>?</span>
// CORRECT:
emel("div{?}*2+span{?}", {
placeholders: ["div", "div", "span"]
});
// <div>div</div><div>div</div><span>span</span>
```
Placeholders can also be an object with keys that refer to any value:
```js
emel("this#is.replaced[with=placeholders]{placeholders}", {
placeholders: {
this: "tag",
is: "id",
replaced: "class",
with: "attr",
placeholders: ["value", "text"],
}
});
// <tag id="id" class="class" attr="value">text</tag>
```
Placeholder keys must match the entire value to be replaced:
```js
emel("#this.is[not='replaced with placholders']", {
placeholders: {
this: "id",
is: "class",
replaced: ["attr"],
with: ["value"],
placeholders: "text",
}
});
// <div id="id" class="class" not="replaced with placholders"></div>
```
Text placeholders may also be replaced by a [DOM Node](https://developer.mozilla.org/en-US/docs/Web/API/Node):
```js
const span = emel("span{text}")
emel("div{?}", {
placeholders: span
});
// <div><span>text</span></div>
```
Attribute name placeholders that equal `false`, `null`, or `undefined` will not be set.
```js
emel("div[attr=val]", {
placeholders: {
attr: undefined
}
});
// <div></div>
emel("div[attr=val]", {
placeholders: {
attr: null
}
});
// <div></div>
emel("div[attr.]", {
placeholders: {
attr: false
}
});
// <div></div>
```
Attribute name placeholders that equal `true` will not be changed.
```js
emel("input[type='checkbox' checked.]", {
placeholders: {
checked: false
}
});
// <input type="checked" />
emel("input[type='checkbox' checked.]", {
placeholders: {
checked: true
}
});
// <input type="checked" checked/>
```