@oscarpalmer/abydon 0.14.0 → 0.15.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/abydon.full.js +229 -108
- package/dist/fragment.js +32 -11
- package/dist/fragments.js +74 -0
- package/dist/helpers/dom.js +1 -1
- package/dist/helpers/index.js +4 -1
- package/dist/index.js +5 -1
- package/dist/node/index.js +7 -2
- package/dist/node/value.js +44 -39
- package/dist/parse.js +6 -3
- package/package.json +2 -2
- package/src/fragment.ts +55 -20
- package/src/fragments.ts +134 -0
- package/src/helpers/index.ts +10 -0
- package/src/index.ts +18 -4
- package/src/models.ts +10 -1
- package/src/node/index.ts +12 -2
- package/src/node/value.ts +25 -3
- package/types/fragment.d.ts +23 -3
- package/types/fragments.d.ts +13 -0
- package/types/helpers/index.d.ts +2 -0
- package/types/index.d.ts +5 -1
- package/types/models.d.ts +16 -3
package/dist/abydon.full.js
CHANGED
|
@@ -358,14 +358,14 @@ function setAtIndex(array$1, index, value) {
|
|
|
358
358
|
function isKey(value) {
|
|
359
359
|
return typeof value === "number" || typeof value === "string";
|
|
360
360
|
}
|
|
361
|
-
function isPlainObject
|
|
361
|
+
function isPlainObject(value) {
|
|
362
362
|
if (value === null || typeof value !== "object") return false;
|
|
363
363
|
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
364
364
|
const prototype = Object.getPrototypeOf(value);
|
|
365
365
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
366
366
|
}
|
|
367
367
|
|
|
368
|
-
function getString
|
|
368
|
+
function getString(value) {
|
|
369
369
|
if (typeof value === "string") return value;
|
|
370
370
|
if (value == null) return "";
|
|
371
371
|
if (typeof value !== "object") return String(value);
|
|
@@ -374,7 +374,7 @@ function getString$1(value) {
|
|
|
374
374
|
}
|
|
375
375
|
|
|
376
376
|
function isNullableOrWhitespace(value) {
|
|
377
|
-
return value == null || EXPRESSION_WHITESPACE.test(getString
|
|
377
|
+
return value == null || EXPRESSION_WHITESPACE.test(getString(value));
|
|
378
378
|
}
|
|
379
379
|
var EXPRESSION_WHITESPACE = /^\s*$/;
|
|
380
380
|
|
|
@@ -397,7 +397,7 @@ var Store = class extends Reactive {
|
|
|
397
397
|
}
|
|
398
398
|
set(first, second) {
|
|
399
399
|
if (isKey(first)) this.state.value[first] = second;
|
|
400
|
-
else if (first == null || isPlainObject
|
|
400
|
+
else if (first == null || isPlainObject(first)) setProxyValue(this.state.value, first ?? {});
|
|
401
401
|
}
|
|
402
402
|
subscribe(first, second) {
|
|
403
403
|
if (isKey(first) && typeof second === "function") return getReactiveValueInProxy(this, this.#keyed, first, false).subscribe(second);
|
|
@@ -405,11 +405,11 @@ var Store = class extends Reactive {
|
|
|
405
405
|
}
|
|
406
406
|
update(callback) {
|
|
407
407
|
const updated = callback({ ...this.state.value });
|
|
408
|
-
if (updated == null || isPlainObject
|
|
408
|
+
if (updated == null || isPlainObject(updated)) setProxyValue(this.state.value, updated ?? {});
|
|
409
409
|
}
|
|
410
410
|
};
|
|
411
411
|
function store(value, options) {
|
|
412
|
-
return new Store(isPlainObject
|
|
412
|
+
return new Store(isPlainObject(value) ? value : {}, options);
|
|
413
413
|
}
|
|
414
414
|
|
|
415
415
|
function isChildNode(value) {
|
|
@@ -426,21 +426,6 @@ var CHILD_NODE_TYPES = new Set([
|
|
|
426
426
|
Node.DOCUMENT_TYPE_NODE
|
|
427
427
|
]);
|
|
428
428
|
|
|
429
|
-
function getString(value) {
|
|
430
|
-
if (typeof value === "string") return value;
|
|
431
|
-
if (value == null) return "";
|
|
432
|
-
if (typeof value !== "object") return String(value);
|
|
433
|
-
const asString = String(value.valueOf?.() ?? value);
|
|
434
|
-
return asString.startsWith("[object ") ? JSON.stringify(value) : asString;
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
function isPlainObject(value) {
|
|
438
|
-
if (value === null || typeof value !== "object") return false;
|
|
439
|
-
if (Symbol.toStringTag in value || Symbol.iterator in value) return false;
|
|
440
|
-
const prototype = Object.getPrototypeOf(value);
|
|
441
|
-
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
442
|
-
}
|
|
443
|
-
|
|
444
429
|
function isAttribute(value) {
|
|
445
430
|
return value instanceof Attr || isPlainObject(value) && typeof value.name === "string" && typeof value.value === "string";
|
|
446
431
|
}
|
|
@@ -524,14 +509,6 @@ const booleanAttributes = Object.freeze([
|
|
|
524
509
|
"selected"
|
|
525
510
|
]);
|
|
526
511
|
|
|
527
|
-
function getOptions$1(input) {
|
|
528
|
-
const options = isPlainObject(input) ? input : {};
|
|
529
|
-
options.sanitizeBooleanAttributes = typeof options.sanitizeBooleanAttributes === "boolean" ? options.sanitizeBooleanAttributes : true;
|
|
530
|
-
return options;
|
|
531
|
-
}
|
|
532
|
-
function sanitize(value, options) {
|
|
533
|
-
return sanitizeNodes$1(Array.isArray(value) ? value : [value], getOptions$1(options));
|
|
534
|
-
}
|
|
535
512
|
function sanitizeAttributes(element, attributes, options) {
|
|
536
513
|
const { length } = attributes;
|
|
537
514
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -545,50 +522,179 @@ function sanitizeNodes$1(nodes, options) {
|
|
|
545
522
|
const { length } = nodes;
|
|
546
523
|
for (let index = 0; index < length; index += 1) {
|
|
547
524
|
const node = actual[index];
|
|
548
|
-
if (node instanceof Element)
|
|
525
|
+
if (node instanceof Element) {
|
|
526
|
+
const scripts = node.querySelectorAll("script");
|
|
527
|
+
for (const script of scripts) script.remove();
|
|
528
|
+
sanitizeAttributes(node, [...node.attributes], options);
|
|
529
|
+
}
|
|
549
530
|
if (node.hasChildNodes()) sanitizeNodes$1([...node.childNodes], options);
|
|
550
531
|
}
|
|
551
532
|
return nodes;
|
|
552
533
|
}
|
|
553
534
|
|
|
554
|
-
function createTemplate(html$1) {
|
|
535
|
+
function createTemplate(html$1, ignore) {
|
|
555
536
|
const template = document.createElement("template");
|
|
556
537
|
template.innerHTML = html$1;
|
|
557
|
-
templates[html$1] = template;
|
|
538
|
+
if (!ignore) templates[html$1] = template;
|
|
558
539
|
return template;
|
|
559
540
|
}
|
|
560
|
-
function
|
|
541
|
+
function getHtml(value, options) {
|
|
542
|
+
if (typeof value !== "string" && !(value instanceof HTMLTemplateElement)) return [];
|
|
543
|
+
const template = value instanceof HTMLTemplateElement ? value : getTemplate(value, options.ignoreCache);
|
|
544
|
+
if (template == null) return [];
|
|
545
|
+
const cloned = template.content.cloneNode(true);
|
|
546
|
+
const scripts = cloned.querySelectorAll("script");
|
|
547
|
+
for (const script of scripts) script.remove();
|
|
548
|
+
cloned.normalize();
|
|
549
|
+
return sanitizeNodes$1([...cloned.childNodes], options);
|
|
550
|
+
}
|
|
551
|
+
function getOptions$1(input) {
|
|
552
|
+
const options = isPlainObject(input) ? input : {};
|
|
553
|
+
options.ignoreCache = typeof options.ignoreCache === "boolean" ? options.ignoreCache : false;
|
|
554
|
+
options.sanitizeBooleanAttributes = typeof options.sanitizeBooleanAttributes === "boolean" ? options.sanitizeBooleanAttributes : true;
|
|
555
|
+
return options;
|
|
556
|
+
}
|
|
557
|
+
function getTemplate(value, ignore) {
|
|
561
558
|
if (typeof value !== "string" || value.trim().length === 0) return;
|
|
562
559
|
let template = templates[value];
|
|
563
560
|
if (template != null) return template;
|
|
564
561
|
const element = EXPRESSION_ID.test(value) ? document.querySelector(`#${value}`) : null;
|
|
565
|
-
template = element instanceof HTMLTemplateElement ? element : createTemplate(value);
|
|
566
|
-
templates[value] = template;
|
|
562
|
+
template = element instanceof HTMLTemplateElement ? element : createTemplate(value, ignore);
|
|
567
563
|
return template;
|
|
568
564
|
}
|
|
569
|
-
var html$1 = ((value,
|
|
570
|
-
|
|
571
|
-
let options;
|
|
572
|
-
if (sanitization == null || sanitization === true) options = {};
|
|
573
|
-
else options = sanitization === false ? void 0 : sanitization;
|
|
574
|
-
const template = value instanceof HTMLTemplateElement ? value : getTemplate(value);
|
|
575
|
-
if (template == null) return [];
|
|
576
|
-
const cloned = template.content.cloneNode(true);
|
|
577
|
-
const scripts = cloned.querySelectorAll("script");
|
|
578
|
-
const { length } = scripts;
|
|
579
|
-
for (let index = 0; index < length; index += 1) scripts[index].remove();
|
|
580
|
-
cloned.normalize();
|
|
581
|
-
return options != null ? sanitize([...cloned.childNodes], options) : [...cloned.childNodes];
|
|
565
|
+
var html$1 = ((value, options) => {
|
|
566
|
+
return getHtml(value, getOptions$1(options));
|
|
582
567
|
});
|
|
583
568
|
html$1.clear = () => {
|
|
584
569
|
templates = {};
|
|
585
570
|
};
|
|
586
571
|
html$1.remove = (template) => {
|
|
587
|
-
if (typeof template
|
|
572
|
+
if (typeof template !== "string" || templates[template] == null) return;
|
|
573
|
+
const keys = Object.keys(templates);
|
|
574
|
+
const { length } = keys;
|
|
575
|
+
const updated = {};
|
|
576
|
+
for (let index = 0; index < length; index += 1) {
|
|
577
|
+
const key = keys[index];
|
|
578
|
+
if (key !== template) updated[key] = templates[key];
|
|
579
|
+
}
|
|
580
|
+
templates = updated;
|
|
588
581
|
};
|
|
589
582
|
var EXPRESSION_ID = /^[a-z][\w-]*$/i;
|
|
590
583
|
var templates = {};
|
|
591
584
|
|
|
585
|
+
function compareArrays(first, second) {
|
|
586
|
+
const firstIsLarger = first.length > second.length;
|
|
587
|
+
const from = firstIsLarger ? first : second;
|
|
588
|
+
const to = firstIsLarger ? second : first;
|
|
589
|
+
if (!from
|
|
590
|
+
.filter(key => to.includes(key))
|
|
591
|
+
.every((key, index) => to[index] === key)) {
|
|
592
|
+
return 'dissimilar';
|
|
593
|
+
}
|
|
594
|
+
return firstIsLarger ? 'removed' : 'added';
|
|
595
|
+
}
|
|
596
|
+
function isFragment(value) {
|
|
597
|
+
return (typeof value === 'object' &&
|
|
598
|
+
value != null &&
|
|
599
|
+
'$fragment' in value &&
|
|
600
|
+
value.$fragment === true);
|
|
601
|
+
}
|
|
602
|
+
function isFragments(value) {
|
|
603
|
+
return (typeof value === 'object' &&
|
|
604
|
+
value != null &&
|
|
605
|
+
'$fragments' in value &&
|
|
606
|
+
value.$fragments === true);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
class Fragments {
|
|
610
|
+
#state;
|
|
611
|
+
/**
|
|
612
|
+
* Fragment items
|
|
613
|
+
*/
|
|
614
|
+
get items() {
|
|
615
|
+
return this.#state.mapped;
|
|
616
|
+
}
|
|
617
|
+
constructor(items, identify, fragment) {
|
|
618
|
+
Object.defineProperty(this, '$fragments', {
|
|
619
|
+
value: true,
|
|
620
|
+
});
|
|
621
|
+
this.#state = {
|
|
622
|
+
fragment,
|
|
623
|
+
identify,
|
|
624
|
+
array: items,
|
|
625
|
+
instances: {},
|
|
626
|
+
mapped: array([]),
|
|
627
|
+
subscriber: undefined,
|
|
628
|
+
};
|
|
629
|
+
states.set(this, this.#state);
|
|
630
|
+
initializeFragments(this.#state);
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
function handleFragments(item, remove) {
|
|
634
|
+
const state = isFragments(item) ? states.get(item) : item;
|
|
635
|
+
if (state != null) {
|
|
636
|
+
(remove ? removeFragments$1 : initializeFragments)(state);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
function handleItems(state, items) {
|
|
640
|
+
const keys = new Set();
|
|
641
|
+
const mapped = [];
|
|
642
|
+
const { length } = items;
|
|
643
|
+
for (let index = 0; index < length; index += 1) {
|
|
644
|
+
const item = items[index];
|
|
645
|
+
const identifier = state.identify(item);
|
|
646
|
+
if (identifier == null) {
|
|
647
|
+
throw new Error('Identifier cannot be null or undefined');
|
|
648
|
+
}
|
|
649
|
+
const key = getString(identifier);
|
|
650
|
+
if (keys.has(key)) {
|
|
651
|
+
throw new Error(`Duplicate identifier found: "${key}"`);
|
|
652
|
+
}
|
|
653
|
+
let instance = state.instances[key];
|
|
654
|
+
if (instance == null) {
|
|
655
|
+
instance = state.fragment(item);
|
|
656
|
+
if (!isFragment(instance)) {
|
|
657
|
+
throw new Error('Fragment function must return a Fragment instance');
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
instance.identify(key);
|
|
661
|
+
state.instances[key] = instance;
|
|
662
|
+
keys.add(key);
|
|
663
|
+
mapped.push(instance);
|
|
664
|
+
}
|
|
665
|
+
state.mapped.set(mapped);
|
|
666
|
+
updateFragments(state, keys);
|
|
667
|
+
}
|
|
668
|
+
function initializeFragments(state) {
|
|
669
|
+
state.subscriber ??= state.array.subscribe(items => {
|
|
670
|
+
handleItems(state, items);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
function removeFragments$1(state) {
|
|
674
|
+
state.subscriber?.();
|
|
675
|
+
updateFragments(state);
|
|
676
|
+
state.subscriber = undefined;
|
|
677
|
+
}
|
|
678
|
+
function updateFragments(state, active) {
|
|
679
|
+
const next = {};
|
|
680
|
+
const previous = { ...state.instances };
|
|
681
|
+
const keys = Object.keys(previous);
|
|
682
|
+
const { length } = keys;
|
|
683
|
+
for (let index = 0; index < length; index += 1) {
|
|
684
|
+
const key = keys[index];
|
|
685
|
+
if (active?.has(key)) {
|
|
686
|
+
next[key] = previous[key];
|
|
687
|
+
}
|
|
688
|
+
else {
|
|
689
|
+
previous[key].remove();
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
state.instances = next;
|
|
693
|
+
active?.clear();
|
|
694
|
+
}
|
|
695
|
+
//
|
|
696
|
+
const states = new WeakMap();
|
|
697
|
+
|
|
592
698
|
const ABORT_CONTROLLERS = new WeakMap();
|
|
593
699
|
const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
594
700
|
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
@@ -630,24 +736,6 @@ function removeEvents(element) {
|
|
|
630
736
|
ABORT_CONTROLLERS.delete(element);
|
|
631
737
|
}
|
|
632
738
|
|
|
633
|
-
function compareArrays(first, second) {
|
|
634
|
-
const firstIsLarger = first.length > second.length;
|
|
635
|
-
const from = firstIsLarger ? first : second;
|
|
636
|
-
const to = firstIsLarger ? second : first;
|
|
637
|
-
if (!from
|
|
638
|
-
.filter(key => to.includes(key))
|
|
639
|
-
.every((key, index) => to[index] === key)) {
|
|
640
|
-
return 'dissimilar';
|
|
641
|
-
}
|
|
642
|
-
return firstIsLarger ? 'removed' : 'added';
|
|
643
|
-
}
|
|
644
|
-
function isFragment(value) {
|
|
645
|
-
return (typeof value === 'object' &&
|
|
646
|
-
value != null &&
|
|
647
|
-
'$fragment' in value &&
|
|
648
|
-
value.$fragment === true);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
739
|
function createNodes(value) {
|
|
652
740
|
if (isFragment(value)) {
|
|
653
741
|
return value.get();
|
|
@@ -655,7 +743,7 @@ function createNodes(value) {
|
|
|
655
743
|
if (isChildNode(value)) {
|
|
656
744
|
return [value];
|
|
657
745
|
}
|
|
658
|
-
return [new Text(getString
|
|
746
|
+
return [new Text(getString(value))];
|
|
659
747
|
}
|
|
660
748
|
function removeNodes(nodes) {
|
|
661
749
|
sanitizeNodes(nodes);
|
|
@@ -725,7 +813,7 @@ function setStyle(data, element, name, value) {
|
|
|
725
813
|
element.style.removeProperty(property);
|
|
726
814
|
}
|
|
727
815
|
else {
|
|
728
|
-
element.style.setProperty(property, value === true ? unit : getString
|
|
816
|
+
element.style.setProperty(property, value === true ? unit : getString(value));
|
|
729
817
|
}
|
|
730
818
|
}
|
|
731
819
|
if (isReactive(value)) {
|
|
@@ -849,6 +937,16 @@ function removeFragments(fragments) {
|
|
|
849
937
|
}
|
|
850
938
|
}
|
|
851
939
|
}
|
|
940
|
+
function replaceText(item, comment, isNullable) {
|
|
941
|
+
let to;
|
|
942
|
+
if (isNullable) {
|
|
943
|
+
to = [comment];
|
|
944
|
+
}
|
|
945
|
+
else {
|
|
946
|
+
to = item.text == null ? [] : [item.text];
|
|
947
|
+
}
|
|
948
|
+
replaceNodes(item.nodes ?? [], to);
|
|
949
|
+
}
|
|
852
950
|
function setArray(item, comment, value) {
|
|
853
951
|
if (value.length === 0) {
|
|
854
952
|
return {
|
|
@@ -913,7 +1011,12 @@ function setReactiveValueForArray(item, comment, value) {
|
|
|
913
1011
|
const result = setArray(item, comment, value);
|
|
914
1012
|
item.fragments = typeof result === 'boolean' ? undefined : result?.fragments;
|
|
915
1013
|
if (typeof result === 'boolean') {
|
|
916
|
-
|
|
1014
|
+
if (result) {
|
|
1015
|
+
item.nodes = item.text == null ? [] : [item.text];
|
|
1016
|
+
}
|
|
1017
|
+
else {
|
|
1018
|
+
item.nodes = undefined;
|
|
1019
|
+
}
|
|
917
1020
|
}
|
|
918
1021
|
else {
|
|
919
1022
|
item.nodes = result?.nodes;
|
|
@@ -932,11 +1035,11 @@ function setReactiveValueForSingle(item, comment, value) {
|
|
|
932
1035
|
function setText(item, comment, value) {
|
|
933
1036
|
const isNullable = isNullableOrWhitespace(value);
|
|
934
1037
|
if (item.text != null) {
|
|
935
|
-
item.text.textContent = isNullable ? '' : getString
|
|
1038
|
+
item.text.textContent = isNullable ? '' : getString(value);
|
|
936
1039
|
}
|
|
937
1040
|
let result = false;
|
|
938
1041
|
if (item.nodes != null) {
|
|
939
|
-
|
|
1042
|
+
replaceText(item, comment, isNullable);
|
|
940
1043
|
result = !isNullable;
|
|
941
1044
|
}
|
|
942
1045
|
else if (isNullable && comment.parentNode == null) {
|
|
@@ -949,7 +1052,9 @@ function setText(item, comment, value) {
|
|
|
949
1052
|
result = true;
|
|
950
1053
|
}
|
|
951
1054
|
removeFragments(item.fragments);
|
|
952
|
-
|
|
1055
|
+
if (result) {
|
|
1056
|
+
return item.text == null ? [] : [item.text];
|
|
1057
|
+
}
|
|
953
1058
|
}
|
|
954
1059
|
|
|
955
1060
|
function mapNode(data, comment) {
|
|
@@ -980,6 +1085,10 @@ function mapValue(data, comment, value) {
|
|
|
980
1085
|
case typeof value === 'function':
|
|
981
1086
|
setComputedValue(data, comment, value);
|
|
982
1087
|
break;
|
|
1088
|
+
case isFragments(value):
|
|
1089
|
+
handleFragments(value, false);
|
|
1090
|
+
setReactiveValue(data, comment, value.items);
|
|
1091
|
+
break;
|
|
983
1092
|
case isReactive(value):
|
|
984
1093
|
setReactiveValue(data, comment, value);
|
|
985
1094
|
break;
|
|
@@ -1033,34 +1142,22 @@ function parse(data) {
|
|
|
1033
1142
|
return data.template;
|
|
1034
1143
|
}
|
|
1035
1144
|
|
|
1036
|
-
function calculate() {
|
|
1037
|
-
return new Promise((resolve) => {
|
|
1038
|
-
const values = [];
|
|
1039
|
-
let last;
|
|
1040
|
-
function step(now) {
|
|
1041
|
-
if (last != null) values.push(now - last);
|
|
1042
|
-
last = now;
|
|
1043
|
-
if (values.length >= CALCULATION_TOTAL) resolve(values.sort().slice(2, -2).reduce((first, second) => first + second, 0) / (values.length - CALCULATION_TRIM));
|
|
1044
|
-
else requestAnimationFrame(step);
|
|
1045
|
-
}
|
|
1046
|
-
requestAnimationFrame(step);
|
|
1047
|
-
});
|
|
1048
|
-
}
|
|
1049
|
-
var CALCULATION_TOTAL = 10;
|
|
1050
|
-
var CALCULATION_TRIM = 4;
|
|
1051
|
-
calculate().then((value) => {
|
|
1052
|
-
});
|
|
1053
|
-
|
|
1054
1145
|
class Fragment {
|
|
1055
1146
|
#data;
|
|
1056
1147
|
#configuration = {
|
|
1057
1148
|
identifier: undefined,
|
|
1058
1149
|
ignoreCache: false,
|
|
1059
1150
|
};
|
|
1151
|
+
/**
|
|
1152
|
+
* Fragment identifier
|
|
1153
|
+
*/
|
|
1060
1154
|
get identifier() {
|
|
1061
1155
|
return this.#configuration.identifier;
|
|
1062
1156
|
}
|
|
1063
1157
|
constructor(strings, expressions) {
|
|
1158
|
+
Object.defineProperty(this, '$fragment', {
|
|
1159
|
+
value: true,
|
|
1160
|
+
});
|
|
1064
1161
|
this.#data = {
|
|
1065
1162
|
expressions,
|
|
1066
1163
|
strings,
|
|
@@ -1071,18 +1168,21 @@ class Fragment {
|
|
|
1071
1168
|
},
|
|
1072
1169
|
values: [],
|
|
1073
1170
|
};
|
|
1074
|
-
Object.defineProperty(this, '$fragment', {
|
|
1075
|
-
value: true,
|
|
1076
|
-
});
|
|
1077
1171
|
}
|
|
1078
1172
|
/**
|
|
1079
|
-
*
|
|
1173
|
+
* Append the fragment to the given element
|
|
1174
|
+
* @param element Element to append to
|
|
1080
1175
|
*/
|
|
1081
1176
|
appendTo(element) {
|
|
1082
1177
|
element.append(...this.get());
|
|
1083
1178
|
}
|
|
1179
|
+
/**
|
|
1180
|
+
* Configure the fragment
|
|
1181
|
+
* @param configuration Configuration options
|
|
1182
|
+
* @returns Fragment
|
|
1183
|
+
*/
|
|
1084
1184
|
configure(configuration) {
|
|
1085
|
-
const actual = isPlainObject
|
|
1185
|
+
const actual = isPlainObject(configuration) ? configuration : {};
|
|
1086
1186
|
if (actual.identifier !== undefined) {
|
|
1087
1187
|
this.#configuration.identifier = actual.identifier;
|
|
1088
1188
|
}
|
|
@@ -1092,33 +1192,44 @@ class Fragment {
|
|
|
1092
1192
|
return this;
|
|
1093
1193
|
}
|
|
1094
1194
|
/**
|
|
1095
|
-
*
|
|
1195
|
+
* Get a list of the fragment's nodes
|
|
1196
|
+
* @returns List of nodes
|
|
1096
1197
|
*/
|
|
1097
1198
|
get() {
|
|
1098
1199
|
const data = this.#data;
|
|
1099
1200
|
if (data.items.length === 0) {
|
|
1100
1201
|
const parsed = parse(data);
|
|
1101
1202
|
const templated = html$1(parsed, {
|
|
1203
|
+
ignoreCache: this.#configuration.ignoreCache,
|
|
1102
1204
|
sanitizeBooleanAttributes: false,
|
|
1103
1205
|
});
|
|
1104
|
-
if (this.#configuration.ignoreCache) {
|
|
1105
|
-
html$1.remove(parsed);
|
|
1106
|
-
}
|
|
1107
1206
|
data.items.splice(0, data.items.length, ...templated.map(node => ({
|
|
1108
1207
|
nodes: [node],
|
|
1109
1208
|
})));
|
|
1110
|
-
mapNodes(data, data.items.flatMap(item => item.fragments?.flatMap(fragment => fragment.get()) ??
|
|
1209
|
+
mapNodes(data, data.items.flatMap(item => item.fragments?.flatMap(fragment => fragment.get()) ??
|
|
1210
|
+
item.nodes ??
|
|
1211
|
+
[]));
|
|
1111
1212
|
}
|
|
1112
1213
|
return [
|
|
1113
|
-
...data.items.flatMap(item => item.fragments?.flatMap(fragment => fragment.get()) ??
|
|
1214
|
+
...data.items.flatMap(item => item.fragments?.flatMap(fragment => fragment.get()) ??
|
|
1215
|
+
item.nodes ??
|
|
1216
|
+
[]),
|
|
1114
1217
|
];
|
|
1115
1218
|
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Set an identifier for the fragment
|
|
1221
|
+
*
|
|
1222
|
+
* _An identifier can be used to uniquely identify a fragment,
|
|
1223
|
+
* which helps prevent re-rendering in certain scenarios._
|
|
1224
|
+
* @param identifier Identifier
|
|
1225
|
+
* @returns Fragment
|
|
1226
|
+
*/
|
|
1116
1227
|
identify(identifier) {
|
|
1117
1228
|
this.#configuration.identifier = identifier;
|
|
1118
1229
|
return this;
|
|
1119
1230
|
}
|
|
1120
1231
|
/**
|
|
1121
|
-
*
|
|
1232
|
+
* Remove the fragment from the DOM
|
|
1122
1233
|
*/
|
|
1123
1234
|
remove() {
|
|
1124
1235
|
removeFragment(this.#data);
|
|
@@ -1126,16 +1237,23 @@ class Fragment {
|
|
|
1126
1237
|
}
|
|
1127
1238
|
function removeFragment(data) {
|
|
1128
1239
|
removeMora(data);
|
|
1129
|
-
|
|
1240
|
+
let { length } = data.items;
|
|
1130
1241
|
for (let index = 0; index < length; index += 1) {
|
|
1131
1242
|
const { fragments, nodes } = data.items[index];
|
|
1132
|
-
const
|
|
1133
|
-
for (let
|
|
1134
|
-
fragments?.[
|
|
1243
|
+
const fragmentsLength = fragments?.length ?? 0;
|
|
1244
|
+
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) {
|
|
1245
|
+
fragments?.[fragmentIndex]?.remove();
|
|
1135
1246
|
}
|
|
1136
1247
|
removeNodes(nodes ?? []);
|
|
1137
1248
|
}
|
|
1138
1249
|
data.items.length = 0;
|
|
1250
|
+
length = data.values.length;
|
|
1251
|
+
for (let index = 0; index < length; index += 1) {
|
|
1252
|
+
const value = data.values[index];
|
|
1253
|
+
if (isFragments(value)) {
|
|
1254
|
+
handleFragments(value, true);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1139
1257
|
}
|
|
1140
1258
|
function removeMora(data) {
|
|
1141
1259
|
const unsubscribers = [...data.mora.subscribers];
|
|
@@ -1146,8 +1264,11 @@ function removeMora(data) {
|
|
|
1146
1264
|
}
|
|
1147
1265
|
}
|
|
1148
1266
|
|
|
1267
|
+
function fragments(array, identify, fragment) {
|
|
1268
|
+
return new Fragments(array, identify, fragment);
|
|
1269
|
+
}
|
|
1149
1270
|
function html(strings, ...values) {
|
|
1150
1271
|
return new Fragment(strings, values);
|
|
1151
1272
|
}
|
|
1152
1273
|
|
|
1153
|
-
export { array, computed, effect, html, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
|
1274
|
+
export { array, computed, effect, fragments, html, isArray, isComputed, isEffect, isReactive, isSignal, signal, startBatch, stopBatch, store };
|
package/dist/fragment.js
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
import { parse } from "./parse.js";
|
|
2
|
+
import { isFragments } from "./helpers/index.js";
|
|
3
|
+
import { handleFragments } from "./fragments.js";
|
|
2
4
|
import { removeNodes } from "./helpers/dom.js";
|
|
3
5
|
import { mapNodes } from "./node/index.js";
|
|
6
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
7
|
import { html } from "@oscarpalmer/toretto/html";
|
|
5
8
|
var Fragment = class {
|
|
6
9
|
#data;
|
|
10
|
+
#configuration = {
|
|
11
|
+
identifier: void 0,
|
|
12
|
+
ignoreCache: false
|
|
13
|
+
};
|
|
7
14
|
get identifier() {
|
|
8
|
-
return this.#
|
|
15
|
+
return this.#configuration.identifier;
|
|
9
16
|
}
|
|
10
17
|
constructor(strings, expressions) {
|
|
18
|
+
Object.defineProperty(this, "$fragment", { value: true });
|
|
11
19
|
this.#data = {
|
|
12
20
|
expressions,
|
|
13
21
|
strings,
|
|
@@ -18,22 +26,30 @@ var Fragment = class {
|
|
|
18
26
|
},
|
|
19
27
|
values: []
|
|
20
28
|
};
|
|
21
|
-
Object.defineProperty(this, "$fragment", { value: true });
|
|
22
29
|
}
|
|
23
30
|
appendTo(element) {
|
|
24
31
|
element.append(...this.get());
|
|
25
32
|
}
|
|
33
|
+
configure(configuration) {
|
|
34
|
+
const actual = isPlainObject(configuration) ? configuration : {};
|
|
35
|
+
if (actual.identifier !== void 0) this.#configuration.identifier = actual.identifier;
|
|
36
|
+
if (typeof actual.ignoreCache === "boolean") this.#configuration.ignoreCache = actual.ignoreCache;
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
26
39
|
get() {
|
|
27
40
|
const data = this.#data;
|
|
28
41
|
if (data.items.length === 0) {
|
|
29
|
-
const templated = html(parse(data), {
|
|
42
|
+
const templated = html(parse(data), {
|
|
43
|
+
ignoreCache: this.#configuration.ignoreCache,
|
|
44
|
+
sanitizeBooleanAttributes: false
|
|
45
|
+
});
|
|
30
46
|
data.items.splice(0, data.items.length, ...templated.map((node) => ({ nodes: [node] })));
|
|
31
|
-
mapNodes(data, data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes));
|
|
47
|
+
mapNodes(data, data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []));
|
|
32
48
|
}
|
|
33
|
-
return [...data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes)];
|
|
49
|
+
return [...data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? [])];
|
|
34
50
|
}
|
|
35
51
|
identify(identifier) {
|
|
36
|
-
this.#
|
|
52
|
+
this.#configuration.identifier = identifier;
|
|
37
53
|
return this;
|
|
38
54
|
}
|
|
39
55
|
remove() {
|
|
@@ -42,14 +58,19 @@ var Fragment = class {
|
|
|
42
58
|
};
|
|
43
59
|
function removeFragment(data) {
|
|
44
60
|
removeMora(data);
|
|
45
|
-
|
|
61
|
+
let { length } = data.items;
|
|
46
62
|
for (let index = 0; index < length; index += 1) {
|
|
47
63
|
const { fragments, nodes } = data.items[index];
|
|
48
|
-
const
|
|
49
|
-
for (let
|
|
50
|
-
removeNodes(nodes);
|
|
64
|
+
const fragmentsLength = fragments?.length ?? 0;
|
|
65
|
+
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) fragments?.[fragmentIndex]?.remove();
|
|
66
|
+
removeNodes(nodes ?? []);
|
|
67
|
+
}
|
|
68
|
+
data.items.length = 0;
|
|
69
|
+
length = data.values.length;
|
|
70
|
+
for (let index = 0; index < length; index += 1) {
|
|
71
|
+
const value = data.values[index];
|
|
72
|
+
if (isFragments(value)) handleFragments(value, true);
|
|
51
73
|
}
|
|
52
|
-
data.items.splice(0, length);
|
|
53
74
|
}
|
|
54
75
|
function removeMora(data) {
|
|
55
76
|
const unsubscribers = [...data.mora.subscribers];
|