NEWS: Welcome to my new homepage! <3

Renamed project - figure - Unnamed repository; edit this file 'description' to name the repository.

figure

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit b674b08e305c7fb1c9163d7c2aa0c16bcd3fc781
parent c2e0ed2e15e9bb827e5df4d6a99fa4da1b24888d
Author: typable <contact@typable.dev>
Date:   Thu,  3 Nov 2022 10:00:54 +0100

Renamed project

Diffstat:
MREADME.md | 6+++---
Mexamples/counter.html | 4++--
Mexamples/picker.html | 4++--
Alib.js | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsegment.js | 141-------------------------------------------------------------------------------
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 };