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.
This commit is contained in:
Talia 2024-01-22 10:35:20 +01:00
parent 75fc1a7ce7
commit 3f838821e4

View file

@ -52,7 +52,7 @@ const getCustom = args => args.reduce(
const isElement = object => HTMLElement.prototype.isPrototypeOf(object) const isElement = object => HTMLElement.prototype.isPrototypeOf(object)
const isReactive = object => !(object instanceof HTMLElement) export const isReactive = object => !(object instanceof HTMLElement)
&& (object instanceof EventTarget) && (object instanceof EventTarget)
&& ("value" in object) && ("value" in object)
@ -63,6 +63,8 @@ const toChild = arg => {
return arg return arg
} else if (isReactive(arg)) { } else if (isReactive(arg)) {
return reactiveChild(arg) return reactiveChild(arg)
} else {
return document.createComment("Placeholder for reactive content")
} }
} }
@ -98,7 +100,7 @@ const specialAttributes = {
}, },
shadowRoot: { shadowRoot: {
set: (element, value) => { 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 if (element.content) element = element.content
for (const arg of args) if (arg !== empty) { for (const arg of args) if (arg !== empty) {
const child = toChild(arg) if (arg instanceof Array) {
if (child) parseArgs(element, ...arg)
element.insertBefore(child, before) } else {
else if (arg === undefined || arg == null) const child = toChild(arg)
console.warn(`An argument of type ${typeof arg} has been ignored`, element) if (child)
else if (typeof arg == "function") element.append(child)
arg(element) else if (arg === undefined || arg == null)
else if ("length" in arg) console.warn(`An argument of type ${typeof arg} has been ignored`, element)
parseArgs(element, before, ...arg) else if (typeof arg == "function" && arg.length == 0)
else parseArgs(element, arg())
for (const key in arg) else if (typeof arg == "function")
setAttribute(element, key, arg[key]) 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) element = document.createElementNS(options.xmlns, name, opts)
else else
element = document.createElement(name, opts) element = document.createElement(name, opts)
parseArgs(element, null, args) parseArgs(element, args)
return element return element
} }