@stencil/mock-doc 5.0.0-alpha.8 → 5.0.0-beta.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/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # @stencil/mock-doc
2
+
3
+ A minimal mock DOM implementation for server-side rendering and unit testing of Stencil components.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install --save-dev @stencil/mock-doc
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### `createDocument(html?)` — lightweight document only
14
+
15
+ Use this when you only need a `Document` with no surrounding `window` object:
16
+
17
+ ```ts
18
+ import { createDocument, serializeNodeToHtml } from '@stencil/mock-doc';
19
+
20
+ const doc = createDocument('<div class="greeting">Hello</div>');
21
+ const el = doc.querySelector('.greeting');
22
+ el.textContent = 'Hello, world!';
23
+
24
+ console.log(serializeNodeToHtml(el, { outerHtml: true }));
25
+ // <div class="greeting">Hello, world!</div>
26
+ ```
27
+
28
+ ### `MockWindow(html?)` — full window environment
29
+
30
+ Use this when your code accesses `window`, `location`, `navigator`, `localStorage`, etc.:
31
+
32
+ ```ts
33
+ import { MockWindow, serializeNodeToHtml } from '@stencil/mock-doc';
34
+
35
+ const win = new MockWindow('<html><body><my-comp></my-comp></body></html>');
36
+ const doc = win.document;
37
+
38
+ const el = doc.querySelector('my-comp');
39
+ el.setAttribute('label', 'Hello');
40
+
41
+ const html = serializeNodeToHtml(doc);
42
+ ```
43
+
44
+ ### `parseHtmlToDocument` / `parseHtmlToFragment`
45
+
46
+ Parse an HTML string into a `Document` or a `DocumentFragment`:
47
+
48
+ ```ts
49
+ import { parseHtmlToDocument, parseHtmlToFragment } from '@stencil/mock-doc';
50
+
51
+ const doc = parseHtmlToDocument('<p>Hello</p>');
52
+ const frag = parseHtmlToFragment('<li>one</li><li>two</li>');
53
+ ```
54
+
55
+ ### `serializeNodeToHtml(node, options?)`
56
+
57
+ Serialize any node back to an HTML string. Useful for snapshot tests and SSR output.
58
+
59
+ ```ts
60
+ import { serializeNodeToHtml } from '@stencil/mock-doc';
61
+
62
+ // Pretty-printed output
63
+ const pretty = serializeNodeToHtml(doc, { prettyHtml: true });
64
+
65
+ // Outer HTML of a single element (includes the element's own tag)
66
+ const outer = serializeNodeToHtml(el, { outerHtml: true });
67
+
68
+ // Serialize shadow roots as Declarative Shadow DOM
69
+ const dsd = serializeNodeToHtml(doc, {
70
+ serializeShadowRoot: 'declarative-shadow-dom',
71
+ });
72
+ ```
73
+
74
+ Key options:
75
+
76
+ | Option | Default | Description |
77
+ |---|---|---|
78
+ | `prettyHtml` | `false` | Indent and add newlines |
79
+ | `indentSpaces` | `2` (when pretty) | Spaces per indent level |
80
+ | `outerHtml` | `false` | Include the root element's own tag |
81
+ | `removeEmptyAttributes` | `true` | Strip attributes with empty string values |
82
+ | `removeHtmlComments` | `false` | Strip HTML comments |
83
+ | `serializeShadowRoot` | — | `'declarative-shadow-dom'` or `'scoped'` |
84
+ | `fullDocument` | `false` | Always emit a full `<!DOCTYPE html>` document |
85
+
86
+ ### `setupGlobal` / `teardownGlobal` — test framework integration
87
+
88
+ Installs a `MockWindow` onto `global` so that `window`, `document`, `customElements`, etc. are available without a browser. Call in `beforeEach`/`afterEach` to get a fresh environment per test:
89
+
90
+ ```ts
91
+ import { setupGlobal, teardownGlobal } from '@stencil/mock-doc';
92
+
93
+ beforeEach(() => setupGlobal(global));
94
+ afterEach(() => teardownGlobal(global));
95
+
96
+ it('reads document.title', () => {
97
+ document.title = 'My Page';
98
+ expect(document.title).toBe('My Page');
99
+ });
100
+ ```
101
+
102
+ `setupGlobal` returns the `MockWindow` it created, which you can use to reach `window`-level APIs directly if needed.
103
+
104
+ ### `patchWindow(win)` — fill gaps in a partial window
105
+
106
+ Useful when running in an environment that has _some_ browser globals but is missing others (e.g. a custom SSR runtime):
107
+
108
+ ```ts
109
+ import { patchWindow } from '@stencil/mock-doc';
110
+
111
+ patchWindow(globalThis); // fills in any missing window APIs with mock implementations
112
+ ```
113
+
114
+ ### Fetch mocks
115
+
116
+ Use `MockRequest`, `MockResponse`, and `MockHeaders` to test code that calls `fetch` without hitting the network:
117
+
118
+ ```ts
119
+ import { MockRequest, MockResponse, MockHeaders } from '@stencil/mock-doc';
120
+
121
+ // Simulate an incoming request
122
+ const req = new MockRequest('/api/data', { method: 'POST' });
123
+ console.log(req.method); // 'POST'
124
+ console.log(req.url); // 'http://localhost/api/data'
125
+
126
+ // Build a response your handler returns
127
+ const res = new MockResponse(JSON.stringify({ ok: true }), {
128
+ status: 200,
129
+ headers: new MockHeaders({ 'content-type': 'application/json' }),
130
+ });
131
+
132
+ const body = await res.json(); // { ok: true }
133
+ ```
package/dist/index.d.mts CHANGED
@@ -139,6 +139,7 @@ declare class MockLocation implements Location {
139
139
  private _href;
140
140
  get href(): string;
141
141
  set href(value: string);
142
+ constructor();
142
143
  assign(_url: string): void;
143
144
  reload(_forcedReload?: boolean): void;
144
145
  replace(_url: string): void;
@@ -166,8 +167,11 @@ declare class MockResizeObserver {
166
167
  declare class MockShadowRoot extends MockDocumentFragment {
167
168
  private _mode;
168
169
  private _delegatesFocus;
170
+ private _clonable;
171
+ private _serializable;
169
172
  get activeElement(): HTMLElement | null;
170
- get cloneable(): boolean;
173
+ get clonable(): boolean;
174
+ set clonable(value: boolean);
171
175
  get delegatesFocus(): boolean;
172
176
  set delegatesFocus(value: boolean);
173
177
  get fullscreenElement(): HTMLElement | null;
@@ -177,6 +181,7 @@ declare class MockShadowRoot extends MockDocumentFragment {
177
181
  get pictureInPictureElement(): HTMLElement | null;
178
182
  get pointerLockElement(): HTMLElement | null;
179
183
  get serializable(): boolean;
184
+ set serializable(value: boolean);
180
185
  get slotAssignment(): 'named' | 'manual';
181
186
  get styleSheets(): StyleSheet[];
182
187
  }
@@ -241,7 +246,7 @@ declare class MockWindow {
241
246
  KeyboardEvent: typeof MockKeyboardEvent;
242
247
  MouseEvent: typeof MockMouseEvent;
243
248
  constructor(html?: string | boolean);
244
- addEventListener(type: string, handler: (ev?: any) => void): void;
249
+ addEventListener(type: string, handler: (ev?: any) => void, options?: boolean | AddEventListenerOptions): void;
245
250
  alert(msg: string): void;
246
251
  blur(): any;
247
252
  cancelAnimationFrame(id: any): void;
@@ -328,7 +333,7 @@ declare class MockWindow {
328
333
  prompt(): string;
329
334
  open(): any;
330
335
  get origin(): string;
331
- removeEventListener(type: string, handler: any): void;
336
+ removeEventListener(type: string, handler: any, options?: boolean | EventListenerOptions): void;
332
337
  requestAnimationFrame(callback: (timestamp: number) => void): number;
333
338
  requestIdleCallback(callback: (deadline: {
334
339
  didTimeout: boolean;
@@ -508,15 +513,10 @@ declare class MockFocusEvent extends MockUIEvent {
508
513
  declare class MockEventListener {
509
514
  type: string;
510
515
  handler: (ev?: any) => void;
511
- constructor(type: string, handler: any);
516
+ capture: boolean;
517
+ once: boolean;
518
+ constructor(type: string, handler: any, options?: boolean | AddEventListenerOptions);
512
519
  }
513
- /**
514
- * Add an event listener to an element.
515
- *
516
- * @param elm - the element to add the listener to
517
- * @param type - the event type to listen for
518
- * @param handler - the event handler function
519
- */
520
520
  interface EventTarget {
521
521
  __listeners: MockEventListener[];
522
522
  }
@@ -606,8 +606,8 @@ declare class MockNode {
606
606
  replaceChild(newChild: MockNode, oldChild: MockNode): MockNode;
607
607
  get textContent(): string;
608
608
  set textContent(value: string);
609
- addEventListener(type: string, handler: (ev?: any) => void): void;
610
- removeEventListener(type: string, handler: any): void;
609
+ addEventListener(type: string, handler: (ev?: any) => void, options?: boolean | AddEventListenerOptions): void;
610
+ removeEventListener(type: string, handler: any, options?: boolean | EventListenerOptions): void;
611
611
  dispatchEvent(ev: MockEvent): boolean;
612
612
  static ELEMENT_NODE: number;
613
613
  static TEXT_NODE: number;
@@ -626,7 +626,7 @@ declare class MockElement extends MockNode {
626
626
  __style: MockCSSStyleDeclaration | null | undefined;
627
627
  attachInternals(): MockElementInternals;
628
628
  constructor(ownerDocument: any, nodeName: string | null, namespaceURI?: string | null);
629
- addEventListener(type: string, handler: (ev?: any) => void): void;
629
+ addEventListener(type: string, handler: (ev?: any) => void, options?: boolean | AddEventListenerOptions): void;
630
630
  attachShadow(_opts: ShadowRootInit): any;
631
631
  blur(): void;
632
632
  get localName(): string;
@@ -710,7 +710,7 @@ declare class MockElement extends MockNode {
710
710
  querySelectorAll<E extends Element = Element>(selectors: string): E[];
711
711
  removeAttribute(attrName: string): void;
712
712
  removeAttributeNS(namespaceURI: string | null, attrName: string): void;
713
- removeEventListener(type: string, handler: any): void;
713
+ removeEventListener(type: string, handler: any, options?: boolean | EventListenerOptions): void;
714
714
  setAttribute(attrName: string, value: any): void;
715
715
  setAttributeNS(namespaceURI: string | null, attrName: string, value: any): void;
716
716
  get style(): any;
@@ -874,6 +874,7 @@ interface NwsapiInstance {
874
874
  configure(config: {
875
875
  LOGERRORS?: boolean;
876
876
  VERBOSITY?: boolean;
877
+ IDS_DUPES?: boolean;
877
878
  }): void;
878
879
  match(selector: string, element: unknown): boolean;
879
880
  first(selector: string, context: unknown): unknown | null;
@@ -972,7 +973,7 @@ declare class MockHeaders {
972
973
  value: string;
973
974
  done: boolean;
974
975
  };
975
- [Symbol.iterator](): /*elided*/any;
976
+ [Symbol.iterator](): /*elided*/ any;
976
977
  };
977
978
  set(key: string, value: string): void;
978
979
  values(): any;
package/dist/index.mjs CHANGED
@@ -17,7 +17,7 @@ var __copyProps = (to, from, except, desc) => {
17
17
  }
18
18
  return to;
19
19
  };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
21
21
  value: mod,
22
22
  enumerable: true
23
23
  }) : target, mod));
@@ -361,12 +361,12 @@ function createCustomElement(customElements, ownerDocument, tagName) {
361
361
  const host = new Proxy({}, {
362
362
  get(obj, prop) {
363
363
  const elm = proxyElements.get(host);
364
- if (elm != null) return elm[prop];
364
+ if (elm != null) return Reflect.get(elm, prop, host);
365
365
  return obj[prop];
366
366
  },
367
367
  set(obj, prop, val) {
368
368
  const elm = proxyElements.get(host);
369
- if (elm != null) elm[prop] = val;
369
+ if (elm != null) Reflect.set(elm, prop, val, host);
370
370
  else obj[prop] = val;
371
371
  return true;
372
372
  },
@@ -374,6 +374,26 @@ function createCustomElement(customElements, ownerDocument, tagName) {
374
374
  if (prop in proxyElements.get(host)) return true;
375
375
  if (prop in obj) return true;
376
376
  return false;
377
+ },
378
+ defineProperty(obj, prop, descriptor) {
379
+ const elm = proxyElements.get(host);
380
+ return Reflect.defineProperty(elm != null ? elm : obj, prop, descriptor);
381
+ },
382
+ deleteProperty(obj, prop) {
383
+ const elm = proxyElements.get(host);
384
+ return Reflect.deleteProperty(elm != null ? elm : obj, prop);
385
+ },
386
+ getOwnPropertyDescriptor(obj, prop) {
387
+ const elm = proxyElements.get(host);
388
+ return Reflect.getOwnPropertyDescriptor(elm != null ? elm : obj, prop);
389
+ },
390
+ ownKeys(obj) {
391
+ const elm = proxyElements.get(host);
392
+ return Reflect.ownKeys(elm != null ? elm : obj);
393
+ },
394
+ getPrototypeOf(obj) {
395
+ const elm = proxyElements.get(host);
396
+ return Reflect.getPrototypeOf(elm != null ? elm : obj);
377
397
  }
378
398
  });
379
399
  const elm = new MockHTMLElement(ownerDocument, tagName);
@@ -574,9 +594,18 @@ var MockFocusEvent = class extends MockUIEvent {
574
594
  var MockEventListener = class {
575
595
  type;
576
596
  handler;
577
- constructor(type, handler) {
597
+ capture;
598
+ once;
599
+ constructor(type, handler, options) {
578
600
  this.type = type;
579
601
  this.handler = handler;
602
+ if (typeof options === "boolean") {
603
+ this.capture = options;
604
+ this.once = false;
605
+ } else {
606
+ this.capture = options?.capture ?? false;
607
+ this.once = options?.once ?? false;
608
+ }
580
609
  }
581
610
  };
582
611
  /**
@@ -585,11 +614,12 @@ var MockEventListener = class {
585
614
  * @param elm - the element to add the listener to
586
615
  * @param type - the event type to listen for
587
616
  * @param handler - the event handler function
617
+ * @param options - `capture` and `once` are supported; `passive` and `signal` are accepted but not implemented
588
618
  */
589
- function addEventListener(elm, type, handler) {
619
+ function addEventListener(elm, type, handler, options) {
590
620
  const target = elm;
591
621
  if (target.__listeners == null) target.__listeners = [];
592
- target.__listeners.push(new MockEventListener(type, handler));
622
+ target.__listeners.push(new MockEventListener(type, handler, options));
593
623
  }
594
624
  /**
595
625
  * Remove an event listener from an element.
@@ -597,11 +627,13 @@ function addEventListener(elm, type, handler) {
597
627
  * @param elm - the element to remove the listener from
598
628
  * @param type - the event type to remove
599
629
  * @param handler - the event handler function to remove
630
+ * @param options - only `capture` is relevant here, since listeners are keyed by type + handler + capture
600
631
  */
601
- function removeEventListener(elm, type, handler) {
632
+ function removeEventListener(elm, type, handler, options) {
602
633
  const target = elm;
634
+ const capture = typeof options === "boolean" ? options : options?.capture ?? false;
603
635
  if (target != null && Array.isArray(target.__listeners) === true) {
604
- const elmListener = target.__listeners.find((e) => e.type === type && e.handler === handler);
636
+ const elmListener = target.__listeners.find((e) => e.type === type && e.handler === handler && e.capture === capture);
605
637
  if (elmListener != null) {
606
638
  const index = target.__listeners.indexOf(elmListener);
607
639
  target.__listeners.splice(index, 1);
@@ -627,6 +659,7 @@ function triggerEventListener(elm, ev) {
627
659
  const target = elm;
628
660
  ev.currentTarget = elm;
629
661
  if (Array.isArray(target.__listeners) === true) target.__listeners.filter((e) => e.type === ev.type).forEach((listener) => {
662
+ if (listener.once) removeEventListener(target, listener.type, listener.handler, { capture: listener.capture });
630
663
  try {
631
664
  listener.handler.call(target, ev);
632
665
  } catch (err) {
@@ -913,6 +946,14 @@ function* streamToHtml(node, opts, output) {
913
946
  yield " shadowrootdelegatesfocus";
914
947
  output.currentLineWidth += 25;
915
948
  }
949
+ if (node.clonable) {
950
+ yield " shadowrootclonable";
951
+ output.currentLineWidth += 19;
952
+ }
953
+ if (node.serializable) {
954
+ yield " shadowrootserializable";
955
+ output.currentLineWidth += 23;
956
+ }
916
957
  }
917
958
  const attrsLength = node.attributes.length;
918
959
  const attributes = opts.prettyHtml && attrsLength > 1 ? cloneAttributes(node.attributes, true) : node.attributes;
@@ -934,14 +975,15 @@ function* streamToHtml(node, opts, output) {
934
975
  } else if (attrNamespaceURI === "http://www.w3.org/XML/1998/namespace") {
935
976
  yield " xml:" + attrLocalName;
936
977
  output.currentLineWidth += attrLocalName.length + 5;
937
- } else if (attrNamespaceURI === "http://www.w3.org/2000/xmlns/") if (attrLocalName !== "xmlns") {
938
- yield " xmlns:" + attrLocalName;
939
- output.currentLineWidth += attrLocalName.length + 7;
940
- } else {
941
- yield " " + attrLocalName;
942
- output.currentLineWidth += attrLocalName.length + 1;
943
- }
944
- else if (attrNamespaceURI === "http://www.w3.org/1999/xlink") {
978
+ } else if (attrNamespaceURI === "http://www.w3.org/2000/xmlns/") {
979
+ if (attrLocalName !== "xmlns") {
980
+ yield " xmlns:" + attrLocalName;
981
+ output.currentLineWidth += attrLocalName.length + 7;
982
+ } else {
983
+ yield " " + attrLocalName;
984
+ output.currentLineWidth += attrLocalName.length + 1;
985
+ }
986
+ } else if (attrNamespaceURI === "http://www.w3.org/1999/xlink") {
945
987
  yield " xlink:" + attrLocalName;
946
988
  output.currentLineWidth += attrLocalName.length + 7;
947
989
  } else {
@@ -994,34 +1036,36 @@ function* streamToHtml(node, opts, output) {
994
1036
  const tag = tagName === shadowRootTag ? "template" : tagName;
995
1037
  const childNodes = tagName === "template" ? node.content.childNodes : getChildNodes(node);
996
1038
  const childNodeLength = childNodes.length;
997
- if (childNodeLength > 0) if (childNodeLength === 1 && childNodes[0].nodeType === 3 && (typeof childNodes[0].nodeValue !== "string" || childNodes[0].nodeValue.trim() === "")) {} else {
998
- const isWithinWhitespaceSensitiveNode = opts.newLines || (opts.indentSpaces ?? 0) > 0 ? isWithinWhitespaceSensitive(node) : false;
999
- if (!isWithinWhitespaceSensitiveNode && (opts.indentSpaces ?? 0) > 0 && ignoreTag === false) output.indent = output.indent + (opts.indentSpaces ?? 0);
1000
- for (let i = 0; i < childNodeLength; i++) {
1001
- /**
1002
- * In cases where a user would pass in a declarative shadow dom of a
1003
- * Stencil component, we want to skip over the template tag as we
1004
- * will be parsing the shadow root of the component again.
1005
- *
1006
- * We know it is a hydrated Stencil component by checking if the `HYDRATE_ID`
1007
- * is set on the node.
1008
- */
1009
- const sId = node.attributes.getNamedItem(HYDRATE_ID);
1010
- if (childNodes[i].nodeName.toLowerCase() === "template" && sId) {
1011
- yield `\n${" ".repeat(output.indent)}<!--r.${sId.value}-->`;
1012
- continue;
1013
- }
1014
- yield* streamToHtml(childNodes[i], opts, output);
1015
- }
1016
- if (ignoreTag === false) {
1017
- if (opts.newLines && !isWithinWhitespaceSensitiveNode) {
1018
- yield "\n";
1019
- output.currentLineWidth = 0;
1039
+ if (childNodeLength > 0) {
1040
+ if (childNodeLength === 1 && childNodes[0].nodeType === 3 && (typeof childNodes[0].nodeValue !== "string" || childNodes[0].nodeValue.trim() === "")) {} else {
1041
+ const isWithinWhitespaceSensitiveNode = opts.newLines || (opts.indentSpaces ?? 0) > 0 ? isWithinWhitespaceSensitive(node) : false;
1042
+ if (!isWithinWhitespaceSensitiveNode && (opts.indentSpaces ?? 0) > 0 && ignoreTag === false) output.indent = output.indent + (opts.indentSpaces ?? 0);
1043
+ for (let i = 0; i < childNodeLength; i++) {
1044
+ /**
1045
+ * In cases where a user would pass in a declarative shadow dom of a
1046
+ * Stencil component, we want to skip over the template tag as we
1047
+ * will be parsing the shadow root of the component again.
1048
+ *
1049
+ * We know it is a hydrated Stencil component by checking if the `HYDRATE_ID`
1050
+ * is set on the node.
1051
+ */
1052
+ const sId = node.attributes.getNamedItem(HYDRATE_ID);
1053
+ if (childNodes[i].nodeName.toLowerCase() === "template" && sId) {
1054
+ yield `\n${" ".repeat(output.indent)}<!--r.${sId.value}-->`;
1055
+ continue;
1056
+ }
1057
+ yield* streamToHtml(childNodes[i], opts, output);
1020
1058
  }
1021
- if ((opts.indentSpaces ?? 0) > 0 && !isWithinWhitespaceSensitiveNode) {
1022
- output.indent = output.indent - (opts.indentSpaces ?? 0);
1023
- for (let i = 0; i < output.indent; i++) yield " ";
1024
- output.currentLineWidth += output.indent;
1059
+ if (ignoreTag === false) {
1060
+ if (opts.newLines && !isWithinWhitespaceSensitiveNode) {
1061
+ yield "\n";
1062
+ output.currentLineWidth = 0;
1063
+ }
1064
+ if ((opts.indentSpaces ?? 0) > 0 && !isWithinWhitespaceSensitiveNode) {
1065
+ output.indent = output.indent - (opts.indentSpaces ?? 0);
1066
+ for (let i = 0; i < output.indent; i++) yield " ";
1067
+ output.currentLineWidth += output.indent;
1068
+ }
1025
1069
  }
1026
1070
  }
1027
1071
  }
@@ -1080,10 +1124,12 @@ function* streamToHtml(node, opts, output) {
1080
1124
  if (/\s/.test(textContent.charAt(0))) textContent = " " + textContent.trimStart();
1081
1125
  textContentLength = textContent.length;
1082
1126
  if (textContentLength > 1) {
1083
- if (/\s/.test(textContent.charAt(textContentLength - 1))) if (opts.approximateLineWidth && opts.approximateLineWidth > 0 && output.currentLineWidth + textContentLength > opts.approximateLineWidth) {
1084
- textContent = textContent.trimEnd() + "\n";
1085
- output.currentLineWidth = 0;
1086
- } else textContent = textContent.trimEnd() + " ";
1127
+ if (/\s/.test(textContent.charAt(textContentLength - 1))) {
1128
+ if (opts.approximateLineWidth && opts.approximateLineWidth > 0 && output.currentLineWidth + textContentLength > opts.approximateLineWidth) {
1129
+ textContent = textContent.trimEnd() + "\n";
1130
+ output.currentLineWidth = 0;
1131
+ } else textContent = textContent.trimEnd() + " ";
1132
+ }
1087
1133
  }
1088
1134
  output.currentLineWidth += textContentLength;
1089
1135
  }
@@ -1154,7 +1200,7 @@ function isWithinWhitespaceSensitive(node) {
1154
1200
  function getChildNodes(node) {
1155
1201
  return node.__childNodes || node.childNodes;
1156
1202
  }
1157
- const NON_ESCAPABLE_CONTENT = new Set([
1203
+ const NON_ESCAPABLE_CONTENT = /* @__PURE__ */ new Set([
1158
1204
  "STYLE",
1159
1205
  "SCRIPT",
1160
1206
  "IFRAME",
@@ -1163,7 +1209,7 @@ const NON_ESCAPABLE_CONTENT = new Set([
1163
1209
  /**
1164
1210
  * A list of whitespace sensitive tag names, such as `code`, `pre`, etc.
1165
1211
  */
1166
- const WHITESPACE_SENSITIVE = new Set([
1212
+ const WHITESPACE_SENSITIVE = /* @__PURE__ */ new Set([
1167
1213
  "CODE",
1168
1214
  "OUTPUT",
1169
1215
  "PRE",
@@ -1171,7 +1217,7 @@ const WHITESPACE_SENSITIVE = new Set([
1171
1217
  "TEMPLATE",
1172
1218
  "TEXTAREA"
1173
1219
  ]);
1174
- const EMPTY_ELEMENTS = new Set([
1220
+ const EMPTY_ELEMENTS = /* @__PURE__ */ new Set([
1175
1221
  "area",
1176
1222
  "base",
1177
1223
  "br",
@@ -1187,7 +1233,7 @@ const EMPTY_ELEMENTS = new Set([
1187
1233
  "track",
1188
1234
  "wbr"
1189
1235
  ]);
1190
- const REMOVE_EMPTY_ATTR = new Set([
1236
+ const REMOVE_EMPTY_ATTR = /* @__PURE__ */ new Set([
1191
1237
  "class",
1192
1238
  "dir",
1193
1239
  "id",
@@ -1195,7 +1241,7 @@ const REMOVE_EMPTY_ATTR = new Set([
1195
1241
  "name",
1196
1242
  "title"
1197
1243
  ]);
1198
- const BOOLEAN_ATTR = new Set([
1244
+ const BOOLEAN_ATTR = /* @__PURE__ */ new Set([
1199
1245
  "allowfullscreen",
1200
1246
  "async",
1201
1247
  "autofocus",
@@ -1225,7 +1271,7 @@ const BOOLEAN_ATTR = new Set([
1225
1271
  "shadowrootdelegatesfocus",
1226
1272
  "shadowrootserializable"
1227
1273
  ]);
1228
- const STRUCTURE_ELEMENTS = new Set([
1274
+ const STRUCTURE_ELEMENTS = /* @__PURE__ */ new Set([
1229
1275
  "html",
1230
1276
  "body",
1231
1277
  "head",
@@ -1417,8 +1463,9 @@ var MockNode = class {
1417
1463
  }
1418
1464
  get nextSibling() {
1419
1465
  if (this.parentNode != null) {
1420
- const index = this.parentNode.childNodes.indexOf(this) + 1;
1421
- return this.parentNode.childNodes[index] || null;
1466
+ const selfIndex = this.parentNode.childNodes.indexOf(this);
1467
+ if (selfIndex === -1) return null;
1468
+ return this.parentNode.childNodes[selfIndex + 1] || null;
1422
1469
  }
1423
1470
  return null;
1424
1471
  }
@@ -1460,8 +1507,10 @@ var MockNode = class {
1460
1507
  return childNode;
1461
1508
  }
1462
1509
  remove() {
1463
- if (this.parentNode != null) if (this.__parentNode) this.__parentNode.removeChild(this);
1464
- else this.parentNode.removeChild(this);
1510
+ if (this.parentNode != null) {
1511
+ if (this.__parentNode) this.__parentNode.removeChild(this);
1512
+ else this.parentNode.removeChild(this);
1513
+ }
1465
1514
  }
1466
1515
  replaceChild(newChild, oldChild) {
1467
1516
  if (oldChild.parentNode === this) {
@@ -1477,11 +1526,11 @@ var MockNode = class {
1477
1526
  set textContent(value) {
1478
1527
  this._nodeValue = String(value);
1479
1528
  }
1480
- addEventListener(type, handler) {
1481
- addEventListener(this, type, handler);
1529
+ addEventListener(type, handler, options) {
1530
+ addEventListener(this, type, handler, options);
1482
1531
  }
1483
- removeEventListener(type, handler) {
1484
- removeEventListener(this, type, handler);
1532
+ removeEventListener(type, handler, options) {
1533
+ removeEventListener(this, type, handler, options);
1485
1534
  }
1486
1535
  dispatchEvent(ev) {
1487
1536
  return dispatchEvent(this, ev);
@@ -1526,13 +1575,15 @@ var MockElement = class extends MockNode {
1526
1575
  this.__shadowRoot = null;
1527
1576
  this.__attributeMap = null;
1528
1577
  }
1529
- addEventListener(type, handler) {
1530
- addEventListener(this, type, handler);
1578
+ addEventListener(type, handler, options) {
1579
+ addEventListener(this, type, handler, options);
1531
1580
  }
1532
1581
  attachShadow(_opts) {
1533
1582
  const shadowRoot = this.ownerDocument.createDocumentFragment();
1534
1583
  shadowRoot.mode = _opts.mode ?? "open";
1535
1584
  shadowRoot.delegatesFocus = _opts.delegatesFocus ?? false;
1585
+ shadowRoot.clonable = _opts.clonable ?? false;
1586
+ shadowRoot.serializable = _opts.serializable ?? false;
1536
1587
  this.shadowRoot = shadowRoot;
1537
1588
  return shadowRoot;
1538
1589
  }
@@ -1792,8 +1843,9 @@ var MockElement = class extends MockNode {
1792
1843
  get nextElementSibling() {
1793
1844
  const parentElement = this.parentElement;
1794
1845
  if (parentElement != null && (parentElement.nodeType === 1 || parentElement.nodeType === 11 || parentElement.nodeType === 9)) {
1795
- const index = parentElement.children.indexOf(this) + 1;
1796
- return parentElement.children[index] || null;
1846
+ const selfIndex = parentElement.children.indexOf(this);
1847
+ if (selfIndex === -1) return null;
1848
+ return parentElement.children[selfIndex + 1] || null;
1797
1849
  }
1798
1850
  return null;
1799
1851
  }
@@ -1807,8 +1859,9 @@ var MockElement = class extends MockNode {
1807
1859
  get previousElementSibling() {
1808
1860
  const parentElement = this.parentElement;
1809
1861
  if (parentElement != null && (parentElement.nodeType === 1 || parentElement.nodeType === 11 || parentElement.nodeType === 9)) {
1810
- const index = parentElement.children.indexOf(this) - 1;
1811
- return parentElement.children[index] || null;
1862
+ const selfIndex = parentElement.children.indexOf(this);
1863
+ if (selfIndex === -1) return null;
1864
+ return parentElement.children[selfIndex - 1] || null;
1812
1865
  }
1813
1866
  return null;
1814
1867
  }
@@ -1846,8 +1899,8 @@ var MockElement = class extends MockNode {
1846
1899
  if (checkAttributeChanged(this) === true) attributeChanged(this, attrName, attr.value, null);
1847
1900
  }
1848
1901
  }
1849
- removeEventListener(type, handler) {
1850
- removeEventListener(this, type, handler);
1902
+ removeEventListener(type, handler, options) {
1903
+ removeEventListener(this, type, handler, options);
1851
1904
  }
1852
1905
  setAttribute(attrName, value) {
1853
1906
  if (attrName === "style") this.style = value;
@@ -1855,12 +1908,13 @@ var MockElement = class extends MockNode {
1855
1908
  const attributes = this.attributes;
1856
1909
  let attr = attributes.getNamedItem(attrName);
1857
1910
  const checkAttrChanged = checkAttributeChanged(this);
1858
- if (attr != null) if (checkAttrChanged === true) {
1859
- const oldValue = attr.value;
1860
- attr.value = value;
1861
- if (oldValue !== attr.value) attributeChanged(this, attr.name, oldValue, attr.value);
1862
- } else attr.value = value;
1863
- else {
1911
+ if (attr != null) {
1912
+ if (checkAttrChanged === true) {
1913
+ const oldValue = attr.value;
1914
+ attr.value = value;
1915
+ if (oldValue !== attr.value) attributeChanged(this, attr.name, oldValue, attr.value);
1916
+ } else attr.value = value;
1917
+ } else {
1864
1918
  if (attributes.caseInsensitive) attrName = attrName.toLowerCase();
1865
1919
  attr = new MockAttr(attrName, value);
1866
1920
  attributes.__items.push(attr);
@@ -1882,12 +1936,13 @@ var MockElement = class extends MockNode {
1882
1936
  }
1883
1937
  let attr = attributes.getNamedItemNS(namespaceURI, localName);
1884
1938
  const checkAttrChanged = checkAttributeChanged(this);
1885
- if (attr != null) if (checkAttrChanged === true) {
1886
- const oldValue = attr.value;
1887
- attr.value = value;
1888
- if (oldValue !== attr.value) attributeChanged(this, attr.name, oldValue, attr.value);
1889
- } else attr.value = value;
1890
- else {
1939
+ if (attr != null) {
1940
+ if (checkAttrChanged === true) {
1941
+ const oldValue = attr.value;
1942
+ attr.value = value;
1943
+ if (oldValue !== attr.value) attributeChanged(this, attr.name, oldValue, attr.value);
1944
+ } else attr.value = value;
1945
+ } else {
1891
1946
  attr = new MockAttr(localName, value, namespaceURI, prefix);
1892
1947
  attributes.__items.push(attr);
1893
1948
  if (checkAttrChanged === true) attributeChanged(this, attr.name, null, attr.value);
@@ -2199,7 +2254,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2199
2254
  global.NW.Dom = factory(global, Export);
2200
2255
  }
2201
2256
  })(exports, function Factory(global, Export) {
2202
- var version = "nwsapi-2.2.23", doc = global.document, root = doc.documentElement, slice = Array.prototype.slice, VSP = "[\\r\\n\\f]", WSP = "[\\x20\\t\\r\\n\\f]", CFG = {
2257
+ var version = "nwsapi-2.2.24", doc = global.document, root = doc.documentElement, slice = Array.prototype.slice, HSP = "\\x20\\t", VSP = "\\r\\n\\f", WSP = "[" + HSP + VSP + "]", CFG = {
2203
2258
  operators: "[~*^$|]=|=",
2204
2259
  combinators: "[\\x20\\t>+~](?=[^>+~])"
2205
2260
  }, NOT = {
@@ -2224,9 +2279,9 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2224
2279
  apimethods: RegExp("^(?:\\w+|\\*)\\|"),
2225
2280
  namespaces: RegExp("(\\*|\\w+)\\|[\\w-]+")
2226
2281
  }, GROUPS = {
2227
- linguistic: "(dir|lang)(?:\\x28\\s?([-\\w]{2,})\\s?\\x29)",
2228
- logicalsel: "(is|where|matches|not|has)(?:\\x28\\s?([^()]*|.*)\\s?\\x29)",
2229
- treestruct: "(nth(?:-last)?(?:-child|-of\\-type))(?:\\x28\\s?(even|odd|(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)?)\\s?\\x29)",
2282
+ linguistic: "(dir|lang)(?:\\x28\\s?([-\\w]{2,})\\s?(?:\\x29|$))",
2283
+ logicalsel: "(is|where|matches|not|has)(?:\\x28\\s?([^()]*|.*)\\s?(?:\\x29|$))",
2284
+ treestruct: "(nth(?:-last)?(?:-child|-of\\-type))(?:\\x28\\s?(even|odd|(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)?)\\s?(?:\\x29|$))",
2230
2285
  locationpc: "(any\\-link|link|visited|target|defined)\\b",
2231
2286
  useraction: "(hover|active|focus\\-within|focus\\-visible|focus)\\b",
2232
2287
  structural: "(scope|root|empty|(?:(?:first|last|only)(?:-child|\\-of\\-type)))\\b",
@@ -2425,7 +2480,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2425
2480
  if (codePoint < 1 || codePoint > 1114111 || codePoint > 55295 && codePoint < 57344) return "�";
2426
2481
  if (codePoint < 65536) return String.fromCharCode(codePoint);
2427
2482
  return String.fromCodePoint ? String.fromCodePoint(codePoint) : String.fromCharCode((codePoint - 65536 >> 10) + 55296, (codePoint - 65536) % 1024 + 56320);
2428
- }, convertEscapes = function(str) {
2483
+ }, escapeIdentifier = function(str) {
2429
2484
  return REX.HasEscapes.test(str) ? str.replace(REX.FixEscapes, function(substring, p1, p2) {
2430
2485
  return p2 ? "\\" + p2 : REX.HexNumbers.test(p1) ? codePointToUTF16(parseInt(p1, 16)) : REX.EscOrQuote.test(p1) ? substring : p1;
2431
2486
  }) : str;
@@ -2455,12 +2510,14 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2455
2510
  var e, i, l, nodes, api = method["#"];
2456
2511
  if (Config.IDS_DUPES === false) {
2457
2512
  if (api in context) return (e = context[api](id)) ? [e] : none;
2458
- } else if ("all" in context) if (e = context.all[id]) {
2459
- if (e.nodeType == 1) return e.getAttribute("id") != id ? [] : [e];
2460
- else if (id == "length") return (e = context[api](id)) ? [e] : none;
2461
- for (i = 0, l = e.length, nodes = []; l > i; ++i) if (e[i].id == id) nodes[nodes.length] = e[i];
2462
- return nodes && nodes.length ? nodes : [nodes];
2463
- } else return none;
2513
+ } else if ("all" in context) {
2514
+ if (e = context.all[id]) {
2515
+ if (e.nodeType == 1) return e.getAttribute("id") != id ? [] : [e];
2516
+ else if (id == "length") return (e = context[api](id)) ? [e] : none;
2517
+ for (i = 0, l = e.length, nodes = []; l > i; ++i) if (e[i].id == id) nodes[nodes.length] = e[i];
2518
+ return nodes && nodes.length ? nodes : [nodes];
2519
+ } else return none;
2520
+ }
2464
2521
  return byIdRaw(id, context);
2465
2522
  }, byTagNS = function(context, tag) {
2466
2523
  return byTag(tag, context);
@@ -2469,15 +2526,16 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2469
2526
  if (api in context) return slice.call(context[api](tag));
2470
2527
  else {
2471
2528
  tag = tag.toLowerCase();
2472
- if (e = context.firstElementChild) if (!(e.nextElementSibling || tag == "*" || e.localName == tag)) return slice.call(e[api](tag));
2473
- else {
2474
- nodes = [];
2475
- do {
2476
- if (tag == "*" || e.localName == tag) nodes[nodes.length] = e;
2477
- concatList(nodes, e[api](tag));
2478
- } while (e = e.nextElementSibling);
2479
- }
2480
- else nodes = none;
2529
+ if (e = context.firstElementChild) {
2530
+ if (!(e.nextElementSibling || tag == "*" || e.localName == tag)) return slice.call(e[api](tag));
2531
+ else {
2532
+ nodes = [];
2533
+ do {
2534
+ if (tag == "*" || e.localName == tag) nodes[nodes.length] = e;
2535
+ concatList(nodes, e[api](tag));
2536
+ } while (e = e.nextElementSibling);
2537
+ }
2538
+ } else nodes = none;
2481
2539
  }
2482
2540
  return !Config.NODE_LIST ? nodes : isInstanceOf(nodes) ? nodes : toNodeList(nodes);
2483
2541
  }, byClass = function(cls, context) {
@@ -2669,7 +2727,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2669
2727
  setIdentifierSyntax();
2670
2728
  lastContext = switchContext(doc, true);
2671
2729
  }, setIdentifierSyntax = function() {
2672
- var noascii = "[^\\x00-\\x9f]", escaped = "\\\\[^\\r\\n\\f0-9a-fA-F]", unicode = "\\\\[0-9a-fA-F]{1,6}(?:\\r\\n|\\s)?", identifier = "-?(?:[a-zA-Z_-]|" + noascii + "|" + escaped + "|" + unicode + ")(?:-{2}|[0-9]|[a-zA-Z_-]|" + noascii + "|" + escaped + "|" + unicode + ")*", pseudonames = "[-\\w]+", pseudoparms = "(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)", attrparser = identifier + "|\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*(?:\"|$)|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*(?:'|$)", attrvalues = "([\\x22\\x27]?)((?!\\3)*|(?:\\\\?.)*?)(?:\\3|$)", attributes = "\\[(?:\\*\\|)?" + WSP + "?(" + identifier + "(?::" + identifier + ")?)" + WSP + "?(?:(" + CFG.operators + ")" + WSP + "?(?:" + attrparser + "))?(?:" + WSP + "?\\b(i))?" + WSP + "?(?:\\]|$)", attrmatcher = attributes.replace(attrparser, attrvalues), pseudoclass = "(?:\\x28" + WSP + "*(?:" + pseudoparms + "?)?|(?:\\*|\\*\\|)|(?:(?::" + pseudonames + "(?:\\x28" + pseudoparms + "?(?:\\x29|$))?|)|(?:[.#]?" + identifier + ")|(?:" + attributes + "))+|(?:" + WSP + "?[>+~][^>+~]" + WSP + "?)|(?:" + WSP + "?," + WSP + "?)|(?:" + WSP + "?)|(?:\\x29|$))*", standardValidator = "(?=" + WSP + "?[^>+~(){}<>])(?:(?:\\*|\\*\\|)|(?:[.#]?" + identifier + ")+|(?:" + attributes + ")+|(?:::?" + pseudonames + pseudoclass + ")|(?:" + WSP + "?" + CFG.combinators + WSP + "?)|(?:" + WSP + "?," + WSP + "?)|(?:" + WSP + "?))+";
2730
+ var identifier = "(?:-|--|\\\\[0-9a-fA-F]{1,6}[" + HSP + "]?|\\\\[^" + VSP + "]|[^\\x00-\\x9f]|[\\w-])+", pseudonames = "[-\\w]+", pseudoparms = "(?:[-+]?\\d*)(?:n\\s?[-+]?\\s?\\d*)", attrparser = identifier + "|\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*(?:\"|$)|'[^'\\\\]*(?:\\\\.[^'\\\\]*)*(?:'|$)", attrvalues = "([\\x22\\x27]?)((?!\\3)*|(?:\\\\?.)*?)(?:\\3|$)", attributes = "\\[(?:\\*\\|)?" + WSP + "?(" + identifier + "(?::" + identifier + ")?)" + WSP + "?(?:(" + CFG.operators + ")" + WSP + "?(?:" + attrparser + "))?(?:" + WSP + "?\\b(i))?" + WSP + "?(?:\\]|$)", attrmatcher = attributes.replace(attrparser, attrvalues), pseudoclass = "(?:\\x28" + WSP + "*(?:" + pseudoparms + "?)?|(?:\\*|\\*\\|)|(?:(?::" + pseudonames + "(?:\\x28" + pseudoparms + "?(?:\\x29|$))?|)|(?:[.#]?" + identifier + ")|(?:" + attributes + "))+|(?:" + WSP + "?[>+~][^>+~]" + WSP + "?)|(?:" + WSP + "?," + WSP + "?)|(?:" + WSP + "?)|(?:\\x29|$))*", standardValidator = "(?=" + WSP + "?[^>+~(){}<>])(?:(?:\\*|\\*\\|)|(?:[.#]?" + identifier + ")+|(?:" + attributes + ")+|(?:::?" + pseudonames + pseudoclass + ")|(?:" + WSP + "?" + CFG.combinators + WSP + "?)|(?:" + WSP + "?," + WSP + "?)|(?:" + WSP + "?))+";
2673
2731
  reOptimizer = RegExp("(?:([.:#*]?)(" + identifier + ")(?::[-\\w]+|\\[[^\\]]+(?:\\]|$)|\\x28[^\\x29]+(?:\\x29|$))*)$");
2674
2732
  reValidator = RegExp(standardValidator, "g");
2675
2733
  Patterns.id = RegExp("^#(" + identifier + ")(.*)");
@@ -2696,8 +2754,6 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2696
2754
  macro = N_BODY + (callback ? N_TEST : "") + N_TAIL;
2697
2755
  head = N_HEAD;
2698
2756
  loop = N_LOOP;
2699
- break;
2700
- default: break;
2701
2757
  }
2702
2758
  source = compileSelector(selector, macro, mode, callback);
2703
2759
  loop += mode || mode === null ? "{" + source + "}" : source;
@@ -2714,9 +2770,10 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2714
2770
  factory = Function("s", F_INIT + "{" + head + vars + ";" + loop + "return r;}")(Snapshot);
2715
2771
  return mode || mode === null ? selectLambdas[selector] = factory : matchLambdas[selector] = factory;
2716
2772
  }, compileSelector = function(expression, source, mode, callback) {
2717
- var a, b, n, f, name, NS, compat, expr, match, result, status, symbol, test, type, selector = expression, vars;
2773
+ var a, b, n, f, k = 0, name, NS, compat, expr, match, result, status, symbol, test, type, selector = expression, vars;
2718
2774
  selector = selector.replace(STD.combinator, "$1");
2719
2775
  selector_recursion_label: while (selector) {
2776
+ ++k;
2720
2777
  symbol = STD.apimethods.test(selector) ? "|" : selector[0];
2721
2778
  switch (symbol) {
2722
2779
  case "*":
@@ -2762,26 +2819,26 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2762
2819
  p3: "true"
2763
2820
  } : test;
2764
2821
  else if (match[2] == "~=" && match[4].includes(" ")) break;
2765
- else if (match[4]) match[4] = convertEscapes(match[4]).replace(REX.RegExpChar, "\\$&");
2822
+ else if (match[4]) match[4] = escapeIdentifier(match[4]).replace(REX.RegExpChar, "\\$&");
2766
2823
  type = match[5] == "i" || HTML_DOCUMENT && HTML_TABLE[expr.toLowerCase()] ? "i" : "";
2767
2824
  source = "if((" + (!match[2] ? NS ? "s.hasAttributeNS(e,\"" + name + "\")" : "e.hasAttribute&&e.hasAttribute(\"" + name + "\")" : !match[4] && ATTR_STD_OPS[match[2]] && match[2] != "~=" ? "e.getAttribute&&e.getAttribute(\"" + name + "\")==\"\"" : "(/" + test.p1 + match[4] + test.p2 + "/" + type + ").test(e.getAttribute&&e.getAttribute(\"" + name + "\"))==" + test.p3) + ")){" + source + "}";
2768
2825
  break;
2769
2826
  case "~":
2770
2827
  match = selector.match(Patterns.relative);
2771
- source = "while(e&&(e=e.previousElementSibling)){" + source + "}";
2828
+ source = "var N" + k + "=e;while(e&&(e=e.previousElementSibling)){" + source + "}e=N" + k + ";";
2772
2829
  break;
2773
2830
  case "+":
2774
2831
  match = selector.match(Patterns.adjacent);
2775
- source = "if(e&&(e=e.previousElementSibling)){" + source + "}";
2832
+ source = "var N" + k + "=e;if(e&&(e=e.previousElementSibling)){" + source + "}e=N" + k + ";";
2776
2833
  break;
2777
2834
  case " ":
2778
2835
  case " ":
2779
2836
  match = selector.match(Patterns.ancestor);
2780
- source = "while(e&&(e=e.parentElement)){" + source + "}";
2837
+ source = "var N" + k + "=e;while(e&&(e=e.parentElement)){" + source + "}e=N" + k + ";";
2781
2838
  break;
2782
2839
  case ">":
2783
2840
  match = selector.match(Patterns.children);
2784
- source = "if(e&&(e=e.parentElement)){" + source + "}";
2841
+ source = "var N" + k + "=e;if(e&&(e=e.parentElement)){" + source + "}e=N" + k + ";";
2785
2842
  break;
2786
2843
  case symbol in Combinators ? symbol : void 0:
2787
2844
  match[match.length - 1] = "*";
@@ -2818,9 +2875,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2818
2875
  case "first-of-type":
2819
2876
  source = "n=e;o=e.localName;while((n=n.previousElementSibling)&&n.localName!=o);if(!n){" + source + "}";
2820
2877
  break;
2821
- default:
2822
- emit("'" + expression + "'" + qsInvalid);
2823
- break;
2878
+ default: emit("'" + expression + "'" + qsInvalid);
2824
2879
  }
2825
2880
  } else if (match = selector.match(Patterns.treestruct)) {
2826
2881
  match[1] = match[1].toLowerCase();
@@ -2856,9 +2911,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2856
2911
  source = "n=s.nth" + expr + "(e," + type + ");if((" + test + ")){" + source + "}";
2857
2912
  } else emit("'" + expression + "'" + qsInvalid);
2858
2913
  break;
2859
- default:
2860
- emit("'" + expression + "'" + qsInvalid);
2861
- break;
2914
+ default: emit("'" + expression + "'" + qsInvalid);
2862
2915
  }
2863
2916
  } else if (match = selector.match(Patterns.logicalsel)) {
2864
2917
  match[1] = match[1].toLowerCase();
@@ -2877,11 +2930,9 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2877
2930
  break;
2878
2931
  case "has":
2879
2932
  if (/^\s*(\+|\~)/.test(match[2])) source = "if(e.parentElement&&Array.from(e.parentElement" + (/^\s*[+]/.test(match[2]) ? ".querySelectorAll(\"*" + expr + "\")" : ".children") + ").includes(e.nextElementSibling)){" + source + "}";
2880
- else source = "if(e.querySelector(\":scope " + expr + "\")){" + source + "}";
2881
- break;
2882
- default:
2883
- emit("'" + expression + "'" + qsInvalid);
2933
+ else source = "if(s.first(\":scope " + expr + "\",e)){" + source + "}";
2884
2934
  break;
2935
+ default: emit("'" + expression + "'" + qsInvalid);
2885
2936
  }
2886
2937
  } else if (match = selector.match(Patterns.linguistic)) {
2887
2938
  match[1] = match[1].toLowerCase();
@@ -2893,9 +2944,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2893
2944
  expr = "(?:^|-)" + match[2] + "(?:-|$)";
2894
2945
  source = "var p;if(((e.isConnected&&(e.lang==\"\"&&(p=s.ancestor(\"[lang]\",e)))&&(p.lang==\"" + match[2] + "\")||/" + expr + "/i.test(e.lang)))){" + source + "};";
2895
2946
  break;
2896
- default:
2897
- emit("'" + expression + "'" + qsInvalid);
2898
- break;
2947
+ default: emit("'" + expression + "'" + qsInvalid);
2899
2948
  }
2900
2949
  } else if (match = selector.match(Patterns.locationpc)) {
2901
2950
  match[1] = match[1].toLowerCase();
@@ -2915,9 +2964,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2915
2964
  case "defined":
2916
2965
  source = "n=s.doc.defaultView.customElements.get(e.localName);if(n&&e instanceof n){" + source + "}";
2917
2966
  break;
2918
- default:
2919
- emit("'" + expression + "'" + qsInvalid);
2920
- break;
2967
+ default: emit("'" + expression + "'" + qsInvalid);
2921
2968
  }
2922
2969
  } else if (match = selector.match(Patterns.useraction)) {
2923
2970
  match[1] = match[1].toLowerCase();
@@ -2937,9 +2984,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2937
2984
  case "focus-within":
2938
2985
  source = "if(n=s.isFocusable(e)){if(n!==e){while(n){n=n.parentElement;if(n===e)break;}}}if((n===e||n.autofocus)){" + source + "}";
2939
2986
  break;
2940
- default:
2941
- emit("'" + expression + "'" + qsInvalid);
2942
- break;
2987
+ default: emit("'" + expression + "'" + qsInvalid);
2943
2988
  }
2944
2989
  } else if (match = selector.match(Patterns.inputstate)) {
2945
2990
  match[1] = match[1].toLowerCase();
@@ -2962,9 +3007,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2962
3007
  case "default":
2963
3008
  source = "if((\"form\" in e && e.form)){var x=0;n=[];if(e.type==\"image\")n=e.form.getElementsByTagName(\"input\");if(e.type==\"submit\")n=e.form.elements;while(n[x]&&e!==n[x]){if(n[x].type==\"image\")break;if(n[x].type==\"submit\")break;x++;}}if((e.form&&(e===n[x]&&\"|image|submit|\".includes(\"|\"+e.type+\"|\"))||((/^option$/i.test(e.localName))&&e.defaultSelected)||((\"|radio|checkbox|\".includes(\"|\"+e.type+\"|\"))&&e.defaultChecked))){" + source + "}";
2964
3009
  break;
2965
- default:
2966
- emit("'" + expression + "'" + qsInvalid);
2967
- break;
3010
+ default: emit("'" + expression + "'" + qsInvalid);
2968
3011
  }
2969
3012
  } else if (match = selector.match(Patterns.inputvalue)) {
2970
3013
  match[1] = match[1].toLowerCase();
@@ -2993,9 +3036,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
2993
3036
  case "out-of-range":
2994
3037
  source = "if((/^input$/i.test(e.localName))&&(e.willValidate&&!e.formNoValidate)&&(e.validity.rangeUnderflow||e.validity.rangeOverflow)&&(\"|date|datetime-local|month|number|range|time|week|\".includes(\"|\"+e.type+\"|\"))&&(\"range\"==e.type||e.getAttribute(\"min\")||e.getAttribute(\"max\"))){" + source + "}";
2995
3038
  break;
2996
- default:
2997
- emit("'" + expression + "'" + qsInvalid);
2998
- break;
3039
+ default: emit("'" + expression + "'" + qsInvalid);
2999
3040
  }
3000
3041
  } else if (match = selector.match(Patterns.rsrc_state)) {
3001
3042
  match[1] = match[1].toLowerCase();
@@ -3011,11 +3052,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
3011
3052
  break;
3012
3053
  case "buffering": break;
3013
3054
  case "stalled": break;
3014
- case "muted":
3015
- source = "if(e.localName==\"audio\"&&e.getAttribute(\"muted\")){" + source + "}";
3016
- break;
3017
- case "volume-locked": break;
3018
- default: break;
3055
+ case "muted": source = "if(e.localName==\"audio\"&&e.getAttribute(\"muted\")){" + source + "}";
3019
3056
  }
3020
3057
  } else if (match = selector.match(Patterns.pseudo_nop)) break;
3021
3058
  else if (match = selector.match(Patterns.pseudo_sng)) source = "if(e.element&&e.type.toLowerCase()==\":" + match[0].toLowerCase() + "\"){e=e.element;" + source + "}";
@@ -3059,7 +3096,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
3059
3096
  return source;
3060
3097
  }, makeref = function(selectors, element) {
3061
3098
  if (element.nodeType === 9) element = element.documentElement;
3062
- return selectors.replace(/:scope/i, element.localName + (element.id ? "#" + escape(element.id) : "") + (element.className ? "." + escape(element.classList[0]) : ""));
3099
+ return selectors.replace(/:scope/i, element.localName + (element.id ? "#" + escapeIdentifier(element.id) : "") + (element.className ? "." + escapeIdentifier(element.classList[0]) : ""));
3063
3100
  }, ancestor = function _closest(selectors, element, callback) {
3064
3101
  parse(selectors, true);
3065
3102
  selectors = makeref(selectors, element);
@@ -3082,10 +3119,12 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
3082
3119
  } else if (arguments[0] === "") {
3083
3120
  emit("''" + qsInvalid);
3084
3121
  return Config.VERBOSITY ? void 0 : type ? none : false;
3122
+ } else if (/^[.#]?\d/.test(selectors)) {
3123
+ emit("''" + qsInvalid);
3124
+ return Config.VERBOSITY ? void 0 : type ? none : false;
3085
3125
  }
3086
3126
  if (typeof selectors != "string") selectors = "" + selectors;
3087
- if (/:scope/i.test(selectors)) selectors = makeref(selectors, Snapshot.from);
3088
- parsed = unescape(selectors).replace(/\x00|\\$/g, "�").replace(REX.CombineWSP, " ").replace(REX.PseudosWSP, "$1").replace(REX.TabCharWSP, " ").replace(REX.CommaGroup, ",").replace(REX.TrimSpaces, "");
3127
+ parsed = selectors.replace(/\x00|\\$/g, "�").replace(REX.CombineWSP, " ").replace(REX.PseudosWSP, "$1").replace(REX.TabCharWSP, " ").replace(REX.CommaGroup, ",").replace(REX.TrimSpaces, "");
3089
3128
  if ((selectors = parsed.match(reValidator)) && selectors.join("") == parsed) {
3090
3129
  selectors = parsed.match(REX.SplitGroup);
3091
3130
  if (parsed[parsed.length - 1] == ",") {
@@ -3256,6 +3295,7 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
3256
3295
  byTag,
3257
3296
  first,
3258
3297
  match,
3298
+ select,
3259
3299
  ancestor,
3260
3300
  nthOfType,
3261
3301
  nthElement,
@@ -3277,8 +3317,8 @@ var import_nwsapi = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exp
3277
3317
  byId,
3278
3318
  byTag,
3279
3319
  byClass,
3280
- match,
3281
3320
  first,
3321
+ match,
3282
3322
  select,
3283
3323
  closest: ancestor,
3284
3324
  compile,
@@ -4205,11 +4245,13 @@ function createConsole() {
4205
4245
  var MockHeaders = class {
4206
4246
  _values = [];
4207
4247
  constructor(init) {
4208
- if (typeof init === "object") if (typeof init[Symbol.iterator] === "function") {
4209
- const kvs = [];
4210
- for (const kv of init) if (typeof kv[Symbol.iterator] === "function") kvs.push([...kv]);
4211
- for (const kv of kvs) this.append(kv[0], kv[1]);
4212
- } else for (const key in init) this.append(key, init[key]);
4248
+ if (typeof init === "object") {
4249
+ if (typeof init[Symbol.iterator] === "function") {
4250
+ const kvs = [];
4251
+ for (const kv of init) if (typeof kv[Symbol.iterator] === "function") kvs.push([...kv]);
4252
+ for (const kv of kvs) this.append(kv[0], kv[1]);
4253
+ } else for (const key in init) this.append(key, init[key]);
4254
+ }
4213
4255
  }
4214
4256
  append(key, value) {
4215
4257
  this._values.push([key, value + ""]);
@@ -4548,6 +4590,7 @@ var MockIntersectionObserver = class {
4548
4590
  };
4549
4591
  //#endregion
4550
4592
  //#region src/location.ts
4593
+ const DEFAULT_LOCATION_HREF = "http://localhost/";
4551
4594
  var MockLocation = class {
4552
4595
  ancestorOrigins = null;
4553
4596
  protocol = "";
@@ -4578,6 +4621,9 @@ var MockLocation = class {
4578
4621
  this.password = url.password;
4579
4622
  this.origin = url.origin;
4580
4623
  }
4624
+ constructor() {
4625
+ this.href = DEFAULT_LOCATION_HREF;
4626
+ }
4581
4627
  assign(_url) {}
4582
4628
  reload(_forcedReload) {}
4583
4629
  replace(_url) {}
@@ -4661,11 +4707,16 @@ var MockResizeObserver = class {
4661
4707
  var MockShadowRoot = class extends MockDocumentFragment {
4662
4708
  _mode = "open";
4663
4709
  _delegatesFocus = false;
4710
+ _clonable = false;
4711
+ _serializable = false;
4664
4712
  get activeElement() {
4665
4713
  return null;
4666
4714
  }
4667
- get cloneable() {
4668
- return false;
4715
+ get clonable() {
4716
+ return this._clonable;
4717
+ }
4718
+ set clonable(value) {
4719
+ this._clonable = value;
4669
4720
  }
4670
4721
  get delegatesFocus() {
4671
4722
  return this._delegatesFocus;
@@ -4697,7 +4748,10 @@ var MockShadowRoot = class extends MockDocumentFragment {
4697
4748
  return null;
4698
4749
  }
4699
4750
  get serializable() {
4700
- return false;
4751
+ return this._serializable;
4752
+ }
4753
+ set serializable(value) {
4754
+ this._serializable = value;
4701
4755
  }
4702
4756
  get slotAssignment() {
4703
4757
  return "named";
@@ -4783,8 +4837,8 @@ var MockWindow = class {
4783
4837
  resetWindowDefaults(this);
4784
4838
  resetWindowDimensions(this);
4785
4839
  }
4786
- addEventListener(type, handler) {
4787
- addEventListener(this, type, handler);
4840
+ addEventListener(type, handler, options) {
4841
+ addEventListener(this, type, handler, options);
4788
4842
  }
4789
4843
  alert(msg) {
4790
4844
  if (this.console) this.console.debug(msg);
@@ -5006,8 +5060,8 @@ var MockWindow = class {
5006
5060
  get origin() {
5007
5061
  return this.location.origin;
5008
5062
  }
5009
- removeEventListener(type, handler) {
5010
- removeEventListener(this, type, handler);
5063
+ removeEventListener(type, handler, options) {
5064
+ removeEventListener(this, type, handler, options);
5011
5065
  }
5012
5066
  requestAnimationFrame(callback) {
5013
5067
  return this.setTimeout(() => {
@@ -5323,7 +5377,8 @@ var MockDocument = class MockDocument extends MockHTMLElement {
5323
5377
  this.#nwsapi = (0, import_nwsapi.default)({ document: this });
5324
5378
  this.#nwsapi.configure({
5325
5379
  LOGERRORS: false,
5326
- VERBOSITY: false
5380
+ VERBOSITY: false,
5381
+ IDS_DUPES: false
5327
5382
  });
5328
5383
  }
5329
5384
  return this.#nwsapi;
@@ -5517,7 +5572,7 @@ function resetDocument(doc) {
5517
5572
  } catch {}
5518
5573
  }
5519
5574
  }
5520
- const DOC_KEY_KEEPERS = new Set([
5575
+ const DOC_KEY_KEEPERS = /* @__PURE__ */ new Set([
5521
5576
  "nodeName",
5522
5577
  "nodeType",
5523
5578
  "nodeValue",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stencil/mock-doc",
3
- "version": "5.0.0-alpha.8",
3
+ "version": "5.0.0-beta.0",
4
4
  "description": "A minimal mock DOM implementation for SSR and testing",
5
5
  "keywords": [
6
6
  "dom",
@@ -32,14 +32,14 @@
32
32
  }
33
33
  },
34
34
  "dependencies": {
35
- "nwsapi": "^2.0.0",
36
- "parse5": "^8.0.0"
35
+ "nwsapi": "^2.2.24",
36
+ "parse5": "^8.0.1"
37
37
  },
38
38
  "devDependencies": {
39
- "@stencil/vitest": "^1.12.1",
40
- "tsdown": ">=0.21.0 <1.0.0",
41
- "typescript": ">4.0.0 <7.0.0",
42
- "vitest": "^4.1.7"
39
+ "@stencil/vitest": "^1.14.0",
40
+ "tsdown": "^0.22.14",
41
+ "typescript": ">5.0.0 <7.0.0",
42
+ "vitest": "^4.1.10"
43
43
  },
44
44
  "volta": {
45
45
  "extends": "../../package.json"
File without changes