@oscarpalmer/abydon 0.14.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 +814 -645
- package/dist/constants.js +20 -5
- package/dist/fragment.js +31 -12
- package/dist/fragments.js +75 -0
- package/dist/helpers/dom.js +1 -11
- package/dist/helpers/index.js +14 -4
- package/dist/index.js +7 -3
- 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 +9 -4
- package/dist/node/value.js +49 -44
- package/dist/parse.js +15 -4
- package/package.json +13 -15
- package/src/constants.ts +30 -10
- package/src/fragment.ts +53 -30
- package/src/fragments.ts +132 -0
- package/src/helpers/dom.ts +1 -20
- package/src/helpers/index.ts +22 -9
- package/src/index.ts +26 -8
- package/src/models.ts +20 -2
- 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 +12 -14
- package/src/node/value.ts +35 -44
- package/src/parse.ts +15 -17
- package/types/constants.d.ts +12 -4
- 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 +16 -1
- package/types/models.d.ts +25 -3
- 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/dist/constants.js
CHANGED
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
const ABORT_CONTROLLERS = /* @__PURE__ */ new WeakMap();
|
|
2
1
|
const ATTRIBUTE_CLASS_PREFIX_LENGTH = 6;
|
|
2
|
+
const EVENT_DEFAULTS = {
|
|
3
|
+
A: "click",
|
|
4
|
+
BUTTON: "click",
|
|
5
|
+
DETAILS: "toggle",
|
|
6
|
+
FORM: "submit",
|
|
7
|
+
SELECT: "change",
|
|
8
|
+
TEXTAREA: "input"
|
|
9
|
+
};
|
|
10
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_FULL = /(@?\w+)="<!--abydon.(\d+)-->"/g;
|
|
11
|
+
const EXPRESSION_ABYDON_ATTRIBUTE_PREFIX = /^_/;
|
|
12
|
+
const EXPRESSION_ABYDON_CONTENT = /^@?abydon\.(\d+)@?$/;
|
|
3
13
|
const EXPRESSION_ATTRIBUTE_CLASS = /^class\./;
|
|
4
14
|
const EXPRESSION_ATTRIBUTE_STYLE_FULL = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
|
|
5
15
|
const EXPRESSION_ATTRIBUTE_STYLE_PREFIX = /^style\./;
|
|
6
|
-
const
|
|
7
|
-
const EXPRESSION_COMMENT_CONTENT = /^abydon\.(\d+)$/;
|
|
16
|
+
const EXPRESSION_EVENT_CHANGE_TYPES = /^(checkbox|radio)$/;
|
|
8
17
|
const EXPRESSION_EVENT_NAME = /^@([\w-]+)(?::([a-z:]+))?$/i;
|
|
9
|
-
const
|
|
10
|
-
|
|
18
|
+
const EXPRESSION_EVENT_OPTIONS_ACTIVE = /^a(ctive)$/i;
|
|
19
|
+
const EXPRESSION_EVENT_OPTIONS_CAPTURE = /^c(apture)$/i;
|
|
20
|
+
const EXPRESSION_EVENT_OPTIONS_ONCE = /^o(nce)$/i;
|
|
21
|
+
const EXPRESSION_EVENT_PREFIX = /^@/;
|
|
22
|
+
const EXPRESSION_PERIOD = /\./;
|
|
23
|
+
const NAME_FRAGMENT = "$fragment";
|
|
24
|
+
const NAME_FRAGMENTS = "$fragments";
|
|
25
|
+
export { ATTRIBUTE_CLASS_PREFIX_LENGTH, EVENT_DEFAULTS, EXPRESSION_ABYDON_ATTRIBUTE_FULL, EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD, NAME_FRAGMENT, NAME_FRAGMENTS };
|
package/dist/fragment.js
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NAME_FRAGMENT } from "./constants.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 { parse } from "./parse.js";
|
|
7
|
+
import { isPlainObject } from "@oscarpalmer/atoms/is";
|
|
4
8
|
import { html } from "@oscarpalmer/toretto/html";
|
|
5
9
|
var Fragment = class {
|
|
6
10
|
#data;
|
|
11
|
+
#configuration = {
|
|
12
|
+
identifier: void 0,
|
|
13
|
+
cache: true
|
|
14
|
+
};
|
|
7
15
|
get identifier() {
|
|
8
|
-
return this.#
|
|
16
|
+
return this.#configuration.identifier;
|
|
9
17
|
}
|
|
10
18
|
constructor(strings, expressions) {
|
|
19
|
+
Object.defineProperty(this, NAME_FRAGMENT, { value: true });
|
|
11
20
|
this.#data = {
|
|
12
21
|
expressions,
|
|
13
22
|
strings,
|
|
@@ -18,22 +27,27 @@ var Fragment = class {
|
|
|
18
27
|
},
|
|
19
28
|
values: []
|
|
20
29
|
};
|
|
21
|
-
Object.defineProperty(this, "$fragment", { value: true });
|
|
22
30
|
}
|
|
23
31
|
appendTo(element) {
|
|
24
32
|
element.append(...this.get());
|
|
25
33
|
}
|
|
34
|
+
configure(configuration) {
|
|
35
|
+
const actual = isPlainObject(configuration) ? configuration : {};
|
|
36
|
+
if ("identifier" in actual) this.#configuration.identifier = actual.identifier;
|
|
37
|
+
if (typeof actual.cache === "boolean") this.#configuration.cache = actual.cache;
|
|
38
|
+
return this;
|
|
39
|
+
}
|
|
26
40
|
get() {
|
|
27
41
|
const data = this.#data;
|
|
28
42
|
if (data.items.length === 0) {
|
|
29
|
-
const templated = html(parse(data), {
|
|
43
|
+
const templated = html(parse(data), { cache: this.#configuration.cache });
|
|
30
44
|
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));
|
|
45
|
+
mapNodes(data, data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []));
|
|
32
46
|
}
|
|
33
|
-
return
|
|
47
|
+
return data.items.flatMap((item) => item.fragments?.flatMap((fragment) => fragment.get()) ?? item.nodes ?? []);
|
|
34
48
|
}
|
|
35
49
|
identify(identifier) {
|
|
36
|
-
this.#
|
|
50
|
+
this.#configuration.identifier = identifier;
|
|
37
51
|
return this;
|
|
38
52
|
}
|
|
39
53
|
remove() {
|
|
@@ -42,14 +56,19 @@ var Fragment = class {
|
|
|
42
56
|
};
|
|
43
57
|
function removeFragment(data) {
|
|
44
58
|
removeMora(data);
|
|
45
|
-
|
|
59
|
+
let { length } = data.items;
|
|
46
60
|
for (let index = 0; index < length; index += 1) {
|
|
47
61
|
const { fragments, nodes } = data.items[index];
|
|
48
|
-
const
|
|
49
|
-
for (let
|
|
50
|
-
removeNodes(nodes);
|
|
62
|
+
const fragmentsLength = fragments?.length ?? 0;
|
|
63
|
+
for (let fragmentIndex = 0; fragmentIndex < fragmentsLength; fragmentIndex += 1) fragments?.[fragmentIndex]?.remove();
|
|
64
|
+
removeNodes(nodes ?? []);
|
|
65
|
+
}
|
|
66
|
+
data.items.length = 0;
|
|
67
|
+
length = data.values.length;
|
|
68
|
+
for (let index = 0; index < length; index += 1) {
|
|
69
|
+
const value = data.values[index];
|
|
70
|
+
if (isFragments(value)) handleFragments(value, true);
|
|
51
71
|
}
|
|
52
|
-
data.items.splice(0, length);
|
|
53
72
|
}
|
|
54
73
|
function removeMora(data) {
|
|
55
74
|
const unsubscribers = [...data.mora.subscribers];
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { NAME_FRAGMENTS } from "./constants.js";
|
|
2
|
+
import { isFragment, isFragments } from "./helpers/index.js";
|
|
3
|
+
import { getString } from "@oscarpalmer/atoms/string";
|
|
4
|
+
import { array } from "@oscarpalmer/mora";
|
|
5
|
+
var Fragments = class {
|
|
6
|
+
#state;
|
|
7
|
+
get items() {
|
|
8
|
+
return this.#state.mapped;
|
|
9
|
+
}
|
|
10
|
+
constructor(items, identify, fragment) {
|
|
11
|
+
Object.defineProperty(this, NAME_FRAGMENTS, { value: true });
|
|
12
|
+
this.#state = {
|
|
13
|
+
fragment,
|
|
14
|
+
identify,
|
|
15
|
+
array: items,
|
|
16
|
+
instances: {},
|
|
17
|
+
mapped: array([]),
|
|
18
|
+
subscriber: void 0
|
|
19
|
+
};
|
|
20
|
+
states.set(this, this.#state);
|
|
21
|
+
initializeFragments(this.#state);
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
function handleFragments(item, remove) {
|
|
25
|
+
const state = isFragments(item) ? states.get(item) : item;
|
|
26
|
+
if (state != null) (remove ? removeFragments : initializeFragments)(state);
|
|
27
|
+
}
|
|
28
|
+
function handleItems(state, items) {
|
|
29
|
+
const keys = /* @__PURE__ */ new Set();
|
|
30
|
+
const mapped = [];
|
|
31
|
+
const { length } = items;
|
|
32
|
+
for (let index = 0; index < length; index += 1) {
|
|
33
|
+
const item = items[index];
|
|
34
|
+
const identifier = state.identify(item);
|
|
35
|
+
if (identifier == null) throw new Error("Identifier cannot be null or undefined");
|
|
36
|
+
const key = getString(identifier);
|
|
37
|
+
if (keys.has(key)) throw new Error(`Duplicate identifier found: "${key}"`);
|
|
38
|
+
let instance = state.instances[key];
|
|
39
|
+
if (instance == null) {
|
|
40
|
+
instance = state.fragment(item);
|
|
41
|
+
if (!isFragment(instance)) throw new Error("Fragment function must return a Fragment instance");
|
|
42
|
+
}
|
|
43
|
+
instance.identify(key);
|
|
44
|
+
state.instances[key] = instance;
|
|
45
|
+
keys.add(key);
|
|
46
|
+
mapped.push(instance);
|
|
47
|
+
}
|
|
48
|
+
state.mapped.set(mapped);
|
|
49
|
+
updateFragments(state, keys);
|
|
50
|
+
}
|
|
51
|
+
function initializeFragments(state) {
|
|
52
|
+
state.subscriber ??= state.array.subscribe((items) => {
|
|
53
|
+
handleItems(state, items);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
function removeFragments(state) {
|
|
57
|
+
state.subscriber?.();
|
|
58
|
+
updateFragments(state);
|
|
59
|
+
state.subscriber = void 0;
|
|
60
|
+
}
|
|
61
|
+
function updateFragments(state, active) {
|
|
62
|
+
const next = {};
|
|
63
|
+
const previous = { ...state.instances };
|
|
64
|
+
const keys = Object.keys(previous);
|
|
65
|
+
const { length } = keys;
|
|
66
|
+
for (let index = 0; index < length; index += 1) {
|
|
67
|
+
const key = keys[index];
|
|
68
|
+
if (active?.has(key)) next[key] = previous[key];
|
|
69
|
+
else previous[key].remove();
|
|
70
|
+
}
|
|
71
|
+
state.instances = next;
|
|
72
|
+
active?.clear();
|
|
73
|
+
}
|
|
74
|
+
var states = /* @__PURE__ */ new WeakMap();
|
|
75
|
+
export { Fragments, handleFragments, initializeFragments };
|
package/dist/helpers/dom.js
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { removeEvents } from "../node/event.js";
|
|
2
1
|
import { isFragment } from "./index.js";
|
|
3
2
|
import { getString } from "@oscarpalmer/atoms/string";
|
|
4
|
-
import { isChildNode
|
|
3
|
+
import { isChildNode } from "@oscarpalmer/toretto/is";
|
|
5
4
|
function createNodes(value) {
|
|
6
5
|
if (isFragment(value)) return value.get();
|
|
7
6
|
if (isChildNode(value)) return [value];
|
|
8
7
|
return [new Text(getString(value))];
|
|
9
8
|
}
|
|
10
9
|
function removeNodes(nodes) {
|
|
11
|
-
sanitizeNodes(nodes);
|
|
12
10
|
const { length } = nodes;
|
|
13
11
|
for (let index = 0; index < length; index += 1) nodes[index].remove();
|
|
14
12
|
}
|
|
@@ -17,12 +15,4 @@ function replaceNodes(from, to) {
|
|
|
17
15
|
const { length } = from;
|
|
18
16
|
for (let index = 1; index < length; index += 1) from[index].remove();
|
|
19
17
|
}
|
|
20
|
-
function sanitizeNodes(nodes) {
|
|
21
|
-
const { length } = nodes;
|
|
22
|
-
for (let index = 0; index < length; index += 1) {
|
|
23
|
-
const node = nodes[index];
|
|
24
|
-
if (isHTMLOrSVGElement(node)) removeEvents(node);
|
|
25
|
-
if (node.hasChildNodes()) sanitizeNodes([...node.childNodes]);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
18
|
export { createNodes, removeNodes, replaceNodes };
|
package/dist/helpers/index.js
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
|
+
import { NAME_FRAGMENT, NAME_FRAGMENTS } from "../constants.js";
|
|
1
2
|
function compareArrays(first, second) {
|
|
2
3
|
const firstIsLarger = first.length > second.length;
|
|
3
4
|
const from = firstIsLarger ? first : second;
|
|
4
5
|
const to = firstIsLarger ? second : first;
|
|
5
|
-
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return
|
|
6
|
-
return firstIsLarger ?
|
|
6
|
+
if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) return COMPARISON_DISSIMILAR;
|
|
7
|
+
return firstIsLarger ? COMPARISON_REMOVED : COMPARISON_ADDED;
|
|
7
8
|
}
|
|
8
9
|
function isFragment(value) {
|
|
9
|
-
return
|
|
10
|
+
return isNamed(value, NAME_FRAGMENT);
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
+
function isFragments(value) {
|
|
13
|
+
return isNamed(value, NAME_FRAGMENTS);
|
|
14
|
+
}
|
|
15
|
+
function isNamed(value, name) {
|
|
16
|
+
return typeof value === "object" && value != null && name in value && value[name] === true;
|
|
17
|
+
}
|
|
18
|
+
var COMPARISON_ADDED = "added";
|
|
19
|
+
var COMPARISON_DISSIMILAR = "dissimilar";
|
|
20
|
+
var COMPARISON_REMOVED = "removed";
|
|
21
|
+
export { compareArrays, isFragment, isFragments };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { Fragments } from "./fragments.js";
|
|
1
2
|
import { Fragment } from "./fragment.js";
|
|
2
3
|
import "@oscarpalmer/mora";
|
|
3
4
|
export * from "@oscarpalmer/mora";
|
|
4
|
-
function
|
|
5
|
-
return new
|
|
5
|
+
function fragments(array$1, identify, fragment) {
|
|
6
|
+
return new Fragments(array$1, identify, fragment);
|
|
6
7
|
}
|
|
7
|
-
|
|
8
|
+
function html(template, ...values) {
|
|
9
|
+
return new Fragment(template, values);
|
|
10
|
+
}
|
|
11
|
+
export { fragments, html };
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, EXPRESSION_ABYDON_CONTENT, EXPRESSION_EVENT_PREFIX, EXPRESSION_PERIOD } from "../../constants.js";
|
|
2
2
|
import { mapEvent } from "../event.js";
|
|
3
|
-
import { setAttribute
|
|
3
|
+
import { setAttribute } from "./value.js";
|
|
4
4
|
import { computed, isReactive } from "@oscarpalmer/mora";
|
|
5
|
-
import { isBooleanAttribute, setProperty } from "@oscarpalmer/toretto/attribute";
|
|
6
5
|
function getValue(data, original) {
|
|
7
|
-
const matches =
|
|
6
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(original ?? "");
|
|
8
7
|
return matches == null ? original : data.values[+matches[1]];
|
|
9
8
|
}
|
|
10
9
|
function mapAttributes(data, element) {
|
|
@@ -12,16 +11,17 @@ function mapAttributes(data, element) {
|
|
|
12
11
|
const { length } = attributes;
|
|
13
12
|
for (let index = 0; index < length; index += 1) {
|
|
14
13
|
const { name, value } = attributes[index];
|
|
15
|
-
const
|
|
14
|
+
const actualName = name.replace(EXPRESSION_ABYDON_ATTRIBUTE_PREFIX, "");
|
|
15
|
+
const actualValue = getValue(data, value);
|
|
16
|
+
if (actualName !== name) element.removeAttribute(name);
|
|
16
17
|
switch (true) {
|
|
17
|
-
case
|
|
18
|
-
mapEvent(element,
|
|
18
|
+
case EXPRESSION_EVENT_PREFIX.test(actualName):
|
|
19
|
+
mapEvent(element, actualName, actualValue);
|
|
19
20
|
break;
|
|
20
|
-
case
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
setProperty(element, name, value);
|
|
21
|
+
case EXPRESSION_PERIOD.test(actualName):
|
|
22
|
+
case typeof actualValue === "function":
|
|
23
|
+
case isReactive(actualValue):
|
|
24
|
+
mapValue(data, element, actualName, actualValue);
|
|
25
25
|
break;
|
|
26
26
|
default: break;
|
|
27
27
|
}
|
|
@@ -29,11 +29,11 @@ function mapAttributes(data, element) {
|
|
|
29
29
|
}
|
|
30
30
|
function mapValue(data, element, name, value) {
|
|
31
31
|
if (typeof value === "function") setComputedAttribute(data, element, name, value);
|
|
32
|
-
else setAttribute
|
|
32
|
+
else setAttribute(data, element, name, value);
|
|
33
33
|
}
|
|
34
34
|
function setComputedAttribute(data, element, name, callback) {
|
|
35
35
|
const value = computed(callback);
|
|
36
36
|
data.mora.values.add(value);
|
|
37
|
-
setAttribute
|
|
37
|
+
setAttribute(data, element, name, value);
|
|
38
38
|
}
|
|
39
39
|
export { mapAttributes };
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { ATTRIBUTE_CLASS_PREFIX_LENGTH, EXPRESSION_ATTRIBUTE_CLASS, EXPRESSION_ATTRIBUTE_STYLE_FULL, EXPRESSION_ATTRIBUTE_STYLE_PREFIX } from "../../constants.js";
|
|
2
2
|
import { isReactive } from "@oscarpalmer/mora";
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { isBooleanAttribute, setAttribute as setAttribute$1, setProperty } from "@oscarpalmer/toretto/attribute";
|
|
4
|
+
function getCallback(element, name) {
|
|
5
|
+
if (isBooleanAttribute(name) && name in element) return name === "checked" ? updateChecked : updateProperty;
|
|
6
|
+
return name === "value" ? updateValue : setAttribute$1;
|
|
7
|
+
}
|
|
5
8
|
function setAttribute(data, element, name, value) {
|
|
6
|
-
element.removeAttribute(name);
|
|
7
9
|
switch (true) {
|
|
8
10
|
case EXPRESSION_ATTRIBUTE_CLASS.test(name):
|
|
9
11
|
setClasses(data, element, name, value);
|
|
@@ -30,27 +32,31 @@ function setStyle(data, element, name, value) {
|
|
|
30
32
|
if (property == null) return;
|
|
31
33
|
function update(value$1) {
|
|
32
34
|
if (value$1 == null || value$1 === false || value$1 === true && unit == null) element.style.removeProperty(property);
|
|
33
|
-
else element.style.setProperty(property, value$1 === true ? unit :
|
|
35
|
+
else element.style.setProperty(property, value$1 === true ? unit : String(value$1));
|
|
34
36
|
}
|
|
35
37
|
if (isReactive(value)) data.mora.subscribers.add(value.subscribe(update));
|
|
36
38
|
else update(value);
|
|
37
39
|
}
|
|
38
40
|
function setValue(data, element, name, value) {
|
|
39
|
-
|
|
40
|
-
if (isBooleanAttribute(name) && name in element) callback = name === "selected" ? updateSelected : updateProperty;
|
|
41
|
-
else callback = setAttribute$1;
|
|
41
|
+
const callback = getCallback(element, name);
|
|
42
42
|
if (isReactive(value)) data.mora.subscribers.add(value.subscribe((next) => {
|
|
43
43
|
callback(element, name, next);
|
|
44
44
|
}));
|
|
45
45
|
else callback(element, name, value);
|
|
46
46
|
}
|
|
47
|
+
function updateChecked(element, name, value) {
|
|
48
|
+
updateElement("change", "checked", element, name, value, value === true);
|
|
49
|
+
}
|
|
50
|
+
function updateElement(event, property, element, name, value, next) {
|
|
51
|
+
if (!(property in element) || element[property] === next) return;
|
|
52
|
+
setAttribute$1(element, name, value);
|
|
53
|
+
element[property] = next;
|
|
54
|
+
element.dispatchEvent(new Event(event, { bubbles: true }));
|
|
55
|
+
}
|
|
47
56
|
function updateProperty(element, name, value) {
|
|
48
|
-
element
|
|
57
|
+
setProperty(element, name, value === true);
|
|
49
58
|
}
|
|
50
|
-
function
|
|
51
|
-
|
|
52
|
-
const options = [...select?.options ?? []];
|
|
53
|
-
if (select != null && options.includes(element)) select.dispatchEvent(new Event("change", { bubbles: true }));
|
|
54
|
-
updateProperty(element, name, value);
|
|
59
|
+
function updateValue(element, name, value) {
|
|
60
|
+
updateElement(element instanceof HTMLSelectElement ? "change" : "input", "value", element, name, value, String(value));
|
|
55
61
|
}
|
|
56
62
|
export { setAttribute };
|
package/dist/node/event.js
CHANGED
|
@@ -1,30 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
let controller = ABORT_CONTROLLERS.get(element);
|
|
4
|
-
if (controller == null) {
|
|
5
|
-
controller = new AbortController();
|
|
6
|
-
ABORT_CONTROLLERS.set(element, controller);
|
|
7
|
-
}
|
|
8
|
-
return controller;
|
|
9
|
-
}
|
|
1
|
+
import { EVENT_DEFAULTS, EXPRESSION_EVENT_CHANGE_TYPES, EXPRESSION_EVENT_NAME, EXPRESSION_EVENT_OPTIONS_ACTIVE, EXPRESSION_EVENT_OPTIONS_CAPTURE, EXPRESSION_EVENT_OPTIONS_ONCE } from "../constants.js";
|
|
2
|
+
import { on } from "@oscarpalmer/toretto/event";
|
|
10
3
|
function getOptions(options) {
|
|
11
4
|
const parts = options.split(":");
|
|
12
5
|
return {
|
|
13
|
-
capture: parts.
|
|
14
|
-
once: parts.
|
|
15
|
-
passive: !
|
|
6
|
+
capture: parts.some((part) => EXPRESSION_EVENT_OPTIONS_CAPTURE.test(part)),
|
|
7
|
+
once: parts.some((part) => EXPRESSION_EVENT_OPTIONS_ONCE.test(part)),
|
|
8
|
+
passive: !parts.some((part) => EXPRESSION_EVENT_OPTIONS_ACTIVE.test(part))
|
|
16
9
|
};
|
|
17
10
|
}
|
|
11
|
+
function getType(element, type) {
|
|
12
|
+
if (type !== "on") return type;
|
|
13
|
+
if (element instanceof HTMLInputElement) {
|
|
14
|
+
if (EXPRESSION_EVENT_CHANGE_TYPES.test(element.type)) return "change";
|
|
15
|
+
return element.type === "submit" ? "submit" : "input";
|
|
16
|
+
}
|
|
17
|
+
return EVENT_DEFAULTS[element.tagName] ?? type;
|
|
18
|
+
}
|
|
18
19
|
function mapEvent(element, name, value) {
|
|
19
|
-
element.removeAttribute(name);
|
|
20
20
|
const [, type, options] = EXPRESSION_EVENT_NAME.exec(name) ?? [];
|
|
21
|
-
if (typeof value === "function"
|
|
22
|
-
...getOptions(options ?? ""),
|
|
23
|
-
signal: getController(element).signal
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
function removeEvents(element) {
|
|
27
|
-
ABORT_CONTROLLERS.get(element)?.abort(REASON_EVENT_REMOVED);
|
|
28
|
-
ABORT_CONTROLLERS.delete(element);
|
|
21
|
+
if (type != null && typeof value === "function") on(element, getType(element, type), value, getOptions(options ?? ""));
|
|
29
22
|
}
|
|
30
|
-
export { mapEvent
|
|
23
|
+
export { mapEvent };
|
package/dist/node/index.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isFragment } from "../helpers/index.js";
|
|
1
|
+
import { EXPRESSION_ABYDON_CONTENT } from "../constants.js";
|
|
2
|
+
import { isFragment, isFragments } from "../helpers/index.js";
|
|
3
|
+
import { handleFragments } from "../fragments.js";
|
|
3
4
|
import { createNodes } from "../helpers/dom.js";
|
|
4
5
|
import { mapAttributes } from "./attribute/index.js";
|
|
5
6
|
import { setReactiveValue } from "./value.js";
|
|
6
7
|
import { computed, isReactive } from "@oscarpalmer/mora";
|
|
7
8
|
import { isHTMLOrSVGElement } from "@oscarpalmer/toretto/is";
|
|
8
9
|
function mapNode(data, comment) {
|
|
9
|
-
const matches =
|
|
10
|
+
const matches = EXPRESSION_ABYDON_CONTENT.exec(comment.textContent ?? "");
|
|
10
11
|
const value = matches == null ? null : data.values[+matches[1]];
|
|
11
12
|
if (value != null) mapValue(data, comment, value);
|
|
12
13
|
}
|
|
@@ -27,6 +28,10 @@ function mapValue(data, comment, value) {
|
|
|
27
28
|
case typeof value === "function":
|
|
28
29
|
setComputedValue(data, comment, value);
|
|
29
30
|
break;
|
|
31
|
+
case isFragments(value):
|
|
32
|
+
handleFragments(value, false);
|
|
33
|
+
setReactiveValue(data, comment, value.items);
|
|
34
|
+
break;
|
|
30
35
|
case isReactive(value):
|
|
31
36
|
setReactiveValue(data, comment, value);
|
|
32
37
|
break;
|
|
@@ -36,7 +41,7 @@ function mapValue(data, comment, value) {
|
|
|
36
41
|
}
|
|
37
42
|
}
|
|
38
43
|
function replaceComment(data, comment, value) {
|
|
39
|
-
const item = data.items.find((item$1) => item$1.nodes
|
|
44
|
+
const item = data.items.find((item$1) => item$1.nodes?.includes(comment));
|
|
40
45
|
const nodes = createNodes(value);
|
|
41
46
|
if (item != null) {
|
|
42
47
|
item.fragments = isFragment(value) ? [value] : void 0;
|
package/dist/node/value.js
CHANGED
|
@@ -5,7 +5,7 @@ import { getString } from "@oscarpalmer/atoms/string";
|
|
|
5
5
|
import { isChildNode } from "@oscarpalmer/toretto/is";
|
|
6
6
|
function addToArray(identifiers, items, nodes, added) {
|
|
7
7
|
let position = nodes[0];
|
|
8
|
-
const before = added && !identifiers.previous.
|
|
8
|
+
const before = added && !identifiers.previous.has(items.templates[0].identifier);
|
|
9
9
|
const next = items.next.flatMap((fragment) => fragment.get().flatMap((node) => ({
|
|
10
10
|
identifier: fragment.identifier,
|
|
11
11
|
value: node
|
|
@@ -13,7 +13,7 @@ function addToArray(identifiers, items, nodes, added) {
|
|
|
13
13
|
const { length } = next;
|
|
14
14
|
for (let index = 0; index < length; index += 1) {
|
|
15
15
|
const node = next[index];
|
|
16
|
-
if (!(added && identifiers.previous.
|
|
16
|
+
if (!(added && identifiers.previous.has(node.identifier))) if (index === 0 && before) position.before(node.value);
|
|
17
17
|
else position.after(node.value);
|
|
18
18
|
position = node.value;
|
|
19
19
|
}
|
|
@@ -25,7 +25,7 @@ function handleArray(identifiers, items, nodes) {
|
|
|
25
25
|
...items,
|
|
26
26
|
next
|
|
27
27
|
}, nodes, comparison === "added");
|
|
28
|
-
const toRemove = items.fragments?.filter((fragment) => !identifiers.next.
|
|
28
|
+
const toRemove = items.fragments?.filter((fragment) => !identifiers.next.has(fragment.identifier)) ?? [];
|
|
29
29
|
const { length } = toRemove;
|
|
30
30
|
for (let index = 0; index < length; index += 1) toRemove[index].remove();
|
|
31
31
|
return {
|
|
@@ -39,70 +39,75 @@ function removeFragments(fragments) {
|
|
|
39
39
|
for (let index = 0; index < length; index += 1) fragments[index].remove();
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
function replaceText(item, comment, isNullable) {
|
|
43
|
+
let to;
|
|
44
|
+
if (isNullable) to = [comment];
|
|
45
|
+
else to = item.text == null ? [] : [item.text];
|
|
46
|
+
replaceNodes(item.nodes ?? [], to);
|
|
47
|
+
}
|
|
48
|
+
function setArray(item, comment, value) {
|
|
49
|
+
if (value.length === 0) return { nodes: setText(item, comment, value) };
|
|
50
|
+
let templates = value.filter((item$1) => isFragment(item$1) && item$1.identifier != null);
|
|
45
51
|
const next = templates.map((fragment) => fragment.identifier);
|
|
46
|
-
const previous =
|
|
52
|
+
const previous = item.fragments?.map((fragment) => fragment.identifier) ?? [];
|
|
47
53
|
if (new Set(next).size !== templates.length) templates = [];
|
|
48
54
|
const noTemplates = templates.length === 0;
|
|
49
|
-
if (noTemplates ||
|
|
55
|
+
if (noTemplates || item.nodes == null || previous.some((identifier) => identifier == null)) return {
|
|
50
56
|
fragments: noTemplates ? void 0 : templates,
|
|
51
|
-
nodes: setNodes(
|
|
57
|
+
nodes: setNodes(item, comment, noTemplates ? value.flatMap((item$1) => createNodes(item$1)) : templates.flatMap((template) => template.get()))
|
|
52
58
|
};
|
|
53
59
|
return handleArray({
|
|
54
|
-
next,
|
|
55
|
-
previous
|
|
60
|
+
next: new Set(next),
|
|
61
|
+
previous: new Set(previous)
|
|
56
62
|
}, {
|
|
57
63
|
templates,
|
|
58
|
-
fragments:
|
|
59
|
-
},
|
|
64
|
+
fragments: item.fragments ?? []
|
|
65
|
+
}, item.nodes);
|
|
60
66
|
}
|
|
61
|
-
function setNodes(
|
|
62
|
-
if (
|
|
67
|
+
function setNodes(item, comment, next) {
|
|
68
|
+
if (item.nodes == null) {
|
|
63
69
|
if (comment.parentNode != null) replaceNodes([comment], next);
|
|
64
|
-
else if (
|
|
65
|
-
} else replaceNodes(
|
|
66
|
-
removeFragments(
|
|
70
|
+
else if (item.text?.parentNode != null) replaceNodes([item.text], next);
|
|
71
|
+
} else replaceNodes(item.nodes, next);
|
|
72
|
+
removeFragments(item.fragments);
|
|
67
73
|
return next;
|
|
68
74
|
}
|
|
69
75
|
function setReactiveValue(data, comment, reactive) {
|
|
70
|
-
|
|
71
|
-
|
|
76
|
+
let item = data.items.find((item$1) => item$1.nodes?.includes(comment));
|
|
77
|
+
item ??= {};
|
|
78
|
+
item.text = new Text();
|
|
72
79
|
data.mora.subscribers.add(reactive.subscribe((value) => {
|
|
73
|
-
if (Array.isArray(value)) setReactiveValueForArray(
|
|
74
|
-
else setReactiveValueForSingle(
|
|
75
|
-
|
|
76
|
-
item.fragments = state.fragments;
|
|
77
|
-
item.nodes = [...state.nodes ?? [comment]];
|
|
78
|
-
}
|
|
80
|
+
if (Array.isArray(value)) setReactiveValueForArray(item, comment, value);
|
|
81
|
+
else setReactiveValueForSingle(item, comment, value);
|
|
82
|
+
item.nodes = [...item.nodes ?? [comment]];
|
|
79
83
|
}));
|
|
80
84
|
}
|
|
81
|
-
function setReactiveValueForArray(
|
|
82
|
-
const result = setArray(
|
|
83
|
-
|
|
84
|
-
if (typeof result === "boolean")
|
|
85
|
-
else
|
|
85
|
+
function setReactiveValueForArray(item, comment, value) {
|
|
86
|
+
const result = setArray(item, comment, value);
|
|
87
|
+
item.fragments = typeof result === "boolean" ? void 0 : result?.fragments;
|
|
88
|
+
if (typeof result === "boolean") if (result) item.nodes = item.text == null ? [] : [item.text];
|
|
89
|
+
else item.nodes = void 0;
|
|
90
|
+
else item.nodes = result?.nodes;
|
|
86
91
|
}
|
|
87
|
-
function setReactiveValueForSingle(
|
|
92
|
+
function setReactiveValueForSingle(item, comment, value) {
|
|
88
93
|
const valueIsFragment = isFragment(value);
|
|
89
|
-
|
|
90
|
-
if (valueIsFragment || isChildNode(value))
|
|
91
|
-
else
|
|
94
|
+
item.fragments = valueIsFragment ? [value] : void 0;
|
|
95
|
+
if (valueIsFragment || isChildNode(value)) item.nodes = setNodes(item, comment, createNodes(value));
|
|
96
|
+
else item.nodes = setText(item, comment, value);
|
|
92
97
|
}
|
|
93
|
-
function setText(
|
|
98
|
+
function setText(item, comment, value) {
|
|
94
99
|
const isNullable = isNullableOrWhitespace(value);
|
|
95
|
-
|
|
100
|
+
if (item.text != null) item.text.textContent = isNullable ? "" : getString(value);
|
|
96
101
|
let result = false;
|
|
97
|
-
if (
|
|
98
|
-
|
|
102
|
+
if (item.nodes != null) {
|
|
103
|
+
replaceText(item, comment, isNullable);
|
|
99
104
|
result = !isNullable;
|
|
100
|
-
} else if (isNullable && comment.parentNode == null)
|
|
101
|
-
else if (!isNullable &&
|
|
102
|
-
comment.replaceWith(
|
|
105
|
+
} else if (isNullable && comment.parentNode == null) item.text?.replaceWith(comment);
|
|
106
|
+
else if (!isNullable && item?.text?.parentNode == null) {
|
|
107
|
+
if (item.text != null) comment.replaceWith(item.text);
|
|
103
108
|
result = true;
|
|
104
109
|
}
|
|
105
|
-
removeFragments(
|
|
106
|
-
|
|
110
|
+
removeFragments(item.fragments);
|
|
111
|
+
if (result) return item.text == null ? [] : [item.text];
|
|
107
112
|
}
|
|
108
113
|
export { setReactiveValue };
|
package/dist/parse.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { EXPRESSION_ABYDON_ATTRIBUTE_FULL } from "./constants.js";
|
|
1
2
|
import { isNullableOrWhitespace } from "@oscarpalmer/atoms/is";
|
|
2
3
|
function handleExpression(data, prefix, expression) {
|
|
3
4
|
if (Array.isArray(expression)) {
|
|
@@ -6,13 +7,23 @@ function handleExpression(data, prefix, expression) {
|
|
|
6
7
|
for (let index = 0; index < length; index += 1) expressions += handleExpression(data, "", expression[index]);
|
|
7
8
|
return `${prefix}${expressions}`;
|
|
8
9
|
}
|
|
9
|
-
if (typeof expression === "function" || typeof expression === "object" && expression != null) return
|
|
10
|
+
if (typeof expression === "function" || typeof expression === "object" && expression != null) return transformExpression(prefix, data.values.push(expression) - 1);
|
|
10
11
|
return isNullableOrWhitespace(expression) ? prefix : `${prefix}${expression}`;
|
|
11
12
|
}
|
|
12
13
|
function parse(data) {
|
|
14
|
+
if (data.template != null) return data.template;
|
|
13
15
|
const { length } = data.strings;
|
|
14
|
-
|
|
15
|
-
for (let index = 0; index < length; index += 1) template += handleExpression(data, data.strings[index], data.expressions[index]);
|
|
16
|
-
|
|
16
|
+
data.template = "";
|
|
17
|
+
for (let index = 0; index < length; index += 1) data.template += handleExpression(data, data.strings[index], data.expressions[index]);
|
|
18
|
+
data.template = data.template.replaceAll(EXPRESSION_ABYDON_ATTRIBUTE_FULL, transformAttribute);
|
|
19
|
+
data.expressions = [];
|
|
20
|
+
data.strings = [];
|
|
21
|
+
return data.template;
|
|
22
|
+
}
|
|
23
|
+
function transformAttribute(_, name, index) {
|
|
24
|
+
return `_${name}="@abydon.${index}@"`;
|
|
25
|
+
}
|
|
26
|
+
function transformExpression(prefix, index) {
|
|
27
|
+
return `${prefix}<!--abydon.${index}-->`;
|
|
17
28
|
}
|
|
18
29
|
export { parse };
|