@lokascript/core 1.1.1 → 1.1.3

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 (83) hide show
  1. package/dist/behaviors/index.js +1151 -0
  2. package/dist/behaviors/index.js.map +1 -0
  3. package/dist/behaviors/index.mjs +1141 -0
  4. package/dist/behaviors/index.mjs.map +1 -0
  5. package/dist/chunks/bridge-qXDe7P1g.js +2 -0
  6. package/dist/chunks/bridge-qXDe7P1g.js.map +1 -0
  7. package/dist/chunks/browser-modular-DfWTWK1K.js +2 -0
  8. package/dist/chunks/browser-modular-DfWTWK1K.js.map +1 -0
  9. package/dist/chunks/feature-eventsource-VXpBMoKs.js +2 -0
  10. package/dist/chunks/feature-eventsource-VXpBMoKs.js.map +1 -0
  11. package/dist/chunks/feature-sockets-CFuglALU.js +2 -0
  12. package/dist/chunks/feature-sockets-CFuglALU.js.map +1 -0
  13. package/dist/chunks/feature-webworker-JSaX8ZKW.js +2 -0
  14. package/dist/chunks/feature-webworker-JSaX8ZKW.js.map +1 -0
  15. package/dist/commands/index.js +9080 -0
  16. package/dist/commands/index.js.map +1 -0
  17. package/dist/commands/index.mjs +8922 -0
  18. package/dist/commands/index.mjs.map +1 -0
  19. package/dist/expressions/index.js +6484 -0
  20. package/dist/expressions/index.js.map +1 -0
  21. package/dist/expressions/index.mjs +6466 -0
  22. package/dist/expressions/index.mjs.map +1 -0
  23. package/dist/hyperfixi-browser-classic-i18n.js +2 -0
  24. package/dist/hyperfixi-browser-classic-i18n.js.map +1 -0
  25. package/dist/hyperfixi-browser-minimal.js +1 -0
  26. package/dist/hyperfixi-browser-standard.js +2 -0
  27. package/dist/hyperfixi-browser-standard.js.map +1 -0
  28. package/dist/hyperfixi-browser.js +2 -0
  29. package/dist/hyperfixi-browser.js.map +1 -0
  30. package/dist/hyperfixi-hybrid-complete.js +1 -0
  31. package/dist/hyperfixi-hybrid-hx.js +1 -0
  32. package/dist/hyperfixi-lite-plus.js +1 -0
  33. package/dist/hyperfixi-lite.js +1 -0
  34. package/dist/hyperfixi.mjs +2 -0
  35. package/dist/hyperfixi.mjs.map +1 -0
  36. package/dist/lokascript-browser-classic-i18n.js +2 -0
  37. package/dist/lokascript-browser-classic-i18n.js.map +1 -0
  38. package/dist/lokascript-browser-minimal.js +1 -0
  39. package/dist/lokascript-browser-standard.js +2 -0
  40. package/dist/lokascript-browser-standard.js.map +1 -0
  41. package/dist/lokascript-browser.js +2 -0
  42. package/dist/lokascript-browser.js.map +1 -0
  43. package/dist/lokascript-hybrid-complete.js +1 -0
  44. package/dist/lokascript-hybrid-hx.js +1 -0
  45. package/dist/lokascript-lite-plus.js +1 -0
  46. package/dist/lokascript-lite.js +1 -0
  47. package/dist/lokascript-multilingual.js +2 -0
  48. package/dist/lokascript-multilingual.js.map +1 -0
  49. package/dist/metadata.js +378 -0
  50. package/dist/metadata.js.map +1 -0
  51. package/dist/metadata.mjs +368 -0
  52. package/dist/metadata.mjs.map +1 -0
  53. package/dist/parser/full-parser.js +6408 -0
  54. package/dist/parser/full-parser.js.map +1 -0
  55. package/dist/parser/full-parser.mjs +6405 -0
  56. package/dist/parser/full-parser.mjs.map +1 -0
  57. package/dist/parser/regex-parser.js +412 -0
  58. package/dist/parser/regex-parser.js.map +1 -0
  59. package/dist/parser/regex-parser.mjs +409 -0
  60. package/dist/parser/regex-parser.mjs.map +1 -0
  61. package/dist/reference/index.js +602 -0
  62. package/dist/reference/index.js.map +1 -0
  63. package/dist/reference/index.mjs +593 -0
  64. package/dist/reference/index.mjs.map +1 -0
  65. package/dist/registry/browser-types.js +81 -0
  66. package/dist/registry/browser-types.js.map +1 -0
  67. package/dist/registry/browser-types.mjs +76 -0
  68. package/dist/registry/browser-types.mjs.map +1 -0
  69. package/dist/registry/environment.js +36 -0
  70. package/dist/registry/environment.js.map +1 -0
  71. package/dist/registry/environment.mjs +30 -0
  72. package/dist/registry/environment.mjs.map +1 -0
  73. package/dist/registry/index.js +7111 -0
  74. package/dist/registry/index.js.map +1 -0
  75. package/dist/registry/index.mjs +7087 -0
  76. package/dist/registry/index.mjs.map +1 -0
  77. package/dist/registry/universal-types.js +91 -0
  78. package/dist/registry/universal-types.js.map +1 -0
  79. package/dist/registry/universal-types.mjs +86 -0
  80. package/dist/registry/universal-types.mjs.map +1 -0
  81. package/dist/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +2 -2
  83. package/src/expressions/properties/impl/index.test.ts +3 -2
@@ -0,0 +1,1151 @@
1
+ 'use strict';
2
+
3
+ // src/morphlex.ts
4
+ var SUPPORTS_MOVE_BEFORE = "moveBefore" in Element.prototype;
5
+ var ELEMENT_NODE_TYPE = 1;
6
+ var TEXT_NODE_TYPE = 3;
7
+ var IS_PARENT_NODE_TYPE = [
8
+ 0,
9
+ 1,
10
+ 0,
11
+ 0,
12
+ 0,
13
+ 0,
14
+ 0,
15
+ 0,
16
+ 0,
17
+ 1,
18
+ 0,
19
+ 1,
20
+ 0
21
+ ];
22
+ var Operation = {
23
+ EqualNode: 0,
24
+ SameElement: 1,
25
+ SameNode: 2
26
+ };
27
+ var candidateNodes = new Set;
28
+ var candidateElements = new Set;
29
+ var unmatchedNodes = new Set;
30
+ var unmatchedElements = new Set;
31
+ var whitespaceNodes = new Set;
32
+ function morph(from, to, options = {}) {
33
+ if (typeof to === "string")
34
+ to = parseFragment(to).childNodes;
35
+ if (!options.preserveChanges && isParentNode(from))
36
+ flagDirtyInputs(from);
37
+ new Morph(options).morph(from, to);
38
+ }
39
+ function morphInner(from, to, options = {}) {
40
+ if (typeof to === "string") {
41
+ const fragment = parseFragment(to);
42
+ if (fragment.firstChild && fragment.childNodes.length === 1 && fragment.firstChild.nodeType === ELEMENT_NODE_TYPE) {
43
+ to = fragment.firstChild;
44
+ } else {
45
+ throw new Error("[Morphlex] The string was not a valid HTML element.");
46
+ }
47
+ }
48
+ if (from.nodeType === ELEMENT_NODE_TYPE && to.nodeType === ELEMENT_NODE_TYPE && from.localName === to.localName) {
49
+ if (isParentNode(from))
50
+ flagDirtyInputs(from);
51
+ new Morph(options).visitChildNodes(from, to);
52
+ } else {
53
+ throw new Error("[Morphlex] You can only do an inner morph with matching elements.");
54
+ }
55
+ }
56
+ function flagDirtyInputs(node) {
57
+ for (const input of node.querySelectorAll("input")) {
58
+ if (input.name && input.value !== input.defaultValue || input.checked !== input.defaultChecked) {
59
+ input.setAttribute("morphlex-dirty", "");
60
+ }
61
+ }
62
+ for (const element of node.querySelectorAll("option")) {
63
+ if (element.value && element.selected !== element.defaultSelected) {
64
+ element.setAttribute("morphlex-dirty", "");
65
+ }
66
+ }
67
+ for (const element of node.querySelectorAll("textarea")) {
68
+ if (element.value !== element.defaultValue) {
69
+ element.setAttribute("morphlex-dirty", "");
70
+ }
71
+ }
72
+ }
73
+ function parseFragment(string) {
74
+ const template = document.createElement("template");
75
+ template.innerHTML = string.trim();
76
+ return template.content;
77
+ }
78
+ function moveBefore(parent, node, insertionPoint) {
79
+ if (node === insertionPoint)
80
+ return;
81
+ if (node.parentNode === parent) {
82
+ if (node.nextSibling === insertionPoint)
83
+ return;
84
+ if (SUPPORTS_MOVE_BEFORE) {
85
+ parent.moveBefore(node, insertionPoint);
86
+ return;
87
+ }
88
+ }
89
+ parent.insertBefore(node, insertionPoint);
90
+ }
91
+
92
+ class Morph {
93
+ #idArrayMap = new WeakMap;
94
+ #idSetMap = new WeakMap;
95
+ #options;
96
+ constructor(options = {}) {
97
+ this.#options = options;
98
+ }
99
+ morph(from, to) {
100
+ if (isParentNode(from)) {
101
+ this.#mapIdSets(from);
102
+ }
103
+ if (to instanceof NodeList) {
104
+ this.#mapIdArraysForEach(to);
105
+ this.#morphOneToMany(from, to);
106
+ } else if (isParentNode(to)) {
107
+ this.#mapIdArrays(to);
108
+ this.#morphOneToOne(from, to);
109
+ }
110
+ }
111
+ #morphOneToMany(from, to) {
112
+ const length = to.length;
113
+ if (length === 0) {
114
+ this.#removeNode(from);
115
+ } else if (length === 1) {
116
+ this.#morphOneToOne(from, to[0]);
117
+ } else if (length > 1) {
118
+ const newNodes = [...to];
119
+ this.#morphOneToOne(from, newNodes.shift());
120
+ const insertionPoint = from.nextSibling;
121
+ const parent = from.parentNode || document;
122
+ for (let i = 0;i < newNodes.length; i++) {
123
+ const newNode = newNodes[i];
124
+ if (this.#options.beforeNodeAdded?.(parent, newNode, insertionPoint) ?? true) {
125
+ parent.insertBefore(newNode, insertionPoint);
126
+ this.#options.afterNodeAdded?.(newNode);
127
+ }
128
+ }
129
+ }
130
+ }
131
+ #morphOneToOne(from, to) {
132
+ if (from === to)
133
+ return;
134
+ if (from.isEqualNode(to))
135
+ return;
136
+ if (from.nodeType === ELEMENT_NODE_TYPE && to.nodeType === ELEMENT_NODE_TYPE) {
137
+ if (from.localName === to.localName) {
138
+ this.#morphMatchingElements(from, to);
139
+ } else {
140
+ this.#morphNonMatchingElements(from, to);
141
+ }
142
+ } else {
143
+ this.#morphOtherNode(from, to);
144
+ }
145
+ }
146
+ #morphMatchingElements(from, to) {
147
+ if (!(this.#options.beforeNodeVisited?.(from, to) ?? true))
148
+ return;
149
+ if (from.hasAttributes() || to.hasAttributes()) {
150
+ this.#visitAttributes(from, to);
151
+ }
152
+ if (from.localName === "textarea" && to.localName === "textarea") {
153
+ this.#visitTextArea(from, to);
154
+ } else if (from.hasChildNodes() || to.hasChildNodes()) {
155
+ this.visitChildNodes(from, to);
156
+ }
157
+ this.#options.afterNodeVisited?.(from, to);
158
+ }
159
+ #morphNonMatchingElements(from, to) {
160
+ if (!(this.#options.beforeNodeVisited?.(from, to) ?? true))
161
+ return;
162
+ this.#replaceNode(from, to);
163
+ this.#options.afterNodeVisited?.(from, to);
164
+ }
165
+ #morphOtherNode(from, to) {
166
+ if (!(this.#options.beforeNodeVisited?.(from, to) ?? true))
167
+ return;
168
+ if (from.nodeType === to.nodeType && from.nodeValue !== null && to.nodeValue !== null) {
169
+ from.nodeValue = to.nodeValue;
170
+ } else {
171
+ this.#replaceNode(from, to);
172
+ }
173
+ this.#options.afterNodeVisited?.(from, to);
174
+ }
175
+ #visitAttributes(from, to) {
176
+ if (from.hasAttribute("morphlex-dirty")) {
177
+ from.removeAttribute("morphlex-dirty");
178
+ }
179
+ for (const { name, value } of to.attributes) {
180
+ if (name === "value") {
181
+ if (isInputElement(from) && from.value !== value) {
182
+ if (!this.#options.preserveChanges || from.value === from.defaultValue) {
183
+ from.value = value;
184
+ }
185
+ }
186
+ }
187
+ if (name === "selected") {
188
+ if (isOptionElement(from) && !from.selected) {
189
+ if (!this.#options.preserveChanges || from.selected === from.defaultSelected) {
190
+ from.selected = true;
191
+ }
192
+ }
193
+ }
194
+ if (name === "checked") {
195
+ if (isInputElement(from) && !from.checked) {
196
+ if (!this.#options.preserveChanges || from.checked === from.defaultChecked) {
197
+ from.checked = true;
198
+ }
199
+ }
200
+ }
201
+ const oldValue = from.getAttribute(name);
202
+ if (oldValue !== value && (this.#options.beforeAttributeUpdated?.(from, name, value) ?? true)) {
203
+ from.setAttribute(name, value);
204
+ this.#options.afterAttributeUpdated?.(from, name, oldValue);
205
+ }
206
+ }
207
+ for (const { name, value } of from.attributes) {
208
+ if (!to.hasAttribute(name)) {
209
+ if (name === "selected") {
210
+ if (isOptionElement(from) && from.selected) {
211
+ if (!this.#options.preserveChanges || from.selected === from.defaultSelected) {
212
+ from.selected = false;
213
+ }
214
+ }
215
+ }
216
+ if (name === "checked") {
217
+ if (isInputElement(from) && from.checked) {
218
+ if (!this.#options.preserveChanges || from.checked === from.defaultChecked) {
219
+ from.checked = false;
220
+ }
221
+ }
222
+ }
223
+ if (this.#options.beforeAttributeUpdated?.(from, name, null) ?? true) {
224
+ from.removeAttribute(name);
225
+ this.#options.afterAttributeUpdated?.(from, name, value);
226
+ }
227
+ }
228
+ }
229
+ }
230
+ #visitTextArea(from, to) {
231
+ const newTextContent = to.textContent || "";
232
+ const isModified = from.value !== from.defaultValue;
233
+ if (from.textContent !== newTextContent) {
234
+ from.textContent = newTextContent;
235
+ }
236
+ if (this.#options.preserveChanges && isModified)
237
+ return;
238
+ from.value = from.defaultValue;
239
+ }
240
+ visitChildNodes(from, to) {
241
+ if (!(this.#options.beforeChildrenVisited?.(from) ?? true))
242
+ return;
243
+ const parent = from;
244
+ const fromChildNodes = [...from.childNodes];
245
+ const toChildNodes = [...to.childNodes];
246
+ candidateNodes.clear();
247
+ candidateElements.clear();
248
+ unmatchedNodes.clear();
249
+ unmatchedElements.clear();
250
+ whitespaceNodes.clear();
251
+ const matches = [];
252
+ const op = [];
253
+ const nodeTypeMap = [];
254
+ const candidateNodeTypeMap = [];
255
+ const localNameMap = [];
256
+ const candidateLocalNameMap = [];
257
+ for (let i = 0;i < fromChildNodes.length; i++) {
258
+ const candidate = fromChildNodes[i];
259
+ const nodeType = candidate.nodeType;
260
+ candidateNodeTypeMap[i] = nodeType;
261
+ if (nodeType === ELEMENT_NODE_TYPE) {
262
+ candidateLocalNameMap[i] = candidate.localName;
263
+ candidateElements.add(i);
264
+ } else if (nodeType === TEXT_NODE_TYPE && candidate.textContent?.trim() === "") {
265
+ whitespaceNodes.add(i);
266
+ } else {
267
+ candidateNodes.add(i);
268
+ }
269
+ }
270
+ for (let i = 0;i < toChildNodes.length; i++) {
271
+ const node = toChildNodes[i];
272
+ const nodeType = node.nodeType;
273
+ nodeTypeMap[i] = nodeType;
274
+ if (nodeType === ELEMENT_NODE_TYPE) {
275
+ localNameMap[i] = node.localName;
276
+ unmatchedElements.add(i);
277
+ } else if (nodeType === TEXT_NODE_TYPE && node.textContent?.trim() === "") {
278
+ continue;
279
+ } else {
280
+ unmatchedNodes.add(i);
281
+ }
282
+ }
283
+ for (const unmatchedIndex of unmatchedElements) {
284
+ const localName = localNameMap[unmatchedIndex];
285
+ const element = toChildNodes[unmatchedIndex];
286
+ for (const candidateIndex of candidateElements) {
287
+ if (localName !== candidateLocalNameMap[candidateIndex])
288
+ continue;
289
+ const candidate = fromChildNodes[candidateIndex];
290
+ if (candidate.isEqualNode(element)) {
291
+ matches[unmatchedIndex] = candidateIndex;
292
+ op[unmatchedIndex] = Operation.EqualNode;
293
+ candidateElements.delete(candidateIndex);
294
+ unmatchedElements.delete(unmatchedIndex);
295
+ break;
296
+ }
297
+ }
298
+ }
299
+ for (const unmatchedIndex of unmatchedElements) {
300
+ const element = toChildNodes[unmatchedIndex];
301
+ const id = element.id;
302
+ const idArray = this.#idArrayMap.get(element);
303
+ if (id === "" && !idArray)
304
+ continue;
305
+ candidateLoop:
306
+ for (const candidateIndex of candidateElements) {
307
+ const candidate = fromChildNodes[candidateIndex];
308
+ if (localNameMap[unmatchedIndex] === candidateLocalNameMap[candidateIndex]) {
309
+ if (id !== "" && id === candidate.id) {
310
+ matches[unmatchedIndex] = candidateIndex;
311
+ op[unmatchedIndex] = Operation.SameElement;
312
+ candidateElements.delete(candidateIndex);
313
+ unmatchedElements.delete(unmatchedIndex);
314
+ break candidateLoop;
315
+ }
316
+ if (idArray) {
317
+ const candidateIdSet = this.#idSetMap.get(candidate);
318
+ if (candidateIdSet) {
319
+ for (let i = 0;i < idArray.length; i++) {
320
+ const arrayId = idArray[i];
321
+ if (candidateIdSet.has(arrayId)) {
322
+ matches[unmatchedIndex] = candidateIndex;
323
+ op[unmatchedIndex] = Operation.SameElement;
324
+ candidateElements.delete(candidateIndex);
325
+ unmatchedElements.delete(unmatchedIndex);
326
+ break candidateLoop;
327
+ }
328
+ }
329
+ }
330
+ }
331
+ }
332
+ }
333
+ }
334
+ for (const unmatchedIndex of unmatchedElements) {
335
+ const element = toChildNodes[unmatchedIndex];
336
+ const name = element.getAttribute("name");
337
+ const href = element.getAttribute("href");
338
+ const src = element.getAttribute("src");
339
+ for (const candidateIndex of candidateElements) {
340
+ const candidate = fromChildNodes[candidateIndex];
341
+ if (localNameMap[unmatchedIndex] === candidateLocalNameMap[candidateIndex] && (name && name === candidate.getAttribute("name") || href && href === candidate.getAttribute("href") || src && src === candidate.getAttribute("src"))) {
342
+ matches[unmatchedIndex] = candidateIndex;
343
+ op[unmatchedIndex] = Operation.SameElement;
344
+ candidateElements.delete(candidateIndex);
345
+ unmatchedElements.delete(unmatchedIndex);
346
+ break;
347
+ }
348
+ }
349
+ }
350
+ for (const unmatchedIndex of unmatchedElements) {
351
+ const element = toChildNodes[unmatchedIndex];
352
+ const localName = localNameMap[unmatchedIndex];
353
+ for (const candidateIndex of candidateElements) {
354
+ const candidate = fromChildNodes[candidateIndex];
355
+ const candidateLocalName = candidateLocalNameMap[candidateIndex];
356
+ if (localName === candidateLocalName) {
357
+ if (localName === "input" && candidate.type !== element.type) {
358
+ continue;
359
+ }
360
+ matches[unmatchedIndex] = candidateIndex;
361
+ op[unmatchedIndex] = Operation.SameElement;
362
+ candidateElements.delete(candidateIndex);
363
+ unmatchedElements.delete(unmatchedIndex);
364
+ break;
365
+ }
366
+ }
367
+ }
368
+ for (const unmatchedIndex of unmatchedNodes) {
369
+ const node = toChildNodes[unmatchedIndex];
370
+ for (const candidateIndex of candidateNodes) {
371
+ const candidate = fromChildNodes[candidateIndex];
372
+ if (candidate.isEqualNode(node)) {
373
+ matches[unmatchedIndex] = candidateIndex;
374
+ op[unmatchedIndex] = Operation.EqualNode;
375
+ candidateNodes.delete(candidateIndex);
376
+ unmatchedNodes.delete(unmatchedIndex);
377
+ break;
378
+ }
379
+ }
380
+ }
381
+ for (const unmatchedIndex of unmatchedNodes) {
382
+ const nodeType = nodeTypeMap[unmatchedIndex];
383
+ for (const candidateIndex of candidateNodes) {
384
+ if (nodeType === candidateNodeTypeMap[candidateIndex]) {
385
+ matches[unmatchedIndex] = candidateIndex;
386
+ op[unmatchedIndex] = Operation.SameNode;
387
+ candidateNodes.delete(candidateIndex);
388
+ unmatchedNodes.delete(unmatchedIndex);
389
+ break;
390
+ }
391
+ }
392
+ }
393
+ for (const i of candidateNodes)
394
+ this.#removeNode(fromChildNodes[i]);
395
+ for (const i of whitespaceNodes)
396
+ this.#removeNode(fromChildNodes[i]);
397
+ for (const i of candidateElements)
398
+ this.#removeNode(fromChildNodes[i]);
399
+ const lisIndices = longestIncreasingSubsequence(matches);
400
+ const shouldNotMove = new Array(fromChildNodes.length);
401
+ for (let i = 0;i < lisIndices.length; i++) {
402
+ shouldNotMove[matches[lisIndices[i]]] = true;
403
+ }
404
+ let insertionPoint = parent.firstChild;
405
+ for (let i = 0;i < toChildNodes.length; i++) {
406
+ const node = toChildNodes[i];
407
+ const matchInd = matches[i];
408
+ if (matchInd !== undefined) {
409
+ const match = fromChildNodes[matchInd];
410
+ const operation = op[i];
411
+ if (!shouldNotMove[matchInd]) {
412
+ moveBefore(parent, match, insertionPoint);
413
+ }
414
+ if (operation === Operation.EqualNode) ; else if (operation === Operation.SameElement) {
415
+ this.#morphMatchingElements(match, node);
416
+ } else {
417
+ this.#morphOneToOne(match, node);
418
+ }
419
+ insertionPoint = match.nextSibling;
420
+ } else {
421
+ if (this.#options.beforeNodeAdded?.(parent, node, insertionPoint) ?? true) {
422
+ parent.insertBefore(node, insertionPoint);
423
+ this.#options.afterNodeAdded?.(node);
424
+ insertionPoint = node.nextSibling;
425
+ }
426
+ }
427
+ }
428
+ this.#options.afterChildrenVisited?.(from);
429
+ }
430
+ #replaceNode(node, newNode) {
431
+ const parent = node.parentNode || document;
432
+ const insertionPoint = node;
433
+ if ((this.#options.beforeNodeRemoved?.(node) ?? true) && (this.#options.beforeNodeAdded?.(parent, newNode, insertionPoint) ?? true)) {
434
+ parent.insertBefore(newNode, insertionPoint);
435
+ this.#options.afterNodeAdded?.(newNode);
436
+ node.remove();
437
+ this.#options.afterNodeRemoved?.(node);
438
+ }
439
+ }
440
+ #removeNode(node) {
441
+ if (this.#options.beforeNodeRemoved?.(node) ?? true) {
442
+ node.remove();
443
+ this.#options.afterNodeRemoved?.(node);
444
+ }
445
+ }
446
+ #mapIdArraysForEach(nodeList) {
447
+ for (const childNode of nodeList) {
448
+ if (isParentNode(childNode)) {
449
+ this.#mapIdArrays(childNode);
450
+ }
451
+ }
452
+ }
453
+ #mapIdArrays(node) {
454
+ const idArrayMap = this.#idArrayMap;
455
+ for (const element of node.querySelectorAll("[id]")) {
456
+ const id = element.id;
457
+ if (id === "")
458
+ continue;
459
+ let currentElement = element;
460
+ while (currentElement) {
461
+ const idArray = idArrayMap.get(currentElement);
462
+ if (idArray) {
463
+ idArray.push(id);
464
+ } else {
465
+ idArrayMap.set(currentElement, [id]);
466
+ }
467
+ if (currentElement === node)
468
+ break;
469
+ currentElement = currentElement.parentElement;
470
+ }
471
+ }
472
+ }
473
+ #mapIdSets(node) {
474
+ const idSetMap = this.#idSetMap;
475
+ for (const element of node.querySelectorAll("[id]")) {
476
+ const id = element.id;
477
+ if (id === "")
478
+ continue;
479
+ let currentElement = element;
480
+ while (currentElement) {
481
+ const idSet = idSetMap.get(currentElement);
482
+ if (idSet) {
483
+ idSet.add(id);
484
+ } else {
485
+ idSetMap.set(currentElement, new Set([id]));
486
+ }
487
+ if (currentElement === node)
488
+ break;
489
+ currentElement = currentElement.parentElement;
490
+ }
491
+ }
492
+ }
493
+ }
494
+ function isInputElement(element) {
495
+ return element.localName === "input";
496
+ }
497
+ function isOptionElement(element) {
498
+ return element.localName === "option";
499
+ }
500
+ function isParentNode(node) {
501
+ return !!IS_PARENT_NODE_TYPE[node.nodeType];
502
+ }
503
+ function longestIncreasingSubsequence(sequence) {
504
+ const n = sequence.length;
505
+ if (n === 0)
506
+ return [];
507
+ const smallestEnding = [];
508
+ const indices = [];
509
+ const prev = new Array(n);
510
+ for (let i = 0;i < n; i++) {
511
+ const val = sequence[i];
512
+ if (val === undefined)
513
+ continue;
514
+ let left = 0;
515
+ let right = smallestEnding.length;
516
+ while (left < right) {
517
+ const mid = Math.floor((left + right) / 2);
518
+ if (smallestEnding[mid] < val)
519
+ left = mid + 1;
520
+ else
521
+ right = mid;
522
+ }
523
+ prev[i] = left > 0 ? indices[left - 1] : -1;
524
+ if (left === smallestEnding.length) {
525
+ smallestEnding.push(val);
526
+ indices.push(i);
527
+ } else {
528
+ smallestEnding[left] = val;
529
+ indices[left] = i;
530
+ }
531
+ }
532
+ const result = [];
533
+ if (indices.length === 0)
534
+ return result;
535
+ let curr = indices[indices.length - 1];
536
+ while (curr !== undefined && curr !== -1) {
537
+ result.unshift(curr);
538
+ curr = prev[curr];
539
+ }
540
+ return result;
541
+ }
542
+
543
+ //# debugId=744BF12CDB5DA17964756E2164756E21
544
+
545
+ const morphlexMorph = morph;
546
+ const morphlexMorphInner = morphInner;
547
+ function toMorphlexOptions(options) {
548
+ if (!options) {
549
+ return { preserveChanges: true };
550
+ }
551
+ return {
552
+ preserveChanges: options.preserveChanges ?? true,
553
+ beforeNodeVisited: options.beforeNodeVisited,
554
+ afterNodeVisited: options.afterNodeVisited,
555
+ beforeNodeAdded: options.beforeNodeAdded
556
+ ? (node) => options.beforeNodeAdded(node.parentNode, node, null)
557
+ : undefined,
558
+ afterNodeAdded: options.afterNodeAdded,
559
+ beforeNodeRemoved: options.beforeNodeRemoved,
560
+ afterNodeRemoved: options.afterNodeRemoved,
561
+ };
562
+ }
563
+ const morphlexEngine = {
564
+ morph(target, content, options) {
565
+ const morphlexOpts = toMorphlexOptions(options);
566
+ morphlexMorph(target, content, morphlexOpts);
567
+ },
568
+ morphInner(target, content, options) {
569
+ const morphlexOpts = toMorphlexOptions(options);
570
+ let contentEl;
571
+ if (typeof content === 'string') {
572
+ const wrapper = document.createElement(target.tagName);
573
+ wrapper.innerHTML = content;
574
+ contentEl = wrapper;
575
+ }
576
+ else {
577
+ contentEl = content;
578
+ }
579
+ morphlexMorphInner(target, contentEl, morphlexOpts);
580
+ },
581
+ };
582
+ let currentEngine = morphlexEngine;
583
+ const morphAdapter = {
584
+ morph(target, content, options) {
585
+ currentEngine.morph(target, content, options);
586
+ },
587
+ morphInner(target, content, options) {
588
+ currentEngine.morphInner(target, content, options);
589
+ },
590
+ };
591
+
592
+ function isViewTransitionsSupported() {
593
+ return (typeof document !== 'undefined' && typeof document.startViewTransition === 'function');
594
+ }
595
+ let config = {
596
+ enabled: isViewTransitionsSupported(),
597
+ defaultTimeout: 5000};
598
+ let transitionQueue = [];
599
+ let isProcessingQueue = false;
600
+ async function processQueue() {
601
+ if (isProcessingQueue || transitionQueue.length === 0) {
602
+ return;
603
+ }
604
+ isProcessingQueue = true;
605
+ while (transitionQueue.length > 0) {
606
+ const item = transitionQueue.shift();
607
+ try {
608
+ await executeTransition(item.callback, item.options);
609
+ item.resolve();
610
+ }
611
+ catch (error) {
612
+ item.reject(error);
613
+ }
614
+ }
615
+ isProcessingQueue = false;
616
+ }
617
+ async function executeTransition(callback, options) {
618
+ const { skipTransition = false, timeout = config.defaultTimeout } = options;
619
+ if (!config.enabled || !isViewTransitionsSupported() || skipTransition) {
620
+ await callback();
621
+ return;
622
+ }
623
+ const transition = document.startViewTransition(async () => {
624
+ await callback();
625
+ });
626
+ const timeoutPromise = new Promise((_, reject) => {
627
+ setTimeout(() => reject(new Error('View transition timed out')), timeout);
628
+ });
629
+ try {
630
+ await Promise.race([transition.finished, timeoutPromise]);
631
+ }
632
+ catch (error) {
633
+ }
634
+ }
635
+ function withViewTransition(callback, options = {}) {
636
+ return new Promise((resolve, reject) => {
637
+ transitionQueue.push({
638
+ callback,
639
+ options,
640
+ resolve,
641
+ reject,
642
+ });
643
+ processQueue().catch(reject);
644
+ });
645
+ }
646
+
647
+ function isHTMLElement(value) {
648
+ return (value !== null &&
649
+ typeof value === 'object' &&
650
+ 'nodeType' in value &&
651
+ value.nodeType === 1 &&
652
+ 'tagName' in value &&
653
+ typeof value.tagName === 'string' &&
654
+ 'classList' in value);
655
+ }
656
+
657
+ function isDevMode() {
658
+ if (typeof window !== 'undefined' && window.__HYPERFIXI_PROD__) {
659
+ return false;
660
+ }
661
+ if (typeof process !== 'undefined' && process.env?.NODE_ENV === 'production') {
662
+ return false;
663
+ }
664
+ return true;
665
+ }
666
+ ({
667
+ enabled: isDevMode()});
668
+
669
+ function executeSwap(target, content, strategy, morphOptions) {
670
+ const contentStr = content !== null && !isHTMLElement(content) ? content : '';
671
+ const contentEl = isHTMLElement(content) ? content : null;
672
+ switch (strategy) {
673
+ case 'morph':
674
+ if (content !== null) {
675
+ try {
676
+ morphAdapter.morphInner(target, contentEl || contentStr, morphOptions);
677
+ }
678
+ catch (error) {
679
+ console.warn('[HyperFixi] Morph failed, falling back to innerHTML:', error);
680
+ if (contentEl) {
681
+ target.innerHTML = '';
682
+ target.appendChild(contentEl);
683
+ }
684
+ else {
685
+ target.innerHTML = contentStr;
686
+ }
687
+ }
688
+ }
689
+ break;
690
+ case 'morphOuter':
691
+ if (content !== null) {
692
+ try {
693
+ morphAdapter.morph(target, contentEl || contentStr, morphOptions);
694
+ }
695
+ catch (error) {
696
+ console.warn('[HyperFixi] Morph failed, falling back to outerHTML:', error);
697
+ if (contentEl) {
698
+ target.replaceWith(contentEl);
699
+ }
700
+ else {
701
+ target.outerHTML = contentStr;
702
+ }
703
+ }
704
+ }
705
+ break;
706
+ case 'innerHTML':
707
+ if (contentEl) {
708
+ target.innerHTML = '';
709
+ target.appendChild(contentEl);
710
+ }
711
+ else {
712
+ target.innerHTML = contentStr;
713
+ }
714
+ break;
715
+ case 'outerHTML':
716
+ if (contentEl) {
717
+ target.replaceWith(contentEl);
718
+ }
719
+ else {
720
+ target.outerHTML = contentStr;
721
+ }
722
+ break;
723
+ case 'beforeBegin':
724
+ if (contentEl) {
725
+ target.parentElement?.insertBefore(contentEl, target);
726
+ }
727
+ else {
728
+ target.insertAdjacentHTML('beforebegin', contentStr);
729
+ }
730
+ break;
731
+ case 'afterBegin':
732
+ if (contentEl) {
733
+ target.insertBefore(contentEl, target.firstChild);
734
+ }
735
+ else {
736
+ target.insertAdjacentHTML('afterbegin', contentStr);
737
+ }
738
+ break;
739
+ case 'beforeEnd':
740
+ if (contentEl) {
741
+ target.appendChild(contentEl);
742
+ }
743
+ else {
744
+ target.insertAdjacentHTML('beforeend', contentStr);
745
+ }
746
+ break;
747
+ case 'afterEnd':
748
+ if (contentEl) {
749
+ target.parentElement?.insertBefore(contentEl, target.nextSibling);
750
+ }
751
+ else {
752
+ target.insertAdjacentHTML('afterend', contentStr);
753
+ }
754
+ break;
755
+ case 'delete':
756
+ target.remove();
757
+ break;
758
+ case 'none':
759
+ break;
760
+ default:
761
+ throw new Error(`[HyperFixi] swap: unknown strategy "${strategy}"`);
762
+ }
763
+ }
764
+
765
+ function createCustomEvent(eventName, detail, options = {}) {
766
+ return new CustomEvent(eventName, {
767
+ detail: detail !== undefined ? detail : {},
768
+ bubbles: options.bubbles !== undefined ? options.bubbles : true,
769
+ cancelable: options.cancelable !== undefined ? options.cancelable : true,
770
+ composed: options.composed !== undefined ? options.composed : false,
771
+ });
772
+ }
773
+ function dispatchCustomEvent(target, eventName, detail = {}, options = {}) {
774
+ const event = createCustomEvent(eventName, detail, options);
775
+ target.dispatchEvent(event);
776
+ return event;
777
+ }
778
+ function dispatchLokaScriptEvent(target, eventName, detail = {}, options = {}) {
779
+ const lokascriptEvent = dispatchCustomEvent(target, `lokascript:${eventName}`, detail, options);
780
+ const hyperfixiEvent = dispatchCustomEvent(target, `hyperfixi:${eventName}`, detail, options);
781
+ return {
782
+ lokascript: lokascriptEvent,
783
+ hyperfixi: hyperfixiEvent,
784
+ };
785
+ }
786
+
787
+ function createHistorySwap(config) {
788
+ const { target, strategy = 'morph', useViewTransition = false, fetchOptions = {}, transformUrl, onBeforeFetch, onAfterSwap, onError, } = config;
789
+ const resolveTarget = () => {
790
+ if (typeof target === 'string') {
791
+ const element = document.querySelector(target);
792
+ return isHTMLElement(element) ? element : null;
793
+ }
794
+ return isHTMLElement(target) ? target : null;
795
+ };
796
+ const handlePopstate = async (event) => {
797
+ const targetElement = resolveTarget();
798
+ if (!targetElement) {
799
+ console.warn(`HistorySwap: target "${target}" not found`);
800
+ return;
801
+ }
802
+ let url = window.location.href;
803
+ if (transformUrl) {
804
+ url = transformUrl(url);
805
+ }
806
+ try {
807
+ if (onBeforeFetch) {
808
+ await onBeforeFetch(url);
809
+ }
810
+ targetElement.classList.add('hx-swapping');
811
+ const response = await fetch(url, {
812
+ method: 'GET',
813
+ headers: {
814
+ Accept: 'text/html',
815
+ 'HX-Request': 'true',
816
+ 'HX-History-Restore-Request': 'true',
817
+ },
818
+ ...fetchOptions,
819
+ });
820
+ if (!response.ok) {
821
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
822
+ }
823
+ const html = await response.text();
824
+ const performSwap = () => {
825
+ executeSwap(targetElement, html, strategy);
826
+ };
827
+ if (useViewTransition && isViewTransitionsSupported()) {
828
+ await withViewTransition(performSwap);
829
+ }
830
+ else {
831
+ performSwap();
832
+ }
833
+ targetElement.classList.remove('hx-swapping');
834
+ if (onAfterSwap) {
835
+ await onAfterSwap(url, html);
836
+ }
837
+ dispatchLokaScriptEvent(window, 'historyswap', { url, strategy, target });
838
+ }
839
+ catch (error) {
840
+ targetElement.classList.remove('hx-swapping');
841
+ if (onError) {
842
+ onError(error, url);
843
+ }
844
+ else {
845
+ console.error('HistorySwap fetch failed:', error);
846
+ }
847
+ }
848
+ };
849
+ window.addEventListener('popstate', handlePopstate);
850
+ return {
851
+ destroy: () => {
852
+ window.removeEventListener('popstate', handlePopstate);
853
+ },
854
+ config,
855
+ };
856
+ }
857
+ const HistorySwapBehavior = {
858
+ name: 'HistorySwap',
859
+ init(element, params = {}) {
860
+ const config = {
861
+ target: params.target || element,
862
+ strategy: params.strategy || 'morph',
863
+ useViewTransition: Boolean(params.useViewTransition),
864
+ };
865
+ return createHistorySwap(config);
866
+ },
867
+ destroy(instance) {
868
+ instance.destroy();
869
+ },
870
+ };
871
+ function registerHistorySwap(registry) {
872
+ if (registry instanceof Map) {
873
+ registry.set('HistorySwap', HistorySwapBehavior);
874
+ }
875
+ else if (registry && typeof registry.set === 'function') {
876
+ registry.set('HistorySwap', HistorySwapBehavior);
877
+ }
878
+ else if (registry && typeof registry === 'object') {
879
+ registry['HistorySwap'] = HistorySwapBehavior;
880
+ }
881
+ }
882
+ const historySwapHyperscript = `
883
+ behavior HistorySwap(target, strategy)
884
+ init
885
+ if no target then set target to me end
886
+ if no strategy then set strategy to 'morph' end
887
+ end
888
+
889
+ on popstate from window
890
+ add .hx-swapping to target
891
+ fetch location.href as html
892
+ if strategy is 'morph' then
893
+ swap target with it
894
+ else if strategy is 'innerHTML' then
895
+ swap innerHTML of target with it
896
+ else
897
+ swap target with it
898
+ end
899
+ remove .hx-swapping from target
900
+ end
901
+ end
902
+ `;
903
+
904
+ function isExternalUrl(url) {
905
+ try {
906
+ const parsed = new URL(url, window.location.origin);
907
+ return parsed.origin !== window.location.origin;
908
+ }
909
+ catch {
910
+ return false;
911
+ }
912
+ }
913
+
914
+ function shouldBoostLink(link) {
915
+ if (isExternalUrl(link.href)) {
916
+ return false;
917
+ }
918
+ if (link.target && link.target !== '_self') {
919
+ return false;
920
+ }
921
+ if (link.hasAttribute('download')) {
922
+ return false;
923
+ }
924
+ if (link.hasAttribute('data-no-boost') || link.hasAttribute('hx-boost-off')) {
925
+ return false;
926
+ }
927
+ if (link.protocol === 'javascript:' || link.protocol === 'mailto:') {
928
+ return false;
929
+ }
930
+ return true;
931
+ }
932
+ function shouldHandleClick(event) {
933
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
934
+ return false;
935
+ }
936
+ if (event.button !== 0) {
937
+ return false;
938
+ }
939
+ return true;
940
+ }
941
+ function createBoosted(config) {
942
+ const { container, target, linkSelector = 'a[href]', formSelector = 'form', boostForms = false, strategy = 'morph', pushUrl = true, useViewTransition = false, fetchOptions = {}, onBeforeFetch, onAfterSwap, onError, } = config;
943
+ const resolveTarget = () => {
944
+ if (!target) {
945
+ return document.body;
946
+ }
947
+ if (typeof target === 'string') {
948
+ const element = document.querySelector(target);
949
+ return isHTMLElement(element) ? element : null;
950
+ }
951
+ return isHTMLElement(target) ? target : null;
952
+ };
953
+ const boost = async (url, method = 'GET', body = null) => {
954
+ const targetElement = resolveTarget();
955
+ if (!targetElement) {
956
+ console.warn(`Boosted: target "${target}" not found`);
957
+ return;
958
+ }
959
+ try {
960
+ if (onBeforeFetch) {
961
+ const result = await onBeforeFetch(url, method);
962
+ if (result === false) {
963
+ return;
964
+ }
965
+ }
966
+ targetElement.classList.add('hx-swapping');
967
+ container.classList.add('hx-boosting');
968
+ const requestInit = {
969
+ method,
970
+ headers: {
971
+ Accept: 'text/html',
972
+ 'HX-Request': 'true',
973
+ 'HX-Boosted': 'true',
974
+ },
975
+ ...fetchOptions,
976
+ };
977
+ if (body && method !== 'GET') {
978
+ requestInit.body = body;
979
+ }
980
+ const response = await fetch(url, requestInit);
981
+ if (!response.ok) {
982
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
983
+ }
984
+ const html = await response.text();
985
+ const performSwap = () => {
986
+ executeSwap(targetElement, html, strategy);
987
+ };
988
+ if (useViewTransition && isViewTransitionsSupported()) {
989
+ await withViewTransition(performSwap);
990
+ }
991
+ else {
992
+ performSwap();
993
+ }
994
+ targetElement.classList.remove('hx-swapping');
995
+ container.classList.remove('hx-boosting');
996
+ if (pushUrl && method === 'GET') {
997
+ window.history.pushState(null, '', url);
998
+ }
999
+ if (onAfterSwap) {
1000
+ await onAfterSwap(url, html);
1001
+ }
1002
+ dispatchLokaScriptEvent(window, 'boosted', { url, method, strategy, target });
1003
+ }
1004
+ catch (error) {
1005
+ targetElement.classList.remove('hx-swapping');
1006
+ container.classList.remove('hx-boosting');
1007
+ if (onError) {
1008
+ onError(error, url);
1009
+ }
1010
+ else {
1011
+ console.error('Boosted fetch failed:', error);
1012
+ window.location.href = url;
1013
+ }
1014
+ }
1015
+ };
1016
+ const handleClick = async (event) => {
1017
+ const link = event.target.closest(linkSelector);
1018
+ if (!link) {
1019
+ return;
1020
+ }
1021
+ if (!shouldHandleClick(event)) {
1022
+ return;
1023
+ }
1024
+ if (!shouldBoostLink(link)) {
1025
+ return;
1026
+ }
1027
+ event.preventDefault();
1028
+ event.stopPropagation();
1029
+ await boost(link.href);
1030
+ };
1031
+ const handleSubmit = async (event) => {
1032
+ if (!boostForms) {
1033
+ return;
1034
+ }
1035
+ const form = event.target.closest(formSelector);
1036
+ if (!form) {
1037
+ return;
1038
+ }
1039
+ if (form.hasAttribute('data-no-boost') || form.hasAttribute('hx-boost-off')) {
1040
+ return;
1041
+ }
1042
+ if (form.target && form.target !== '_self') {
1043
+ return;
1044
+ }
1045
+ event.preventDefault();
1046
+ event.stopPropagation();
1047
+ const method = (form.method || 'GET').toUpperCase();
1048
+ const formData = new FormData(form);
1049
+ let url;
1050
+ let body = null;
1051
+ if (method === 'GET') {
1052
+ const params = new URLSearchParams();
1053
+ formData.forEach((value, key) => {
1054
+ params.append(key, String(value));
1055
+ });
1056
+ url = `${form.action || window.location.pathname}?${params.toString()}`;
1057
+ }
1058
+ else {
1059
+ url = form.action || window.location.pathname;
1060
+ body = formData;
1061
+ }
1062
+ await boost(url, method, body);
1063
+ };
1064
+ container.addEventListener('click', handleClick);
1065
+ if (boostForms) {
1066
+ container.addEventListener('submit', handleSubmit);
1067
+ }
1068
+ return {
1069
+ destroy: () => {
1070
+ container.removeEventListener('click', handleClick);
1071
+ container.removeEventListener('submit', handleSubmit);
1072
+ },
1073
+ config,
1074
+ boost,
1075
+ };
1076
+ }
1077
+ const BoostedBehavior = {
1078
+ name: 'Boosted',
1079
+ init(element, params = {}) {
1080
+ const config = {
1081
+ container: element,
1082
+ target: params.target,
1083
+ linkSelector: params.linkSelector || 'a[href]',
1084
+ formSelector: params.formSelector || 'form',
1085
+ boostForms: Boolean(params.boostForms),
1086
+ strategy: params.strategy || 'morph',
1087
+ pushUrl: params.pushUrl !== false,
1088
+ useViewTransition: Boolean(params.useViewTransition),
1089
+ };
1090
+ return createBoosted(config);
1091
+ },
1092
+ destroy(instance) {
1093
+ instance.destroy();
1094
+ },
1095
+ };
1096
+ function registerBoosted(registry) {
1097
+ if (registry instanceof Map) {
1098
+ registry.set('Boosted', BoostedBehavior);
1099
+ }
1100
+ else if (registry && typeof registry.set === 'function') {
1101
+ registry.set('Boosted', BoostedBehavior);
1102
+ }
1103
+ else if (registry && typeof registry === 'object') {
1104
+ registry['Boosted'] = BoostedBehavior;
1105
+ }
1106
+ }
1107
+ const boostedHyperscript = `
1108
+ behavior Boosted(target, pushHistory)
1109
+ init
1110
+ if no target then set target to document.body end
1111
+ if no pushHistory then set pushHistory to true end
1112
+ end
1113
+
1114
+ on click from <a[href]/> in me
1115
+ -- Skip if modifier keys pressed
1116
+ if event.metaKey or event.ctrlKey or event.shiftKey or event.altKey then exit end
1117
+
1118
+ -- Skip external links
1119
+ set href to the @href of the target
1120
+ if href starts with 'http' and not (href starts with location.origin) then exit end
1121
+
1122
+ -- Skip links with target attribute
1123
+ if the target has @target then exit end
1124
+
1125
+ halt the event
1126
+ add .hx-swapping to target
1127
+ fetch href as html
1128
+ swap target with it
1129
+ remove .hx-swapping from target
1130
+ if pushHistory then push url href end
1131
+ end
1132
+ end
1133
+ `;
1134
+
1135
+ function registerAllBehaviors(registry) {
1136
+ const { registerHistorySwap } = require('./history-swap');
1137
+ const { registerBoosted } = require('./boosted');
1138
+ registerHistorySwap(registry);
1139
+ registerBoosted(registry);
1140
+ }
1141
+
1142
+ exports.BoostedBehavior = BoostedBehavior;
1143
+ exports.HistorySwapBehavior = HistorySwapBehavior;
1144
+ exports.boostedHyperscript = boostedHyperscript;
1145
+ exports.createBoosted = createBoosted;
1146
+ exports.createHistorySwap = createHistorySwap;
1147
+ exports.historySwapHyperscript = historySwapHyperscript;
1148
+ exports.registerAllBehaviors = registerAllBehaviors;
1149
+ exports.registerBoosted = registerBoosted;
1150
+ exports.registerHistorySwap = registerHistorySwap;
1151
+ //# sourceMappingURL=index.js.map