@oscarpalmer/abydon 0.12.0 → 0.14.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 +1153 -0
- package/dist/constants.js +10 -0
- package/dist/fragment.js +60 -0
- package/dist/helpers/dom.js +28 -0
- package/dist/helpers/index.js +11 -0
- package/dist/index.js +6 -911
- package/dist/node/attribute/index.js +39 -0
- package/dist/node/attribute/value.js +56 -0
- package/dist/node/event.js +30 -0
- package/dist/node/index.js +52 -0
- package/dist/node/value.js +108 -0
- package/dist/parse.js +18 -0
- package/package.json +38 -27
- package/src/constants.ts +20 -0
- package/src/fragment.ts +63 -36
- package/src/helpers/dom.ts +5 -4
- package/src/helpers/index.ts +0 -9
- package/src/index.ts +13 -3
- package/src/models.ts +14 -11
- package/src/node/attribute/index.ts +28 -22
- package/src/node/attribute/value.ts +38 -42
- package/src/node/event.ts +12 -13
- package/src/node/index.ts +7 -7
- package/src/node/value.ts +169 -122
- package/src/{html.ts → parse.ts} +15 -17
- package/types/constants.d.ts +9 -0
- package/types/fragment.d.ts +3 -5
- package/types/helpers/index.d.ts +0 -3
- package/types/index.d.ts +4 -2
- package/types/models.d.ts +7 -9
- package/types/node/attribute/index.d.ts +2 -1
- package/types/node/attribute/value.d.ts +2 -1
- package/types/node/event.d.ts +1 -1
- package/types/node/value.d.ts +2 -2
- package/types/parse.d.ts +2 -0
- package/dist/fragment.mjs +0 -75
- package/dist/helpers/dom.mjs +0 -44
- package/dist/helpers/index.mjs +0 -25
- package/dist/html.mjs +0 -36
- package/dist/index.mjs +0 -6
- package/dist/node/attribute/index.mjs +0 -40
- package/dist/node/attribute/value.mjs +0 -89
- package/dist/node/event.mjs +0 -38
- package/dist/node/index.mjs +0 -60
- package/dist/node/value.mjs +0 -123
- package/types/html.d.ts +0 -4
- package/types/index.d.cts +0 -26
- /package/dist/{models.mjs → models.js} +0 -0
package/src/models.ts
CHANGED
|
@@ -1,24 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {Effect, Reactive} from '@oscarpalmer/sentinel';
|
|
1
|
+
import type {Reactive} from '@oscarpalmer/mora';
|
|
3
2
|
import type {Fragment} from './fragment';
|
|
4
3
|
|
|
4
|
+
export type FragmentConfiguration = {
|
|
5
|
+
identifier?: unknown;
|
|
6
|
+
ignoreCache?: boolean;
|
|
7
|
+
};
|
|
8
|
+
|
|
5
9
|
export type FragmentData = {
|
|
6
10
|
expressions: unknown[];
|
|
7
|
-
identifier?: Key;
|
|
8
11
|
items: FragmentItem[];
|
|
9
|
-
|
|
12
|
+
mora: MoraData;
|
|
10
13
|
strings: TemplateStringsArray;
|
|
14
|
+
template?: string;
|
|
11
15
|
values: unknown[];
|
|
12
16
|
};
|
|
13
17
|
|
|
14
|
-
type FragmentDataSentinel = {
|
|
15
|
-
effects: Set<Effect>;
|
|
16
|
-
values: Set<Reactive>;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
18
|
export type FragmentItem = {
|
|
20
19
|
fragments?: Fragment[];
|
|
21
|
-
nodes
|
|
20
|
+
nodes?: ChildNode[];
|
|
21
|
+
text?: Text;
|
|
22
22
|
};
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
type MoraData = {
|
|
25
|
+
subscribers: Set<() => void>;
|
|
26
|
+
values: Set<Reactive<unknown>>;
|
|
27
|
+
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {computed, isReactive} from '@oscarpalmer/
|
|
3
|
-
import
|
|
2
|
+
import {computed, isReactive} from '@oscarpalmer/mora';
|
|
3
|
+
import {isBooleanAttribute, setProperty} from '@oscarpalmer/toretto/attribute';
|
|
4
|
+
import type {HTMLOrSVGElement} from '@oscarpalmer/toretto/models';
|
|
5
|
+
import {EXPRESSION_COMMENT_FULL} from '../../constants';
|
|
6
|
+
import type {FragmentData} from '../../models';
|
|
4
7
|
import {mapEvent} from '../event';
|
|
5
8
|
import {setAttribute} from './value';
|
|
6
9
|
|
|
7
|
-
const commentExpression = /^<!--abydon\.(\d+)-->$/;
|
|
8
|
-
|
|
9
10
|
function getValue(data: FragmentData, original: string): unknown {
|
|
10
|
-
const matches =
|
|
11
|
+
const matches = EXPRESSION_COMMENT_FULL.exec(original ?? '');
|
|
11
12
|
|
|
12
13
|
return matches == null ? original : data.values[+matches[1]];
|
|
13
14
|
}
|
|
@@ -24,14 +25,23 @@ export function mapAttributes(
|
|
|
24
25
|
|
|
25
26
|
const actual = getValue(data, value);
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
switch (true) {
|
|
29
|
+
case name.startsWith('@'):
|
|
30
|
+
mapEvent(element, name, actual);
|
|
31
|
+
break;
|
|
32
|
+
|
|
33
|
+
case name.includes('.') ||
|
|
34
|
+
typeof actual === 'function' ||
|
|
35
|
+
isReactive(actual):
|
|
36
|
+
mapValue(data, element, name, actual);
|
|
37
|
+
break;
|
|
38
|
+
|
|
39
|
+
case isBooleanAttribute(name):
|
|
40
|
+
setProperty(element, name, value);
|
|
41
|
+
break;
|
|
42
|
+
|
|
43
|
+
default:
|
|
44
|
+
break;
|
|
35
45
|
}
|
|
36
46
|
}
|
|
37
47
|
}
|
|
@@ -42,14 +52,10 @@ function mapValue(
|
|
|
42
52
|
name: string,
|
|
43
53
|
value: unknown,
|
|
44
54
|
): void {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
default:
|
|
51
|
-
setAttribute(data, element, name, value);
|
|
52
|
-
break;
|
|
55
|
+
if (typeof value === 'function') {
|
|
56
|
+
setComputedAttribute(data, element, name, value as GenericCallback);
|
|
57
|
+
} else {
|
|
58
|
+
setAttribute(data, element, name, value);
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
|
|
@@ -61,7 +67,7 @@ function setComputedAttribute(
|
|
|
61
67
|
): void {
|
|
62
68
|
const value = computed(callback);
|
|
63
69
|
|
|
64
|
-
data.
|
|
70
|
+
data.mora.values.add(value);
|
|
65
71
|
|
|
66
72
|
setAttribute(data, element, name, value);
|
|
67
73
|
}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import type {PlainObject} from '@oscarpalmer/atoms/models';
|
|
2
2
|
import {getString} from '@oscarpalmer/atoms/string';
|
|
3
|
-
import {
|
|
3
|
+
import {isReactive} from '@oscarpalmer/mora';
|
|
4
4
|
import {
|
|
5
5
|
isBooleanAttribute,
|
|
6
6
|
setAttribute as setAttr,
|
|
7
7
|
} from '@oscarpalmer/toretto/attribute';
|
|
8
|
-
import type {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
import type {HTMLOrSVGElement} from '@oscarpalmer/toretto/models';
|
|
9
|
+
import {
|
|
10
|
+
ATTRIBUTE_CLASS_PREFIX_LENGTH,
|
|
11
|
+
EXPRESSION_ATTRIBUTE_CLASS,
|
|
12
|
+
EXPRESSION_ATTRIBUTE_STYLE_FULL,
|
|
13
|
+
EXPRESSION_ATTRIBUTE_STYLE_PREFIX,
|
|
14
|
+
} from '../../constants';
|
|
15
|
+
import type {FragmentData} from '../../models';
|
|
13
16
|
|
|
14
17
|
export function setAttribute(
|
|
15
18
|
data: FragmentData,
|
|
@@ -20,11 +23,11 @@ export function setAttribute(
|
|
|
20
23
|
element.removeAttribute(name);
|
|
21
24
|
|
|
22
25
|
switch (true) {
|
|
23
|
-
case
|
|
26
|
+
case EXPRESSION_ATTRIBUTE_CLASS.test(name):
|
|
24
27
|
setClasses(data, element, name, value);
|
|
25
28
|
return;
|
|
26
29
|
|
|
27
|
-
case
|
|
30
|
+
case EXPRESSION_ATTRIBUTE_STYLE_PREFIX.test(name):
|
|
28
31
|
setStyle(data, element, name, value);
|
|
29
32
|
return;
|
|
30
33
|
|
|
@@ -48,14 +51,10 @@ function setClasses(
|
|
|
48
51
|
}
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
const classes = name.slice(
|
|
54
|
+
const classes = name.slice(ATTRIBUTE_CLASS_PREFIX_LENGTH).split('.');
|
|
52
55
|
|
|
53
56
|
if (isReactive(value)) {
|
|
54
|
-
data.
|
|
55
|
-
effect(() => {
|
|
56
|
-
update(value.get());
|
|
57
|
-
}),
|
|
58
|
-
);
|
|
57
|
+
data.mora.subscribers.add(value.subscribe(update));
|
|
59
58
|
} else {
|
|
60
59
|
update(value);
|
|
61
60
|
}
|
|
@@ -67,6 +66,12 @@ function setStyle(
|
|
|
67
66
|
name: string,
|
|
68
67
|
value: unknown,
|
|
69
68
|
): void {
|
|
69
|
+
const [, property, unit] = EXPRESSION_ATTRIBUTE_STYLE_FULL.exec(name) ?? [];
|
|
70
|
+
|
|
71
|
+
if (property == null) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
|
|
70
75
|
function update(value: unknown): void {
|
|
71
76
|
if (value == null || value === false || (value === true && unit == null)) {
|
|
72
77
|
element.style.removeProperty(property);
|
|
@@ -78,18 +83,10 @@ function setStyle(
|
|
|
78
83
|
}
|
|
79
84
|
}
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
data.sentinel.effects.add(
|
|
86
|
-
effect(() => {
|
|
87
|
-
update(value.get());
|
|
88
|
-
}),
|
|
89
|
-
);
|
|
90
|
-
} else {
|
|
91
|
-
update(value);
|
|
92
|
-
}
|
|
86
|
+
if (isReactive(value)) {
|
|
87
|
+
data.mora.subscribers.add(value.subscribe(update));
|
|
88
|
+
} else {
|
|
89
|
+
update(value);
|
|
93
90
|
}
|
|
94
91
|
}
|
|
95
92
|
|
|
@@ -99,17 +96,22 @@ function setValue(
|
|
|
99
96
|
name: string,
|
|
100
97
|
value: unknown,
|
|
101
98
|
): void {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
99
|
+
let callback: (
|
|
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
|
+
}
|
|
108
110
|
|
|
109
111
|
if (isReactive(value)) {
|
|
110
|
-
data.
|
|
111
|
-
|
|
112
|
-
callback(element, name,
|
|
112
|
+
data.mora.subscribers.add(
|
|
113
|
+
value.subscribe(next => {
|
|
114
|
+
callback(element, name, next);
|
|
113
115
|
}),
|
|
114
116
|
);
|
|
115
117
|
} else {
|
|
@@ -117,12 +119,6 @@ function setValue(
|
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
function triggerSelectChange(select: HTMLSelectElement): void {
|
|
121
|
-
if (select != null) {
|
|
122
|
-
select.dispatchEvent(new Event('change', {bubbles: true}));
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
|
|
126
122
|
function updateProperty(
|
|
127
123
|
element: HTMLOrSVGElement,
|
|
128
124
|
name: string,
|
|
@@ -140,7 +136,7 @@ function updateSelected(
|
|
|
140
136
|
const options = [...(select?.options ?? [])];
|
|
141
137
|
|
|
142
138
|
if (select != null && options.includes(element as HTMLOptionElement)) {
|
|
143
|
-
|
|
139
|
+
select.dispatchEvent(new Event('change', {bubbles: true}));
|
|
144
140
|
}
|
|
145
141
|
|
|
146
142
|
updateProperty(element, name, value);
|
package/src/node/event.ts
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
import type {HTMLOrSVGElement} from '
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const reason = 'Event removed as element was removed from document by Abydon';
|
|
1
|
+
import type {HTMLOrSVGElement} from '@oscarpalmer/toretto/models';
|
|
2
|
+
import {
|
|
3
|
+
ABORT_CONTROLLERS,
|
|
4
|
+
EXPRESSION_EVENT_NAME,
|
|
5
|
+
REASON_EVENT_REMOVED,
|
|
6
|
+
} from '../constants';
|
|
8
7
|
|
|
9
8
|
function getController(element: HTMLOrSVGElement): AbortController {
|
|
10
|
-
let controller =
|
|
9
|
+
let controller = ABORT_CONTROLLERS.get(element);
|
|
11
10
|
|
|
12
11
|
if (controller == null) {
|
|
13
12
|
controller = new AbortController();
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
ABORT_CONTROLLERS.set(element, controller);
|
|
16
15
|
}
|
|
17
16
|
|
|
18
17
|
return controller;
|
|
@@ -24,7 +23,7 @@ function getOptions(options: string): AddEventListenerOptions {
|
|
|
24
23
|
return {
|
|
25
24
|
capture: parts.includes('c') || parts.includes('capture'),
|
|
26
25
|
once: parts.includes('o') || parts.includes('once'),
|
|
27
|
-
passive: !parts.includes('a')
|
|
26
|
+
passive: !(parts.includes('a') || parts.includes('active')),
|
|
28
27
|
};
|
|
29
28
|
}
|
|
30
29
|
|
|
@@ -35,7 +34,7 @@ export function mapEvent(
|
|
|
35
34
|
): void {
|
|
36
35
|
element.removeAttribute(name);
|
|
37
36
|
|
|
38
|
-
const [, type, options] =
|
|
37
|
+
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name) ?? [];
|
|
39
38
|
|
|
40
39
|
if (typeof value === 'function' && type != null) {
|
|
41
40
|
element.addEventListener(type, value as EventListener, {
|
|
@@ -46,6 +45,6 @@ export function mapEvent(
|
|
|
46
45
|
}
|
|
47
46
|
|
|
48
47
|
export function removeEvents(element: HTMLOrSVGElement): void {
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
ABORT_CONTROLLERS.get(element)?.abort(REASON_EVENT_REMOVED);
|
|
49
|
+
ABORT_CONTROLLERS.delete(element);
|
|
51
50
|
}
|
package/src/node/index.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type {GenericCallback} from '@oscarpalmer/atoms/models';
|
|
2
|
-
import {computed, isReactive} from '@oscarpalmer/
|
|
3
|
-
import {
|
|
2
|
+
import {computed, isReactive} from '@oscarpalmer/mora';
|
|
3
|
+
import {isHTMLOrSVGElement} from '@oscarpalmer/toretto/is';
|
|
4
|
+
import {EXPRESSION_COMMENT_CONTENT} from '../constants';
|
|
5
|
+
import {isFragment} from '../helpers';
|
|
4
6
|
import {createNodes} from '../helpers/dom';
|
|
5
7
|
import type {FragmentData} from '../models';
|
|
6
8
|
import {mapAttributes} from './attribute';
|
|
7
9
|
import {setReactiveValue} from './value';
|
|
8
10
|
|
|
9
|
-
const commentExpression = /^abydon\.(\d+)$/;
|
|
10
|
-
|
|
11
11
|
function mapNode(data: FragmentData, comment: Comment): void {
|
|
12
|
-
const matches =
|
|
12
|
+
const matches = EXPRESSION_COMMENT_CONTENT.exec(comment.textContent ?? '');
|
|
13
13
|
const value = matches == null ? null : data.values[+matches[1]];
|
|
14
14
|
|
|
15
15
|
if (value != null) {
|
|
@@ -60,7 +60,7 @@ function replaceComment(
|
|
|
60
60
|
comment: Comment,
|
|
61
61
|
value: unknown,
|
|
62
62
|
): void {
|
|
63
|
-
const item = data.items.find(item => item.nodes
|
|
63
|
+
const item = data.items.find(item => item.nodes?.includes(comment));
|
|
64
64
|
const nodes = createNodes(value);
|
|
65
65
|
|
|
66
66
|
if (item != null) {
|
|
@@ -78,7 +78,7 @@ function setComputedValue(
|
|
|
78
78
|
): void {
|
|
79
79
|
const value = computed(callback);
|
|
80
80
|
|
|
81
|
-
data.
|
|
81
|
+
data.mora.values.add(value);
|
|
82
82
|
|
|
83
83
|
setReactiveValue(data, comment, value);
|
|
84
84
|
}
|