From f7ea49c88717c0c15835c9024c84a95678836a30 Mon Sep 17 00:00:00 2001 From: Akshay Nair Date: Fri, 25 Aug 2023 11:38:01 +0530 Subject: refactor: refactors declarations --- TODO.norg | 3 +- examples/form/signup.css | 11 +++- examples/todo-list/style.css | 8 --- src/declarations.ts | 141 ++++++++++++++++++------------------------- src/index.ts | 13 ++-- 5 files changed, 77 insertions(+), 99 deletions(-) diff --git a/TODO.norg b/TODO.norg index 348b06f..588994e 100644 --- a/TODO.norg +++ b/TODO.norg @@ -8,13 +8,14 @@ - (x) Scoped catch on try - (x) `do` expression - (x) `let` expression + - ( ) `h` declarations - ( ) `has-class` - ( ) `add-class` & `remove-class` should use self if id is not specified? - ( ) Update `--cssx-text` on update * Later - ( ) keyboard events - - ( ) Code cleanup + - ( ) Tail recursion optimization - ( ) Additional events - ( ) Improve parser error messages - ( ) Improve eval error messages diff --git a/examples/form/signup.css b/examples/form/signup.css index 2335334..5dfb8f6 100644 --- a/examples/form/signup.css +++ b/examples/form/signup.css @@ -39,7 +39,16 @@ remove-class(form, 'submitting') ; - --cssx-children: input#input-email input#input-password #actions #message; + --cssx-children: + input#input-email + input#input-password + #actions + h(#message[data-attr="wiow"], map(--wow: "wow"), + div#wow + div#yay + h(div#yay, map(--wow: "wow")) + ) + ; } #form.submitted #message::after { display: block; diff --git a/examples/todo-list/style.css b/examples/todo-list/style.css index cda7003..66ec5f0 100644 --- a/examples/todo-list/style.css +++ b/examples/todo-list/style.css @@ -18,14 +18,6 @@ body * { box-sizing: border-box; } border-radius: 5px; overflow: hidden; - /* --my-func: */ - /* js-eval(get-var(--js)) */ - /* delay(1s) */ - /* call(--my-func, map(--js: get-var(--js))) */ - /* ; */ - /**/ - /* --cssx-on-mount: call(--my-func, map(--js: "console.log(`yay`)")); */ - --cssx-children: form#task-input-form #task-list; } diff --git a/src/declarations.ts b/src/declarations.ts index c0966fa..a82f42f 100644 --- a/src/declarations.ts +++ b/src/declarations.ts @@ -1,37 +1,14 @@ -import { EvalActions, evalExprAsString } from './eval' +import { EvalActions, EvalValue, evalExpr } from './eval' import { Expr, Selector, SelectorComp, parseDeclarations } from './parser' import { match, matchString } from './utils/adt' export interface Declaration { selector: Selector - properties: Map + properties: Map + children: Array isInstance: boolean } -export interface DeclarationEval { - selector: Selector - properties: Array -} - -export const evaluateDeclaration = async ( - { selector, properties }: Declaration, - actions: EvalActions, -): Promise => { - if (properties.size === 0) return { selector, properties: [] } - - const props = await Promise.all( - [...properties.entries()].map(async ([key, expr]) => { - // Ignore errors? - const result = await evalExprAsString(expr, actions).catch((e: any) => - console.warn(e), - ) - return [key, result ?? ''] as const - }), - ) - - return { selector, properties: props } -} - const instanceCountMap = new Map() const getUniqueInstanceId = (id: string) => { const instanceCount = instanceCountMap.get(id) ?? 0 @@ -39,78 +16,76 @@ const getUniqueInstanceId = (id: string) => { return `${id}--index-${instanceCount}` } -export const toDeclaration = (expr: Expr): Declaration | undefined => { - let selector: Selector | undefined - const properties: Map = new Map() - let isInstance = false +export const toDeclaration = + (actions: EvalActions) => + async (expr: Expr): Promise => { + let selector: Selector | undefined + const properties: Map = new Map() + const children: Array = [] + let isInstance = false - match(expr, { - Selector: sel => { - selector = sel - }, - Call: ({ name, args }) => { - matchString(name, { - instance: () => { - isInstance = true - const [sel, map] = args + await match(expr, { + Selector: async sel => { + selector = sel + }, + Call: async ({ name, args }) => { + return matchString(name, { + // h: () => { + // + // }, + instance: async () => { + isInstance = true + const [sel, map] = args - // Selector - match(sel, { - Selector: sel => { - selector = sel - }, - _: _ => {}, - }) + // Selector + match(sel, { + Selector: sel => { + selector = sel + }, + _: _ => {}, + }) - // TODO: Refactor with eval - match(map, { - Call: ({ name, args }) => { - if (name !== 'map') return - for (const arg of args) { - match(arg, { - Pair: ({ key, value }) => properties.set(key, value), - _: _ => {}, - }) - } - }, - }) - }, - _: () => { - throw new Error(`weird function in cssx-chi9ldren: ${name}`) - }, - }) - }, - _: () => {}, - }) + const props = await evalExpr(map, actions) + match(props, { + Map: props => { + for (const [key, value] of Object.entries(props)) { + properties.set(key, value) + } + }, + _: _ => {}, + }) + }, + _: async () => { + throw new Error(`weird function in cssx-chi9ldren: ${name}`) + }, + }) + }, + _: async () => {}, + }) - if (!selector) return undefined + if (!selector) return undefined - if (isInstance) { - const baseId = selector.id - selector.id = getUniqueInstanceId(selector.id) - selector.selectors.push(SelectorComp.Attr(['data-instance', baseId])) - } + if (isInstance) { + const baseId = selector.id + selector.id = getUniqueInstanceId(selector.id) + selector.selectors.push(SelectorComp.Attr(['data-instance', baseId])) + } - return { selector, properties, isInstance } -} + return { selector, properties, children, isInstance } + } export const expressionsToDeclrs = async ( exprs: Array, actions: EvalActions, -): Promise> => { - const declrs = await Promise.all( - exprs - .map(toDeclaration) - .filter(declr => !!declr) - .map(declr => declr && evaluateDeclaration(declr, actions)), - ) - return declrs.filter(declr => !!declr) as Array +): Promise> => { + const declrs = await Promise.all(exprs.map(toDeclaration(actions))) + return declrs.filter(declr => !!declr) as Array } export const extractDeclaration = async ( input: string, actions: EvalActions, -): Promise> => { +): Promise> => { const exprs = parseDeclarations(input) return expressionsToDeclrs(exprs, actions) } diff --git a/src/index.ts b/src/index.ts index e5803d2..69d1fea 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,8 +7,8 @@ import { } from './eval' import { extractDeclaration, - DeclarationEval, expressionsToDeclrs, + Declaration, } from './declarations' import { Expr, parse } from './parser' import { match, matchString } from './utils/adt' @@ -68,7 +68,7 @@ export const getPropertyValue = ($element: HTMLElement, prop: string) => { export const getDeclarations = ( $element: HTMLElement, actions: EvalActions, -): Promise> => { +): Promise> => { const value = getPropertyValue($element, PROPERTIES.CHILDREN) return extractDeclaration(value, actions) } @@ -248,7 +248,7 @@ export const handleEvents = async ( } const declarationToElement = ( - declaration: DeclarationEval, + declaration: Declaration, $parent?: HTMLElement, ): { node: HTMLElement; isNewElement: boolean } => { const { tag, id, selectors } = declaration.selector @@ -270,15 +270,16 @@ const declarationToElement = ( }) } - for (const [key, value] of declaration.properties) { - $child?.style.setProperty(key, JSON.stringify(value)) + for (const [key, evalValue] of declaration.properties) { + const value = evalValueToString(evalValue) + $child?.style.setProperty(key, JSON.stringify(value || '')) } return { node: $child, isNewElement } } const createLayer = async ( - declarations: Array, + declarations: Array, $parent: HTMLElement, ) => { const $childrenRoot = -- cgit v1.3.1