@oscarpalmer/abydon 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14,58 +14,168 @@ function getString(value2) {
14
14
  function isNullableOrWhitespace(value2) {
15
15
  return value2 == null || /^\s*$/.test(getString(value2));
16
16
  }
17
+ // node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/js/string/index.mjs
18
+ function getString2(value3) {
19
+ if (typeof value3 === "string") {
20
+ return value3;
21
+ }
22
+ if (typeof value3 !== "object" || value3 == null) {
23
+ return String(value3);
24
+ }
25
+ const valueOff = value3.valueOf?.() ?? value3;
26
+ const asString = valueOff?.toString?.() ?? String(valueOff);
27
+ return asString.startsWith("[object ") ? JSON.stringify(value3) : asString;
28
+ }
29
+ // node_modules/@oscarpalmer/toretto/node_modules/@oscarpalmer/atoms/dist/js/is.mjs
30
+ function isPlainObject2(value3) {
31
+ if (typeof value3 !== "object" || value3 === null) {
32
+ return false;
33
+ }
34
+ const prototype = Object.getPrototypeOf(value3);
35
+ return (prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null) && !(Symbol.toStringTag in value3) && !(Symbol.iterator in value3);
36
+ }
17
37
 
18
- // src/helpers/index.ts
19
- function isFragment(value2) {
20
- return typeof value2 === "object" && value2 != null && "$fragment" in value2 && value2.$fragment === true;
38
+ // node_modules/@oscarpalmer/toretto/dist/attribute.mjs
39
+ function isBadAttribute(attribute) {
40
+ return onPrefix.test(attribute.name) || sourcePrefix.test(attribute.name) && valuePrefix.test(attribute.value);
21
41
  }
22
- function isFragmentElement(value2) {
23
- return value2 instanceof HTMLElement || value2 instanceof SVGElement;
42
+ function isBooleanAttribute(name) {
43
+ return booleanAttributes.includes(name.toLowerCase());
24
44
  }
25
- function isFragmentNode(value2) {
26
- return value2 instanceof Comment || value2 instanceof Element || value2 instanceof Text;
45
+ function isEmptyNonBooleanAttribute(attribute) {
46
+ return !booleanAttributes.includes(attribute.name) && attribute.value.trim().length === 0;
27
47
  }
48
+ function isInvalidBooleanAttribute(attribute) {
49
+ if (!booleanAttributes.includes(attribute.name)) {
50
+ return true;
51
+ }
52
+ const normalised = attribute.value.toLowerCase().trim();
53
+ return !(normalised.length === 0 || normalised === attribute.name || attribute.name === "hidden" && normalised === "until-found");
54
+ }
55
+ function setAttribute(element, first, second) {
56
+ if (isPlainObject2(first) && typeof first?.name === "string") {
57
+ setAttributeValue(element, first.name, first.value);
58
+ } else if (typeof first === "string") {
59
+ setAttributeValue(element, first, second);
60
+ }
61
+ }
62
+ function setAttributeValue(element, name, value3) {
63
+ if (value3 == null) {
64
+ element.removeAttribute(name);
65
+ } else {
66
+ element.setAttribute(name, typeof value3 === "string" ? value3 : getString2(value3));
67
+ }
68
+ }
69
+ var booleanAttributes = Object.freeze([
70
+ "async",
71
+ "autofocus",
72
+ "autoplay",
73
+ "checked",
74
+ "controls",
75
+ "default",
76
+ "defer",
77
+ "disabled",
78
+ "formnovalidate",
79
+ "hidden",
80
+ "inert",
81
+ "ismap",
82
+ "itemscope",
83
+ "loop",
84
+ "multiple",
85
+ "muted",
86
+ "nomodule",
87
+ "novalidate",
88
+ "open",
89
+ "playsinline",
90
+ "readonly",
91
+ "required",
92
+ "reversed",
93
+ "selected"
94
+ ]);
95
+ var onPrefix = /^on/i;
96
+ var sourcePrefix = /^(href|src|xlink:href)$/i;
97
+ var valuePrefix = /(data:text\/html|javascript:)/i;
28
98
 
29
- // src/helpers/dom.ts
30
- function createNodes(value2) {
31
- if (isFragmentNode(value2)) {
32
- return [value2];
99
+ // node_modules/@oscarpalmer/toretto/dist/sanitise.mjs
100
+ function sanitise(value3, options) {
101
+ return sanitiseNodes(Array.isArray(value3) ? value3 : [value3], {
102
+ sanitiseBooleanAttributes: options?.sanitiseBooleanAttributes ?? true
103
+ });
104
+ }
105
+ function sanitiseAttributes(element, attributes, options) {
106
+ const { length } = attributes;
107
+ for (let index = 0;index < length; index += 1) {
108
+ const attribute2 = attributes[index];
109
+ if (isBadAttribute(attribute2) || isEmptyNonBooleanAttribute(attribute2)) {
110
+ element.removeAttribute(attribute2.name);
111
+ } else if (options.sanitiseBooleanAttributes && isInvalidBooleanAttribute(attribute2)) {
112
+ element.setAttribute(attribute2.name, "");
113
+ }
33
114
  }
34
- if (isFragment(value2)) {
35
- return value2.get();
115
+ }
116
+ function sanitiseNodes(nodes, options) {
117
+ const { length } = nodes;
118
+ for (let index = 0;index < length; index += 1) {
119
+ const node = nodes[index];
120
+ if (node instanceof Element) {
121
+ sanitiseAttributes(node, [...node.attributes], options);
122
+ }
123
+ sanitiseNodes([...node.childNodes], options);
36
124
  }
37
- return [new Text(getString(value2))];
125
+ return nodes;
38
126
  }
127
+
128
+ // node_modules/@oscarpalmer/toretto/dist/html.mjs
39
129
  function createTemplate(html) {
40
- const template2 = document.createElement("template");
41
- template2.innerHTML = html;
42
- const cloned = template2.content.cloneNode(true);
43
- const scripts = [
44
- ...cloned instanceof Element ? cloned.querySelectorAll("script") : []
45
- ];
130
+ const template3 = document.createElement("template");
131
+ template3.innerHTML = html;
132
+ templates[html] = template3;
133
+ return template3;
134
+ }
135
+ function getTemplate(value3) {
136
+ if (value3.trim().length === 0) {
137
+ return;
138
+ }
139
+ let template3;
140
+ if (/^[\w-]+$/.test(value3)) {
141
+ template3 = document.querySelector(`#${value3}`);
142
+ }
143
+ if (template3 instanceof HTMLTemplateElement) {
144
+ return template3;
145
+ }
146
+ return templates[value3] ?? createTemplate(value3);
147
+ }
148
+ function html(value3, sanitisation) {
149
+ const options = sanitisation == null || sanitisation === true ? {} : isPlainObject2(sanitisation) ? { ...sanitisation } : null;
150
+ const template3 = value3 instanceof HTMLTemplateElement ? value3 : typeof value3 === "string" ? getTemplate(value3) : null;
151
+ if (template3 == null) {
152
+ return [];
153
+ }
154
+ const cloned = template3.content.cloneNode(true);
155
+ const scripts = cloned.querySelectorAll("script");
46
156
  const { length } = scripts;
47
157
  for (let index = 0;index < length; index += 1) {
48
158
  scripts[index].remove();
49
159
  }
50
160
  cloned.normalize();
51
- return cloned;
161
+ return options != null ? sanitise([...cloned.childNodes], options) : [...cloned.childNodes];
52
162
  }
53
- function getNodes(node) {
54
- return /^documentfragment$/i.test(node.constructor.name) ? [...node.childNodes] : [node];
55
- }
56
- function replaceNodes(from, to) {
57
- const { length } = from;
58
- for (let index = 0;index < length; index += 1) {
59
- const node = from[index];
60
- if (index === 0) {
61
- node.replaceWith(...to);
62
- } else {
63
- node.remove();
64
- }
163
+ var templates = {};
164
+
165
+ // node_modules/@oscarpalmer/sentinel/node_modules/@oscarpalmer/atoms/dist/js/queue.mjs
166
+ function queue(callback) {
167
+ _atomic_queued.add(callback);
168
+ if (_atomic_queued.size > 0) {
169
+ queueMicrotask(() => {
170
+ const callbacks = [..._atomic_queued];
171
+ const { length } = callbacks;
172
+ _atomic_queued.clear();
173
+ for (let index = 0;index < length; index += 1) {
174
+ callbacks[index]();
175
+ }
176
+ });
65
177
  }
66
178
  }
67
-
68
- // node_modules/@oscarpalmer/atoms/dist/js/queue.mjs
69
179
  if (globalThis._atomic_queued == null) {
70
180
  const queued = new Set;
71
181
  Object.defineProperty(globalThis, "_atomic_queued", {
@@ -89,6 +199,22 @@ if (globalThis._sentinels == null) {
89
199
  function effect(callback) {
90
200
  return new Effect(callback);
91
201
  }
202
+ function watch(reactive, key) {
203
+ const effect2 = globalThis._sentinels[globalThis._sentinels.length - 1];
204
+ if (effect2 != null) {
205
+ if (key == null) {
206
+ reactive.callbacks.any.add(effect2);
207
+ } else {
208
+ if (!reactive.callbacks.keys.has(key)) {
209
+ reactive.callbacks.keys.add(key);
210
+ reactive.callbacks.values.set(key, new Set);
211
+ }
212
+ reactive.callbacks.values.get(key)?.add(effect2);
213
+ }
214
+ effect2.reactives.add(reactive);
215
+ }
216
+ }
217
+
92
218
  class Effect {
93
219
  $sentinel = "effect";
94
220
  state;
@@ -126,14 +252,104 @@ class Effect {
126
252
  }
127
253
 
128
254
  // node_modules/@oscarpalmer/sentinel/dist/helpers/is.mjs
129
- function isReactive(value2) {
130
- return isSentinel(value2, /^array|computed|signal|store$/i);
255
+ function isReactive(value3) {
256
+ return isSentinel(value3, /^array|computed|signal|store$/i);
257
+ }
258
+ function isSentinel(value3, expression) {
259
+ return expression.test(value3?.$sentinel ?? "");
260
+ }
261
+
262
+ // node_modules/@oscarpalmer/sentinel/node_modules/@oscarpalmer/atoms/dist/js/function.mjs
263
+ function noop() {
264
+ }
265
+
266
+ // node_modules/@oscarpalmer/sentinel/dist/helpers/subscription.mjs
267
+ function subscribe(state, subscriber, key) {
268
+ let set5;
269
+ if (key != null) {
270
+ if (state.callbacks.keys.has(key)) {
271
+ set5 = state.callbacks.values.get(key);
272
+ } else {
273
+ set5 = new Set;
274
+ state.callbacks.keys.add(key);
275
+ state.callbacks.values.set(key, set5);
276
+ }
277
+ } else {
278
+ set5 = state.callbacks.any;
279
+ }
280
+ if (set5 == null || set5.has(subscriber)) {
281
+ return noop;
282
+ }
283
+ set5.add(subscriber);
284
+ subscriber(state.value);
285
+ return () => {
286
+ unsubscribe(state, subscriber, key);
287
+ };
288
+ }
289
+ function unsubscribe(state, subscriber, key) {
290
+ if (key != null) {
291
+ const set5 = state.callbacks.values.get(key);
292
+ if (set5 != null) {
293
+ if (subscriber == null) {
294
+ set5.clear();
295
+ } else {
296
+ set5.delete(subscriber);
297
+ }
298
+ if (set5.size === 0) {
299
+ state.callbacks.keys.delete(key);
300
+ state.callbacks.values.delete(key);
301
+ }
302
+ }
303
+ } else if (subscriber != null) {
304
+ state.callbacks.any.delete(subscriber);
305
+ }
306
+ }
307
+
308
+ // node_modules/@oscarpalmer/sentinel/dist/helpers/event.mjs
309
+ function disable(state) {
310
+ if (state.active) {
311
+ state.active = false;
312
+ const effects = [...state.callbacks.any, ...state.callbacks.values.values()].flatMap((value3) => value3 instanceof Set ? [...value3.values()] : value3).filter((value3) => typeof value3 !== "function");
313
+ for (const fx of effects) {
314
+ if (typeof fx !== "function") {
315
+ fx.reactives.delete(state);
316
+ }
317
+ }
318
+ }
319
+ }
320
+ function emit(state, keys) {
321
+ if (state.active) {
322
+ const subscribers = [
323
+ ...state.callbacks.any,
324
+ ...[...state.callbacks.values.entries()].filter(([key]) => keys == null || keys.includes(key)).map(([, value3]) => value3)
325
+ ].flatMap((value3) => value3 instanceof Set ? [...value3.values()] : value3).map((value3) => typeof value3 === "function" ? value3 : value3.callback);
326
+ for (const subsriber of subscribers) {
327
+ if (typeof subsriber === "function") {
328
+ queue(() => {
329
+ subsriber(state.value);
330
+ });
331
+ }
332
+ }
333
+ }
131
334
  }
132
- function isSentinel(value2, expression) {
133
- return expression.test(value2?.$sentinel ?? "");
335
+ function enable(state) {
336
+ if (!state.active) {
337
+ state.active = true;
338
+ emit(state);
339
+ }
134
340
  }
135
341
 
136
342
  // node_modules/@oscarpalmer/sentinel/dist/helpers/value.mjs
343
+ function getValue3(reactive, key) {
344
+ watch(reactive, typeof key === "symbol" ? undefined : key);
345
+ return key == null ? reactive.value : Array.isArray(reactive.value) ? reactive.value.at(key) : reactive.value[key];
346
+ }
347
+ function setValue3(reactive, value3) {
348
+ if (!Object.is(reactive.value, value3)) {
349
+ reactive.value = value3;
350
+ emit(reactive);
351
+ }
352
+ }
137
353
  var arrayOperations = new Set([
138
354
  "copyWithin",
139
355
  "fill",
@@ -146,10 +362,96 @@ var arrayOperations = new Set([
146
362
  "unshift"
147
363
  ]);
148
364
 
365
+ // node_modules/@oscarpalmer/sentinel/dist/reactive/instance.mjs
366
+ class ReactiveInstance {
367
+ state;
368
+ constructor(type, value22) {
369
+ this.$sentinel = type;
370
+ this.state = {
371
+ value: value22,
372
+ active: true,
373
+ callbacks: {
374
+ any: new Set,
375
+ keys: new Set,
376
+ values: new Map
377
+ }
378
+ };
379
+ }
380
+ get() {
381
+ return getValue3(this.state);
382
+ }
383
+ peek() {
384
+ return this.state.value;
385
+ }
386
+ run() {
387
+ enable(this.state);
388
+ }
389
+ stop() {
390
+ disable(this.state);
391
+ }
392
+ toJSON() {
393
+ return getValue3(this.state);
394
+ }
395
+ toString() {
396
+ return String(getValue3(this.state));
397
+ }
398
+ }
399
+
400
+ // node_modules/@oscarpalmer/sentinel/dist/reactive/value.mjs
401
+ class ReactiveValue extends ReactiveInstance {
402
+ subscribe(subscriber) {
403
+ return subscribe(this.state, subscriber);
404
+ }
405
+ unsubscribe(subscriber) {
406
+ if (subscriber == null) {
407
+ this.state.callbacks.any.clear();
408
+ } else {
409
+ this.state.callbacks.any.delete(subscriber);
410
+ }
411
+ }
412
+ }
413
+
414
+ // node_modules/@oscarpalmer/sentinel/dist/reactive/computed.mjs
415
+ function computed(value32) {
416
+ return new Computed(value32);
417
+ }
418
+
419
+ class Computed extends ReactiveValue {
420
+ fx;
421
+ constructor(value32) {
422
+ super("computed", undefined);
423
+ this.fx = effect(() => setValue3(this.state, value32()));
424
+ }
425
+ run() {
426
+ this.fx.start();
427
+ }
428
+ stop() {
429
+ this.fx.stop();
430
+ }
431
+ }
149
432
  // node_modules/@oscarpalmer/sentinel/dist/reactive/index.mjs
150
433
  var primitives = new Set(["boolean", "number", "string"]);
151
434
 
435
+ // src/helpers/index.ts
436
+ function isFragment(value11) {
437
+ return typeof value11 === "object" && value11 != null && "$fragment" in value11 && value11.$fragment === true;
438
+ }
439
+ function isProperElement(value11) {
440
+ return value11 instanceof HTMLElement || value11 instanceof SVGElement;
441
+ }
442
+ function isProperNode(value11) {
443
+ return value11 instanceof CharacterData || value11 instanceof Element;
444
+ }
445
+
152
446
  // src/node/event.ts
447
+ function getController(element) {
448
+ let controller = controllers.get(element);
449
+ if (controller == null) {
450
+ controller = new AbortController;
451
+ controllers.set(element, controller);
452
+ }
453
+ return controller;
454
+ }
153
455
  function getOptions(options) {
154
456
  const parts = options.split(":");
155
457
  return {
@@ -158,145 +460,124 @@ function getOptions(options) {
158
460
  passive: !parts.includes("a") && !parts.includes("active")
159
461
  };
160
462
  }
161
- function mapEvent(element, name, value9) {
463
+ function mapEvent(element, name, value11) {
162
464
  element.removeAttribute(name);
163
- const [, type, options] = /^@(\w+)(?::([a-z:]+))?$/.exec(name) ?? [];
164
- if (typeof value9 === "function" && type != null) {
165
- element.addEventListener(type, value9, getOptions(options ?? ""));
465
+ const [, type, options] = eventNamePattern.exec(name) ?? [];
466
+ if (typeof value11 === "function" && type != null) {
467
+ element.addEventListener(type, value11, {
468
+ ...getOptions(options ?? ""),
469
+ signal: getController(element).signal
470
+ });
166
471
  }
167
472
  }
473
+ function removeEvents(element) {
474
+ if (controllers.has(element)) {
475
+ controllers.get(element)?.abort();
476
+ controllers.delete(element);
477
+ }
478
+ }
479
+ var controllers = new WeakMap;
480
+ var eventNamePattern = /^@([\w-]+)(?::([a-z:]+))?$/i;
168
481
 
169
- // node_modules/@oscarpalmer/atoms/dist/js/element/closest.mjs
170
- function calculateDistance(origin, target) {
171
- if (origin === target || origin.parentElement === target) {
172
- return 0;
482
+ // src/helpers/dom.ts
483
+ function createNodes(value11) {
484
+ if (isFragment(value11)) {
485
+ return value11.get();
173
486
  }
174
- const comparison = origin.compareDocumentPosition(target);
175
- const children = [...origin.parentElement?.children ?? []];
176
- switch (true) {
177
- case children.includes(target):
178
- return Math.abs(children.indexOf(origin) - children.indexOf(target));
179
- case !!(comparison & 2 || comparison & 8):
180
- return traverse(origin, target);
181
- case !!(comparison & 4 || comparison & 16):
182
- return traverse(target, origin);
183
- default:
184
- return -1;
487
+ if (isProperNode(value11)) {
488
+ return [value11];
185
489
  }
490
+ return [new Text(getString(value11))];
186
491
  }
187
- function closest(origin, selector, context) {
188
- if (origin.matches(selector)) {
189
- return [origin];
190
- }
191
- const elements = [...(context ?? document).querySelectorAll(selector)];
192
- const { length } = elements;
193
- if (length === 0) {
194
- return [];
492
+ function removeNodes(nodes) {
493
+ sanitiseNodes2(nodes);
494
+ const { length } = nodes;
495
+ for (let index = 0;index < length; index += 1) {
496
+ nodes[index].remove();
195
497
  }
196
- const distances = [];
197
- let minimum = null;
498
+ }
499
+ function replaceNodes(from, to) {
500
+ const { length } = from;
198
501
  for (let index = 0;index < length; index += 1) {
199
- const element = elements[index];
200
- const distance = calculateDistance(origin, element);
201
- if (distance < 0) {
202
- continue;
203
- }
204
- if (minimum == null || distance < minimum) {
205
- minimum = distance;
502
+ if (index === 0) {
503
+ from[index].replaceWith(...to);
504
+ } else {
505
+ from[index].remove();
206
506
  }
207
- distances.push({
208
- distance,
209
- element
210
- });
211
507
  }
212
- return minimum == null ? [] : distances.filter((found) => found.distance === minimum).map((found) => found.element);
213
508
  }
214
- function traverse(from, to) {
215
- const children = [...to.children];
216
- if (children.includes(from)) {
217
- return children.indexOf(from) + 1;
218
- }
219
- let current = from;
220
- let distance = 0;
221
- let parent = from.parentElement;
222
- while (parent != null) {
223
- if (parent === to) {
224
- return distance + 1;
225
- }
226
- const children2 = [...parent.children ?? []];
227
- if (children2.includes(to)) {
228
- return distance + Math.abs(children2.indexOf(current) - children2.indexOf(to));
509
+ function sanitiseNodes2(nodes) {
510
+ const { length } = nodes;
511
+ for (let index = 0;index < length; index += 1) {
512
+ const node = nodes[index];
513
+ if (isProperElement(node)) {
514
+ removeEvents(node);
229
515
  }
230
- const index = children2.findIndex((child) => child.contains(to));
231
- if (index > -1) {
232
- return distance + Math.abs(index - children2.indexOf(current)) + traverse(to, children2[index]);
516
+ if (node.hasChildNodes()) {
517
+ sanitiseNodes2([...node.childNodes]);
233
518
  }
234
- current = parent;
235
- distance += 1;
236
- parent = parent.parentElement;
237
519
  }
238
- return -1e6;
239
520
  }
521
+
240
522
  // src/node/attribute/value.ts
241
- function setAttribute(element2, name, value9) {
242
- element2.removeAttribute(name);
523
+ function setAttribute2(element, name, value11) {
524
+ element.removeAttribute(name);
243
525
  switch (true) {
244
- case classPattern.test(name):
245
- setClasses(element2, name, value9);
526
+ case classExpression.test(name):
527
+ setClasses(element, name, value11);
246
528
  return;
247
- case stylePattern.test(name):
248
- setStyle(element2, name, value9);
529
+ case stylePrefixExpression.test(name):
530
+ setStyle(element, name, value11);
249
531
  return;
250
532
  default:
251
- setValue3(element2, name, value9);
533
+ setValue5(element, name, value11);
252
534
  break;
253
535
  }
254
536
  }
255
- function setClasses(element2, name, value9) {
256
- function update(value10) {
257
- if (/^(|true)$/.test(getString(value10))) {
258
- element2.classList.add(...classes);
537
+ function setClasses(element, name, value11) {
538
+ function update(value12) {
539
+ if (value12 === true) {
540
+ element.classList.add(...classes);
259
541
  } else {
260
- element2.classList.remove(...classes);
542
+ element.classList.remove(...classes);
261
543
  }
262
544
  }
263
545
  const classes = name.slice(6).split(".");
264
- if (isReactive(value9)) {
546
+ if (isReactive(value11)) {
265
547
  effect(() => {
266
- update(value9.get());
548
+ update(value11.get());
267
549
  });
268
550
  } else {
269
- update(value9);
551
+ update(value11);
270
552
  }
271
553
  }
272
- function setStyle(element2, name, value9) {
273
- function update(value10) {
274
- if (value10 == null || value10 === false || value10 === true && unit == null) {
275
- element2.style.removeProperty(property);
554
+ function setStyle(element, name, value11) {
555
+ function update(value12) {
556
+ if (value12 == null || value12 === false || value12 === true && unit == null) {
557
+ element.style.removeProperty(property);
276
558
  } else {
277
- element2.style.setProperty(property, value10 === true ? unit : getString(value10));
559
+ element.style.setProperty(property, value12 === true ? unit : getString(value12));
278
560
  }
279
561
  }
280
- const [, property, unit] = /^\w+\.([a-z-]+)(?:\.(\w+))?$/i.exec(name) ?? [];
281
- if (property == null) {
282
- return;
283
- }
284
- if (isReactive(value9)) {
285
- effect(() => {
286
- update(value9.get());
287
- });
288
- } else {
289
- update(value9);
562
+ const [, property, unit] = styleFullExpression.exec(name) ?? [];
563
+ if (property != null) {
564
+ if (isReactive(value11)) {
565
+ effect(() => {
566
+ update(value11.get());
567
+ });
568
+ } else {
569
+ update(value11);
570
+ }
290
571
  }
291
572
  }
292
- function setValue3(element2, name, value9) {
293
- const callback = booleanAttributes.has(name) && name in element2 ? name === "selected" ? updateSelected(element2) : updateProperty : updateAttribute;
294
- if (isReactive(value9)) {
573
+ function setValue5(element, name, value11) {
574
+ const callback = isBooleanAttribute(name) && name in element ? name === "selected" ? updateSelected : updateProperty : setAttribute;
575
+ if (isReactive(value11)) {
295
576
  effect(() => {
296
- callback(element2, name, value9.get());
577
+ callback(element, name, value11.get());
297
578
  });
298
579
  } else {
299
- callback(element2, name, value9);
580
+ callback(element, name, value11);
300
581
  }
301
582
  }
302
583
  function triggerSelectChange(select) {
@@ -304,184 +585,192 @@ function triggerSelectChange(select) {
304
585
  select.dispatchEvent(new Event("change", { bubbles: true }));
305
586
  }
306
587
  }
307
- function updateAttribute(element2, name, value9) {
308
- if (value9 == null) {
309
- element2.removeAttribute(name);
310
- } else {
311
- element2.setAttribute(name, getString(value9));
312
- }
313
- }
314
- function updateProperty(element2, name, value9) {
315
- element2[name] = /^(|true)$/.test(getString(value9));
588
+ function updateProperty(element, name, value11) {
589
+ element[name] = value11 === true;
316
590
  }
317
- function updateSelected(element2) {
318
- const select = closest(element2, "select")[0];
591
+ function updateSelected(element, name, value11) {
592
+ const select = element.closest("select");
319
593
  const options = [...select?.options ?? []];
320
- return (element3, name, value9) => {
321
- if (select != null && options.includes(element3)) {
322
- triggerSelectChange(select);
323
- }
324
- updateProperty(element3, name, value9);
325
- };
594
+ if (select != null && options.includes(element)) {
595
+ triggerSelectChange(select);
596
+ }
597
+ updateProperty(element, name, value11);
326
598
  }
327
- var booleanAttributes = new Set([
328
- "checked",
329
- "disabled",
330
- "hidden",
331
- "inert",
332
- "multiple",
333
- "open",
334
- "readOnly",
335
- "required",
336
- "selected"
337
- ]);
338
- var classPattern = /^class\./;
339
- var stylePattern = /^style\./;
599
+ var classExpression = /^class\./;
600
+ var styleFullExpression = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
601
+ var stylePrefixExpression = /^style\./;
340
602
 
341
603
  // src/node/attribute/index.ts
342
- function getValue3(data2, original) {
604
+ function getValue5(data, original) {
343
605
  const matches = commentExpression.exec(original ?? "");
344
- return matches == null ? original : data2.values[+matches[1]];
345
- }
346
- function isBadAttribute(name, value10) {
347
- return /^on/i.test(name) || /^(href|src|xlink:href)$/i.test(name) && /(data:text\/html|javascript:)/i.test(value10);
606
+ return matches == null ? original : data.values[+matches[1]];
348
607
  }
349
- function mapAttributes(data2, element2) {
350
- const attributes = [...element2.attributes];
608
+ function mapAttributes(data, element) {
609
+ const attributes = [...element.attributes];
351
610
  const { length } = attributes;
352
611
  for (let index = 0;index < length; index += 1) {
353
- const { name, value: value10 } = attributes[index];
354
- if (isBadAttribute(name, value10)) {
355
- element2.removeAttribute(name);
356
- continue;
357
- }
358
- const actual = getValue3(data2, value10);
612
+ const { name, value: value12 } = attributes[index];
613
+ const actual = getValue5(data, value12);
359
614
  if (name.startsWith("@")) {
360
- mapEvent(element2, name, actual);
361
- } else if (name.includes(".") || isReactive(actual)) {
362
- mapValue(element2, name, actual);
615
+ mapEvent(element, name, actual);
616
+ } else if (name.includes(".") || typeof value12 === "function" || isReactive(actual)) {
617
+ mapValue(element, name, actual);
363
618
  }
364
619
  }
365
620
  }
366
- function mapValue(element2, name, value10) {
621
+ function mapValue(element, name, value12) {
367
622
  switch (true) {
368
- case typeof value10 === "function":
369
- mapValue(element2, name, value10());
370
- return;
623
+ case typeof value12 === "function":
624
+ setAttribute2(element, name, computed(value12));
625
+ break;
371
626
  default:
372
- setAttribute(element2, name, value10);
627
+ setAttribute2(element, name, value12);
373
628
  break;
374
629
  }
375
630
  }
376
631
  var commentExpression = /^<!--abydon\.(\d+)-->$/;
377
632
 
378
633
  // src/node/value.ts
379
- function setReactiveNode(comment, reactive3) {
634
+ function setNodes(nodes, comment, text, value12) {
635
+ const next = createNodes(value12);
636
+ if (nodes == null) {
637
+ if (comment.parentNode != null) {
638
+ replaceNodes([comment], next);
639
+ } else if (text.parentNode != null) {
640
+ replaceNodes([text], next);
641
+ }
642
+ } else {
643
+ replaceNodes(nodes, next);
644
+ }
645
+ return next;
646
+ }
647
+ function setReactiveNode(data, comment, reactive3) {
648
+ const item = data.items.find((item2) => item2.nodes.includes(comment));
380
649
  const text = new Text;
381
650
  let nodes;
382
651
  effect(() => {
383
- const value10 = reactive3.get();
384
- if (isFragment(value10) || isFragmentNode(value10)) {
385
- const next = createNodes(value10);
386
- if (nodes == null) {
387
- if (comment.parentNode != null) {
388
- replaceNodes([comment], next);
389
- } else if (text.parentNode != null) {
390
- replaceNodes([text], next);
391
- }
392
- } else {
393
- replaceNodes(nodes, next);
394
- }
395
- nodes = next;
396
- return;
652
+ const value12 = reactive3.get();
653
+ const valueIsFragment = isFragment(value12);
654
+ if (valueIsFragment || isProperNode(value12)) {
655
+ nodes = setNodes(nodes, comment, text, value12);
656
+ } else {
657
+ nodes = setText(nodes, comment, text, value12) ? [text] : undefined;
397
658
  }
398
- const isNullable = isNullableOrWhitespace(value10);
399
- text.textContent = getString(value10);
400
- if (nodes != null) {
401
- replaceNodes(nodes, [isNullable ? comment : text]);
402
- } else if (isNullable && comment.parentNode == null) {
403
- text.replaceWith(comment);
404
- } else if (!isNullable && text.parentNode == null) {
405
- comment.replaceWith(text);
659
+ if (item != null) {
660
+ item.fragment = valueIsFragment ? value12 : undefined;
661
+ item.nodes = [...nodes ?? [comment]];
406
662
  }
407
- nodes = undefined;
408
663
  });
409
664
  }
665
+ function setText(nodes, comment, text, value12) {
666
+ const isNullable = isNullableOrWhitespace(value12);
667
+ text.textContent = isNullable ? "" : getString(value12);
668
+ if (nodes != null) {
669
+ replaceNodes(nodes, [isNullable ? comment : text]);
670
+ return !isNullable;
671
+ }
672
+ if (isNullable && comment.parentNode == null) {
673
+ text.replaceWith(comment);
674
+ return false;
675
+ }
676
+ if (!isNullable && text.parentNode == null) {
677
+ comment.replaceWith(text);
678
+ return true;
679
+ }
680
+ return false;
681
+ }
410
682
 
411
683
  // src/node/index.ts
412
- function mapNode(data2, comment) {
684
+ function mapNode(data, comment) {
413
685
  const matches = commentExpression2.exec(comment.textContent ?? "");
414
- const value11 = matches == null ? null : data2.values[+matches[1]];
415
- if (value11 != null) {
416
- mapValue2(comment, value11);
686
+ const value13 = matches == null ? null : data.values[+matches[1]];
687
+ if (value13 != null) {
688
+ mapValue2(data, comment, value13);
417
689
  }
418
690
  }
419
- function mapNodes(data2, nodes) {
691
+ function mapNodes(data, nodes) {
420
692
  const { length } = nodes;
421
693
  for (let index = 0;index < length; index += 1) {
422
694
  const node = nodes[index];
423
695
  if (node instanceof Comment) {
424
- mapNode(data2, node);
696
+ mapNode(data, node);
425
697
  continue;
426
698
  }
427
- if (isFragmentElement(node)) {
428
- mapAttributes(data2, node);
699
+ if (isProperElement(node)) {
700
+ mapAttributes(data, node);
429
701
  }
430
702
  if (node.hasChildNodes()) {
431
- mapNodes(data2, [...node.childNodes]);
703
+ mapNodes(data, [...node.childNodes]);
432
704
  }
433
705
  }
434
706
  }
435
- function mapValue2(comment, value11) {
707
+ function mapValue2(data, comment, value13) {
436
708
  switch (true) {
437
- case typeof value11 === "function":
438
- mapValue2(comment, value11());
439
- return;
440
- case isReactive(value11):
441
- setReactiveNode(comment, value11);
709
+ case typeof value13 === "function":
710
+ setReactiveNode(data, comment, computed(value13));
711
+ break;
712
+ case isReactive(value13):
713
+ setReactiveNode(data, comment, value13);
442
714
  break;
443
715
  default:
444
- comment.replaceWith(...createNodes(value11));
716
+ replaceComment(data, comment, value13);
445
717
  break;
446
718
  }
447
719
  }
720
+ function replaceComment(data, comment, value13) {
721
+ const item = data.items.find((item2) => item2.nodes.includes(comment));
722
+ const nodes = createNodes(value13);
723
+ if (item != null) {
724
+ item.fragment = isFragment(value13) ? value13 : undefined;
725
+ item.nodes = nodes;
726
+ }
727
+ comment.replaceWith(...nodes);
728
+ }
448
729
  var commentExpression2 = /^abydon\.(\d+)$/;
449
730
 
450
731
  // src/fragment.ts
451
732
  class Fragment {
733
+ $fragment = true;
452
734
  data;
453
735
  constructor(strings, expressions) {
454
736
  this.data = {
455
737
  expressions,
456
738
  strings,
457
- nodes: [],
739
+ items: [],
458
740
  values: []
459
741
  };
460
742
  }
461
- appendTo(element2) {
462
- element2.append(...this.get());
743
+ appendTo(element) {
744
+ element.append(...this.get());
463
745
  }
464
746
  get() {
465
- if (this.data.nodes.length === 0) {
466
- const parsed = parse2(this.data);
467
- const templated = createTemplate(parsed);
468
- this.data.nodes.splice(0, this.data.nodes.length, ...getNodes(templated));
469
- mapNodes(this.data, this.data.nodes);
747
+ if (this.data.items.length === 0) {
748
+ const parsed = parse(this.data);
749
+ const templated = html(parsed, {
750
+ sanitiseBooleanAttributes: false
751
+ });
752
+ this.data.items.splice(0, this.data.items.length, ...templated.map((node2) => ({
753
+ nodes: [node2]
754
+ })));
755
+ mapNodes(this.data, this.data.items.flatMap((item) => item.fragment?.get() ?? item.nodes));
470
756
  }
471
- return [...this.data.nodes];
757
+ return [
758
+ ...this.data.items.flatMap((item) => item.fragment?.get() ?? item.nodes)
759
+ ];
472
760
  }
473
761
  remove() {
474
- const { length } = this.data.nodes;
762
+ const { length } = this.data.items;
475
763
  for (let index = 0;index < length; index += 1) {
476
- const node2 = this.data.nodes[index];
477
- node2.parentNode?.removeChild(node2);
764
+ const { fragment, nodes } = this.data.items[index];
765
+ fragment?.remove();
766
+ removeNodes(nodes);
478
767
  }
479
- this.data.nodes.splice(0, length);
768
+ this.data.items.splice(0, length);
480
769
  }
481
770
  }
482
771
 
483
772
  // src/html.ts
484
- function handleExpression(data2, prefix, expression) {
773
+ function handleExpression(data, prefix, expression) {
485
774
  if (isNullableOrWhitespace(expression)) {
486
775
  return prefix;
487
776
  }
@@ -489,27 +778,27 @@ function handleExpression(data2, prefix, expression) {
489
778
  const { length } = expression;
490
779
  let expressions = "";
491
780
  for (let index = 0;index < length; index += 1) {
492
- expressions += handleExpression(data2, "", expression[index]);
781
+ expressions += handleExpression(data, "", expression[index]);
493
782
  }
494
783
  return `${prefix}${expressions}`;
495
784
  }
496
785
  if (typeof expression === "function" || typeof expression === "object") {
497
- const index = data2.values.push(expression) - 1;
786
+ const index = data.values.push(expression) - 1;
498
787
  return `${prefix}<!--abydon.${index}-->`;
499
788
  }
500
789
  return `${prefix}${expression}`;
501
790
  }
502
- function html2(strings, ...values) {
791
+ function html4(strings, ...values) {
503
792
  return new Fragment(strings, values);
504
793
  }
505
- function parse2(data2) {
506
- const { length } = data2.strings;
507
- let template2 = "";
794
+ function parse(data) {
795
+ const { length } = data.strings;
796
+ let template4 = "";
508
797
  for (let index = 0;index < length; index += 1) {
509
- template2 += handleExpression(data2, data2.strings[index], data2.expressions[index]);
798
+ template4 += handleExpression(data, data.strings[index], data.expressions[index]);
510
799
  }
511
- return template2;
800
+ return template4;
512
801
  }
513
802
  export {
514
- html2 as html
803
+ html4 as html
515
804
  };