commit b674b08e305c7fb1c9163d7c2aa0c16bcd3fc781
parent c2e0ed2e15e9bb827e5df4d6a99fa4da1b24888d
Author: typable <contact@typable.dev>
Date: Thu, 3 Nov 2022 10:00:54 +0100
Renamed project
Diffstat:
5 files changed, 148 insertions(+), 148 deletions(-)
diff --git a/README.md b/README.md
@@ -1,12 +1,12 @@
-# segment
+# figure
Reactive template literals for React
### Example
```javascript
-import {segment, html, css} from './segment.js';
+import {figure, html, css} from '...';
-segment({createElement});
+figure({createElement});
const Counter = () => {
const [count, setCount] = useState(0);
diff --git a/examples/counter.html b/examples/counter.html
@@ -4,7 +4,7 @@
import {useState, createElement} from 'https://cdn.skypack.dev/react';
import {render} from 'https://cdn.skypack.dev/react-dom';
- import {segment, html, css} from '../segment.js';
+ import {figure, html, css} from '../lib.js';
const Counter = () => {
const [count, setCount] = useState(0);
@@ -43,7 +43,7 @@
}
const app = document.querySelector('#app');
- segment({createElement});
+ figure({createElement});
render(createElement(Counter), app);
</script>
diff --git a/examples/picker.html b/examples/picker.html
@@ -4,7 +4,7 @@
import {useState, createElement} from 'https://cdn.skypack.dev/react';
import {render} from 'https://cdn.skypack.dev/react-dom';
- import {segment, html, css} from '../segment.js';
+ import {figure, html, css} from '../lib.js';
const Range = ({index, value, setValue}) => {
const style = css`
@@ -85,7 +85,7 @@
}
const app = document.querySelector('#app');
- segment({createElement});
+ figure({createElement});
render(createElement(Picker), app);
</script>
diff --git a/lib.js b/lib.js
@@ -0,0 +1,141 @@
+const parser = new DOMParser();
+let count = 1000;
+let create = null;
+
+const figure = ({createElement}) => {
+ create = createElement;
+}
+
+const html = (strings, ...props) => {
+ const [html, refs] = compose(strings, props);
+ let dom;
+ try {
+ dom = parser.parseFromString(html, 'text/html');
+ }
+ catch(error) {
+ console.error(error);
+ throw 'Invalid DOM structure!';
+ }
+ const node = dom.body.childNodes[0] ?? dom.head.childNodes[0];
+ const elements = render(node, refs);
+ if(elements.length === 0) {
+ throw 'No DOM element was returned!';
+ }
+ if(elements.length > 1) {
+ console.warn('Only one DOM element can be returned!');
+ }
+ return elements[0];
+}
+
+/**
+ * Joins the template literal strings together and replaces the properties with references.
+ * The properties are being mapped to there corresponding references and with the populated
+ * HTML string returned.
+ *
+ * @param {string[]} strings - The template literal strings
+ * @param {any[]} props - The template literal properties
+ * @return {any[]} The joined HTML string and the properties mapped to there references.
+ */
+const compose = (strings, props) => {
+ const refs = {};
+ let string = '';
+ for(let i = 0; i < strings.length; i++) {
+ string += strings[i];
+ if(props[i] !== undefined) {
+ const uid = `$tlx-${count++}`;
+ refs[uid] = props[i];
+ string += uid ?? '';
+ }
+ }
+ return [string.trim(), refs];
+}
+
+/**
+ * Injects the properties into the corresponding reference locations of the string.
+ *
+ * @param {string} string - The string containing references
+ * @param {any[]} refs - The properties mapped to there references
+ * @return {any[]} The string populate with the passed properties
+ */
+const feed = (string, refs) => {
+ const expr = /\$tlx-\d+/g;
+ let values = [];
+ let match = null;
+ let last = 0;
+ while((match = expr.exec(string)) !== null) {
+ const index = match.index;
+ const uid = match[0];
+ values.push(string.substring(last, index));
+ let value = refs[uid];
+ if(value instanceof Function) {
+ value = value();
+ }
+ values.push(value);
+ last = index + uid.length;
+ }
+ values.push(string.substring(last));
+ return values;
+}
+
+const render = (node, refs) => {
+ if(node.nodeType === Node.TEXT_NODE) {
+ return feed(node.textContent, refs);
+ }
+ if(node.nodeType === Node.COMMENT_NODE) {
+ return [];
+ }
+ const tag = node.tagName;
+ const attributes = {};
+ for(const attribute of node.attributes) {
+ const key = attribute.name;
+ const value = attribute.textContent;
+ let isDynamic = false;
+ for(const ref in refs) {
+ if(value === ref) {
+ let match = null;
+ if((match = /^@(\w+)$/.exec(key)) !== null) {
+ const event = match[1];
+ attributes[`on${event.substring(0, 1).toUpperCase()}${event.substring(1)}`] = refs[ref];
+ }
+ else {
+ attributes[key] = refs[ref];
+ }
+ isDynamic = true;
+ break;
+ }
+ }
+ if(!isDynamic) {
+ if(key === 'style') {
+ const styles = {};
+ for(const item of value.split(';')) {
+ if(item.trim().length === 0) {
+ break;
+ }
+ let [key, value] = item.split(':');
+ key = key.trim();
+ let match = null;
+ if((match = /-(\w)/.exec(key)) !== null) {
+ const char = match[1];
+ key = key.replace(`-${char}`, char.toUpperCase());
+ }
+ value = value.trim();
+ styles[key] = feed(value, refs).join('');
+ }
+ attributes[key] = styles;
+ }
+ else {
+ attributes[key] = feed(value, refs).join('');
+ }
+ }
+ }
+ const children = [];
+ (node.childNodes ?? []).forEach((child) => children.push(...render(child, refs)));
+ return [create(tag, attributes, ...children)];
+}
+
+import {defCss, defStyle} from './mods.js';
+
+const css = defCss({html, compose, feed});
+const style = defStyle({html, compose, feed});
+
+export { figure, html, css, style };
diff --git a/segment.js b/segment.js
@@ -1,141 +0,0 @@
-const parser = new DOMParser();
-let count = 1000;
-let create = null;
-
-const segment = ({createElement}) => {
- create = createElement;
-}
-
-const html = (strings, ...props) => {
- const [html, refs] = compose(strings, props);
- let dom;
- try {
- dom = parser.parseFromString(html, 'text/html');
- }
- catch(error) {
- console.error(error);
- throw 'Invalid DOM structure!';
- }
- const node = dom.body.childNodes[0] ?? dom.head.childNodes[0];
- const elements = render(node, refs);
- if(elements.length === 0) {
- throw 'No DOM element was returned!';
- }
- if(elements.length > 1) {
- console.warn('Only one DOM element can be returned!');
- }
- return elements[0];
-}
-
-/**
- * Joins the template literal strings together and replaces the properties with references.
- * The properties are being mapped to there corresponding references and with the populated
- * HTML string returned.
- *
- * @param {string[]} strings - The template literal strings
- * @param {any[]} props - The template literal properties
- * @return {any[]} The joined HTML string and the properties mapped to there references.
- */
-const compose = (strings, props) => {
- const refs = {};
- let string = '';
- for(let i = 0; i < strings.length; i++) {
- string += strings[i];
- if(props[i] !== undefined) {
- const uid = `$tlx-${count++}`;
- refs[uid] = props[i];
- string += uid ?? '';
- }
- }
- return [string.trim(), refs];
-}
-
-/**
- * Injects the properties into the corresponding reference locations of the string.
- *
- * @param {string} string - The string containing references
- * @param {any[]} refs - The properties mapped to there references
- * @return {any[]} The string populate with the passed properties
- */
-const feed = (string, refs) => {
- const expr = /\$tlx-\d+/g;
- let values = [];
- let match = null;
- let last = 0;
- while((match = expr.exec(string)) !== null) {
- const index = match.index;
- const uid = match[0];
- values.push(string.substring(last, index));
- let value = refs[uid];
- if(value instanceof Function) {
- value = value();
- }
- values.push(value);
- last = index + uid.length;
- }
- values.push(string.substring(last));
- return values;
-}
-
-const render = (node, refs) => {
- if(node.nodeType === Node.TEXT_NODE) {
- return feed(node.textContent, refs);
- }
- if(node.nodeType === Node.COMMENT_NODE) {
- return [];
- }
- const tag = node.tagName;
- const attributes = {};
- for(const attribute of node.attributes) {
- const key = attribute.name;
- const value = attribute.textContent;
- let isDynamic = false;
- for(const ref in refs) {
- if(value === ref) {
- let match = null;
- if((match = /^@(\w+)$/.exec(key)) !== null) {
- const event = match[1];
- attributes[`on${event.substring(0, 1).toUpperCase()}${event.substring(1)}`] = refs[ref];
- }
- else {
- attributes[key] = refs[ref];
- }
- isDynamic = true;
- break;
- }
- }
- if(!isDynamic) {
- if(key === 'style') {
- const styles = {};
- for(const item of value.split(';')) {
- if(item.trim().length === 0) {
- break;
- }
- let [key, value] = item.split(':');
- key = key.trim();
- let match = null;
- if((match = /-(\w)/.exec(key)) !== null) {
- const char = match[1];
- key = key.replace(`-${char}`, char.toUpperCase());
- }
- value = value.trim();
- styles[key] = feed(value, refs).join('');
- }
- attributes[key] = styles;
- }
- else {
- attributes[key] = feed(value, refs).join('');
- }
- }
- }
- const children = [];
- (node.childNodes ?? []).forEach((child) => children.push(...render(child, refs)));
- return [create(tag, attributes, ...children)];
-}
-
-import {defCss, defStyle} from './mods.js';
-
-const css = defCss({html, compose, feed});
-const style = defStyle({html, compose, feed});
-
-export { segment, html, css, style };