mirror of
https://github.com/sweidac/peasy.git
synced 2025-07-27 19:31:55 +02:00
Initial commit.
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
yarn.lock
|
67
index.mjs
Normal file
67
index.mjs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
const REMOVE_ANY_INDENTATION_REGEX = /[\n\t]| {2,}/g;
|
||||||
|
|
||||||
|
const RENDERER = document.createElement('div');
|
||||||
|
|
||||||
|
const ID_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
||||||
|
ID_LENGTH = 10;
|
||||||
|
|
||||||
|
function _removeIndentation(strings) {
|
||||||
|
return strings.map(htmlPart => htmlPart.replace(REMOVE_ANY_INDENTATION_REGEX, ''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function _generateId() {
|
||||||
|
let id = "";
|
||||||
|
|
||||||
|
for (let i = 0; i < ID_LENGTH; i++) {
|
||||||
|
id += ID_ALPHABET.charAt(Math.floor(Math.random() * ID_ALPHABET.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _createInterpolationPlaceholders(values) {
|
||||||
|
const interpolations = {
|
||||||
|
nodes : []
|
||||||
|
};
|
||||||
|
|
||||||
|
interpolations.values = values.map(value => {
|
||||||
|
if (value instanceof Node) {
|
||||||
|
const id = _generateId();
|
||||||
|
|
||||||
|
interpolations.nodes.push({
|
||||||
|
id,
|
||||||
|
node : value
|
||||||
|
});
|
||||||
|
|
||||||
|
return `<div id="${id}"></div>`; // placeholder
|
||||||
|
} else {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return interpolations;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function html(strings, ...values){
|
||||||
|
const interpolations = _createInterpolationPlaceholders(values);
|
||||||
|
const htmlText = String.raw({ raw : _removeIndentation(strings.raw) }, ...interpolations.values);
|
||||||
|
|
||||||
|
RENDERER.innerHTML = htmlText;
|
||||||
|
|
||||||
|
interpolations.nodes.forEach(({ id, node }) => {
|
||||||
|
const placeholder = RENDERER.querySelector(`#${id}`);
|
||||||
|
|
||||||
|
placeholder.after(node);
|
||||||
|
placeholder.remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
const childCount = RENDERER.childElementCount;
|
||||||
|
|
||||||
|
if (childCount === 1) {
|
||||||
|
return RENDERER.firstChild;
|
||||||
|
} else if (RENDERER.childElementCount > 1) {
|
||||||
|
return RENDERER.children;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
3
jest.config.json
Normal file
3
jest.config.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"testEnvironment" : "jsdom"
|
||||||
|
}
|
17
package.json
Normal file
17
package.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "peasy",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "Make creating HTMLElements easy with the help of tag functions.",
|
||||||
|
"main": "index.js",
|
||||||
|
"author": "Simon Weidacher",
|
||||||
|
"license": "MIT",
|
||||||
|
"private": false,
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"test": "yarn node --experimental-vm-modules $(yarn bin jest)"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"jest": "^29.3.1",
|
||||||
|
"jest-environment-jsdom": "^29.3.1"
|
||||||
|
}
|
||||||
|
}
|
47
peasy.test.js
Normal file
47
peasy.test.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import html from './index.mjs';
|
||||||
|
|
||||||
|
it('it exports the tagging function', () => {
|
||||||
|
expect(html).toBeInstanceOf(Function);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates simple html elements', () => {
|
||||||
|
const div = html`<div></div>`;
|
||||||
|
|
||||||
|
expect(div).toBeInstanceOf(HTMLElement);
|
||||||
|
expect(div.nodeName).toBe('DIV');
|
||||||
|
|
||||||
|
const span = html`<span>`;
|
||||||
|
|
||||||
|
expect(span).toBeInstanceOf(HTMLElement);
|
||||||
|
expect(span.nodeName).toBe('SPAN');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates a deeper html structure', () => {
|
||||||
|
const view = html`
|
||||||
|
<div>
|
||||||
|
<h1>Title</h1>
|
||||||
|
<span>Text</span>
|
||||||
|
<span>Text2</span>
|
||||||
|
<p>paragraph</p>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
expect(view.childElementCount).toBe(4);
|
||||||
|
expect(view.childNodes.length).toBe(4); // make sure we have no textnodes from the indentation
|
||||||
|
expect(view.querySelectorAll('span').length).toBe(2);
|
||||||
|
expect(view.querySelector('p').textContent).toBe('paragraph');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with interpolations', () => {
|
||||||
|
const divWithText = html`<div>${'Text'}</div>`;
|
||||||
|
|
||||||
|
expect(divWithText.textContent).toBe('Text');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works with node interpolations', () => {
|
||||||
|
const innerView = html`<div class="myuser"><span>John</span><span>Doe</span></div>`,
|
||||||
|
outerView = html`<section>${innerView}</section>`;
|
||||||
|
|
||||||
|
expect(outerView).toBeInstanceOf(HTMLElement);
|
||||||
|
expect(outerView.querySelector('.myuser').textContent).toBe('JohnDoe');
|
||||||
|
});
|
Reference in New Issue
Block a user