diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/eval.ts | 2 | ||||
| -rw-r--r-- | src/index.ts | 93 |
2 files changed, 49 insertions, 46 deletions
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() |
