@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.
Files changed (48) hide show
  1. package/dist/abydon.full.js +1153 -0
  2. package/dist/constants.js +10 -0
  3. package/dist/fragment.js +60 -0
  4. package/dist/helpers/dom.js +28 -0
  5. package/dist/helpers/index.js +11 -0
  6. package/dist/index.js +6 -911
  7. package/dist/node/attribute/index.js +39 -0
  8. package/dist/node/attribute/value.js +56 -0
  9. package/dist/node/event.js +30 -0
  10. package/dist/node/index.js +52 -0
  11. package/dist/node/value.js +108 -0
  12. package/dist/parse.js +18 -0
  13. package/package.json +38 -27
  14. package/src/constants.ts +20 -0
  15. package/src/fragment.ts +63 -36
  16. package/src/helpers/dom.ts +5 -4
  17. package/src/helpers/index.ts +0 -9
  18. package/src/index.ts +13 -3
  19. package/src/models.ts +14 -11
  20. package/src/node/attribute/index.ts +28 -22
  21. package/src/node/attribute/value.ts +38 -42
  22. package/src/node/event.ts +12 -13
  23. package/src/node/index.ts +7 -7
  24. package/src/node/value.ts +169 -122
  25. package/src/{html.ts → parse.ts} +15 -17
  26. package/types/constants.d.ts +9 -0
  27. package/types/fragment.d.ts +3 -5
  28. package/types/helpers/index.d.ts +0 -3
  29. package/types/index.d.ts +4 -2
  30. package/types/models.d.ts +7 -9
  31. package/types/node/attribute/index.d.ts +2 -1
  32. package/types/node/attribute/value.d.ts +2 -1
  33. package/types/node/event.d.ts +1 -1
  34. package/types/node/value.d.ts +2 -2
  35. package/types/parse.d.ts +2 -0
  36. package/dist/fragment.mjs +0 -75
  37. package/dist/helpers/dom.mjs +0 -44
  38. package/dist/helpers/index.mjs +0 -25
  39. package/dist/html.mjs +0 -36
  40. package/dist/index.mjs +0 -6
  41. package/dist/node/attribute/index.mjs +0 -40
  42. package/dist/node/attribute/value.mjs +0 -89
  43. package/dist/node/event.mjs +0 -38
  44. package/dist/node/index.mjs +0 -60
  45. package/dist/node/value.mjs +0 -123
  46. package/types/html.d.ts +0 -4
  47. package/types/index.d.cts +0 -26
  48. /package/dist/{models.mjs → models.js} +0 -0
@@ -1,25 +0,0 @@
1
- // src/helpers/index.ts
2
- function compareArrays(first, second) {
3
- const firstIsLarger = first.length > second.length;
4
- const from = firstIsLarger ? first : second;
5
- const to = firstIsLarger ? second : first;
6
- if (!from.filter((key) => to.includes(key)).every((key, index) => to[index] === key)) {
7
- return "dissimilar";
8
- }
9
- return firstIsLarger ? "removed" : "added";
10
- }
11
- function isChildNode(value) {
12
- return value instanceof CharacterData || value instanceof Element;
13
- }
14
- function isFragment(value) {
15
- return typeof value === "object" && value != null && "$fragment" in value && value.$fragment === true;
16
- }
17
- function isHTMLOrSVGElement(value) {
18
- return value instanceof HTMLElement || value instanceof SVGElement;
19
- }
20
- export {
21
- isHTMLOrSVGElement,
22
- isFragment,
23
- isChildNode,
24
- compareArrays
25
- };
package/dist/html.mjs DELETED
@@ -1,36 +0,0 @@
1
- // src/html.ts
2
- import {isNullableOrWhitespace} from "@oscarpalmer/atoms/is";
3
- import {Fragment} from "./fragment";
4
- function handleExpression(data, prefix, expression) {
5
- if (isNullableOrWhitespace(expression)) {
6
- return prefix;
7
- }
8
- if (Array.isArray(expression)) {
9
- const { length } = expression;
10
- let expressions = "";
11
- for (let index = 0;index < length; index += 1) {
12
- expressions += handleExpression(data, "", expression[index]);
13
- }
14
- return `${prefix}${expressions}`;
15
- }
16
- if (typeof expression === "function" || typeof expression === "object") {
17
- const index = data.values.push(expression) - 1;
18
- return `${prefix}<!--abydon.${index}-->`;
19
- }
20
- return `${prefix}${expression}`;
21
- }
22
- function html(strings, ...values) {
23
- return new Fragment(strings, values);
24
- }
25
- function parse(data) {
26
- const { length } = data.strings;
27
- let template = "";
28
- for (let index = 0;index < length; index += 1) {
29
- template += handleExpression(data, data.strings[index], data.expressions[index]);
30
- }
31
- return template;
32
- }
33
- export {
34
- parse,
35
- html
36
- };
package/dist/index.mjs DELETED
@@ -1,6 +0,0 @@
1
- // src/index.ts
2
- import"@oscarpalmer/sentinel";
3
- import {html} from "./html";
4
- export {
5
- html
6
- };
@@ -1,40 +0,0 @@
1
- // src/node/attribute/index.ts
2
- import {computed, isReactive} from "@oscarpalmer/sentinel";
3
- import {mapEvent} from "../event";
4
- import {setAttribute} from "./value";
5
- function getValue(data, original) {
6
- const matches = commentExpression.exec(original ?? "");
7
- return matches == null ? original : data.values[+matches[1]];
8
- }
9
- function mapAttributes(data, element) {
10
- const attributes = [...element.attributes];
11
- const { length } = attributes;
12
- for (let index = 0;index < length; index += 1) {
13
- const { name, value: value2 } = attributes[index];
14
- const actual = getValue(data, value2);
15
- if (name.startsWith("@")) {
16
- mapEvent(element, name, actual);
17
- } else if (name.includes(".") || typeof value2 === "function" || isReactive(actual)) {
18
- mapValue(data, element, name, actual);
19
- }
20
- }
21
- }
22
- function mapValue(data, element, name, value2) {
23
- switch (true) {
24
- case typeof value2 === "function":
25
- setComputedAttribute(data, element, name, value2);
26
- break;
27
- default:
28
- setAttribute(data, element, name, value2);
29
- break;
30
- }
31
- }
32
- function setComputedAttribute(data, element, name, callback) {
33
- const value2 = computed(callback);
34
- data.sentinel.values.add(value2);
35
- setAttribute(data, element, name, value2);
36
- }
37
- var commentExpression = /^<!--abydon\.(\d+)-->$/;
38
- export {
39
- mapAttributes
40
- };
@@ -1,89 +0,0 @@
1
- // src/node/attribute/value.ts
2
- import {getString} from "@oscarpalmer/atoms/string";
3
- import {effect, isReactive} from "@oscarpalmer/sentinel";
4
- import {
5
- isBooleanAttribute,
6
- setAttribute as setAttr
7
- } from "@oscarpalmer/toretto/attribute";
8
- function setAttribute(data, element, name, value) {
9
- element.removeAttribute(name);
10
- switch (true) {
11
- case classExpression.test(name):
12
- setClasses(data, element, name, value);
13
- return;
14
- case stylePrefixExpression.test(name):
15
- setStyle(data, element, name, value);
16
- return;
17
- default:
18
- setValue(data, element, name, value);
19
- break;
20
- }
21
- }
22
- function setClasses(data, element, name, value) {
23
- function update(value2) {
24
- if (value2 === true) {
25
- element.classList.add(...classes);
26
- } else {
27
- element.classList.remove(...classes);
28
- }
29
- }
30
- const classes = name.slice(6).split(".");
31
- if (isReactive(value)) {
32
- data.sentinel.effects.add(effect(() => {
33
- update(value.get());
34
- }));
35
- } else {
36
- update(value);
37
- }
38
- }
39
- function setStyle(data, element, name, value) {
40
- function update(value2) {
41
- if (value2 == null || value2 === false || value2 === true && unit == null) {
42
- element.style.removeProperty(property);
43
- } else {
44
- element.style.setProperty(property, value2 === true ? unit : getString(value2));
45
- }
46
- }
47
- const [, property, unit] = styleFullExpression.exec(name) ?? [];
48
- if (property != null) {
49
- if (isReactive(value)) {
50
- data.sentinel.effects.add(effect(() => {
51
- update(value.get());
52
- }));
53
- } else {
54
- update(value);
55
- }
56
- }
57
- }
58
- function setValue(data, element, name, value) {
59
- const callback = isBooleanAttribute(name) && name in element ? name === "selected" ? updateSelected : updateProperty : setAttr;
60
- if (isReactive(value)) {
61
- data.sentinel.effects.add(effect(() => {
62
- callback(element, name, value.get());
63
- }));
64
- } else {
65
- callback(element, name, value);
66
- }
67
- }
68
- function triggerSelectChange(select) {
69
- if (select != null) {
70
- select.dispatchEvent(new Event("change", { bubbles: true }));
71
- }
72
- }
73
- function updateProperty(element, name, value) {
74
- element[name] = value === true;
75
- }
76
- function updateSelected(element, name, value) {
77
- const select = element.closest("select");
78
- const options = [...select?.options ?? []];
79
- if (select != null && options.includes(element)) {
80
- triggerSelectChange(select);
81
- }
82
- updateProperty(element, name, value);
83
- }
84
- var classExpression = /^class\./;
85
- var styleFullExpression = /^style\.([\w-]+)(?:\.([\w-]+))?$/;
86
- var stylePrefixExpression = /^style\./;
87
- export {
88
- setAttribute
89
- };
@@ -1,38 +0,0 @@
1
- // src/node/event.ts
2
- function getController(element) {
3
- let controller = controllers.get(element);
4
- if (controller == null) {
5
- controller = new AbortController;
6
- controllers.set(element, controller);
7
- }
8
- return controller;
9
- }
10
- function getOptions(options) {
11
- const parts = options.split(":");
12
- return {
13
- capture: parts.includes("c") || parts.includes("capture"),
14
- once: parts.includes("o") || parts.includes("once"),
15
- passive: !parts.includes("a") && !parts.includes("active")
16
- };
17
- }
18
- function mapEvent(element, name, value) {
19
- element.removeAttribute(name);
20
- const [, type, options] = eventNamePattern.exec(name) ?? [];
21
- if (typeof value === "function" && type != null) {
22
- element.addEventListener(type, value, {
23
- ...getOptions(options ?? ""),
24
- signal: getController(element).signal
25
- });
26
- }
27
- }
28
- function removeEvents(element) {
29
- controllers.get(element)?.abort(reason);
30
- controllers.delete(element);
31
- }
32
- var controllers = new WeakMap;
33
- var eventNamePattern = /^@([\w-]+)(?::([a-z:]+))?$/i;
34
- var reason = "Event removed as element was removed from document by Abydon";
35
- export {
36
- removeEvents,
37
- mapEvent
38
- };
@@ -1,60 +0,0 @@
1
- // src/node/index.ts
2
- import {computed, isReactive} from "@oscarpalmer/sentinel";
3
- import {isFragment, isHTMLOrSVGElement} from "../helpers";
4
- import {createNodes} from "../helpers/dom";
5
- import {mapAttributes} from "./attribute";
6
- import {setReactiveValue} from "./value";
7
- function mapNode(data, comment) {
8
- const matches = commentExpression.exec(comment.textContent ?? "");
9
- const value2 = matches == null ? null : data.values[+matches[1]];
10
- if (value2 != null) {
11
- mapValue(data, comment, value2);
12
- }
13
- }
14
- function mapNodes(data, nodes) {
15
- const { length } = nodes;
16
- for (let index = 0;index < length; index += 1) {
17
- const node = nodes[index];
18
- if (node instanceof Comment) {
19
- mapNode(data, node);
20
- continue;
21
- }
22
- if (isHTMLOrSVGElement(node)) {
23
- mapAttributes(data, node);
24
- }
25
- if (node.hasChildNodes()) {
26
- mapNodes(data, [...node.childNodes]);
27
- }
28
- }
29
- }
30
- function mapValue(data, comment, value2) {
31
- switch (true) {
32
- case typeof value2 === "function":
33
- setComputedValue(data, comment, value2);
34
- break;
35
- case isReactive(value2):
36
- setReactiveValue(data, comment, value2);
37
- break;
38
- default:
39
- replaceComment(data, comment, value2);
40
- break;
41
- }
42
- }
43
- function replaceComment(data, comment, value2) {
44
- const item = data.items.find((item2) => item2.nodes.includes(comment));
45
- const nodes = createNodes(value2);
46
- if (item != null) {
47
- item.fragments = isFragment(value2) ? [value2] : undefined;
48
- item.nodes = nodes;
49
- }
50
- comment.replaceWith(...nodes);
51
- }
52
- function setComputedValue(data, comment, callback) {
53
- const value2 = computed(callback);
54
- data.sentinel.values.add(value2);
55
- setReactiveValue(data, comment, value2);
56
- }
57
- var commentExpression = /^abydon\.(\d+)$/;
58
- export {
59
- mapNodes
60
- };
@@ -1,123 +0,0 @@
1
- // src/node/value.ts
2
- import {isNullableOrWhitespace} from "@oscarpalmer/atoms/is";
3
- import {getString} from "@oscarpalmer/atoms/string";
4
- import {effect} from "@oscarpalmer/sentinel";
5
- import {compareArrays, isChildNode, isFragment} from "../helpers";
6
- import {createNodes, replaceNodes} from "../helpers/dom";
7
- function removeFragments(fragments) {
8
- if (fragments != null) {
9
- const { length } = fragments;
10
- for (let index = 0;index < length; index += 1) {
11
- fragments[index].remove();
12
- }
13
- }
14
- }
15
- function setArray(fragments, nodes, comment, text, value) {
16
- if (value.length === 0) {
17
- return {
18
- nodes: setText(fragments, nodes, comment, text, value)
19
- };
20
- }
21
- let templates = value.filter((item) => isFragment(item) && item.identifier != null);
22
- const identifiers = templates.map((fragment) => fragment.identifier);
23
- const oldIdentifiers = fragments?.map((fragment) => fragment.identifier) ?? [];
24
- if (new Set(identifiers).size !== templates.length) {
25
- templates = [];
26
- }
27
- const noTemplates = templates.length === 0;
28
- if (noTemplates || nodes == null || oldIdentifiers.some((identifier) => identifier == null)) {
29
- return {
30
- fragments: noTemplates ? undefined : templates,
31
- nodes: setNodes(fragments, nodes, comment, text, noTemplates ? value.flatMap((item) => createNodes(item)) : templates.flatMap((template) => template.get()))
32
- };
33
- }
34
- const next = templates.map((template) => fragments?.find((fragment) => fragment.identifier === template.identifier) ?? template);
35
- const comparison = compareArrays(fragments ?? [], templates);
36
- if (comparison !== "removed") {
37
- let position = nodes[0];
38
- const before = comparison === "added" && !oldIdentifiers.includes(templates[0].identifier);
39
- const items = next.flatMap((fragment) => fragment.get().flatMap((node) => ({
40
- identifier: fragment.identifier,
41
- value: node
42
- })));
43
- const { length: length2 } = items;
44
- for (let index = 0;index < length2; index += 1) {
45
- const item = items[index];
46
- if (comparison === "dissimilar" || !oldIdentifiers.includes(item.identifier)) {
47
- if (index === 0 && before) {
48
- position.before(item.value);
49
- } else {
50
- position.after(item.value);
51
- }
52
- }
53
- position = item.value;
54
- }
55
- }
56
- const toRemove = fragments?.filter((fragment) => !identifiers.includes(fragment.identifier)) ?? [];
57
- const { length } = toRemove;
58
- for (let index = 0;index < length; index += 1) {
59
- toRemove[index].remove();
60
- }
61
- return {
62
- fragments: next,
63
- nodes: next.flatMap((fragment) => fragment.get())
64
- };
65
- }
66
- function setNodes(fragments, nodes, comment, text, next) {
67
- if (nodes == null) {
68
- if (comment.parentNode != null) {
69
- replaceNodes([comment], next);
70
- } else if (text.parentNode != null) {
71
- replaceNodes([text], next);
72
- }
73
- } else {
74
- replaceNodes(nodes, next);
75
- }
76
- removeFragments(fragments);
77
- return next;
78
- }
79
- function setReactiveValue(data, comment, reactive) {
80
- const item = data.items.find((item2) => item2.nodes.includes(comment));
81
- const text = new Text;
82
- let fragments;
83
- let nodes;
84
- data.sentinel.effects.add(effect(() => {
85
- const value = reactive.get();
86
- if (Array.isArray(value)) {
87
- const result = setArray(fragments, nodes, comment, text, value);
88
- fragments = typeof result === "boolean" ? undefined : result?.fragments;
89
- nodes = typeof result === "boolean" ? result ? [text] : undefined : result?.nodes;
90
- } else {
91
- const valueIsFragment = isFragment(value);
92
- fragments = valueIsFragment ? [value] : undefined;
93
- if (valueIsFragment || isChildNode(value)) {
94
- nodes = setNodes(fragments, nodes, comment, text, createNodes(value));
95
- } else {
96
- nodes = setText(fragments, nodes, comment, text, value);
97
- }
98
- }
99
- if (item != null) {
100
- item.fragments = fragments;
101
- item.nodes = [...nodes ?? [comment]];
102
- }
103
- }));
104
- }
105
- function setText(fragments, nodes, comment, text, value) {
106
- const isNullable = isNullableOrWhitespace(value);
107
- text.textContent = isNullable ? "" : getString(value);
108
- let result = false;
109
- if (nodes != null) {
110
- replaceNodes(nodes, [isNullable ? comment : text]);
111
- result = !isNullable;
112
- } else if (isNullable && comment.parentNode == null) {
113
- text.replaceWith(comment);
114
- } else if (!isNullable && text.parentNode == null) {
115
- comment.replaceWith(text);
116
- result = true;
117
- }
118
- removeFragments(fragments);
119
- return result ? [text] : undefined;
120
- }
121
- export {
122
- setReactiveValue
123
- };
package/types/html.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import { Fragment } from './fragment';
2
- import type { FragmentData } from './models';
3
- export declare function html(strings: TemplateStringsArray, ...values: unknown[]): Fragment;
4
- export declare function parse(data: FragmentData): string;
package/types/index.d.cts DELETED
@@ -1,26 +0,0 @@
1
- // Generated by dts-bundle-generator v9.5.1
2
-
3
- import { Key } from '@oscarpalmer/atoms/models';
4
-
5
- export declare class Fragment {
6
- private readonly $fragment;
7
- private readonly data;
8
- get identifier(): Key | undefined;
9
- constructor(strings: TemplateStringsArray, expressions: unknown[]);
10
- /**
11
- * Appends the fragment to the given element
12
- */
13
- appendTo(element: Element): void;
14
- /**
15
- * Gets a list of the fragment's nodes
16
- */
17
- get(): ChildNode[];
18
- identify(identifier: Key): Fragment;
19
- /**
20
- * Removes the fragment from the DOM
21
- */
22
- remove(): void;
23
- }
24
- export declare function html(strings: TemplateStringsArray, ...values: unknown[]): Fragment;
25
-
26
- export {};
File without changes