@oscarpalmer/abydon 0.15.0 → 0.16.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 +799 -751
- package/dist/constants.js +20 -5
- package/dist/fragment.js +8 -10
- package/dist/fragments.js +3 -2
- package/dist/helpers/dom.js +1 -11
- package/dist/helpers/index.js +11 -4
- package/dist/index.js +2 -2
- package/dist/node/attribute/index.js +14 -14
- package/dist/node/attribute/value.js +19 -13
- package/dist/node/event.js +15 -22
- package/dist/node/index.js +2 -2
- package/dist/node/value.js +5 -5
- package/dist/parse.js +9 -1
- package/package.json +13 -15
- package/src/constants.ts +30 -10
- package/src/fragment.ts +12 -24
- package/src/fragments.ts +3 -5
- package/src/helpers/dom.ts +1 -20
- package/src/helpers/index.ts +18 -15
- package/src/index.ts +14 -10
- package/src/models.ts +10 -1
- package/src/node/attribute/index.ts +22 -21
- package/src/node/attribute/value.ts +44 -37
- package/src/node/event.ts +26 -33
- package/src/node/index.ts +6 -18
- package/src/node/value.ts +15 -46
- package/src/parse.ts +15 -17
- package/types/constants.d.ts +12 -4
- package/types/index.d.ts +12 -1
- package/types/models.d.ts +10 -1
- package/types/node/attribute/index.d.ts +1 -2
- package/types/node/attribute/value.d.ts +1 -2
- package/types/node/event.d.ts +1 -3
package/src/helpers/dom.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
2
|
-
import {isChildNode
|
|
3
|
-
import {removeEvents} from '../node/event';
|
|
2
|
+
import {isChildNode} from '@oscarpalmer/toretto/is';
|
|
4
3
|
import {isFragment} from './index';
|
|
5
4
|
|
|
6
5
|
export function createNodes(value: unknown): ChildNode[] {
|
|
@@ -16,8 +15,6 @@ export function createNodes(value: unknown): ChildNode[] {
|
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
export function removeNodes(nodes: ChildNode[]): void {
|
|
19
|
-
sanitizeNodes(nodes);
|
|
20
|
-
|
|
21
18
|
const {length} = nodes;
|
|
22
19
|
|
|
23
20
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -34,19 +31,3 @@ export function replaceNodes(from: ChildNode[], to: ChildNode[]): void {
|
|
|
34
31
|
from[index].remove();
|
|
35
32
|
}
|
|
36
33
|
}
|
|
37
|
-
|
|
38
|
-
function sanitizeNodes(nodes: ChildNode[]): void {
|
|
39
|
-
const {length} = nodes;
|
|
40
|
-
|
|
41
|
-
for (let index = 0; index < length; index += 1) {
|
|
42
|
-
const node = nodes[index];
|
|
43
|
-
|
|
44
|
-
if (isHTMLOrSVGElement(node)) {
|
|
45
|
-
removeEvents(node);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
if (node.hasChildNodes()) {
|
|
49
|
-
sanitizeNodes([...node.childNodes] as ChildNode[]);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
package/src/helpers/index.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
|
+
import {NAME_FRAGMENT, NAME_FRAGMENTS} from '../constants';
|
|
1
3
|
import type {Fragment} from '../fragment';
|
|
2
4
|
import type {Fragments} from '../fragments';
|
|
3
5
|
|
|
@@ -9,31 +11,32 @@ export function compareArrays(
|
|
|
9
11
|
const from = firstIsLarger ? first : second;
|
|
10
12
|
const to = firstIsLarger ? second : first;
|
|
11
13
|
|
|
12
|
-
if (
|
|
13
|
-
|
|
14
|
-
.filter(key => to.includes(key))
|
|
15
|
-
.every((key, index) => to[index] === key)
|
|
16
|
-
) {
|
|
17
|
-
return 'dissimilar';
|
|
14
|
+
if (!from.filter(key => to.includes(key)).every((key, index) => to[index] === key)) {
|
|
15
|
+
return COMPARISON_DISSIMILAR;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
return firstIsLarger ?
|
|
18
|
+
return firstIsLarger ? COMPARISON_REMOVED : COMPARISON_ADDED;
|
|
21
19
|
}
|
|
22
20
|
|
|
23
21
|
export function isFragment(value: unknown): value is Fragment {
|
|
24
|
-
return (
|
|
25
|
-
typeof value === 'object' &&
|
|
26
|
-
value != null &&
|
|
27
|
-
'$fragment' in value &&
|
|
28
|
-
value.$fragment === true
|
|
29
|
-
);
|
|
22
|
+
return isNamed(value, NAME_FRAGMENT);
|
|
30
23
|
}
|
|
31
24
|
|
|
32
25
|
export function isFragments(value: unknown): value is Fragments {
|
|
26
|
+
return isNamed(value, NAME_FRAGMENTS);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function isNamed(value: unknown, name: string): boolean {
|
|
33
30
|
return (
|
|
34
31
|
typeof value === 'object' &&
|
|
35
32
|
value != null &&
|
|
36
|
-
|
|
37
|
-
value
|
|
33
|
+
name in value &&
|
|
34
|
+
(value as PlainObject)[name] === true
|
|
38
35
|
);
|
|
39
36
|
}
|
|
37
|
+
|
|
38
|
+
const COMPARISON_ADDED = 'added';
|
|
39
|
+
|
|
40
|
+
const COMPARISON_DISSIMILAR = 'dissimilar';
|
|
41
|
+
|
|
42
|
+
const COMPARISON_REMOVED = 'removed';
|
package/src/index.ts
CHANGED
|
@@ -3,23 +3,27 @@ import type {ReactiveArray} from '@oscarpalmer/mora';
|
|
|
3
3
|
import {Fragment} from './fragment';
|
|
4
4
|
import {Fragments} from './fragments';
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Create Fragments from a reactive array
|
|
8
|
+
* @param array Reactive array
|
|
9
|
+
* @param identify Function to identify item
|
|
10
|
+
* @param fragment Function to create fragment from item
|
|
11
|
+
* @returns Fragments
|
|
12
|
+
*/
|
|
6
13
|
export function fragments<Item>(
|
|
7
14
|
array: ReactiveArray<Item>,
|
|
8
15
|
identify: (item: Item) => unknown,
|
|
9
16
|
fragment: (item: Item) => Fragment,
|
|
10
17
|
): Fragments {
|
|
11
|
-
return new Fragments(
|
|
12
|
-
array as ReactiveArray<unknown>,
|
|
13
|
-
identify as never,
|
|
14
|
-
fragment as never,
|
|
15
|
-
);
|
|
18
|
+
return new Fragments(array as ReactiveArray<unknown>, identify as never, fragment as never);
|
|
16
19
|
}
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Create Fragment from a template
|
|
23
|
+
* @returns Fragment
|
|
24
|
+
*/
|
|
25
|
+
export function html(template: TemplateStringsArray, ...values: unknown[]): Fragment {
|
|
26
|
+
return new Fragment(template, values);
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
export * from '@oscarpalmer/mora';
|
package/src/models.ts
CHANGED
|
@@ -2,8 +2,17 @@ import type {Reactive, ReactiveArray, Unsubscribe} from '@oscarpalmer/mora';
|
|
|
2
2
|
import type {Fragment} from './fragment';
|
|
3
3
|
|
|
4
4
|
export type FragmentConfiguration = {
|
|
5
|
+
/**
|
|
6
|
+
* Should the template be cached? _(defaults to `true`)_
|
|
7
|
+
*/
|
|
8
|
+
cache?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Identifier for the fragment
|
|
11
|
+
*
|
|
12
|
+
* _(An identifier can be used to uniquely identify a fragment,
|
|
13
|
+
* which helps prevent re-rendering in certain scenarios)_
|
|
14
|
+
*/
|
|
5
15
|
identifier?: unknown;
|
|
6
|
-
ignoreCache?: boolean;
|
|
7
16
|
};
|
|
8
17
|
|
|
9
18
|
export type FragmentData = {
|
|
@@ -1,43 +1,44 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {computed, isReactive} from '@oscarpalmer/mora';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import {
|
|
4
|
+
EXPRESSION_ABYDON_ATTRIBUTE_PREFIX,
|
|
5
|
+
EXPRESSION_ABYDON_CONTENT,
|
|
6
|
+
EXPRESSION_EVENT_PREFIX,
|
|
7
|
+
EXPRESSION_PERIOD,
|
|
8
|
+
} from '../../constants';
|
|
6
9
|
import type {FragmentData} from '../../models';
|
|
7
10
|
import {mapEvent} from '../event';
|
|
8
11
|
import {setAttribute} from './value';
|
|
9
12
|
|
|
10
13
|
function getValue(data: FragmentData, original: string): unknown {
|
|
11
|
-
const matches =
|
|
14
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(original ?? '');
|
|
12
15
|
|
|
13
16
|
return matches == null ? original : data.values[+matches[1]];
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
export function mapAttributes(
|
|
17
|
-
data: FragmentData,
|
|
18
|
-
element: HTMLOrSVGElement,
|
|
19
|
-
): void {
|
|
19
|
+
export function mapAttributes(data: FragmentData, element: HTMLElement | SVGElement): void {
|
|
20
20
|
const attributes = [...element.attributes];
|
|
21
21
|
const {length} = attributes;
|
|
22
22
|
|
|
23
23
|
for (let index = 0; index < length; index += 1) {
|
|
24
24
|
const {name, value} = attributes[index];
|
|
25
25
|
|
|
26
|
-
const
|
|
26
|
+
const actualName = name.replace(EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, '');
|
|
27
|
+
const actualValue = getValue(data, value) as never;
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
break;
|
|
29
|
+
if (actualName !== name) {
|
|
30
|
+
element.removeAttribute(name);
|
|
31
|
+
}
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
mapValue(data, element, name, actual);
|
|
33
|
+
switch (true) {
|
|
34
|
+
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
35
|
+
mapEvent(element, actualName, actualValue);
|
|
37
36
|
break;
|
|
38
37
|
|
|
39
|
-
case
|
|
40
|
-
|
|
38
|
+
case EXPRESSION_PERIOD.test(actualName):
|
|
39
|
+
case typeof actualValue === 'function':
|
|
40
|
+
case isReactive(actualValue):
|
|
41
|
+
mapValue(data, element, actualName, actualValue);
|
|
41
42
|
break;
|
|
42
43
|
|
|
43
44
|
default:
|
|
@@ -48,7 +49,7 @@ export function mapAttributes(
|
|
|
48
49
|
|
|
49
50
|
function mapValue(
|
|
50
51
|
data: FragmentData,
|
|
51
|
-
element:
|
|
52
|
+
element: HTMLElement | SVGElement,
|
|
52
53
|
name: string,
|
|
53
54
|
value: unknown,
|
|
54
55
|
): void {
|
|
@@ -61,7 +62,7 @@ function mapValue(
|
|
|
61
62
|
|
|
62
63
|
function setComputedAttribute(
|
|
63
64
|
data: FragmentData,
|
|
64
|
-
element:
|
|
65
|
+
element: HTMLElement | SVGElement,
|
|
65
66
|
name: string,
|
|
66
67
|
callback: GenericCallback,
|
|
67
68
|
): void {
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {getString} from '@oscarpalmer/atoms/string';
|
|
3
2
|
import {isReactive} from '@oscarpalmer/mora';
|
|
4
3
|
import {
|
|
5
4
|
isBooleanAttribute,
|
|
6
5
|
setAttribute as setAttr,
|
|
6
|
+
setProperty,
|
|
7
7
|
} from '@oscarpalmer/toretto/attribute';
|
|
8
|
-
import type {HTMLOrSVGElement} from '@oscarpalmer/toretto/models';
|
|
9
8
|
import {
|
|
10
9
|
ATTRIBUTE_CLASS_PREFIX_LENGTH,
|
|
11
10
|
EXPRESSION_ATTRIBUTE_CLASS,
|
|
@@ -14,14 +13,20 @@ import {
|
|
|
14
13
|
} from '../../constants';
|
|
15
14
|
import type {FragmentData} from '../../models';
|
|
16
15
|
|
|
16
|
+
function getCallback(element: HTMLElement | SVGElement, name: string) {
|
|
17
|
+
if (isBooleanAttribute(name) && name in element) {
|
|
18
|
+
return name === 'checked' ? updateChecked : updateProperty;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return name === 'value' ? updateValue : setAttr;
|
|
22
|
+
}
|
|
23
|
+
|
|
17
24
|
export function setAttribute(
|
|
18
25
|
data: FragmentData,
|
|
19
|
-
element:
|
|
26
|
+
element: HTMLElement | SVGElement,
|
|
20
27
|
name: string,
|
|
21
28
|
value: unknown,
|
|
22
29
|
): void {
|
|
23
|
-
element.removeAttribute(name);
|
|
24
|
-
|
|
25
30
|
switch (true) {
|
|
26
31
|
case EXPRESSION_ATTRIBUTE_CLASS.test(name):
|
|
27
32
|
setClasses(data, element, name, value);
|
|
@@ -39,7 +44,7 @@ export function setAttribute(
|
|
|
39
44
|
|
|
40
45
|
function setClasses(
|
|
41
46
|
data: FragmentData,
|
|
42
|
-
element:
|
|
47
|
+
element: HTMLElement | SVGElement,
|
|
43
48
|
name: string,
|
|
44
49
|
value: unknown,
|
|
45
50
|
): void {
|
|
@@ -62,7 +67,7 @@ function setClasses(
|
|
|
62
67
|
|
|
63
68
|
function setStyle(
|
|
64
69
|
data: FragmentData,
|
|
65
|
-
element:
|
|
70
|
+
element: HTMLElement | SVGElement,
|
|
66
71
|
name: string,
|
|
67
72
|
value: unknown,
|
|
68
73
|
): void {
|
|
@@ -76,10 +81,7 @@ function setStyle(
|
|
|
76
81
|
if (value == null || value === false || (value === true && unit == null)) {
|
|
77
82
|
element.style.removeProperty(property);
|
|
78
83
|
} else {
|
|
79
|
-
element.style.setProperty(
|
|
80
|
-
property,
|
|
81
|
-
value === true ? unit : getString(value),
|
|
82
|
-
);
|
|
84
|
+
element.style.setProperty(property, value === true ? unit : String(value));
|
|
83
85
|
}
|
|
84
86
|
}
|
|
85
87
|
|
|
@@ -92,21 +94,11 @@ function setStyle(
|
|
|
92
94
|
|
|
93
95
|
function setValue(
|
|
94
96
|
data: FragmentData,
|
|
95
|
-
element:
|
|
97
|
+
element: HTMLElement | SVGElement,
|
|
96
98
|
name: string,
|
|
97
99
|
value: unknown,
|
|
98
100
|
): void {
|
|
99
|
-
|
|
100
|
-
element: HTMLOrSVGElement,
|
|
101
|
-
name: string,
|
|
102
|
-
value: unknown,
|
|
103
|
-
) => void;
|
|
104
|
-
|
|
105
|
-
if (isBooleanAttribute(name) && name in element) {
|
|
106
|
-
callback = name === 'selected' ? updateSelected : updateProperty;
|
|
107
|
-
} else {
|
|
108
|
-
callback = setAttr;
|
|
109
|
-
}
|
|
101
|
+
const callback = getCallback(element, name);
|
|
110
102
|
|
|
111
103
|
if (isReactive(value)) {
|
|
112
104
|
data.mora.subscribers.add(
|
|
@@ -119,25 +111,40 @@ function setValue(
|
|
|
119
111
|
}
|
|
120
112
|
}
|
|
121
113
|
|
|
122
|
-
function
|
|
123
|
-
element
|
|
124
|
-
name: string,
|
|
125
|
-
value: unknown,
|
|
126
|
-
): void {
|
|
127
|
-
(element as unknown as PlainObject)[name] = value === true;
|
|
114
|
+
function updateChecked(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
115
|
+
updateElement('change', 'checked', element, name, value, value === true);
|
|
128
116
|
}
|
|
129
117
|
|
|
130
|
-
function
|
|
131
|
-
|
|
118
|
+
function updateElement(
|
|
119
|
+
event: string,
|
|
120
|
+
property: string,
|
|
121
|
+
element: HTMLElement | SVGElement,
|
|
132
122
|
name: string,
|
|
133
123
|
value: unknown,
|
|
124
|
+
next: unknown,
|
|
134
125
|
): void {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (select != null && options.includes(element as HTMLOptionElement)) {
|
|
139
|
-
select.dispatchEvent(new Event('change', {bubbles: true}));
|
|
126
|
+
if (!(property in element) || (element as unknown as PlainObject)[property] === next) {
|
|
127
|
+
return;
|
|
140
128
|
}
|
|
141
129
|
|
|
142
|
-
|
|
130
|
+
setAttr(element, name, value);
|
|
131
|
+
|
|
132
|
+
(element as unknown as PlainObject)[property] = next;
|
|
133
|
+
|
|
134
|
+
element.dispatchEvent(new Event(event, {bubbles: true}));
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function updateProperty(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
138
|
+
setProperty(element, name, value === true);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function updateValue(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
142
|
+
updateElement(
|
|
143
|
+
element instanceof HTMLSelectElement ? 'change' : 'input',
|
|
144
|
+
'value',
|
|
145
|
+
element,
|
|
146
|
+
name,
|
|
147
|
+
value,
|
|
148
|
+
String(value),
|
|
149
|
+
);
|
|
143
150
|
}
|
package/src/node/event.ts
CHANGED
|
@@ -1,50 +1,43 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {on} from '@oscarpalmer/toretto/event';
|
|
2
2
|
import {
|
|
3
|
-
|
|
3
|
+
EVENT_DEFAULTS,
|
|
4
|
+
EXPRESSION_EVENT_CHANGE_TYPES,
|
|
4
5
|
EXPRESSION_EVENT_NAME,
|
|
5
|
-
|
|
6
|
+
EXPRESSION_EVENT_OPTIONS_ACTIVE,
|
|
7
|
+
EXPRESSION_EVENT_OPTIONS_CAPTURE,
|
|
8
|
+
EXPRESSION_EVENT_OPTIONS_ONCE,
|
|
6
9
|
} from '../constants';
|
|
7
10
|
|
|
8
|
-
function getController(element: HTMLOrSVGElement): AbortController {
|
|
9
|
-
let controller = ABORT_CONTROLLERS.get(element);
|
|
10
|
-
|
|
11
|
-
if (controller == null) {
|
|
12
|
-
controller = new AbortController();
|
|
13
|
-
|
|
14
|
-
ABORT_CONTROLLERS.set(element, controller);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
return controller;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
11
|
function getOptions(options: string): AddEventListenerOptions {
|
|
21
12
|
const parts = options.split(':');
|
|
22
13
|
|
|
23
14
|
return {
|
|
24
|
-
capture: parts.
|
|
25
|
-
once: parts.
|
|
26
|
-
passive: !
|
|
15
|
+
capture: parts.some(part => EXPRESSION_EVENT_OPTIONS_CAPTURE.test(part)),
|
|
16
|
+
once: parts.some(part => EXPRESSION_EVENT_OPTIONS_ONCE.test(part)),
|
|
17
|
+
passive: !parts.some(part => EXPRESSION_EVENT_OPTIONS_ACTIVE.test(part)),
|
|
27
18
|
};
|
|
28
19
|
}
|
|
29
20
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
): void {
|
|
35
|
-
element.removeAttribute(name);
|
|
21
|
+
function getType(element: HTMLElement | SVGElement, type: string): string {
|
|
22
|
+
if (type !== 'on') {
|
|
23
|
+
return type;
|
|
24
|
+
}
|
|
36
25
|
|
|
37
|
-
|
|
26
|
+
if (element instanceof HTMLInputElement) {
|
|
27
|
+
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) {
|
|
28
|
+
return 'change';
|
|
29
|
+
}
|
|
38
30
|
|
|
39
|
-
|
|
40
|
-
element.addEventListener(type, value as EventListener, {
|
|
41
|
-
...getOptions(options ?? ''),
|
|
42
|
-
signal: getController(element).signal,
|
|
43
|
-
});
|
|
31
|
+
return element.type === 'submit' ? 'submit' : 'input';
|
|
44
32
|
}
|
|
33
|
+
|
|
34
|
+
return EVENT_DEFAULTS[element.tagName] ?? type;
|
|
45
35
|
}
|
|
46
36
|
|
|
47
|
-
export function
|
|
48
|
-
|
|
49
|
-
|
|
37
|
+
export function mapEvent(element: HTMLElement | SVGElement, name: string, value: unknown): void {
|
|
38
|
+
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name) ?? [];
|
|
39
|
+
|
|
40
|
+
if (type != null && typeof value === 'function') {
|
|
41
|
+
on(element, getType(element, type), value as EventListener, getOptions(options ?? ''));
|
|
42
|
+
}
|
|
50
43
|
}
|
package/src/node/index.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {computed, isReactive, Reactive} from '@oscarpalmer/mora';
|
|
2
|
+
import {computed, isReactive, type Reactive} from '@oscarpalmer/mora';
|
|
3
3
|
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
4
|
-
import {
|
|
4
|
+
import {EXPRESSION_ABYDON_CONTENT} from '../constants';
|
|
5
5
|
import {handleFragments} from '../fragments';
|
|
6
6
|
import {isFragment, isFragments} from '../helpers';
|
|
7
7
|
import {createNodes} from '../helpers/dom';
|
|
@@ -10,7 +10,7 @@ import {mapAttributes} from './attribute';
|
|
|
10
10
|
import {setReactiveValue} from './value';
|
|
11
11
|
|
|
12
12
|
function mapNode(data: FragmentData, comment: Comment): void {
|
|
13
|
-
const matches =
|
|
13
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent ?? '');
|
|
14
14
|
const value = matches == null ? null : data.values[+matches[1]];
|
|
15
15
|
|
|
16
16
|
if (value != null) {
|
|
@@ -48,11 +48,7 @@ function mapValue(data: FragmentData, comment: Comment, value: unknown): void {
|
|
|
48
48
|
|
|
49
49
|
case isFragments(value):
|
|
50
50
|
handleFragments(value, false);
|
|
51
|
-
setReactiveValue(
|
|
52
|
-
data,
|
|
53
|
-
comment,
|
|
54
|
-
value.items as Reactive<unknown[], unknown>,
|
|
55
|
-
);
|
|
51
|
+
setReactiveValue(data, comment, value.items as Reactive<unknown[], unknown>);
|
|
56
52
|
break;
|
|
57
53
|
|
|
58
54
|
case isReactive(value):
|
|
@@ -65,11 +61,7 @@ function mapValue(data: FragmentData, comment: Comment, value: unknown): void {
|
|
|
65
61
|
}
|
|
66
62
|
}
|
|
67
63
|
|
|
68
|
-
function replaceComment(
|
|
69
|
-
data: FragmentData,
|
|
70
|
-
comment: Comment,
|
|
71
|
-
value: unknown,
|
|
72
|
-
): void {
|
|
64
|
+
function replaceComment(data: FragmentData, comment: Comment, value: unknown): void {
|
|
73
65
|
const item = data.items.find(item => item.nodes?.includes(comment));
|
|
74
66
|
const nodes = createNodes(value);
|
|
75
67
|
|
|
@@ -81,11 +73,7 @@ function replaceComment(
|
|
|
81
73
|
comment.replaceWith(...nodes);
|
|
82
74
|
}
|
|
83
75
|
|
|
84
|
-
function setComputedValue(
|
|
85
|
-
data: FragmentData,
|
|
86
|
-
comment: Comment,
|
|
87
|
-
callback: GenericCallback,
|
|
88
|
-
): void {
|
|
76
|
+
function setComputedValue(data: FragmentData, comment: Comment, callback: GenericCallback): void {
|
|
89
77
|
const value = computed(callback);
|
|
90
78
|
|
|
91
79
|
data.mora.values.add(value);
|
package/src/node/value.ts
CHANGED
|
@@ -10,8 +10,8 @@ import type {FragmentData, FragmentItem} from '../models';
|
|
|
10
10
|
//
|
|
11
11
|
|
|
12
12
|
type Identifiers = {
|
|
13
|
-
next: unknown
|
|
14
|
-
previous:
|
|
13
|
+
next: Set<unknown>;
|
|
14
|
+
previous: Set<unknown>;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
type BaseItems = {
|
|
@@ -33,8 +33,7 @@ function addToArray(
|
|
|
33
33
|
): void {
|
|
34
34
|
let position = nodes[0];
|
|
35
35
|
|
|
36
|
-
const before =
|
|
37
|
-
added && !identifiers.previous.includes(items.templates[0].identifier);
|
|
36
|
+
const before = added && !identifiers.previous.has(items.templates[0].identifier);
|
|
38
37
|
|
|
39
38
|
const next = items.next.flatMap(fragment =>
|
|
40
39
|
fragment.get().flatMap(node => ({
|
|
@@ -48,7 +47,7 @@ function addToArray(
|
|
|
48
47
|
for (let index = 0; index < length; index += 1) {
|
|
49
48
|
const node = next[index];
|
|
50
49
|
|
|
51
|
-
if (!(added && identifiers.previous.
|
|
50
|
+
if (!(added && identifiers.previous.has(node.identifier))) {
|
|
52
51
|
if (index === 0 && before) {
|
|
53
52
|
position.before(node.value);
|
|
54
53
|
} else {
|
|
@@ -67,9 +66,7 @@ function handleArray(
|
|
|
67
66
|
): Partial<FragmentItem> {
|
|
68
67
|
const next = items.templates.map(
|
|
69
68
|
template =>
|
|
70
|
-
items.fragments?.find(
|
|
71
|
-
fragment => fragment.identifier === template.identifier,
|
|
72
|
-
) ?? template,
|
|
69
|
+
items.fragments?.find(fragment => fragment.identifier === template.identifier) ?? template,
|
|
73
70
|
);
|
|
74
71
|
|
|
75
72
|
const comparison = compareArrays(items.fragments ?? [], items.templates);
|
|
@@ -79,9 +76,7 @@ function handleArray(
|
|
|
79
76
|
}
|
|
80
77
|
|
|
81
78
|
const toRemove =
|
|
82
|
-
items.fragments?.filter(
|
|
83
|
-
fragment => !identifiers.next.includes(fragment.identifier),
|
|
84
|
-
) ?? [];
|
|
79
|
+
items.fragments?.filter(fragment => !identifiers.next.has(fragment.identifier)) ?? [];
|
|
85
80
|
|
|
86
81
|
const {length} = toRemove;
|
|
87
82
|
|
|
@@ -105,11 +100,7 @@ function removeFragments(fragments: Fragment[] | undefined): void {
|
|
|
105
100
|
}
|
|
106
101
|
}
|
|
107
102
|
|
|
108
|
-
function replaceText(
|
|
109
|
-
item: FragmentItem,
|
|
110
|
-
comment: Comment,
|
|
111
|
-
isNullable: boolean,
|
|
112
|
-
): void {
|
|
103
|
+
function replaceText(item: FragmentItem, comment: Comment, isNullable: boolean): void {
|
|
113
104
|
let to: ChildNode[];
|
|
114
105
|
|
|
115
106
|
if (isNullable) {
|
|
@@ -132,9 +123,7 @@ function setArray(
|
|
|
132
123
|
};
|
|
133
124
|
}
|
|
134
125
|
|
|
135
|
-
let templates = value.filter(
|
|
136
|
-
item => isFragment(item) && item.identifier != null,
|
|
137
|
-
) as Fragment[];
|
|
126
|
+
let templates = value.filter(item => isFragment(item) && item.identifier != null) as Fragment[];
|
|
138
127
|
|
|
139
128
|
const next = templates.map(fragment => fragment.identifier) as unknown[];
|
|
140
129
|
const previous = item.fragments?.map(fragment => fragment.identifier) ?? [];
|
|
@@ -145,11 +134,7 @@ function setArray(
|
|
|
145
134
|
|
|
146
135
|
const noTemplates = templates.length === 0;
|
|
147
136
|
|
|
148
|
-
if (
|
|
149
|
-
noTemplates ||
|
|
150
|
-
item.nodes == null ||
|
|
151
|
-
previous.some(identifier => identifier == null)
|
|
152
|
-
) {
|
|
137
|
+
if (noTemplates || item.nodes == null || previous.some(identifier => identifier == null)) {
|
|
153
138
|
return {
|
|
154
139
|
fragments: noTemplates ? undefined : templates,
|
|
155
140
|
nodes: setNodes(
|
|
@@ -164,8 +149,8 @@ function setArray(
|
|
|
164
149
|
|
|
165
150
|
return handleArray(
|
|
166
151
|
{
|
|
167
|
-
next,
|
|
168
|
-
previous,
|
|
152
|
+
next: new Set(next),
|
|
153
|
+
previous: new Set(previous),
|
|
169
154
|
},
|
|
170
155
|
{
|
|
171
156
|
templates,
|
|
@@ -175,11 +160,7 @@ function setArray(
|
|
|
175
160
|
);
|
|
176
161
|
}
|
|
177
162
|
|
|
178
|
-
function setNodes(
|
|
179
|
-
item: FragmentItem,
|
|
180
|
-
comment: Comment,
|
|
181
|
-
next: ChildNode[],
|
|
182
|
-
): ChildNode[] {
|
|
163
|
+
function setNodes(item: FragmentItem, comment: Comment, next: ChildNode[]): ChildNode[] {
|
|
183
164
|
if (item.nodes == null) {
|
|
184
165
|
if (comment.parentNode != null) {
|
|
185
166
|
replaceNodes([comment], next);
|
|
@@ -219,11 +200,7 @@ export function setReactiveValue(
|
|
|
219
200
|
);
|
|
220
201
|
}
|
|
221
202
|
|
|
222
|
-
function setReactiveValueForArray(
|
|
223
|
-
item: FragmentItem,
|
|
224
|
-
comment: Comment,
|
|
225
|
-
value: unknown[],
|
|
226
|
-
): void {
|
|
203
|
+
function setReactiveValueForArray(item: FragmentItem, comment: Comment, value: unknown[]): void {
|
|
227
204
|
const result = setArray(item, comment, value);
|
|
228
205
|
|
|
229
206
|
item.fragments = typeof result === 'boolean' ? undefined : result?.fragments;
|
|
@@ -239,11 +216,7 @@ function setReactiveValueForArray(
|
|
|
239
216
|
}
|
|
240
217
|
}
|
|
241
218
|
|
|
242
|
-
function setReactiveValueForSingle(
|
|
243
|
-
item: FragmentItem,
|
|
244
|
-
comment: Comment,
|
|
245
|
-
value: unknown,
|
|
246
|
-
): void {
|
|
219
|
+
function setReactiveValueForSingle(item: FragmentItem, comment: Comment, value: unknown): void {
|
|
247
220
|
const valueIsFragment = isFragment(value);
|
|
248
221
|
|
|
249
222
|
item.fragments = valueIsFragment ? [value] : undefined;
|
|
@@ -255,11 +228,7 @@ function setReactiveValueForSingle(
|
|
|
255
228
|
}
|
|
256
229
|
}
|
|
257
230
|
|
|
258
|
-
function setText(
|
|
259
|
-
item: FragmentItem,
|
|
260
|
-
comment: Comment,
|
|
261
|
-
value: unknown,
|
|
262
|
-
): ChildNode[] | undefined {
|
|
231
|
+
function setText(item: FragmentItem, comment: Comment, value: unknown): ChildNode[] | undefined {
|
|
263
232
|
const isNullable = isNullableOrWhitespace(value);
|
|
264
233
|
|
|
265
234
|
if (item.text != null) {
|