commit 8c7dde575f551d83d5ef8c43870a0faa7c90783e Author: Simon Weidacher <17548832+sweidac@users.noreply.github.com> Date: Fri Dec 16 02:21:02 2022 +0100 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..167ab9f --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +yarn.lock \ No newline at end of file diff --git a/index.mjs b/index.mjs new file mode 100644 index 0000000..97fd7f6 --- /dev/null +++ b/index.mjs @@ -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 `
`; // 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; + } +} \ No newline at end of file diff --git a/jest.config.json b/jest.config.json new file mode 100644 index 0000000..69a1b7b --- /dev/null +++ b/jest.config.json @@ -0,0 +1,3 @@ +{ + "testEnvironment" : "jsdom" +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..78dda3e --- /dev/null +++ b/package.json @@ -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" + } +} diff --git a/peasy.test.js b/peasy.test.js new file mode 100644 index 0000000..45eb310 --- /dev/null +++ b/peasy.test.js @@ -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``; + + expect(div).toBeInstanceOf(HTMLElement); + expect(div.nodeName).toBe('DIV'); + + const span = html``; + + expect(span).toBeInstanceOf(HTMLElement); + expect(span.nodeName).toBe('SPAN'); +}); + +it('creates a deeper html structure', () => { + const view = html` +paragraph
+