diff options
| -rw-r--r-- | TODO.norg | 9 | ||||
| -rw-r--r-- | esbuild.js | 2 | ||||
| -rw-r--r-- | package.json | 1 | ||||
| -rw-r--r-- | src/eval.ts | 2 | ||||
| -rw-r--r-- | src/index.ts | 93 |
5 files changed, 59 insertions, 48 deletions
diff --git a/TODO.norg b/TODO.norg new file mode 100644 index 0000000..6469cb9 --- /dev/null +++ b/TODO.norg @@ -0,0 +1,9 @@ +* Tasks + - (x) Hydrate existing elements instead of re-creating + - ( ) `load-cssx` functions + - ( ) Use css units for `delay` function + - ( ) `get-variable` + - ( ) `update-variable` + - ( ) Evaluate `calc`? + - ( ) `list` & `tuple` data structures? + - ( ) Non div elements @@ -9,6 +9,6 @@ esbuild minify: true, splitting: false, format: 'iife', - target: ['es2015'] + target: ['es2015'], }) .catch(e => (console.error(e), process.exit(1))) diff --git a/package.json b/package.json index aa3d8fa..bcb7de9 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,6 @@ "scripts": { "build": "node esbuild.js", "serve": "serve -p 3000 .", - "watch": "yarn build", "test": "jest" }, "devDependencies": { diff --git a/src/eval.ts b/src/eval.ts index 0ab52c8..76eaa21 100644 --- a/src/eval.ts +++ b/src/eval.ts @@ -6,7 +6,7 @@ export type Dependencies = { removeClass(id: string, classes: string): Promise<void> delay(num: number): Promise<void> jsEval(js: string): Promise<any> - // requestGetCss(url: string): Promise<string> + // loadCssx(id: string, url: string): Promise<string> // getVarable(name: string, def?: string): Promise<string> // updateVariable(id: string, varName: string, value: string): Promise<void> // calculate ?? diff --git a/src/index.ts b/src/index.ts index f09d940..4987e65 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,90 +1,93 @@ -import { Dependencies, evalExpr } from "./eval"; -import { parse } from "./parser"; +import { Dependencies, evalExpr } from './eval' +import { parse } from './parser' -const UNSET_PROPERTY_VALUE = '<unset>'; +const UNSET_PROPERTY_VALUE = '<unset>' const EVENT_HANDLERS = { click: '--cssx-on-click', load: '--cssx-on-load', } const injectStyles = () => { - const STYLE_TAG_CLASS = 'cssx-style-root'; - if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return; + const STYLE_TAG_CLASS = 'cssx-style-root' + if (document.querySelector(`.${STYLE_TAG_CLASS}`)) return - const $style = document.createElement('style'); - $style.className = STYLE_TAG_CLASS; + const $style = document.createElement('style') + $style.className = STYLE_TAG_CLASS - const properties = [ - '--cssx-children', - ...Object.values(EVENT_HANDLERS), - ]; + const properties = ['--cssx-children', ...Object.values(EVENT_HANDLERS)] $style.textContent = `.cssx-layer { - ${properties.map(p => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')} - }`; + ${properties.map((p) => `${p}: ${UNSET_PROPERTY_VALUE};`).join(' ')} + }` - document.body.appendChild($style); + document.body.appendChild($style) } -const getPropertyValue = ($element: HTMLElement, prop: string) => { +const getPropertyValue = ($element: Element, prop: string) => { const value = `${getComputedStyle($element).getPropertyValue(prop)}`.trim() - return !value || value === UNSET_PROPERTY_VALUE ? '' : value; -}; + return !value || value === UNSET_PROPERTY_VALUE ? '' : value +} -const getChildrenIds = ($element: HTMLElement) => { +const getChildrenIds = ($element: Element) => { const value = getPropertyValue($element, '--cssx-children') return value.split(/(\s*,\s*)|\s+/g).filter(Boolean) } -const evalDeps = (_el: HTMLElement): Dependencies => ({ +const evalDeps = (_el: Element): Dependencies => ({ addClass: async (id, cls) => document.getElementById(id)?.classList.add(cls), - removeClass: async (id, cls) => document.getElementById(id)?.classList.remove(cls), - delay: delay => new Promise((res) => setTimeout(res, delay)), - jsEval: async js => (0, eval)(js), + removeClass: async (id, cls) => + document.getElementById(id)?.classList.remove(cls), + delay: (delay) => new Promise((res) => setTimeout(res, delay)), + jsEval: async (js) => (0, eval)(js), }) -const handleEvents = async ($element: HTMLElement) => { +const handleEvents = async ($element: Element) => { for (const [event, property] of Object.entries(EVENT_HANDLERS)) { - const handlerExpr = getPropertyValue($element, property); + const handlerExpr = getPropertyValue($element, property) if (handlerExpr) { - ($element as any)[`on${event}`] = async () => { + ;($element as any)[`on${event}`] = async () => { console.log(`Triggered event: ${event}`) const exprs = parse(handlerExpr) for (const expr of exprs) { await evalExpr(expr, evalDeps($element)) } - }; + } } } -}; +} -let iters = 0; -const manageElement = async ($element: HTMLElement) => { - if (iters++ > 100) return; // NOTE: Temporary. To prevent infinite rec +let nodeCount = 0 +const manageElement = async ($element: Element) => { + if (nodeCount++ > 100) return // NOTE: Temporary. To prevent infinite rec - await handleEvents($element); + await handleEvents($element) + const childrenIds = getChildrenIds($element) - const $childrenRoot = Object.assign(document.createElement('div'), { - className: 'cssx-layer', - }); - $element.appendChild($childrenRoot); + if (childrenIds.length > 0) { + const $childrenRoot = + $element.querySelector(':scope > .cssx-layer') ?? + Object.assign(document.createElement('div'), { + className: 'cssx-layer', + }) + $element.appendChild($childrenRoot) - const childrenIds = getChildrenIds($element); - for (const id of childrenIds) { - const $child = Object.assign(document.createElement('div'), { id }); - $childrenRoot.appendChild($child); - await manageElement($child); + for (const id of childrenIds) { + const $child = + $childrenRoot.querySelector(`:scope > #${id}`) ?? + Object.assign(document.createElement('div'), { id }) + $childrenRoot.appendChild($child) + await manageElement($child) + } } } interface Options { - root?: HTMLElement; + root?: HTMLElement } const render = async ({ root = document.body }: Options = {}) => { - injectStyles(); - await manageElement(root); + injectStyles() + await manageElement(root) } -render(); - +render() |
