diff options
| author | Akshay Nair <phenax5@gmail.com> | 2023-08-13 15:34:18 +0530 |
|---|---|---|
| committer | Akshay Nair <phenax5@gmail.com> | 2023-08-13 15:34:18 +0530 |
| commit | c327a1dfc40b834b31c3488020859223f3583b4c (patch) | |
| tree | e0090a6a49914f528bc4c1f517a329c3c0ae879a /src | |
| parent | 1f147a779114a641b4abe5e47ac0b05433ec02fb (diff) | |
| download | css-everything-c327a1dfc40b834b31c3488020859223f3583b4c.tar.gz css-everything-c327a1dfc40b834b31c3488020859223f3583b4c.zip | |
feat: adds add-children and remove-element actions
Diffstat (limited to 'src')
| -rw-r--r-- | src/declarations.ts | 15 | ||||
| -rw-r--r-- | src/eval.ts | 11 | ||||
| -rw-r--r-- | src/index.ts | 93 |
3 files changed, 86 insertions, 33 deletions
diff --git a/src/declarations.ts b/src/declarations.ts index 6c33fda..78c9801 100644 --- a/src/declarations.ts +++ b/src/declarations.ts @@ -87,11 +87,10 @@ export const toDeclaration = (expr: Expr): Declaration | undefined => { return { selector, properties } } -export const extractDeclaration = async ( - input: string, +export const expressionsToDeclrs = async ( + exprs: Array<Expr>, actions: EvalActions, -): Promise<Array<DeclarationEval>> => { - const exprs = parseDeclarations(input) +) => { const declrs = await Promise.all( exprs .map(toDeclaration) @@ -100,3 +99,11 @@ export const extractDeclaration = async ( ) return declrs.filter(declr => !!declr) as Array<DeclarationEval> } + +export const extractDeclaration = async ( + input: string, + actions: EvalActions, +): Promise<Array<DeclarationEval>> => { + const exprs = parseDeclarations(input) + return expressionsToDeclrs(exprs, actions) +} diff --git a/src/eval.ts b/src/eval.ts index 3a4e4f9..3d6734f 100644 --- a/src/eval.ts +++ b/src/eval.ts @@ -25,6 +25,8 @@ export interface EvalActions { url: string data: FormData | undefined }): Promise<void> + addChildren(id: string, children: Expr[]): Promise<void> + removeElement(id: string | undefined): Promise<void> // calculate ?? } @@ -126,6 +128,15 @@ const getFunctions = (name: string, args: Expr[], actions: EvalActions) => } }, + 'add-children': async () => { + const id = await evalExpr(args[0], actions) + if (id) actions.addChildren(id, args.slice(1)) + }, + 'remove-element': async () => + actions.removeElement( + (args[0] && (await evalExpr(args[0], actions))) ?? undefined, + ), + _: () => Promise.reject(new Error('not supposed to be here')), }) diff --git a/src/index.ts b/src/index.ts index 80e67d9..81e5b88 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,10 @@ import { EvalActions, evalExpr } from './eval' -import { extractDeclaration, DeclarationEval } from './declarations' +import { + extractDeclaration, + DeclarationEval, + Declaration, + expressionsToDeclrs, +} from './declarations' import { parse } from './parser' import { match } from './utils/adt' @@ -99,6 +104,18 @@ const getEvalActions = ($element: Element, event: any): EvalActions => ({ await fetch(url, { method, body: data }) // TODO: Handle response? }, + addChildren: async (id, children) => { + const $el = document.getElementById(id) + const declarations = await expressionsToDeclrs( + children, + getEvalActions($element, event), + ) + $el && createLayer(declarations, $el) + }, + removeElement: async id => { + const $el = id ? document.getElementById(id) : $element + $el?.parentNode?.removeChild($el) + }, }) export const handleEvents = async ( @@ -125,6 +142,51 @@ export const handleEvents = async ( } } +const declarationToElement = ( + declaration: DeclarationEval, + $parent?: Element, +) => { + const { tag, id, selectors } = declaration.selector + const tagName = tag || 'div' + + let $child = $parent?.querySelector(`:scope > #${id}`) + if (!$child) { + $child = Object.assign(document.createElement(tagName), { id }) + } + + // Add selectors + for (const selector of selectors) { + match(selector, { + ClassName: cls => + !$child?.classList.contains(cls) && $child?.classList.add(cls), + Attr: ([key, val]) => $child?.setAttribute(key, val), + }) + } + + return { node: $child, isNewElement: !$child } +} + +const createLayer = async ( + declarations: Array<DeclarationEval>, + $parent: Element, +) => { + const LAYER_CLASS = 'cssx-layer' + const $childrenRoot = + $parent?.querySelector(`:scope > .${LAYER_CLASS}`) ?? + Object.assign(document.createElement('div'), { className: LAYER_CLASS }) + + for (const declaration of declarations) { + const { node: $child, isNewElement } = declarationToElement( + declaration, + $childrenRoot, + ) + $childrenRoot.appendChild($child) + await manageElement($child, isNewElement) + } + + if (!$childrenRoot.parentNode) $parent.appendChild($childrenRoot) +} + export const manageElement = async ( $element: Element, isNewElement: boolean = false, @@ -142,34 +204,7 @@ export const manageElement = async ( getEvalActions($element, null), ) if (declarations.length > 0) { - const LAYER_CLASS = 'cssx-layer' - const $childrenRoot = - $element.querySelector(`:scope > .${LAYER_CLASS}`) ?? - Object.assign(document.createElement('div'), { className: LAYER_CLASS }) - $element.appendChild($childrenRoot) - - for (const declaration of declarations) { - const { tag, id, selectors } = declaration.selector - const tagName = tag || 'div' - - let $child = $childrenRoot.querySelector(`:scope > #${id}`) - const isNewElement = !$child - if (!$child) { - $child = Object.assign(document.createElement(tagName), { id }) - } - - // Add selectors - for (const selector of selectors) { - match(selector, { - ClassName: cls => - !$child?.classList.contains(cls) && $child?.classList.add(cls), - Attr: ([key, val]) => $child?.setAttribute(key, val), - }) - } - - $childrenRoot.appendChild($child) - await manageElement($child, isNewElement) - } + await createLayer(declarations, $element) } } |
