aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkshay Nair <phenax5@gmail.com>2023-08-13 15:34:18 +0530
committerAkshay Nair <phenax5@gmail.com>2023-08-13 15:34:18 +0530
commitc327a1dfc40b834b31c3488020859223f3583b4c (patch)
treee0090a6a49914f528bc4c1f517a329c3c0ae879a
parent1f147a779114a641b4abe5e47ac0b05433ec02fb (diff)
downloadcss-everything-c327a1dfc40b834b31c3488020859223f3583b4c.tar.gz
css-everything-c327a1dfc40b834b31c3488020859223f3583b4c.zip
feat: adds add-children and remove-element actions
-rw-r--r--src/declarations.ts15
-rw-r--r--src/eval.ts11
-rw-r--r--src/index.ts93
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)
}
}