aberdeen 1.17.1 → 2.0.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 (139) hide show
  1. package/dist/src/aberdeen.d.ts +928 -944
  2. package/dist/src/aberdeen.js +1693 -1705
  3. package/dist/src/aberdeen.js.map +3 -3
  4. package/dist/src/index.d.ts +12 -0
  5. package/dist/src/index.js +11 -0
  6. package/dist/src/index.js.map +10 -0
  7. package/dist/src/prediction.d.ts +7 -4
  8. package/dist/src/prediction.js +18 -23
  9. package/dist/src/prediction.js.map +3 -3
  10. package/dist/src/route.d.ts +112 -99
  11. package/dist/src/route.js +254 -254
  12. package/dist/src/route.js.map +3 -3
  13. package/dist/src/server-dom.d.ts +158 -0
  14. package/dist/src/server-dom.js +458 -0
  15. package/dist/src/server-dom.js.map +10 -0
  16. package/dist/src/server.d.ts +55 -0
  17. package/dist/src/server.js +25 -0
  18. package/dist/src/server.js.map +10 -0
  19. package/dist/src/transitions.js +7 -4
  20. package/dist/src/transitions.js.map +3 -3
  21. package/dist/tests/environment.d.ts +24 -0
  22. package/dist/tests/{fakedom.js → environment.js} +239 -288
  23. package/dist/tests/environment.js.map +11 -0
  24. package/dist/tests/helpers.d.ts +15 -3
  25. package/dist/tests/helpers.js +277 -306
  26. package/dist/tests/helpers.js.map +6 -5
  27. package/dist-docs/Tutorial/index.html +30 -30
  28. package/dist-docs/aberdeen/Aberdeen/index.html +350 -0
  29. package/dist-docs/aberdeen/InitOptions/index.html +4 -0
  30. package/dist-docs/aberdeen/KeyToString/index.html +2 -0
  31. package/dist-docs/aberdeen/PromiseProxy/index.html +6 -6
  32. package/dist-docs/aberdeen/SortKeyType/index.html +2 -0
  33. package/dist-docs/aberdeen/TargetType/index.html +2 -0
  34. package/dist-docs/aberdeen/ValueRef/index.html +2 -0
  35. package/dist-docs/aberdeen/WindowLike/index.html +5 -0
  36. package/dist-docs/aberdeen/{clone → createA}/index.html +10 -5
  37. package/dist-docs/aberdeen/index.html +13 -54
  38. package/dist-docs/assets/aberdeen/aberdeen.d.ts +928 -944
  39. package/dist-docs/assets/aberdeen/aberdeen.js +1693 -1705
  40. package/dist-docs/assets/aberdeen/aberdeen.js.map +3 -3
  41. package/dist-docs/assets/aberdeen/index.d.ts +12 -0
  42. package/dist-docs/assets/aberdeen/index.js +11 -0
  43. package/dist-docs/assets/aberdeen/index.js.map +10 -0
  44. package/dist-docs/assets/aberdeen/prediction.d.ts +7 -4
  45. package/dist-docs/assets/aberdeen/prediction.js +18 -23
  46. package/dist-docs/assets/aberdeen/prediction.js.map +3 -3
  47. package/dist-docs/assets/aberdeen/route.d.ts +112 -99
  48. package/dist-docs/assets/aberdeen/route.js +254 -254
  49. package/dist-docs/assets/aberdeen/route.js.map +3 -3
  50. package/dist-docs/assets/aberdeen/server-dom.d.ts +158 -0
  51. package/dist-docs/assets/aberdeen/server-dom.js +458 -0
  52. package/dist-docs/assets/aberdeen/server-dom.js.map +10 -0
  53. package/dist-docs/assets/aberdeen/server.d.ts +55 -0
  54. package/dist-docs/assets/aberdeen/server.js +25 -0
  55. package/dist-docs/assets/aberdeen/server.js.map +10 -0
  56. package/dist-docs/assets/aberdeen/transitions.js +7 -4
  57. package/dist-docs/assets/aberdeen/transitions.js.map +3 -3
  58. package/dist-docs/assets/navigation.js +1 -1
  59. package/dist-docs/assets/search.js +1 -1
  60. package/dist-docs/dispatcher/Dispatcher/index.html +5 -6
  61. package/dist-docs/dispatcher/MATCH_FAILED/index.html +2 -2
  62. package/dist-docs/dispatcher/MATCH_REST/index.html +2 -2
  63. package/dist-docs/dispatcher/index.html +2 -2
  64. package/dist-docs/hierarchy.html +1 -1
  65. package/dist-docs/index-1/index.html +2 -0
  66. package/dist-docs/index.html +2 -2
  67. package/dist-docs/media/CHANGELOG.md +10 -1
  68. package/dist-docs/modules.html +1 -1
  69. package/dist-docs/prediction/applyCanon/index.html +4 -3
  70. package/dist-docs/prediction/applyPrediction/index.html +4 -3
  71. package/dist-docs/prediction/index.html +2 -2
  72. package/dist-docs/route/Route/index.html +9 -9
  73. package/dist-docs/route/RouteApi/index.html +60 -0
  74. package/dist-docs/route/index.html +6 -15
  75. package/dist-docs/route/init/index.html +5 -0
  76. package/dist-docs/server/RenderToStringOptions/index.html +6 -0
  77. package/dist-docs/server/RenderToStringResult/index.html +6 -0
  78. package/dist-docs/server/index.html +4 -0
  79. package/dist-docs/server/renderToString/index.html +6 -0
  80. package/dist-docs/sitemap.xml +51 -155
  81. package/dist-docs/transitions/grow/index.html +2 -2
  82. package/dist-docs/transitions/index.html +2 -2
  83. package/dist-docs/transitions/shrink/index.html +2 -2
  84. package/package.json +17 -7
  85. package/skill/SKILL.md +28 -28
  86. package/skill/aberdeen.md +471 -3448
  87. package/skill/dispatcher.md +6 -16
  88. package/skill/prediction.md +17 -5
  89. package/skill/route.md +95 -77
  90. package/skill/transitions.md +3 -3
  91. package/src/aberdeen.ts +1224 -741
  92. package/src/index.ts +13 -0
  93. package/src/prediction.ts +25 -24
  94. package/src/route.ts +192 -142
  95. package/src/server-dom.ts +508 -0
  96. package/src/server.ts +74 -0
  97. package/src/transitions.ts +9 -3
  98. package/dist/tests/fakedom.d.ts +0 -9
  99. package/dist/tests/fakedom.js.map +0 -10
  100. package/dist-docs/aberdeen/A/index.html +0 -115
  101. package/dist-docs/aberdeen/CUSTOM_DUMP/index.html +0 -7
  102. package/dist-docs/aberdeen/NO_COPY/index.html +0 -2
  103. package/dist-docs/aberdeen/OPAQUE/index.html +0 -12
  104. package/dist-docs/aberdeen/clean/index.html +0 -11
  105. package/dist-docs/aberdeen/copy/index.html +0 -22
  106. package/dist-docs/aberdeen/count/index.html +0 -7
  107. package/dist-docs/aberdeen/cssVars/index.html +0 -11
  108. package/dist-docs/aberdeen/darkMode/index.html +0 -9
  109. package/dist-docs/aberdeen/default/index.html +0 -341
  110. package/dist-docs/aberdeen/derive/index.html +0 -18
  111. package/dist-docs/aberdeen/disableCreateDestroy/index.html +0 -6
  112. package/dist-docs/aberdeen/dump/index.html +0 -11
  113. package/dist-docs/aberdeen/insertCss/index.html +0 -30
  114. package/dist-docs/aberdeen/insertGlobalCss/index.html +0 -19
  115. package/dist-docs/aberdeen/invertString/index.html +0 -13
  116. package/dist-docs/aberdeen/isEmpty/index.html +0 -12
  117. package/dist-docs/aberdeen/map/index.html +0 -26
  118. package/dist-docs/aberdeen/merge/index.html +0 -11
  119. package/dist-docs/aberdeen/mount/index.html +0 -17
  120. package/dist-docs/aberdeen/multiMap/index.html +0 -28
  121. package/dist-docs/aberdeen/onEach/index.html +0 -19
  122. package/dist-docs/aberdeen/partition/index.html +0 -36
  123. package/dist-docs/aberdeen/peek/index.html +0 -40
  124. package/dist-docs/aberdeen/proxy/index.html +0 -35
  125. package/dist-docs/aberdeen/ref/index.html +0 -13
  126. package/dist-docs/aberdeen/runQueue/index.html +0 -13
  127. package/dist-docs/aberdeen/setErrorHandler/index.html +0 -16
  128. package/dist-docs/aberdeen/setSpacingCssVars/index.html +0 -8
  129. package/dist-docs/aberdeen/unmountAll/index.html +0 -5
  130. package/dist-docs/aberdeen/unproxy/index.html +0 -11
  131. package/dist-docs/route/back/index.html +0 -4
  132. package/dist-docs/route/current/index.html +0 -2
  133. package/dist-docs/route/go/index.html +0 -14
  134. package/dist-docs/route/interceptLinks/index.html +0 -8
  135. package/dist-docs/route/matchCurrent/index.html +0 -10
  136. package/dist-docs/route/persistScroll/index.html +0 -6
  137. package/dist-docs/route/push/index.html +0 -6
  138. package/dist-docs/route/setLog/index.html +0 -3
  139. package/dist-docs/route/up/index.html +0 -5
@@ -1,29 +1,8 @@
1
1
  // @bun
2
- var __defProp = Object.defineProperty;
3
- var __returnValue = (v) => v;
4
- function __exportSetter(name, newValue) {
5
- this[name] = __returnValue.bind(null, newValue);
6
- }
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, {
10
- get: all[name],
11
- enumerable: true,
12
- configurable: true,
13
- set: __exportSetter.bind(all, name)
14
- });
15
- };
2
+ // tests/environment.ts
3
+ import { createA } from "aberdeen";
16
4
 
17
- // tests/fakedom.ts
18
- var exports_fakedom = {};
19
- __export(exports_fakedom, {
20
- setMediaQuery: () => setMediaQuery,
21
- resetCounts: () => resetCounts,
22
- resetBrowserState: () => resetBrowserState,
23
- passTime: () => passTime,
24
- getCounts: () => getCounts,
25
- clearBody: () => clearBody
26
- });
5
+ // src/server-dom.ts
27
6
  var newCount = 0;
28
7
  var changeCount = 0;
29
8
  var resetCounts = function() {
@@ -32,13 +11,11 @@ var resetCounts = function() {
32
11
  var getCounts = function() {
33
12
  return { new: newCount, changed: changeCount };
34
13
  };
35
- var clearBody = function() {
36
- document2.body.childNodes.length = 0;
37
- };
38
14
 
39
15
  class Node {
40
16
  parentNode = null;
41
17
  childNodes = [];
18
+ ownerDocument = null;
42
19
  get nextSibling() {
43
20
  return this.getSibling(1);
44
21
  }
@@ -56,13 +33,15 @@ class Node {
56
33
  }
57
34
  }
58
35
 
59
- class Element2 extends Node {
36
+ class Element extends Node {
60
37
  tagName;
61
38
  namespaceURI;
62
39
  _style = {};
63
40
  attrs = {};
64
41
  events = {};
65
42
  _classList;
43
+ _scrollTop;
44
+ _scrollLeft;
66
45
  constructor(tag, namespaceURI) {
67
46
  super();
68
47
  this.tagName = tag;
@@ -141,7 +120,7 @@ class Element2 extends Node {
141
120
  });
142
121
  }
143
122
  get parentElement() {
144
- if (this.parentNode instanceof Element2)
123
+ if (this.parentNode instanceof Element)
145
124
  return this.parentNode;
146
125
  return;
147
126
  }
@@ -176,7 +155,7 @@ class Element2 extends Node {
176
155
  }
177
156
  _querySelectorAllRecursive(selector, results) {
178
157
  for (const child of this.childNodes) {
179
- if (child instanceof Element2) {
158
+ if (child instanceof Element) {
180
159
  if (child.tagName === selector) {
181
160
  results.push(child);
182
161
  }
@@ -187,7 +166,7 @@ class Element2 extends Node {
187
166
  set innerHTML(html) {
188
167
  this.childNodes = [];
189
168
  if (html) {
190
- let n = new Element2("fake-emulated-html");
169
+ let n = new Element("fake-emulated-html");
191
170
  n.textContent = html;
192
171
  this.appendChild(n);
193
172
  }
@@ -227,8 +206,6 @@ class Element2 extends Node {
227
206
  set scrollLeft(value) {
228
207
  this._scrollLeft = value;
229
208
  }
230
- _scrollTop;
231
- _scrollLeft;
232
209
  toString() {
233
210
  let arr = [];
234
211
  for (let [symbol, items, toKebab] of [["=", this.attrs, false], ["->", this, false], [":", this.style, true]]) {
@@ -284,7 +261,7 @@ class Element2 extends Node {
284
261
  if (this.attrs.id === id)
285
262
  return this;
286
263
  for (let child of this.childNodes) {
287
- if (child instanceof Element2) {
264
+ if (child instanceof Element) {
288
265
  let el = child.getElementById(id);
289
266
  if (el)
290
267
  return el;
@@ -293,225 +270,7 @@ class Element2 extends Node {
293
270
  return;
294
271
  }
295
272
  }
296
- var document2 = {
297
- createElement: (tag) => new Element2(tag, "http://www.w3.org/1999/xhtml"),
298
- createElementNS: (namespaceURI, tag) => new Element2(tag, namespaceURI),
299
- createTextNode: (text) => new TextNode(text),
300
- head: new Element2("head", "http://www.w3.org/1999/xhtml"),
301
- body: new Element2("body", "http://www.w3.org/1999/xhtml")
302
- };
303
-
304
- class FakeLocation {
305
- _href = "http://localhost/";
306
- get href() {
307
- return this._href;
308
- }
309
- set href(value) {
310
- if (value.startsWith("/")) {
311
- const currentUrl = new URL(this._href);
312
- this._href = `${currentUrl.protocol}//${currentUrl.host}${value}`;
313
- } else {
314
- this._href = value;
315
- }
316
- }
317
- get host() {
318
- const url = new URL(this._href);
319
- return url.host;
320
- }
321
- get pathname() {
322
- const url = new URL(this._href);
323
- return url.pathname;
324
- }
325
- set pathname(value) {
326
- const url = new URL(this._href);
327
- url.pathname = value;
328
- this._href = url.href;
329
- }
330
- get search() {
331
- const url = new URL(this._href);
332
- return url.search;
333
- }
334
- set search(value) {
335
- const url = new URL(this._href);
336
- url.search = value;
337
- this._href = url.href;
338
- }
339
- get hash() {
340
- const url = new URL(this._href);
341
- return url.hash;
342
- }
343
- set hash(value) {
344
- const url = new URL(this._href);
345
- url.hash = value;
346
- this._href = url.href;
347
- }
348
- }
349
-
350
- class FakeHistory {
351
- _state = null;
352
- _entries = [];
353
- _index = 0;
354
- constructor() {
355
- this._entries = [{ url: location.href, state: null }];
356
- }
357
- get state() {
358
- return this._state;
359
- }
360
- pushState(state, title, url) {
361
- this._entries = this._entries.slice(0, this._index + 1);
362
- this._entries.push({ url, state });
363
- this._index = this._entries.length - 1;
364
- this._state = state;
365
- location.href = url;
366
- }
367
- replaceState(state, title, url) {
368
- this._entries[this._index] = { url, state };
369
- this._state = state;
370
- location.href = url;
371
- }
372
- go(delta) {
373
- const newIndex = this._index + delta;
374
- if (newIndex >= 0 && newIndex < this._entries.length) {
375
- this._index = newIndex;
376
- const entry = this._entries[this._index];
377
- this._state = entry.state;
378
- location.href = entry.url;
379
- setTimeout(() => {
380
- const event = {
381
- type: "popstate",
382
- state: this._state,
383
- target: window,
384
- preventDefault: () => {},
385
- stopPropagation: () => {}
386
- };
387
- window.dispatchEvent(event);
388
- }, 0);
389
- }
390
- }
391
- back() {
392
- this.go(-1);
393
- }
394
- forward() {
395
- this.go(1);
396
- }
397
- _reset() {
398
- this._state = null;
399
- this._entries = [{ url: location.href, state: null }];
400
- this._index = 0;
401
- }
402
- _getLength() {
403
- return this._entries.length;
404
- }
405
- }
406
-
407
- class FakeWindow {
408
- _listeners = {};
409
- addEventListener(type, listener) {
410
- if (!this._listeners[type]) {
411
- this._listeners[type] = new Set;
412
- }
413
- this._listeners[type].add(listener);
414
- }
415
- removeEventListener(type, listener) {
416
- if (this._listeners[type]) {
417
- this._listeners[type].delete(listener);
418
- }
419
- }
420
- dispatchEvent(event) {
421
- const listeners = this._listeners[event.type];
422
- if (listeners) {
423
- for (const listener of listeners) {
424
- listener.call(this, event);
425
- }
426
- }
427
- }
428
- matchMedia(query) {
429
- if (!mediaQueries.has(query)) {
430
- mediaQueries.set(query, new MediaQueryList(query));
431
- }
432
- return mediaQueries.get(query);
433
- }
434
- _reset() {
435
- this._listeners = {};
436
- }
437
- }
438
- var location = new FakeLocation;
439
- var history = new FakeHistory;
440
- var window = new FakeWindow;
441
- var resetBrowserState = function() {
442
- location.href = "http://localhost/";
443
- history._reset();
444
- };
445
- var timeouts = [];
446
- var currentTime = 0;
447
- var deferredErrors = [];
448
- var realSetTimeout = global.setTimeout;
449
- var realClearTimeout = global.clearTimeout;
450
- function fireItem(item) {
451
- const idx = timeouts.indexOf(item);
452
- if (idx < 0)
453
- return;
454
- timeouts.splice(idx, 1);
455
- if (item.time > currentTime)
456
- currentTime = item.time;
457
- item.func();
458
- }
459
- var setTimeout = function(func, time) {
460
- const item = { func, time: time + currentTime, realId: undefined };
461
- item.realId = realSetTimeout(() => {
462
- try {
463
- fireItem(item);
464
- } catch (e) {
465
- deferredErrors.push(e);
466
- }
467
- }, time);
468
- timeouts.push(item);
469
- };
470
- var queueMicrotask = function(func) {
471
- const item = { func, time: 0, realId: undefined };
472
- item.realId = realSetTimeout(() => {
473
- try {
474
- fireItem(item);
475
- } catch (e) {
476
- deferredErrors.push(e);
477
- }
478
- }, 0);
479
- timeouts.push(item);
480
- };
481
- var passTime = async function(ms = 0) {
482
- let targetTime = currentTime + ms;
483
- while (true) {
484
- await new Promise((resolve) => realSetTimeout(resolve, 0));
485
- if (deferredErrors.length) {
486
- const err = deferredErrors.shift();
487
- throw err;
488
- }
489
- if (!timeouts.length) {
490
- let settled = false;
491
- for (let r = 0;r < 5 && !settled; r++) {
492
- await new Promise((resolve) => realSetTimeout(resolve, 0));
493
- settled = timeouts.length > 0;
494
- }
495
- if (!settled)
496
- break;
497
- }
498
- let smallestIdx = 0;
499
- for (let idx = 1;idx < timeouts.length; idx++) {
500
- if (timeouts[idx].time < timeouts[smallestIdx].time)
501
- smallestIdx = idx;
502
- }
503
- let item = timeouts[smallestIdx];
504
- if (item.time > targetTime)
505
- break;
506
- timeouts.splice(smallestIdx, 1);
507
- realClearTimeout(item.realId);
508
- if (item.time > currentTime)
509
- currentTime = item.time;
510
- await item.func();
511
- }
512
- currentTime = targetTime;
513
- };
514
- var IGNORE_OUTPUT = new Set("tagName-> attrs-> events-> childNodes-> parentNode-> class= namespaceURI->".split(" "));
273
+ var IGNORE_OUTPUT = new Set("tagName-> attrs-> events-> childNodes-> parentNode-> class= namespaceURI-> ownerDocument->".split(" "));
515
274
 
516
275
  class TextNode extends Node {
517
276
  textContent;
@@ -527,52 +286,271 @@ class TextNode extends Node {
527
286
  this.parentNode?.removeChild(this);
528
287
  }
529
288
  }
530
- function getComputedStyle(el) {
531
- return el._style;
289
+ var XHTML_NS = "http://www.w3.org/1999/xhtml";
290
+ function createDocument() {
291
+ const doc = {
292
+ createElement: (tag) => own(new Element(tag, XHTML_NS)),
293
+ createElementNS: (namespaceURI, tag) => own(new Element(tag, namespaceURI)),
294
+ createTextNode: (text) => own(new TextNode(text)),
295
+ head: new Element("head", XHTML_NS),
296
+ body: new Element("body", XHTML_NS),
297
+ defaultView: null
298
+ };
299
+ function own(node) {
300
+ node.ownerDocument = doc;
301
+ return node;
302
+ }
303
+ own(doc.head);
304
+ own(doc.body);
305
+ return doc;
532
306
  }
307
+ var VOID_ELEMENTS = new Set("area base br col embed hr img input link meta param source track wbr".split(" "));
308
+ var RAW_TEXT_ELEMENTS = new Set(["script", "style"]);
533
309
 
534
- class MediaQueryList {
535
- matches;
536
- media;
537
- listeners = new Set;
538
- constructor(query) {
539
- this.media = query;
540
- const preset = mediaQueryPresets.get(query);
541
- this.matches = preset !== undefined ? preset : query.includes("dark") ? false : true;
542
- }
543
- addEventListener(type, listener) {
544
- if (type === "change") {
545
- this.listeners.add(listener);
310
+ // tests/environment.ts
311
+ var realSetTimeout = globalThis.setTimeout;
312
+ var realClearTimeout = globalThis.clearTimeout;
313
+ function createEnvironment() {
314
+ let timeouts = [];
315
+ let currentTime = 0;
316
+ let deferredErrors = [];
317
+ function fireItem(item) {
318
+ const idx = timeouts.indexOf(item);
319
+ if (idx < 0)
320
+ return;
321
+ timeouts.splice(idx, 1);
322
+ if (item.time > currentTime)
323
+ currentTime = item.time;
324
+ item.func();
325
+ }
326
+ const setTimeout = function(func, time = 0) {
327
+ const item = { func, time: time + currentTime, realId: undefined };
328
+ item.realId = realSetTimeout(() => {
329
+ try {
330
+ fireItem(item);
331
+ } catch (e) {
332
+ deferredErrors.push(e);
333
+ }
334
+ }, time);
335
+ timeouts.push(item);
336
+ };
337
+ const queueMicrotask = function(func) {
338
+ const item = { func, time: 0, realId: undefined };
339
+ item.realId = realSetTimeout(() => {
340
+ try {
341
+ fireItem(item);
342
+ } catch (e) {
343
+ deferredErrors.push(e);
344
+ }
345
+ }, 0);
346
+ timeouts.push(item);
347
+ };
348
+ const passTime = async function(ms = 0) {
349
+ let targetTime = currentTime + ms;
350
+ while (true) {
351
+ await new Promise((resolve) => realSetTimeout(resolve, 0));
352
+ if (deferredErrors.length) {
353
+ const err = deferredErrors.shift();
354
+ throw err;
355
+ }
356
+ if (!timeouts.length) {
357
+ let settled = false;
358
+ for (let r = 0;r < 5 && !settled; r++) {
359
+ await new Promise((resolve) => realSetTimeout(resolve, 0));
360
+ settled = timeouts.length > 0;
361
+ }
362
+ if (!settled)
363
+ break;
364
+ }
365
+ let smallestIdx = 0;
366
+ for (let idx = 1;idx < timeouts.length; idx++) {
367
+ if (timeouts[idx].time < timeouts[smallestIdx].time)
368
+ smallestIdx = idx;
369
+ }
370
+ let item = timeouts[smallestIdx];
371
+ if (item.time > targetTime)
372
+ break;
373
+ timeouts.splice(smallestIdx, 1);
374
+ realClearTimeout(item.realId);
375
+ if (item.time > currentTime)
376
+ currentTime = item.time;
377
+ await item.func();
378
+ }
379
+ currentTime = targetTime;
380
+ };
381
+ const mediaQueries = new Map;
382
+ const mediaQueryPresets = new Map;
383
+
384
+ class MediaQueryList {
385
+ matches;
386
+ media;
387
+ listeners = new Set;
388
+ constructor(query) {
389
+ this.media = query;
390
+ const preset = mediaQueryPresets.get(query);
391
+ this.matches = preset !== undefined ? preset : query.includes("dark") ? false : true;
392
+ }
393
+ addEventListener(type, listener) {
394
+ if (type === "change")
395
+ this.listeners.add(listener);
396
+ }
397
+ removeEventListener(type, listener) {
398
+ if (type === "change")
399
+ this.listeners.delete(listener);
400
+ }
401
+ _trigger(matches) {
402
+ this.matches = matches;
403
+ for (const listener of this.listeners)
404
+ listener({ matches, media: this.media });
546
405
  }
547
406
  }
548
- removeEventListener(type, listener) {
549
- if (type === "change") {
550
- this.listeners.delete(listener);
407
+ function setMediaQuery(query, matches) {
408
+ mediaQueryPresets.set(query, matches);
409
+ if (mediaQueries.has(query))
410
+ mediaQueries.get(query)._trigger(matches);
411
+ }
412
+
413
+ class FakeLocation {
414
+ _href = "http://localhost/";
415
+ get href() {
416
+ return this._href;
417
+ }
418
+ set href(value) {
419
+ if (value.startsWith("/")) {
420
+ const currentUrl = new URL(this._href);
421
+ this._href = `${currentUrl.protocol}//${currentUrl.host}${value}`;
422
+ } else
423
+ this._href = value;
424
+ }
425
+ get host() {
426
+ return new URL(this._href).host;
427
+ }
428
+ get pathname() {
429
+ return new URL(this._href).pathname;
430
+ }
431
+ set pathname(value) {
432
+ const u = new URL(this._href);
433
+ u.pathname = value;
434
+ this._href = u.href;
435
+ }
436
+ get search() {
437
+ return new URL(this._href).search;
438
+ }
439
+ set search(value) {
440
+ const u = new URL(this._href);
441
+ u.search = value;
442
+ this._href = u.href;
443
+ }
444
+ get hash() {
445
+ return new URL(this._href).hash;
446
+ }
447
+ set hash(value) {
448
+ const u = new URL(this._href);
449
+ u.hash = value;
450
+ this._href = u.href;
551
451
  }
552
452
  }
553
- _trigger(matches) {
554
- this.matches = matches;
555
- const event = { matches, media: this.media };
556
- for (const listener of this.listeners) {
557
- listener(event);
453
+
454
+ class FakeHistory {
455
+ _state = null;
456
+ _entries = [{ url: "http://localhost/", state: null }];
457
+ _index = 0;
458
+ get state() {
459
+ return this._state;
460
+ }
461
+ pushState(state, _title, url) {
462
+ this._entries = this._entries.slice(0, this._index + 1);
463
+ this._entries.push({ url, state });
464
+ this._index = this._entries.length - 1;
465
+ this._state = state;
466
+ location.href = url;
467
+ }
468
+ replaceState(state, _title, url) {
469
+ this._entries[this._index] = { url, state };
470
+ this._state = state;
471
+ location.href = url;
472
+ }
473
+ go(delta) {
474
+ const newIndex = this._index + delta;
475
+ if (newIndex >= 0 && newIndex < this._entries.length) {
476
+ this._index = newIndex;
477
+ const entry = this._entries[this._index];
478
+ this._state = entry.state;
479
+ location.href = entry.url;
480
+ setTimeout(() => window.dispatchEvent({
481
+ type: "popstate",
482
+ state: this._state,
483
+ target: window,
484
+ preventDefault: () => {},
485
+ stopPropagation: () => {}
486
+ }), 0);
487
+ }
488
+ }
489
+ back() {
490
+ this.go(-1);
491
+ }
492
+ forward() {
493
+ this.go(1);
558
494
  }
559
495
  }
560
- }
561
- var mediaQueries = new Map;
562
- var mediaQueryPresets = new Map;
563
- function setMediaQuery(query, matches) {
564
- mediaQueryPresets.set(query, matches);
565
- if (mediaQueries.has(query)) {
566
- mediaQueries.get(query)._trigger(matches);
496
+
497
+ class FakeWindow {
498
+ _listeners = {};
499
+ addEventListener(type, listener) {
500
+ (this._listeners[type] ||= new Set).add(listener);
501
+ }
502
+ removeEventListener(type, listener) {
503
+ this._listeners[type]?.delete(listener);
504
+ }
505
+ dispatchEvent(event) {
506
+ this._listeners[event.type]?.forEach((l) => l.call(this, event));
507
+ }
508
+ matchMedia(query) {
509
+ if (!mediaQueries.has(query))
510
+ mediaQueries.set(query, new MediaQueryList(query));
511
+ return mediaQueries.get(query);
512
+ }
567
513
  }
514
+ const location = new FakeLocation;
515
+ const history = new FakeHistory;
516
+ const window = new FakeWindow;
517
+ const getComputedStyle = (el) => el._style;
518
+ const document = createDocument();
519
+ Object.assign(window, { document, Node, Element, TextNode, location, history, setTimeout, queueMicrotask, getComputedStyle });
520
+ document.defaultView = window;
521
+ const A = createA(window);
522
+ resetCounts();
523
+ return { A, window, document, location, history, setTimeout, passTime, setMediaQuery, getCounts, resetCounts };
568
524
  }
569
- var globals = { Node, Element: Element2, TextNode, document: document2, window, setTimeout, queueMicrotask, getComputedStyle, location, history, URLSearchParams };
570
- Object.assign(global, globals);
571
- Object.assign(window, globals);
572
525
 
573
526
  // tests/helpers.ts
574
- import { expect } from "bun:test";
575
- import A from "aberdeen";
527
+ import { expect, beforeEach } from "bun:test";
528
+ var env;
529
+ var A;
530
+ var window;
531
+ var document;
532
+ var location;
533
+ var history;
534
+ var setTimeout;
535
+ var passTime;
536
+ function newEnvironment() {
537
+ env = createEnvironment();
538
+ A = env.A;
539
+ window = env.window;
540
+ document = env.document;
541
+ location = env.location;
542
+ history = env.history;
543
+ setTimeout = env.setTimeout;
544
+ passTime = env.passTime;
545
+ }
546
+ newEnvironment();
547
+ beforeEach(newEnvironment);
548
+ function setMediaQuery(query, matches) {
549
+ env.setMediaQuery(query, matches);
550
+ }
551
+ function getCounts2() {
552
+ return env.getCounts();
553
+ }
576
554
  function toDisplay(value) {
577
555
  if (value instanceof Map) {
578
556
  let results = [];
@@ -640,40 +618,33 @@ async function assertThrow(a, b) {
640
618
  }
641
619
  throw new AssertError(`exception expected`, undefined, `something containing "${a}"`, true);
642
620
  }
643
- var passTime2 = passTime;
644
621
  function assertDomUpdates(expected) {
645
- const counts = getCounts();
622
+ const counts = env.getCounts();
646
623
  if (expected.new != null)
647
624
  expect(counts.new).toEqual(expected.new);
648
625
  if (expected.changed != null)
649
626
  expect(counts.changed).toEqual(expected.changed);
650
627
  }
651
- async function reset() {
652
- A.copy(A.cssVars, {});
653
- A.unmountAll();
654
- try {
655
- await passTime(2001);
656
- assertBody(``);
657
- } finally {
658
- clearBody();
659
- }
660
- resetCounts();
661
- A.setErrorHandler();
662
- }
663
628
  export {
664
- reset,
665
- passTime2 as passTime,
629
+ window,
630
+ setTimeout,
631
+ setMediaQuery,
632
+ passTime,
633
+ location,
634
+ history,
666
635
  getCss,
636
+ getCounts2 as getCounts,
667
637
  getBody,
668
- exports_fakedom as fakedom,
638
+ document,
669
639
  assertThrow,
670
640
  assertDomUpdates,
671
641
  assertCss,
672
642
  assertContains,
673
643
  assertBody,
674
644
  assert,
675
- AssertError
645
+ AssertError,
646
+ A
676
647
  };
677
648
 
678
- //# debugId=CFA9235CDB3924EF64756E2164756E21
649
+ //# debugId=E9E14C2775DDDF9564756E2164756E21
679
650
  //# sourceMappingURL=helpers.js.map