From 3f838821e41adce691dc04fb1d38921178d33209 Mon Sep 17 00:00:00 2001 From: DarkWiiPlayer Date: Mon, 22 Jan 2024 10:35:20 +0100 Subject: [PATCH] Add support for child generators as skooma args Function arguments to skooma generators are now only treated as initialisers if they take at least one named argument. Otherwise they are called and their return value is evaluated as their replacement. The process is recursive and can happen repeatedly for functions that themselves return functions. --- skooma.js | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/skooma.js b/skooma.js index 4edcfd7..8e4edd5 100644 --- a/skooma.js +++ b/skooma.js @@ -52,7 +52,7 @@ const getCustom = args => args.reduce( const isElement = object => HTMLElement.prototype.isPrototypeOf(object) -const isReactive = object => !(object instanceof HTMLElement) +export const isReactive = object => !(object instanceof HTMLElement) && (object instanceof EventTarget) && ("value" in object) @@ -63,6 +63,8 @@ const toChild = arg => { return arg } else if (isReactive(arg)) { return reactiveChild(arg) + } else { + return document.createComment("Placeholder for reactive content") } } @@ -98,7 +100,7 @@ const specialAttributes = { }, shadowRoot: { set: (element, value) => { - parseArgs((element.shadowRoot || element.attachShadow({mode: "open"})), null, value) + parseArgs((element.shadowRoot || element.attachShadow({mode: "open"})), value) } } } @@ -145,21 +147,25 @@ const setReactiveAttribute = (element, attribute, reactive, abortController) => } } -const parseArgs = (element, before, ...args) => { +const parseArgs = (element, ...args) => { if (element.content) element = element.content for (const arg of args) if (arg !== empty) { - const child = toChild(arg) - if (child) - element.insertBefore(child, before) - else if (arg === undefined || arg == null) - console.warn(`An argument of type ${typeof arg} has been ignored`, element) - else if (typeof arg == "function") - arg(element) - else if ("length" in arg) - parseArgs(element, before, ...arg) - else - for (const key in arg) - setAttribute(element, key, arg[key]) + if (arg instanceof Array) { + parseArgs(element, ...arg) + } else { + const child = toChild(arg) + if (child) + element.append(child) + else if (arg === undefined || arg == null) + console.warn(`An argument of type ${typeof arg} has been ignored`, element) + else if (typeof arg == "function" && arg.length == 0) + parseArgs(element, arg()) + else if (typeof arg == "function") + arg(element) + else + for (const key in arg) + setAttribute(element, key, arg[key]) + } } } @@ -173,7 +179,7 @@ const node = (name, args, options) => { element = document.createElementNS(options.xmlns, name, opts) else element = document.createElement(name, opts) - parseArgs(element, null, args) + parseArgs(element, args) return element }