This commit is contained in:
Talia 2024-01-24 16:43:50 +01:00
parent 017cd9fbd2
commit 9983c57f23

View file

@ -5,6 +5,7 @@ const untilDeathDoThemPart = (referrer, reference) => {
weakReferences.get(referrer).add(reference) weakReferences.get(referrer).add(reference)
} }
// Like AbortController, but resets after each abort
class MultiAbortController { class MultiAbortController {
#controller = new AbortController() #controller = new AbortController()
get signal() { return this.#controller.signal } get signal() { return this.#controller.signal }
@ -13,17 +14,17 @@ class MultiAbortController {
export const empty = Symbol("Explicit empty argument for Skooma") export const empty = Symbol("Explicit empty argument for Skooma")
const keyToPropName = key => key.replace(/^[A-Z]/, a => "-"+a).replace(/[A-Z]/g, a => '-'+a.toLowerCase()) const snakeToCSS = key => key.replace(/^[A-Z]/, a => "-"+a).replace(/[A-Z]/g, a => '-'+a.toLowerCase())
const insertStyles = (rule, styles) => { const insertStyles = (rule, styles) => {
for (const [key, value] of Object.entries(styles)) for (const [key, value] of Object.entries(styles))
if (typeof value == "undefined") if (typeof value == "undefined")
rule.removeProperty(keyToPropName(key)) rule.removeProperty(snakeToCSS(key))
else else
rule.setProperty(keyToPropName(key), value.toString()) rule.setProperty(snakeToCSS(key), value.toString())
} }
const parseAttribute = (attribute) => { const processAttribute = (attribute) => {
if (typeof attribute == "string" || typeof attribute == "number") if (typeof attribute == "string" || typeof attribute == "number")
return attribute return attribute
else if (attribute && "join" in attribute) else if (attribute && "join" in attribute)
@ -83,13 +84,13 @@ const specialAttributes = {
dataset: { dataset: {
set(value) { set(value) {
for (const [attribute2, value2] of Object.entries(value)) { for (const [attribute2, value2] of Object.entries(value)) {
this.dataset[attribute2] = parseAttribute(value2) this.dataset[attribute2] = processAttribute(value2)
} }
} }
}, },
shadowRoot: { shadowRoot: {
set(value) { set(value) {
parseArgs((this.shadowRoot || this.attachShadow({mode: "open"})), value) processArgs((this.shadowRoot || this.attachShadow({mode: "open"})), value)
} }
} }
} }
@ -107,10 +108,11 @@ const setAttribute = (element, attribute, value, cleanupSignal) => {
else if (value === false) else if (value === false)
element.removeAttribute(attribute) element.removeAttribute(attribute)
else { else {
element.setAttribute(attribute, parseAttribute(value)) element.setAttribute(attribute, processAttribute(value))
} }
} }
// (Two-way) binding between an attribute and a state container
const setReactiveAttribute = (element, attribute, reactive) => { const setReactiveAttribute = (element, attribute, reactive) => {
untilDeathDoThemPart(element, reactive) untilDeathDoThemPart(element, reactive)
const multiAbort = new MultiAbortController() const multiAbort = new MultiAbortController()
@ -129,11 +131,11 @@ const setReactiveAttribute = (element, attribute, reactive) => {
} }
} }
const parseArgs = (element, ...args) => { const processArgs = (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) {
if (arg instanceof Array) { if (arg instanceof Array) {
parseArgs(element, ...arg) processArgs(element, ...arg)
} else { } else {
const child = toChild(arg) const child = toChild(arg)
if (child) if (child)
@ -141,7 +143,7 @@ const parseArgs = (element, ...args) => {
else if (arg === undefined || arg == null) else if (arg === undefined || arg == null)
console.warn(`An argument of type ${typeof arg} has been ignored`, element) console.warn(`An argument of type ${typeof arg} has been ignored`, element)
else if (typeof arg == "function" && arg.length == 0) else if (typeof arg == "function" && arg.length == 0)
parseArgs(element, arg()) processArgs(element, arg())
else if (typeof arg == "function") else if (typeof arg == "function")
arg(element) arg(element)
else else
@ -161,7 +163,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, args) processArgs(element, args)
return element return element
} }